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/ta/CMakeLists.txt b/ta/CMakeLists.txt
index 6f0d904..28721c3 100644
--- a/ta/CMakeLists.txt
+++ b/ta/CMakeLists.txt
@@ -20,4 +20,5 @@
 	INTERFACE socket/include
 	INTERFACE storage_benchmark/include
 	INTERFACE tpm_log_test/include
+	INTERFACE supp_plugin/include
 )
diff --git a/ta/Makefile b/ta/Makefile
index c26e18f..e85533c 100644
--- a/ta/Makefile
+++ b/ta/Makefile
@@ -30,7 +30,8 @@
 	   storage_benchmark \
 	   sha_perf \
 	   aes_perf \
-	   socket
+	   socket \
+	   supp_plugin
 
 ifeq ($(CFG_SECURE_DATA_PATH),y)
 TA_DIRS += sdp_basic
diff --git a/ta/supp_plugin/Android.mk b/ta/supp_plugin/Android.mk
new file mode 100644
index 0000000..1633640
--- /dev/null
+++ b/ta/supp_plugin/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH := $(call my-dir)
+
+local_module := 380231ac-fb99-47ad-a689-9e017eb6e78a
+include $(BUILD_OPTEE_MK)
diff --git a/ta/supp_plugin/Makefile b/ta/supp_plugin/Makefile
new file mode 100644
index 0000000..5c1965b
--- /dev/null
+++ b/ta/supp_plugin/Makefile
@@ -0,0 +1,2 @@
+BINARY = 380231ac-fb99-47ad-a689-9e017eb6e78a
+include ../ta_common.mk
diff --git a/ta/supp_plugin/include/ta_supp_plugin.h b/ta/supp_plugin/include/ta_supp_plugin.h
new file mode 100644
index 0000000..fd05255
--- /dev/null
+++ b/ta/supp_plugin/include/ta_supp_plugin.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2021 Open Mobile Platform LLC
+ */
+
+#ifndef TA_SUPP_PLUGIN_H
+#define TA_SUPP_PLUGIN_H
+
+#define TA_SUPP_PLUGIN_UUID { 0x380231ac, 0xfb99, 0x47ad, \
+	{ 0xa6, 0x89, 0x9e, 0x01, 0x7e, 0xb6, 0xe7, 0x8a } }
+
+#define TA_SUPP_PLUGIN_CMD_PASS_VALUES	0
+#define TA_SUPP_PLUGIN_CMD_WRITE_ARR	1
+#define TA_SUPP_PLUGIN_CMD_GET_ARR	2
+#define TA_SUPP_PLUGIN_CMD_BAD_UUID	3
+#define TA_SUPP_PLUGIN_CMD_BAD_IN_DATA	4
+#define TA_SUPP_PLUGIN_CMD_BAD_IN_LEN	5
+#define TA_SUPP_PLUGIN_CMD_UNKNOWN_UUID	6
+
+#endif /* TA_SUPP_PLUGIN_H */
diff --git a/ta/supp_plugin/include/user_ta_header_defines.h b/ta/supp_plugin/include/user_ta_header_defines.h
new file mode 100644
index 0000000..0003c92
--- /dev/null
+++ b/ta/supp_plugin/include/user_ta_header_defines.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2021 Open Mobile Platform LLC
+ */
+
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+#include <ta_supp_plugin.h>
+#include <user_ta_header.h>
+
+#define TA_UUID		TA_SUPP_PLUGIN_UUID
+#define TA_FLAGS	0
+#define TA_STACK_SIZE	(8 * 1024)
+#define TA_DATA_SIZE	(32 * 1024)
+
+#endif /* USER_TA_HEADER_DEFINES_H */
diff --git a/ta/supp_plugin/sub.mk b/ta/supp_plugin/sub.mk
new file mode 100644
index 0000000..dd01461
--- /dev/null
+++ b/ta/supp_plugin/sub.mk
@@ -0,0 +1,3 @@
+global-incdirs-y += include
+global-incdirs-y += ../../host/supp_plugin/include
+srcs-y += ta_entry.c
diff --git a/ta/supp_plugin/ta_entry.c b/ta/supp_plugin/ta_entry.c
new file mode 100644
index 0000000..33bdbff
--- /dev/null
+++ b/ta/supp_plugin/ta_entry.c
@@ -0,0 +1,180 @@
+//SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021 Open Mobile Platform LLC
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ta_supp_plugin.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <test_supp_plugin.h>
+#include <trace.h>
+
+static const TEE_UUID uuid = TEST_PLUGIN_UUID;
+
+TEE_Result TA_CreateEntryPoint(void)
+{
+	return TEE_SUCCESS;
+}
+
+void TA_DestroyEntryPoint(void)
+{
+}
+
+TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes __unused,
+				    TEE_Param pParams[4] __unused,
+				    void **ppSessionContext __unused)
+{
+	/* check the plugin was loaded */
+	return tee_invoke_supp_plugin(&uuid, TEST_PLUGIN_CMD_PING, 0, NULL, 0,
+				      NULL);
+}
+
+void TA_CloseSessionEntryPoint(void *pSessionContext __unused)
+{
+}
+
+static TEE_Result pass_values(uint32_t param_types,
+			     TEE_Param params[TEE_NUM_PARAMS])
+{
+	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT,
+					  TEE_PARAM_TYPE_VALUE_INPUT,
+					  TEE_PARAM_TYPE_NONE,
+					  TEE_PARAM_TYPE_NONE);
+	TEE_Result res = TEE_ERROR_GENERIC;
+	size_t outlen = 0;
+	struct add_op {
+		uint32_t a;
+		uint32_t b;
+	} values = { 0 };
+
+	if (exp_pt != param_types)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	values.a = params[0].value.a;
+	values.b = params[0].value.b;
+
+	res = tee_invoke_supp_plugin(&uuid, TEST_PLUGIN_CMD_PASS_VALUES,
+				     params[1].value.a, (void *)&values,
+				     sizeof(struct add_op), &outlen);
+	params[0].value.a = values.a;
+
+	return res;
+}
+
+static TEE_Result write_array(uint32_t param_types,
+			      TEE_Param params[TEE_NUM_PARAMS])
+{
+	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
+					  TEE_PARAM_TYPE_NONE,
+					  TEE_PARAM_TYPE_NONE);
+	TEE_Result res = TEE_ERROR_GENERIC;
+	size_t outlen = 0;
+	char *buf = NULL;
+
+	if (exp_pt != param_types)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	buf = malloc(params[0].memref.size);
+	if (!buf)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	/*
+	 * Plugins use a same buffer for input and output data.
+	 * Make copy of input data to avoid erasing of it by the output.
+	 *
+	 * Output data contain file name the input data will be stored.
+	 */
+	memcpy(buf, params[0].memref.buffer, params[0].memref.size);
+	res = tee_invoke_supp_plugin(&uuid, TEST_PLUGIN_CMD_WRITE_ARR, 0, buf,
+				     params[0].memref.size, &outlen);
+	memcpy(params[1].memref.buffer, buf, outlen);
+	free(buf);
+
+	return res;
+}
+
+static TEE_Result get_array(uint32_t param_types,
+			    TEE_Param params[TEE_NUM_PARAMS])
+{
+	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
+					  TEE_PARAM_TYPE_VALUE_OUTPUT,
+					  TEE_PARAM_TYPE_NONE,
+					  TEE_PARAM_TYPE_NONE);
+	TEE_Result res = TEE_ERROR_GENERIC;
+	size_t outlen = 0;
+
+	if (exp_pt != param_types)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	res = tee_invoke_supp_plugin(&uuid, TEST_PLUGIN_CMD_GET_ARR, 0,
+				     params[0].memref.buffer,
+				     params[0].memref.size,
+				     &outlen);
+	params[1].value.a = (uint32_t)outlen;
+
+	return res;
+}
+
+static TEE_Result bad_input_uuid(uint32_t param_types __unused,
+				 TEE_Param params[TEE_NUM_PARAMS] __unused)
+{
+	char data[32] = {  };
+	size_t inlen = sizeof(data);
+
+	return tee_invoke_supp_plugin(NULL, 0, 0, data, inlen, NULL);
+}
+
+static TEE_Result bad_input_data(uint32_t param_types __unused,
+				 TEE_Param params[TEE_NUM_PARAMS] __unused)
+{
+	return tee_invoke_supp_plugin(&uuid, 0, 0, NULL, 10, NULL);
+}
+
+static TEE_Result bad_input_inlen(uint32_t param_types __unused,
+				  TEE_Param params[TEE_NUM_PARAMS] __unused)
+{
+	char data[32] = {  };
+
+	return tee_invoke_supp_plugin(&uuid, 0, 0, data, 0, NULL);
+}
+
+static TEE_Result call_unknown_plugin(uint32_t param_types __unused,
+				      TEE_Param params[TEE_NUM_PARAMS]
+				      __unused)
+{
+	const TEE_UUID nulluuid = {  };
+	char data[32] = {  };
+	size_t inlen = sizeof(data);
+
+	return tee_invoke_supp_plugin(&nulluuid, 0, 0, data, inlen, NULL);
+}
+
+TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext __unused,
+				      uint32_t nCommandID,
+				      uint32_t nParamTypes,
+				      TEE_Param pParams[4])
+{
+	switch (nCommandID) {
+	case TA_SUPP_PLUGIN_CMD_PASS_VALUES:
+		return pass_values(nParamTypes, pParams);
+	case TA_SUPP_PLUGIN_CMD_WRITE_ARR:
+		return write_array(nParamTypes, pParams);
+	case TA_SUPP_PLUGIN_CMD_GET_ARR:
+		return get_array(nParamTypes, pParams);
+	case TA_SUPP_PLUGIN_CMD_BAD_UUID:
+		return bad_input_uuid(nParamTypes, pParams);
+	case TA_SUPP_PLUGIN_CMD_BAD_IN_DATA:
+		return bad_input_data(nParamTypes, pParams);
+	case TA_SUPP_PLUGIN_CMD_BAD_IN_LEN:
+		return bad_input_inlen(nParamTypes, pParams);
+	case TA_SUPP_PLUGIN_CMD_UNKNOWN_UUID:
+		return call_unknown_plugin(nParamTypes, pParams);
+	default:
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+}