regression: add tests for the supplicant plugin framework
Add test cases for checking functionality of supplicant plugins:
- Ability to pass values and arrays to/from a plugin
- Right handle situations with bad input parameters
- Right handle situations with calling an unknown plugin
Signed-off-by: Aleksandr Anisimov <a.anisimov@omprussia.ru>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/host/supp_plugin/CMakeLists.txt b/host/supp_plugin/CMakeLists.txt
new file mode 100644
index 0000000..63972bb
--- /dev/null
+++ b/host/supp_plugin/CMakeLists.txt
@@ -0,0 +1,9 @@
+project (f07bfc66-958c-4a15-99c0-260e4e7375dd.plugin C)
+
+set (CFG_TEE_PLUGIN_LOAD_PATH "/usr/lib/tee-supplicant/plugins/")
+set (CMAKE_SHARED_LIBRARY_PREFIX "")
+
+add_library(${PROJECT_NAME} SHARED test_supp_plugin.c)
+target_include_directories(${PROJECT_NAME} PRIVATE ./include)
+
+install (TARGETS ${PROJECT_NAME} DESTINATION ${CFG_TEE_PLUGIN_LOAD_PATH})
diff --git a/host/supp_plugin/Makefile b/host/supp_plugin/Makefile
new file mode 100644
index 0000000..621f8de
--- /dev/null
+++ b/host/supp_plugin/Makefile
@@ -0,0 +1,22 @@
+PLUGIN_UUID = f07bfc66-958c-4a15-99c0-260e4e7375dd
+
+PLUGIN = $(PLUGIN_UUID).plugin
+PLUGIN_SRS = $(wildcard ./*.c)
+PLUGIN_OBJ = $(patsubst %.c, $(O)/supp_plugin/%.o, $(PLUGIN_SRS))
+PLUGIN_INCLUDES_DIR = $(CURDIR)/include $(OPTEE_CLIENT_EXPORT)/include
+
+PLUGIN_INCLUDES = $(addprefix -I, $(PLUGIN_INCLUDES_DIR))
+PLUGIN_CCFLAGS = -Wall -fPIC
+PLUGIN_LDFLAGS = -shared
+
+$(O)/supp_plugin/$(PLUGIN): $(PLUGIN_OBJ)
+ $(q)$(CROSS_COMPILE)gcc $(PLUGIN_LDFLAGS) $(PLUGIN_OBJ) -o $@
+
+$(O)/supp_plugin/%.o: $(CURDIR)/%.c
+ $(q)mkdir -p $(O)/supp_plugin
+ @echo ' CC $<'
+ $(q)$(CROSS_COMPILE)gcc $(PLUGIN_INCLUDES) $(PLUGIN_CCFLAGS) -c $< -o $@
+
+.PHONY: clean
+clean:
+ $(q)$(RM) -rf $(O)/supp_plugin/
diff --git a/host/supp_plugin/include/test_supp_plugin.h b/host/supp_plugin/include/test_supp_plugin.h
new file mode 100644
index 0000000..2e7e961
--- /dev/null
+++ b/host/supp_plugin/include/test_supp_plugin.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2021 Open Mobile Platform LLC
+ */
+
+#ifndef TEST_SUPP_PLUGIN_H
+#define TEST_SUPP_PLUGIN_H
+
+#define TEST_PLUGIN_UUID { 0xf07bfc66, 0x958c, 0x4a15, \
+ { 0x99, 0xc0, 0x26, 0x0e, 0x4e, 0x73, 0x75, 0xdd } }
+
+#define TEST_PLUGIN_CMD_PING 0
+#define TEST_PLUGIN_CMD_PASS_VALUES 1
+#define TEST_PLUGIN_CMD_WRITE_ARR 2
+#define TEST_PLUGIN_CMD_GET_ARR 3
+
+#endif /* TEST_SUPP_PLUGIN_H */
diff --git a/host/supp_plugin/test_supp_plugin.c b/host/supp_plugin/test_supp_plugin.c
new file mode 100644
index 0000000..6b90b17
--- /dev/null
+++ b/host/supp_plugin/test_supp_plugin.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021, Open Mobile Platform LLC
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <tee_plugin_method.h>
+#include <test_supp_plugin.h>
+#include <unistd.h>
+
+static TEEC_Result pass_values(unsigned int sub_cmd, void *data,
+ size_t data_len, size_t *out_len)
+{
+ struct add_op {
+ uint32_t a;
+ uint32_t b;
+ } *values = NULL;
+
+ values = (struct add_op *)data;
+ *out_len = sizeof(uint32_t);
+
+ if (sub_cmd == '+')
+ values->a = values->a + values->b;
+ else
+ values->a = values->a - values->b;
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result write_test_arr(unsigned int sub_cmd, void *data,
+ size_t data_len, size_t *out_len)
+{
+ (void)sub_cmd;
+ (void)out_len;
+
+ int fd = -1;
+ int n = -1;
+ char template[] = "/tmp/testplugin-XXXXXX";
+ char fname[PATH_MAX] = { 0 };
+
+ strcpy(fname, template);
+
+ fd = mkstemp(fname);
+ if (fd < 0)
+ return TEEC_ERROR_GENERIC;
+
+ n = write(fd, (const void *)data, data_len);
+ if (n < 0) {
+ close(fd);
+ return TEEC_ERROR_GENERIC;
+ }
+
+ *out_len = sizeof(template);
+ memcpy(data, (const void *)fname, *out_len);
+ close(fd);
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result get_test_arr(unsigned int sub_cmd, void *data,
+ size_t data_len, size_t *out_len)
+{
+ (void)sub_cmd;
+ char test_arr[] = "Array from plugin";
+ size_t test_size = sizeof(test_arr);
+
+ if (data_len < test_size)
+ return TEEC_ERROR_GENERIC;
+
+ memcpy(data, test_arr, test_size);
+ *out_len = test_size;
+
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result test_plugin_invoke(unsigned int cmd, unsigned int sub_cmd,
+ void *data, size_t data_len,
+ size_t *out_len)
+{
+ switch (cmd) {
+ case TEST_PLUGIN_CMD_PING:
+ return TEEC_SUCCESS;
+ case TEST_PLUGIN_CMD_PASS_VALUES:
+ return pass_values(sub_cmd, data, data_len, out_len);
+ case TEST_PLUGIN_CMD_WRITE_ARR:
+ return write_test_arr(sub_cmd, data, data_len, out_len);
+ case TEST_PLUGIN_CMD_GET_ARR:
+ return get_test_arr(sub_cmd, data, data_len, out_len);
+ default:
+ break;
+ }
+
+ return TEEC_ERROR_NOT_SUPPORTED;
+}
+
+struct plugin_method plugin_method = {
+ .name = "test",
+ .uuid = TEST_PLUGIN_UUID,
+ .invoke = test_plugin_invoke,
+};
diff --git a/host/xtest/CMakeLists.txt b/host/xtest/CMakeLists.txt
index b77b2fb..461d387 100644
--- a/host/xtest/CMakeLists.txt
+++ b/host/xtest/CMakeLists.txt
@@ -115,6 +115,7 @@
target_include_directories(${PROJECT_NAME}
PRIVATE .
+ PRIVATE ../supp_plugin/include
PRIVATE adbg/include
PRIVATE ${OPTEE_TEST_SDK}/host_include
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
diff --git a/host/xtest/Makefile b/host/xtest/Makefile
index 3ca8a28..297cd12 100644
--- a/host/xtest/Makefile
+++ b/host/xtest/Makefile
@@ -104,6 +104,7 @@
CFLAGS += -I./
CFLAGS += -I./adbg/include
+CFLAGS += -I../supp_plugin/include
CFLAGS += -I$(out-dir)/xtest
CFLAGS += -I$(OPTEE_CLIENT_EXPORT)/include
@@ -126,6 +127,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
TA_DIR ?= /lib/optee_armtz
CFLAGS += -DTA_DIR=\"$(TA_DIR)\"
diff --git a/host/xtest/regression_1000.c b/host/xtest/regression_1000.c
index 5e3c773..a819838 100644
--- a/host/xtest/regression_1000.c
+++ b/host/xtest/regression_1000.c
@@ -4,6 +4,7 @@
* Copyright (c) 2014, STMicroelectronics International N.V.
*/
+#include <errno.h>
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
@@ -29,9 +30,12 @@
#include <ta_sims_keepalive_test.h>
#include <ta_concurrent.h>
#include <ta_tpm_log_test.h>
+#include <ta_supp_plugin.h>
#include <sdp_basic.h>
#include <pta_secstor_ta_mgmt.h>
+#include <test_supp_plugin.h>
+
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
@@ -2345,3 +2349,139 @@
}
ADBG_CASE_DEFINE(regression, 1032, xtest_tee_test_1032,
"Register read-only shared memory");
+
+static void xtest_tee_test_1033(ADBG_Case_t *c)
+{
+ TEEC_Session session = { };
+ uint32_t ret_orig = 0;
+
+ /* TA will ping the test plugin during open session operation */
+ if (!ADBG_EXPECT_TEEC_SUCCESS(c,
+ xtest_teec_open_session(&session, &supp_plugin_test_ta_uuid,
+ NULL, &ret_orig)))
+ return;
+
+ Do_ADBG_BeginSubCase(c, "Pass values to/from a plugin");
+ {
+ TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
+
+ op.params[0].value.a = 20;
+ op.params[0].value.b = 10;
+ op.params[1].value.a = '+';
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT,
+ TEEC_VALUE_INPUT, TEEC_NONE,
+ TEEC_NONE);
+
+ ADBG_EXPECT_TEEC_SUCCESS(c,
+ TEEC_InvokeCommand(&session,
+ TA_SUPP_PLUGIN_CMD_PASS_VALUES, &op,
+ &ret_orig));
+ ADBG_EXPECT(c, 30, op.params[0].value.a);
+
+ /* reassign, because the values was changed during previous op */
+ op.params[0].value.a = 20;
+ op.params[0].value.b = 10;
+ op.params[1].value.a = '-';
+ ADBG_EXPECT_TEEC_SUCCESS(c,
+ TEEC_InvokeCommand(&session,
+ TA_SUPP_PLUGIN_CMD_PASS_VALUES, &op,
+ &ret_orig));
+ ADBG_EXPECT(c, 10, op.params[0].value.a);
+ }
+ Do_ADBG_EndSubCase(c, "Pass values to/from a plugin");
+
+ Do_ADBG_BeginSubCase(c, "Pass array to a plugin");
+ {
+ TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
+ char to_plugin[] = "Plugin must write this array to the test file";
+ char from_file[sizeof(to_plugin)] = { };
+ char test_fname[PATH_MAX] = { };
+ FILE *fp = NULL;
+
+ op.params[0].tmpref.buffer = to_plugin;
+ op.params[0].tmpref.size = sizeof(to_plugin);
+ op.params[1].tmpref.buffer = test_fname;
+ op.params[1].tmpref.size = PATH_MAX;
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
+ TEEC_MEMREF_TEMP_OUTPUT,
+ TEEC_NONE, TEEC_NONE);
+
+ ADBG_EXPECT_TEEC_SUCCESS(c,
+ TEEC_InvokeCommand(&session,
+ TA_SUPP_PLUGIN_CMD_WRITE_ARR,
+ &op, &ret_orig));
+
+ /*
+ * Test file is generated by the plugin with the help of
+ * mkstemp(). Check the file content here.
+ */
+ fp = fopen(test_fname, "r");
+ ADBG_EXPECT_NOT_NULL(c, fp);
+ if (fp) {
+ fread(from_file, sizeof(char), sizeof(to_plugin), fp);
+ ADBG_EXPECT_EQUAL(c, to_plugin, from_file, sizeof(to_plugin));
+ fclose(fp);
+ remove(test_fname);
+ }
+ }
+ Do_ADBG_EndSubCase(c, "Pass array to a plugin");
+
+ Do_ADBG_BeginSubCase(c, "Get array from a plugin");
+ {
+ TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
+ char from_plugin[64] = { };
+ char expected_arr[] = "Array from plugin";
+ size_t expectes_size = sizeof(expected_arr);
+
+ op.params[0].tmpref.buffer = from_plugin;
+ op.params[0].tmpref.size = sizeof(from_plugin);
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT,
+ TEEC_VALUE_OUTPUT, TEEC_NONE,
+ TEEC_NONE);
+ ADBG_EXPECT_TEEC_SUCCESS(c,
+ TEEC_InvokeCommand(&session,
+ TA_SUPP_PLUGIN_CMD_GET_ARR, &op,
+ &ret_orig));
+ ADBG_EXPECT(c, expectes_size, op.params[1].value.a);
+ ADBG_EXPECT_EQUAL(c, expected_arr, from_plugin, expectes_size);
+ }
+ Do_ADBG_EndSubCase(c, "Get array from a plugin");
+
+ Do_ADBG_BeginSubCase(c, "Not allow bad input to a plugin");
+ {
+ TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
+
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_BAD_PARAMETERS,
+ TEEC_InvokeCommand(&session,
+ TA_SUPP_PLUGIN_CMD_BAD_UUID, &op,
+ &ret_orig));
+ ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_BAD_PARAMETERS,
+ TEEC_InvokeCommand(&session,
+ TA_SUPP_PLUGIN_CMD_BAD_IN_DATA, &op,
+ &ret_orig));
+ ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_BAD_PARAMETERS,
+ TEEC_InvokeCommand(&session,
+ TA_SUPP_PLUGIN_CMD_BAD_IN_LEN, &op,
+ &ret_orig));
+ }
+ Do_ADBG_EndSubCase(c, "Not allow bad input to a plugin");
+
+ Do_ADBG_BeginSubCase(c, "Call an unknown plugin");
+ {
+ TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
+
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND,
+ TEEC_InvokeCommand(&session,
+ TA_SUPP_PLUGIN_CMD_UNKNOWN_UUID,
+ &op, &ret_orig));
+ }
+ Do_ADBG_EndSubCase(c, "Call an unknown plugin");
+
+ TEEC_CloseSession(&session);
+}
+ADBG_CASE_DEFINE(regression, 1033, xtest_tee_test_1033,
+ "Test the supplicant plugin framework");
diff --git a/host/xtest/xtest_test.c b/host/xtest/xtest_test.c
index d13e96d..b812057 100644
--- a/host/xtest/xtest_test.c
+++ b/host/xtest/xtest_test.c
@@ -20,6 +20,7 @@
#include <ta_storage_benchmark.h>
#include <ta_socket.h>
#include <ta_tpm_log_test.h>
+#include <ta_supp_plugin.h>
#include <tee_api_defines.h>
#include <__tee_isocket_defines.h>
#include <__tee_tcpsocket_defines.h>
@@ -196,3 +197,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;
diff --git a/host/xtest/xtest_test.h b/host/xtest/xtest_test.h
index aed4ca0..892c7f7 100644
--- a/host/xtest/xtest_test.h
+++ b/host/xtest/xtest_test.h
@@ -133,6 +133,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 char *xtest_tee_name;
#endif /*XTEST_TEST_H*/