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