blob: a61466bacfd98de95d944bc44eaca39f45c18d14 [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
Jerome Forissier04511d82018-01-30 14:33:49 +0100477 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
478 TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0);
Pascal Brandc639ac82015-07-02 08:53:34 +0200479 l_params[0].memref.buffer = buf;
480 l_params[0].memref.size = sizeof(buf);
Jerome Forissier04511d82018-01-30 14:33:49 +0100481 l_params[1].memref.buffer = NULL;
482 l_params[1].memref.size = 0;
Etienne Carriere281065d2016-10-28 15:41:33 +0200483 res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_PARAMS_ACCESS,
Pascal Brandc639ac82015-07-02 08:53:34 +0200484 l_pts, l_params, &ret_orig);
485 if (res != TEE_SUCCESS) {
486 EMSG("test_mem_access_right: TEE_InvokeTACommand failed\n");
487 goto cleanup_return;
488 }
489
490cleanup_return:
491 TEE_CloseTASession(sess);
492 return res;
493}
494
495static TEE_Result test_time(void)
496{
497 TEE_Result res;
498 TEE_Time t;
499 TEE_Time sys_t;
500
501 static const TEE_Time null_time = { 0, 0 };
502 static const TEE_Time wrap_time = { UINT32_MAX, 999 };
503
504 TEE_GetSystemTime(&sys_t);
505 printf("system time %u.%03u\n", (unsigned int)sys_t.seconds,
506 (unsigned int)sys_t.millis);
507
508 TEE_GetREETime(&t);
509 printf("REE time %u.%03u\n", (unsigned int)t.seconds,
510 (unsigned int)t.millis);
511
512 res = TEE_GetTAPersistentTime(&t);
513 switch (res) {
514 case TEE_SUCCESS:
515 printf("Stored TA time %u.%03u\n", (unsigned int)t.seconds,
516 (unsigned int)t.millis);
517 break;
518 case TEE_ERROR_OVERFLOW:
519 EMSG("Stored TA time overflowed %u.%03u\n",
520 (unsigned int)t.seconds, (unsigned int)t.millis);
521 break;
522 case TEE_ERROR_TIME_NOT_SET:
523 EMSG("TA time not stored\n");
524 break;
525 case TEE_ERROR_TIME_NEEDS_RESET:
526 EMSG("TA time needs reset\n");
527 break;
528 default:
529 return res;
530 }
531
532 res = TEE_SetTAPersistentTime(&null_time);
533 if (res != TEE_SUCCESS) {
534 EMSG("TEE_SetTAPersistentTime: failed\n");
535 return res;
536 }
537
538 res = TEE_GetTAPersistentTime(&t);
539 if (res != TEE_SUCCESS) {
540 EMSG("TEE_GetTAPersistentTime null: failed\n");
541 return res;
542 }
543 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
544 (unsigned int)t.millis);
545 /*
546 * The time between TEE_SetTAPersistentTime() and
547 * TEE_GetTAPersistentTime() should be much less than 1 second, in fact
548 * it's not even a millisecond.
549 */
550 if (t.seconds > 1 || t.millis >= 1000) {
551 EMSG("Unexpected stored TA time %u.%03u\n",
552 (unsigned int)t.seconds, (unsigned int)t.millis);
553 return TEE_ERROR_BAD_STATE;
554 }
555
556 res = TEE_SetTAPersistentTime(&wrap_time);
557 if (res != TEE_SUCCESS) {
558 EMSG("TEE_SetTAPersistentTime wrap: failed\n");
559 return res;
560 }
561
562 res = TEE_Wait(1000);
563 if (res != TEE_SUCCESS)
564 EMSG("TEE_Wait wrap: failed\n");
565
566 res = TEE_GetTAPersistentTime(&t);
567 if (res != TEE_ERROR_OVERFLOW) {
568 EMSG("TEE_GetTAPersistentTime: failed\n");
569 return TEE_ERROR_BAD_STATE;
570 }
571 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
572 (unsigned int)t.millis);
573
574 if (t.seconds > sys_t.seconds) {
575 EMSG("Unexpected wrapped time %u.%03u (sys_t %u.%03u)\n",
576 (unsigned int)t.seconds, (unsigned int)t.millis,
577 (unsigned int)sys_t.seconds, (unsigned int)sys_t.millis);
578 return TEE_ERROR_BAD_STATE;
579 }
580
581 return TEE_SUCCESS;
582}
583
Jens Wiklander246184a2015-12-11 08:28:59 +0100584#ifdef CFG_TA_FLOAT_SUPPORT
585static bool my_dcmpeq(double v1, double v2, double prec)
586{
587 return v1 > (v2 - prec) && v1 < (v2 + prec);
588}
589
590static bool my_fcmpeq(float v1, float v2, float prec)
591{
592 return v1 > (v2 - prec) && v1 < (v2 + prec);
593}
594
595
596static TEE_Result test_float(void)
597{
598#define VAL1 2.6
599#define VAL1_INT 2
600#define VAL2 5.3
601#define DPREC 0.000000000000001
602#define FPREC 0.000001
603#define EXPECT(expr) do { \
604 if (!(expr)) { \
605 EMSG("Expression %s failed", #expr); \
606 return TEE_ERROR_GENERIC; \
607 } \
608 } while (0)
609
610 IMSG("Testing floating point operations");
611
612 EXPECT(my_dcmpeq(test_float_dadd(VAL1, VAL2), VAL1 + VAL2, DPREC));
613 EXPECT(my_dcmpeq(test_float_ddiv(VAL1, VAL2), VAL1 / VAL2, DPREC));
614 EXPECT(my_dcmpeq(test_float_dmul(VAL1, VAL2), VAL1 * VAL2, DPREC));
615 EXPECT(my_dcmpeq(test_float_drsub(VAL1, VAL2), VAL2 - VAL1, DPREC));
616 EXPECT(my_dcmpeq(test_float_dsub(VAL1, VAL2), VAL1 - VAL2, DPREC));
617
618 EXPECT(test_float_dcmpeq(VAL1, VAL1) == 1);
619 EXPECT(test_float_dcmplt(VAL1, VAL2) == 1);
620 EXPECT(test_float_dcmple(VAL1, VAL1) == 1);
621 EXPECT(test_float_dcmpge(VAL1, VAL1) == 1);
622 EXPECT(test_float_dcmpgt(VAL2, VAL1) == 1);
623
624 EXPECT(my_fcmpeq(test_float_fadd(VAL1, VAL2), VAL1 + VAL2, FPREC));
625 EXPECT(my_fcmpeq(test_float_fdiv(VAL1, VAL2), VAL1 / VAL2, FPREC));
626 EXPECT(my_fcmpeq(test_float_fmul(VAL1, VAL2), VAL1 * VAL2, FPREC));
627 EXPECT(my_fcmpeq(test_float_frsub(VAL1, VAL2), VAL2 - VAL1, FPREC));
628 EXPECT(my_fcmpeq(test_float_fsub(VAL1, VAL2), VAL1 - VAL2, FPREC));
629
630 EXPECT(test_float_fcmpeq(VAL1, VAL1) == 1);
631 EXPECT(test_float_fcmplt(VAL1, VAL2) == 1);
632 EXPECT(test_float_fcmple(VAL1, VAL1) == 1);
633 EXPECT(test_float_fcmpge(VAL1, VAL1) == 1);
634 EXPECT(test_float_fcmpgt(VAL2, VAL1) == 1);
635
636 EXPECT(test_float_d2iz(VAL1) == VAL1_INT);
637 EXPECT(test_float_d2uiz(VAL1) == VAL1_INT);
638 EXPECT(test_float_d2lz(VAL1) == VAL1_INT);
639 EXPECT(test_float_d2ulz(VAL1) == VAL1_INT);
640
641 EXPECT(test_float_f2iz(VAL1) == VAL1_INT);
642 EXPECT(test_float_f2uiz(VAL1) == VAL1_INT);
643 EXPECT(test_float_f2lz(VAL1) == VAL1_INT);
644 EXPECT(test_float_f2ulz(VAL1) == VAL1_INT);
645
646 EXPECT(my_fcmpeq(test_float_d2f(VAL1), VAL1, FPREC));
647 EXPECT(my_dcmpeq(test_float_f2d(VAL1), VAL1, FPREC));
648
649 EXPECT(my_dcmpeq(test_float_i2d(VAL1_INT), VAL1_INT, DPREC));
650 EXPECT(my_dcmpeq(test_float_ui2d(VAL1_INT), VAL1_INT, DPREC));
651 EXPECT(my_dcmpeq(test_float_l2d(VAL1_INT), VAL1_INT, DPREC));
652 EXPECT(my_dcmpeq(test_float_ul2d(VAL1_INT), VAL1_INT, DPREC));
653
654 EXPECT(my_fcmpeq(test_float_i2f(VAL1_INT), VAL1_INT, FPREC));
655 EXPECT(my_fcmpeq(test_float_ui2f(VAL1_INT), VAL1_INT, FPREC));
656 EXPECT(my_fcmpeq(test_float_l2f(VAL1_INT), VAL1_INT, FPREC));
657 EXPECT(my_fcmpeq(test_float_ul2f(VAL1_INT), VAL1_INT, FPREC));
658 return TEE_SUCCESS;
659}
660#else /*CFG_TA_FLOAT_SUPPORT*/
661static TEE_Result test_float(void)
662{
663 IMSG("Floating point disabled");
664 return TEE_SUCCESS;
665}
666#endif /*CFG_TA_FLOAT_SUPPORT*/
667
Jens Wiklander9f682c62016-03-27 20:23:06 +0200668static __noinline void call_longjmp(jmp_buf env)
669{
670 DMSG("Calling longjmp");
671 longjmp(env, 1);
672 EMSG("error: longjmp returned to calling function");
673}
674
675static TEE_Result test_setjmp(void)
676{
677 jmp_buf env;
678
679 if (setjmp(env)) {
680 IMSG("Returned via longjmp");
681 return TEE_SUCCESS;
682 } else {
683 call_longjmp(env);
684 return TEE_ERROR_GENERIC;
685 }
686}
687
Pascal Brandc639ac82015-07-02 08:53:34 +0200688TEE_Result ta_entry_basic(uint32_t param_types, TEE_Param params[4])
689{
690 TEE_Result res = TEE_ERROR_GENERIC;
691
692 printf("ta_entry_basic: enter\n");
693
694 res = test_malloc();
695 if (res != TEE_SUCCESS)
696 return res;
697
698 res = test_properties();
699 if (res != TEE_SUCCESS)
700 return res;
701
702 res = test_mem_access_right(param_types, params);
703 if (res != TEE_SUCCESS)
704 return res;
705
706 res = test_time();
707 if (res != TEE_SUCCESS)
708 return res;
709
Jens Wiklander246184a2015-12-11 08:28:59 +0100710 res = test_float();
711 if (res != TEE_SUCCESS)
712 return res;
713
Jens Wiklander9f682c62016-03-27 20:23:06 +0200714 res = test_setjmp();
715 if (res != TEE_SUCCESS)
716 return res;
717
Pascal Brandc639ac82015-07-02 08:53:34 +0200718 /* mpa lib test bench, panics TA on failure */
719 tb_main();
720
721 return TEE_SUCCESS;
722}
723
724TEE_Result ta_entry_panic(uint32_t param_types, TEE_Param params[4])
725{
726 volatile bool mytrue = true;
727 (void)param_types;
728 (void)params;
729
730 printf("ta_entry_panic: enter\n");
731 /*
732 * Somewhat clumsy way of avoiding compile errors if TEE_Panic() has
733 * the __noreturn attribute.
734 */
735 if (mytrue)
736 TEE_Panic(0xbeef);
737
738 /*
739 * Should not be reached, but if it is the testsuite can detect that
740 * TEE_Panic() returned instead of panicking the TA.
741 */
742 return TEE_SUCCESS;
743}
744
745TEE_Result ta_entry_client_with_timeout(uint32_t param_types,
746 TEE_Param params[4])
747{
748 static const TEE_UUID os_test_uuid = TA_OS_TEST_UUID;
749 TEE_Result res;
750 TEE_TASessionHandle sess;
751 uint32_t ret_orig;
752
753 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
754 TEE_PARAM_TYPE_NONE,
755 TEE_PARAM_TYPE_NONE,
756 TEE_PARAM_TYPE_NONE)) {
757 EMSG("ta_entry_client_with_timeout: bad parameters\n");
758 return TEE_ERROR_BAD_PARAMETERS;
759 }
760
761 res = TEE_OpenTASession(&os_test_uuid, 0, 0, NULL, &sess, &ret_orig);
762 if (res != TEE_SUCCESS) {
763 EMSG(
764 "ta_entry_client_with_timeout: TEE_OpenTASession failed\n");
765 return res;
766 }
767
768 res =
769 TEE_InvokeTACommand(sess, params[0].value.a / 2,
770 TA_OS_TEST_CMD_WAIT, param_types, params,
771 &ret_orig);
772
773 if (ret_orig != TEE_ORIGIN_TRUSTED_APP || res != TEE_ERROR_CANCEL) {
774 EMSG("ta_entry_client_with_timeout: TEE_InvokeTACommand: "
775 "res 0x%x ret_orig 0x%x\n", (unsigned int)res,
776 (unsigned int)ret_orig);
777 res = TEE_ERROR_GENERIC;
778 } else
779 res = TEE_SUCCESS;
780
781 TEE_CloseTASession(sess);
782 return res;
783
784}
785
786TEE_Result ta_entry_client(uint32_t param_types, TEE_Param params[4])
787{
788 static const TEE_UUID crypt_uuid = TA_CRYPT_UUID;
789 TEE_Result res;
790 uint32_t l_pts;
791 TEE_Param l_params[4] = { { {0} } };
792 TEE_TASessionHandle sess;
793 uint32_t ret_orig;
794 static const uint8_t sha256_in[] = { 'a', 'b', 'c' };
795 static const uint8_t sha256_out[] = {
796 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
797 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
798 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
799 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
800 };
801 uint8_t out[32] = { 0 };
802 void *in = NULL;
803
804 (void)param_types;
805 (void)params;
806
807 printf("ta_entry_client: enter\n");
808
809 in = TEE_Malloc(sizeof(sha256_in), 0);
810 if (in == NULL)
811 return TEE_ERROR_OUT_OF_MEMORY;
812 TEE_MemMove(in, sha256_in, sizeof(sha256_in));
813
814 res = TEE_OpenTASession(&crypt_uuid, 0, 0, NULL, &sess, &ret_orig);
815 if (res != TEE_SUCCESS) {
816 EMSG("ta_entry_client: TEE_OpenTASession failed\n");
817 goto cleanup_return;
818 }
819
820 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
821 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0);
822 l_params[0].memref.buffer = in;
823 l_params[0].memref.size = sizeof(sha256_in);
824 l_params[1].memref.buffer = out;
825 l_params[1].memref.size = sizeof(out);
826
827 res = TEE_InvokeTACommand(sess, 0, TA_CRYPT_CMD_SHA256, l_pts, l_params,
828 &ret_orig);
829 if (res != TEE_SUCCESS) {
830 EMSG("ta_entry_client: TEE_InvokeTACommand failed\n");
831 goto cleanup_return;
832 }
833
834 if (TEE_MemCompare(sha256_out, out, sizeof(sha256_out)) != 0) {
835 EMSG("ta_entry_client: out parameter failed\n");
836 res = TEE_ERROR_GENERIC;
837 goto cleanup_return;
838 }
839
840cleanup_return:
841 TEE_Free(in);
842 TEE_CloseTASession(sess);
843 return res;
844}
845
Etienne Carriere281065d2016-10-28 15:41:33 +0200846TEE_Result ta_entry_params_access_rights(uint32_t param_types, TEE_Param params[4])
Pascal Brandc639ac82015-07-02 08:53:34 +0200847{
848 TEE_Result res;
849
850 if (param_types !=
Jerome Forissier04511d82018-01-30 14:33:49 +0100851 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
852 TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0))
Pascal Brandc639ac82015-07-02 08:53:34 +0200853 return TEE_ERROR_GENERIC;
Etienne Carriere281065d2016-10-28 15:41:33 +0200854
855 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
856 TEE_MEMORY_ACCESS_ANY_OWNER,
857 params[0].memref.buffer,
858 params[0].memref.size);
Pascal Brandc639ac82015-07-02 08:53:34 +0200859 if (res != TEE_SUCCESS)
860 return res;
861
862 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
863 params[0].memref.buffer,
864 params[0].memref.size);
Etienne Carriere281065d2016-10-28 15:41:33 +0200865 if (res != TEE_ERROR_ACCESS_DENIED)
866 return TEE_ERROR_GENERIC;
Jerome Forissier04511d82018-01-30 14:33:49 +0100867 if (params[1].memref.buffer || params[1].memref.size)
868 return TEE_ERROR_BAD_PARAMETERS;
Pascal Brandc639ac82015-07-02 08:53:34 +0200869
Etienne Carriere281065d2016-10-28 15:41:33 +0200870 return TEE_SUCCESS;
Pascal Brandc639ac82015-07-02 08:53:34 +0200871}
872
873TEE_Result ta_entry_wait(uint32_t param_types, TEE_Param params[4])
874{
875 TEE_Result res = TEE_SUCCESS;
876 (void)param_types;
877
878 printf("ta_entry_wait: waiting %d\n", (unsigned int)params[0].value.a);
879 /* Wait */
880 res = TEE_Wait(params[0].value.a);
881
882 return res;
883}
884
Jens Wiklander1425f952016-07-21 09:02:30 +0200885static void undef_instr(void)
886{
887#if defined(ARM64)
888 __asm__(".word 0x0");
889#elif defined(ARM32)
890 __asm__(".word 0xe7ffffff");
891#else
892#error "Unsupported architecture"
893#endif
894}
895
Pascal Brandc639ac82015-07-02 08:53:34 +0200896TEE_Result ta_entry_bad_mem_access(uint32_t param_types, TEE_Param params[4])
897{
898 long stack;
899 long stack_addr = (long)&stack;
900
Etienne Carriere92c34422018-02-09 13:11:40 +0100901 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0) &&
902 param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
903 TEE_PARAM_TYPE_MEMREF_INOUT, 0, 0))
Pascal Brandc639ac82015-07-02 08:53:34 +0200904 return TEE_ERROR_GENERIC;
905
906 switch (params[0].value.a) {
907 case 1:
908 *((uint32_t *) 0) = 0;
909 break;
910 case 2:
911 *((uint32_t *)(stack_addr + 0x40000000)) = 0;
912 break;
913 case 3:
914 ((void (*)(void))0) ();
915 break;
916 case 4:
917 ((void (*)(void))(stack_addr + 0x40000000)) ();
918 break;
919 case 5:
Jens Wiklander1425f952016-07-21 09:02:30 +0200920 undef_instr();
Pascal Brandc639ac82015-07-02 08:53:34 +0200921 break;
922 default:
923 break;
924 }
925
926 return TEE_SUCCESS;
927}
Jerome Forissiere916b102017-06-07 17:55:52 +0200928
929static void incr_values(size_t bufsize, uint8_t *a, uint8_t *b, uint8_t *c)
930{
931 size_t i;
932
933 for (i = 0; i < bufsize; i++) {
934 a[i]++; b[i]++; c[i]++;
935 }
936}
937
938TEE_Result ta_entry_ta2ta_memref(uint32_t param_types, TEE_Param params[4])
939{
940 static const TEE_UUID test_uuid = TA_OS_TEST_UUID;
941 TEE_TASessionHandle sess = TEE_HANDLE_NULL;
942 TEE_Param l_params[4] = { { {0} } };
943 size_t bufsize = 2 * 1024;
944 uint8_t in[bufsize];
945 uint8_t inout[bufsize];
946 uint8_t out[bufsize];
947 TEE_Result res;
948 uint32_t ret_orig;
949 uint32_t l_pts;
950 size_t i;
951 (void)params;
952
953 if (param_types != TEE_PARAM_TYPES(0, 0, 0, 0))
954 return TEE_ERROR_GENERIC;
955
956 res = TEE_OpenTASession(&test_uuid, 0, 0, NULL, &sess, &ret_orig);
957 if (res != TEE_SUCCESS) {
958 EMSG("TEE_OpenTASession failed");
959 goto cleanup_return;
960 }
961
962 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
963 TEE_PARAM_TYPE_MEMREF_INOUT,
964 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0);
965 l_params[0].memref.buffer = in;
966 l_params[0].memref.size = bufsize;
967 l_params[1].memref.buffer = inout;
968 l_params[1].memref.size = bufsize;
969 l_params[2].memref.buffer = out;
970 l_params[2].memref.size = bufsize;
971
972 /* Initialize buffers */
973 for (i = 0; i < bufsize; i++) {
974 in[i] = 5;
975 inout[i] = 10;
976 out[i] = 0;
977 }
978
979 /*
980 * TA will compute: out = ++inout + in
981 * Expected values after this step: in: 5, inout: 11, out: 16
982 */
983 res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_TA2TA_MEMREF_MIX,
984 l_pts, l_params, &ret_orig);
985 if (res != TEE_SUCCESS) {
986 EMSG("TEE_InvokeTACommand failed");
987 goto cleanup_return;
988 }
989
990 /*
991 * Increment all values by one.
992 * Expected values after this step: in: 6, inout: 12, out: 17
993 */
994 incr_values(bufsize, in, inout, out);
995
996 /*
997 * TA will compute: out = ++inout + in
998 * Expected values after this step: in: 6, inout: 13, out: 19
999 */
1000 res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_TA2TA_MEMREF_MIX,
1001 l_pts, l_params, &ret_orig);
1002 if (res != TEE_SUCCESS) {
1003 EMSG("TEE_InvokeTACommand failed");
1004 goto cleanup_return;
1005 }
1006
1007 /* Check the actual values */
1008 for (i = 0; i < bufsize; i++) {
1009 if (in[i] != 6 || inout[i] != 13 || out[i] != 19) {
1010 EMSG("Unexpected value in buffer(s)");
1011 DHEXDUMP(in, bufsize);
1012 DHEXDUMP(inout, bufsize);
1013 DHEXDUMP(out, bufsize);
1014 return TEE_ERROR_GENERIC;
1015 }
1016 }
1017
1018cleanup_return:
1019 TEE_CloseTASession(sess);
1020 return res;
1021}
1022
1023TEE_Result ta_entry_ta2ta_memref_mix(uint32_t param_types, TEE_Param params[4])
1024{
1025 uint8_t *in;
1026 uint8_t *inout;
1027 uint8_t *out;
1028 size_t bufsize;
1029 size_t i;
1030
1031 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1032 TEE_PARAM_TYPE_MEMREF_INOUT,
1033 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0))
1034 return TEE_ERROR_GENERIC;
1035
1036 bufsize = params[0].memref.size;
1037 if (params[1].memref.size != bufsize ||
1038 params[2].memref.size != bufsize)
1039 return TEE_ERROR_GENERIC;
1040
1041 in = params[0].memref.buffer;
1042 inout = params[1].memref.buffer;
1043 out = params[2].memref.buffer;
1044
1045 for (i = 0; i < bufsize; i++)
1046 out[i] = ++inout[i] + in[i];
1047
1048 return TEE_SUCCESS;
1049}
Jens Wiklander87e81702018-03-20 12:00:00 +08001050
1051TEE_Result ta_entry_params(uint32_t param_types, TEE_Param params[4])
1052{
1053 size_t n;
1054
1055 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1056 TEE_PARAM_TYPE_MEMREF_INPUT,
1057 TEE_PARAM_TYPE_MEMREF_OUTPUT,
1058 TEE_PARAM_TYPE_MEMREF_OUTPUT))
1059 return TEE_ERROR_BAD_PARAMETERS;
1060
1061 for (n = 0; n < TEE_NUM_PARAMS; n++)
1062 if (!params[n].memref.buffer || !params[n].memref.size)
1063 return TEE_ERROR_BAD_PARAMETERS;
1064
1065 return TEE_SUCCESS;
1066}