1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
4 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <strings.h>
9 #include <compiler.h>
10 #include <pthread.h>
11 #include <unistd.h>
12 #include <arpa/inet.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <rktest_ta.h>
16 #include <rktest.h>
17 #include <pta_secstor_ta_mgmt.h>
18 #include <sys/time.h>
19
20 #define STORAGE_UUID \
21 { 0x2d26d8a8, 0x5134, 0x4dd8, \
22 { 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71 } }
23 #define STORAGE_CMD_WRITE_OEM_NS_OTP 12
24 #define STORAGE_CMD_READ_OEM_NS_OTP 13
25
dump_hex(char * var_name __unused,const uint8_t * data __unused,uint32_t len __unused)26 static void dump_hex(char *var_name __unused, const uint8_t *data __unused,
27 uint32_t len __unused)
28 {
29 uint32_t i;
30
31 printf("LINE:%d %s:", __LINE__, var_name);
32 for (i = 0; i < len; i++) {
33 if ((i % 16) == 7)
34 printf(" ");
35 if ((i % 16) == 0)
36 printf("\n");
37 printf("0x%02x", data[i]);
38 }
39 printf("\n");
40 }
41
invoke_transfer_data(TEEC_Context * context,TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)42 static TEEC_Result invoke_transfer_data(TEEC_Context *context,
43 TEEC_Session *session,
44 TEEC_Operation *operation, uint32_t *error_origin)
45 {
46 TEEC_Result res = TEEC_SUCCESS;
47 TEEC_SharedMemory sm;
48 uint8_t temref_input[50];
49 const uint8_t transfer_inout[] = "Transfer data test.";
50
51 memcpy(temref_input, transfer_inout, sizeof(transfer_inout));
52 //Initialize the Shared Memory buffers
53 sm.size = sizeof(temref_input);
54 sm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
55
56 res = TEEC_AllocateSharedMemory(context, &sm);
57 if (res != TEEC_SUCCESS) {
58 printf("AllocateSharedMemory ERR! res= 0x%x\n", res);
59 return res;
60 }
61
62 memset(operation, 0, sizeof(TEEC_Operation));
63 //Note: these parameters must correspond to operation.params[],
64 operation->paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT,
65 TEEC_MEMREF_TEMP_INPUT,
66 TEEC_MEMREF_PARTIAL_OUTPUT, TEEC_NONE);
67 operation->params[0].value.a = 66;
68 //This buffer will be temporarily shared.
69 operation->params[1].tmpref.size = sizeof(temref_input);
70 operation->params[1].tmpref.buffer = (void *)temref_input;
71 operation->params[2].memref.parent = &sm;
72 operation->params[2].memref.offset = 0;
73 operation->params[2].memref.size = sm.size;
74
75 //Invoke to TA
76 res = TEEC_InvokeCommand(session, RKTEST_TA_CMD_TRANSFER_DATA,
77 operation, error_origin);
78 if (res != TEEC_SUCCESS) {
79 printf("InvokeCommand ERR! res= 0x%x\n", res);
80 goto out;
81 }
82
83 //Check the result
84 if (operation->params[0].value.a == 66 + 1 &&
85 operation->params[0].value.b == operation->params[0].value.a)
86 printf("test value : Pass!\n");
87 else
88 printf("test value : Fail! (mismatch values)\n");
89
90 //Check if the sm->buffer (params[2]) = TRANSFER_INOUT (params[1])
91 if (memcmp(sm.buffer, transfer_inout, sizeof(transfer_inout)) == 0)
92 printf("test buffer : Pass!\n");
93 else
94 printf("test buffer : Fail! (mismatch buffer)\n");
95
96 out:
97 TEEC_ReleaseSharedMemory(&sm);
98 return res;
99 };
100
invoke_storage(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)101 static TEEC_Result invoke_storage(TEEC_Session *session,
102 TEEC_Operation *operation, uint32_t *error_origin)
103 {
104 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_STORAGE,
105 operation, error_origin);
106 };
107
test_storage_speed(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin,uint32_t storage_type,uint32_t * storage_size,uint32_t times)108 static TEEC_Result test_storage_speed(TEEC_Session *session,
109 TEEC_Operation *operation, uint32_t *error_origin,
110 uint32_t storage_type, uint32_t *storage_size, uint32_t times)
111 {
112 TEEC_Result res = TEEC_SUCCESS;
113 uint8_t *temref_input = NULL;
114
115 for (uint32_t i = 0; i < times; i++) {
116 temref_input = malloc(storage_size[i]);
117 memset(temref_input, 0xab, storage_size[i]);
118 memset(operation, 0, sizeof(TEEC_Operation));
119
120 //Note: these parameters must correspond to operation.params[],
121 operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, TEEC_VALUE_INPUT,
122 TEEC_NONE, TEEC_NONE);
123 operation->params[0].tmpref.size = storage_size[i];
124 operation->params[0].tmpref.buffer = (void *)temref_input;
125 operation->params[1].value.a = storage_type;
126
127 //Invoke to TA
128 res = TEEC_InvokeCommand(session, RKTEST_TA_CMD_STORAGE_SPEED,
129 operation, error_origin);
130
131 if (temref_input)
132 free(temref_input);
133
134 if (res != TEEC_SUCCESS) {
135 printf("InvokeCommand ERR! res= 0x%x\n", res);
136 break;
137 }
138 }
139
140 return res;
141 };
142
invoke_storage_speed(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)143 static TEEC_Result invoke_storage_speed(TEEC_Session *session,
144 TEEC_Operation *operation, uint32_t *error_origin)
145 {
146 TEEC_Result res = TEEC_SUCCESS;
147 uint32_t rpmb_storage_size[] = {32, 1024, 4096, 30000};
148 uint32_t ree_storage_size[] = {32, 1024, 4096, 30000, 60000};
149
150 res = test_storage_speed(session, operation, error_origin, TEE_STORAGE_PRIVATE_RPMB,
151 rpmb_storage_size, sizeof(rpmb_storage_size) / sizeof(rpmb_storage_size[0]));
152 if (res != TEEC_SUCCESS)
153 return res;
154
155 res = test_storage_speed(session, operation, error_origin, TEE_STORAGE_PRIVATE_REE,
156 ree_storage_size, sizeof(ree_storage_size) / sizeof(ree_storage_size[0]));
157 return res;
158 }
159
invoke_property(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)160 static TEEC_Result invoke_property(TEEC_Session *session,
161 TEEC_Operation *operation, uint32_t *error_origin)
162 {
163 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_PROPERTY,
164 operation, error_origin);
165 };
166
invoke_crypto_sha(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)167 static TEEC_Result invoke_crypto_sha(TEEC_Session *session,
168 TEEC_Operation *operation, uint32_t *error_origin)
169 {
170 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_CRYPTO_SHA,
171 operation, error_origin);
172 };
173
invoke_crypto_aes(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)174 static TEEC_Result invoke_crypto_aes(TEEC_Session *session,
175 TEEC_Operation *operation, uint32_t *error_origin)
176 {
177 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_CRYPTO_AES,
178 operation, error_origin);
179 };
180
invoke_crypto_rsa(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)181 static TEEC_Result invoke_crypto_rsa(TEEC_Session *session,
182 TEEC_Operation *operation, uint32_t *error_origin)
183 {
184 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_CRYPTO_RSA,
185 operation, error_origin);
186 };
187
invoke_secstor_ta(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)188 static TEEC_Result invoke_secstor_ta(TEEC_Session *session,
189 TEEC_Operation *operation, uint32_t *error_origin)
190 {
191 FILE *f = NULL;
192 void *buf = NULL;
193 size_t s = 0;
194 const char *ta_path_v2_and =
195 "/vendor/lib/optee_armtz/1db57234-dacd-462d-9bb1-ae79de44e2a5.ta";
196 const char *ta_path_v2_linux =
197 "/lib/optee_armtz/1db57234-dacd-462d-9bb1-ae79de44e2a5.ta";
198 TEEC_Result res = TEEC_ERROR_GENERIC;
199
200 /* Read ta to the buf. */
201 f = fopen(ta_path_v2_and, "rb");
202 if (!f) {
203 f = fopen(ta_path_v2_linux, "rb");
204 if (!f) {
205 printf("fopen(\"%s\") and (\"%s\") fail!", ta_path_v2_and, ta_path_v2_linux);
206 goto out;
207 }
208 }
209 if (fseek(f, 0, SEEK_END)) {
210 printf("fseek fail!");
211 goto out;
212 }
213 s = ftell(f);
214 rewind(f);
215 buf = malloc(s);
216 if (!buf) {
217 printf("malloc fail!");
218 goto out;
219 }
220 if (fread(buf, 1, s, f) != s) {
221 printf("fread fail!");
222 goto out;
223 }
224 fclose(f);
225
226 memset(operation, 0, sizeof(TEEC_Operation));
227 operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE,
228 TEEC_NONE, TEEC_NONE);
229 operation->params[0].tmpref.buffer = buf;
230 operation->params[0].tmpref.size = s;
231
232 /*
233 * The data will be sent to the built-in TA(secstor_ta_mgmt) for processing,
234 * such as verification, encryption, secure storage, etc.
235 */
236 res = TEEC_InvokeCommand(session, PTA_SECSTOR_TA_MGMT_BOOTSTRAP, operation,
237 error_origin);
238 if (res != TEEC_SUCCESS) {
239 printf("InvokeCommand ERR! res= 0x%x\n", res);
240 goto out;
241 }
242
243 out:
244 printf("Installing TAs done\n");
245 if (buf)
246 free(buf);
247 return res;
248 };
249
invoke_otp_read(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)250 static TEEC_Result invoke_otp_read(TEEC_Session *session,
251 TEEC_Operation *operation, uint32_t *error_origin)
252 {
253 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_OEM_OTP_READ,
254 operation, error_origin);
255 };
256
invoke_otp_write(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)257 static TEEC_Result invoke_otp_write(TEEC_Session *session,
258 TEEC_Operation *operation, uint32_t *error_origin)
259 {
260 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_OEM_OTP_WRITE,
261 operation, error_origin);
262 };
263
invoke_otp_size(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)264 static TEEC_Result invoke_otp_size(TEEC_Session *session,
265 TEEC_Operation *operation, uint32_t *error_origin)
266 {
267 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_OEM_OTP_SIZE,
268 operation, error_origin);
269 };
270
invoke_otp_ns_read(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)271 static TEEC_Result invoke_otp_ns_read(TEEC_Session *session,
272 TEEC_Operation *operation,
273 uint32_t *error_origin)
274 {
275 TEEC_Result res = TEEC_SUCCESS;
276 uint32_t offset = 0;
277 uint8_t read_data[8];
278
279 memset(read_data, 0, sizeof(read_data));
280 memset(operation, 0, sizeof(TEEC_Operation));
281 operation->paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
282 TEEC_MEMREF_TEMP_OUTPUT,
283 TEEC_NONE, TEEC_NONE);
284 operation->params[0].value.a = offset;
285 operation->params[1].tmpref.size = sizeof(read_data);
286 operation->params[1].tmpref.buffer = (void *)read_data;
287
288 res = TEEC_InvokeCommand(session, STORAGE_CMD_READ_OEM_NS_OTP,
289 operation, error_origin);
290 if (res != TEEC_SUCCESS) {
291 printf("InvokeCommand ERR! res= 0x%x\n", res);
292 return res;
293 }
294
295 dump_hex("otp_ns_read data", read_data, sizeof(read_data));
296 printf("test otp_ns_read : Pass!\n");
297 return res;
298 };
299
invoke_otp_ns_write(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)300 static TEEC_Result invoke_otp_ns_write(TEEC_Session *session,
301 TEEC_Operation *operation,
302 uint32_t *error_origin)
303 {
304 TEEC_Result res = TEEC_SUCCESS;
305 uint32_t offset = 0;
306 uint8_t write_data = 0x01;
307
308 memset(operation, 0, sizeof(TEEC_Operation));
309 operation->paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
310 TEEC_MEMREF_TEMP_INPUT,
311 TEEC_NONE, TEEC_NONE);
312 operation->params[0].value.a = offset;
313 operation->params[1].tmpref.size = sizeof(write_data);
314 operation->params[1].tmpref.buffer = (void *)&write_data;
315
316 res = TEEC_InvokeCommand(session, STORAGE_CMD_WRITE_OEM_NS_OTP,
317 operation, error_origin);
318 if (res != TEEC_SUCCESS) {
319 printf("InvokeCommand ERR! res= 0x%x\n", res);
320 return res;
321 }
322
323 printf("test otp_ns_write : Pass!\n");
324 return res;
325 };
326
invoke_trng_read(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)327 static TEEC_Result invoke_trng_read(TEEC_Session *session,
328 TEEC_Operation *operation, uint32_t *error_origin)
329 {
330 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_TRNG_READ,
331 operation, error_origin);
332 }
333
server_init(void * arg __unused)334 static void *server_init(void *arg __unused)
335 {
336 int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
337 struct sockaddr_in serv_addr;
338
339 memset(&serv_addr, 0, sizeof(serv_addr));
340 serv_addr.sin_family = AF_INET;
341 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
342 serv_addr.sin_port = htons(2345);
343
344 bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
345 listen(serv_sock, 10);
346
347 struct sockaddr_in clnt_addr;
348 socklen_t clnt_addr_size = sizeof(clnt_addr);
349 int clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_size);
350
351 char str[] = "I am data from server!";
352 write(clnt_sock, str, sizeof(str));
353
354 char buffer[64];
355 read(clnt_sock, buffer, sizeof(buffer));
356 printf("Message from TA: %s\n", buffer);
357
358 read(clnt_sock, buffer, 1);
359
360 close(clnt_sock);
361 close(serv_sock);
362 return NULL;
363 }
364
invoke_socket(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)365 static TEEC_Result invoke_socket(TEEC_Session *session,
366 TEEC_Operation *operation, uint32_t *error_origin)
367 {
368 pthread_t server;
369 pthread_create(&server, 0, server_init, NULL);
370
371 TEEC_Result res;
372 res = TEEC_InvokeCommand(session, RKTEST_TA_CMD_SOCKET,
373 operation, error_origin);
374 pthread_join(server, NULL);
375 return res;
376 }
377
invoke_crypto_hw(TEEC_Context * context,TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)378 static TEEC_Result invoke_crypto_hw(TEEC_Context *context, TEEC_Session *session,
379 TEEC_Operation *operation, uint32_t *error_origin)
380 {
381 TEEC_Result res;
382 TEEC_SharedMemory sm;
383 uint8_t data[128 * 1024];
384 uint8_t check_data[128 * 1024];
385
386 memset(data, 0xab, sizeof(data));
387 memset(check_data, 0xab, sizeof(check_data));
388 memset(operation, 0, sizeof(TEEC_Operation));
389
390 operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT,
391 TEEC_NONE,
392 TEEC_NONE,
393 TEEC_NONE);
394
395 sm.size = sizeof(data);
396 sm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
397 res = TEEC_AllocateSharedMemory(context, &sm);
398 if (res != TEEC_SUCCESS) {
399 printf("AllocateSharedMemory ERR! TEEC res= 0x%x", res);
400 return res;
401 }
402 memcpy(sm.buffer, data, sm.size);
403 operation->params[0].memref.parent = &sm;
404 operation->params[0].memref.offset = 0;
405 operation->params[0].memref.size = sm.size;
406
407 struct timeval time;
408 gettimeofday(&time, NULL);
409 res = TEEC_InvokeCommand(session, RKTEST_TA_CMD_CRYPTO_HW,
410 operation, error_origin);
411 struct timeval time2;
412 gettimeofday(&time2, NULL);
413 printf("invoke_crypto_hw use time: %ld us \n",
414 (time2.tv_sec - time.tv_sec) * 1000000 + (time2.tv_usec - time.tv_usec));
415
416 if (res == TEEC_SUCCESS) {
417 if (memcmp(data, check_data, sizeof(data)) == 0) {
418 printf("hardware crypto success!\n");
419 } else {
420 printf("hardware crypto fail!\n");
421 }
422 }
423 return res;
424 };
425
invoke_derive_key(TEEC_Session * session,TEEC_Operation * operation,uint32_t * error_origin)426 static TEEC_Result invoke_derive_key(TEEC_Session *session,
427 TEEC_Operation *operation, uint32_t *error_origin)
428 {
429 return TEEC_InvokeCommand(session, RKTEST_TA_CMD_DERIVE_KEY,
430 operation, error_origin);
431 }
432
rk_test(uint32_t invoke_command)433 TEEC_Result rk_test(uint32_t invoke_command)
434 {
435 TEEC_Result res = TEEC_SUCCESS;
436 uint32_t error_origin = 0;
437 TEEC_Context contex;
438 TEEC_Session session;
439 TEEC_Operation operation;
440 const TEEC_UUID secstor_uuid = PTA_SECSTOR_TA_MGMT_UUID;
441 const TEEC_UUID rktest_uuid = RKTEST_TA_UUID;
442 const TEEC_UUID storage_uuid = STORAGE_UUID;
443 const TEEC_UUID *uuid;
444
445 switch (invoke_command) {
446 case SECSTOR_TA:
447 /*
448 * Call the built-in TA(secstor_ta_mgmt) to handle SECSTOR.
449 */
450 uuid = &secstor_uuid;
451 break;
452 case OTP_NS_READ:
453 case OTP_NS_WRITE:
454 /*
455 * Call the built-in TA(uboot_storedata_otp.ta) to handle NS OTP.
456 */
457 uuid = &storage_uuid;
458 break;
459 default:
460 uuid = &rktest_uuid;
461 break;
462 }
463
464 //[1] Connect to TEE
465 res = TEEC_InitializeContext(NULL, &contex);
466 if (res != TEEC_SUCCESS) {
467 printf("TEEC_InitializeContext failed with code 0x%x\n", res);
468 return res;
469 }
470
471 //[2] Open session with TEE application
472 res = TEEC_OpenSession(&contex, &session, uuid,
473 TEEC_LOGIN_PUBLIC, NULL, NULL, &error_origin);
474 if (res != TEEC_SUCCESS) {
475 printf("TEEC_Opensession failed with code 0x%x origin 0x%x\n",
476 res, error_origin);
477 goto out;
478 }
479
480 //[3] Perform operation initialization
481 memset(&operation, 0, sizeof(TEEC_Operation));
482 operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE,
483 TEEC_NONE, TEEC_NONE);
484
485 //[4] Start invoke command to the TEE application.
486 switch (invoke_command) {
487 case TRANSFER_DATA:
488 res = invoke_transfer_data(&contex, &session, &operation, &error_origin);
489 break;
490 case STORAGE:
491 res = invoke_storage(&session, &operation, &error_origin);
492 break;
493 case STORAGE_SPEED:
494 res = invoke_storage_speed(&session, &operation, &error_origin);
495 break;
496 case PROPERTY:
497 res = invoke_property(&session, &operation, &error_origin);
498 break;
499 case CRYPTO_SHA:
500 res = invoke_crypto_sha(&session, &operation, &error_origin);
501 break;
502 case CRYPTO_AES:
503 res = invoke_crypto_aes(&session, &operation, &error_origin);
504 break;
505 case CRYPTO_RSA:
506 res = invoke_crypto_rsa(&session, &operation, &error_origin);
507 break;
508 case SECSTOR_TA:
509 res = invoke_secstor_ta(&session, &operation, &error_origin);
510 break;
511 case OTP_READ:
512 res = invoke_otp_read(&session, &operation, &error_origin);
513 break;
514 case OTP_WRITE:
515 res = invoke_otp_write(&session, &operation, &error_origin);
516 break;
517 case OTP_SIZE:
518 res = invoke_otp_size(&session, &operation, &error_origin);
519 break;
520 case OTP_NS_READ:
521 res = invoke_otp_ns_read(&session, &operation, &error_origin);
522 break;
523 case OTP_NS_WRITE:
524 res = invoke_otp_ns_write(&session, &operation, &error_origin);
525 break;
526 case TRNG_READ:
527 res = invoke_trng_read(&session, &operation, &error_origin);
528 break;
529 case SOCKET:
530 res = invoke_socket(&session, &operation, &error_origin);
531 break;
532 case CRYPTO_HW:
533 res = invoke_crypto_hw(&contex, &session, &operation, &error_origin);
534 break;
535 case DERIVE_KEY:
536 res = invoke_derive_key(&session, &operation, &error_origin);
537 break;
538 default:
539 printf("Doing nothing.\n");
540 break;
541 }
542 if (res != TEEC_SUCCESS) {
543 printf("Test ERR. res 0x%x origin 0x%x\n", res, error_origin);
544 goto out1;
545 }
546 printf("Test OK.\n");
547 //[5] Tidyup resources
548 out1:
549 TEEC_CloseSession(&session);
550 out:
551 TEEC_FinalizeContext(&contex);
552 return res;
553 }
554
555