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