diff --git a/Android.mk b/Android.mk index b0eea21dc..91576522c 100644 --- a/Android.mk +++ b/Android.mk @@ -102,7 +102,8 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/host/xtest \ $(LOCAL_PATH)/ta/aes_perf/include \ $(LOCAL_PATH)/ta/socket/include \ $(LOCAL_PATH)/ta/sdp_basic/include \ - $(LOCAL_PATH)/ta/tpm_log_test/include + $(LOCAL_PATH)/ta/tpm_log_test/include \ + $(LOCAL_PATH)/ta/ocall/include # Include configuration file generated by OP-TEE OS (CFG_* macros) LOCAL_CFLAGS += -I $(TA_DEV_KIT_DIR)/host_include -include conf.h diff --git a/host/xtest/CMakeLists.txt b/host/xtest/CMakeLists.txt index 461d387e8..37c71e0ef 100644 --- a/host/xtest/CMakeLists.txt +++ b/host/xtest/CMakeLists.txt @@ -106,6 +106,10 @@ if (CFG_PKCS11_TA) list (APPEND SRC pkcs11_1000.c) endif() +if (CFG_OCALL) + list (APPEND SRC regression_1100.c) +endif() + ################################################################################ # Built binary ################################################################################ diff --git a/host/xtest/Makefile b/host/xtest/Makefile index 297cd1254..00136ad92 100644 --- a/host/xtest/Makefile +++ b/host/xtest/Makefile @@ -100,6 +100,10 @@ CFLAGS += -I$(OPTEE_PKCS11_TA_HEADERS) LDFLAGS += -L$(OPTEE_CLIENT_EXPORT)/lib -lckteec endif +ifeq ($(CFG_OCALL),y) +srcs += regression_1100.c +endif + objs := $(patsubst %.c,$(out-dir)/xtest/%.o, $(srcs)) CFLAGS += -I./ @@ -128,6 +132,7 @@ CFLAGS += -I../../ta/socket/include CFLAGS += -I../../ta/sdp_basic/include CFLAGS += -I../../ta/tpm_log_test/include CFLAGS += -I../../ta/supp_plugin/include +CFLAGS += -I../../ta/ocall/include TA_DIR ?= /lib/optee_armtz CFLAGS += -DTA_DIR=\"$(TA_DIR)\" diff --git a/host/xtest/regression_1100.c b/host/xtest/regression_1100.c new file mode 100644 index 000000000..894d294d4 --- /dev/null +++ b/host/xtest/regression_1100.c @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Microsoft Corporation + */ + +#include +#include +#include +#include +#include + +#include "xtest_helpers.h" +#include "xtest_test.h" + +static ADBG_Case_t *local_c; + +static bool no_ecall_params_no_ocall_params_reply; +static bool no_ecall_params_ocall_value_params_reply; +static bool no_ecall_params_ocall_memref_params_reply; +static bool null_memref_params_reply; +static bool null_memref_params_mixed_reply; +static bool null_memref_params_invalid_reply; +static bool session_open_ocall_reply; +static bool session_open_ocall_premature_ctx_finalize_reply; + +static TEEC_Result +ocall_handler(TEEC_UUID *taUUID, uint32_t commandId, uint32_t paramTypes, + TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT], + void *ctx_data, void *session_data) +{ + uint32_t exp_pt; + + ADBG_EXPECT_EQUAL(local_c, &ocall_ta_uuid, taUUID, + sizeof(*taUUID)); + + switch (commandId) { + case CA_OCALL_CMD_NO_ECALL_PARAMS_NO_OCALL_PARAMS: + no_ecall_params_no_ocall_params_reply = true; + + exp_pt = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + break; + + case CA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_VALUE_PARAMS: + no_ecall_params_ocall_value_params_reply = true; + + exp_pt = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INOUT, + TEEC_VALUE_OUTPUT, TEEC_VALUE_INPUT); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + + ADBG_EXPECT_COMPARE_UNSIGNED(local_c, + params[0].value.a, ==, ocall_test_val1_in_a); + ADBG_EXPECT_COMPARE_UNSIGNED(local_c, + params[0].value.b, ==, ocall_test_val1_in_b); + ADBG_EXPECT_COMPARE_UNSIGNED(local_c, + params[1].value.a, ==, ocall_test_val2_in_a); + ADBG_EXPECT_COMPARE_UNSIGNED(local_c, + params[1].value.b, ==, ocall_test_val2_in_b); + ADBG_EXPECT_COMPARE_UNSIGNED(local_c, + params[3].value.a, ==, ocall_test_val4_in_a); + ADBG_EXPECT_COMPARE_UNSIGNED(local_c, + params[3].value.b, ==, ocall_test_val4_in_b); + + params[1].value.a = ocall_test_val2_out_a; + params[1].value.b = ocall_test_val2_out_b; + params[2].value.a = ocall_test_val3_out_a; + params[2].value.b = ocall_test_val3_out_b; + break; + + case CA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_MEMREF_PARAMS: + no_ecall_params_ocall_memref_params_reply = true; + + exp_pt = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INOUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_INPUT); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + + ADBG_EXPECT_BUFFER(local_c, ocall_test_buf1_in, + sizeof(ocall_test_buf1_in), + params[0].tmpref.buffer, + params[0].tmpref.size); + ADBG_EXPECT_BUFFER(local_c, ocall_test_buf2_in, + sizeof(ocall_test_buf2_in), + params[1].tmpref.buffer, + params[1].tmpref.size); + ADBG_EXPECT_BUFFER(local_c, ocall_test_buf4_in, + sizeof(ocall_test_buf4_in), + params[3].tmpref.buffer, + params[3].tmpref.size); + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(local_c, + params[1].tmpref.size, ==, + sizeof(ocall_test_buf2_out)) || + !ADBG_EXPECT_COMPARE_UNSIGNED(local_c, + params[2].tmpref.size, ==, + sizeof(ocall_test_buf3_out))) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(params[1].tmpref.buffer, ocall_test_buf2_out, + sizeof(ocall_test_buf2_out)); + memcpy(params[2].tmpref.buffer, ocall_test_buf3_out, + sizeof(ocall_test_buf3_out)); + break; + + case CA_OCALL_CMD_PREMATURE_SESSION_CLOSE: + exp_pt = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + ADBG_EXPECT_NOT_NULL(local_c, session_data); + TEEC_CloseSession((TEEC_Session *)session_data); + break; + + case CA_OCALL_CMD_PREMATURE_CONTEXT_FINALIZE: + exp_pt = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + ADBG_EXPECT_NOT_NULL(local_c, ctx_data); + TEEC_FinalizeContext((TEEC_Context *)ctx_data); + break; + + case CA_OCALL_CMD_NULL_MEMREF_PARAMS: + null_memref_params_reply = true; + + exp_pt = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INOUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + ADBG_EXPECT_BUFFER(local_c, NULL, 0, params[0].tmpref.buffer, + params[0].tmpref.size); + ADBG_EXPECT_BUFFER(local_c, NULL, 0, params[1].tmpref.buffer, + params[1].tmpref.size); + ADBG_EXPECT_BUFFER(local_c, NULL, 0, params[2].tmpref.buffer, + params[2].tmpref.size); + break; + + case CA_OCALL_CMD_NULL_MEMREF_PARAMS_MIXED: + null_memref_params_mixed_reply = true; + + exp_pt = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INOUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_VALUE_OUTPUT); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + + ADBG_EXPECT_BUFFER(local_c, NULL, 0, params[0].tmpref.buffer, + params[0].tmpref.size); + ADBG_EXPECT_BUFFER(local_c, ocall_test_buf2_in, + sizeof(ocall_test_buf2_in), + params[1].tmpref.buffer, + params[1].tmpref.size); + ADBG_EXPECT_BUFFER(local_c, NULL, 0, params[2].tmpref.buffer, + params[2].tmpref.size); + + memcpy(params[1].tmpref.buffer, ocall_test_buf2_out, + sizeof(ocall_test_buf2_out)); + params[3].value.a = ocall_test_val5_out_a; + params[3].value.b = ocall_test_val5_out_b; + break; + + case CA_OCALL_CMD_NULL_MEMREF_PARAMS_INVALID: + /* + * Should not be called; the OCALL should fail to send at the + * TA due to invalid parameters. + */ + null_memref_params_invalid_reply = true; + break; + + case CA_OCALL_CMD_OPEN_SESSION_OCALL: + session_open_ocall_reply = true; + + exp_pt = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + break; + + case CA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE: + session_open_ocall_premature_ctx_finalize_reply = true; + + exp_pt = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + ADBG_EXPECT(local_c, exp_pt, paramTypes); + ADBG_EXPECT_NOT_NULL(local_c, ctx_data); + TEEC_FinalizeContext((TEEC_Context *)ctx_data); + break; + + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + + return TEEC_SUCCESS; +} + +static bool test_premature_session_close_prologue(ADBG_Case_t *c) +{ + TEEC_Context ctx = {}; + TEEC_Session sess = {}; + uint32_t ret_orig = 0; + bool ret = false; + + TEEC_ContextSettingOCall ocall_setting = { ocall_handler, &ctx }; + TEEC_ContextSetting ctx_settings[] = { + { .type = TEEC_CONTEXT_SETTING_OCALL, + .u.ocall = &ocall_setting } + }; + + TEEC_SessionSettingData data_setting = { &sess }; + TEEC_SessionSetting sess_settings[] = { + { .type = TEEC_SESSION_SETTING_DATA, + .u.data = &data_setting } + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InitializeContext2(xtest_tee_name, &ctx, ctx_settings, 1))) + goto no_ctx; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_OpenSession2(&ctx, &sess, &ocall_ta_uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &ret_orig, + sess_settings, 1))) + goto no_sess; + + if (!ADBG_EXPECT_TEEC_RESULT(c, + TEE_ERROR_GENERIC, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_PREMATURE_SESSION_CLOSE, + NULL, &ret_orig))) + goto no_invoke; + + ret = true; + + /* The session will have been closed by the OCALL handler */ + goto no_sess; + +no_invoke: + TEEC_CloseSession(&sess); +no_sess: + TEEC_FinalizeContext(&ctx); +no_ctx: + return ret; +} + +static bool test_premature_context_finalize_prologue(ADBG_Case_t *c) +{ + TEEC_Context ctx = {}; + TEEC_Session sess = {}; + uint32_t ret_orig = 0; + bool ret = false; + + TEEC_ContextSettingOCall ocall_setting = { ocall_handler, &ctx }; + TEEC_ContextSetting ctx_settings[] = { + { .type = TEEC_CONTEXT_SETTING_OCALL, + .u.ocall = &ocall_setting } + }; + + TEEC_SessionSettingData data_setting = { &sess }; + TEEC_SessionSetting sess_settings[] = { + { .type = TEEC_SESSION_SETTING_DATA, + .u.data = &data_setting } + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InitializeContext2(xtest_tee_name, &ctx, ctx_settings, 1))) + goto no_ctx; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_OpenSession2(&ctx, &sess, &ocall_ta_uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &ret_orig, + sess_settings, 1))) + goto no_sess; + + if (!ADBG_EXPECT_TEEC_RESULT(c, + TEE_ERROR_GENERIC, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_PREMATURE_CONTEXT_FINALIZE, + NULL, &ret_orig))) + goto no_invoke; + + ret = true; + + /* The context will have been finalized by the OCALL handler */ + goto no_ctx; + +no_invoke: + TEEC_CloseSession(&sess); +no_sess: + TEEC_FinalizeContext(&ctx); +no_ctx: + return ret; +} + +static bool test_ocall_during_session_open(ADBG_Case_t *c) +{ + TEEC_Context ctx = {}; + TEEC_Session sess = {}; + uint32_t ret_orig = 0; + TEEC_Operation op = { 0 }; + bool ret = false; + + TEEC_ContextSettingOCall ocall_setting = { ocall_handler, &ctx }; + TEEC_ContextSetting ctx_settings[] = { + { .type = TEEC_CONTEXT_SETTING_OCALL, + .u.ocall = &ocall_setting } + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InitializeContext2(xtest_tee_name, &ctx, ctx_settings, 1))) + return false; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + op.params[0].value.a = TA_OCALL_CMD_OPEN_SESSION_OCALL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_OpenSession(&ctx, &sess, &ocall_ta_uuid, TEEC_LOGIN_PUBLIC, + NULL, &op, &ret_orig))) + goto no_sess; + + /* Executes after the OCALL handler */ + ADBG_EXPECT_BOOLEAN(c, true, session_open_ocall_reply); + + TEEC_CloseSession(&sess); + ret = true; + +no_sess: + TEEC_FinalizeContext(&ctx); + return ret; +} + +static bool text_ctx_finalize_during_session_open_ocall(ADBG_Case_t *c) +{ + TEEC_Context ctx = {}; + TEEC_Session sess = {}; + uint32_t ret_orig = 0; + TEEC_Operation op = { 0 }; + bool ret = false; + + TEEC_ContextSettingOCall ocall_setting = { ocall_handler, &ctx }; + TEEC_ContextSetting ctx_settings[] = { + { .type = TEEC_CONTEXT_SETTING_OCALL, + .u.ocall = &ocall_setting } + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InitializeContext2(xtest_tee_name, &ctx, ctx_settings, 1))) + return false; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + op.params[0].value.a = + TA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE; + + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_GENERIC, + TEEC_OpenSession(&ctx, &sess, &ocall_ta_uuid, TEEC_LOGIN_PUBLIC, + NULL, &op, &ret_orig))) + goto no_sess; + + /* Executes after the OCALL handler */ + ADBG_EXPECT_BOOLEAN(c, true, + session_open_ocall_premature_ctx_finalize_reply); + + /* + * The OCALL handler will have closed the session by finalizing the + * context. + */ + ret = true; + +no_sess: + TEEC_FinalizeContext(&ctx); + return ret; +} + +static void xtest_tee_test_1101(ADBG_Case_t *c) +{ + TEEC_Context ctx = {}; + TEEC_Session sess = {}; + uint32_t ret_orig = 0; + + TEEC_ContextSettingOCall ocall_setting = { ocall_handler, &ctx }; + TEEC_ContextSetting ctx_settings[] = { + { .type = TEEC_CONTEXT_SETTING_OCALL, + .u.ocall = &ocall_setting } + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InitializeContext2(xtest_tee_name, &ctx, ctx_settings, 1))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_OpenSession(&ctx, &sess, &ocall_ta_uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &ret_orig))) + goto out; + + local_c = c; + + Do_ADBG_BeginSubCase(c, "OCALL without parameters"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_NO_ECALL_PARAMS_NO_OCALL_PARAMS, + NULL, &ret_orig)); + ADBG_EXPECT_BOOLEAN(c, true, no_ecall_params_no_ocall_params_reply); + Do_ADBG_EndSubCase(c, "OCALL without parameters"); + + Do_ADBG_BeginSubCase(c, "OCALL with value parameters (in/inout/out/in)"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_VALUE_PARAMS, + NULL, &ret_orig)); + ADBG_EXPECT_BOOLEAN(c, true, no_ecall_params_ocall_value_params_reply); + Do_ADBG_EndSubCase(c, "OCALL with value parameters (in/inout/out/in)"); + + Do_ADBG_BeginSubCase(c, "OCALL with memref parameters (in/inout/out/in)"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_MEMREF_PARAMS, + NULL, &ret_orig)); + ADBG_EXPECT_BOOLEAN(c, true, no_ecall_params_ocall_memref_params_reply); + Do_ADBG_EndSubCase(c, "OCALL with memref parameters (in/inout/out/in)"); + + Do_ADBG_BeginSubCase(c, "Close session during OCALL"); + if (test_premature_session_close_prologue(c)) + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_GET_PREMATURE_SESSION_CLOSE_STATUS, + NULL, &ret_orig)); + Do_ADBG_EndSubCase(c, "Close session during OCALL"); + + Do_ADBG_BeginSubCase(c, "Finalize context during OCALL"); + if (test_premature_context_finalize_prologue(c)) + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_GET_PREMATURE_CONTEXT_FINALIZE_STATUS, + NULL, &ret_orig)); + Do_ADBG_EndSubCase(c, "Finalize context during OCALL"); + + Do_ADBG_BeginSubCase(c, "NULL memref param"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_NULL_MEMREF_PARAMS, + NULL, &ret_orig)); + ADBG_EXPECT_BOOLEAN(c, true, null_memref_params_reply); + Do_ADBG_EndSubCase(c, "NULL memref param"); + + Do_ADBG_BeginSubCase(c, "NULL memref param (mixed params)"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_NULL_MEMREF_PARAMS_MIXED, + NULL, &ret_orig)); + ADBG_EXPECT_BOOLEAN(c, true, null_memref_params_mixed_reply); + Do_ADBG_EndSubCase(c, "NULL memref param (mixed params)"); + + Do_ADBG_BeginSubCase(c, "NULL memref param (invalid params)"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_NULL_MEMREF_PARAMS_INVALID, + NULL, &ret_orig)); + ADBG_EXPECT_BOOLEAN(c, false, null_memref_params_invalid_reply); + Do_ADBG_EndSubCase(c, "NULL memref param (invalid params)"); + + Do_ADBG_BeginSubCase(c, "OCALL during session open"); + ADBG_EXPECT_BOOLEAN(c, true, test_ocall_during_session_open(c)); + Do_ADBG_EndSubCase(c, "OCALL during session open"); + + Do_ADBG_BeginSubCase(c, "Finalize context during session open OCALL"); + ADBG_EXPECT_BOOLEAN(c, true, + text_ctx_finalize_during_session_open_ocall(c)); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, + TA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE_STATUS, + NULL, &ret_orig)); + Do_ADBG_EndSubCase(c, "Finalize context during session open OCALL"); + + TEEC_CloseSession(&sess); + +out: + TEEC_FinalizeContext(&ctx); +} +ADBG_CASE_DEFINE(regression, 1100, xtest_tee_test_1101, + "Test OCALLs"); diff --git a/host/xtest/xtest_test.c b/host/xtest/xtest_test.c index b8120576b..bfd1a7bbb 100644 --- a/host/xtest/xtest_test.c +++ b/host/xtest/xtest_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include <__tee_isocket_defines.h> #include <__tee_tcpsocket_defines.h> @@ -198,3 +199,4 @@ const TEEC_UUID socket_ta_uuid = TA_SOCKET_UUID; const TEEC_UUID sdp_basic_ta_uuid = TA_SDP_BASIC_UUID; const TEEC_UUID tpm_log_test_ta_uuid = TA_TPM_LOG_TEST_UUID; const TEEC_UUID supp_plugin_test_ta_uuid = TA_SUPP_PLUGIN_UUID; +const TEEC_UUID ocall_ta_uuid = TA_OCALL_UUID; diff --git a/host/xtest/xtest_test.h b/host/xtest/xtest_test.h index 892c7f7fa..90415f376 100644 --- a/host/xtest/xtest_test.h +++ b/host/xtest/xtest_test.h @@ -8,6 +8,7 @@ #define XTEST_TEST_H #include #include +#include #ifdef CFG_PKCS11_TA #include @@ -134,6 +135,7 @@ extern const TEEC_UUID socket_ta_uuid; extern const TEEC_UUID sdp_basic_ta_uuid; extern const TEEC_UUID tpm_log_test_ta_uuid; extern const TEEC_UUID supp_plugin_test_ta_uuid; +extern const TEEC_UUID ocall_ta_uuid; extern char *xtest_tee_name; #endif /*XTEST_TEST_H*/ diff --git a/ta/CMakeLists.txt b/ta/CMakeLists.txt index 28721c3f2..ea00fe320 100644 --- a/ta/CMakeLists.txt +++ b/ta/CMakeLists.txt @@ -21,4 +21,5 @@ target_include_directories(${PROJECT_NAME} INTERFACE storage_benchmark/include INTERFACE tpm_log_test/include INTERFACE supp_plugin/include + INTERFACE ocall/include ) diff --git a/ta/Makefile b/ta/Makefile index e85533cb0..ee7860754 100644 --- a/ta/Makefile +++ b/ta/Makefile @@ -37,6 +37,10 @@ ifeq ($(CFG_SECURE_DATA_PATH),y) TA_DIRS += sdp_basic endif +ifeq ($(CFG_OCALL),y) +TA_DIRS += ocall +endif + .PHONY: all all: ta diff --git a/ta/ocall/Android.mk b/ta/ocall/Android.mk new file mode 100644 index 000000000..ba9309a2e --- /dev/null +++ b/ta/ocall/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 616906e4-2fa8-44c6-a698-2cf2d35b99f9.ta +include $(BUILD_OPTEE_MK) diff --git a/ta/ocall/Makefile b/ta/ocall/Makefile new file mode 100644 index 000000000..f131bf753 --- /dev/null +++ b/ta/ocall/Makefile @@ -0,0 +1,2 @@ +BINARY = 616906e4-2fa8-44c6-a698-2cf2d35b99f9 +include ../ta_common.mk diff --git a/ta/ocall/include/ta_ocall.h b/ta/ocall/include/ta_ocall.h new file mode 100644 index 000000000..bc5af98e1 --- /dev/null +++ b/ta/ocall/include/ta_ocall.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Microsoft Corporation + */ + +#ifndef TA_OCALL_H +#define TA_OCALL_H + +#include + +extern bool g_close_session_entry_point_called; +extern bool g_test_premature_context_finalize_during_session_open_ocall_ok; + +TEE_Result test_no_ecall_params_no_ocall_params(uint32_t param_types); +TEE_Result test_no_ecall_params_ocall_value_params(uint32_t param_types); +TEE_Result test_no_ecall_params_ocall_memref_params(uint32_t param_types); +TEE_Result test_null_memref_params(uint32_t param_types); +TEE_Result test_null_memref_params_mixed(uint32_t param_types); +TEE_Result test_null_memref_params_invalid(uint32_t param_types); +TEE_Result test_premature_session_close(uint32_t param_types); +TEE_Result get_premature_session_close_status(uint32_t param_types); +TEE_Result test_premature_context_finalize(uint32_t param_types); +TEE_Result get_premature_context_finalize_status(uint32_t param_types); +TEE_Result get_premature_context_finalize_during_session_open_ocall_status(uint32_t param_types); + +#endif /* TA_OCALL_H */ diff --git a/ta/ocall/include/ta_ocall_data.h b/ta/ocall/include/ta_ocall_data.h new file mode 100644 index 000000000..394f00b8b --- /dev/null +++ b/ta/ocall/include/ta_ocall_data.h @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Microsoft Corporation + */ + +#ifndef TA_OCALL_DATA_H +#define TA_OCALL_DATA_H + +/* + * Test values (in/out specified from the TA's point of view) + */ + +static const uint32_t ocall_test_val1_in_a = 0; +static const uint32_t ocall_test_val1_in_b = 0xffffffff; + +static const uint32_t ocall_test_val2_in_a = 0xacd0281f; +static const uint32_t ocall_test_val2_in_b = 104826; + +static const uint32_t ocall_test_val2_out_a = 9; +static const uint32_t ocall_test_val2_out_b = 0x98f5d1ce; + +static const uint32_t ocall_test_val3_out_a = 0x71fae3db; +static const uint32_t ocall_test_val3_out_b = 10394; + +static const uint32_t ocall_test_val4_in_a = 0xfffffffe; +static const uint32_t ocall_test_val4_in_b = 1; + +static const uint32_t ocall_test_val5_out_a = 0xfd185; +static const uint32_t ocall_test_val5_out_b = 0; + +/* + * Test buffers (in/out specified from the TA's point of view) + */ + +/* 1 byte */ +static const char ocall_test_buf1_in[] = { 0xe3 }; + +/* 8 bytes */ +static const char ocall_test_buf2_in[] = { + 0x5a, 0xc9, 0x5f, 0x4a, 0x79, 0x39, 0x88, 0xb8 +}; +static const char ocall_test_buf2_out[] = { + 0x37, 0x52, 0x26, 0xab, 0x57, 0x9f, 0xc9, 0xd1 +}; + +/* 16 bytes */ +static const char ocall_test_buf3_out[] = { + 0x03, 0x63, 0x23, 0xc2, 0x80, 0x5c, 0x5b, 0xd6, + 0xcf, 0xaf, 0xfd, 0x7c, 0x2f, 0x4d, 0xcf, 0x47, +}; + +/* 32 bytes */ +static const char ocall_test_buf4_in[] = { + 0xc8, 0x62, 0x93, 0x9b, 0x37, 0xd5, 0x3a, 0xd9, + 0x65, 0xb1, 0xea, 0x36, 0x97, 0x7d, 0x36, 0x30, + 0xff, 0x94, 0x00, 0xa3, 0xc1, 0x59, 0x7f, 0x34, + 0x47, 0x5d, 0x8e, 0x77, 0xe8, 0x2a, 0x83, 0x06, +}; + +#endif /* TA_OCALL_DATA_H */ diff --git a/ta/ocall/include/ta_ocall_test.h b/ta/ocall/include/ta_ocall_test.h new file mode 100644 index 000000000..099b7f75b --- /dev/null +++ b/ta/ocall/include/ta_ocall_test.h @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Microsoft Corporation + */ + +#ifndef TA_OCALL_TEST_H +#define TA_OCALL_TEST_H + +/* This UUID was generated with uuidgen */ +#define TA_OCALL_UUID { 0x616906e4, 0x2fa8, 0x44c6, \ + { 0xa6, 0x98, 0x2c, 0xf2, 0xd3, 0x5b, 0x99, 0xf9 } } + +/* Command IDs understood by the TA */ +#define TA_OCALL_CMD_NO_ECALL_PARAMS_NO_OCALL_PARAMS 0 +#define TA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_VALUE_PARAMS 1 +#define TA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_MEMREF_PARAMS 2 +#define TA_OCALL_CMD_NULL_MEMREF_PARAMS 3 +#define TA_OCALL_CMD_NULL_MEMREF_PARAMS_MIXED 4 +#define TA_OCALL_CMD_NULL_MEMREF_PARAMS_INVALID 5 +#define TA_OCALL_CMD_PREMATURE_SESSION_CLOSE 6 +#define TA_OCALL_CMD_GET_PREMATURE_SESSION_CLOSE_STATUS 7 +#define TA_OCALL_CMD_PREMATURE_CONTEXT_FINALIZE 8 +#define TA_OCALL_CMD_GET_PREMATURE_CONTEXT_FINALIZE_STATUS 9 +#define TA_OCALL_CMD_OPEN_SESSION_OCALL 10 +#define TA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE 11 +#define TA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE_STATUS 12 + +/* Command IDs understood by the CA */ +#define CA_OCALL_CMD_NO_ECALL_PARAMS_NO_OCALL_PARAMS \ + TA_OCALL_CMD_NO_ECALL_PARAMS_NO_OCALL_PARAMS +#define CA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_VALUE_PARAMS \ + TA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_VALUE_PARAMS +#define CA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_MEMREF_PARAMS \ + TA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_MEMREF_PARAMS +#define CA_OCALL_CMD_NULL_MEMREF_PARAMS \ + TA_OCALL_CMD_NULL_MEMREF_PARAMS +#define CA_OCALL_CMD_NULL_MEMREF_PARAMS_MIXED \ + TA_OCALL_CMD_NULL_MEMREF_PARAMS_MIXED +#define CA_OCALL_CMD_NULL_MEMREF_PARAMS_INVALID \ + TA_OCALL_CMD_NULL_MEMREF_PARAMS_INVALID +#define CA_OCALL_CMD_PREMATURE_SESSION_CLOSE \ + TA_OCALL_CMD_PREMATURE_SESSION_CLOSE +#define CA_OCALL_CMD_PREMATURE_CONTEXT_FINALIZE \ + TA_OCALL_CMD_PREMATURE_CONTEXT_FINALIZE +#define CA_OCALL_CMD_OPEN_SESSION_OCALL \ + TA_OCALL_CMD_OPEN_SESSION_OCALL +#define CA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE \ + TA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE + +#endif /* TA_OCALL_TEST_H */ diff --git a/ta/ocall/include/user_ta_header_defines.h b/ta/ocall/include/user_ta_header_defines.h new file mode 100644 index 000000000..92968a7d8 --- /dev/null +++ b/ta/ocall/include/user_ta_header_defines.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Microsoft Corporation + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include + +#define TA_UUID TA_OCALL_UUID + +#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_MULTI_SESSION | \ + TA_FLAG_INSTANCE_KEEP_ALIVE) + +#define TA_STACK_SIZE (4 * 1024) +#define TA_DATA_SIZE (64 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/ta/ocall/sub.mk b/ta/ocall/sub.mk new file mode 100644 index 000000000..08dc4c01f --- /dev/null +++ b/ta/ocall/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +srcs-y += ta_entry.c +srcs-y += ta_ocall.c diff --git a/ta/ocall/ta_entry.c b/ta/ocall/ta_entry.c new file mode 100644 index 000000000..036085c34 --- /dev/null +++ b/ta/ocall/ta_entry.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Microsoft Corporation + */ + +#include +#include +#include +#include +#include +#include + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + DMSG("TA_CreateEntryPoint"); + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ + DMSG("TA_DestroyEntryPoint"); +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext __unused) +{ + TEE_Result res; + uint32_t eorig; + + const uint32_t expected_pt1 = TEE_PARAM_TYPES( + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + const uint32_t expected_pt2 = TEE_PARAM_TYPES( + TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + + DMSG("TA_OpenSessionEntryPoint"); + + if (nParamTypes == expected_pt1) + return TEE_SUCCESS; + + if (nParamTypes != expected_pt2) + return TEE_ERROR_BAD_PARAMETERS; + + switch (pParams[0].value.a) { + case TA_OCALL_CMD_OPEN_SESSION_OCALL: + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_OPEN_SESSION_OCALL, 0, + NULL, &eorig); + if (res != TEE_SUCCESS) + EMSG("TEE_InvokeCACommand failed with code 0x%x origin 0x%x", + res, eorig); + break; + + case TA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE: + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE, + 0, NULL, &eorig); + if (res != TEE_ERROR_TARGET_DEAD || eorig != TEE_ORIGIN_COMMS) { + EMSG("TEE_InvokeCACommand failed with wrong code 0x%x and/or origin 0x%x", + res, eorig); + return res; + } + + g_test_premature_context_finalize_during_session_open_ocall_ok = true; + + break; + + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return res; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; + g_close_session_entry_point_called = true; + DMSG("TA_CloseSessionEntryPoint"); +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + (void)pSessionContext; + (void)pParams; + + switch (nCommandID) { + case TA_OCALL_CMD_NO_ECALL_PARAMS_NO_OCALL_PARAMS: + return test_no_ecall_params_no_ocall_params(nParamTypes); + + case TA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_VALUE_PARAMS: + return test_no_ecall_params_ocall_value_params(nParamTypes); + + case TA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_MEMREF_PARAMS: + return test_no_ecall_params_ocall_memref_params(nParamTypes); + + case TA_OCALL_CMD_PREMATURE_SESSION_CLOSE: + return test_premature_session_close(nParamTypes); + + case TA_OCALL_CMD_GET_PREMATURE_SESSION_CLOSE_STATUS: + return get_premature_session_close_status(nParamTypes); + + case TA_OCALL_CMD_PREMATURE_CONTEXT_FINALIZE: + return test_premature_context_finalize(nParamTypes); + + case TA_OCALL_CMD_GET_PREMATURE_CONTEXT_FINALIZE_STATUS: + return get_premature_context_finalize_status(nParamTypes); + + case TA_OCALL_CMD_NULL_MEMREF_PARAMS: + return test_null_memref_params(nParamTypes); + + case TA_OCALL_CMD_NULL_MEMREF_PARAMS_MIXED: + return test_null_memref_params_mixed(nParamTypes); + + case TA_OCALL_CMD_NULL_MEMREF_PARAMS_INVALID: + return test_null_memref_params_invalid(nParamTypes); + + case TA_OCALL_CMD_OPEN_SESSION_OCALL_PREMATURE_CONTEXT_FINALIZE_STATUS: + return get_premature_context_finalize_during_session_open_ocall_status(nParamTypes); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/ta/ocall/ta_ocall.c b/ta/ocall/ta_ocall.c new file mode 100644 index 000000000..39d80be68 --- /dev/null +++ b/ta/ocall/ta_ocall.c @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Microsoft Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +bool g_close_session_entry_point_called; +bool g_test_premature_context_finalize_during_session_open_ocall_ok; + +TEE_Result test_no_ecall_params_no_ocall_params(uint32_t param_types) +{ + TEE_Result res; + uint32_t eorig; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_NO_ECALL_PARAMS_NO_OCALL_PARAMS, + 0, NULL, &eorig); + if (res != TEE_SUCCESS) + EMSG("TEE_InvokeCACommand failed with code 0x%x origin 0x%x", + res, eorig); + + return res; +} + +TEE_Result test_no_ecall_params_ocall_value_params(uint32_t param_types) +{ + TEE_Param ocall_params[TEE_NUM_PARAMS]; + TEE_Result res; + uint32_t eorig; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + const uint32_t ocall_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_INPUT); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ocall_params[0].value.a = ocall_test_val1_in_a; + ocall_params[0].value.b = ocall_test_val1_in_b; + + ocall_params[1].value.a = ocall_test_val2_in_a; + ocall_params[1].value.b = ocall_test_val2_in_b; + + ocall_params[3].value.a = ocall_test_val4_in_a; + ocall_params[3].value.b = ocall_test_val4_in_b; + + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_VALUE_PARAMS, + ocall_pt, ocall_params, &eorig); + if (res != TEE_SUCCESS) { + EMSG("TEE_InvokeCACommand failed with code 0x%x origin 0x%x", + res, eorig); + return res; + } + + if (ocall_params[1].value.a != ocall_test_val2_out_a || + ocall_params[1].value.b != ocall_test_val2_out_b || + ocall_params[2].value.a != ocall_test_val3_out_a || + ocall_params[2].value.b != ocall_test_val3_out_b) + return TEE_ERROR_BAD_PARAMETERS; + + return res; +} + +TEE_Result test_no_ecall_params_ocall_memref_params(uint32_t param_types) +{ + TEE_Param ocall_params[TEE_NUM_PARAMS]; + TEE_Result res; + uint32_t eorig; + + char ocall_test_buf2_in_local[8]; + char ocall_test_buf3_in[16] = { 0 }; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + const uint32_t ocall_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(ocall_test_buf2_in_local, ocall_test_buf2_in, + sizeof(ocall_test_buf2_in_local)); + + ocall_params[0].memref.buffer = (void *)ocall_test_buf1_in; + ocall_params[0].memref.size = sizeof(ocall_test_buf1_in); + + ocall_params[1].memref.buffer = (void *)ocall_test_buf2_in_local; + ocall_params[1].memref.size = sizeof(ocall_test_buf2_in_local); + + ocall_params[2].memref.buffer = (void *)ocall_test_buf3_in; + ocall_params[2].memref.size = sizeof(ocall_test_buf3_in); + + ocall_params[3].memref.buffer = (void *)ocall_test_buf4_in; + ocall_params[3].memref.size = sizeof(ocall_test_buf4_in); + + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_NO_ECALL_PARAMS_OCALL_MEMREF_PARAMS, + ocall_pt, ocall_params, &eorig); + if (res != TEE_SUCCESS) { + EMSG("TEE_InvokeCACommand failed with code 0x%x origin 0x%x", + res, eorig); + return res; + } + + if (ocall_params[1].memref.size != sizeof(ocall_test_buf2_out) || + ocall_params[2].memref.size != sizeof(ocall_test_buf3_out)) + return TEE_ERROR_BAD_PARAMETERS; + + if (TEE_MemCompare(ocall_params[1].memref.buffer, ocall_test_buf2_out, + sizeof(ocall_test_buf2_out))) + return TEE_ERROR_BAD_PARAMETERS; + + if (TEE_MemCompare(ocall_params[2].memref.buffer, ocall_test_buf3_out, + sizeof(ocall_test_buf3_out))) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +static bool g_test_premature_session_close_ok; +TEE_Result test_premature_session_close(uint32_t param_types) +{ + TEE_Result res; + uint32_t eorig; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_PREMATURE_SESSION_CLOSE, + 0, NULL, &eorig); + if (res != TEE_ERROR_TARGET_DEAD || eorig != TEE_ORIGIN_COMMS) { + EMSG("TEE_InvokeCACommand failed with wrong code 0x%x and/or origin 0x%x", + res, eorig); + return res; + } + + g_test_premature_session_close_ok = true; + + return TEE_SUCCESS; +} + +TEE_Result get_premature_session_close_status(uint32_t param_types) +{ + TEE_Result res; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (g_close_session_entry_point_called && + g_test_premature_session_close_ok) + res = TEE_SUCCESS; + else + res = TEE_ERROR_BAD_STATE; + + g_close_session_entry_point_called = false; + g_test_premature_session_close_ok = false; + + return res; +} + +static bool g_test_premature_context_finalize_ok; +TEE_Result test_premature_context_finalize(uint32_t param_types) +{ + TEE_Result res; + uint32_t eorig; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_PREMATURE_CONTEXT_FINALIZE, + 0, NULL, &eorig); + if (res != TEE_ERROR_TARGET_DEAD || eorig != TEE_ORIGIN_COMMS) { + EMSG("TEE_InvokeCACommand failed with wrong code 0x%x and/or origin 0x%x", + res, eorig); + return res; + } + + g_test_premature_context_finalize_ok = true; + + return TEE_SUCCESS; +} + +TEE_Result get_premature_context_finalize_status(uint32_t param_types) +{ + TEE_Result res; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (g_close_session_entry_point_called && + g_test_premature_context_finalize_ok) + res = TEE_SUCCESS; + else + res = TEE_ERROR_BAD_STATE; + + g_close_session_entry_point_called = false; + g_test_premature_context_finalize_ok = false; + + return res; +} + +TEE_Result test_null_memref_params(uint32_t param_types) +{ + TEE_Param ocall_params[TEE_NUM_PARAMS]; + TEE_Result res; + uint32_t eorig; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + const uint32_t ocall_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ocall_params[0].memref.buffer = NULL; + ocall_params[0].memref.size = 0; + + ocall_params[1].memref.buffer = NULL; + ocall_params[1].memref.size = 0; + + ocall_params[2].memref.buffer = NULL; + ocall_params[2].memref.size = 0; + + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_NULL_MEMREF_PARAMS, + ocall_pt, ocall_params, &eorig); + if (res != TEE_SUCCESS) { + EMSG("TEE_InvokeCACommand failed with code 0x%x origin 0x%x", + res, eorig); + return res; + } + + return TEE_SUCCESS; +} + +TEE_Result test_null_memref_params_mixed(uint32_t param_types) +{ + TEE_Param ocall_params[TEE_NUM_PARAMS]; + TEE_Result res; + uint32_t eorig; + + char ocall_test_buf2_in_local[8]; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + const uint32_t ocall_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(ocall_test_buf2_in_local, ocall_test_buf2_in, + sizeof(ocall_test_buf2_in_local)); + + ocall_params[0].memref.buffer = NULL; + ocall_params[0].memref.size = 0; + + ocall_params[1].memref.buffer = (void *)ocall_test_buf2_in_local; + ocall_params[1].memref.size = sizeof(ocall_test_buf2_in_local); + + ocall_params[2].memref.buffer = NULL; + ocall_params[2].memref.size = 0; + + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_NULL_MEMREF_PARAMS_MIXED, + ocall_pt, ocall_params, &eorig); + if (res != TEE_SUCCESS) { + EMSG("TEE_InvokeCACommand failed with code 0x%x origin 0x%x", + res, eorig); + return res; + } + + if (ocall_params[1].memref.size != sizeof(ocall_test_buf2_out)) + return TEE_ERROR_BAD_PARAMETERS; + + if (TEE_MemCompare(ocall_params[1].memref.buffer, ocall_test_buf2_out, + sizeof(ocall_test_buf2_out))) + return TEE_ERROR_BAD_PARAMETERS; + + if (ocall_params[3].value.a != ocall_test_val5_out_a || + ocall_params[3].value.b != ocall_test_val5_out_b) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +TEE_Result test_null_memref_params_invalid(uint32_t param_types) +{ + TEE_Param ocall_params[TEE_NUM_PARAMS]; + TEE_Result res; + uint32_t eorig; + + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + const uint32_t ocall_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ocall_params[0].memref.buffer = NULL; + ocall_params[0].memref.size = UINT32_MAX; + + ocall_params[1].memref.buffer = (void *)ocall_params; + ocall_params[1].memref.size = 0; + + res = TEE_InvokeCACommand(TEE_TIMEOUT_INFINITE, + CA_OCALL_CMD_NULL_MEMREF_PARAMS_INVALID, + ocall_pt, ocall_params, &eorig); + if (res != TEE_ERROR_BAD_PARAMETERS || eorig != TEE_ORIGIN_API) { + EMSG("TEE_InvokeCACommand failed with wrong code 0x%x and/or origin 0x%x", + res, eorig); + return res; + } + + return TEE_SUCCESS; +} + +TEE_Result +get_premature_context_finalize_during_session_open_ocall_status(uint32_t param_types) +{ + const uint32_t expected_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != expected_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (g_test_premature_context_finalize_during_session_open_ocall_ok) { + g_test_premature_context_finalize_during_session_open_ocall_ok = false; + return TEE_SUCCESS; + } + + return TEE_ERROR_BAD_STATE; +}