xref: /OK3568_Linux_fs/buildroot/package/rockchip/tee-user-app/extra_app/host/main.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdint.h>
9 #include <tee_client_api.h>
10 #include <tee_api_defines_extensions.h>
11 #include "ta_keybox.h"
12 
13 #define KEY_SIZE 32
14 #define DEFAULT_STORAGE		TEE_STORAGE_PRIVATE_RPMB
15 
run_system(const char * command)16 static int run_system(const char *command)
17 {
18 	int status;
19 
20 	status = system(command);
21 	if (status == -1) {
22 		printf("ERROR: system fork failed\n");
23 		return -1;
24 	} else {
25 		if (WIFEXITED(status)) {
26 			if (WEXITSTATUS(status)) {
27 				printf("ERROR: system command failed\n");
28 				return -1;
29 			}
30 		}
31 	}
32 
33 	return 0;
34 }
35 
grep_string(const char * dst,const char * target)36 static int grep_string(const char *dst, const char *target)
37 {
38 	int i;
39 
40 	for (i = 0; i < strlen(dst); i++) {
41 		if (!memcmp(&dst[i], target, strlen(target)))
42 			return 0;
43 	}
44 	return -1;
45 }
46 
check_ramdisk_env(const char * file)47 static int check_ramdisk_env(const char *file)
48 {
49 	FILE *fp;
50 	char buf[1000];
51 
52 	fp = fopen(file, "r");
53 	if (!fp) {
54 		printf("ERROR: bad node\n");
55 		return -1;
56 	}
57 
58 	while (!feof(fp)) {
59 		fgets(buf, 1000, fp);
60 		if (!grep_string(buf, "none / rootfs")) {
61 			fclose(fp);
62 			return 0;
63 		}
64 	};
65 
66 	fclose(fp);
67 	return -1;
68 }
69 
dump_hex(char * var_name,const uint8_t * data,uint32_t len)70 static void dump_hex(char *var_name, const uint8_t *data,
71 	      uint32_t len)
72 {
73 #ifdef DEBUG_DUMP
74 	uint32_t i;
75 
76 	printf("LINE:%d  %s:", __LINE__, var_name);
77 	for (i = 0; i < len; i++) {
78 		if ((i % 16) == 7)
79 			printf(" ");
80 		if ((i % 16) == 0)
81 			printf("\n");
82 		printf("0x%02x", data[i]);
83 	}
84 	printf("\n");
85 #endif
86 }
87 
js_hash(uint32_t hash,uint8_t * buf,int len)88 static uint32_t js_hash(uint32_t hash, uint8_t *buf, int len)
89 {
90 	int i;
91 
92 	for (i = 0; i < len; i++)
93 		hash ^= ((hash << 5) + buf[i] + (hash >> 2));
94 
95 	return hash;
96 }
97 
process_key(int cmd,char * key)98 static int process_key(int cmd, char *key)
99 {
100 	TEEC_Result res = TEEC_SUCCESS;
101 	uint32_t error_origin = 0;
102 	TEEC_Context contex;
103 	TEEC_Session session;
104 	TEEC_Operation operation;
105 	TEEC_SharedMemory sm;
106 	const TEEC_UUID uuid = TA_KEYBOX_UUID;
107 
108 	/* [1] Connect to TEE */
109 	res = TEEC_InitializeContext(NULL, &contex);
110 	if (res != TEEC_SUCCESS) {
111 		printf("TEEC_InitializeContext failed with code 0x%x\n", res);
112 		return res;
113 	}
114 
115 	/* [2] Open seesion with TEE application */
116 	res = TEEC_OpenSession(&contex, &session, &uuid,
117 			       TEEC_LOGIN_PUBLIC, NULL, NULL, &error_origin);
118 	if (res != TEEC_SUCCESS) {
119 		printf("TEEC_Opensession failed with code 0x%x origin 0x%x\n",
120 		       res, error_origin);
121 		goto out;
122 	}
123 
124 	/* [3] Perform operation initialization */
125 	memset(&operation, 0, sizeof(TEEC_Operation));
126 	if (cmd == TA_KEY_READ) {
127 		sm.size = KEY_SIZE;
128 		sm.flags = TEEC_MEM_OUTPUT;
129 
130 		res = TEEC_AllocateSharedMemory(&contex, &sm);
131 		if (res != TEEC_SUCCESS) {
132 			printf("AllocateSharedMemory ERR! res = 0x%x\n", res);
133 			goto out1;
134 		}
135 
136 		operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_OUTPUT,
137 							TEEC_NONE,
138 							TEEC_NONE,
139 							TEEC_NONE);
140 		operation.params[0].memref.parent = &sm;
141 		operation.params[0].memref.offset = 0;
142 		operation.params[0].memref.size = sm.size;
143 
144 		res = TEEC_InvokeCommand(&session, TA_KEY_RNG, &operation, &error_origin);
145 		if (res != TEEC_SUCCESS) {
146 			printf("InvokeCommand ERR! res = 0x%x\n", res);
147 			TEEC_ReleaseSharedMemory(&sm);
148 			goto out1;
149 		}
150 		dump_hex("RNG -> ", sm.buffer, KEY_SIZE);
151 
152 		operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
153 							TEEC_NONE,
154 							TEEC_NONE,
155 							TEEC_NONE);
156 		operation.params[0].value.a = js_hash(0x47c6a7e6, sm.buffer, KEY_SIZE);
157 
158 		res = TEEC_InvokeCommand(&session, TA_KEY_VER, &operation, &error_origin);
159 		if (res != TEEC_SUCCESS) {
160 			printf("InvokeCommand ERR! res = 0x%x\n", res);
161 			TEEC_ReleaseSharedMemory(&sm);
162 			goto out1;
163 		}
164 		//printf("HASH -> %x", operation.params[0].value.a);
165 
166 		operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_OUTPUT,
167 							TEEC_VALUE_INPUT,
168 							TEEC_NONE,
169 							TEEC_NONE);
170 		operation.params[0].memref.parent = &sm;
171 		operation.params[0].memref.offset = 0;
172 		operation.params[0].memref.size = sm.size;
173 		operation.params[1].value.a = DEFAULT_STORAGE;
174 		res = TEEC_InvokeCommand(&session, TA_KEY_READ, &operation, &error_origin);
175 		if (res != TEEC_SUCCESS) {
176 			printf("InvokeCommand ERR! res = 0x%x\n", res);
177 			TEEC_ReleaseSharedMemory(&sm);
178 			goto out1;
179 		}
180 		 dump_hex("read key -> ", sm.buffer, KEY_SIZE);
181 
182 		operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_OUTPUT,
183 							TEEC_VALUE_INPUT,
184 							TEEC_NONE,
185 							TEEC_NONE);
186 		operation.params[0].memref.parent = &sm;
187 		operation.params[0].memref.offset = 0;
188 		operation.params[0].memref.size = sm.size;
189 		operation.params[1].value.a = DEFAULT_STORAGE;
190 		res = TEEC_InvokeCommand(&session, TA_KEY_READ, &operation, &error_origin);
191 		if (res != TEEC_SUCCESS) {
192 			printf("InvokeCommand ERR! res = 0x%x\n", res);
193 			TEEC_ReleaseSharedMemory(&sm);
194 			goto out1;
195 		}
196 		dump_hex("read key -> ", sm.buffer, KEY_SIZE);
197 
198 		memcpy(key, sm.buffer, KEY_SIZE);
199 
200 		TEEC_ReleaseSharedMemory(&sm);
201 	} else {
202 		operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
203 							TEEC_VALUE_INPUT,
204 							TEEC_NONE,
205 							TEEC_NONE);
206 
207 		operation.params[0].tmpref.size = KEY_SIZE;
208 		operation.params[0].tmpref.buffer = (void *)key;
209 		operation.params[1].value.a = DEFAULT_STORAGE;
210 
211 		res = TEEC_InvokeCommand(&session, TA_KEY_WRITE, &operation, &error_origin);
212 		if (res != TEEC_SUCCESS) {
213 			printf("InvokeCommand ERR! res = 0x%x\n", res);
214 		}
215 	}
216 
217 out1:
218 	TEEC_CloseSession(&session);
219 out:
220 	TEEC_FinalizeContext(&contex);
221 	return (res == TEEC_SUCCESS) ? 0 : -1;
222 }
223 
224 /* 1 -> string to ascii */
transform_byte(int direction,uint8_t c)225 static char transform_byte(int direction, uint8_t c)
226 {
227 	if (direction) {
228 		if (c > 'f')
229 			return -1;
230 		else if (c >= 'a')
231 			return c - 'a' + 10;
232 		else if (c > 'F')
233 			return -1;
234 		else if (c >= 'A')
235 			return c - 'A' + 10;
236 		else if (c > '9')
237 			return -1;
238 		else if (c >= '0')
239 			return c - '0';
240 		else
241 			return -1;
242 	} else {
243 		if (c > 9)
244 			return c + 'a' - 10;
245 		else
246 			return c + '0';
247 	}
248 }
249 
transform_key_to_ascii(int direction,uint8_t * in,uint8_t * out,int size)250 static int transform_key_to_ascii(int direction, uint8_t *in, uint8_t *out, int size)
251 {
252 	int i;
253 	uint8_t tmp;
254 
255 	for (i = 0; i < size; i++) {
256 		if (direction) {
257 			out[i] = (transform_byte(1, in[i << 1]) << 4) | transform_byte(1, in[(i << 1) + 1]);
258 		} else {
259 			out[i << 1] = transform_byte(0, in[i] >> 4);
260 			out[(i << 1) + 1] = transform_byte(0, in[i] & 0x0f);
261 		}
262 	}
263 }
264 
process_recovery(int argc,char * argv[])265 static int process_recovery(int argc, char *argv[])
266 {
267 	int fd, ret;
268 	uint8_t pw[KEY_SIZE];
269 	uint8_t t_pw[KEY_SIZE << 1];
270 
271 	fd = open("/tmp/syspw", O_RDONLY);
272 	if (fd == -1) {
273 		printf("ERROR: failed to open syspw\n");
274 		return -1;
275 	}
276 
277 	ret = read(fd, t_pw, KEY_SIZE << 1);
278 	if (ret != (KEY_SIZE << 1)) {
279 		printf("ERROR: bad pw length\n");
280 		return -1;
281 	}
282 
283 	transform_key_to_ascii(1, t_pw, pw, KEY_SIZE);
284 
285 	dump_hex("pw -> ", pw, KEY_SIZE);
286 	close(fd);
287 #ifdef CA_DEBUG
288 	return process_key((argc > 1) ? TA_KEY_READ : TA_KEY_WRITE,
289 			   pw);
290 #else
291 	return process_key(TA_KEY_WRITE, pw);
292 #endif
293 }
294 
process_ramfs(void)295 static int process_ramfs(void)
296 {
297 	int fd, ret;
298 	uint8_t pw[KEY_SIZE];
299 	uint8_t t_pw[KEY_SIZE << 1];
300 
301 	if (process_key(TA_KEY_READ, pw))
302 		return -1;
303 
304 	fd = open("/tmp/syspw", O_WRONLY | O_CREAT);
305 	if (fd == -1) {
306 		printf("ERROR: failed to open syspw\n");
307 		return -1;
308 	}
309 
310 	ftruncate(fd, 0);
311 	lseek(fd, 0, SEEK_SET);
312 
313 	transform_key_to_ascii(0, pw, t_pw, KEY_SIZE);
314 	ret = write(fd, t_pw, KEY_SIZE << 1);
315 	if (ret != (KEY_SIZE << 1)) {
316 		printf("ERROR: failed to write syspw (ret = %d)\n", ret);
317 		return -1;
318 	}
319 
320 	close(fd);
321 	return 0;
322 }
323 
main(int argc,char * argv[])324 int main(int argc, char *argv[])
325 {
326 #ifdef CA_DEBUG
327 	return (argc > 1) ? process_ramfs() : process_recovery(argc, argv);
328 #else
329 	int status;
330 
331 	/* check run under pid 1(init) */
332 	if ((getppid() != 1) || (argc > 1)) {
333 		return process_recovery(argc, argv);
334 	}
335 
336 	/* check proc has mounted */
337 	if (run_system("/bin/mount -t proc proc /proc")) {
338 		printf("ERROR: failed to run system command\n");
339 		return -1;
340 	}
341 
342 	/* check run at ramdisk */
343 	if (run_system("cat /proc/mounts > /tmp/proc_test")) {
344 		printf("ERROR: failed to run system command\n");
345 		return -1;
346 	}
347 
348 	status = check_ramdisk_env("/tmp/proc_test");
349 	remove("/tmp/proc_test");
350 	if (status)
351 		return -1;
352 
353 	return process_ramfs();
354 #endif
355 }
356