| /* |
| * Copyright (c) 2014, STMicroelectronics International N.V. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License Version 2 as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| #include "xtest_test.h" |
| #include "xtest_helpers.h" |
| #include "tee_api_defines.h" |
| #include "tee_client_api.h" |
| |
| #define OFFSET0 0 |
| |
| #define PARAM_0 0 |
| #define PARAM_1 1 |
| #define PARAM_2 2 |
| #define PARAM_3 3 |
| |
| struct xtest_session { |
| ADBG_Case_t *c; |
| TEEC_Session session; |
| TEEC_Context context; |
| }; |
| |
| /* Compares two memories and checks if their length and content is the same */ |
| #define EXPECT_SHARED_MEM_BUFFER(c, exp_buf, exp_blen, op, param_num, shrm) \ |
| do { \ |
| if ((exp_buf) == NULL) { \ |
| ADBG_EXPECT((c), exp_blen, \ |
| (op)->params[(param_num)].memref.size); \ |
| } else { \ |
| ADBG_EXPECT_COMPARE_POINTER((c), (shrm), ==, \ |
| (op)->params[(param_num)].memref.parent); \ |
| ADBG_EXPECT_BUFFER((c), (exp_buf), (exp_blen), \ |
| (shrm)->buffer, \ |
| (op)->params[(param_num)].memref.size); \ |
| } \ |
| } while (0) |
| |
| /* |
| * Compares the content of the memory cells in OP with the expected value |
| * contained. |
| */ |
| #define EXPECT_OP_TMP_MEM_BUFFER(c, exp_buf, exp_blen, op, param_num, buf) \ |
| do { \ |
| if ((exp_buf) == NULL) { \ |
| ADBG_EXPECT((c), exp_blen, \ |
| (op)->params[(param_num)].tmpref.size); \ |
| } else { \ |
| ADBG_EXPECT_COMPARE_POINTER((c), (buf), ==, \ |
| (op)->params[(param_num)].tmpref.buffer); \ |
| ADBG_EXPECT_BUFFER((c), (exp_buf), (exp_blen), \ |
| (buf), \ |
| (op)->params[(param_num)].memref.size); \ |
| } \ |
| } while (0) |
| |
| /* Registers the TEEC_SharedMemory to the TEE. */ |
| static TEEC_Result RegisterSharedMemory(TEEC_Context *ctx, |
| TEEC_SharedMemory *shm, size_t size, |
| uint32_t flags) |
| { |
| shm->flags = flags; |
| shm->size = size; |
| return TEEC_RegisterSharedMemory(ctx, shm); |
| } |
| |
| /* Allocates shared memory inside of the TEE. */ |
| static TEEC_Result AllocateSharedMemory(TEEC_Context *ctx, |
| TEEC_SharedMemory *shm, size_t size, |
| uint32_t flags) |
| { |
| shm->flags = flags; |
| shm->size = size; |
| return TEEC_AllocateSharedMemory(ctx, shm); |
| } |
| |
| static void CloseSession_null(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "CloseSession_null"); |
| { |
| /* In reality doesn't test anything. */ |
| TEEC_CloseSession(NULL); |
| } |
| Do_ADBG_EndSubCase(cs->c, "CloseSession_null"); |
| } |
| |
| static void Allocate_In(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Allocate_In"); |
| { |
| TEEC_SharedMemory shm = { }; |
| size_t size = 1024; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| AllocateSharedMemory(&cs->context, &shm, size, |
| TEEC_MEM_INPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Allocate_In"); |
| } |
| |
| static void Allocate_out_of_memory(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Allocate_out_of_memory"); |
| { |
| TEEC_SharedMemory shm = { }; |
| size_t SIZE_OVER_MEMORY_CAPACITY = SIZE_MAX; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| ADBG_EXPECT_TEEC_RESULT(cs->c, TEEC_ERROR_OUT_OF_MEMORY, |
| AllocateSharedMemory(&cs->context, &shm, |
| SIZE_OVER_MEMORY_CAPACITY, |
| TEEC_MEM_INPUT)); |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Allocate_out_of_memory"); |
| } |
| |
| static void OpenSession_error_notExistingTA(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "OpenSession_error_notExistingTA"); |
| { |
| TEEC_UUID NONEXISTING_TA_UUID = { 0x534D1192, 0x6143, 0x234C, |
| { 0x47, 0x55, 0x53, 0x52, |
| 0x54, 0x4F, 0x4F, 0x59 } }; |
| uint32_t ret_orig = 0; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| ADBG_EXPECT_COMPARE_UNSIGNED(cs->c, TEEC_SUCCESS, !=, |
| TEEC_OpenSession(&cs->context, &cs->session, |
| &NONEXISTING_TA_UUID, |
| TEEC_LOGIN_PUBLIC, NULL, NULL, |
| &ret_orig)); |
| ADBG_EXPECT_COMPARE_UNSIGNED(cs->c, TEEC_ORIGIN_TRUSTED_APP, !=, |
| ret_orig); |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "OpenSession_error_notExistingTA"); |
| } |
| |
| static void Allocate_InOut(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Allocate_InOut"); |
| { |
| TEEC_SharedMemory shm = { }; |
| uint8_t val[] = { 54, 76, 98, 32 }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| AllocateSharedMemory(&cs->context, &shm, sizeof(val), |
| TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Allocate_InOut"); |
| } |
| |
| static void Register_In(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Register_In"); |
| { |
| TEEC_SharedMemory shm = { }; |
| uint8_t val[] = { 32, 65, 43, 21, 98 }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| shm.buffer = val; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| RegisterSharedMemory(&cs->context, &shm, sizeof(val), |
| TEEC_MEM_INPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Register_In"); |
| } |
| |
| static void Register_notZeroLength_Out(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Register_notZeroLength_Out"); |
| { |
| TEEC_SharedMemory shm = { }; |
| uint8_t val[] = { 56, 67, 78, 99 }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| shm.buffer = val; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| RegisterSharedMemory(&cs->context, &shm, sizeof(val), |
| TEEC_MEM_OUTPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Register_notZeroLength_Out"); |
| } |
| |
| static void Register_InOut(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Register_InOut"); |
| { |
| TEEC_SharedMemory shm = { }; |
| uint8_t val[] = { 54, 76, 23, 98, 255, 23, 86 }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| shm.buffer = val; |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| RegisterSharedMemory(&cs->context, &shm, sizeof(val), |
| TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Register_InOut"); |
| } |
| |
| static void Register_zeroLength_Out(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Register_zeroLength_Out"); |
| { |
| uint8_t val[] = { 65, 76, 98, 32 }; |
| TEEC_SharedMemory shm = { }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| shm.buffer = val; |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| RegisterSharedMemory(&cs->context, &shm, 0, |
| TEEC_MEM_OUTPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Register_zeroLength_Out"); |
| } |
| |
| static void Allocate_Out(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Allocate_Out"); |
| { |
| TEEC_SharedMemory shm = { }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| AllocateSharedMemory(&cs->context, &shm, 0, |
| TEEC_MEM_OUTPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Allocate_Out"); |
| } |
| |
| static void FinalizeContext_null(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "FinalizeContext_null"); |
| { |
| TEEC_FinalizeContext(NULL); |
| } |
| Do_ADBG_EndSubCase(cs->c, "FinalizeContext_null"); |
| } |
| |
| static void InitializeContext_NotExistingTEE(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "InitializeContext_NotExistingTEE"); |
| { |
| if (!ADBG_EXPECT_COMPARE_UNSIGNED(cs->c, TEEC_SUCCESS, !=, |
| TEEC_InitializeContext("Invalid TEE name", |
| &cs->context))) |
| TEEC_FinalizeContext(&cs->context); |
| } |
| Do_ADBG_EndSubCase(cs->c, "InitializeContext_NotExistingTEE"); |
| } |
| |
| static void AllocateThenRegister_SameMemory(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "AllocateThenRegister_SameMemory"); |
| { |
| TEEC_SharedMemory shm = { }; |
| size_t size_allocation = 32; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| AllocateSharedMemory(&cs->context, &shm, |
| size_allocation, TEEC_MEM_INPUT))) |
| goto out_final; |
| |
| ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| RegisterSharedMemory(&cs->context, &shm, |
| size_allocation, TEEC_MEM_INPUT)); |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "AllocateThenRegister_SameMemory"); |
| } |
| |
| static void AllocateSameMemory_twice(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "AllocateSameMemory_twice"); |
| { |
| TEEC_SharedMemory shm = { }; |
| size_t size_allocation = 32; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| AllocateSharedMemory(&cs->context, &shm, |
| size_allocation, TEEC_MEM_INPUT))) |
| goto out_final; |
| |
| ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| AllocateSharedMemory(&cs->context, &shm, |
| size_allocation, TEEC_MEM_INPUT)); |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "AllocateSameMemory_twice"); |
| } |
| |
| static void RegisterSameMemory_twice(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "RegisterSameMemory_twice"); |
| { |
| uint8_t val[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; |
| TEEC_SharedMemory shm = { }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| shm.buffer = val; |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| RegisterSharedMemory(&cs->context, &shm, sizeof(val), |
| TEEC_MEM_INPUT))) |
| goto out_final; |
| |
| ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| RegisterSharedMemory(&cs->context, &shm, sizeof(val), |
| TEEC_MEM_INPUT)); |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "RegisterSameMemory_twice"); |
| } |
| |
| #ifndef MIN |
| #define MIN(a,b) ((a) < (b) ? (a) : (b)) |
| #endif |
| |
| static void Allocate_sharedMemory_32k(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Allocate_sharedMemory_32k"); |
| { |
| size_t size = MIN(32 * 1024, |
| TEEC_CONFIG_SHAREDMEM_MAX_SIZE); |
| TEEC_SharedMemory shm = { }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| AllocateSharedMemory(&cs->context, &shm, size, |
| TEEC_MEM_INPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Allocate_sharedMemory_32k"); |
| } |
| |
| #define SHM_32K_SIZE MIN(32 * 1024, TEEC_CONFIG_SHAREDMEM_MAX_SIZE) |
| |
| static void Register_sharedMemory_32k(struct xtest_session *cs) |
| { |
| Do_ADBG_BeginSubCase(cs->c, "Register_sharedMemory_32k"); |
| { |
| uint8_t val[SHM_32K_SIZE] = { }; |
| TEEC_SharedMemory shm = { }; |
| |
| if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, |
| TEEC_InitializeContext(_device, &cs->context))) |
| goto out; |
| |
| shm.buffer = val; |
| if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, |
| RegisterSharedMemory(&cs->context, &shm, SHM_32K_SIZE, |
| TEEC_MEM_INPUT))) |
| goto out_final; |
| |
| TEEC_ReleaseSharedMemory(&shm); |
| out_final: |
| TEEC_FinalizeContext(&cs->context); |
| } |
| out: |
| Do_ADBG_EndSubCase(cs->c, "Register_sharedMemory_32k"); |
| } |
| |
| static void xtest_teec_TEE(ADBG_Case_t *c) |
| { |
| struct xtest_session connection = { c }; |
| |
| CloseSession_null(&connection); |
| |
| Allocate_In(&connection); |
| |
| Allocate_out_of_memory(&connection); |
| |
| OpenSession_error_notExistingTA(&connection); |
| |
| Allocate_InOut(&connection); |
| |
| Register_In(&connection); |
| |
| Register_notZeroLength_Out(&connection); |
| |
| Register_InOut(&connection); |
| |
| Register_zeroLength_Out(&connection); |
| |
| Allocate_Out(&connection); |
| |
| FinalizeContext_null(&connection); |
| |
| InitializeContext_NotExistingTEE(&connection); |
| |
| AllocateThenRegister_SameMemory(&connection); |
| |
| AllocateSameMemory_twice(&connection); |
| |
| RegisterSameMemory_twice(&connection); |
| |
| Allocate_sharedMemory_32k(&connection); |
| |
| Register_sharedMemory_32k(&connection); |
| } |
| |
| ADBG_CASE_DEFINE(regression, 5006, xtest_teec_TEE, |
| "Tests for Global platform TEEC"); |