blob: 6fcbc7cbab7b3176faf490d4d892ec39b63892cb [file] [log] [blame]
Pascal Brandc639ac82015-07-02 08:53:34 +02001/*
2 * Copyright (c) 2014, STMicroelectronics International N.V.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27#include <stdint.h>
28
29#include <compiler.h>
30#include <ta_crypt.h>
31#include <ta_os_test.h>
32#include <tee_internal_api_extensions.h>
33
34#include "os_test.h"
35#include "testframework.h"
36
37enum p_type {
38 P_TYPE_BOOL,
39 P_TYPE_INT,
40 P_TYPE_UUID,
41 P_TYPE_IDENTITY,
42 P_TYPE_STRING,
43 P_TYPE_BINARY_BLOCK,
44};
45
46struct p_attr {
47 const char *str;
48 enum p_type type;
49 bool retrieved;
50};
51
52static TEE_Result print_properties(TEE_PropSetHandle h,
53 TEE_PropSetHandle prop_set,
54 struct p_attr *p_attrs, size_t num_p_attrs)
55{
56TEE_Result res;
57size_t n;
58
59TEE_StartPropertyEnumerator(h, prop_set);
60
61while (true) {
62 char nbuf[80];
63 char vbuf[80];
64 char vbuf2[80];
65 size_t nblen = sizeof(nbuf);
66 size_t vblen = sizeof(vbuf);
67 size_t vblen2 = sizeof(vbuf2);
68
69 res = TEE_GetPropertyName(h, nbuf, &nblen);
70 if (res != TEE_SUCCESS) {
71 EMSG("TEE_GetPropertyName returned 0x%x\n",
72 (unsigned int)res);
73 return res;
74 }
75
76 res = TEE_GetPropertyAsString(h, NULL, vbuf, &vblen);
77 if (res != TEE_SUCCESS) {
78 EMSG("1TEE_GetPropertyAsString(\"%s\") returned 0x%x\n",
79 nbuf, (unsigned int)res);
80 return res;
81 }
82 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
83 if (res != TEE_SUCCESS) {
84 EMSG("2TEE_GetPropertyAsString(\"%s\") returned 0x%x\n",
85 nbuf, (unsigned int)res);
86 return res;
87 }
88 if (my_strcmp(vbuf, vbuf2) != 0) {
89 EMSG("String of \"%s\" differs\n", nbuf);
90 return TEE_ERROR_GENERIC;
91 }
92
93 DMSG("Found \"%s\" value \"%s\"\n", nbuf, vbuf);
94
95 for (n = 0; n < num_p_attrs; n++) {
96 if (my_strcmp(nbuf, p_attrs[n].str) != 0)
97 continue;
98
99 if (p_attrs[n].retrieved) {
100 EMSG("Value \"%s\" already retrieved\n",
101 p_attrs[n].str);
102 return TEE_ERROR_GENERIC;
103 }
104 p_attrs[n].retrieved = true;
105
106 switch (p_attrs[n].type) {
107 case P_TYPE_BOOL:
108 {
109 bool v;
110
111 res =
112 TEE_GetPropertyAsBool(h, NULL, &v);
113 if (res != TEE_SUCCESS) {
114 EMSG(
115 "TEE_GetPropertyAsBool(\"%s\") returned 0x%x\n",
116 nbuf, (unsigned int)res);
117 return res;
118 }
119 }
120 break;
121
122 case P_TYPE_INT:
123 {
124 uint32_t v;
125
126 res = TEE_GetPropertyAsU32(h, NULL, &v);
127 if (res != TEE_SUCCESS) {
128 EMSG(
129 "TEE_GetPropertyAsU32(\"%s\") returned 0x%x\n",
130 nbuf, (unsigned int)res);
131 return res;
132 }
133 }
134 break;
135
136 case P_TYPE_UUID:
137 {
138 TEE_UUID v;
139
140 res =
141 TEE_GetPropertyAsUUID(h, NULL, &v);
142 if (res != TEE_SUCCESS) {
143 EMSG(
144 "TEE_GetPropertyAsUUID(\"%s\") returned 0x%x\n",
145 nbuf, (unsigned int)res);
146 return res;
147 }
148 }
149 break;
150
151 case P_TYPE_IDENTITY:
152 {
153 TEE_Identity v;
154
155 res =
156 TEE_GetPropertyAsIdentity(h, NULL,
157 &v);
158 if (res != TEE_SUCCESS) {
159 EMSG(
160 "TEE_GetPropertyAsIdentity(\"%s\") returned 0x%x\n",
161 nbuf, (unsigned int)res);
162 return res;
163 }
164 }
165 break;
166
167 case P_TYPE_STRING:
168 /* Already read as string */
169 break;
170
171 case P_TYPE_BINARY_BLOCK:
172 {
173 char bbuf[80];
174 size_t bblen = sizeof(bbuf);
175
176 res =
177 TEE_GetPropertyAsBinaryBlock(h,
178 NULL,
179 bbuf,
180 &bblen);
181 if (res != TEE_SUCCESS) {
182 EMSG(
183 "TEE_GetPropertyAsBinaryBlock(\"%s\") returned 0x%x\n",
184 nbuf, (unsigned int)res);
185 return res;
186 }
187 if (my_strcmp
188 ("myprop.binaryblock", nbuf) == 0) {
189 const char exp_bin_value[] =
190 "Hello world!";
191
192 if (bblen !=
193 my_strlen(exp_bin_value)
194 ||
195 TEE_MemCompare
196 (exp_bin_value, bbuf,
197 bblen) != 0) {
198 EMSG(
199 "Binary buffer of \"%s\" differs from \"%s\"\n",
200 nbuf, exp_bin_value);
201 EMSG(
202 "Got \"%s\"\n",
203 bbuf);
204 return
205 TEE_ERROR_GENERIC;
206 }
207 }
208
209 }
210 break;
211
212 default:
213 EMSG("Unknown type (%d) for \"%s\"\n",
214 p_attrs[n].type, p_attrs[n].str);
215 return TEE_ERROR_GENERIC;
216 }
217 }
218
219 res = TEE_GetNextProperty(h);
220 if (res != TEE_SUCCESS) {
221 if (res == TEE_ERROR_ITEM_NOT_FOUND)
222 return TEE_SUCCESS;
223 return res;
224 }
225}
226}
227
228static TEE_Result test_malloc(void)
229{
230 void *p = TEE_Malloc(4, 0);
231
232 if (p == NULL) {
233 EMSG("TEE_Malloc failed\n");
234 return TEE_ERROR_OUT_OF_MEMORY;
235 }
236 TEE_Free(p);
237 TEE_Free(NULL);
238
239 return TEE_SUCCESS;
240}
241
242static TEE_Result test_properties(void)
243{
244 TEE_Result res = TEE_ERROR_GENERIC;
245 TEE_PropSetHandle h;
246 struct p_attr p_attrs[] = {
247 {"gpd.ta.appID", P_TYPE_UUID},
248 {"gpd.ta.singleInstance", P_TYPE_BOOL},
249 {"gpd.ta.multiSession", P_TYPE_BOOL},
250 {"gpd.ta.instanceKeepAlive", P_TYPE_BOOL},
251 {"gpd.ta.dataSize", P_TYPE_INT},
252 {"gpd.ta.stackSize", P_TYPE_INT},
253 {"gpd.ta.version", P_TYPE_STRING},
254 {"gpd.ta.description", P_TYPE_STRING},
255 {"gpd.client.identity", P_TYPE_IDENTITY},
256 {"gpd.tee.apiversion", P_TYPE_STRING},
257 {"gpd.tee.description", P_TYPE_STRING},
258 {"gpd.tee.deviceID", P_TYPE_UUID},
259 {"gpd.tee.systemTime.protectionLevel", P_TYPE_INT},
260 {"gpd.tee.TAPersistentTime.protectionLevel", P_TYPE_INT},
261 {"gpd.tee.arith.maxBigIntSize", P_TYPE_INT},
262 {"gpd.tee.cryptography.ecc", P_TYPE_BOOL},
263 {"gpd.tee.trustedStorage.antiRollback.protectionLevel", P_TYPE_INT},
264 {"gpd.tee.trustedos.implementation.version", P_TYPE_STRING},
265 {"gpd.tee.trustedos.implementation.binaryversion", P_TYPE_INT},
266 {"gpd.tee.trustedos.manufacturer", P_TYPE_STRING},
267 {"gpd.tee.firmware.implementation.version", P_TYPE_STRING},
268 {"gpd.tee.firmware.implementation.binaryversion", P_TYPE_INT},
269 {"gpd.tee.firmware.manufacturer", P_TYPE_STRING},
270 {"myprop.true", P_TYPE_BOOL},
271 {"myprop.42", P_TYPE_INT},
272 {"myprop.123", P_TYPE_UUID},
273 {"myprop.1234", P_TYPE_IDENTITY},
274 {"myprop.hello", P_TYPE_STRING},
275 {"myprop.binaryblock", P_TYPE_BINARY_BLOCK},
276 };
277 const size_t num_p_attrs = sizeof(p_attrs) / sizeof(p_attrs[0]);
278 size_t n;
279
280 res = TEE_AllocatePropertyEnumerator(&h);
281 if (res != TEE_SUCCESS) {
282 EMSG("TEE_AllocatePropertyEnumerator: returned 0x%x\n",
283 (unsigned int)res);
284 return TEE_ERROR_GENERIC;
285 }
286
287 printf("Getting properties for current TA\n");
288 res = print_properties(h, TEE_PROPSET_CURRENT_TA, p_attrs, num_p_attrs);
289 if (res != TEE_SUCCESS)
290 goto cleanup_return;
291
292 printf("Getting properties for current client\n");
293 res = print_properties(h, TEE_PROPSET_CURRENT_CLIENT, p_attrs,
294 num_p_attrs);
295 if (res != TEE_SUCCESS)
296 goto cleanup_return;
297
298 printf("Getting properties for implementation\n");
299 res = print_properties(h, TEE_PROPSET_TEE_IMPLEMENTATION, p_attrs,
300 num_p_attrs);
301 if (res != TEE_SUCCESS)
302 goto cleanup_return;
303
304 for (n = 0; n < num_p_attrs; n++) {
305 if (!p_attrs[n].retrieved) {
306 EMSG("\"%s\" not retrieved\n", p_attrs[n].str);
307 res = TEE_ERROR_GENERIC;
308 goto cleanup_return;
309 }
310 }
311
312cleanup_return:
313 TEE_FreePropertyEnumerator(h);
314 return res;
315}
316
317static TEE_Result test_mem_access_right(uint32_t param_types,
318 TEE_Param params[4])
319{
320 static const TEE_UUID test_uuid = TA_OS_TEST_UUID;
321 TEE_Result res;
322 uint32_t ret_orig;
323 uint32_t l_pts;
324 TEE_Param l_params[4] = { { {0} } };
325 uint8_t buf[32];
326 TEE_TASessionHandle sess = TEE_HANDLE_NULL;
327
328 if (param_types !=
329 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
330 return TEE_ERROR_GENERIC;
331 res =
332 TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
333 TEE_MEMORY_ACCESS_ANY_OWNER,
334 params[0].memref.buffer,
335 params[0].memref.size);
336 if (res != TEE_SUCCESS)
337 return res;
338 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
339 params[0].memref.buffer,
340 params[0].memref.size);
341 if (res != TEE_ERROR_ACCESS_DENIED)
342 return TEE_ERROR_GENERIC;
343
344 res = TEE_OpenTASession(&test_uuid, 0, 0, NULL, &sess, &ret_orig);
345 if (res != TEE_SUCCESS) {
346 EMSG("test_mem_access_right: TEE_OpenTASession failed\n");
347 goto cleanup_return;
348 }
349
350 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0);
351 l_params[0].memref.buffer = buf;
352 l_params[0].memref.size = sizeof(buf);
353 res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_PRIVATE_PARAMS,
354 l_pts, l_params, &ret_orig);
355 if (res != TEE_SUCCESS) {
356 EMSG("test_mem_access_right: TEE_InvokeTACommand failed\n");
357 goto cleanup_return;
358 }
359
360cleanup_return:
361 TEE_CloseTASession(sess);
362 return res;
363}
364
365static TEE_Result test_time(void)
366{
367 TEE_Result res;
368 TEE_Time t;
369 TEE_Time sys_t;
370
371 static const TEE_Time null_time = { 0, 0 };
372 static const TEE_Time wrap_time = { UINT32_MAX, 999 };
373
374 TEE_GetSystemTime(&sys_t);
375 printf("system time %u.%03u\n", (unsigned int)sys_t.seconds,
376 (unsigned int)sys_t.millis);
377
378 TEE_GetREETime(&t);
379 printf("REE time %u.%03u\n", (unsigned int)t.seconds,
380 (unsigned int)t.millis);
381
382 res = TEE_GetTAPersistentTime(&t);
383 switch (res) {
384 case TEE_SUCCESS:
385 printf("Stored TA time %u.%03u\n", (unsigned int)t.seconds,
386 (unsigned int)t.millis);
387 break;
388 case TEE_ERROR_OVERFLOW:
389 EMSG("Stored TA time overflowed %u.%03u\n",
390 (unsigned int)t.seconds, (unsigned int)t.millis);
391 break;
392 case TEE_ERROR_TIME_NOT_SET:
393 EMSG("TA time not stored\n");
394 break;
395 case TEE_ERROR_TIME_NEEDS_RESET:
396 EMSG("TA time needs reset\n");
397 break;
398 default:
399 return res;
400 }
401
402 res = TEE_SetTAPersistentTime(&null_time);
403 if (res != TEE_SUCCESS) {
404 EMSG("TEE_SetTAPersistentTime: failed\n");
405 return res;
406 }
407
408 res = TEE_GetTAPersistentTime(&t);
409 if (res != TEE_SUCCESS) {
410 EMSG("TEE_GetTAPersistentTime null: failed\n");
411 return res;
412 }
413 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
414 (unsigned int)t.millis);
415 /*
416 * The time between TEE_SetTAPersistentTime() and
417 * TEE_GetTAPersistentTime() should be much less than 1 second, in fact
418 * it's not even a millisecond.
419 */
420 if (t.seconds > 1 || t.millis >= 1000) {
421 EMSG("Unexpected stored TA time %u.%03u\n",
422 (unsigned int)t.seconds, (unsigned int)t.millis);
423 return TEE_ERROR_BAD_STATE;
424 }
425
426 res = TEE_SetTAPersistentTime(&wrap_time);
427 if (res != TEE_SUCCESS) {
428 EMSG("TEE_SetTAPersistentTime wrap: failed\n");
429 return res;
430 }
431
432 res = TEE_Wait(1000);
433 if (res != TEE_SUCCESS)
434 EMSG("TEE_Wait wrap: failed\n");
435
436 res = TEE_GetTAPersistentTime(&t);
437 if (res != TEE_ERROR_OVERFLOW) {
438 EMSG("TEE_GetTAPersistentTime: failed\n");
439 return TEE_ERROR_BAD_STATE;
440 }
441 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
442 (unsigned int)t.millis);
443
444 if (t.seconds > sys_t.seconds) {
445 EMSG("Unexpected wrapped time %u.%03u (sys_t %u.%03u)\n",
446 (unsigned int)t.seconds, (unsigned int)t.millis,
447 (unsigned int)sys_t.seconds, (unsigned int)sys_t.millis);
448 return TEE_ERROR_BAD_STATE;
449 }
450
451 return TEE_SUCCESS;
452}
453
454TEE_Result ta_entry_basic(uint32_t param_types, TEE_Param params[4])
455{
456 TEE_Result res = TEE_ERROR_GENERIC;
457
458 printf("ta_entry_basic: enter\n");
459
460 res = test_malloc();
461 if (res != TEE_SUCCESS)
462 return res;
463
464 res = test_properties();
465 if (res != TEE_SUCCESS)
466 return res;
467
468 res = test_mem_access_right(param_types, params);
469 if (res != TEE_SUCCESS)
470 return res;
471
472 res = test_time();
473 if (res != TEE_SUCCESS)
474 return res;
475
476 /* mpa lib test bench, panics TA on failure */
477 tb_main();
478
479 return TEE_SUCCESS;
480}
481
482TEE_Result ta_entry_panic(uint32_t param_types, TEE_Param params[4])
483{
484 volatile bool mytrue = true;
485 (void)param_types;
486 (void)params;
487
488 printf("ta_entry_panic: enter\n");
489 /*
490 * Somewhat clumsy way of avoiding compile errors if TEE_Panic() has
491 * the __noreturn attribute.
492 */
493 if (mytrue)
494 TEE_Panic(0xbeef);
495
496 /*
497 * Should not be reached, but if it is the testsuite can detect that
498 * TEE_Panic() returned instead of panicking the TA.
499 */
500 return TEE_SUCCESS;
501}
502
503TEE_Result ta_entry_client_with_timeout(uint32_t param_types,
504 TEE_Param params[4])
505{
506 static const TEE_UUID os_test_uuid = TA_OS_TEST_UUID;
507 TEE_Result res;
508 TEE_TASessionHandle sess;
509 uint32_t ret_orig;
510
511 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
512 TEE_PARAM_TYPE_NONE,
513 TEE_PARAM_TYPE_NONE,
514 TEE_PARAM_TYPE_NONE)) {
515 EMSG("ta_entry_client_with_timeout: bad parameters\n");
516 return TEE_ERROR_BAD_PARAMETERS;
517 }
518
519 res = TEE_OpenTASession(&os_test_uuid, 0, 0, NULL, &sess, &ret_orig);
520 if (res != TEE_SUCCESS) {
521 EMSG(
522 "ta_entry_client_with_timeout: TEE_OpenTASession failed\n");
523 return res;
524 }
525
526 res =
527 TEE_InvokeTACommand(sess, params[0].value.a / 2,
528 TA_OS_TEST_CMD_WAIT, param_types, params,
529 &ret_orig);
530
531 if (ret_orig != TEE_ORIGIN_TRUSTED_APP || res != TEE_ERROR_CANCEL) {
532 EMSG("ta_entry_client_with_timeout: TEE_InvokeTACommand: "
533 "res 0x%x ret_orig 0x%x\n", (unsigned int)res,
534 (unsigned int)ret_orig);
535 res = TEE_ERROR_GENERIC;
536 } else
537 res = TEE_SUCCESS;
538
539 TEE_CloseTASession(sess);
540 return res;
541
542}
543
544TEE_Result ta_entry_client(uint32_t param_types, TEE_Param params[4])
545{
546 static const TEE_UUID crypt_uuid = TA_CRYPT_UUID;
547 TEE_Result res;
548 uint32_t l_pts;
549 TEE_Param l_params[4] = { { {0} } };
550 TEE_TASessionHandle sess;
551 uint32_t ret_orig;
552 static const uint8_t sha256_in[] = { 'a', 'b', 'c' };
553 static const uint8_t sha256_out[] = {
554 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
555 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
556 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
557 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
558 };
559 uint8_t out[32] = { 0 };
560 void *in = NULL;
561
562 (void)param_types;
563 (void)params;
564
565 printf("ta_entry_client: enter\n");
566
567 in = TEE_Malloc(sizeof(sha256_in), 0);
568 if (in == NULL)
569 return TEE_ERROR_OUT_OF_MEMORY;
570 TEE_MemMove(in, sha256_in, sizeof(sha256_in));
571
572 res = TEE_OpenTASession(&crypt_uuid, 0, 0, NULL, &sess, &ret_orig);
573 if (res != TEE_SUCCESS) {
574 EMSG("ta_entry_client: TEE_OpenTASession failed\n");
575 goto cleanup_return;
576 }
577
578 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
579 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0);
580 l_params[0].memref.buffer = in;
581 l_params[0].memref.size = sizeof(sha256_in);
582 l_params[1].memref.buffer = out;
583 l_params[1].memref.size = sizeof(out);
584
585 res = TEE_InvokeTACommand(sess, 0, TA_CRYPT_CMD_SHA256, l_pts, l_params,
586 &ret_orig);
587 if (res != TEE_SUCCESS) {
588 EMSG("ta_entry_client: TEE_InvokeTACommand failed\n");
589 goto cleanup_return;
590 }
591
592 if (TEE_MemCompare(sha256_out, out, sizeof(sha256_out)) != 0) {
593 EMSG("ta_entry_client: out parameter failed\n");
594 res = TEE_ERROR_GENERIC;
595 goto cleanup_return;
596 }
597
598cleanup_return:
599 TEE_Free(in);
600 TEE_CloseTASession(sess);
601 return res;
602}
603
604TEE_Result ta_entry_private_params(uint32_t param_types, TEE_Param params[4])
605{
606 TEE_Result res;
607
608 if (param_types !=
609 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
610 return TEE_ERROR_GENERIC;
611 res =
612 TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
613 TEE_MEMORY_ACCESS_ANY_OWNER,
614 params[0].memref.buffer,
615 params[0].memref.size);
616 if (res != TEE_SUCCESS)
617 return res;
618
619 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
620 params[0].memref.buffer,
621 params[0].memref.size);
622
623 return res;
624}
625
626TEE_Result ta_entry_wait(uint32_t param_types, TEE_Param params[4])
627{
628 TEE_Result res = TEE_SUCCESS;
629 (void)param_types;
630
631 printf("ta_entry_wait: waiting %d\n", (unsigned int)params[0].value.a);
632 /* Wait */
633 res = TEE_Wait(params[0].value.a);
634
635 return res;
636}
637
638TEE_Result ta_entry_bad_mem_access(uint32_t param_types, TEE_Param params[4])
639{
640 long stack;
641 long stack_addr = (long)&stack;
642
643 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0))
644 return TEE_ERROR_GENERIC;
645
646 switch (params[0].value.a) {
647 case 1:
648 *((uint32_t *) 0) = 0;
649 break;
650 case 2:
651 *((uint32_t *)(stack_addr + 0x40000000)) = 0;
652 break;
653 case 3:
654 ((void (*)(void))0) ();
655 break;
656 case 4:
657 ((void (*)(void))(stack_addr + 0x40000000)) ();
658 break;
659 case 5:
660 {
661 static const uint32_t my_undef = 0xffffffff;
662 ((void (*)(void))(uintptr_t) &my_undef) ();
663 }
664 break;
665 default:
666 break;
667 }
668
669 return TEE_SUCCESS;
670}