| /* |
| * 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 <string.h> |
| #include <stdio.h> |
| #include <pthread.h> |
| |
| #include <adbg.h> |
| #include <xtest_test.h> |
| #include <xtest_helpers.h> |
| |
| #include <tee_client_api.h> |
| #include <ta_storage.h> |
| #include <tee_api_defines.h> |
| #include <tee_api_defines_extensions.h> |
| #include <tee_api_types.h> |
| #ifdef WITH_GP_TESTS |
| #include <TTA_DS_protocol.h> |
| #endif |
| #include <util.h> |
| |
| static uint32_t storage_ids[] = { |
| TEE_STORAGE_PRIVATE, |
| #ifdef CFG_REE_FS |
| TEE_STORAGE_PRIVATE_REE, |
| #endif |
| #ifdef CFG_RPMB_FS |
| TEE_STORAGE_PRIVATE_RPMB, |
| #endif |
| }; |
| |
| static uint8_t file_00[] = { |
| 0x00, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, |
| 0xF0, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, |
| 0xE9, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, |
| 0xF0, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x8E |
| }; |
| |
| static uint8_t file_01[] = { |
| 0x01, 0x00 |
| }; |
| |
| static uint8_t file_02[] = { |
| 0x02, 0x11, 0x02 |
| }; |
| |
| static uint8_t file_03[] = { |
| 0x03, 0x13, 0x03 |
| }; |
| |
| static uint8_t file_04[] = { |
| 0x00, 0x01, 0x02 |
| }; |
| |
| static uint8_t data_00[] = { |
| 0x00, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, |
| 0x00, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, |
| 0x00, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, |
| 0x00, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x00 |
| }; |
| |
| static uint8_t data_01[] = { |
| 0x01, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, |
| 0x01, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, |
| 0x01, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, |
| 0x01, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x01 |
| }; |
| |
| static uint32_t fs_id_for_tee_storage_private(void) |
| { |
| #if defined(CFG_REE_FS) |
| return TEE_STORAGE_PRIVATE_REE; |
| #elif defined(CFG_RPMB_FS) |
| return TEE_STORAGE_PRIVATE_RPMB; |
| #endif |
| } |
| |
| static uint32_t real_id_for(uint32_t id) |
| { |
| if (id == TEE_STORAGE_PRIVATE) |
| return fs_id_for_tee_storage_private(); |
| return id; |
| } |
| |
| static bool storage_is(uint32_t id1, uint32_t id2) |
| { |
| return (real_id_for(id1) == real_id_for(id2)); |
| } |
| |
| static TEEC_Result fs_open(TEEC_Session *sess, void *id, uint32_t id_size, |
| uint32_t flags, uint32_t *obj, uint32_t storage_id) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| TEEC_Result res; |
| uint32_t org; |
| |
| op.params[0].tmpref.buffer = id; |
| op.params[0].tmpref.size = id_size; |
| op.params[1].value.a = flags; |
| op.params[1].value.b = 0; |
| op.params[2].value.a = storage_id; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, |
| TEEC_VALUE_INOUT, TEEC_VALUE_INPUT, |
| TEEC_NONE); |
| |
| res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_OPEN, &op, &org); |
| |
| if (res == TEEC_SUCCESS) |
| *obj = op.params[1].value.b; |
| |
| return res; |
| } |
| |
| static TEEC_Result fs_create(TEEC_Session *sess, void *id, uint32_t id_size, |
| uint32_t flags, uint32_t attr, void *data, |
| uint32_t data_size, uint32_t *obj, |
| uint32_t storage_id) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| TEEC_Result res; |
| uint32_t org; |
| |
| op.params[0].tmpref.buffer = id; |
| op.params[0].tmpref.size = id_size; |
| op.params[1].value.a = flags; |
| op.params[1].value.b = 0; |
| op.params[2].value.a = attr; |
| op.params[2].value.b = storage_id; |
| op.params[3].tmpref.buffer = data; |
| op.params[3].tmpref.size = data_size; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, |
| TEEC_VALUE_INOUT, TEEC_VALUE_INPUT, |
| TEEC_MEMREF_TEMP_INPUT); |
| |
| res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_CREATE, &op, &org); |
| |
| if (res == TEEC_SUCCESS) |
| *obj = op.params[1].value.b; |
| |
| return res; |
| } |
| |
| static TEEC_Result fs_create_overwrite(TEEC_Session *sess, void *id, |
| uint32_t id_size, uint32_t storage_id) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| TEEC_Result res; |
| uint32_t org; |
| |
| op.params[0].tmpref.buffer = id; |
| op.params[0].tmpref.size = id_size; |
| op.params[1].value.a = storage_id; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, |
| TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE); |
| |
| res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_CREATE_OVERWRITE, &op, &org); |
| |
| return res; |
| } |
| |
| static TEEC_Result fs_close(TEEC_Session *sess, uint32_t obj) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_CLOSE, &op, &org); |
| } |
| |
| static TEEC_Result fs_read(TEEC_Session *sess, uint32_t obj, void *data, |
| uint32_t data_size, uint32_t *count) |
| { |
| TEEC_Result res; |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].tmpref.buffer = data; |
| op.params[0].tmpref.size = data_size; |
| op.params[1].value.a = obj; |
| op.params[1].value.b = 0; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, |
| TEEC_VALUE_INOUT, TEEC_NONE, |
| TEEC_NONE); |
| |
| res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_READ, &op, &org); |
| |
| if (res == TEEC_SUCCESS) |
| *count = op.params[1].value.b; |
| |
| return res; |
| } |
| |
| static TEEC_Result fs_write(TEEC_Session *sess, uint32_t obj, void *data, |
| uint32_t data_size) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].tmpref.buffer = data; |
| op.params[0].tmpref.size = data_size; |
| op.params[1].value.a = obj; |
| op.params[1].value.b = 0; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, |
| TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_WRITE, &op, &org); |
| } |
| |
| static TEEC_Result fs_seek(TEEC_Session *sess, uint32_t obj, int32_t offset, |
| int32_t whence) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj; |
| op.params[0].value.b = *(uint32_t *)&offset; |
| op.params[1].value.a = whence; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INOUT, |
| TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_SEEK, &op, &org); |
| } |
| |
| static TEEC_Result fs_unlink(TEEC_Session *sess, uint32_t obj) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_UNLINK, &op, &org); |
| } |
| |
| static TEEC_Result fs_trunc(TEEC_Session *sess, uint32_t obj, uint32_t len) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj; |
| op.params[0].value.b = len; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_TRUNC, &op, &org); |
| } |
| |
| static TEEC_Result fs_rename(TEEC_Session *sess, uint32_t obj, void *id, |
| uint32_t id_size) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj; |
| op.params[1].tmpref.buffer = id; |
| op.params[1].tmpref.size = id_size; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, |
| TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, |
| TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_RENAME, &op, &org); |
| } |
| |
| static TEEC_Result fs_alloc_enum(TEEC_Session *sess, uint32_t *e) |
| { |
| TEEC_Result res; |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_ALLOC_ENUM, &op, &org); |
| |
| if (res == TEEC_SUCCESS) |
| *e = op.params[0].value.a; |
| |
| return res; |
| } |
| |
| static TEEC_Result fs_reset_enum(TEEC_Session *sess, uint32_t e) |
| { |
| TEEC_Result res; |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| op.params[0].value.a = e; |
| res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_RESET_ENUM, &op, &org); |
| |
| return res; |
| } |
| |
| static TEEC_Result fs_free_enum(TEEC_Session *sess, uint32_t e) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, |
| TEEC_NONE); |
| |
| op.params[0].value.a = e; |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_FREE_ENUM, &op, &org); |
| } |
| |
| static TEEC_Result fs_start_enum(TEEC_Session *sess, uint32_t e, |
| uint32_t storage_id) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| op.params[0].value.a = e; |
| op.params[0].value.b = storage_id; |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_START_ENUM, &op, &org); |
| } |
| |
| static TEEC_Result fs_next_enum(TEEC_Session *sess, uint32_t e, void *obj_info, |
| size_t info_size, void *id, uint32_t id_size) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); |
| if (obj_info && info_size) |
| op.paramTypes |= (TEEC_MEMREF_TEMP_OUTPUT << 4); |
| |
| op.params[0].value.a = e; |
| op.params[1].tmpref.buffer = obj_info; |
| op.params[1].tmpref.size = info_size; |
| op.params[2].tmpref.buffer = id; |
| op.params[2].tmpref.size = id_size; |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_NEXT_ENUM, &op, &org); |
| } |
| |
| static TEEC_Result fs_restrict_usage(TEEC_Session *sess, uint32_t obj, |
| uint32_t obj_usage) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj; |
| op.params[0].value.b = obj_usage; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_RESTRICT_USAGE, |
| &op, &org); |
| } |
| |
| static TEEC_Result fs_alloc_obj(TEEC_Session *sess, uint32_t obj_type, |
| uint32_t max_key_size, uint32_t *obj) |
| { |
| TEEC_Result res; |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj_type; |
| op.params[0].value.b = max_key_size; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, |
| TEEC_NONE, TEEC_NONE); |
| |
| res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_ALLOC_OBJ, &op, &org); |
| *obj = op.params[1].value.a; |
| return res; |
| } |
| |
| static TEEC_Result fs_free_obj(TEEC_Session *sess, uint32_t obj) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_FREE_OBJ, &op, &org); |
| } |
| |
| static TEEC_Result fs_reset_obj(TEEC_Session *sess, uint32_t obj) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.params[0].value.a = obj; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_RESET_OBJ, &op, &org); |
| } |
| |
| static TEEC_Result fs_get_obj_info(TEEC_Session *sess, uint32_t obj, |
| void *obj_info, size_t info_size) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, |
| TEEC_MEMREF_TEMP_OUTPUT, |
| TEEC_NONE, TEEC_NONE); |
| |
| op.params[0].value.a = obj; |
| op.params[1].tmpref.buffer = obj_info; |
| op.params[1].tmpref.size = info_size; |
| |
| return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_GET_OBJ_INFO, &op, &org); |
| } |
| |
| /* trunc */ |
| static void test_truncate_file_length(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint8_t out[10] = { 0 }; |
| uint32_t count; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| /* create */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit; |
| |
| /* trunc */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_trunc(&sess, obj, 10))) |
| goto exit; |
| |
| /* seek */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS( |
| c, fs_seek(&sess, obj, 5, TEE_DATA_SEEK_SET))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| /* check buffer */ |
| (void)ADBG_EXPECT_BUFFER(c, &data_00[5], 5, out, count); |
| |
| /* close */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| /* open */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| /* seek */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS( |
| c, fs_seek(&sess, obj, 5, TEE_DATA_SEEK_SET))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| /* check buffer */ |
| (void)ADBG_EXPECT_BUFFER(c, &data_00[5], 5, out, count); |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| /* extend */ |
| static void test_extend_file_length(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint8_t out[10] = { 0 }; |
| uint8_t expect[10] = { 0 }; |
| uint32_t count; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| /* create */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit; |
| |
| /* extend */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_trunc(&sess, obj, 40))) |
| goto exit; |
| |
| /* seek */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS( |
| c, fs_seek(&sess, obj, 30, TEE_DATA_SEEK_SET))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| /* check buffer */ |
| expect[0] = data_00[30]; |
| expect[1] = data_00[31]; |
| (void)ADBG_EXPECT_BUFFER(c, &expect[0], 10, out, count); |
| |
| /* close */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| /* open */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| /* seek */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS( |
| c, fs_seek(&sess, obj, 30, TEE_DATA_SEEK_SET))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| /* check buffer */ |
| expect[0] = data_00[30]; |
| expect[1] = data_00[31]; |
| (void)ADBG_EXPECT_BUFFER(c, &expect[0], 10, out, count); |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| /* file hole */ |
| static void test_file_hole(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint8_t out[10] = { 0 }; |
| uint8_t expect[10] = { 0 }; |
| uint32_t count; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| /* create */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit; |
| |
| /* seek */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS( |
| c, fs_seek(&sess, obj, 80, TEE_DATA_SEEK_SET))) |
| goto exit; |
| |
| /* write */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_write(&sess, obj, data_00, |
| sizeof(data_00)))) |
| goto exit; |
| |
| /* seek */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS( |
| c, fs_seek(&sess, obj, 74, TEE_DATA_SEEK_SET))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| /* check buffer */ |
| expect[6] = data_00[0]; |
| expect[7] = data_00[1]; |
| expect[8] = data_00[2]; |
| expect[9] = data_00[3]; |
| (void)ADBG_EXPECT_BUFFER(c, &expect[0], 10, out, count); |
| |
| /* close */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| /* open */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| /* seek */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS( |
| c, fs_seek(&sess, obj, 74, TEE_DATA_SEEK_SET))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| /* check buffer */ |
| expect[6] = data_00[0]; |
| expect[7] = data_00[1]; |
| expect[8] = data_00[2]; |
| expect[9] = data_00[3]; |
| (void)ADBG_EXPECT_BUFFER(c, &expect[0], 10, out, count); |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| #ifdef WITH_GP_TESTS |
| static TEEC_Result ds_seek_obj_inv_handle(TEEC_Session *sess) |
| { |
| TEEC_Operation op; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES( |
| TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| |
| op.params[0].value.a = CASE_DATA_OBJECT_NOT_PERSISTENT; |
| |
| return TEEC_InvokeCommand( |
| sess, CMD_SeekObjectData_panic, &op, &org); |
| } |
| |
| static TEEC_Result ds_seek_gp( |
| TEEC_Session *sess, TEE_Whence wh, uint32_t wh_off, uint32_t set_off, |
| void *in, size_t in_size, void *out, size_t out_size) |
| { |
| TEEC_Operation op; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES( |
| TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, |
| TEEC_MEMREF_TEMP_OUTPUT); |
| |
| op.params[0].value.a = wh; |
| op.params[0].value.b = wh_off; |
| op.params[1].value.a = set_off; |
| op.params[2].tmpref.buffer = in; |
| op.params[2].tmpref.size = in_size; |
| op.params[3].tmpref.buffer = out; |
| op.params[3].tmpref.size = out_size; |
| |
| return TEEC_InvokeCommand(sess, CMD_SeekWriteReadObjectData, &op, &org); |
| } |
| |
| static TEEC_Result ds_init_object_and_attributes(TEEC_Session *sess, |
| uint32_t obj_type, uint32_t obj_size, const void *attr_meta, |
| size_t attr_meta_len, const void *attr_data, size_t attr_data_len, |
| uint32_t option) |
| { |
| TEEC_Operation op; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES( |
| TEEC_VALUE_INPUT, TEEC_MEMREF_TEMP_INPUT, |
| TEEC_MEMREF_TEMP_INPUT, TEEC_VALUE_INPUT); |
| |
| op.params[0].value.a = obj_type; |
| op.params[0].value.b = obj_size; |
| op.params[1].tmpref.buffer = (void *)attr_meta; |
| op.params[1].tmpref.size = attr_meta_len; |
| op.params[2].tmpref.buffer = (void *)attr_data; |
| op.params[2].tmpref.size = attr_data_len; |
| op.params[3].value.a = option; |
| |
| return TEEC_InvokeCommand(sess, CMD_InitObjectAndAttributes, &op, &org); |
| } |
| |
| static TEEC_Result ds_rename_access_conflict(TEEC_Session *sess) |
| { |
| TEEC_Operation op; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES( |
| TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand( |
| sess, CMD_RenamePersistentObject_AccessConflict, &op, &org); |
| } |
| |
| static TEEC_Result ds_start_enum_no_item(TEEC_Session *sess) |
| { |
| TEEC_Operation op; |
| uint32_t org; |
| TEEC_Result res; |
| |
| op.paramTypes = TEEC_PARAM_TYPES( |
| TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| |
| res = TEEC_InvokeCommand( |
| sess, CMD_StartNGetPersistentObjectEnumerator_itemNotFound, &op, &org); |
| |
| if (res != TEEC_SUCCESS) |
| return res; |
| |
| if (op.params[0].value.a != 0 || op.params[0].value.b != 0) |
| return TEEC_ERROR_GENERIC; |
| |
| return res; |
| } |
| |
| static TEEC_Result ds_rename_success(TEEC_Session *sess) |
| { |
| TEEC_Operation op; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES( |
| TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand( |
| sess, CMD_RenamePersistentObject_Success, &op, &org); |
| } |
| |
| static TEEC_Result ds_null_close_free_reset(TEEC_Session *sess) |
| { |
| TEEC_Operation op; |
| uint32_t org; |
| |
| op.paramTypes = TEEC_PARAM_TYPES( |
| TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); |
| |
| return TEEC_InvokeCommand( |
| sess, CMD_CloseFreeAndResetObjectSuccessHandleNull, &op, &org); |
| } |
| #endif |
| |
| /* create */ |
| static void xtest_tee_test_6001_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_00, sizeof(file_00), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit; |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| #define DEFINE_TEST_MULTIPLE_STORAGE_IDS(test_name) \ |
| static void test_name(ADBG_Case_t *c) \ |
| { \ |
| size_t i; \ |
| \ |
| for (i = 0; i < ARRAY_SIZE(storage_ids); i++) { \ |
| Do_ADBG_BeginSubCase(c, "Storage id: %08x", storage_ids[i]); \ |
| test_name##_single(c, storage_ids[i]); \ |
| Do_ADBG_EndSubCase(c, "Storage id: %08x", storage_ids[i]); \ |
| } \ |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6001) |
| |
| /* open */ |
| static void xtest_tee_test_6002_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6002) |
| |
| /* read */ |
| static void xtest_tee_test_6003_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint8_t out[10] = { 0 }; |
| uint32_t count; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, |
| sizeof(data_01), &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| (void)ADBG_EXPECT_BUFFER(c, data_01, 10, out, count); |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6003) |
| |
| /* write */ |
| static void xtest_tee_test_6004_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint8_t out[10] = { 0 }; |
| uint32_t count; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| /* create */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, |
| sizeof(data_01), &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| /* write new data */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_WRITE, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_write(&sess, obj, data_00, sizeof(data_00)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| (void)ADBG_EXPECT_BUFFER(c, data_00, 10, out, count); |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6004) |
| |
| /* seek */ |
| static void xtest_tee_test_6005_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint8_t out[10] = { 0 }; |
| uint32_t count; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| /* create */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit; |
| |
| /* seek */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_seek(&sess, obj, 10, TEE_DATA_SEEK_SET))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| (void)ADBG_EXPECT_BUFFER(c, &data_00[10], 10, out, count); |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6005) |
| |
| /* unlink */ |
| static void xtest_tee_test_6006_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| /* create */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit; |
| |
| /* del & close */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| /* check result */ |
| if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND, |
| fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_READ, &obj, storage_id))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6006) |
| |
| static void xtest_tee_test_6007_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| Do_ADBG_BeginSubCase(c, "Test truncate file length"); |
| test_truncate_file_length(c, storage_id); |
| Do_ADBG_EndSubCase(c, "Test truncate file length"); |
| |
| Do_ADBG_BeginSubCase(c, "Test extend file length"); |
| test_extend_file_length(c, storage_id); |
| Do_ADBG_EndSubCase(c, "Test extend file length"); |
| |
| Do_ADBG_BeginSubCase(c, "Test file hole"); |
| test_file_hole(c, storage_id); |
| Do_ADBG_EndSubCase(c, "Test file hole"); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6007) |
| |
| static void xtest_tee_test_6008_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj; |
| uint8_t out[10] = { 0 }; |
| uint32_t count; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| /* create */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, |
| sizeof(data_01), &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| /* write new data */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_write(&sess, obj, data_00, sizeof(data_00)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_rename(&sess, obj, file_03, sizeof(file_03)))) |
| goto exit; |
| |
| /* close */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_03, sizeof(file_03), |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| /* check buffer */ |
| (void)ADBG_EXPECT_BUFFER(c, data_00, 10, out, count); |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6008) |
| |
| static void xtest_tee_test_6009_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t obj0; |
| uint32_t obj1; |
| uint32_t obj2; |
| uint32_t e = 0; |
| uint8_t info[200]; |
| uint8_t id[200]; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| /* create file 00 */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_00, sizeof(file_00), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, |
| sizeof(data_01), &obj0, storage_id))) |
| goto exit; |
| |
| /* create file 01 */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, |
| sizeof(data_01), &obj1, storage_id))) |
| goto exit; |
| |
| /* create file 02 */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, |
| sizeof(data_01), &obj2, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj0))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj1))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj2))) |
| goto exit; |
| |
| /* iterate */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_alloc_enum(&sess, &e))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_start_enum(&sess, e, storage_id))) |
| goto exit; |
| |
| /* get 00 */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_next_enum(&sess, e, info, sizeof(info), id, sizeof(id)))) |
| goto exit; |
| |
| /* get 01 */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_next_enum(&sess, e, NULL, 0, id, sizeof(id)))) |
| goto exit; |
| |
| /* get 02 */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_next_enum(&sess, e, info, sizeof(info), id, sizeof(id)))) |
| goto exit; |
| |
| /* we should not have more files */ |
| if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND, |
| fs_next_enum(&sess, e, info, sizeof(info), id, sizeof(id)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_free_enum(&sess, e))) |
| goto exit; |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_00, sizeof(file_00), |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj0, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj0))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj1, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj1))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_02, sizeof(file_02), |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj2, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj2))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6009) |
| |
| static void xtest_tee_test_6010_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t orig; |
| uint32_t o1; |
| uint32_t o2; |
| uint32_t e; |
| uint32_t f; |
| uint8_t data[1024]; |
| uint8_t out[1024]; |
| uint32_t n; |
| |
| for (n = 0; n < ARRAY_SIZE(data); n++) |
| data[n] = n; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| Do_ADBG_BeginSubCase(c, "CreatePersistentObject AccessConflict"); |
| |
| o1 = TEE_HANDLE_NULL; |
| o2 = TEE_HANDLE_NULL; |
| f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | |
| TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; |
| |
| ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_00, sizeof(file_00), f, 0, data, |
| sizeof(data), &o1, storage_id)); |
| |
| f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE; |
| ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ACCESS_CONFLICT, |
| fs_create(&sess, file_00, sizeof(file_00), f, 0, data, |
| sizeof(data), &o2, storage_id)); |
| |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); |
| if (o2) |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o2)); |
| |
| Do_ADBG_EndSubCase(c, "CreatePersistentObject AccessConflict"); |
| |
| |
| |
| Do_ADBG_BeginSubCase(c, "RestrictObjectUsage Panic"); |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, |
| fs_restrict_usage(&sess, 0xffffbad0, 0xffffffff)); |
| Do_ADBG_EndSubCase(c, "RestrictObjectUsage Panic"); |
| |
| TEEC_CloseSession(&sess); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| Do_ADBG_BeginSubCase(c, "SeekObjectData BadHandle"); |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, |
| fs_seek(&sess, 0xffffbad0, 5, TEE_DATA_SEEK_SET)); |
| Do_ADBG_EndSubCase(c, "SeekObjectData BadHandle"); |
| |
| TEEC_CloseSession(&sess); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| Do_ADBG_BeginSubCase(c, "SeekObjectData NotPersist"); |
| o1 = 0; |
| ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_alloc_obj(&sess, TEE_TYPE_AES, 256, &o1)); |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, |
| fs_seek(&sess, o1, 5, TEE_DATA_SEEK_SET)); |
| Do_ADBG_EndSubCase(c, "SeekObjectData NotPersist"); |
| |
| TEEC_CloseSession(&sess); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| Do_ADBG_BeginSubCase(c, "SeekWriteRead"); |
| o1 = 0; |
| f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | |
| TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_00, sizeof(file_00), f, 0, data, |
| sizeof(data), &o1, storage_id))) |
| goto seek_write_read_out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_seek(&sess, o1, 2, TEE_DATA_SEEK_SET))) |
| goto seek_write_read_out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_seek(&sess, o1, 0, TEE_DATA_SEEK_END))) |
| goto seek_write_read_out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_write(&sess, o1, data, sizeof(data)))) |
| goto seek_write_read_out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_seek(&sess, o1, sizeof(data), TEE_DATA_SEEK_SET))) |
| goto seek_write_read_out; |
| |
| memset(out, 0xab, sizeof(out)); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_read(&sess, o1, out, sizeof(out), &n))) |
| goto seek_write_read_out; |
| |
| ADBG_EXPECT_BUFFER(c, data, sizeof(data), out, n); |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_seek(&sess, o1, 10, TEE_DATA_SEEK_END))) |
| goto seek_write_read_out; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_read(&sess, o1, out, sizeof(out), &n))) |
| goto seek_write_read_out; |
| ADBG_EXPECT_COMPARE_UNSIGNED(c, n, ==, 0); |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_seek(&sess, o1, -(int32_t)sizeof(data) / 2, |
| TEE_DATA_SEEK_END))) |
| goto seek_write_read_out; |
| |
| memset(out, 0xab, sizeof(out) / 2); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_read(&sess, o1, out, sizeof(out) / 2, &n))) |
| goto seek_write_read_out; |
| |
| ADBG_EXPECT_BUFFER(c, |
| data + sizeof(data) / 2, sizeof(data) / 2, |
| out, n); |
| |
| seek_write_read_out: |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); |
| Do_ADBG_EndSubCase(c, "SeekWriteRead"); |
| |
| Do_ADBG_BeginSubCase(c, "Rename Access Conflict"); |
| |
| o1 = TEE_HANDLE_NULL; |
| o2 = TEE_HANDLE_NULL; |
| f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | |
| TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; |
| ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_00, sizeof(file_00), f, 0, data, |
| sizeof(data), &o1, storage_id)); |
| ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), f, 0, data, |
| sizeof(data) / 2, &o2, storage_id)); |
| |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_ACCESS_CONFLICT, |
| fs_rename(&sess, o2, file_00, sizeof(file_00))); |
| |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o2)); |
| |
| Do_ADBG_EndSubCase(c, "Rename Access Conflict"); |
| |
| Do_ADBG_BeginSubCase(c, "AllocPersistentObjectEnumerator + " |
| "ResetPersistentObjectEnumerator"); |
| e = TEE_HANDLE_NULL; |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_alloc_enum(&sess, &e)); |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_reset_enum(&sess, e)); |
| Do_ADBG_EndSubCase(c, "AllocPersistentObjectEnumerator + " |
| "ResetPersistentObjectEnumerator"); |
| |
| Do_ADBG_BeginSubCase(c, "StartPersistentObjectEnumerator ItemNotFound"); |
| e = TEE_HANDLE_NULL; |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_alloc_enum(&sess, &e)); |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_ITEM_NOT_FOUND, |
| fs_next_enum(&sess, e, NULL, 0, out, sizeof(out))); |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_ITEM_NOT_FOUND, |
| fs_start_enum(&sess, e, storage_id)); |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_free_enum(&sess, e)); |
| Do_ADBG_EndSubCase(c, "StartPersistentObjectEnumerator ItemNotFound"); |
| |
| Do_ADBG_BeginSubCase(c, "RenamePersistent ReadWrite"); |
| o1 = TEE_HANDLE_NULL; |
| f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | |
| TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; |
| ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_00, sizeof(file_00), f, 0, data, |
| sizeof(data), &o1, storage_id)); |
| ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_rename(&sess, o1, file_01, sizeof(file_01))); |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); |
| Do_ADBG_EndSubCase(c, "RenamePersistent ReadWrite"); |
| |
| Do_ADBG_BeginSubCase(c, "Close Free Reset Null"); |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, TEE_HANDLE_NULL)); |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_free_obj(&sess, TEE_HANDLE_NULL)); |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_reset_obj(&sess, TEE_HANDLE_NULL)); |
| Do_ADBG_EndSubCase(c, "Close Free Reset Null"); |
| |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6010) |
| |
| #ifdef WITH_GP_TESTS |
| static void xtest_tee_test_6011(ADBG_Case_t *c) |
| { |
| TEEC_Session sess; |
| uint32_t orig; |
| /* |
| * Test data from |
| * Invoke_InitObjectAndAttributes_TEE_TYPE_AES_success_attribute_ |
| * TEE_ATTR_SECRET_VALUE_correct_size (9d-9a-91) |
| */ |
| static const uint8_t attr_meta[] = { |
| 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, |
| 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
| 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
| 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
| }; |
| static const uint8_t attr_data[] = { |
| 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77, |
| 0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14, |
| 0xdf,0xf4, |
| }; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS( |
| c, xtest_teec_open_session( |
| &sess, &gp_tta_ds_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, ds_init_object_and_attributes(&sess, |
| 0xa0000010, 0x100, attr_meta, sizeof(attr_meta), attr_data, |
| sizeof(attr_data), 0))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| #endif /*WITH_GP_TESTS*/ |
| |
| static void xtest_tee_test_6012_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t orig; |
| uint32_t obj; |
| |
| /* |
| * create the object a first time (forced through with overwrite attribute) |
| */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create_overwrite(&sess, file_04, sizeof(file_04), storage_id))) |
| goto bail1; |
| |
| TEEC_CloseSession(&sess); |
| |
| /* |
| * re-create the object two times with overwrite attribute |
| */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create_overwrite(&sess, file_04, sizeof(file_04), |
| storage_id))) |
| goto bail1; |
| |
| /* re-create it with an object */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_04, sizeof(file_04), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | |
| TEE_DATA_FLAG_OVERWRITE, 0, NULL, 0, &obj, |
| storage_id))) |
| goto bail2; |
| |
| TEEC_CloseSession(&sess); |
| |
| /* |
| * re-create it again without overwrite flag: should fail and |
| * existing object should not be altered. |
| */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ACCESS_CONFLICT, |
| fs_create(&sess, file_04, sizeof(file_04), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, 0, NULL, 0, &obj, |
| storage_id))) |
| goto bail2; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_04, sizeof(file_04), |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, |
| storage_id))) |
| goto bail1; |
| |
| bail2: |
| /* remove the object so that xtest 600x can be replayed */ |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); |
| bail1: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6012) |
| |
| static void xtest_tee_test_6013_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t orig; |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| op.params[0].value.a = storage_id; |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| ADBG_EXPECT_TEEC_SUCCESS(c, |
| TEEC_InvokeCommand(&sess, TA_STORAGE_CMD_KEY_IN_PERSISTENT, |
| &op, &orig)); |
| |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6013) |
| |
| static void xtest_tee_test_6014_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| uint32_t orig; |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| op.params[0].value.a = storage_id; |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, |
| TEEC_NONE, TEEC_NONE); |
| |
| ADBG_EXPECT_TEEC_SUCCESS(c, |
| TEEC_InvokeCommand(&sess, TA_STORAGE_CMD_LOOP, &op, &orig)); |
| |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6014) |
| |
| static void xtest_tee_test_6015_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| TEEC_Session sess2; |
| uint32_t orig; |
| uint32_t obj; |
| uint32_t obj2; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess2, &storage2_ta_uuid, NULL, |
| &orig))) |
| goto exit2; |
| |
| /* TA #1 creates a persistent object */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit; |
| |
| /* TA #2 tries to open the object created by TA #1 */ |
| if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND, |
| fs_open(&sess2, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_READ, &obj2, storage_id))) |
| goto clean; |
| |
| clean: |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); |
| exit: |
| TEEC_CloseSession(&sess2); |
| exit2: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6015) |
| |
| |
| struct test_6016_thread_arg { |
| ADBG_Case_t *case_t; |
| uint32_t storage_id; |
| char file_name[8]; |
| TEEC_Session session; |
| }; |
| |
| static void *test_6016_thread(void *arg) |
| { |
| struct test_6016_thread_arg *a = arg; |
| TEEC_Session sess = a->session; |
| uint32_t obj; |
| uint8_t out[10] = { 0 }; |
| uint32_t count; |
| |
| /* create */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, |
| fs_create(&sess, a->file_name, sizeof(a->file_name), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, |
| sizeof(data_01), &obj, a->storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, fs_close(&sess, obj))) |
| goto exit; |
| |
| /* write new data */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, |
| fs_open(&sess, a->file_name, sizeof(a->file_name), |
| TEE_DATA_FLAG_ACCESS_WRITE, &obj, a->storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, |
| fs_write(&sess, obj, data_00, sizeof(data_00)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, fs_close(&sess, obj))) |
| goto exit; |
| |
| /* verify */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, |
| fs_open(&sess, a->file_name, sizeof(a->file_name), |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, a->storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, |
| fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| (void)ADBG_EXPECT_BUFFER(a->case_t, data_00, 10, out, count); |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| return NULL; |
| } |
| |
| |
| #define NUM_THREADS 4 |
| static void xtest_tee_test_6016_loop(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| size_t num_threads = NUM_THREADS; |
| struct test_6016_thread_arg arg[num_threads]; |
| pthread_t thr[num_threads]; |
| uint32_t orig; |
| size_t i; |
| size_t n = 0; |
| size_t m; |
| |
| memset(arg, 0, sizeof(arg)); |
| |
| for (m = 0; m < num_threads; m++) |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&arg[m].session, |
| &storage_ta_uuid, NULL, &orig))) |
| goto out; |
| |
| for (n = 0; n < num_threads; n++) { |
| arg[n].case_t = c; |
| arg[n].storage_id = storage_id; |
| snprintf(arg[n].file_name, sizeof(arg[n].file_name), |
| "file_%zu", n); |
| if (!ADBG_EXPECT(c, 0, pthread_create(thr + n, NULL, |
| test_6016_thread, arg + n))) |
| goto out; |
| } |
| |
| out: |
| for (i = 0; i < n; i++) |
| ADBG_EXPECT(c, 0, pthread_join(thr[i], NULL)); |
| for (i = 0; i < m; i++) |
| TEEC_CloseSession(&arg[i].session); |
| } |
| |
| /* concurency */ |
| static void xtest_tee_test_6016_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| int i; |
| int loops = 8; |
| |
| Do_ADBG_Log(" threads: %d, loops: %d", NUM_THREADS, loops); |
| for (i = 0; i < loops; i++) |
| xtest_tee_test_6016_loop(c, storage_id); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6016) |
| |
| static void xtest_tee_test_6017_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| TEE_ObjectInfo obj_info1; |
| TEE_ObjectInfo obj_info2; |
| uint32_t obj; |
| uint32_t orig; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, NULL, |
| 0, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_write(&sess, obj, data_00, sizeof(data_00)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_get_obj_info(&sess, obj, &obj_info1, |
| sizeof(TEE_ObjectInfo)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_get_obj_info(&sess, obj, &obj_info2, |
| sizeof(TEE_ObjectInfo)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, |
| obj_info1.dataSize, ==, obj_info2.dataSize)) |
| goto exit; |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6017) |
| |
| static void xtest_tee_test_6018_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| TEE_ObjectInfo obj_info1; |
| TEE_ObjectInfo obj_info2; |
| uint32_t obj; |
| uint32_t orig; |
| uint8_t block[32 * 1024]; |
| size_t num_blocks; |
| size_t block_size; |
| size_t n; |
| |
| if (storage_is(storage_id, TEE_STORAGE_PRIVATE_RPMB)) { |
| /* RPMB FS is a bit resource constrained */ |
| num_blocks = 10; |
| block_size = 1024; |
| } else { |
| num_blocks = 20; |
| block_size = sizeof(block); |
| } |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE, 0, NULL, |
| 0, &obj, storage_id))) |
| goto exit; |
| |
| for (n = 0; n < num_blocks; n++) { |
| memset(block, n, block_size); |
| |
| Do_ADBG_Log("writing %zu", n); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_write(&sess, obj, block, block_size))) |
| goto exit; |
| } |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_get_obj_info(&sess, obj, &obj_info1, |
| sizeof(TEE_ObjectInfo)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, |
| obj_info1.dataSize, ==, block_size * num_blocks)) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_get_obj_info(&sess, obj, &obj_info2, |
| sizeof(TEE_ObjectInfo)))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, |
| obj_info1.dataSize, ==, obj_info2.dataSize)) |
| goto exit; |
| |
| for (n = 0; n < num_blocks; n++) { |
| uint8_t br[block_size]; |
| uint32_t count; |
| |
| memset(block, n, block_size); |
| |
| Do_ADBG_Log("reading %zu", n); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_read(&sess, obj, br, sizeof(br), &count))) |
| goto exit; |
| if (!ADBG_EXPECT_BUFFER(c, block, block_size, br, count)) |
| goto exit; |
| } |
| |
| /* clean */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) |
| goto exit; |
| |
| exit: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6018) |
| |
| static void xtest_tee_test_6019_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Session sess; |
| TEEC_Session sess2; |
| uint32_t orig; |
| uint32_t obj; |
| uint32_t obj2; |
| uint8_t out[10] = { 0 }; |
| uint32_t count; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) |
| return; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| xtest_teec_open_session(&sess2, &storage2_ta_uuid, NULL, |
| &orig))) |
| goto exit3; |
| |
| /* TA #1 creates a persistent object */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | |
| TEE_DATA_FLAG_OVERWRITE, 0, data_00, |
| sizeof(data_00), &obj, storage_id))) |
| goto exit2; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit1; |
| |
| /* TA #2 creates a persistent object */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_create(&sess2, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | |
| TEE_DATA_FLAG_OVERWRITE, 0, data_01, |
| sizeof(data_01), &obj2, storage_id))) |
| goto exit1; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess2, obj2))) |
| goto exit; |
| |
| /* TA #1 open and read */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) |
| goto exit; |
| |
| /* verify */ |
| (void)ADBG_EXPECT_BUFFER(c, data_00, 10, out, count); |
| |
| /* TA #2 open and read */ |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, |
| fs_open(&sess2, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, &obj2, storage_id))) |
| goto exit; |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess2, obj2, out, 10, &count))) |
| goto exit; |
| |
| /* verify */ |
| (void)ADBG_EXPECT_BUFFER(c, data_01, 10, out, count); |
| |
| exit: |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess2, obj2)); |
| exit1: |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); |
| exit2: |
| TEEC_CloseSession(&sess2); |
| exit3: |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6019) |
| |
| /* |
| * According to the GP spec V1.1, the object_id in create/open/rename |
| * functions is not allowed to reside in the shared memory. |
| * |
| * The function below replicates fs_open/fs_create/fs_rename but using |
| * specific commands to ask the TA to use the client object ID buffer |
| * from the shared memory when accessing the object through target APIs. |
| * The TA is not expected to use such references and gets killed by the TEE. |
| */ |
| static TEEC_Result fs_access_with_bad_object_id_ref(TEEC_Session *sess, |
| uint32_t command, |
| void *id, uint32_t id_size, |
| uint32_t flags, |
| uint32_t attr, |
| void *data, uint32_t data_size, |
| uint32_t *obj, |
| uint32_t storage_id) |
| { |
| TEEC_Operation op = TEEC_OPERATION_INITIALIZER; |
| TEEC_Result res; |
| uint32_t org; |
| |
| switch (command) { |
| case TA_STORAGE_CMD_OPEN_ID_IN_SHM: |
| op.params[0].tmpref.buffer = id; |
| op.params[0].tmpref.size = id_size; |
| op.params[1].value.a = flags; |
| op.params[1].value.b = 0; |
| op.params[2].value.a = storage_id; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, |
| TEEC_VALUE_INOUT, |
| TEEC_VALUE_INPUT, |
| TEEC_NONE); |
| break; |
| case TA_STORAGE_CMD_CREATE_ID_IN_SHM: |
| op.params[0].tmpref.buffer = id; |
| op.params[0].tmpref.size = id_size; |
| op.params[1].value.a = flags; |
| op.params[1].value.b = 0; |
| op.params[2].value.a = attr; |
| op.params[2].value.b = storage_id; |
| op.params[3].tmpref.buffer = data; |
| op.params[3].tmpref.size = data_size; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, |
| TEEC_VALUE_INOUT, |
| TEEC_VALUE_INPUT, |
| TEEC_MEMREF_TEMP_INPUT); |
| break; |
| case TA_STORAGE_CMD_CREATEOVER_ID_IN_SHM: |
| op.params[0].tmpref.buffer = id; |
| op.params[0].tmpref.size = id_size; |
| op.params[1].value.a = storage_id; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, |
| TEEC_VALUE_INPUT, |
| TEEC_NONE, TEEC_NONE); |
| break; |
| case TA_STORAGE_CMD_RENAME_ID_IN_SHM: |
| op.params[0].value.a = *obj; |
| op.params[1].tmpref.buffer = id; |
| op.params[1].tmpref.size = id_size; |
| |
| op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, |
| TEEC_MEMREF_TEMP_INPUT, |
| TEEC_NONE, TEEC_NONE); |
| break; |
| default: |
| return TEE_ERROR_GENERIC; |
| } |
| |
| res = TEEC_InvokeCommand(sess, command, &op, &org); |
| |
| switch (command) { |
| case TA_STORAGE_CMD_OPEN_ID_IN_SHM: |
| case TA_STORAGE_CMD_CREATE_ID_IN_SHM: |
| if (res == TEEC_SUCCESS) |
| *obj = op.params[1].value.b; |
| break; |
| default: |
| break; |
| } |
| |
| return res; |
| } |
| |
| static void xtest_tee_test_6020_single(ADBG_Case_t *c, uint32_t storage_id) |
| { |
| TEEC_Result res; |
| TEEC_Session sess; |
| uint32_t orig; |
| uint32_t obj; |
| |
| /* |
| * Invalid open request from the TA (object ID reference in SHM) |
| */ |
| res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) |
| return; |
| |
| res = fs_create(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | |
| TEE_DATA_FLAG_OVERWRITE, |
| 0, |
| data_00, sizeof(data_00), |
| &obj, |
| storage_id); |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) |
| goto exit1; |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) |
| goto exit1; |
| |
| res = fs_access_with_bad_object_id_ref(&sess, |
| TA_STORAGE_CMD_OPEN_ID_IN_SHM, |
| file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | |
| TEE_DATA_FLAG_OVERWRITE, |
| 0, |
| NULL, 0, |
| &obj, |
| storage_id); |
| |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, res); |
| |
| /* |
| * Invalid create-overwrite request from the TA (object ID reference in SHM) |
| */ |
| TEEC_CloseSession(&sess); |
| res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) |
| return; |
| |
| res = fs_access_with_bad_object_id_ref(&sess, |
| TA_STORAGE_CMD_CREATEOVER_ID_IN_SHM, |
| file_01, sizeof(file_01), |
| 0, |
| 0, |
| NULL, 0, |
| NULL, |
| storage_id); |
| |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, res); |
| |
| /* |
| * Invalid rename request from the TA (object ID reference in SHM) |
| */ |
| TEEC_CloseSession(&sess); |
| res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) |
| return; |
| |
| res = fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | |
| TEE_DATA_FLAG_OVERWRITE, |
| &obj, |
| storage_id); |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) |
| goto exit1; |
| |
| res = fs_access_with_bad_object_id_ref(&sess, |
| TA_STORAGE_CMD_RENAME_ID_IN_SHM, |
| file_01, sizeof(file_01) - 1, |
| 0, |
| 0, |
| NULL, 0, |
| &obj, |
| 0); |
| |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, res); |
| |
| /* |
| * Invalid creation request from the TA (object ID reference in SHM) |
| */ |
| TEEC_CloseSession(&sess); |
| res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) |
| return; |
| |
| res = fs_open(&sess, file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | |
| TEE_DATA_FLAG_OVERWRITE, |
| &obj, |
| storage_id); |
| |
| if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) |
| goto exit1; |
| |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); |
| |
| res = fs_access_with_bad_object_id_ref(&sess, |
| TA_STORAGE_CMD_CREATE_ID_IN_SHM, |
| file_01, sizeof(file_01), |
| TEE_DATA_FLAG_ACCESS_WRITE | |
| TEE_DATA_FLAG_ACCESS_WRITE_META | |
| TEE_DATA_FLAG_OVERWRITE, |
| 0, |
| data_00, sizeof(data_00), |
| &obj, |
| storage_id); |
| |
| ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, res); |
| |
| return; |
| exit1: |
| ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); |
| TEEC_CloseSession(&sess); |
| } |
| |
| DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6020) |
| |
| ADBG_CASE_DEFINE(regression, 6001, xtest_tee_test_6001, |
| "Test TEE_CreatePersistentObject"); |
| ADBG_CASE_DEFINE(regression, 6002, xtest_tee_test_6002, |
| "Test TEE_OpenPersistentObject"); |
| ADBG_CASE_DEFINE(regression, 6003, xtest_tee_test_6003, |
| "Test TEE_ReadObjectData"); |
| ADBG_CASE_DEFINE(regression, 6004, xtest_tee_test_6004, |
| "Test TEE_WriteObjectData"); |
| ADBG_CASE_DEFINE(regression, 6005, xtest_tee_test_6005, |
| "Test TEE_SeekObjectData"); |
| ADBG_CASE_DEFINE(regression, 6006, xtest_tee_test_6006, |
| "Test TEE_CloseAndDeletePersistentObject"); |
| ADBG_CASE_DEFINE(regression, 6007, xtest_tee_test_6007, |
| "Test TEE_TruncateObjectData"); |
| ADBG_CASE_DEFINE(regression, 6008, xtest_tee_test_6008, |
| "Test TEE_RenamePersistentObject"); |
| ADBG_CASE_DEFINE(regression, 6009, xtest_tee_test_6009, |
| "Test TEE Internal API Persistent Object Enumeration Functions"); |
| ADBG_CASE_DEFINE(regression, 6010, xtest_tee_test_6010, "Test Storage"); |
| |
| #ifdef WITH_GP_TESTS |
| ADBG_CASE_DEFINE(regression, 6011, xtest_tee_test_6011, |
| "Test TEE GP TTA DS init objects"); |
| #endif |
| |
| ADBG_CASE_DEFINE(regression, 6012, xtest_tee_test_6012, |
| "Test TEE GP TTA DS init objects"); |
| ADBG_CASE_DEFINE(regression, 6013, xtest_tee_test_6013, |
| "Key usage in Persistent objects"); |
| ADBG_CASE_DEFINE(regression, 6014, xtest_tee_test_6014, |
| "Loop on Persistent objects"); |
| ADBG_CASE_DEFINE(regression, 6015, xtest_tee_test_6015, "Storage isolation"); |
| ADBG_CASE_DEFINE(regression, 6016, xtest_tee_test_6016, "Storage concurency"); |
| ADBG_CASE_DEFINE(regression, 6017, xtest_tee_test_6017, |
| "Test Persistent objects info"); |
| ADBG_CASE_DEFINE(regression, 6018, xtest_tee_test_6018, "Large object"); |
| ADBG_CASE_DEFINE(regression, 6019, xtest_tee_test_6019, "Storage independence"); |
| ADBG_CASE_DEFINE(regression, 6020, xtest_tee_test_6020, |
| "Object IDs in SHM (negative)"); |