blob: 1a87320a692bf0256e791f03b8797804f981b2f2 [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;
412
413 if (param_types !=
414 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
415 return TEE_ERROR_GENERIC;
416 res =
417 TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
418 TEE_MEMORY_ACCESS_ANY_OWNER,
419 params[0].memref.buffer,
420 params[0].memref.size);
421 if (res != TEE_SUCCESS)
422 return res;
423 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
424 params[0].memref.buffer,
425 params[0].memref.size);
426 if (res != TEE_ERROR_ACCESS_DENIED)
427 return TEE_ERROR_GENERIC;
428
429 res = TEE_OpenTASession(&test_uuid, 0, 0, NULL, &sess, &ret_orig);
430 if (res != TEE_SUCCESS) {
431 EMSG("test_mem_access_right: TEE_OpenTASession failed\n");
432 goto cleanup_return;
433 }
434
435 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0);
436 l_params[0].memref.buffer = buf;
437 l_params[0].memref.size = sizeof(buf);
438 res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_PRIVATE_PARAMS,
439 l_pts, l_params, &ret_orig);
440 if (res != TEE_SUCCESS) {
441 EMSG("test_mem_access_right: TEE_InvokeTACommand failed\n");
442 goto cleanup_return;
443 }
444
445cleanup_return:
446 TEE_CloseTASession(sess);
447 return res;
448}
449
450static TEE_Result test_time(void)
451{
452 TEE_Result res;
453 TEE_Time t;
454 TEE_Time sys_t;
455
456 static const TEE_Time null_time = { 0, 0 };
457 static const TEE_Time wrap_time = { UINT32_MAX, 999 };
458
459 TEE_GetSystemTime(&sys_t);
460 printf("system time %u.%03u\n", (unsigned int)sys_t.seconds,
461 (unsigned int)sys_t.millis);
462
463 TEE_GetREETime(&t);
464 printf("REE time %u.%03u\n", (unsigned int)t.seconds,
465 (unsigned int)t.millis);
466
467 res = TEE_GetTAPersistentTime(&t);
468 switch (res) {
469 case TEE_SUCCESS:
470 printf("Stored TA time %u.%03u\n", (unsigned int)t.seconds,
471 (unsigned int)t.millis);
472 break;
473 case TEE_ERROR_OVERFLOW:
474 EMSG("Stored TA time overflowed %u.%03u\n",
475 (unsigned int)t.seconds, (unsigned int)t.millis);
476 break;
477 case TEE_ERROR_TIME_NOT_SET:
478 EMSG("TA time not stored\n");
479 break;
480 case TEE_ERROR_TIME_NEEDS_RESET:
481 EMSG("TA time needs reset\n");
482 break;
483 default:
484 return res;
485 }
486
487 res = TEE_SetTAPersistentTime(&null_time);
488 if (res != TEE_SUCCESS) {
489 EMSG("TEE_SetTAPersistentTime: failed\n");
490 return res;
491 }
492
493 res = TEE_GetTAPersistentTime(&t);
494 if (res != TEE_SUCCESS) {
495 EMSG("TEE_GetTAPersistentTime null: failed\n");
496 return res;
497 }
498 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
499 (unsigned int)t.millis);
500 /*
501 * The time between TEE_SetTAPersistentTime() and
502 * TEE_GetTAPersistentTime() should be much less than 1 second, in fact
503 * it's not even a millisecond.
504 */
505 if (t.seconds > 1 || t.millis >= 1000) {
506 EMSG("Unexpected stored TA time %u.%03u\n",
507 (unsigned int)t.seconds, (unsigned int)t.millis);
508 return TEE_ERROR_BAD_STATE;
509 }
510
511 res = TEE_SetTAPersistentTime(&wrap_time);
512 if (res != TEE_SUCCESS) {
513 EMSG("TEE_SetTAPersistentTime wrap: failed\n");
514 return res;
515 }
516
517 res = TEE_Wait(1000);
518 if (res != TEE_SUCCESS)
519 EMSG("TEE_Wait wrap: failed\n");
520
521 res = TEE_GetTAPersistentTime(&t);
522 if (res != TEE_ERROR_OVERFLOW) {
523 EMSG("TEE_GetTAPersistentTime: failed\n");
524 return TEE_ERROR_BAD_STATE;
525 }
526 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
527 (unsigned int)t.millis);
528
529 if (t.seconds > sys_t.seconds) {
530 EMSG("Unexpected wrapped time %u.%03u (sys_t %u.%03u)\n",
531 (unsigned int)t.seconds, (unsigned int)t.millis,
532 (unsigned int)sys_t.seconds, (unsigned int)sys_t.millis);
533 return TEE_ERROR_BAD_STATE;
534 }
535
536 return TEE_SUCCESS;
537}
538
Jens Wiklander246184a2015-12-11 08:28:59 +0100539#ifdef CFG_TA_FLOAT_SUPPORT
540static bool my_dcmpeq(double v1, double v2, double prec)
541{
542 return v1 > (v2 - prec) && v1 < (v2 + prec);
543}
544
545static bool my_fcmpeq(float v1, float v2, float prec)
546{
547 return v1 > (v2 - prec) && v1 < (v2 + prec);
548}
549
550
551static TEE_Result test_float(void)
552{
553#define VAL1 2.6
554#define VAL1_INT 2
555#define VAL2 5.3
556#define DPREC 0.000000000000001
557#define FPREC 0.000001
558#define EXPECT(expr) do { \
559 if (!(expr)) { \
560 EMSG("Expression %s failed", #expr); \
561 return TEE_ERROR_GENERIC; \
562 } \
563 } while (0)
564
565 IMSG("Testing floating point operations");
566
567 EXPECT(my_dcmpeq(test_float_dadd(VAL1, VAL2), VAL1 + VAL2, DPREC));
568 EXPECT(my_dcmpeq(test_float_ddiv(VAL1, VAL2), VAL1 / VAL2, DPREC));
569 EXPECT(my_dcmpeq(test_float_dmul(VAL1, VAL2), VAL1 * VAL2, DPREC));
570 EXPECT(my_dcmpeq(test_float_drsub(VAL1, VAL2), VAL2 - VAL1, DPREC));
571 EXPECT(my_dcmpeq(test_float_dsub(VAL1, VAL2), VAL1 - VAL2, DPREC));
572
573 EXPECT(test_float_dcmpeq(VAL1, VAL1) == 1);
574 EXPECT(test_float_dcmplt(VAL1, VAL2) == 1);
575 EXPECT(test_float_dcmple(VAL1, VAL1) == 1);
576 EXPECT(test_float_dcmpge(VAL1, VAL1) == 1);
577 EXPECT(test_float_dcmpgt(VAL2, VAL1) == 1);
578
579 EXPECT(my_fcmpeq(test_float_fadd(VAL1, VAL2), VAL1 + VAL2, FPREC));
580 EXPECT(my_fcmpeq(test_float_fdiv(VAL1, VAL2), VAL1 / VAL2, FPREC));
581 EXPECT(my_fcmpeq(test_float_fmul(VAL1, VAL2), VAL1 * VAL2, FPREC));
582 EXPECT(my_fcmpeq(test_float_frsub(VAL1, VAL2), VAL2 - VAL1, FPREC));
583 EXPECT(my_fcmpeq(test_float_fsub(VAL1, VAL2), VAL1 - VAL2, FPREC));
584
585 EXPECT(test_float_fcmpeq(VAL1, VAL1) == 1);
586 EXPECT(test_float_fcmplt(VAL1, VAL2) == 1);
587 EXPECT(test_float_fcmple(VAL1, VAL1) == 1);
588 EXPECT(test_float_fcmpge(VAL1, VAL1) == 1);
589 EXPECT(test_float_fcmpgt(VAL2, VAL1) == 1);
590
591 EXPECT(test_float_d2iz(VAL1) == VAL1_INT);
592 EXPECT(test_float_d2uiz(VAL1) == VAL1_INT);
593 EXPECT(test_float_d2lz(VAL1) == VAL1_INT);
594 EXPECT(test_float_d2ulz(VAL1) == VAL1_INT);
595
596 EXPECT(test_float_f2iz(VAL1) == VAL1_INT);
597 EXPECT(test_float_f2uiz(VAL1) == VAL1_INT);
598 EXPECT(test_float_f2lz(VAL1) == VAL1_INT);
599 EXPECT(test_float_f2ulz(VAL1) == VAL1_INT);
600
601 EXPECT(my_fcmpeq(test_float_d2f(VAL1), VAL1, FPREC));
602 EXPECT(my_dcmpeq(test_float_f2d(VAL1), VAL1, FPREC));
603
604 EXPECT(my_dcmpeq(test_float_i2d(VAL1_INT), VAL1_INT, DPREC));
605 EXPECT(my_dcmpeq(test_float_ui2d(VAL1_INT), VAL1_INT, DPREC));
606 EXPECT(my_dcmpeq(test_float_l2d(VAL1_INT), VAL1_INT, DPREC));
607 EXPECT(my_dcmpeq(test_float_ul2d(VAL1_INT), VAL1_INT, DPREC));
608
609 EXPECT(my_fcmpeq(test_float_i2f(VAL1_INT), VAL1_INT, FPREC));
610 EXPECT(my_fcmpeq(test_float_ui2f(VAL1_INT), VAL1_INT, FPREC));
611 EXPECT(my_fcmpeq(test_float_l2f(VAL1_INT), VAL1_INT, FPREC));
612 EXPECT(my_fcmpeq(test_float_ul2f(VAL1_INT), VAL1_INT, FPREC));
613 return TEE_SUCCESS;
614}
615#else /*CFG_TA_FLOAT_SUPPORT*/
616static TEE_Result test_float(void)
617{
618 IMSG("Floating point disabled");
619 return TEE_SUCCESS;
620}
621#endif /*CFG_TA_FLOAT_SUPPORT*/
622
Jens Wiklander9f682c62016-03-27 20:23:06 +0200623static __noinline void call_longjmp(jmp_buf env)
624{
625 DMSG("Calling longjmp");
626 longjmp(env, 1);
627 EMSG("error: longjmp returned to calling function");
628}
629
630static TEE_Result test_setjmp(void)
631{
632 jmp_buf env;
633
634 if (setjmp(env)) {
635 IMSG("Returned via longjmp");
636 return TEE_SUCCESS;
637 } else {
638 call_longjmp(env);
639 return TEE_ERROR_GENERIC;
640 }
641}
642
Pascal Brandc639ac82015-07-02 08:53:34 +0200643TEE_Result ta_entry_basic(uint32_t param_types, TEE_Param params[4])
644{
645 TEE_Result res = TEE_ERROR_GENERIC;
646
647 printf("ta_entry_basic: enter\n");
648
649 res = test_malloc();
650 if (res != TEE_SUCCESS)
651 return res;
652
653 res = test_properties();
654 if (res != TEE_SUCCESS)
655 return res;
656
657 res = test_mem_access_right(param_types, params);
658 if (res != TEE_SUCCESS)
659 return res;
660
661 res = test_time();
662 if (res != TEE_SUCCESS)
663 return res;
664
Jens Wiklander246184a2015-12-11 08:28:59 +0100665 res = test_float();
666 if (res != TEE_SUCCESS)
667 return res;
668
Jens Wiklander9f682c62016-03-27 20:23:06 +0200669 res = test_setjmp();
670 if (res != TEE_SUCCESS)
671 return res;
672
Pascal Brandc639ac82015-07-02 08:53:34 +0200673 /* mpa lib test bench, panics TA on failure */
674 tb_main();
675
676 return TEE_SUCCESS;
677}
678
679TEE_Result ta_entry_panic(uint32_t param_types, TEE_Param params[4])
680{
681 volatile bool mytrue = true;
682 (void)param_types;
683 (void)params;
684
685 printf("ta_entry_panic: enter\n");
686 /*
687 * Somewhat clumsy way of avoiding compile errors if TEE_Panic() has
688 * the __noreturn attribute.
689 */
690 if (mytrue)
691 TEE_Panic(0xbeef);
692
693 /*
694 * Should not be reached, but if it is the testsuite can detect that
695 * TEE_Panic() returned instead of panicking the TA.
696 */
697 return TEE_SUCCESS;
698}
699
700TEE_Result ta_entry_client_with_timeout(uint32_t param_types,
701 TEE_Param params[4])
702{
703 static const TEE_UUID os_test_uuid = TA_OS_TEST_UUID;
704 TEE_Result res;
705 TEE_TASessionHandle sess;
706 uint32_t ret_orig;
707
708 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
709 TEE_PARAM_TYPE_NONE,
710 TEE_PARAM_TYPE_NONE,
711 TEE_PARAM_TYPE_NONE)) {
712 EMSG("ta_entry_client_with_timeout: bad parameters\n");
713 return TEE_ERROR_BAD_PARAMETERS;
714 }
715
716 res = TEE_OpenTASession(&os_test_uuid, 0, 0, NULL, &sess, &ret_orig);
717 if (res != TEE_SUCCESS) {
718 EMSG(
719 "ta_entry_client_with_timeout: TEE_OpenTASession failed\n");
720 return res;
721 }
722
723 res =
724 TEE_InvokeTACommand(sess, params[0].value.a / 2,
725 TA_OS_TEST_CMD_WAIT, param_types, params,
726 &ret_orig);
727
728 if (ret_orig != TEE_ORIGIN_TRUSTED_APP || res != TEE_ERROR_CANCEL) {
729 EMSG("ta_entry_client_with_timeout: TEE_InvokeTACommand: "
730 "res 0x%x ret_orig 0x%x\n", (unsigned int)res,
731 (unsigned int)ret_orig);
732 res = TEE_ERROR_GENERIC;
733 } else
734 res = TEE_SUCCESS;
735
736 TEE_CloseTASession(sess);
737 return res;
738
739}
740
741TEE_Result ta_entry_client(uint32_t param_types, TEE_Param params[4])
742{
743 static const TEE_UUID crypt_uuid = TA_CRYPT_UUID;
744 TEE_Result res;
745 uint32_t l_pts;
746 TEE_Param l_params[4] = { { {0} } };
747 TEE_TASessionHandle sess;
748 uint32_t ret_orig;
749 static const uint8_t sha256_in[] = { 'a', 'b', 'c' };
750 static const uint8_t sha256_out[] = {
751 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
752 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
753 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
754 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
755 };
756 uint8_t out[32] = { 0 };
757 void *in = NULL;
758
759 (void)param_types;
760 (void)params;
761
762 printf("ta_entry_client: enter\n");
763
764 in = TEE_Malloc(sizeof(sha256_in), 0);
765 if (in == NULL)
766 return TEE_ERROR_OUT_OF_MEMORY;
767 TEE_MemMove(in, sha256_in, sizeof(sha256_in));
768
769 res = TEE_OpenTASession(&crypt_uuid, 0, 0, NULL, &sess, &ret_orig);
770 if (res != TEE_SUCCESS) {
771 EMSG("ta_entry_client: TEE_OpenTASession failed\n");
772 goto cleanup_return;
773 }
774
775 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
776 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0);
777 l_params[0].memref.buffer = in;
778 l_params[0].memref.size = sizeof(sha256_in);
779 l_params[1].memref.buffer = out;
780 l_params[1].memref.size = sizeof(out);
781
782 res = TEE_InvokeTACommand(sess, 0, TA_CRYPT_CMD_SHA256, l_pts, l_params,
783 &ret_orig);
784 if (res != TEE_SUCCESS) {
785 EMSG("ta_entry_client: TEE_InvokeTACommand failed\n");
786 goto cleanup_return;
787 }
788
789 if (TEE_MemCompare(sha256_out, out, sizeof(sha256_out)) != 0) {
790 EMSG("ta_entry_client: out parameter failed\n");
791 res = TEE_ERROR_GENERIC;
792 goto cleanup_return;
793 }
794
795cleanup_return:
796 TEE_Free(in);
797 TEE_CloseTASession(sess);
798 return res;
799}
800
801TEE_Result ta_entry_private_params(uint32_t param_types, TEE_Param params[4])
802{
803 TEE_Result res;
804
805 if (param_types !=
806 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
807 return TEE_ERROR_GENERIC;
808 res =
809 TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
810 TEE_MEMORY_ACCESS_ANY_OWNER,
811 params[0].memref.buffer,
812 params[0].memref.size);
813 if (res != TEE_SUCCESS)
814 return res;
815
816 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
817 params[0].memref.buffer,
818 params[0].memref.size);
819
820 return res;
821}
822
823TEE_Result ta_entry_wait(uint32_t param_types, TEE_Param params[4])
824{
825 TEE_Result res = TEE_SUCCESS;
826 (void)param_types;
827
828 printf("ta_entry_wait: waiting %d\n", (unsigned int)params[0].value.a);
829 /* Wait */
830 res = TEE_Wait(params[0].value.a);
831
832 return res;
833}
834
Jens Wiklander1425f952016-07-21 09:02:30 +0200835static void undef_instr(void)
836{
837#if defined(ARM64)
838 __asm__(".word 0x0");
839#elif defined(ARM32)
840 __asm__(".word 0xe7ffffff");
841#else
842#error "Unsupported architecture"
843#endif
844}
845
Pascal Brandc639ac82015-07-02 08:53:34 +0200846TEE_Result ta_entry_bad_mem_access(uint32_t param_types, TEE_Param params[4])
847{
848 long stack;
849 long stack_addr = (long)&stack;
850
851 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0))
852 return TEE_ERROR_GENERIC;
853
854 switch (params[0].value.a) {
855 case 1:
856 *((uint32_t *) 0) = 0;
857 break;
858 case 2:
859 *((uint32_t *)(stack_addr + 0x40000000)) = 0;
860 break;
861 case 3:
862 ((void (*)(void))0) ();
863 break;
864 case 4:
865 ((void (*)(void))(stack_addr + 0x40000000)) ();
866 break;
867 case 5:
Jens Wiklander1425f952016-07-21 09:02:30 +0200868 undef_instr();
Pascal Brandc639ac82015-07-02 08:53:34 +0200869 break;
870 default:
871 break;
872 }
873
874 return TEE_SUCCESS;
875}