xref: /OK3568_Linux_fs/external/security/rk_tee_user/v2/host/rk_test/rktest.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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