blob: 871c3c76eb4256cc4cc5071a52823feff616fe51 [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>
Jens Wiklander9f682c62016-03-27 20:23:06 +020028#include <setjmp.h>
Pascal Brandc639ac82015-07-02 08:53:34 +020029
30#include <compiler.h>
31#include <ta_crypt.h>
32#include <ta_os_test.h>
33#include <tee_internal_api_extensions.h>
34
35#include "os_test.h"
36#include "testframework.h"
Jens Wiklander246184a2015-12-11 08:28:59 +010037#include "test_float_subj.h"
Pascal Brandc639ac82015-07-02 08:53:34 +020038
39enum p_type {
40 P_TYPE_BOOL,
41 P_TYPE_INT,
42 P_TYPE_UUID,
43 P_TYPE_IDENTITY,
44 P_TYPE_STRING,
45 P_TYPE_BINARY_BLOCK,
46};
47
48struct p_attr {
49 const char *str;
50 enum p_type type;
51 bool retrieved;
52};
53
Pascal Brand624b6a32016-02-16 12:51:34 +010054static TEE_Result check_returned_prop(
Pascal Brandaf77fdd2016-03-08 13:59:01 +010055 int line __maybe_unused, char *prop_name __maybe_unused,
Pascal Brand624b6a32016-02-16 12:51:34 +010056 TEE_Result return_res, TEE_Result expected_res,
57 uint32_t return_len, uint32_t expected_len)
58{
59 if (return_res != expected_res) {
60 EMSG("From line %d (property name=%s): return_res=0x%x vs expected_res=0x%x",
61 line, (prop_name ? prop_name : "unknown"),
62 (unsigned int)return_res, (unsigned int)expected_res);
63 return TEE_ERROR_GENERIC;
64 }
65 if (return_len != expected_len) {
Pascal Brand07bb09f2016-02-19 16:04:10 +010066 EMSG("From line %d (property name=%s): return_len=%u vs expected_res=%u",
67 line, (prop_name ? prop_name : "unknown"),
68 return_len, expected_len);
Pascal Brand624b6a32016-02-16 12:51:34 +010069 return TEE_ERROR_GENERIC;
70 }
71 return TEE_SUCCESS;
72}
73
Pascal Brandc639ac82015-07-02 08:53:34 +020074static TEE_Result print_properties(TEE_PropSetHandle h,
75 TEE_PropSetHandle prop_set,
76 struct p_attr *p_attrs, size_t num_p_attrs)
77{
78TEE_Result res;
79size_t n;
80
81TEE_StartPropertyEnumerator(h, prop_set);
82
83while (true) {
Pascal Brand624b6a32016-02-16 12:51:34 +010084 char nbuf[256];
85 char nbuf_small[256];
86 char vbuf[256];
87 char vbuf2[256];
Jens Wiklanderc5231592015-11-11 09:27:27 +010088 uint32_t nblen = sizeof(nbuf);
Pascal Brand624b6a32016-02-16 12:51:34 +010089 uint32_t nblen_small;
Jens Wiklanderc5231592015-11-11 09:27:27 +010090 uint32_t vblen = sizeof(vbuf);
91 uint32_t vblen2 = sizeof(vbuf2);
Pascal Brandc639ac82015-07-02 08:53:34 +020092
93 res = TEE_GetPropertyName(h, nbuf, &nblen);
94 if (res != TEE_SUCCESS) {
95 EMSG("TEE_GetPropertyName returned 0x%x\n",
96 (unsigned int)res);
97 return res;
98 }
Pascal Brand624b6a32016-02-16 12:51:34 +010099 if (nblen != strlen(nbuf) + 1) {
Pascal Brand5b68cd62016-02-22 10:31:01 +0100100 EMSG("Name has wrong size: %u vs %zu", nblen, strlen(nbuf) + 1);
Pascal Brand624b6a32016-02-16 12:51:34 +0100101 return TEE_ERROR_GENERIC;
102 }
Pascal Brandc639ac82015-07-02 08:53:34 +0200103
Pascal Brand624b6a32016-02-16 12:51:34 +0100104
105 /* Get the property name with a very small buffer */
106 nblen_small = 2;
107 res = TEE_GetPropertyName(h, nbuf_small, &nblen_small);
108 res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER,
109 nblen_small, nblen);
110 if (res != TEE_SUCCESS)
111 return res;
112
113 /* Get the property name with almost the correct buffer */
114 nblen_small = nblen - 1;
115 res = TEE_GetPropertyName(h, nbuf_small, &nblen_small);
116 res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER,
117 nblen_small, nblen);
118 if (res != TEE_SUCCESS)
119 return res;
120
121 /* Get the property name with the exact buffer length */
122 nblen_small = nblen;
123 res = TEE_GetPropertyName(h, nbuf_small, &nblen_small);
124 res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS,
125 nblen_small, nblen);
126 if (res != TEE_SUCCESS)
127 return res;
128
129 /* Get the property value */
Pascal Brandc639ac82015-07-02 08:53:34 +0200130 res = TEE_GetPropertyAsString(h, NULL, vbuf, &vblen);
Pascal Brand624b6a32016-02-16 12:51:34 +0100131 res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS,
132 vblen, strlen(vbuf) + 1);
133 if (res != TEE_SUCCESS)
Pascal Brandc639ac82015-07-02 08:53:34 +0200134 return res;
Pascal Brand624b6a32016-02-16 12:51:34 +0100135
Pascal Brandc639ac82015-07-02 08:53:34 +0200136 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
Pascal Brand624b6a32016-02-16 12:51:34 +0100137 res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS,
138 vblen2, strlen(vbuf2) + 1);
139 if (res != TEE_SUCCESS)
Pascal Brandc639ac82015-07-02 08:53:34 +0200140 return res;
Pascal Brand624b6a32016-02-16 12:51:34 +0100141
Pascal Brandc639ac82015-07-02 08:53:34 +0200142 if (my_strcmp(vbuf, vbuf2) != 0) {
143 EMSG("String of \"%s\" differs\n", nbuf);
144 return TEE_ERROR_GENERIC;
145 }
146
Pascal Brand624b6a32016-02-16 12:51:34 +0100147 /* Get the property with a very small buffer */
148 vblen2 = 1;
149 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
150 res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER,
151 vblen2, vblen);
152 if (res != TEE_SUCCESS)
153 return res;
154
155 /* Get the property with almost the correct buffer */
156 vblen2 = vblen - 1;
157 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
158 res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER,
159 vblen2, vblen);
160 if (res != TEE_SUCCESS)
161 return res;
162
163 /* Get the property name with the exact buffer length */
164 vblen2 = vblen;
165 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
166 res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS, vblen2, vblen);
167 if (res != TEE_SUCCESS)
168 return res;
169
170 /* check specific myprop.hello property, which is larger than 80 */
171 if (!strcmp("myprop.hello", nbuf) &&
172 vblen2 != 1 + strlen("hello property, larger than 80 characters, so that it checks that it is not truncated by anything in the source code which may be wrong")) {
173 EMSG("TEE_GetPropertyAsString(\"%s\") is truncated - returned \"%s\"\n",
174 nbuf, vbuf);
175 return TEE_ERROR_GENERIC;
176 }
177
Pascal Brandc639ac82015-07-02 08:53:34 +0200178 DMSG("Found \"%s\" value \"%s\"\n", nbuf, vbuf);
179
180 for (n = 0; n < num_p_attrs; n++) {
181 if (my_strcmp(nbuf, p_attrs[n].str) != 0)
182 continue;
183
184 if (p_attrs[n].retrieved) {
185 EMSG("Value \"%s\" already retrieved\n",
186 p_attrs[n].str);
187 return TEE_ERROR_GENERIC;
188 }
189 p_attrs[n].retrieved = true;
190
191 switch (p_attrs[n].type) {
192 case P_TYPE_BOOL:
193 {
194 bool v;
195
196 res =
197 TEE_GetPropertyAsBool(h, NULL, &v);
198 if (res != TEE_SUCCESS) {
199 EMSG(
200 "TEE_GetPropertyAsBool(\"%s\") returned 0x%x\n",
201 nbuf, (unsigned int)res);
202 return res;
203 }
204 }
205 break;
206
207 case P_TYPE_INT:
208 {
209 uint32_t v;
210
211 res = TEE_GetPropertyAsU32(h, NULL, &v);
212 if (res != TEE_SUCCESS) {
213 EMSG(
214 "TEE_GetPropertyAsU32(\"%s\") returned 0x%x\n",
215 nbuf, (unsigned int)res);
216 return res;
217 }
218 }
219 break;
220
221 case P_TYPE_UUID:
222 {
223 TEE_UUID v;
224
225 res =
226 TEE_GetPropertyAsUUID(h, NULL, &v);
227 if (res != TEE_SUCCESS) {
228 EMSG(
229 "TEE_GetPropertyAsUUID(\"%s\") returned 0x%x\n",
230 nbuf, (unsigned int)res);
231 return res;
232 }
233 }
234 break;
235
236 case P_TYPE_IDENTITY:
237 {
238 TEE_Identity v;
239
240 res =
241 TEE_GetPropertyAsIdentity(h, NULL,
242 &v);
243 if (res != TEE_SUCCESS) {
244 EMSG(
245 "TEE_GetPropertyAsIdentity(\"%s\") returned 0x%x\n",
246 nbuf, (unsigned int)res);
247 return res;
248 }
249 }
250 break;
251
252 case P_TYPE_STRING:
253 /* Already read as string */
254 break;
255
256 case P_TYPE_BINARY_BLOCK:
257 {
258 char bbuf[80];
Jens Wiklanderc5231592015-11-11 09:27:27 +0100259 uint32_t bblen = sizeof(bbuf);
Pascal Brandc639ac82015-07-02 08:53:34 +0200260
261 res =
262 TEE_GetPropertyAsBinaryBlock(h,
263 NULL,
264 bbuf,
265 &bblen);
266 if (res != TEE_SUCCESS) {
267 EMSG(
268 "TEE_GetPropertyAsBinaryBlock(\"%s\") returned 0x%x\n",
269 nbuf, (unsigned int)res);
270 return res;
271 }
272 if (my_strcmp
273 ("myprop.binaryblock", nbuf) == 0) {
274 const char exp_bin_value[] =
275 "Hello world!";
276
277 if (bblen !=
278 my_strlen(exp_bin_value)
279 ||
280 TEE_MemCompare
281 (exp_bin_value, bbuf,
282 bblen) != 0) {
283 EMSG(
284 "Binary buffer of \"%s\" differs from \"%s\"\n",
285 nbuf, exp_bin_value);
286 EMSG(
287 "Got \"%s\"\n",
288 bbuf);
289 return
290 TEE_ERROR_GENERIC;
291 }
292 }
293
294 }
295 break;
296
297 default:
298 EMSG("Unknown type (%d) for \"%s\"\n",
299 p_attrs[n].type, p_attrs[n].str);
300 return TEE_ERROR_GENERIC;
301 }
302 }
303
304 res = TEE_GetNextProperty(h);
305 if (res != TEE_SUCCESS) {
306 if (res == TEE_ERROR_ITEM_NOT_FOUND)
307 return TEE_SUCCESS;
308 return res;
309 }
310}
311}
312
313static TEE_Result test_malloc(void)
314{
315 void *p = TEE_Malloc(4, 0);
316
317 if (p == NULL) {
318 EMSG("TEE_Malloc failed\n");
319 return TEE_ERROR_OUT_OF_MEMORY;
320 }
321 TEE_Free(p);
322 TEE_Free(NULL);
323
324 return TEE_SUCCESS;
325}
326
327static TEE_Result test_properties(void)
328{
329 TEE_Result res = TEE_ERROR_GENERIC;
330 TEE_PropSetHandle h;
331 struct p_attr p_attrs[] = {
332 {"gpd.ta.appID", P_TYPE_UUID},
333 {"gpd.ta.singleInstance", P_TYPE_BOOL},
334 {"gpd.ta.multiSession", P_TYPE_BOOL},
335 {"gpd.ta.instanceKeepAlive", P_TYPE_BOOL},
336 {"gpd.ta.dataSize", P_TYPE_INT},
337 {"gpd.ta.stackSize", P_TYPE_INT},
338 {"gpd.ta.version", P_TYPE_STRING},
339 {"gpd.ta.description", P_TYPE_STRING},
340 {"gpd.client.identity", P_TYPE_IDENTITY},
341 {"gpd.tee.apiversion", P_TYPE_STRING},
342 {"gpd.tee.description", P_TYPE_STRING},
343 {"gpd.tee.deviceID", P_TYPE_UUID},
344 {"gpd.tee.systemTime.protectionLevel", P_TYPE_INT},
345 {"gpd.tee.TAPersistentTime.protectionLevel", P_TYPE_INT},
346 {"gpd.tee.arith.maxBigIntSize", P_TYPE_INT},
347 {"gpd.tee.cryptography.ecc", P_TYPE_BOOL},
348 {"gpd.tee.trustedStorage.antiRollback.protectionLevel", P_TYPE_INT},
349 {"gpd.tee.trustedos.implementation.version", P_TYPE_STRING},
350 {"gpd.tee.trustedos.implementation.binaryversion", P_TYPE_INT},
351 {"gpd.tee.trustedos.manufacturer", P_TYPE_STRING},
352 {"gpd.tee.firmware.implementation.version", P_TYPE_STRING},
353 {"gpd.tee.firmware.implementation.binaryversion", P_TYPE_INT},
354 {"gpd.tee.firmware.manufacturer", P_TYPE_STRING},
355 {"myprop.true", P_TYPE_BOOL},
356 {"myprop.42", P_TYPE_INT},
357 {"myprop.123", P_TYPE_UUID},
358 {"myprop.1234", P_TYPE_IDENTITY},
359 {"myprop.hello", P_TYPE_STRING},
360 {"myprop.binaryblock", P_TYPE_BINARY_BLOCK},
361 };
362 const size_t num_p_attrs = sizeof(p_attrs) / sizeof(p_attrs[0]);
363 size_t n;
364
365 res = TEE_AllocatePropertyEnumerator(&h);
366 if (res != TEE_SUCCESS) {
367 EMSG("TEE_AllocatePropertyEnumerator: returned 0x%x\n",
368 (unsigned int)res);
369 return TEE_ERROR_GENERIC;
370 }
371
372 printf("Getting properties for current TA\n");
373 res = print_properties(h, TEE_PROPSET_CURRENT_TA, p_attrs, num_p_attrs);
374 if (res != TEE_SUCCESS)
375 goto cleanup_return;
376
377 printf("Getting properties for current client\n");
378 res = print_properties(h, TEE_PROPSET_CURRENT_CLIENT, p_attrs,
379 num_p_attrs);
380 if (res != TEE_SUCCESS)
381 goto cleanup_return;
382
383 printf("Getting properties for implementation\n");
384 res = print_properties(h, TEE_PROPSET_TEE_IMPLEMENTATION, p_attrs,
385 num_p_attrs);
386 if (res != TEE_SUCCESS)
387 goto cleanup_return;
388
389 for (n = 0; n < num_p_attrs; n++) {
390 if (!p_attrs[n].retrieved) {
391 EMSG("\"%s\" not retrieved\n", p_attrs[n].str);
392 res = TEE_ERROR_GENERIC;
393 goto cleanup_return;
394 }
395 }
396
397cleanup_return:
398 TEE_FreePropertyEnumerator(h);
399 return res;
400}
401
402static TEE_Result test_mem_access_right(uint32_t param_types,
403 TEE_Param params[4])
404{
405 static const TEE_UUID test_uuid = TA_OS_TEST_UUID;
406 TEE_Result res;
407 uint32_t ret_orig;
408 uint32_t l_pts;
409 TEE_Param l_params[4] = { { {0} } };
410 uint8_t buf[32];
411 TEE_TASessionHandle sess = TEE_HANDLE_NULL;
Etienne Carriere281065d2016-10-28 15:41:33 +0200412 TEE_UUID *uuid;
Pascal Brandc639ac82015-07-02 08:53:34 +0200413
414 if (param_types !=
415 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
416 return TEE_ERROR_GENERIC;
Etienne Carriere281065d2016-10-28 15:41:33 +0200417
418 /* test access rights on memref parameter */
419 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
420 TEE_MEMORY_ACCESS_ANY_OWNER,
421 params[0].memref.buffer,
422 params[0].memref.size);
Pascal Brandc639ac82015-07-02 08:53:34 +0200423 if (res != TEE_SUCCESS)
424 return res;
Etienne Carriere281065d2016-10-28 15:41:33 +0200425
Pascal Brandc639ac82015-07-02 08:53:34 +0200426 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
427 params[0].memref.buffer,
428 params[0].memref.size);
429 if (res != TEE_ERROR_ACCESS_DENIED)
430 return TEE_ERROR_GENERIC;
431
Etienne Carriere281065d2016-10-28 15:41:33 +0200432 /* test access rights on private read-only and read-write memory */
433 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
434 (void *)&test_uuid, sizeof(test_uuid));
435 if (res != TEE_SUCCESS)
436 return res;
437
438 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_WRITE,
439 (void *)&test_uuid, sizeof(test_uuid));
440 if (res == TEE_SUCCESS)
441 return TEE_ERROR_GENERIC;
442
443 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
444 TEE_MEMORY_ACCESS_WRITE,
445 &ret_orig, sizeof(ret_orig));
446 if (res != TEE_SUCCESS)
447 return res;
448
449 uuid = TEE_Malloc(sizeof(*uuid), 0);
450 if (!uuid)
451 return TEE_ERROR_OUT_OF_MEMORY;
452
453 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
454 TEE_MEMORY_ACCESS_WRITE,
455 uuid, sizeof(*uuid));
456 TEE_Free(uuid);
457 if (res != TEE_SUCCESS)
458 return res;
459
460 /* test access rights on invalid memory (at least lower 256kB) */
461 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
462 NULL, 1);
463 if (res == TEE_SUCCESS)
464 return TEE_ERROR_GENERIC;
465
466 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
467 (void*)(256 * 1024), 1);
468 if (res == TEE_SUCCESS)
469 return TEE_ERROR_GENERIC;
470
Pascal Brandc639ac82015-07-02 08:53:34 +0200471 res = TEE_OpenTASession(&test_uuid, 0, 0, NULL, &sess, &ret_orig);
472 if (res != TEE_SUCCESS) {
473 EMSG("test_mem_access_right: TEE_OpenTASession failed\n");
474 goto cleanup_return;
475 }
476
477 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0);
478 l_params[0].memref.buffer = buf;
479 l_params[0].memref.size = sizeof(buf);
Etienne Carriere281065d2016-10-28 15:41:33 +0200480 res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_PARAMS_ACCESS,
Pascal Brandc639ac82015-07-02 08:53:34 +0200481 l_pts, l_params, &ret_orig);
482 if (res != TEE_SUCCESS) {
483 EMSG("test_mem_access_right: TEE_InvokeTACommand failed\n");
484 goto cleanup_return;
485 }
486
487cleanup_return:
488 TEE_CloseTASession(sess);
489 return res;
490}
491
492static TEE_Result test_time(void)
493{
494 TEE_Result res;
495 TEE_Time t;
496 TEE_Time sys_t;
497
498 static const TEE_Time null_time = { 0, 0 };
499 static const TEE_Time wrap_time = { UINT32_MAX, 999 };
500
501 TEE_GetSystemTime(&sys_t);
502 printf("system time %u.%03u\n", (unsigned int)sys_t.seconds,
503 (unsigned int)sys_t.millis);
504
505 TEE_GetREETime(&t);
506 printf("REE time %u.%03u\n", (unsigned int)t.seconds,
507 (unsigned int)t.millis);
508
509 res = TEE_GetTAPersistentTime(&t);
510 switch (res) {
511 case TEE_SUCCESS:
512 printf("Stored TA time %u.%03u\n", (unsigned int)t.seconds,
513 (unsigned int)t.millis);
514 break;
515 case TEE_ERROR_OVERFLOW:
516 EMSG("Stored TA time overflowed %u.%03u\n",
517 (unsigned int)t.seconds, (unsigned int)t.millis);
518 break;
519 case TEE_ERROR_TIME_NOT_SET:
520 EMSG("TA time not stored\n");
521 break;
522 case TEE_ERROR_TIME_NEEDS_RESET:
523 EMSG("TA time needs reset\n");
524 break;
525 default:
526 return res;
527 }
528
529 res = TEE_SetTAPersistentTime(&null_time);
530 if (res != TEE_SUCCESS) {
531 EMSG("TEE_SetTAPersistentTime: failed\n");
532 return res;
533 }
534
535 res = TEE_GetTAPersistentTime(&t);
536 if (res != TEE_SUCCESS) {
537 EMSG("TEE_GetTAPersistentTime null: failed\n");
538 return res;
539 }
540 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
541 (unsigned int)t.millis);
542 /*
543 * The time between TEE_SetTAPersistentTime() and
544 * TEE_GetTAPersistentTime() should be much less than 1 second, in fact
545 * it's not even a millisecond.
546 */
547 if (t.seconds > 1 || t.millis >= 1000) {
548 EMSG("Unexpected stored TA time %u.%03u\n",
549 (unsigned int)t.seconds, (unsigned int)t.millis);
550 return TEE_ERROR_BAD_STATE;
551 }
552
553 res = TEE_SetTAPersistentTime(&wrap_time);
554 if (res != TEE_SUCCESS) {
555 EMSG("TEE_SetTAPersistentTime wrap: failed\n");
556 return res;
557 }
558
559 res = TEE_Wait(1000);
560 if (res != TEE_SUCCESS)
561 EMSG("TEE_Wait wrap: failed\n");
562
563 res = TEE_GetTAPersistentTime(&t);
564 if (res != TEE_ERROR_OVERFLOW) {
565 EMSG("TEE_GetTAPersistentTime: failed\n");
566 return TEE_ERROR_BAD_STATE;
567 }
568 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
569 (unsigned int)t.millis);
570
571 if (t.seconds > sys_t.seconds) {
572 EMSG("Unexpected wrapped time %u.%03u (sys_t %u.%03u)\n",
573 (unsigned int)t.seconds, (unsigned int)t.millis,
574 (unsigned int)sys_t.seconds, (unsigned int)sys_t.millis);
575 return TEE_ERROR_BAD_STATE;
576 }
577
578 return TEE_SUCCESS;
579}
580
Jens Wiklander246184a2015-12-11 08:28:59 +0100581#ifdef CFG_TA_FLOAT_SUPPORT
582static bool my_dcmpeq(double v1, double v2, double prec)
583{
584 return v1 > (v2 - prec) && v1 < (v2 + prec);
585}
586
587static bool my_fcmpeq(float v1, float v2, float prec)
588{
589 return v1 > (v2 - prec) && v1 < (v2 + prec);
590}
591
592
593static TEE_Result test_float(void)
594{
595#define VAL1 2.6
596#define VAL1_INT 2
597#define VAL2 5.3
598#define DPREC 0.000000000000001
599#define FPREC 0.000001
600#define EXPECT(expr) do { \
601 if (!(expr)) { \
602 EMSG("Expression %s failed", #expr); \
603 return TEE_ERROR_GENERIC; \
604 } \
605 } while (0)
606
607 IMSG("Testing floating point operations");
608
609 EXPECT(my_dcmpeq(test_float_dadd(VAL1, VAL2), VAL1 + VAL2, DPREC));
610 EXPECT(my_dcmpeq(test_float_ddiv(VAL1, VAL2), VAL1 / VAL2, DPREC));
611 EXPECT(my_dcmpeq(test_float_dmul(VAL1, VAL2), VAL1 * VAL2, DPREC));
612 EXPECT(my_dcmpeq(test_float_drsub(VAL1, VAL2), VAL2 - VAL1, DPREC));
613 EXPECT(my_dcmpeq(test_float_dsub(VAL1, VAL2), VAL1 - VAL2, DPREC));
614
615 EXPECT(test_float_dcmpeq(VAL1, VAL1) == 1);
616 EXPECT(test_float_dcmplt(VAL1, VAL2) == 1);
617 EXPECT(test_float_dcmple(VAL1, VAL1) == 1);
618 EXPECT(test_float_dcmpge(VAL1, VAL1) == 1);
619 EXPECT(test_float_dcmpgt(VAL2, VAL1) == 1);
620
621 EXPECT(my_fcmpeq(test_float_fadd(VAL1, VAL2), VAL1 + VAL2, FPREC));
622 EXPECT(my_fcmpeq(test_float_fdiv(VAL1, VAL2), VAL1 / VAL2, FPREC));
623 EXPECT(my_fcmpeq(test_float_fmul(VAL1, VAL2), VAL1 * VAL2, FPREC));
624 EXPECT(my_fcmpeq(test_float_frsub(VAL1, VAL2), VAL2 - VAL1, FPREC));
625 EXPECT(my_fcmpeq(test_float_fsub(VAL1, VAL2), VAL1 - VAL2, FPREC));
626
627 EXPECT(test_float_fcmpeq(VAL1, VAL1) == 1);
628 EXPECT(test_float_fcmplt(VAL1, VAL2) == 1);
629 EXPECT(test_float_fcmple(VAL1, VAL1) == 1);
630 EXPECT(test_float_fcmpge(VAL1, VAL1) == 1);
631 EXPECT(test_float_fcmpgt(VAL2, VAL1) == 1);
632
633 EXPECT(test_float_d2iz(VAL1) == VAL1_INT);
634 EXPECT(test_float_d2uiz(VAL1) == VAL1_INT);
635 EXPECT(test_float_d2lz(VAL1) == VAL1_INT);
636 EXPECT(test_float_d2ulz(VAL1) == VAL1_INT);
637
638 EXPECT(test_float_f2iz(VAL1) == VAL1_INT);
639 EXPECT(test_float_f2uiz(VAL1) == VAL1_INT);
640 EXPECT(test_float_f2lz(VAL1) == VAL1_INT);
641 EXPECT(test_float_f2ulz(VAL1) == VAL1_INT);
642
643 EXPECT(my_fcmpeq(test_float_d2f(VAL1), VAL1, FPREC));
644 EXPECT(my_dcmpeq(test_float_f2d(VAL1), VAL1, FPREC));
645
646 EXPECT(my_dcmpeq(test_float_i2d(VAL1_INT), VAL1_INT, DPREC));
647 EXPECT(my_dcmpeq(test_float_ui2d(VAL1_INT), VAL1_INT, DPREC));
648 EXPECT(my_dcmpeq(test_float_l2d(VAL1_INT), VAL1_INT, DPREC));
649 EXPECT(my_dcmpeq(test_float_ul2d(VAL1_INT), VAL1_INT, DPREC));
650
651 EXPECT(my_fcmpeq(test_float_i2f(VAL1_INT), VAL1_INT, FPREC));
652 EXPECT(my_fcmpeq(test_float_ui2f(VAL1_INT), VAL1_INT, FPREC));
653 EXPECT(my_fcmpeq(test_float_l2f(VAL1_INT), VAL1_INT, FPREC));
654 EXPECT(my_fcmpeq(test_float_ul2f(VAL1_INT), VAL1_INT, FPREC));
655 return TEE_SUCCESS;
656}
657#else /*CFG_TA_FLOAT_SUPPORT*/
658static TEE_Result test_float(void)
659{
660 IMSG("Floating point disabled");
661 return TEE_SUCCESS;
662}
663#endif /*CFG_TA_FLOAT_SUPPORT*/
664
Jens Wiklander9f682c62016-03-27 20:23:06 +0200665static __noinline void call_longjmp(jmp_buf env)
666{
667 DMSG("Calling longjmp");
668 longjmp(env, 1);
669 EMSG("error: longjmp returned to calling function");
670}
671
672static TEE_Result test_setjmp(void)
673{
674 jmp_buf env;
675
676 if (setjmp(env)) {
677 IMSG("Returned via longjmp");
678 return TEE_SUCCESS;
679 } else {
680 call_longjmp(env);
681 return TEE_ERROR_GENERIC;
682 }
683}
684
Pascal Brandc639ac82015-07-02 08:53:34 +0200685TEE_Result ta_entry_basic(uint32_t param_types, TEE_Param params[4])
686{
687 TEE_Result res = TEE_ERROR_GENERIC;
688
689 printf("ta_entry_basic: enter\n");
690
691 res = test_malloc();
692 if (res != TEE_SUCCESS)
693 return res;
694
695 res = test_properties();
696 if (res != TEE_SUCCESS)
697 return res;
698
699 res = test_mem_access_right(param_types, params);
700 if (res != TEE_SUCCESS)
701 return res;
702
703 res = test_time();
704 if (res != TEE_SUCCESS)
705 return res;
706
Jens Wiklander246184a2015-12-11 08:28:59 +0100707 res = test_float();
708 if (res != TEE_SUCCESS)
709 return res;
710
Jens Wiklander9f682c62016-03-27 20:23:06 +0200711 res = test_setjmp();
712 if (res != TEE_SUCCESS)
713 return res;
714
Pascal Brandc639ac82015-07-02 08:53:34 +0200715 /* mpa lib test bench, panics TA on failure */
716 tb_main();
717
718 return TEE_SUCCESS;
719}
720
721TEE_Result ta_entry_panic(uint32_t param_types, TEE_Param params[4])
722{
723 volatile bool mytrue = true;
724 (void)param_types;
725 (void)params;
726
727 printf("ta_entry_panic: enter\n");
728 /*
729 * Somewhat clumsy way of avoiding compile errors if TEE_Panic() has
730 * the __noreturn attribute.
731 */
732 if (mytrue)
733 TEE_Panic(0xbeef);
734
735 /*
736 * Should not be reached, but if it is the testsuite can detect that
737 * TEE_Panic() returned instead of panicking the TA.
738 */
739 return TEE_SUCCESS;
740}
741
742TEE_Result ta_entry_client_with_timeout(uint32_t param_types,
743 TEE_Param params[4])
744{
745 static const TEE_UUID os_test_uuid = TA_OS_TEST_UUID;
746 TEE_Result res;
747 TEE_TASessionHandle sess;
748 uint32_t ret_orig;
749
750 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
751 TEE_PARAM_TYPE_NONE,
752 TEE_PARAM_TYPE_NONE,
753 TEE_PARAM_TYPE_NONE)) {
754 EMSG("ta_entry_client_with_timeout: bad parameters\n");
755 return TEE_ERROR_BAD_PARAMETERS;
756 }
757
758 res = TEE_OpenTASession(&os_test_uuid, 0, 0, NULL, &sess, &ret_orig);
759 if (res != TEE_SUCCESS) {
760 EMSG(
761 "ta_entry_client_with_timeout: TEE_OpenTASession failed\n");
762 return res;
763 }
764
765 res =
766 TEE_InvokeTACommand(sess, params[0].value.a / 2,
767 TA_OS_TEST_CMD_WAIT, param_types, params,
768 &ret_orig);
769
770 if (ret_orig != TEE_ORIGIN_TRUSTED_APP || res != TEE_ERROR_CANCEL) {
771 EMSG("ta_entry_client_with_timeout: TEE_InvokeTACommand: "
772 "res 0x%x ret_orig 0x%x\n", (unsigned int)res,
773 (unsigned int)ret_orig);
774 res = TEE_ERROR_GENERIC;
775 } else
776 res = TEE_SUCCESS;
777
778 TEE_CloseTASession(sess);
779 return res;
780
781}
782
783TEE_Result ta_entry_client(uint32_t param_types, TEE_Param params[4])
784{
785 static const TEE_UUID crypt_uuid = TA_CRYPT_UUID;
786 TEE_Result res;
787 uint32_t l_pts;
788 TEE_Param l_params[4] = { { {0} } };
789 TEE_TASessionHandle sess;
790 uint32_t ret_orig;
791 static const uint8_t sha256_in[] = { 'a', 'b', 'c' };
792 static const uint8_t sha256_out[] = {
793 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
794 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
795 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
796 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
797 };
798 uint8_t out[32] = { 0 };
799 void *in = NULL;
800
801 (void)param_types;
802 (void)params;
803
804 printf("ta_entry_client: enter\n");
805
806 in = TEE_Malloc(sizeof(sha256_in), 0);
807 if (in == NULL)
808 return TEE_ERROR_OUT_OF_MEMORY;
809 TEE_MemMove(in, sha256_in, sizeof(sha256_in));
810
811 res = TEE_OpenTASession(&crypt_uuid, 0, 0, NULL, &sess, &ret_orig);
812 if (res != TEE_SUCCESS) {
813 EMSG("ta_entry_client: TEE_OpenTASession failed\n");
814 goto cleanup_return;
815 }
816
817 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
818 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0);
819 l_params[0].memref.buffer = in;
820 l_params[0].memref.size = sizeof(sha256_in);
821 l_params[1].memref.buffer = out;
822 l_params[1].memref.size = sizeof(out);
823
824 res = TEE_InvokeTACommand(sess, 0, TA_CRYPT_CMD_SHA256, l_pts, l_params,
825 &ret_orig);
826 if (res != TEE_SUCCESS) {
827 EMSG("ta_entry_client: TEE_InvokeTACommand failed\n");
828 goto cleanup_return;
829 }
830
831 if (TEE_MemCompare(sha256_out, out, sizeof(sha256_out)) != 0) {
832 EMSG("ta_entry_client: out parameter failed\n");
833 res = TEE_ERROR_GENERIC;
834 goto cleanup_return;
835 }
836
837cleanup_return:
838 TEE_Free(in);
839 TEE_CloseTASession(sess);
840 return res;
841}
842
Etienne Carriere281065d2016-10-28 15:41:33 +0200843TEE_Result ta_entry_params_access_rights(uint32_t param_types, TEE_Param params[4])
Pascal Brandc639ac82015-07-02 08:53:34 +0200844{
845 TEE_Result res;
846
847 if (param_types !=
848 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
849 return TEE_ERROR_GENERIC;
Etienne Carriere281065d2016-10-28 15:41:33 +0200850
851 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
852 TEE_MEMORY_ACCESS_ANY_OWNER,
853 params[0].memref.buffer,
854 params[0].memref.size);
Pascal Brandc639ac82015-07-02 08:53:34 +0200855 if (res != TEE_SUCCESS)
856 return res;
857
858 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
859 params[0].memref.buffer,
860 params[0].memref.size);
Etienne Carriere281065d2016-10-28 15:41:33 +0200861 if (res != TEE_ERROR_ACCESS_DENIED)
862 return TEE_ERROR_GENERIC;
Pascal Brandc639ac82015-07-02 08:53:34 +0200863
Etienne Carriere281065d2016-10-28 15:41:33 +0200864 return TEE_SUCCESS;
Pascal Brandc639ac82015-07-02 08:53:34 +0200865}
866
867TEE_Result ta_entry_wait(uint32_t param_types, TEE_Param params[4])
868{
869 TEE_Result res = TEE_SUCCESS;
870 (void)param_types;
871
872 printf("ta_entry_wait: waiting %d\n", (unsigned int)params[0].value.a);
873 /* Wait */
874 res = TEE_Wait(params[0].value.a);
875
876 return res;
877}
878
Jens Wiklander1425f952016-07-21 09:02:30 +0200879static void undef_instr(void)
880{
881#if defined(ARM64)
882 __asm__(".word 0x0");
883#elif defined(ARM32)
884 __asm__(".word 0xe7ffffff");
885#else
886#error "Unsupported architecture"
887#endif
888}
889
Pascal Brandc639ac82015-07-02 08:53:34 +0200890TEE_Result ta_entry_bad_mem_access(uint32_t param_types, TEE_Param params[4])
891{
892 long stack;
893 long stack_addr = (long)&stack;
894
895 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0))
896 return TEE_ERROR_GENERIC;
897
898 switch (params[0].value.a) {
899 case 1:
900 *((uint32_t *) 0) = 0;
901 break;
902 case 2:
903 *((uint32_t *)(stack_addr + 0x40000000)) = 0;
904 break;
905 case 3:
906 ((void (*)(void))0) ();
907 break;
908 case 4:
909 ((void (*)(void))(stack_addr + 0x40000000)) ();
910 break;
911 case 5:
Jens Wiklander1425f952016-07-21 09:02:30 +0200912 undef_instr();
Pascal Brandc639ac82015-07-02 08:53:34 +0200913 break;
914 default:
915 break;
916 }
917
918 return TEE_SUCCESS;
919}
Jerome Forissiere916b102017-06-07 17:55:52 +0200920
921static void incr_values(size_t bufsize, uint8_t *a, uint8_t *b, uint8_t *c)
922{
923 size_t i;
924
925 for (i = 0; i < bufsize; i++) {
926 a[i]++; b[i]++; c[i]++;
927 }
928}
929
930TEE_Result ta_entry_ta2ta_memref(uint32_t param_types, TEE_Param params[4])
931{
932 static const TEE_UUID test_uuid = TA_OS_TEST_UUID;
933 TEE_TASessionHandle sess = TEE_HANDLE_NULL;
934 TEE_Param l_params[4] = { { {0} } };
935 size_t bufsize = 2 * 1024;
936 uint8_t in[bufsize];
937 uint8_t inout[bufsize];
938 uint8_t out[bufsize];
939 TEE_Result res;
940 uint32_t ret_orig;
941 uint32_t l_pts;
942 size_t i;
943 (void)params;
944
945 if (param_types != TEE_PARAM_TYPES(0, 0, 0, 0))
946 return TEE_ERROR_GENERIC;
947
948 res = TEE_OpenTASession(&test_uuid, 0, 0, NULL, &sess, &ret_orig);
949 if (res != TEE_SUCCESS) {
950 EMSG("TEE_OpenTASession failed");
951 goto cleanup_return;
952 }
953
954 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
955 TEE_PARAM_TYPE_MEMREF_INOUT,
956 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0);
957 l_params[0].memref.buffer = in;
958 l_params[0].memref.size = bufsize;
959 l_params[1].memref.buffer = inout;
960 l_params[1].memref.size = bufsize;
961 l_params[2].memref.buffer = out;
962 l_params[2].memref.size = bufsize;
963
964 /* Initialize buffers */
965 for (i = 0; i < bufsize; i++) {
966 in[i] = 5;
967 inout[i] = 10;
968 out[i] = 0;
969 }
970
971 /*
972 * TA will compute: out = ++inout + in
973 * Expected values after this step: in: 5, inout: 11, out: 16
974 */
975 res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_TA2TA_MEMREF_MIX,
976 l_pts, l_params, &ret_orig);
977 if (res != TEE_SUCCESS) {
978 EMSG("TEE_InvokeTACommand failed");
979 goto cleanup_return;
980 }
981
982 /*
983 * Increment all values by one.
984 * Expected values after this step: in: 6, inout: 12, out: 17
985 */
986 incr_values(bufsize, in, inout, out);
987
988 /*
989 * TA will compute: out = ++inout + in
990 * Expected values after this step: in: 6, inout: 13, out: 19
991 */
992 res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_TA2TA_MEMREF_MIX,
993 l_pts, l_params, &ret_orig);
994 if (res != TEE_SUCCESS) {
995 EMSG("TEE_InvokeTACommand failed");
996 goto cleanup_return;
997 }
998
999 /* Check the actual values */
1000 for (i = 0; i < bufsize; i++) {
1001 if (in[i] != 6 || inout[i] != 13 || out[i] != 19) {
1002 EMSG("Unexpected value in buffer(s)");
1003 DHEXDUMP(in, bufsize);
1004 DHEXDUMP(inout, bufsize);
1005 DHEXDUMP(out, bufsize);
1006 return TEE_ERROR_GENERIC;
1007 }
1008 }
1009
1010cleanup_return:
1011 TEE_CloseTASession(sess);
1012 return res;
1013}
1014
1015TEE_Result ta_entry_ta2ta_memref_mix(uint32_t param_types, TEE_Param params[4])
1016{
1017 uint8_t *in;
1018 uint8_t *inout;
1019 uint8_t *out;
1020 size_t bufsize;
1021 size_t i;
1022
1023 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1024 TEE_PARAM_TYPE_MEMREF_INOUT,
1025 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0))
1026 return TEE_ERROR_GENERIC;
1027
1028 bufsize = params[0].memref.size;
1029 if (params[1].memref.size != bufsize ||
1030 params[2].memref.size != bufsize)
1031 return TEE_ERROR_GENERIC;
1032
1033 in = params[0].memref.buffer;
1034 inout = params[1].memref.buffer;
1035 out = params[2].memref.buffer;
1036
1037 for (i = 0; i < bufsize; i++)
1038 out[i] = ++inout[i] + in[i];
1039
1040 return TEE_SUCCESS;
1041}