[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/mt2712/dapc/include/dapc_public.h b/src/bsp/trustzone/optee/source/mt2xxx/mt2712/dapc/include/dapc_public.h
new file mode 100644
index 0000000..89e023c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/mt2712/dapc/include/dapc_public.h
@@ -0,0 +1,94 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#ifndef __TEE_DAPC_PUBLIC_H__
+#define __TEE_DAPC_PUBLIC_H__
+
+/******************************************************************************
+ * CONST
+ ******************************************************************************/
+typedef enum
+{
+ E_NO_PROTECTION = 0,
+ E_SEC_RW,
+ E_SEC_RW_NS_R,
+ E_FORBIDDEN,
+ E_MAX_APC_ATTR,
+ E_APC_ATTR_RESERVRD = 0x7FFFFFFF /* force enum to use 32 bits */
+} APC_ATTR;
+
+typedef enum
+{
+ E_DOMAIN_0 = 0,
+ E_DOMAIN_1,
+ E_DOMAIN_2,
+ E_DOMAIN_3,
+ E_MAX_DOMAIN,
+ E_MASK_DOM_RESERVRD = 0x7FFFFFFF /* force enum to use 32 bits */
+} E_MASK_DOM;
+
+
+/******************************************************************************
+ * API
+ ******************************************************************************/
+void dump_devapc(void);
+
+/*
+ * set_module_apc: set module permission on device apc.
+ * @module: the index of the moudle to specify permission
+ * @domain_num: domain index number (AP or MD domain)
+ * @permission_control: specified permission
+ * no return value.
+ */
+void set_module_apc(unsigned int module, E_MASK_DOM domain_num, APC_ATTR permission_control);
+
+/*
+ * set_master_transaction: set master transaction type on device apc.
+ * @master_index: the index of the master to set the transaction type
+ * @transaction_type: 1 for secure or 0 for non-secure
+ * @return value: 0 on success,
+ * -100 for devapc not correctly init,
+ * -1 for master index invalid,
+ * -2 for transaction type invalid
+ */
+int set_master_transaction(unsigned int master_index, unsigned int transaction_type);
+
+
+/* Index */
+#define INFRA_AO_DEVICE_APC_AO 14
+
+
+
+#endif // __TEE_DAPC_PUBLIC_H__
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/mt2712/dapc/libdapc.a b/src/bsp/trustzone/optee/source/mt2xxx/mt2712/dapc/libdapc.a
new file mode 100644
index 0000000..cdddeb6
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/mt2712/dapc/libdapc.a
Binary files differ
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/.gitignore b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/.gitignore
new file mode 100644
index 0000000..e90e7d0
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/.gitignore
@@ -0,0 +1,19 @@
+GPATH
+GRTAGS
+GSYMS
+GTAGS
+*.cmd
+*.d
+*.dmp
+*.elf
+*.lds
+*.map
+*.o
+*.swp
+*.ta
+cscope.*
+out/
+hello_world/host/optee_example_hello_world
+random/host/optee_example_random
+aes/host/optee_example_aes
+hotp/host/optee_example_hotp
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/CMakeLists.txt
new file mode 100644
index 0000000..b8879b8
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required (VERSION 3.2)
+project (optee_examples C)
+
+# https://cmake.org/Wiki/CMake_Useful_Variables
+set (CMAKE_TOOLCHAIN_FILE CMakeToolchain.txt)
+
+include(GNUInstallDirs)
+
+add_compile_options (-Wall)
+#add_compile_options (
+# -Wall -Wbad-function-cast -Wcast-align
+# -Werror-implicit-function-declaration -Wextra
+# -Wfloat-equal -Wformat-nonliteral -Wformat-security
+# -Wformat=2 -Winit-self -Wmissing-declarations
+# -Wmissing-format-attribute -Wmissing-include-dirs
+# -Wmissing-noreturn -Wmissing-prototypes -Wnested-externs
+# -Wpointer-arith -Wshadow -Wstrict-prototypes
+# -Wswitch-default -Wunsafe-loop-optimizations
+# -Wwrite-strings -Werror -fPIC
+#)
+
+find_program(CCACHE_FOUND ccache)
+if(CCACHE_FOUND)
+ set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
+ set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
+endif(CCACHE_FOUND)
+
+file(GLOB dirs *)
+foreach(dir ${dirs})
+ if(EXISTS ${dir}/CMakeLists.txt)
+ add_subdirectory(${dir})
+ endif()
+endforeach()
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/CMakeToolchain.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/CMakeToolchain.txt
new file mode 100644
index 0000000..3c10f45
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/CMakeToolchain.txt
@@ -0,0 +1 @@
+set (CMAKE_SYSTEM_NAME Linux)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/LICENSE b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/LICENSE
new file mode 100644
index 0000000..12e3c07
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/LICENSE
@@ -0,0 +1,27 @@
+Unless it has its own copyright/license embedded in its body, each source file
+is subject to the following license terms:
+
+Copyright (c) 2018, Linaro Limited
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/Makefile
new file mode 100644
index 0000000..4f4ed70
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/Makefile
@@ -0,0 +1,41 @@
+export V ?= 0
+
+$(warning OUTPUT_DIR:$(OUTPUT_DIR))
+OUTPUT_DIR ?= $(CURDIR)/out
+
+EXAMPLE_LIST := $(subst /,,$(dir $(wildcard */Makefile)))
+
+.PHONY: all
+all: examples prepare-for-rootfs
+
+.PHONY: clean
+clean: examples-clean prepare-for-rootfs-clean
+
+examples:
+ @for example in $(EXAMPLE_LIST); do \
+ $(MAKE) -C $$example O=$(OUTPUT_DIR)/$$example CROSS_COMPILE="$(HOST_CROSS_COMPILE)" || exit -1; \
+ done
+
+examples-clean:
+ @for example in $(EXAMPLE_LIST); do \
+ $(MAKE) -C $$example clean || exit -1; \
+ done
+
+prepare-for-rootfs: examples
+ @echo "Copying example CA and TA binaries to $(OUTPUT_DIR)..."
+ @mkdir -p $(OUTPUT_DIR)
+ @mkdir -p $(OUTPUT_DIR)/ta
+ @mkdir -p $(OUTPUT_DIR)/ca
+ @for example in $(EXAMPLE_LIST); do \
+ if [ -e $(OUTPUT_DIR)/$$example/host/optee_example_$$example ]; then \
+ cp -p $(OUTPUT_DIR)/$$example/host/optee_example_$$example $(OUTPUT_DIR)/ca/; \
+ fi; \
+ if [ -d $(OUTPUT_DIR)/$$example/ta/ ]; then \
+ cp -pr $(OUTPUT_DIR)/$$example/ta/*.ta $(OUTPUT_DIR)/ta/; \
+ fi; \
+ done
+
+prepare-for-rootfs-clean:
+ @rm -rf $(OUTPUT_DIR)/ta
+ @rm -rf $(OUTPUT_DIR)/ca
+ @rmdir --ignore-fail-on-non-empty $(OUTPUT_DIR) || test ! -e $(OUTPUT_DIR)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/README.md b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/README.md
new file mode 100644
index 0000000..fb96770
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/README.md
@@ -0,0 +1,42 @@
+# OP-TEE Sample Applications
+## Contents
+1. [Introduction](#1-introduction)
+2. [List of sample applications](#2-list-of-sample-applications)
+3. [How to build a Trusted Application](#3-how-to-build-a-trusted-application)
+
+
+## 1. Introduction
+This document describes the sample applications that are included in the OP-TEE,
+that aim to showcase specific functionality and use case.
+
+For sake of simplicity, all OP-TEE example test application are prefixed with
+`optee_example_`.
+
+---
+## 2. List of sample applications
+
+Directory **hello_world/**:
+* A very simple Trusted Application to answer a hello command and incrementing
+an integer value.
+* Test application: `optee_example_hello_world`
+* Trusted application UUID: 8aaaf200-2450-11e4-abe2-0002a5d5c51b
+
+Directory **random/**:
+* Generates a random UUID using capabilities of TEE API (`TEE_GenerateRandom()`).
+* Test application: `optee_example_random`
+* Trusted application UUID: b6c53aba-9669-4668-a7f2-205629d00f86
+
+Directory **aes/**:
+* Runs an AES encryption and decryption from a TA using the GPD TEE Internal
+Core API. Non secure test application provides the key, initial vector and
+ciphered data.
+* Test application: `optee_example_aes`
+* Trusted application UUID: 5dbac793-f574-4871-8ad3-04331ec17f24
+
+## 3. How to build a Trusted Application
+[TA basics] documentation presents the basics for implementing and building
+an OP-TEE trusted application.
+
+One can also refer to the examples provided: source files and make scripts.
+
+[TA basics]: ./docs/TA_basics.md
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/Android.mk
new file mode 100644
index 0000000..b2e1393
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/Android.mk
@@ -0,0 +1,23 @@
+ifeq ($(OPTEE_TEE_SUPPORT),true)
+LOCAL_PATH := $(call my-dir)
+
+OPTEE_CLIENT_EXPORT ?= $(LOCAL_PATH)/../../optee_client/out/export
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -DANDROID_BUILD
+LOCAL_CFLAGS += -Wall
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_SRC_FILES += host/main.c
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include \
+ $(OPTEE_CLIENT_EXPORT)/include
+
+LOCAL_SHARED_LIBRARIES := libteec
+LOCAL_MODULE := optee_example_aes
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+include $(LOCAL_PATH)/ta/Android.mk
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/CMakeLists.txt
new file mode 100644
index 0000000..3972ff5
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/CMakeLists.txt
@@ -0,0 +1,13 @@
+project (aes C)
+
+set (SRC host/main.c)
+
+add_executable (${PROJECT_NAME} ${SRC})
+
+target_include_directories(${PROJECT_NAME}
+ PRIVATE ta/include
+ PRIVATE include)
+
+target_link_libraries (${PROJECT_NAME} PRIVATE teec)
+
+install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/Makefile
new file mode 100644
index 0000000..c6526b9
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/Makefile
@@ -0,0 +1,15 @@
+export V ?= 0
+
+# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
+HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
+TA_CROSS_COMPILE ?= $(CROSS_COMPILE)
+
+.PHONY: all
+all:
+ $(MAKE) -C host O=$(O)/host CROSS_COMPILE="$(HOST_CROSS_COMPILE)" --no-builtin-variables
+ $(MAKE) -C ta O=$(O)/ta CROSS_COMPILE="$(TA_CROSS_COMPILE)" LDFLAGS=""
+
+.PHONY: clean
+clean:
+ $(MAKE) -C host clean
+ $(MAKE) -C ta clean
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/host/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/host/Makefile
new file mode 100644
index 0000000..cc08b2d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/host/Makefile
@@ -0,0 +1,36 @@
+CC ?= $(CROSS_COMPILE)gcc
+LD ?= $(CROSS_COMPILE)ld
+AR ?= $(CROSS_COMPILE)ar
+NM ?= $(CROSS_COMPILE)nm
+OBJCOPY ?= $(CROSS_COMPILE)objcopy
+OBJDUMP ?= $(CROSS_COMPILE)objdump
+READELF ?= $(CROSS_COMPILE)readelf
+
+ifneq ($O,)
+out-dir := $O
+else
+out-dir := .
+endif
+
+OBJS = main.o
+OOBJS = $(foreach obj, $(OBJS), $(out-dir)/$(obj))
+
+CFLAGS += -Wall -I../ta/include -I./include
+CFLAGS += -I$(TEEC_EXPORT)/include
+LDADD += -lteec -L$(TEEC_EXPORT)/lib $(LDFLAGS)
+
+BINARY = $(out-dir)/optee_example_aes
+
+.PHONY: all
+all: $(BINARY)
+
+$(BINARY): $(OOBJS)
+ $(CC) -o $@ $< $(LDADD)
+
+.PHONY: clean
+clean:
+ rm -f $(OOBJS) $(BINARY)
+
+$(out-dir)/%.o: %.c
+ mkdir -p $(dir $@);
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/host/main.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/host/main.c
new file mode 100644
index 0000000..a3f3130
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/host/main.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+
+/* OP-TEE TEE client API (built by optee_client) */
+#include <tee_client_api.h>
+
+/* To the the UUID (found the the TA's h-file(s)) */
+#include <aes_ta.h>
+#include <sys/time.h>
+
+#define AES_TEST_BUFFER_SIZE 4096
+#define AES_TEST_KEY_SIZE 16
+
+#define DECODE 0
+#define ENCODE 1
+
+/* TEE resources */
+struct test_ctx {
+ TEEC_Context ctx;
+ TEEC_Session sess;
+};
+
+void prepare_tee_session(struct test_ctx *ctx)
+{
+ TEEC_UUID uuid = TA_AES_UUID;
+ uint32_t origin;
+ TEEC_Result res;
+
+ /* Initialize a context connecting us to the TEE */
+ res = TEEC_InitializeContext(NULL, &ctx->ctx);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
+
+ /* Open a session with the TA */
+ res = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid,
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
+ res, origin);
+}
+
+void terminate_tee_session(struct test_ctx *ctx)
+{
+ TEEC_CloseSession(&ctx->sess);
+ TEEC_FinalizeContext(&ctx->ctx);
+}
+
+void prepare_aes(struct test_ctx *ctx, int encode)
+{
+ TEEC_Operation op;
+ uint32_t origin;
+ TEEC_Result res;
+
+ memset(&op, 0, sizeof(op));
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
+ TEEC_VALUE_INPUT,
+ TEEC_VALUE_INPUT,
+ TEEC_NONE);
+
+ op.params[0].value.a = TA_AES_ALGO_CBC;
+ op.params[1].value.a = TA_AES_SIZE_128BIT;
+ op.params[2].value.a = encode ? TA_AES_MODE_ENCODE :
+ TA_AES_MODE_DECODE;
+
+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_PREPARE,
+ &op, &origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InvokeCommand(PREPARE) failed 0x%x origin 0x%x",
+ res, origin);
+}
+
+void set_key(struct test_ctx *ctx, char *key, size_t key_sz)
+{
+ TEEC_Operation op;
+ uint32_t origin;
+ TEEC_Result res;
+
+ memset(&op, 0, sizeof(op));
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
+ TEEC_NONE, TEEC_NONE, TEEC_NONE);
+
+ op.params[0].tmpref.buffer = key;
+ op.params[0].tmpref.size = key_sz;
+
+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_KEY,
+ &op, &origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InvokeCommand(SET_KEY) failed 0x%x origin 0x%x",
+ res, origin);
+}
+
+void set_iv(struct test_ctx *ctx, char *iv, size_t iv_sz)
+{
+ TEEC_Operation op;
+ uint32_t origin;
+ TEEC_Result res;
+
+ memset(&op, 0, sizeof(op));
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
+ TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ op.params[0].tmpref.buffer = iv;
+ op.params[0].tmpref.size = iv_sz;
+
+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_IV,
+ &op, &origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InvokeCommand(SET_IV) failed 0x%x origin 0x%x",
+ res, origin);
+}
+
+void cipher_buffer(struct test_ctx *ctx, char *in, char *out, size_t sz)
+{
+ TEEC_Operation op;
+ uint32_t origin;
+ TEEC_Result res;
+
+ memset(&op, 0, sizeof(op));
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
+ TEEC_MEMREF_TEMP_OUTPUT,
+ TEEC_NONE, TEEC_NONE);
+ op.params[0].tmpref.buffer = in;
+ op.params[0].tmpref.size = sz;
+ op.params[1].tmpref.buffer = out;
+ op.params[1].tmpref.size = sz;
+
+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_CIPHER,
+ &op, &origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InvokeCommand(CIPHER) failed 0x%x origin 0x%x",
+ res, origin);
+}
+
+int performance(void)
+{
+ size_t test_size = AES_TEST_BUFFER_SIZE * 10;
+ char *clear = NULL;
+ char *ciph = NULL;
+ char *temp = NULL;
+ struct test_ctx ctx;
+ char key[AES_TEST_KEY_SIZE];
+ char iv[AES_TEST_KEY_SIZE];
+ int index = 0;
+ int round = 250;
+
+ clear = malloc(test_size);
+ if (clear == NULL) {
+ errx(1, "Malloc clear buffer failed!");
+ }
+ ciph = malloc(test_size);
+ if (ciph == NULL) {
+ errx(1, "Malloc cipher buffer failed!");
+ }
+
+ temp = malloc(test_size);
+ if (temp == NULL){
+ errx(1, "Malloc temp buffer failed!");
+ }
+ printf("Prepare session with the TA\n");
+ prepare_tee_session(&ctx);
+
+ printf("Prepare encode operation\n");
+ prepare_aes(&ctx, ENCODE);
+
+ printf("Load key in TA\n");
+ memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
+ set_key(&ctx, key, AES_TEST_KEY_SIZE);
+
+ printf("Reset ciphering operation in TA (provides the initial vector)\n");
+ memset(iv, 0, sizeof(iv)); /* Load some dummy value */
+ set_iv(&ctx, iv, AES_TEST_KEY_SIZE);
+
+ printf("Encore buffer from TA with %d bytes data\n", test_size);
+ memset(clear, 0x5a, test_size); /* Load some dummy value */
+ cipher_buffer(&ctx, clear, ciph, test_size);
+
+ printf("Prepare decode operation\n");
+ prepare_aes(&ctx, DECODE);
+
+ printf("Load key in TA\n");
+ memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
+ set_key(&ctx, key, AES_TEST_KEY_SIZE);
+
+ printf("Reset ciphering operation in TA (provides the initial vector)\n");
+ memset(iv, 0, sizeof(iv)); /* Load some dummy value */
+ set_iv(&ctx, iv, AES_TEST_KEY_SIZE);
+
+ printf("Decode buffer from TA with %d bytes data\n", test_size);
+ memset(clear, 0x5a, test_size); /* Load some dummy value */
+ cipher_buffer(&ctx, ciph, temp, test_size);
+
+ /* Check decoded is the clear content */
+ if (memcmp(clear, temp, test_size))
+ printf("Clear text and decoded text differ => ERROR\n");
+ else
+ printf("Clear text and decoded text match\n");
+ // Performace test begain.
+ printf("Prepare encode performance operation\n");
+ prepare_aes(&ctx, ENCODE);
+
+ printf("Load key in TA\n");
+ memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
+ set_key(&ctx, key, AES_TEST_KEY_SIZE);
+
+ printf("Reset ciphering operation in TA (provides the initial vector)\n");
+ memset(iv, 0, sizeof(iv)); /* Load some dummy value */
+ set_iv(&ctx, iv, AES_TEST_KEY_SIZE);
+
+ printf("Encore buffer from TA with %d bytes data with round %d\n", test_size, round);
+ memset(clear, 0x5a, test_size); /* Load some dummy value */
+ struct timeval tval_be, tval_af, tval_res;
+ gettimeofday(&tval_be, NULL);
+ for (index = 0; index < round; index++)
+ {
+ cipher_buffer(&ctx, ciph, temp, test_size);
+ }
+ gettimeofday(&tval_af, NULL);
+ timersub(&tval_af, &tval_be, &tval_res);
+ printf("Time elapsed:%ld.%06ld\n", (long int)tval_res.tv_sec, (long int)tval_res.tv_usec);
+ printf("Finish encore buffer from TA with %d bytes data with round %d\n", test_size, round);
+
+}
+
+int aes_basic(void)
+{
+ struct test_ctx ctx;
+ char key[AES_TEST_KEY_SIZE];
+ char iv[AES_TEST_KEY_SIZE];
+ char clear[AES_TEST_BUFFER_SIZE];
+ char ciph[AES_TEST_BUFFER_SIZE];
+ char temp[AES_TEST_BUFFER_SIZE];
+
+ printf("Prepare session with the TA\n");
+ prepare_tee_session(&ctx);
+
+ printf("Prepare encode operation\n");
+ prepare_aes(&ctx, ENCODE);
+
+ printf("Load key in TA\n");
+ memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
+ set_key(&ctx, key, AES_TEST_KEY_SIZE);
+
+ printf("Reset ciphering operation in TA (provides the initial vector)\n");
+ memset(iv, 0, sizeof(iv)); /* Load some dummy value */
+ set_iv(&ctx, iv, AES_TEST_KEY_SIZE);
+
+ printf("Encore buffer from TA\n");
+ memset(clear, 0x5a, sizeof(clear)); /* Load some dummy value */
+ cipher_buffer(&ctx, clear, ciph, AES_TEST_BUFFER_SIZE);
+
+ printf("Prepare decode operation\n");
+ prepare_aes(&ctx, DECODE);
+
+ printf("Load key in TA\n");
+ memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
+ set_key(&ctx, key, AES_TEST_KEY_SIZE);
+
+ printf("Reset ciphering operation in TA (provides the initial vector)\n");
+ memset(iv, 0, sizeof(iv)); /* Load some dummy value */
+ set_iv(&ctx, iv, AES_TEST_KEY_SIZE);
+
+ printf("Decode buffer from TA\n");
+ memset(clear, 0x5a, sizeof(clear)); /* Load some dummy value */
+ cipher_buffer(&ctx, ciph, temp, AES_TEST_BUFFER_SIZE);
+
+ /* Check decoded is the clear content */
+ if (memcmp(clear, temp, AES_TEST_BUFFER_SIZE))
+ printf("Clear text and decoded text differ => ERROR\n");
+ else
+ printf("Clear text and decoded text match\n");
+
+ terminate_tee_session(&ctx);
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ aes_basic();
+ performance();
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/Android.mk
new file mode 100644
index 0000000..931f8e4
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH := $(call my-dir)
+
+local_module := 5dbac793-f574-4871-8ad3-04331ec17f24.ta
+include $(BUILD_OPTEE_MK)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/Makefile
new file mode 100644
index 0000000..406b4f8
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/Makefile
@@ -0,0 +1,13 @@
+CFG_TEE_TA_LOG_LEVEL ?= 4
+CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
+
+# The UUID for the Trusted Application
+BINARY=5dbac793-f574-4871-8ad3-04331ec17f24
+
+-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
+clean:
+ @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
+ @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/aes_ta.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/aes_ta.c
new file mode 100644
index 0000000..0814464
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/aes_ta.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <inttypes.h>
+
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include <aes_ta.h>
+
+#define AES128_KEY_BIT_SIZE 128
+#define AES128_KEY_BYTE_SIZE (AES128_KEY_BIT_SIZE / 8)
+#define AES256_KEY_BIT_SIZE 256
+#define AES256_KEY_BYTE_SIZE (AES256_KEY_BIT_SIZE / 8)
+
+/*
+ * Ciphering context: each opened session relates to a cipehring operation.
+ * - configure the AES flavour from a command.
+ * - load key from a command (here the key is provided by the REE)
+ * - reset init vector (here IV is provided by the REE)
+ * - cipher a buffer frame (here input and output buffers are non-secure)
+ */
+struct aes_cipher {
+ uint32_t algo; /* AES flavour */
+ uint32_t mode; /* Encode or decode */
+ uint32_t key_size; /* AES key size in byte */
+ TEE_OperationHandle op_handle; /* AES ciphering operation */
+ TEE_ObjectHandle key_handle; /* transient object to load the key */
+};
+
+/*
+ * Few routines to convert IDs from TA API into IDs from OP-TEE.
+ */
+static TEE_Result ta2tee_algo_id(uint32_t param, uint32_t *algo)
+{
+ switch (param) {
+ case TA_AES_ALGO_ECB:
+ *algo = TEE_ALG_AES_ECB_NOPAD;
+ return TEE_SUCCESS;
+ case TA_AES_ALGO_CBC:
+ *algo = TEE_ALG_AES_CBC_NOPAD;
+ return TEE_SUCCESS;
+ case TA_AES_ALGO_CTR:
+ *algo = TEE_ALG_AES_CTR;
+ return TEE_SUCCESS;
+ default:
+ EMSG("Invalid algo %u", param);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
+static TEE_Result ta2tee_key_size(uint32_t param, uint32_t *key_size)
+{
+ switch (param) {
+ case AES128_KEY_BYTE_SIZE:
+ case AES256_KEY_BYTE_SIZE:
+ *key_size = param;
+ return TEE_SUCCESS;
+ default:
+ EMSG("Invalid key size %u", param);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
+static TEE_Result ta2tee_mode_id(uint32_t param, uint32_t *mode)
+{
+ switch (param) {
+ case TA_AES_MODE_ENCODE:
+ *mode = TEE_MODE_ENCRYPT;
+ return TEE_SUCCESS;
+ case TA_AES_MODE_DECODE:
+ *mode = TEE_MODE_DECRYPT;
+ return TEE_SUCCESS;
+ default:
+ EMSG("Invalid mode %u", param);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
+
+/*
+ * Process command TA_AES_CMD_PREPARE. API in aes_ta.h
+ *
+ * Allocate resources required for the ciphering operation.
+ * During ciphering operation, when expect client can:
+ * - update the key materials (provided by client)
+ * - reset the initial vector (provided by client)
+ * - cipher an input buffer into an output buffer (provided by client)
+ */
+static TEE_Result alloc_resources(void *session, uint32_t param_types,
+ TEE_Param params[4])
+{
+ const uint32_t exp_param_types =
+ TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_NONE);
+ struct aes_cipher *sess;
+ TEE_Attribute attr;
+ TEE_Result res;
+ char *key;
+
+ /* Get ciphering context from session ID */
+ DMSG("Session %p: get ciphering resources", session);
+ sess = (struct aes_cipher *)session;
+
+ /* Safely get the invocation parameters */
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ res = ta2tee_algo_id(params[0].value.a, &sess->algo);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ res = ta2tee_key_size(params[1].value.a, &sess->key_size);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ res = ta2tee_mode_id(params[2].value.a, &sess->mode);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ /*
+ * Ready to allocate the resources which are:
+ * - an operation handle, for an AES ciphering of given configuration
+ * - a transient object that will be use to load the key materials
+ * into the AES ciphering operation.
+ */
+
+ /* Free potential previous operation */
+ if (sess->op_handle != TEE_HANDLE_NULL)
+ TEE_FreeOperation(sess->op_handle);
+
+ /* Allocate operation: AES/CTR, mode and size from params */
+ res = TEE_AllocateOperation(&sess->op_handle,
+ sess->algo,
+ sess->mode,
+ sess->key_size * 8);
+ if (res != TEE_SUCCESS) {
+ EMSG("Failed to allocate operation");
+ sess->op_handle = TEE_HANDLE_NULL;
+ goto err;
+ }
+
+ /* Free potential previous transient object */
+ if (sess->key_handle != TEE_HANDLE_NULL)
+ TEE_FreeTransientObject(sess->key_handle);
+
+ /* Allocate transient object according to target key size */
+ res = TEE_AllocateTransientObject(TEE_TYPE_AES,
+ sess->key_size * 8,
+ &sess->key_handle);
+ if (res != TEE_SUCCESS) {
+ EMSG("Failed to allocate transient object");
+ sess->key_handle = TEE_HANDLE_NULL;
+ goto err;
+ }
+
+ /*
+ * When loading a key in the cipher session, set_aes_key()
+ * will reset the operation and load a key. But we cannot
+ * reset and operation that has no key yet (GPD TEE Internal
+ * Core API Specification – Public Release v1.1.1, section
+ * 6.2.5 TEE_ResetOperation). In consequence, we will load a
+ * dummy key in the operation so that operation can be reset
+ * when updating the key.
+ */
+ key = TEE_Malloc(sess->key_size, 0);
+ if (!key) {
+ res = TEE_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, sess->key_size);
+
+ res = TEE_PopulateTransientObject(sess->key_handle, &attr, 1);
+ if (res != TEE_SUCCESS) {
+ EMSG("TEE_PopulateTransientObject failed, %x", res);
+ goto err;
+ }
+
+ res = TEE_SetOperationKey(sess->op_handle, sess->key_handle);
+ if (res != TEE_SUCCESS) {
+ EMSG("TEE_SetOperationKey failed %x", res);
+ goto err;
+ }
+
+ return res;
+
+err:
+ if (sess->op_handle != TEE_HANDLE_NULL)
+ TEE_FreeOperation(sess->op_handle);
+ sess->op_handle = TEE_HANDLE_NULL;
+
+ if (sess->key_handle != TEE_HANDLE_NULL)
+ TEE_FreeTransientObject(sess->key_handle);
+ sess->key_handle = TEE_HANDLE_NULL;
+
+ return res;
+}
+
+/*
+ * Process command TA_AES_CMD_SET_KEY. API in aes_ta.h
+ */
+static TEE_Result set_aes_key(void *session, uint32_t param_types,
+ TEE_Param params[4])
+{
+ const uint32_t exp_param_types =
+ TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+ struct aes_cipher *sess;
+ TEE_Attribute attr;
+ TEE_Result res;
+ uint32_t key_sz;
+ char *key;
+
+ /* Get ciphering context from session ID */
+ DMSG("Session %p: load key material", session);
+ sess = (struct aes_cipher *)session;
+
+ /* Safely get the invocation parameters */
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ key = params[0].memref.buffer;
+ key_sz = params[0].memref.size;
+
+ if (key_sz != sess->key_size) {
+ EMSG("Wrong key size %" PRIu32 ", expect %" PRIu32 " bytes",
+ key_sz, sess->key_size);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ /*
+ * Load the key material into the configured operation
+ * - create a secret key attribute with the key material
+ * TEE_InitRefAttribute()
+ * - reset transient object and load attribute data
+ * TEE_ResetTransientObject()
+ * TEE_PopulateTransientObject()
+ * - load the key (transient object) into the cihering operation
+ * TEE_SetOperationKey()
+ *
+ * TEE_SetOperationKey() requires operation to be in "initial state".
+ * We can use TEE_ResetOperation() to reset the operation but this
+ * api cannot be used on operation with key(s) not yet set. Hence,
+ * when allocating the operation handle, we prevovision a dummy key.
+ * Thus, set_key sequence always reset then set key on operation.
+ */
+
+ TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_sz);
+
+ TEE_ResetTransientObject(sess->key_handle);
+ res = TEE_PopulateTransientObject(sess->key_handle, &attr, 1);
+ if (res != TEE_SUCCESS) {
+ EMSG("TEE_PopulateTransientObject failed, %x", res);
+ return res;
+ }
+
+ TEE_ResetOperation(sess->op_handle);
+ res = TEE_SetOperationKey(sess->op_handle, sess->key_handle);
+ if (res != TEE_SUCCESS) {
+ EMSG("TEE_SetOperationKey failed %x", res);
+ return res;
+ }
+
+ return res;
+}
+
+/*
+ * Process command TA_AES_CMD_SET_IV. API in aes_ta.h
+ */
+static TEE_Result reset_aes_iv(void *session, uint32_t param_types,
+ TEE_Param params[4])
+{
+ const uint32_t exp_param_types =
+ TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+ struct aes_cipher *sess;
+ size_t iv_sz;
+ char *iv;
+
+ /* Get ciphering context from session ID */
+ DMSG("Session %p: reset initial vector", session);
+ sess = (struct aes_cipher *)session;
+
+ /* Safely get the invocation parameters */
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ iv = params[0].memref.buffer;
+ iv_sz = params[0].memref.size;
+
+ /*
+ * Init cipher operation with the initialization vector.
+ */
+ TEE_CipherInit(sess->op_handle, iv, iv_sz);
+
+ return TEE_SUCCESS;
+}
+
+/*
+ * Process command TA_AES_CMD_CIPHER. API in aes_ta.h
+ */
+static TEE_Result cipher_buffer(void *session, uint32_t param_types,
+ TEE_Param params[4])
+{
+ const uint32_t exp_param_types =
+ TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_MEMREF_OUTPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+ struct aes_cipher *sess;
+
+ /* Get ciphering context from session ID */
+ DMSG("Session %p: cipher buffer", session);
+ sess = (struct aes_cipher *)session;
+
+ /* Safely get the invocation parameters */
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ if (params[1].memref.size < params[0].memref.size) {
+ EMSG("Bad sizes: in %d, out %d", params[0].memref.size,
+ params[1].memref.size);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (sess->op_handle == TEE_HANDLE_NULL)
+ return TEE_ERROR_BAD_STATE;
+
+ /*
+ * Process ciphering operation on provided buffers
+ */
+ return TEE_CipherUpdate(sess->op_handle,
+ params[0].memref.buffer, params[0].memref.size,
+ params[1].memref.buffer, ¶ms[1].memref.size);
+}
+
+TEE_Result TA_CreateEntryPoint(void)
+{
+ /* Nothing to do */
+ return TEE_SUCCESS;
+}
+
+void TA_DestroyEntryPoint(void)
+{
+ /* Nothing to do */
+}
+
+TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
+ TEE_Param __unused params[4],
+ void __unused **session)
+{
+ struct aes_cipher *sess;
+
+ /*
+ * Allocate and init ciphering materials for the session.
+ * The address of the structure is used as session ID for
+ * the client.
+ */
+ sess = TEE_Malloc(sizeof(*sess), 0);
+ if (!sess)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ sess->key_handle = TEE_HANDLE_NULL;
+ sess->op_handle = TEE_HANDLE_NULL;
+
+ *session = (void *)sess;
+ DMSG("Session %p: newly allocated", *session);
+
+ return TEE_SUCCESS;
+}
+
+void TA_CloseSessionEntryPoint(void *session)
+{
+ struct aes_cipher *sess;
+
+ /* Get ciphering context from session ID */
+ DMSG("Session %p: release session", session);
+ sess = (struct aes_cipher *)session;
+
+ /* Release the session resources */
+ if (sess->key_handle != TEE_HANDLE_NULL)
+ TEE_FreeTransientObject(sess->key_handle);
+ if (sess->op_handle != TEE_HANDLE_NULL)
+ TEE_FreeOperation(sess->op_handle);
+ TEE_Free(sess);
+}
+
+TEE_Result TA_InvokeCommandEntryPoint(void *session,
+ uint32_t cmd,
+ uint32_t param_types,
+ TEE_Param params[4])
+{
+ switch (cmd) {
+ case TA_AES_CMD_PREPARE:
+ return alloc_resources(session, param_types, params);
+ case TA_AES_CMD_SET_KEY:
+ return set_aes_key(session, param_types, params);
+ case TA_AES_CMD_SET_IV:
+ return reset_aes_iv(session, param_types, params);
+ case TA_AES_CMD_CIPHER:
+ return cipher_buffer(session, param_types, params);
+ default:
+ EMSG("Command ID 0x%x is not supported", cmd);
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/include/aes_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/include/aes_ta.h
new file mode 100644
index 0000000..ecdddb6
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/include/aes_ta.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __AES_TA_H__
+#define __AES_TA_H__
+
+/* UUID of the AES example trusted application */
+#define TA_AES_UUID \
+ { 0x5dbac793, 0xf574, 0x4871, \
+ { 0x8a, 0xd3, 0x04, 0x33, 0x1e, 0xc1, 0x7f, 0x24 } }
+
+/*
+ * TA_AES_CMD_PREPARE - Allocate resources for the AES ciphering
+ * param[0] (value) a: TA_AES_ALGO_xxx, b: unused
+ * param[1] (value) a: key size in bytes, b: unused
+ * param[2] (value) a: TA_AES_MODE_ENCODE/_DECODE, b: unused
+ * param[3] unused
+ */
+#define TA_AES_CMD_PREPARE 0
+
+#define TA_AES_ALGO_ECB 0
+#define TA_AES_ALGO_CBC 1
+#define TA_AES_ALGO_CTR 2
+
+#define TA_AES_SIZE_128BIT (128 / 8)
+#define TA_AES_SIZE_256BIT (256 / 8)
+
+#define TA_AES_MODE_ENCODE 1
+#define TA_AES_MODE_DECODE 0
+
+/*
+ * TA_AES_CMD_SET_KEY - Allocate resources for the AES ciphering
+ * param[0] (memref) key data, size shall equal key length
+ * param[1] unused
+ * param[2] unused
+ * param[3] unused
+ */
+#define TA_AES_CMD_SET_KEY 1
+
+/*
+ * TA_AES_CMD_SET_IV - reset IV
+ * param[0] (memref) initial vector, size shall equal key length
+ * param[1] unused
+ * param[2] unused
+ * param[3] unused
+ */
+#define TA_AES_CMD_SET_IV 2
+
+/*
+ * TA_AES_CMD_CIPHER - Ciphere inut buffer into output buffer
+ * param[0] (memref) input buffer
+ * param[1] (memref) output buffer (shall be bigger than input buffer)
+ * param[2] unused
+ * param[3] unused
+ */
+#define TA_AES_CMD_CIPHER 3
+
+#endif /* __AES_TA_H */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/sub.mk
new file mode 100644
index 0000000..96c58b2
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/sub.mk
@@ -0,0 +1,2 @@
+global-incdirs-y += include
+srcs-y += aes_ta.c
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/user_ta_header_defines.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/user_ta_header_defines.h
new file mode 100644
index 0000000..9f944b8
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/aes/ta/user_ta_header_defines.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The name of this file must not be modified
+ */
+
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+#include <aes_ta.h>
+
+#define TA_UUID TA_AES_UUID
+
+#define TA_FLAGS TA_FLAG_EXEC_DDR
+#define TA_STACK_SIZE (2 * 1024)
+#define TA_DATA_SIZE (32 * 1024)
+
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
+ "Example of TA using an AES sequence" }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } }
+
+#endif /*USER_TA_HEADER_DEFINES_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/Android.mk
new file mode 100644
index 0000000..7142a22
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/Android.mk
@@ -0,0 +1,39 @@
+ifeq ($(OPTEE_TEE_SUPPORT),true)
+###################### optee-dapc ######################
+LOCAL_PATH := $(call my-dir)
+
+OPTEE_CLIENT_EXPORT = $(LOCAL_PATH)/../../../../optee_client/out/export
+
+## include variants like TA_DEV_KIT_DIR
+## and OPTEE_BIN
+INCLUDE_FOR_BUILD_TA := false
+include $(BUILD_OPTEE_MK)
+INCLUDE_FOR_BUILD_TA :=
+
+# TA_DEV_KIT_DIR must be set to non-empty value to
+# avoid the Android build scripts complaining about
+# includes pointing outside the Android source tree.
+# This var is expected to be set when OPTEE OS built.
+# We set the default value to an invalid path.
+TA_DEV_KIT_DIR ?= ../invalid_include_path
+$(warning TA_DEV_KIT_DIR:$(TA_DEV_KIT_DIR))
+-include $(TA_DEV_KIT_DIR)/host_include/conf.mk
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -DANDROID_BUILD
+LOCAL_CFLAGS += -Wall
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_SRC_FILES += host/main.c
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../pta/mt2712/pta_dapc/include \
+ $(LOCAL_PATH)/../../mt2712/dapc/include \
+ $(OPTEE_CLIENT_EXPORT)/include
+
+LOCAL_SHARED_LIBRARIES := libteec
+LOCAL_MODULE := optee_example_dapc
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/Makefile
new file mode 100644
index 0000000..4f37540
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/Makefile
@@ -0,0 +1,13 @@
+export V?=0
+
+# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
+HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
+TA_CROSS_COMPILE ?= $(CROSS_COMPILE)
+
+.PHONY: all
+all:
+ $(MAKE) -C host O=$(O)/host CROSS_COMPILE="$(HOST_CROSS_COMPILE)" --no-builtin-variables
+
+.PHONY: clean
+clean:
+ $(MAKE) -C host clean
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/host/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/host/Makefile
new file mode 100644
index 0000000..02c279a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/host/Makefile
@@ -0,0 +1,36 @@
+CC ?= $(CROSS_COMPILE)gcc
+LD ?= $(CROSS_COMPILE)ld
+AR ?= $(CROSS_COMPILE)ar
+NM ?= $(CROSS_COMPILE)nm
+OBJCOPY ?= $(CROSS_COMPILE)objcopy
+OBJDUMP ?= $(CROSS_COMPILE)objdump
+READELF ?= $(CROSS_COMPILE)readelf
+
+ifneq ($O,)
+out-dir := $O
+else
+out-dir := .
+endif
+
+OBJS = main.o
+OOBJS = $(foreach obj, $(OBJS), $(out-dir)/$(obj))
+
+CFLAGS += -Wall -I../ta/include -I$(TEEC_EXPORT)/include -I./include -I../../../pta/mt2712/pta_dapc/include -I../../../mt2712/dapc/include
+#Add/link other required libraries here
+LDADD += -lteec -L$(TEEC_EXPORT)/lib $(LDFLAGS)
+
+BINARY = $(out-dir)/optee_example_dapc
+
+.PHONY: all
+all: $(BINARY)
+
+$(BINARY): $(OOBJS)
+ $(CC) -o $@ $< $(LDADD)
+
+.PHONY: clean
+clean:
+ rm -f $(OOBJS) $(BINARY)
+
+$(out-dir)/%.o: %.c
+ mkdir -p $(dir $@);
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/host/main.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/host/main.c
new file mode 100644
index 0000000..814746a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/dapc/host/main.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2020, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+
+/* OP-TEE TEE client API (built by optee_client) */
+#include <tee_client_api.h>
+
+/* To the the UUID (found the the TA's h-file(s)) */
+#include <pta_dapc.h>
+
+/* For DAPC index */
+#include <dapc_public.h>
+
+int main(int argc, char *argv[])
+{
+ TEEC_Result res;
+ TEEC_Context ctx;
+ TEEC_Session sess;
+ TEEC_Operation op;
+ TEEC_UUID uuid = PTA_DAPC_UUID;
+ uint32_t err_origin;
+
+ /* Initialize a context connecting us to the TEE */
+ res = TEEC_InitializeContext(NULL, &ctx);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
+
+ /*
+ * Open a session to the "dapc" PTA, the PTA will print "hello
+ * world!" in the log when the session is created.
+ */
+ res = TEEC_OpenSession(&ctx, &sess, &uuid,
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
+ res, err_origin);
+
+ /*
+ * Execute a function in the TA by invoking it, in this case
+ * we're incrementing a number.
+ *
+ * The value of command ID part and how the parameters are
+ * interpreted is part of the interface provided by the TA.
+ */
+
+ /* Clear the TEEC_Operation struct */
+ memset(&op, 0, sizeof(op));
+
+ /*
+ * Prepare the argument. Pass a value in the first parameter,
+ * the remaining three parameters are unused.
+ */
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ op.params[0].value.a = 56;
+ op.params[0].value.b = 57;
+
+ /*
+ * PTA_CMD_DAPC_TEST is the actual function in the PTA to be
+ * called.
+ */
+ printf("Invoking PTA to test DAPC\n");
+ printf("params[0].a is %d\n", op.params[0].value.a);
+ printf("params[0].b is %d\n", op.params[0].value.b);
+ res = TEEC_InvokeCommand(&sess, PTA_CMD_DAPC_TEST, &op,
+ &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",
+ res, err_origin);
+
+ /* Test PTA_CMD_DAPC_MASTER_TEST */
+ memset(&op, 0, sizeof(op));
+
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_VALUE_INOUT,
+ TEEC_NONE, TEEC_NONE);
+ op.params[0].value.a = 8;
+ op.params[1].value.a = 1;
+
+ res = TEEC_InvokeCommand(&sess, PTA_CMD_DAPC_MASTER_TEST, &op,
+ &err_origin);
+
+ /* Test PTA_CMD_DAPC_SLAVE_APC_TEST */
+ memset(&op, 0, sizeof(op));
+
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_VALUE_INOUT,
+ TEEC_VALUE_INOUT, TEEC_NONE);
+ op.params[0].value.a = INFRA_AO_DEVICE_APC_AO;
+ op.params[1].value.a = 1;
+ op.params[2].value.a = 1;
+
+ res = TEEC_InvokeCommand(&sess, PTA_CMD_DAPC_SLAVE_APC_TEST, &op,
+ &err_origin);
+ /*
+ * We're done with the PTA, close the session and
+ * destroy the context.
+ *
+ * The TA will print "Goodbye!" in the log when the
+ * session is closed.
+ */
+
+ TEEC_CloseSession(&sess);
+
+ TEEC_FinalizeContext(&ctx);
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/docs/TA_basics.md b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/docs/TA_basics.md
new file mode 100644
index 0000000..2e08b50
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/docs/TA_basics.md
@@ -0,0 +1,304 @@
+Basics for Development of OP-TEE Trusted Applications
+=====================================================
+
+This document show how to implement a basic trusted application for OP-TEE,
+using the OP-TEE devkit to build and sign the trusted application binary.
+
+In this document, a trusted application running in the OP-TEE os is referred
+to as a TA.
+
+### Contents
+1. [TA Minimal Source Files](#1-ta-minimal-source-files)
+2. [TA Makefile Script Basics](#2-ta-makefile-script-basics)
+3. [Android Build Environment](#3-android-build-environment)
+4. [TA Entry Points Implementation Basics](#4-ta-entry-points-implementation-basics)
+5. [TA Properties Basics](#5-ta-properties-basics)
+6. [Specific cares on TA invocation parameters](#6-specific-cares-on-ta-invocation-parameters)
+
+
+---
+# 1. TA Minimal Source Files
+
+Trusted Application Makefile must be designed to rely on OP-TEE devkit
+resources in order to successfully build the target application. The OP-TEE
+devkit is built (maybe installed) when one builds (installs) the optee_os.
+
+To build a TA, one must provide:
+
+- **Makefile**, a make script that should set some configuration variables and
+ include the devkit make script.
+
+- **sub.mk**, a make script that lists the sources to build (local source files,
+ subdirectories to parse, source file specific build directives).
+
+- **user_ta_header_defines.h**, a specific ANSI-C header file to define most of
+ the TA properties.
+
+- A implementation of at least the TA entry points, as extern functions:
+ `TA_CreateEntryPoint()`, `TA_DestroyEntryPoint()`,
+ `TA_OpenSessionEntryPoint()`, `TA_CloseSessionEntryPoint()`,
+ `TA_InvokeCommandEntryPoint()`
+
+Looking at example hello_world:
+```
+hello_world/
+├── ...
+└── ta
+ ├── Makefile BINARY=<uuid>
+ ├── Android.mk Android way to invoke the Makefile
+ ├── sub.mk srcs-y += hello_world_ta.c
+ ├── include
+ │ └── hello_world_ta.h Header exported to non-secure: TA commands API
+ ├── hello_world_ta.c Implementaion of TA entry points
+ └── user_ta_header_defines.h TA_UUID, TA_FLAGS, TA_DATA/STACK_SIZE, ...
+```
+
+---
+# 2. TA Makefile Script Basics
+
+## 2.1. Devkit Makefile Requirements
+
+The devkit make script is located in the devkit filetree at path
+**mk/ta_dev_kit.mk**.
+
+The make script supports rules `all` and `clean` to build a TA or
+a library and clean the built objects.
+
+The make script expects some configuration variables:
+
+- Variable `TA_DEV_KIT_DIR`
+
+ Base directory of the devkit. Used the devkit itself to locate its tools.
+
+- Variables `BINARY` and `LIBNAME`
+
+ `BINARY` and `LIBNAME` are exclusives.
+
+ If building a TA, `BINARY` shall provide the TA filename used to load the TA.
+ The built signed TA binary file will be named `${BINARY}.ta`.
+ In native OP-TEE, it is the TA uuid, used by tee-supplicant to identify TAs.
+
+ if building a static library (that will be later linked by a TA),
+ `LIBNAME` shall provide the name of the library. The generated library
+ binary file will be named `lib${LIBNAME}.a`
+
+- Variables `CROSS_COMPILE` and `CROSS_COMPILE32`
+
+ Cross compiler for the TA or the library source files. `CROSS_COMPILE32`
+ is optional. It allows to target AArch32 builds on AArch64 capable systems.
+ On AArch32 systems, `CROSS_COMPILE32` defaults to `CROSS_COMPILE`.
+
+Some optional configuration variables can be supported, check optee_os
+delivery. For examples:
+
+- Variable `O`
+
+ Base directory for build objects filetree. If not set, devit defaults to
+ **./out** from the TA source tree base directory.
+
+A tipical makefile to drive the build of a TA is:
+```make
+# Append specific configuration to the C source build (here log=info)
+# The UUID for the Trusted Application
+BINARY=8aaaf200-2450-11e4-abe2-0002a5d5c51b
+
+# Source the devkit make script
+include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+```
+
+## 2.2. Listing Source Files to Build and Build directives
+
+The make script expects that current directory contains a file `sub.mk` that
+is the entry point for listing the source files to build and other specific
+build directives.
+
+Following are examples of directive one can implement in a sub.mk make script:
+
+* `srcs-y += hello_world_ta.c`\
+ Adds **./hello_world_ta.c** from current directory to the list of the source
+ file to build and link.
+
+* `global-incdirs-y += include/`\
+ Includes path **./include/** from the current directory to the include path.
+
+* `cflags-hello_world_ta.c-y += -Wno-strict-prototypes`\
+ Adds directive `-Wno-strict-prototypes` to the build directove of
+ **./hello_world_ta.c** specific source file.
+
+* `cflags-remove-hello_world_ta.c-y += -Wno-strict-prototypes`\
+ Removes directive `-Wno-strict-prototypes` from the build directives of
+ **./hello_world_ta.c** specific source file.
+
+* `libnames += foo`\
+ Adds the static library `foo` to the list of the linker directives:
+ `-lfoo`.
+
+* `libdirs += path/to/libfoo/install/directory`\
+ Adds the directory path to the libraries pathes list. Archive file
+ **libfoo.a** is expectd in this directory.
+
+* `libdeps += path/to/greatlib/libgreatlib.a`\
+ Adds the static library binary to the TA build dependencies.
+
+---
+# 3. Android Build Environment
+
+OP-TEE devkit supports building in Android build environment. One can
+implement an Android.mk script for its TA next to the Makefile script.
+
+The Android build will parse the TA Android make script which will parse a
+devkit Android make script to locate TA build resources. Then the Android
+build will execute a `make` command to built the TA through its generic
+Makefile script.
+
+A typical Android.mk script for a TA is:
+```make
+$ cat hello_world/ta/Android.mk
+# Define base path for the TA sources filetree
+LOCAL_PATH := $(call my-dir)
+# Define the module name as the signed TA binary filename.
+local_module := 8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta
+# Include the devikt Android mak script
+include $(OPTEE_OS_DIR)/mk/aosp_optee.mk
+```
+
+---
+# 4. TA Entry Points Implementation Basics
+
+TA source code is expected to provide implemenation for the following
+functions:
+
+```c
+TEE_Result TA_CreateEntryPoint(void)
+{
+ /* Allocate some resources, init something, ... */
+ ...
+
+ /* Return with a status */
+ return TEE_SUCCESS;
+}
+
+void TA_DestroyEntryPoint(void)
+{
+ /* Release resources if required before TA destruction */
+ ...
+}
+
+TEE_Result TA_OpenSessionEntryPoint(uint32_t ptype,
+ TEE_Param param[4],
+ void **session_id_ptr)
+{
+ /* Check client identity, and alloc/init some session resources if any */
+ ...
+
+ /* Return with a status */
+ return TEE_SUCCESS;
+}
+
+void TA_CloseSessionEntryPoint(void *sess_ptr)
+{
+ /* check client and handle session resource release, if any */
+ ...
+}
+
+TEE_Result TA_InvokeCommandEntryPoint(void *session_id,
+ uint32_t command_id,
+ uint32_t parameters_type,
+ TEE_Param parameters[4])
+{
+ /* Decode the command and process execution of the target service */
+ ...
+
+ /* Return with a status */
+ return TEE_SUCCESS;
+}
+```
+
+---
+# 5. TA Properties Basics
+
+Trusted Application properties shall be defined in a specific ANSI-C header
+file named **user_ta_header_defines.h**. The header file shall define the following macros:
+
+- `TA_UUID` defines the TA uuid value
+
+- `TA_FLAGS` define some of the TA properties
+
+- `TA_STACK_SIZE` defines the RAM size to be reserved for TA stack
+
+- `TA_DATA_SIZE` defines the RAM size to be reserved for TA heap (TEE_Malloc() pool)
+
+Refer to [TA properties] to configure these macros.
+
+**user_ta_header_defines.h** file may provide the following macro:
+
+- `TA_CURRENT_TA_EXT_PROPERTIES` may define extra properties of the TA.
+
+
+Example of **user_ta_header_defines.h**:
+
+```c
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+#define TA_UUID
+ { 0x8aaaf200, 0x2450, 0x11e4, \
+ { 0xab, 0xe2, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} }
+
+#define TA_FLAGS (TA_FLAG_EXEC_DDR | \
+ TA_FLAG_SINGLE_INSTANCE | \
+ TA_FLAG_MULTI_SESSION)
+#define TA_STACK_SIZE (2 * 1024)
+#define TA_DATA_SIZE (32 * 1024)
+
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, "Foo TA for some purpose." }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0100 } }
+
+#endif /* USER_TA_HEADER_DEFINES_H */
+```
+
+---
+# 6. Specific cares on TA invocation parameters
+
+GPD TEE Client APIs `TEEC_InvokeCommand()` and `TEE_OpenSession()` allow a client
+to invoke a TA with some invocation parameters: values or references to memory buffers.
+
+It is mandatory that TAs verify the parameters types before using the parameters
+themsleves.
+
+TA can rely on macro TEE_PARAM_TYPE_GET(param_type, param_index)` to get the
+type of a parameter and check its value according to the expected parameter.
+
+For example, if TA expect that command ID 0 comes with param#0 being a input
+value, param#2 being a output value, and param#3 being a in/out memory
+reference (buffer), TA should implemented the following sequence:
+
+```c
+TEE_Result handle_command_0(void *session, uint32_t cmd_id,
+ uint32_t param_types, TEE_Param params[4])
+{
+ if ((TEE_PARAM_TYPE_GET(param_types, 0) != TEE_PARAM_TYPE_VALUE_IN) ||
+ (TEE_PARAM_TYPE_GET(param_types, 1) != TEE_PARAM_TYPE_VALUE_OUT) ||
+ (TEE_PARAM_TYPE_GET(param_types, 2) != TEE_PARAM_TYPE_MEMREF_INOUT) ||
+ (TEE_PARAM_TYPE_GET(param_types, 3) != TEE_PARAM_TYPE_NONE)) {
+ return TEE_ERROR_BAD_PARAMETERS
+ }
+
+ /* process command */
+ ...
+}
+
+TEE_Result TA_InvokeCommandEntryPoint(void *session, uint32_t command_id,
+ uint32_t param_types, TEE_Param params[4])
+{
+ switch (command_id) {
+ case 0:
+ return handle_command_0(session, param_types, params);
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+}
+```
+
+[TA properties]: ./TA_properties.md
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/docs/TA_properties.md b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/docs/TA_properties.md
new file mode 100644
index 0000000..7a705b8
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/docs/TA_properties.md
@@ -0,0 +1,140 @@
+Defining Properties of Trusted Applications
+===========================================
+
+This document is related to the trusted application examples documentation [TA basics].
+
+
+### Contents
+
+1. [TA properties defined by GPD TEE specifications](#1-ta-properties-defined-by-gpd-tee-specifications)
+2. [TA Property Flags from the OP-TEE Extensions](#2-ta-property-flags-from-the-op-tee-extensions)
+
+
+# 1. TA properties defined by GPD TEE specifications
+
+Standard TA properties must be defined through property flag in macro
+`TA_FLAGS` by **user_ta_header_defines.h**.
+
+## 1.1. Single Instance Property
+
+`"gpd.ta.singleInstance"` is a boolean property of the TA.
+
+This property defines if one instance of the TA must be created and will
+receive all open session request, or if a new specific TA instance must be
+created for each incoming open session request.
+
+OP-TEE TA flag `TA_FLAG_SINGLE_INSTANCE` sets to configuration of this
+property.
+
+The boolean property is set to `true` if `TA_FLAGS` sets bit
+`TA_FLAG_SINGLE_INSTANCE`, otherwise the boolean property is set to `false`.
+
+## 1.2. Multi-session Property
+
+`"gpd.ta.multiSession"` is a boolean property of the TA.
+
+This property defines if the TA instance can handle several sessions. If
+disabled, TA instance support only one session. In such case, if the TA
+already has a opened session, any open session request will return with a
+busy error status.
+
+This property is meaningless if TA is NOT SingleInstance.
+
+OP-TEE TA flag `TA_FLAG_MULTI_SESSION` sets to configuration of this
+property.
+
+The boolean property is set to `true` if `TA_FLAGS` sets bit
+`TA_FLAG_MULTI_SESSION`, otherwise the boolean property is set to `false`.
+
+## 1.3. Keep Alive Property
+
+`"gpd.ta.instanceKeepAlive"` is a boolean property of the TA.
+
+This property defines if the TA instance created must be destroyed or not when
+all sessions opened towards the TA are closed. If the property is enabled, TA
+instance, once created (at 1st open session request), is never removed unless
+the TEE itself is restarted (boot/reboot).
+
+This property is meaningless if TA is NOT SingleInstance.
+
+OP-TEE TA flag `TA_FLAG_INSTANCE_KEEP_ALIVE` sets to configuration of this
+property.
+
+The boolean property is set to `true` if `TA_FLAGS` sets bit
+`TA_FLAG_INSTANCE_KEEP_ALIVE`, otherwise the boolean property is set to `false`.
+
+## 1.4. Heap Size Property
+
+`"gpd.ta.dataSize"` is a 32bit integer property of the TA.
+
+This property defines the size in bytes of the TA allocation pool, in which
+`TEE_Malloc()` and friends allocate memory.
+
+The value of the property must be defined by the macro `TA_DATA_SIZE` from
+**user_ta_header_defines.h**.
+
+## 1.5. Stack Size Property
+
+`"gpd.ta.stackSize"` is a 32bit integer property of the TA.
+
+This property defines the size in bytes of the stack used for TA execution.
+
+The value of the property must be defined by the macro `TA_STACK_SIZE` from
+**user_ta_header_defines.h**.
+
+# 2. TA Property Flags from the OP-TEE Extensions
+
+## 2.1. User Mode Property Flag
+
+`TA_FLAG_USER_MODE` is a bit flag supported by `TA_FLAGS`.
+
+This property flag is currently meaningless in OP-TEE. It may be set or not
+without impact on TA execution. All OP-TEE TAs are executed in user mode/level.
+
+Because of this we do not recommend to use this flag.
+
+## 2.2. Exec-in-DDR Property Flag
+
+`TA_FLAG_EXEC_DDR` is a bit flag supported by `TA_FLAGS`.
+
+This property flag is currently meaningless in OP-TEE. Nevertheless it shall
+be set. It is a legacy property flag that aimed at targeting location for the TA
+execution, internal RAM or external DDR.
+
+Therefore all TAs must set `TA_FLAG_EXEC_DDR` in `TA_FLAGS` in their
+**user_ta_header_defines.h** header file.
+
+Note: this flag will soon be deprecated.
+
+## 2.3. Secure Data Path Support Property Flag
+
+`TA_FLAG_SECURE_DATA_PATH` is a bit flag supported by `TA_FLAGS`.
+
+This property flag claims the secure data support from the OP-TEE OS for the TA.
+Refer to the OP-TEE OS for secure data path support.
+
+TAs that do not set `TA_FLAG_SECURE_DATA_PATH` in the value of `TA_FLAGS` will
+not be able to handle memory reference invocation parameters that relate to
+secure data path buffers.
+
+## 2.4. Remap Support Property Flag
+
+`TA_FLAG_REMAP_SUPPORT` is a bit flag supported by `TA_FLAGS`.
+
+This property flag is currently meaningless in OP-TEE and therefore we
+recommend to not use this flag.
+
+Note: this flag will soon be deprecated.
+
+## 2.5. Cache maintenance Property Flag
+
+`TA_FLAG_CACHE_MAINTENANCE` is a bit flag supported by `TA_FLAGS`.
+
+This property flag claims access to the cache maintenance API for the TA:
+`TEE_CacheXxxx()`. Refer to the OP-TEE to check if cache API support is
+enabled.
+
+TAs that do not set `TA_FLAG_CACHE_MAINTENANCE` in the value of their `TA_FLAGS`
+will not be able to call the cache maintenance API.
+
+[TA basics]: ./TA_basics.md
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/Android.mk
new file mode 100644
index 0000000..1223ab2
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/Android.mk
@@ -0,0 +1,39 @@
+ifeq ($(OPTEE_TEE_SUPPORT),true)
+###################### optee-hello-world ######################
+LOCAL_PATH := $(call my-dir)
+
+OPTEE_CLIENT_EXPORT = $(LOCAL_PATH)/../../optee_client/out/export
+
+## include variants like TA_DEV_KIT_DIR
+## and OPTEE_BIN
+INCLUDE_FOR_BUILD_TA := false
+include $(BUILD_OPTEE_MK)
+INCLUDE_FOR_BUILD_TA :=
+
+# TA_DEV_KIT_DIR must be set to non-empty value to
+# avoid the Android build scripts complaining about
+# includes pointing outside the Android source tree.
+# This var is expected to be set when OPTEE OS built.
+# We set the default value to an invalid path.
+TA_DEV_KIT_DIR ?= ../invalid_include_path
+$(warning TA_DEV_KIT_DIR:$(TA_DEV_KIT_DIR))
+-include $(TA_DEV_KIT_DIR)/host_include/conf.mk
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -DANDROID_BUILD
+LOCAL_CFLAGS += -Wall
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_SRC_FILES += host/main.c
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include \
+ $(OPTEE_CLIENT_EXPORT)/include \
+
+LOCAL_SHARED_LIBRARIES := libteec
+LOCAL_MODULE := optee_example_interrupt_gpt
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+# include $(LOCAL_PATH)/ta/Android.mk
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/CMakeLists.txt
new file mode 100644
index 0000000..1b46b4c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/CMakeLists.txt
@@ -0,0 +1,13 @@
+project (hello_world C)
+
+set (SRC host/main.c)
+
+add_executable (${PROJECT_NAME} ${SRC})
+
+target_include_directories(${PROJECT_NAME}
+ PRIVATE ta/include
+ PRIVATE include)
+
+target_link_libraries (${PROJECT_NAME} PRIVATE teec)
+
+install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/Makefile
new file mode 100644
index 0000000..70f7777
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/Makefile
@@ -0,0 +1,13 @@
+export V?=0
+
+# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
+HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
+TA_CROSS_COMPILE ?= $(CROSS_COMPILE)
+
+.PHONY: all
+all:
+ $(MAKE) -C host O=$(O)/host CROSS_COMPILE="$(HOST_CROSS_COMPILE)" --no-builtin-variables
+
+.PHONY: clean
+clean:
+ $(MAKE) -C host clean
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/host/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/host/Makefile
new file mode 100644
index 0000000..eb67a29
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/host/Makefile
@@ -0,0 +1,36 @@
+CC ?= $(CROSS_COMPILE)gcc
+LD ?= $(CROSS_COMPILE)ld
+AR ?= $(CROSS_COMPILE)ar
+NM ?= $(CROSS_COMPILE)nm
+OBJCOPY ?= $(CROSS_COMPILE)objcopy
+OBJDUMP ?= $(CROSS_COMPILE)objdump
+READELF ?= $(CROSS_COMPILE)readelf
+
+ifneq ($O,)
+out-dir := $O
+else
+out-dir := .
+endif
+
+OBJS = main.o
+OOBJS = $(foreach obj, $(OBJS), $(out-dir)/$(obj))
+
+CFLAGS += -Wall -I../ta/include -I$(TEEC_EXPORT)/include -I./include
+#Add/link other required libraries here
+LDADD += -lteec -L$(TEEC_EXPORT)/lib $(LDFLAGS)
+
+BINARY = $(out-dir)/optee_example_gpt_interrupt
+
+.PHONY: all
+all: $(BINARY)
+
+$(BINARY): $(OOBJS)
+ $(CC) -o $@ $< $(LDADD)
+
+.PHONY: clean
+clean:
+ rm -f $(OOBJS) $(BINARY)
+
+$(out-dir)/%.o: %.c
+ mkdir -p $(dir $@);
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/host/main.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/host/main.c
new file mode 100644
index 0000000..f152353
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/host/main.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* OP-TEE TEE client API (built by optee_client) */
+#include <tee_client_api.h>
+
+/* To the the UUID (found the the TA's h-file(s)) */
+#include <interrupt_gpt_ta.h>
+
+int main(int argc, char *argv[])
+{
+ TEEC_Result res;
+ TEEC_Context ctx;
+ TEEC_Session sess;
+ TEEC_Operation op;
+ TEEC_UUID uuid = PTA_GPT_TEST_PTA_UUID;
+ uint32_t err_origin;
+
+ /* Initialize a context connecting us to the TEE */
+ res = TEEC_InitializeContext(NULL, &ctx);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
+
+ /*
+ * Open a session to the "hello world" TA, the TA will print "hello
+ * world!" in the log when the session is created.
+ */
+ res = TEEC_OpenSession(&ctx, &sess, &uuid,
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
+ res, err_origin);
+
+ /*
+ * Execute a function in the TA by invoking it, in this case
+ * we're incrementing a number.
+ *
+ * The value of command ID part and how the parameters are
+ * interpreted is part of the interface provided by the TA.
+ */
+
+ /* Clear the TEEC_Operation struct */
+ memset(&op, 0, sizeof(op));
+
+ /*
+ * Prepare the argument. Pass a value in the first parameter,
+ * the remaining three parameters are unused.
+ */
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ op.params[0].value.a = 1;
+ op.params[0].value.b = 3;
+
+ /*
+ * PTA_CMD_GPT_INIT is the actual function in the TA to be
+ * called.
+ */
+ printf("Invoking TA to enable gpt %d\n", op.params[0].value.a);
+ res = TEEC_InvokeCommand(&sess, PTA_CMD_GPT_INIT, &op,
+ &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",
+ res, err_origin);
+ // printf("TA incremented value to %d\n", op.params[0].value.a);
+ printf("Waited %d seconds for gpt interrupt.\n", op.params[0].value.b);
+ /*
+ * We're done with the TA, close the session and
+ * destroy the context.
+ *
+ * The TA will print "Goodbye!" in the log when the
+ * session is closed.
+ */
+
+ TEEC_CloseSession(&sess);
+
+ TEEC_FinalizeContext(&ctx);
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/ta/include/interrupt_gpt_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/ta/include/interrupt_gpt_ta.h
new file mode 100644
index 0000000..9541ce3
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/ta/include/interrupt_gpt_ta.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TA_INTERRUPT_GPT_TA_H
+#define TA_INTERRUPT_GPT_TA_H
+
+
+/*
+ * This UUID is generated with uuidgen
+ * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html
+ */
+
+#define PTA_GPT_TEST_PTA_UUID { 0x472567ad, 0xa180, 0x402c, \
+ { 0x50, 0x95, 0x7b, 0x4e, 0xd3, 0xe0, 0x5e, 0x83 } }
+
+/* The function IDs implemented in this TA */
+#define PTA_CMD_GPT_INIT 0
+
+#endif /*TA_INTERRUPT_GPT_TA_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/ta/user_ta_header_defines.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/ta/user_ta_header_defines.h
new file mode 100644
index 0000000..fdfa6c4
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/gpt_interrupt/ta/user_ta_header_defines.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The name of this file must not be modified
+ */
+
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+/* To get the TA UUID definition */
+#include <hello_world_ta.h>
+
+#define TA_UUID TA_HELLO_WORLD_UUID
+
+/*
+ * TA properties: multi-instance TA, no specific attribute
+ * TA_FLAG_EXEC_DDR is meaningless but mandated.
+ */
+#define TA_FLAGS TA_FLAG_EXEC_DDR
+
+/* Provisioned stack size */
+#define TA_STACK_SIZE (2 * 1024)
+
+/* Provisioned heap size for TEE_Malloc() and friends */
+#define TA_DATA_SIZE (32 * 1024)
+
+/* Extra properties (give a version id and a string name) */
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
+ "Example of OP-TEE Hello World Trusted Application" }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } }
+
+#endif /* USER_TA_HEADER_DEFINES_H */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/Android.mk
new file mode 100644
index 0000000..7060ecb
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/Android.mk
@@ -0,0 +1,39 @@
+ifeq ($(OPTEE_TEE_SUPPORT),true)
+###################### optee-hello-world ######################
+LOCAL_PATH := $(call my-dir)
+
+OPTEE_CLIENT_EXPORT = $(LOCAL_PATH)/../../optee_client/out/export
+
+## include variants like TA_DEV_KIT_DIR
+## and OPTEE_BIN
+INCLUDE_FOR_BUILD_TA := false
+include $(BUILD_OPTEE_MK)
+INCLUDE_FOR_BUILD_TA :=
+
+# TA_DEV_KIT_DIR must be set to non-empty value to
+# avoid the Android build scripts complaining about
+# includes pointing outside the Android source tree.
+# This var is expected to be set when OPTEE OS built.
+# We set the default value to an invalid path.
+TA_DEV_KIT_DIR ?= ../invalid_include_path
+$(warning TA_DEV_KIT_DIR:$(TA_DEV_KIT_DIR))
+-include $(TA_DEV_KIT_DIR)/host_include/conf.mk
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -DANDROID_BUILD
+LOCAL_CFLAGS += -Wall
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_SRC_FILES += host/main.c
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include \
+ $(OPTEE_CLIENT_EXPORT)/include \
+
+LOCAL_SHARED_LIBRARIES := libteec
+LOCAL_MODULE := optee_example_hello_world
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+include $(LOCAL_PATH)/ta/Android.mk
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/CMakeLists.txt
new file mode 100644
index 0000000..1b46b4c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/CMakeLists.txt
@@ -0,0 +1,13 @@
+project (hello_world C)
+
+set (SRC host/main.c)
+
+add_executable (${PROJECT_NAME} ${SRC})
+
+target_include_directories(${PROJECT_NAME}
+ PRIVATE ta/include
+ PRIVATE include)
+
+target_link_libraries (${PROJECT_NAME} PRIVATE teec)
+
+install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/Makefile
new file mode 100644
index 0000000..e46c1c4
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/Makefile
@@ -0,0 +1,15 @@
+export V?=0
+
+# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
+HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
+TA_CROSS_COMPILE ?= $(CROSS_COMPILE)
+
+.PHONY: all
+all:
+ $(MAKE) -C host O=$(O)/host CROSS_COMPILE="$(HOST_CROSS_COMPILE)" --no-builtin-variables
+ $(MAKE) -C ta O=$(O)/ta CROSS_COMPILE="$(TA_CROSS_COMPILE)" LDFLAGS=""
+
+.PHONY: clean
+clean:
+ $(MAKE) -C host clean
+ $(MAKE) -C ta clean
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/host/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/host/Makefile
new file mode 100644
index 0000000..2785e80
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/host/Makefile
@@ -0,0 +1,35 @@
+CC ?= $(CROSS_COMPILE)gcc
+LD ?= $(CROSS_COMPILE)ld
+AR ?= $(CROSS_COMPILE)ar
+NM ?= $(CROSS_COMPILE)nm
+OBJCOPY ?= $(CROSS_COMPILE)objcopy
+OBJDUMP ?= $(CROSS_COMPILE)objdump
+READELF ?= $(CROSS_COMPILE)readelf
+
+ifneq ($O,)
+out-dir := $O
+else
+out-dir := .
+endif
+
+OBJS = main.o
+OOBJS = $(foreach obj, $(OBJS), $(out-dir)/$(obj))
+
+CFLAGS += -Wall -I../ta/include -I$(TEEC_EXPORT)/include -I./include
+#Add/link other required libraries here
+LDADD += -lteec -L$(TEEC_EXPORT)/lib $(LDFLAGS)
+
+BINARY = $(out-dir)/optee_example_hello_world
+.PHONY: all
+all: $(BINARY)
+
+$(BINARY): $(OOBJS)
+ $(CC) -o $@ $< $(LDADD)
+
+.PHONY: clean
+clean:
+ rm -f $(OOBJS) $(BINARY)
+
+$(out-dir)/%.o: %.c
+ mkdir -p $(dir $@);
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/host/main.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/host/main.c
new file mode 100644
index 0000000..43f57ab
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/host/main.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+
+/* OP-TEE TEE client API (built by optee_client) */
+#include <tee_client_api.h>
+
+/* To the the UUID (found the the TA's h-file(s)) */
+#include <hello_world_ta.h>
+
+int main(int argc, char *argv[])
+{
+ TEEC_Result res;
+ TEEC_Context ctx;
+ TEEC_Session sess;
+ TEEC_Operation op;
+ TEEC_UUID uuid = TA_HELLO_WORLD_UUID;
+ uint32_t err_origin;
+
+ /* Initialize a context connecting us to the TEE */
+ res = TEEC_InitializeContext(NULL, &ctx);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
+
+ /*
+ * Open a session to the "hello world" TA, the TA will print "hello
+ * world!" in the log when the session is created.
+ */
+ res = TEEC_OpenSession(&ctx, &sess, &uuid,
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
+ res, err_origin);
+
+ /*
+ * Execute a function in the TA by invoking it, in this case
+ * we're incrementing a number.
+ *
+ * The value of command ID part and how the parameters are
+ * interpreted is part of the interface provided by the TA.
+ */
+
+ /* Clear the TEEC_Operation struct */
+ memset(&op, 0, sizeof(op));
+
+ /*
+ * Prepare the argument. Pass a value in the first parameter,
+ * the remaining three parameters are unused.
+ */
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ op.params[0].value.a = 42;
+
+ /*
+ * TA_HELLO_WORLD_CMD_INC_VALUE is the actual function in the TA to be
+ * called.
+ */
+ printf("Invoking TA to increment %d\n", op.params[0].value.a);
+ res = TEEC_InvokeCommand(&sess, TA_HELLO_WORLD_CMD_INC_VALUE, &op,
+ &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",
+ res, err_origin);
+ printf("TA incremented value to %d\n", op.params[0].value.a);
+
+ /*
+ * We're done with the TA, close the session and
+ * destroy the context.
+ *
+ * The TA will print "Goodbye!" in the log when the
+ * session is closed.
+ */
+
+ TEEC_CloseSession(&sess);
+
+ TEEC_FinalizeContext(&ctx);
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/Android.mk
new file mode 100644
index 0000000..ed416e0
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/Android.mk
@@ -0,0 +1,5 @@
+LOCAL_PATH := $(call my-dir)
+
+local_module := 8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta
+$(warning local_module:$(local_module))
+include $(BUILD_OPTEE_MK)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/Makefile
new file mode 100644
index 0000000..3d2e6fc
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/Makefile
@@ -0,0 +1,13 @@
+CFG_TEE_TA_LOG_LEVEL ?= 4
+CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
+
+# The UUID for the Trusted Application
+BINARY=8aaaf200-2450-11e4-abe2-0002a5d5c51b
+
+-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
+clean:
+ @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
+ @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/hello_world_ta.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/hello_world_ta.c
new file mode 100644
index 0000000..2423b30
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/hello_world_ta.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include <hello_world_ta.h>
+
+/*
+ * Called when the instance of the TA is created. This is the first call in
+ * the TA.
+ */
+TEE_Result TA_CreateEntryPoint(void)
+{
+ DMSG("has been called");
+
+ return TEE_SUCCESS;
+}
+
+/*
+ * Called when the instance of the TA is destroyed if the TA has not
+ * crashed or panicked. This is the last call in the TA.
+ */
+void TA_DestroyEntryPoint(void)
+{
+ DMSG("has been called");
+}
+
+/*
+ * Called when a new session is opened to the TA. *sess_ctx can be updated
+ * with a value to be able to identify this session in subsequent calls to the
+ * TA. In this function you will normally do the global initialization for the
+ * TA.
+ */
+TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types,
+ TEE_Param __maybe_unused params[4],
+ void __maybe_unused **sess_ctx)
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ DMSG("has been called");
+
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ /* Unused parameters */
+ (void)¶ms;
+ (void)&sess_ctx;
+
+ /*
+ * The DMSG() macro is non-standard, TEE Internal API doesn't
+ * specify any means to logging from a TA.
+ */
+ IMSG("Hello World!\n");
+
+ /* If return value != TEE_SUCCESS the session will not be created. */
+ return TEE_SUCCESS;
+}
+
+/*
+ * Called when a session is closed, sess_ctx hold the value that was
+ * assigned by TA_OpenSessionEntryPoint().
+ */
+void TA_CloseSessionEntryPoint(void __maybe_unused *sess_ctx)
+{
+ (void)&sess_ctx; /* Unused parameter */
+ IMSG("Goodbye!\n");
+}
+
+static TEE_Result inc_value(uint32_t param_types,
+ TEE_Param params[4])
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ DMSG("has been called");
+
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ IMSG("Got value: %u from NW", params[0].value.a);
+ params[0].value.a++;
+ IMSG("Increase value to: %u", params[0].value.a);
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result dec_value(uint32_t param_types,
+ TEE_Param params[4])
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ DMSG("has been called");
+
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ IMSG("Got value: %u from NW", params[0].value.a);
+ params[0].value.a--;
+ IMSG("Decrease value to: %u", params[0].value.a);
+
+ return TEE_SUCCESS;
+}
+/*
+ * Called when a TA is invoked. sess_ctx hold that value that was
+ * assigned by TA_OpenSessionEntryPoint(). The rest of the paramters
+ * comes from normal world.
+ */
+TEE_Result TA_InvokeCommandEntryPoint(void __maybe_unused *sess_ctx,
+ uint32_t cmd_id,
+ uint32_t param_types, TEE_Param params[4])
+{
+ (void)&sess_ctx; /* Unused parameter */
+
+ switch (cmd_id) {
+ case TA_HELLO_WORLD_CMD_INC_VALUE:
+ return inc_value(param_types, params);
+ case TA_HELLO_WORLD_CMD_DEC_VALUE:
+ return dec_value(param_types, params);
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/include/hello_world_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/include/hello_world_ta.h
new file mode 100644
index 0000000..8e40276
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/include/hello_world_ta.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TA_HELLO_WORLD_H
+#define TA_HELLO_WORLD_H
+
+
+/*
+ * This UUID is generated with uuidgen
+ * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html
+ */
+#define TA_HELLO_WORLD_UUID \
+ { 0x8aaaf200, 0x2450, 0x11e4, \
+ { 0xab, 0xe2, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} }
+
+/* The function IDs implemented in this TA */
+#define TA_HELLO_WORLD_CMD_INC_VALUE 0
+#define TA_HELLO_WORLD_CMD_DEC_VALUE 1
+
+#endif /*TA_HELLO_WORLD_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/sub.mk
new file mode 100644
index 0000000..957af07
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/sub.mk
@@ -0,0 +1,5 @@
+global-incdirs-y += include
+srcs-y += hello_world_ta.c
+
+# To remove a certain compiler flag, add a line like this
+#cflags-template_ta.c-y += -Wno-strict-prototypes
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/user_ta_header_defines.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/user_ta_header_defines.h
new file mode 100644
index 0000000..fdfa6c4
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hello_world/ta/user_ta_header_defines.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The name of this file must not be modified
+ */
+
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+/* To get the TA UUID definition */
+#include <hello_world_ta.h>
+
+#define TA_UUID TA_HELLO_WORLD_UUID
+
+/*
+ * TA properties: multi-instance TA, no specific attribute
+ * TA_FLAG_EXEC_DDR is meaningless but mandated.
+ */
+#define TA_FLAGS TA_FLAG_EXEC_DDR
+
+/* Provisioned stack size */
+#define TA_STACK_SIZE (2 * 1024)
+
+/* Provisioned heap size for TEE_Malloc() and friends */
+#define TA_DATA_SIZE (32 * 1024)
+
+/* Extra properties (give a version id and a string name) */
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
+ "Example of OP-TEE Hello World Trusted Application" }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } }
+
+#endif /* USER_TA_HEADER_DEFINES_H */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/Android.mk
new file mode 100644
index 0000000..917c941
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/Android.mk
@@ -0,0 +1,24 @@
+ifeq ($(OPTEE_TEE_SUPPORT),true)
+###################### HOTP ######################
+LOCAL_PATH := $(call my-dir)
+
+OPTEE_CLIENT_EXPORT = $(LOCAL_PATH)/../../optee_client/out/export
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -DANDROID_BUILD
+LOCAL_CFLAGS += -Wall
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_SRC_FILES += host/main.c
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include \
+ $(OPTEE_CLIENT_EXPORT)/include
+
+LOCAL_SHARED_LIBRARIES := libteec
+LOCAL_MODULE := hotp
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+include $(LOCAL_PATH)/ta/Android.mk
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/CMakeLists.txt
new file mode 100644
index 0000000..8d61852
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/CMakeLists.txt
@@ -0,0 +1,13 @@
+project (hotp C)
+
+set (SRC host/main.c)
+
+add_executable (${PROJECT_NAME} ${SRC})
+
+target_include_directories(${PROJECT_NAME}
+ PRIVATE ta/include
+ PRIVATE include)
+
+target_link_libraries (${PROJECT_NAME} PRIVATE teec)
+
+install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/Makefile
new file mode 100644
index 0000000..c6526b9
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/Makefile
@@ -0,0 +1,15 @@
+export V ?= 0
+
+# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
+HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
+TA_CROSS_COMPILE ?= $(CROSS_COMPILE)
+
+.PHONY: all
+all:
+ $(MAKE) -C host O=$(O)/host CROSS_COMPILE="$(HOST_CROSS_COMPILE)" --no-builtin-variables
+ $(MAKE) -C ta O=$(O)/ta CROSS_COMPILE="$(TA_CROSS_COMPILE)" LDFLAGS=""
+
+.PHONY: clean
+clean:
+ $(MAKE) -C host clean
+ $(MAKE) -C ta clean
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/README.md b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/README.md
new file mode 100644
index 0000000..4e5398c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/README.md
@@ -0,0 +1,54 @@
+# HMAC based One Time Password in OP-TEE
+[HMAC] based One Time Passwords or shortly just 'HOTP' has been around for many
+years and was initially defined in [RFC4226] back in 2005. Since then it has
+been a popular choice for doing [two factor authentication]. With the
+implementation here we are showing how one could leverage OP-TEE for generating
+such HMAC based One Time Passwords in a secure manner.
+
+## Client (OP-TEE) / Server solution
+The most common way of using HOTP is in a client/server setup, where the client
+needs to authenticate itself to be able to get access to some resources on the
+server. In those cases the server will ask for an One Time Password, the client
+will generate that and send it over to the server and if the server is OK with
+the password it will grant access to the client.
+
+Technically how it is working is that the server and the client needs to agree
+on shared key ('`K`') and also start from the same counter ('`C`'). How that is
+done in practice is another topic, but RFC4226 has some discussion about it. You
+should at least have a secure channel between the client and the server when
+sharing the key, but even better would be if you could establish a secure
+channel all the way down to the TEE (currently we have TCP/UDP support in
+OP-TEE, but not TLS).
+
+When both the server and the client knows about and use the same key and
+counter they can start doing client authentication using HOTP. In short what
+happens is that both the client and the server computes the same HOTP and the
+server compares the result of both computations (which should be the same to
+grant access). How that could work can be seen in the sequence diagram below.
+
+In the current implementation we have OP-TEE acting as a client and the server
+is a remote service running somewhere else. There is no server implemented, but
+that should be pretty easy to add in a real scenario. The important thing here
+is to be able to register the shared key in the TEE and to get HOTP values from
+the TEE on request.
+
+Since the current implementation works as a client we do not need to think about
+implementing the look-ahead synchronization window ('`s`') nor do we have to
+think about adding throttling (which prevents/slows down brute force attacks).
+
+#### Sequence diagram - Client / Server
+
+
+## Client / Server (OP-TEE)?
+Even though the current implementation works as a HOTP client, there is nothing
+saying that the implementation cannot be updated to also work as the validating
+server. One could for example have a simple device (a [security token] only
+generating one time passwords) and use the TEE as a validating service to open
+up other secure services.
+
+[HMAC]: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code
+<!--- The link below to mscgen.js.org should be updated when regenerating the image -->
+[link to sequence diagram]: https://mscgen.js.org/?lang=xu&msc=msc%20%7B%0A%20%20wordwraparcs%3Doff%2C%0A%20%20hscale%3D%220.95%22%2C%0A%20%20watermark%3D%22HOTP%20OP-TEE%20%22%3B%0A%0A%20%20tee%20%5Blabel%3D%22TEE%20%2F%20TA%22%2C%20linecolor%3D%22darkgreen%22%2C%20textcolor%3D%22white%22%2C%20textbgcolor%3D%22darkgreen%22%2C%20arclinecolor%3D%22darkgreen%22%2C%20arctextcolor%3D%22darkgreen%22%5D%2C%0A%20%20client%20%5Blabel%3D%22Client%22%2C%20linecolor%3D%22darkgreen%22%2C%20textcolor%3D%22white%22%2C%20textbgcolor%3D%22darkgreen%22%2C%20arclinecolor%3D%22darkgreen%22%2C%20arctextcolor%3D%22darkgreen%22%5D%2C%0A%20%20server%20%5Blabel%3D%22Server%22%2C%20linecolor%3D%22%233a5795%22%2C%20textcolor%3D%22white%22%2C%20textbgcolor%3D%22%233a5795%22%2C%20arclinecolor%3D%22%233a5795%22%2C%20arctextcolor%3D%22%233a5795%22%5D%3B%0A%20%20%0A%20%20client%20note%20client%20%5Blabel%3D%22Shared%20key%20needs%5Cnto%20be%20handled%5Cnusing%20secure%5Cnchannels%20(TLS%2FSSL)%22%5D%3B%0A%20%20client%20%3C%3D%3E%20server%20%5Blabel%3D%22Agree%20on%20shared%20key%22%5D%3B%0A%20%20client%20%3D%3E%20tee%20%5Blabel%3D%22Store%20shared%20key%22%5D%3B%0A%20%20client%20%3D%3E%20server%20%5Blabel%3D%22Login%22%5D%3B%0A%20%20server%20%3D%3E%20client%20%5Blabel%3D%22Request%20HOTP%22%5D%3B%0A%20%20client%20%3D%3E%20tee%20%5Blabel%3D%22Get%20HOTP%20from%20TEE%22%5D%3B%0A%20%20tee%20%3E%3E%20tee%20%5Blabel%3D%22Calulate%20HOTP%22%5D%3B%0A%20%20tee%20%3E%3E%20client%20%5Blabel%3D%22HOPT%20value%22%5D%3B%0A%20%20client%20%3E%3E%20server%20%5Blabel%3D%22Send%20HTOP%20value%22%5D%3B%0A%20%20server%20%3E%3E%20server%20%5Blabel%3D%22Calulate%20HOTP%20locally%22%5D%3B%0A%20%20client%20alt%20server%20%5Blabel%3D%22Client%20HOTP%20%3D%3D%20Server%20HOTP%3F%22%2C%20linecolor%3D%22grey%22%2C%20textbgcolor%3D%22white%22%5D%20%7B%0A%20%20%09%0A%20%20%20%20---%20%5Blabel%3D%22Yes%22%2C%20linecolor%3Dgrey%2C%20textbgcolor%3Dwhite%5D%3B%0A%20%20%20%20server%20%3E%3E%20client%20%5Blabel%3D%22Grant%20access%22%5D%3B%0A%20%20%20%20%0A%20%20%20%20---%20%5Blabel%3D%22No%22%2C%20linecolor%3Dgrey%2C%20textbgcolor%3Dwhite%5D%3B%0A%20%20%20%20server%20%3E%3E%20client%20%5Blabel%3D%22Access%20denied%22%5D%3B%0A%20%20%7D%3B%0A%7D
+[RFC4226]: https://www.ietf.org/rfc/rfc4226.txt
+[security token]: https://en.wikipedia.org/wiki/Security_token
+[two factor authentication]: https://en.wikipedia.org/wiki/Multi-factor_authentication
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/host/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/host/Makefile
new file mode 100644
index 0000000..51e2415
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/host/Makefile
@@ -0,0 +1,36 @@
+CC ?= $(CROSS_COMPILE)gcc
+LD ?= $(CROSS_COMPILE)ld
+AR ?= $(CROSS_COMPILE)ar
+NM ?= $(CROSS_COMPILE)nm
+OBJCOPY ?= $(CROSS_COMPILE)objcopy
+OBJDUMP ?= $(CROSS_COMPILE)objdump
+READELF ?= $(CROSS_COMPILE)readelf
+
+ifneq ($O,)
+out-dir := $O
+else
+out-dir := .
+endif
+
+OBJS = main.o
+OOBJS = $(foreach obj, $(OBJS), $(out-dir)/$(obj))
+
+CFLAGS += -Wall -I../ta/include -I./include
+CFLAGS += -I$(TEEC_EXPORT)/include
+LDADD += -lteec -L$(TEEC_EXPORT)/lib $(LDFLAGS)
+
+BINARY = $(out-dir)/optee_example_hotp
+
+.PHONY: all
+all: $(BINARY)
+
+$(BINARY): $(OOBJS)
+ $(CC) -o $@ $< $(LDADD)
+
+.PHONY: clean
+clean:
+ rm -f $(OOBJS) $(BINARY)
+
+$(out-dir)/%.o: %.c
+ mkdir -p $(dir $@);
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/host/main.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/host/main.c
new file mode 100644
index 0000000..c816b40
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/host/main.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+
+/* OP-TEE TEE client API (built by optee_client) */
+#include <tee_client_api.h>
+
+/* For the UUID (found in the TA's h-file(s)) */
+#include <hotp_ta.h>
+
+struct test_value {
+ size_t count;
+ uint32_t expected;
+};
+
+/*
+ * Test values coming from the RFC4226 specification.
+ */
+struct test_value rfc4226_test_values[] = {
+ { 0, 755224 },
+ { 1, 287082 },
+ { 2, 359152 },
+ { 3, 969429 },
+ { 4, 338314 },
+ { 5, 254676 },
+ { 6, 287922 },
+ { 7, 162583 },
+ { 8, 399871 },
+ { 9, 520489 }
+};
+
+int main(int argc, char *argv[])
+{
+ TEEC_Context ctx;
+ TEEC_Operation op = { 0 };
+ TEEC_Result res;
+ TEEC_Session sess;
+ TEEC_UUID uuid = TA_HOTP_UUID;
+
+ int i;
+ uint32_t err_origin;
+ uint32_t hotp_value;
+
+ /*
+ * Shared key K ("12345678901234567890"), this is the key used in
+ * RFC4226 - Test Vectors.
+ */
+ uint8_t K[] = {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+ 0x37, 0x38, 0x39, 0x30
+ };
+
+ /* Initialize a context connecting us to the TEE */
+ res = TEEC_InitializeContext(NULL, &ctx);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
+
+ res = TEEC_OpenSession(&ctx, &sess, &uuid,
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
+ res, err_origin);
+
+ /* 1. Register the shared key */
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
+ TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ op.params[0].tmpref.buffer = K;
+ op.params[0].tmpref.size = sizeof(K);
+
+ fprintf(stdout, "Register the shared key: %s\n", K);
+ res = TEEC_InvokeCommand(&sess, TA_HOTP_CMD_REGISTER_SHARED_KEY,
+ &op, &err_origin);
+ if (res != TEEC_SUCCESS) {
+ fprintf(stderr, "TEEC_InvokeCommand failed with code 0x%x "
+ "origin 0x%x\n",
+ res, err_origin);
+ goto exit;
+ }
+
+ /* 2. Get HMAC based One Time Passwords */
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+
+ for (i = 0; i < sizeof(rfc4226_test_values) / sizeof(struct test_value);
+ i++) {
+ res = TEEC_InvokeCommand(&sess, TA_HOTP_CMD_GET_HOTP, &op,
+ &err_origin);
+ if (res != TEEC_SUCCESS) {
+ fprintf(stderr, "TEEC_InvokeCommand failed with code "
+ "0x%x origin 0x%x\n", res, err_origin);
+ goto exit;
+ }
+
+ hotp_value = op.params[0].value.a;
+ fprintf(stdout, "HOTP: %d\n", hotp_value);
+
+ if (hotp_value != rfc4226_test_values[i].expected) {
+ fprintf(stderr, "Got unexpected HOTP from TEE! "
+ "Expected: %d, got: %d\n",
+ rfc4226_test_values[i].expected, hotp_value);
+ }
+ }
+exit:
+ TEEC_CloseSession(&sess);
+ TEEC_FinalizeContext(&ctx);
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/img/sequence_diagram_01.png b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/img/sequence_diagram_01.png
new file mode 100644
index 0000000..61ecb3d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/img/sequence_diagram_01.png
Binary files differ
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/Android.mk
new file mode 100644
index 0000000..036c131
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH := $(call my-dir)
+
+local_module := 484d4143-2d53-4841-3120-4a6f636b6542.ta
+include $(BUILD_OPTEE_MK)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/Makefile
new file mode 100644
index 0000000..a719ab1
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/Makefile
@@ -0,0 +1,13 @@
+CFG_TEE_TA_LOG_LEVEL ?= 3
+CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
+
+# The UUID for the Trusted Application
+BINARY=484d4143-2d53-4841-3120-4a6f636b6542
+
+-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
+clean:
+ @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
+ @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/hotp_ta.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/hotp_ta.c
new file mode 100644
index 0000000..224be60
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/hotp_ta.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+#include <hotp_ta.h>
+#include <string.h>
+#include <tee_internal_api_extensions.h>
+#include <tee_internal_api.h>
+
+/* The size of a SHA1 hash in bytes. */
+#define SHA1_HASH_SIZE 20
+
+/* GP says that for HMAC SHA-1, max is 512 bits and min 80 bits. */
+#define MAX_KEY_SIZE 64 /* In bytes */
+#define MIN_KEY_SIZE 10 /* In bytes */
+
+/* Dynamic Binary Code 2 Modulo, which is 10^6 according to the spec. */
+#define DBC2_MODULO 1000000
+
+/*
+ * Currently this only supports a single key, in the future this could be
+ * updated to support multiple users, all with different unique keys (stored
+ * using secure storage).
+ */
+static uint8_t K[MAX_KEY_SIZE];
+static uint32_t K_len;
+
+/* The counter as defined by RFC4226. */
+static uint8_t counter[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+
+/*
+ * HMAC a block of memory to produce the authentication tag
+ * @param key The secret key
+ * @param keylen The length of the secret key (bytes)
+ * @param in The data to HMAC
+ * @param inlen The length of the data to HMAC (bytes)
+ * @param out [out] Destination of the authentication tag
+ * @param outlen [in/out] Max size and resulting size of authentication tag
+ */
+static TEE_Result hmac_sha1(const uint8_t *key, const size_t keylen,
+ const uint8_t *in, const size_t inlen,
+ uint8_t *out, uint32_t *outlen)
+{
+ TEE_Attribute attr = { 0 };
+ TEE_ObjectHandle key_handle = TEE_HANDLE_NULL;
+ TEE_OperationHandle op_handle = TEE_HANDLE_NULL;
+ TEE_Result res = TEE_SUCCESS;
+
+ if (keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ if (!in || !out || !outlen)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ /*
+ * 1. Allocate cryptographic (operation) handle for the HMAC operation.
+ * Note that the expected size here is in bits (and therefore times
+ * 8)!
+ */
+ res = TEE_AllocateOperation(&op_handle, TEE_ALG_HMAC_SHA1, TEE_MODE_MAC,
+ keylen * 8);
+ if (res != TEE_SUCCESS) {
+ EMSG("0x%08x", res);
+ goto exit;
+ }
+
+ /*
+ * 2. Allocate a container (key handle) for the HMAC attributes. Note
+ * that the expected size here is in bits (and therefore times 8)!
+ */
+ res = TEE_AllocateTransientObject(TEE_TYPE_HMAC_SHA1, keylen * 8,
+ &key_handle);
+ if (res != TEE_SUCCESS) {
+ EMSG("0x%08x", res);
+ goto exit;
+ }
+
+ /*
+ * 3. Initialize the attributes, i.e., point to the actual HMAC key.
+ * Here, the expected size is in bytes and not bits as above!
+ */
+ TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, keylen);
+
+ /* 4. Populate/assign the attributes with the key object */
+ res = TEE_PopulateTransientObject(key_handle, &attr, 1);
+ if (res != TEE_SUCCESS) {
+ EMSG("0x%08x", res);
+ goto exit;
+ }
+
+ /* 5. Associate the key (object) with the operation */
+ res = TEE_SetOperationKey(op_handle, key_handle);
+ if (res != TEE_SUCCESS) {
+ EMSG("0x%08x", res);
+ goto exit;
+ }
+
+ /* 6. Do the HMAC operations */
+ TEE_MACInit(op_handle, NULL, 0);
+ TEE_MACUpdate(op_handle, in, inlen);
+ res = TEE_MACComputeFinal(op_handle, NULL, 0, out, outlen);
+exit:
+ if (op_handle != TEE_HANDLE_NULL)
+ TEE_FreeOperation(op_handle);
+
+ /* It is OK to call this when key_handle is TEE_HANDLE_NULL */
+ TEE_FreeTransientObject(key_handle);
+
+ return res;
+}
+
+/*
+ * Truncate function working as described in RFC4226.
+ */
+static void truncate(uint8_t *hmac_result, uint32_t *bin_code)
+{
+ int offset = hmac_result[19] & 0xf;
+
+ *bin_code = (hmac_result[offset] & 0x7f) << 24 |
+ (hmac_result[offset+1] & 0xff) << 16 |
+ (hmac_result[offset+2] & 0xff) << 8 |
+ (hmac_result[offset+3] & 0xff);
+
+ *bin_code %= DBC2_MODULO;
+}
+
+static TEE_Result register_shared_key(uint32_t param_types, TEE_Param params[4])
+{
+ TEE_Result res = TEE_SUCCESS;
+
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (param_types != exp_param_types) {
+ EMSG("Expected: 0x%x, got: 0x%x", exp_param_types, param_types);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ memset(K, 0, sizeof(K));
+ memcpy(K, params[0].memref.buffer, params[0].memref.size);
+
+ K_len = params[0].memref.size;
+ DMSG("Got shared key %s (%u bytes).", K, params[0].memref.size);
+
+ return res;
+}
+
+static TEE_Result get_hotp(uint32_t param_types, TEE_Param params[4])
+{
+ TEE_Result res = TEE_SUCCESS;
+ uint32_t hotp_val;
+ uint8_t mac[SHA1_HASH_SIZE];
+ uint32_t mac_len = sizeof(mac);
+ int i;
+
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (param_types != exp_param_types) {
+ EMSG("Expected: 0x%x, got: 0x%x", exp_param_types, param_types);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ res = hmac_sha1(K, K_len, counter, sizeof(counter), mac, &mac_len);
+
+ /* Increment the counter. */
+ for (i = sizeof(counter) - 1; i >= 0; i--) {
+ if (++counter[i])
+ break;
+ }
+
+ truncate(mac, &hotp_val);
+ DMSG("HOTP is: %d", hotp_val);
+ params[0].value.a = hotp_val;
+
+ return res;
+}
+
+/*******************************************************************************
+ * Mandatory TA functions.
+ ******************************************************************************/
+TEE_Result TA_CreateEntryPoint(void)
+{
+ return TEE_SUCCESS;
+}
+
+void TA_DestroyEntryPoint(void)
+{
+}
+
+TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types,
+ TEE_Param __unused params[4],
+ void __unused **sess_ctx)
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ return TEE_SUCCESS;
+}
+
+void TA_CloseSessionEntryPoint(void __unused *sess_ctx)
+{
+}
+
+TEE_Result TA_InvokeCommandEntryPoint(void __unused *sess_ctx,
+ uint32_t cmd_id,
+ uint32_t param_types, TEE_Param params[4])
+{
+ switch (cmd_id) {
+ case TA_HOTP_CMD_REGISTER_SHARED_KEY:
+ return register_shared_key(param_types, params);
+
+ case TA_HOTP_CMD_GET_HOTP:
+ return get_hotp(param_types, params);
+
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/include/hotp_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/include/hotp_ta.h
new file mode 100644
index 0000000..b9a787c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/include/hotp_ta.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+#ifndef __HOTP_TA_H__
+#define __HOTP_TA_H__
+
+/*
+ * This TA implements HOTP according to:
+ * https://www.ietf.org/rfc/rfc4226.txt
+ */
+
+#define TA_HOTP_UUID \
+ { 0x484d4143, 0x2d53, 0x4841, \
+ { 0x31, 0x20, 0x4a, 0x6f, 0x63, 0x6b, 0x65, 0x42 } }
+
+/* The function ID(s) implemented in this TA */
+#define TA_HOTP_CMD_REGISTER_SHARED_KEY 0
+#define TA_HOTP_CMD_GET_HOTP 1
+
+#endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/sub.mk
new file mode 100644
index 0000000..122c5bb
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/sub.mk
@@ -0,0 +1,2 @@
+global-incdirs-y += include
+srcs-y += hotp_ta.c
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/user_ta_header_defines.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/user_ta_header_defines.h
new file mode 100644
index 0000000..5018a69
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/hotp/ta/user_ta_header_defines.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/* The name of this file must not be modified */
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+ /* To get the TA_HOTP_UUID define */
+#include <hotp_ta.h>
+
+#define TA_UUID TA_HOTP_UUID
+
+#define TA_FLAGS TA_FLAG_EXEC_DDR
+
+/* Provisioned stack size */
+#define TA_STACK_SIZE (2 * 1024)
+
+/* Provisioned heap size for TEE_Malloc() and friends */
+#define TA_DATA_SIZE (32 * 1024)
+
+/* Extra properties (give a version id and a string name) */
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
+ "HMAC-Based One-Time Password Algorithm (RFC4226)" }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } }
+
+#endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/Android.mk
new file mode 100644
index 0000000..72800e2
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/Android.mk
@@ -0,0 +1,24 @@
+ifeq ($(OPTEE_TEE_SUPPORT),true)
+###################### optee-random ######################
+LOCAL_PATH := $(call my-dir)
+
+OPTEE_CLIENT_EXPORT = $(LOCAL_PATH)/../../optee_client/out/export
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -DANDROID_BUILD
+LOCAL_CFLAGS += -Wall
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_SRC_FILES += host/main.c
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include \
+ $(OPTEE_CLIENT_EXPORT)/include
+
+LOCAL_SHARED_LIBRARIES := libteec
+LOCAL_MODULE := optee_example_random
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+include $(LOCAL_PATH)/ta/Android.mk
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/CMakeLists.txt
new file mode 100644
index 0000000..c0f1a8a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/CMakeLists.txt
@@ -0,0 +1,13 @@
+project (random C)
+
+set (SRC host/main.c)
+
+add_executable (${PROJECT_NAME} ${SRC})
+
+target_include_directories(${PROJECT_NAME}
+ PRIVATE ta/include
+ PRIVATE include)
+
+target_link_libraries (${PROJECT_NAME} PRIVATE teec)
+
+install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/Makefile
new file mode 100644
index 0000000..c6526b9
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/Makefile
@@ -0,0 +1,15 @@
+export V ?= 0
+
+# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
+HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
+TA_CROSS_COMPILE ?= $(CROSS_COMPILE)
+
+.PHONY: all
+all:
+ $(MAKE) -C host O=$(O)/host CROSS_COMPILE="$(HOST_CROSS_COMPILE)" --no-builtin-variables
+ $(MAKE) -C ta O=$(O)/ta CROSS_COMPILE="$(TA_CROSS_COMPILE)" LDFLAGS=""
+
+.PHONY: clean
+clean:
+ $(MAKE) -C host clean
+ $(MAKE) -C ta clean
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/host/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/host/Makefile
new file mode 100644
index 0000000..cec7fb3
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/host/Makefile
@@ -0,0 +1,36 @@
+CC ?= $(CROSS_COMPILE)gcc
+LD ?= $(CROSS_COMPILE)ld
+AR ?= $(CROSS_COMPILE)ar
+NM ?= $(CROSS_COMPILE)nm
+OBJCOPY ?= $(CROSS_COMPILE)objcopy
+OBJDUMP ?= $(CROSS_COMPILE)objdump
+READELF ?= $(CROSS_COMPILE)readelf
+
+ifneq ($O,)
+out-dir := $O
+else
+out-dir := .
+endif
+
+OBJS = main.o
+OOBJS = $(foreach obj, $(OBJS), $(out-dir)/$(obj))
+
+CFLAGS += -Wall -I../ta/include -I./include
+CFLAGS += -I$(TEEC_EXPORT)/include
+LDADD += -lteec -L$(TEEC_EXPORT)/lib $(LDFLAGS)
+
+BINARY = $(out-dir)/optee_example_random
+
+.PHONY: all
+all: $(BINARY)
+
+$(BINARY): $(OOBJS)
+ $(CC) -o $@ $< $(LDADD)
+
+.PHONY: clean
+clean:
+ rm -f $(OOBJS) $(BINARY)
+
+$(out-dir)/%.o: %.c
+ mkdir -p $(dir $@);
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/host/main.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/host/main.c
new file mode 100644
index 0000000..65318c6
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/host/main.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+
+/* OP-TEE TEE client API (built by optee_client) */
+#include <tee_client_api.h>
+
+/* To the the UUID (found the the TA's h-file(s)) */
+#include <random_ta.h>
+
+int main(int argc, char *argv[])
+{
+ TEEC_Result res;
+ TEEC_Context ctx;
+ TEEC_Session sess;
+ TEEC_Operation op = { 0 };
+ TEEC_UUID uuid = TA_RANDOM_UUID;
+ uint8_t random_uuid[16] = { 0 };
+ uint32_t err_origin;
+ int i;
+
+ /* Initialize a context connecting us to the TEE */
+ res = TEEC_InitializeContext(NULL, &ctx);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
+
+ /*
+ * Open a session to the Random example TA, the TA will print "hello
+ * world!" in the log when the session is created.
+ */
+ res = TEEC_OpenSession(&ctx, &sess, &uuid,
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
+ res, err_origin);
+
+ /*
+ * Execute a function in the TA by invoking it, in this case
+ * we're incrementing a number.
+ *
+ * The value of command ID part and how the parameters are
+ * interpreted is part of the interface provided by the TA.
+ */
+
+ /* Clear the TEEC_Operation struct */
+ memset(&op, 0, sizeof(op));
+
+ /*
+ * Prepare the argument. Pass a value in the first parameter,
+ * the remaining three parameters are unused.
+ */
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT,
+ TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ op.params[0].tmpref.buffer = random_uuid;
+ op.params[0].tmpref.size = sizeof(random_uuid);
+
+ /*
+ * TA_EXAMPLE_RANDOM_GENERATE is the actual function in the TA to be
+ * called.
+ */
+ printf("Invoking TA to generate random UUID... \n");
+ res = TEEC_InvokeCommand(&sess, TA_RANDOM_CMD_GENERATE,
+ &op, &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",
+ res, err_origin);
+
+ printf("TA generated UUID value = 0x");
+ for (i = 0; i < 16; i++)
+ printf("%x", random_uuid[i]);
+ printf("\n");
+
+ /*
+ * We're done with the TA, close the session and
+ * destroy the context.
+ *
+ * The TA will print "Goodbye!" in the log when the
+ * session is closed.
+ */
+
+ TEEC_CloseSession(&sess);
+
+ TEEC_FinalizeContext(&ctx);
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/Android.mk
new file mode 100644
index 0000000..edbb4ad
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH := $(call my-dir)
+
+local_module := b6c53aba-9669-4668-a7f2-205629d00f86.ta
+include $(BUILD_OPTEE_MK)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/Makefile
new file mode 100644
index 0000000..066c54e
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/Makefile
@@ -0,0 +1,13 @@
+CFG_TEE_TA_LOG_LEVEL ?= 4
+CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
+
+# The UUID for the Trusted Application
+BINARY=b6c53aba-9669-4668-a7f2-205629d00f86
+
+-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
+clean:
+ @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
+ @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/include/random_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/include/random_ta.h
new file mode 100644
index 0000000..30eeead
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/include/random_ta.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RANDOM_TA_H__
+#define __RANDOM_TA_H__
+
+/*
+ * This UUID is generated with uuidgen
+ * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html
+ */
+#define TA_RANDOM_UUID \
+ { 0xb6c53aba, 0x9669, 0x4668, \
+ { 0xa7, 0xf2, 0x20, 0x56, 0x29, 0xd0, 0x0f, 0x86} }
+
+/* The function ID implemented in this TA */
+#define TA_RANDOM_CMD_GENERATE 0
+
+#endif /* __RANDOM_TA_H__ */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/random_example_ta.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/random_example_ta.c
new file mode 100644
index 0000000..ef4696a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/random_example_ta.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include <random_ta.h>
+
+TEE_Result TA_CreateEntryPoint(void)
+{
+ return TEE_SUCCESS;
+}
+
+void TA_DestroyEntryPoint(void)
+{
+}
+
+TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types,
+ TEE_Param __maybe_unused params[4],
+ void __maybe_unused **sess_ctx)
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ (void)¶ms;
+ (void)&sess_ctx;
+
+ return TEE_SUCCESS;
+}
+
+void TA_CloseSessionEntryPoint(void __maybe_unused *sess_ctx)
+{
+ (void)&sess_ctx;
+}
+
+static TEE_Result random_number_generate(uint32_t param_types,
+ TEE_Param params[4])
+{
+ uint32_t exp_param_types =
+ TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ DMSG("has been called");
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ IMSG("Generating random data over %u bytes.", params[0].memref.size);
+ /*
+ * The TEE_GenerateRandom function is a part of TEE Internal Core API,
+ * which generates random data
+ *
+ * Parameters:
+ * @ randomBuffer : Reference to generated random data
+ * @ randomBufferLen : Byte length of requested random data
+ */
+ TEE_GenerateRandom(params[0].memref.buffer, params[0].memref.size);
+
+ return TEE_SUCCESS;
+}
+
+TEE_Result TA_InvokeCommandEntryPoint(void __maybe_unused *sess_ctx,
+ uint32_t cmd_id,
+ uint32_t param_types, TEE_Param params[4])
+{
+ (void)&sess_ctx;
+
+ switch (cmd_id) {
+ case TA_RANDOM_CMD_GENERATE:
+ return random_number_generate(param_types, params);
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/sub.mk
new file mode 100644
index 0000000..5561015
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/sub.mk
@@ -0,0 +1,5 @@
+global-incdirs-y += include
+srcs-y += random_example_ta.c
+
+# To remove a certain compiler flag, add a line like this
+#cflags-template_ta.c-y += -Wno-strict-prototypes
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/user_ta_header_defines.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/user_ta_header_defines.h
new file mode 100644
index 0000000..37dacc1
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/random/ta/user_ta_header_defines.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The name of this file must not be modified
+ */
+
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+ /* To get the TA_RANDOM_EXAMPLE_UUID define */
+#include <random_ta.h>
+
+#define TA_UUID TA_RANDOM_UUID
+
+/*
+ * TA properties: multi-instance TA, no specific attribute
+ * TA_FLAG_EXEC_DDR is meaningless but mandated.
+ */
+#define TA_FLAGS TA_FLAG_EXEC_DDR
+
+/* Provisioned stack size */
+#define TA_STACK_SIZE (2 * 1024)
+
+/* Provisioned heap size for TEE_Malloc() and friends */
+#define TA_DATA_SIZE (32 * 1024)
+
+/* Extra properties (give a version id and a string name) */
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
+ "Example of a TA that returns the output from TEE_GenerateRandom" }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } }
+
+#endif /* USER_TA_HEADER_DEFINES_H */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/Android.mk
new file mode 100644
index 0000000..6c1c8e7
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/Android.mk
@@ -0,0 +1,39 @@
+ifeq ($(OPTEE_TEE_SUPPORT),true)
+###################### optee-hello-world ######################
+LOCAL_PATH := $(call my-dir)
+
+OPTEE_CLIENT_EXPORT = $(LOCAL_PATH)/../../optee_client/out/export
+
+## include variants like TA_DEV_KIT_DIR
+## and OPTEE_BIN
+INCLUDE_FOR_BUILD_TA := false
+include $(BUILD_OPTEE_MK)
+INCLUDE_FOR_BUILD_TA :=
+
+# TA_DEV_KIT_DIR must be set to non-empty value to
+# avoid the Android build scripts complaining about
+# includes pointing outside the Android source tree.
+# This var is expected to be set when OPTEE OS built.
+# We set the default value to an invalid path.
+TA_DEV_KIT_DIR ?= ../invalid_include_path
+$(warning TA_DEV_KIT_DIR:$(TA_DEV_KIT_DIR))
+-include $(TA_DEV_KIT_DIR)/host_include/conf.mk
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -DANDROID_BUILD
+LOCAL_CFLAGS += -Wall
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_SRC_FILES += host/main.c
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include \
+ $(OPTEE_CLIENT_EXPORT)/include \
+
+LOCAL_SHARED_LIBRARIES := libteec
+LOCAL_MODULE := optee_example_vm_map
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
+
+include $(LOCAL_PATH)/ta/Android.mk
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/CMakeLists.txt
new file mode 100644
index 0000000..a6ecb65
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/CMakeLists.txt
@@ -0,0 +1,13 @@
+project (vm_map C)
+
+set (SRC host/main.c)
+
+add_executable (${PROJECT_NAME} ${SRC})
+
+target_include_directories(${PROJECT_NAME}
+ PRIVATE ta/include
+ PRIVATE include)
+
+target_link_libraries (${PROJECT_NAME} PRIVATE teec)
+
+install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/Makefile
new file mode 100644
index 0000000..e46c1c4
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/Makefile
@@ -0,0 +1,15 @@
+export V?=0
+
+# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
+HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
+TA_CROSS_COMPILE ?= $(CROSS_COMPILE)
+
+.PHONY: all
+all:
+ $(MAKE) -C host O=$(O)/host CROSS_COMPILE="$(HOST_CROSS_COMPILE)" --no-builtin-variables
+ $(MAKE) -C ta O=$(O)/ta CROSS_COMPILE="$(TA_CROSS_COMPILE)" LDFLAGS=""
+
+.PHONY: clean
+clean:
+ $(MAKE) -C host clean
+ $(MAKE) -C ta clean
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/host/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/host/Makefile
new file mode 100644
index 0000000..a385450
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/host/Makefile
@@ -0,0 +1,35 @@
+CC ?= $(CROSS_COMPILE)gcc
+LD ?= $(CROSS_COMPILE)ld
+AR ?= $(CROSS_COMPILE)ar
+NM ?= $(CROSS_COMPILE)nm
+OBJCOPY ?= $(CROSS_COMPILE)objcopy
+OBJDUMP ?= $(CROSS_COMPILE)objdump
+READELF ?= $(CROSS_COMPILE)readelf
+
+ifneq ($O,)
+out-dir := $O
+else
+out-dir := .
+endif
+
+OBJS = main.o
+OOBJS = $(foreach obj, $(OBJS), $(out-dir)/$(obj))
+
+CFLAGS += -Wall -I../ta/include -I$(TEEC_EXPORT)/include -I./include
+#Add/link other required libraries here
+LDADD += -lteec -L$(TEEC_EXPORT)/lib $(LDFLAGS)
+
+BINARY = $(out-dir)/optee_example_vm_map
+.PHONY: all
+all: $(BINARY)
+
+$(BINARY): $(OOBJS)
+ $(CC) -o $@ $< $(LDADD)
+
+.PHONY: clean
+clean:
+ rm -f $(OOBJS) $(BINARY)
+
+$(out-dir)/%.o: %.c
+ mkdir -p $(dir $@);
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/host/main.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/host/main.c
new file mode 100644
index 0000000..529ae8d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/host/main.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+/* OP-TEE TEE client API (built by optee_client) */
+#include <tee_client_api.h>
+
+/* To the the UUID (found the the TA's h-file(s)) */
+#include <vm_map_ta.h>
+#include <stdlib.h>
+
+TEEC_Result call_ta(uint32_t cmd, uint64_t *inout1, uint64_t *intout2, uint32_t attr)
+{
+ TEEC_Result res;
+ TEEC_Context ctx;
+ TEEC_Session sess;
+ TEEC_Operation op;
+ TEEC_UUID uuid = TA_VM_MAP_UUID;
+ uint32_t err_origin;
+
+ /* Initialize a context connecting us to the TEE */
+ res = TEEC_InitializeContext(NULL, &ctx);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
+
+ /*
+ * Open a session to the "hello world" TA, the TA will print "hello
+ * world!" in the log when the session is created.
+ */
+ res = TEEC_OpenSession(&ctx, &sess, &uuid,
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
+ if (res != TEEC_SUCCESS)
+ errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
+ res, err_origin);
+
+ /*
+ * Execute a function in the TA by invoking it, in this case
+ * we're incrementing a number.
+ *
+ * The value of command ID part and how the parameters are
+ * interpreted is part of the interface provided by the TA.
+ */
+
+ /* Clear the TEEC_Operation struct */
+ memset(&op, 0, sizeof(op));
+
+ /*
+ * Prepare the argument. Pass a value in the first parameter,
+ * the remaining three parameters are unused.
+ */
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_VALUE_INOUT,
+ TEEC_VALUE_INPUT, TEEC_VALUE_INPUT);
+ op.params[0].value.a = *inout1;
+ op.params[1].value.a = *intout2;
+ op.params[2].value.a = attr;
+ op.params[3].value.a = *inout1>>32;
+
+ printf("TEEC_InvokeCommand cmd:%x, inout1:%x, inout2:%x\n", cmd, op.params[0].value.a,op.params[1].value.a);
+ res = TEEC_InvokeCommand(&sess, cmd, &op,
+ &err_origin);
+ printf("TEEC_InvokeCommand res:%x, inout1:%x, inout2:%x\n", res, op.params[0].value.a,op.params[1].value.a);
+
+ TEEC_CloseSession(&sess);
+
+ TEEC_FinalizeContext(&ctx);
+
+ return res;
+}
+
+#define CHECK_RESULT(res, exp, info) \
+ do { \
+ if (res!=exp){ \
+ fprintf(stderr, "[%s:%d]Error: %s expect 0x%x bug got 0x%x.\n", __FUNCTION__, __LINE__, info, exp, res); \
+ }else{ \
+ printf("Success: %s\n", info); \
+ } \
+ }while(0)
+
+int test_all_default(){
+ TEEC_Result res = TEEC_SUCCESS;
+ uint64_t inout1 = 0x47000000;
+ uint64_t inout2 = 0x10000;
+ uint32_t attr = 1;
+ res = call_ta(TA_VM_MAP_CMD_MPU_PROTECT, &inout1, &inout2, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "EMI MPU protect");
+ inout1 = 0x47000000;
+ inout2 = 0x1000000;
+ attr = 0;
+ res = call_ta(TA_VM_MAP_CMD_MEM_MAP_RANDOM, &inout1, &inout2, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "EMI memory map/umap");
+ inout1 = 0x47000000;
+ inout2 = 0x1000000;
+ res = call_ta(TA_VM_MAP_CMD_MEM_MAP_TWICE, &inout1, &inout2, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "EMI memory map twice");
+ inout1 = 0x47000000;
+ inout2 = 0x1000000;
+ res = call_ta(TA_VM_MAP_CMD_MEM_MAP_TWO_REGION, &inout1, &inout2, attr);
+ CHECK_RESULT(res, TEEC_ERROR_BAD_PARAMETERS, "EMI memory map two region");
+ inout1 = 0x47000000;
+ inout2 = 0x10000;
+ res = call_ta(TA_VM_MAP_CMD_MPU_UNPROTECT, &inout1, &inout2, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "EMI MPU unprotect");
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ uint32_t err_origin;
+ uint64_t start_addr=0;
+ size_t len=0;
+ uint32_t attr=0;
+ TEEC_Result res = TEEC_SUCCESS;
+ printf("argc %d \n", argc);
+ for (i=0; i<argc; i++){
+ printf("%d is %s\n", i, argv[i]);
+ }
+ if (argc == 3){
+ start_addr = strtoull(argv[2], NULL, 0);
+ printf("Input start_addr:0x%llx\n", start_addr);
+ if (0==memcmp(argv[1],"unprotect",strlen("unprotect"))){
+ res = call_ta(TA_VM_MAP_CMD_MPU_UNPROTECT, &start_addr, &len, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "EMI MPU unprotect");
+ }
+ if (0==memcmp(argv[1],"unmap",strlen("unmap"))){
+ res = call_ta(TA_VM_MAP_CMD_MEM_UNMAP, &start_addr, &len, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "EMI memory map unmap");
+ }
+ }else if (argc == 5){
+ start_addr = strtoull(argv[2], NULL, 0);
+ len = strtoul(argv[3], NULL, 0);
+ attr = strtoul(argv[4], NULL, 0);
+ printf("Input start_addr:0x%llx\n", start_addr);
+ printf("Input start_addr:0x%llx len:0x%llx, attr:0x%x\n", start_addr, len, attr);
+ if (0==memcmp(argv[1],"protect",strlen("protect"))){
+ res = call_ta(TA_VM_MAP_CMD_MPU_PROTECT, &start_addr, &len, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "EMI MPU protect");
+ }
+ if (0==memcmp(argv[1],"map",strlen("map"))){
+ res = call_ta(TA_VM_MAP_CMD_MEM_MAP, &start_addr, &len, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "");
+ }
+ if (0==memcmp(argv[1],"simple",strlen("simple"))){
+ res = call_ta(TA_VM_MAP_CMD_MEM_MAP_SIMPLE, &start_addr, &len, attr);
+ CHECK_RESULT(res, TEEC_SUCCESS, "");
+ }
+ }else{
+ test_all_default();
+ }
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/Android.mk
new file mode 100644
index 0000000..7828169
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/Android.mk
@@ -0,0 +1,5 @@
+LOCAL_PATH := $(call my-dir)
+
+local_module := 86c1e3c4-c271-d3b4-22fe-ab50ee17c8a3.ta
+$(warning local_module:$(local_module))
+include $(BUILD_OPTEE_MK)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/Makefile
new file mode 100644
index 0000000..db0e3d2
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/Makefile
@@ -0,0 +1,13 @@
+CFG_TEE_TA_LOG_LEVEL ?= 4
+CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
+
+# The UUID for the Trusted Application
+BINARY=86c1e3c4-c271-d3b4-22fe-ab50ee17c8a3
+
+-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
+clean:
+ @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
+ @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
+endif
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/include/vm_map_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/include/vm_map_ta.h
new file mode 100644
index 0000000..2aac99f
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/include/vm_map_ta.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TA_VM_MAP_H
+#define TA_VM_MAP_H
+
+
+/*
+ * This UUID is generated with uuidgen
+ * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html
+ */
+#define TA_VM_MAP_UUID \
+ {0x86c1e3c4, 0xc271, 0xd3b4, \
+ { 0x22,0xfe,0xab, 0x50, 0xee, 0x17, 0xc8, 0xa3 } }
+
+/* The function IDs implemented in this TA */
+#define TA_VM_MAP_CMD_MPU 0
+#define TA_VM_MAP_CMD_MPU_PROTECT 1
+#define TA_VM_MAP_CMD_MPU_UNPROTECT 2
+#define TA_VM_MAP_CMD_MAP_MEM 5
+#define TA_VM_MAP_CMD_MEM_MAP_RANDOM 6
+#define TA_VM_MAP_CMD_MEM_MAP_TWICE 7
+#define TA_VM_MAP_CMD_MEM_MAP_TWO_REGION 8
+#define TA_VM_MAP_CMD_MEM_MAP 9
+#define TA_VM_MAP_CMD_MEM_UNMAP 10
+#define TA_VM_MAP_CMD_MEM_MAP_SIMPLE 11
+#endif /*TA_VM_MAP_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/sub.mk
new file mode 100644
index 0000000..11b346f
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/sub.mk
@@ -0,0 +1,5 @@
+global-incdirs-y += include
+srcs-y += vm_map_ta.c
+
+# To remove a certain compiler flag, add a line like this
+#cflags-template_ta.c-y += -Wno-strict-prototypes
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/user_ta_header_defines.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/user_ta_header_defines.h
new file mode 100644
index 0000000..9cb062b
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/user_ta_header_defines.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016-2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The name of this file must not be modified
+ */
+
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+/* To get the TA UUID definition */
+#include <vm_map_ta.h>
+
+#define TA_UUID TA_VM_MAP_UUID
+
+/*
+ * TA properties: multi-instance TA, no specific attribute
+ * TA_FLAG_EXEC_DDR is meaningless but mandated.
+ */
+#define TA_FLAGS TA_FLAG_EXEC_DDR
+
+/* Provisioned stack size */
+#define TA_STACK_SIZE (2 * 1024)
+
+/* Provisioned heap size for TEE_Malloc() and friends */
+#define TA_DATA_SIZE (32 * 1024)
+
+/* Extra properties (give a version id and a string name) */
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
+ "Example of OP-TEE Hello World Trusted Application" }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } }
+
+#endif /* USER_TA_HEADER_DEFINES_H */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/vm_map_ta.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/vm_map_ta.c
new file mode 100644
index 0000000..0ee060e
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_examples/vm_map/ta/vm_map_ta.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <assert.h>
+#include <vm_map_ta.h>
+#include "string.h"
+/*
+ * Called when the instance of the TA is created. This is the first call in
+ * the TA.
+ */
+TEE_Result TA_CreateEntryPoint(void)
+{
+ DMSG("has been called");
+
+ return TEE_SUCCESS;
+}
+
+/*
+ * Called when the instance of the TA is destroyed if the TA has not
+ * crashed or panicked. This is the last call in the TA.
+ */
+void TA_DestroyEntryPoint(void)
+{
+ DMSG("has been called");
+}
+
+/*
+ * Called when a new session is opened to the TA. *sess_ctx can be updated
+ * with a value to be able to identify this session in subsequent calls to the
+ * TA. In this function you will normally do the global initialization for the
+ * TA.
+ */
+TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types,
+ TEE_Param __maybe_unused params[4],
+ void __maybe_unused **sess_ctx)
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ DMSG("has been called");
+
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ /* Unused parameters */
+ (void)¶ms;
+ (void)&sess_ctx;
+
+ /*
+ * The DMSG() macro is non-standard, TEE Internal API doesn't
+ * specify any means to logging from a TA.
+ */
+ IMSG("Hello World!\n");
+
+ /* If return value != TEE_SUCCESS the session will not be created. */
+ return TEE_SUCCESS;
+}
+
+/*
+ * Called when a session is closed, sess_ctx hold the value that was
+ * assigned by TA_OpenSessionEntryPoint().
+ */
+void TA_CloseSessionEntryPoint(void __maybe_unused *sess_ctx)
+{
+ (void)&sess_ctx; /* Unused parameter */
+ IMSG("Goodbye!\n");
+}
+
+void dbg_dump(uint8_t *buf, size_t buf_len)
+{
+ int i=0;
+ DMSG("size:%zd", buf_len);
+ for(i=0; i<buf_len/8; i++){
+ DMSG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", buf[i*8], buf[i*8+1], buf[i*8+2], buf[i*8+3], buf[i*8+4], buf[i*8+5], buf[i*8+6], buf[i*8+7]);
+ }
+ for(i*=8; i<buf_len; i++){
+ DMSG("0x%02x", buf[i]);
+ }
+}
+
+#define RANDOM_BUF_LEN 128
+#define MAX_RW_LEN 0x200000
+TEE_Result mem_rw_test(uint8_t* start, size_t len)
+{
+ len = len>MAX_RW_LEN ? MAX_RW_LEN : len;
+ IMSG("test range:%p, len:%d", start, len);
+ uint8_t randomBuffer[RANDOM_BUF_LEN];
+ TEE_GenerateRandom(randomBuffer, RANDOM_BUF_LEN);
+ // dbg_dump(randomBuffer, RANDOM_BUF_LEN);
+ int i = 0;
+ size_t i_len = len;
+ i_len = (len/RANDOM_BUF_LEN)*RANDOM_BUF_LEN;
+ for(i=0; i<i_len; i+=RANDOM_BUF_LEN){
+ memcpy(start+i, randomBuffer, RANDOM_BUF_LEN);
+ if (memcmp(start+i, randomBuffer, RANDOM_BUF_LEN)){
+ EMSG("memory rw test fail at 0x%x.", start+i);
+ EMSG("Read:");
+ dbg_dump(start+i, RANDOM_BUF_LEN);
+ EMSG("Expect:");
+ dbg_dump(randomBuffer, RANDOM_BUF_LEN);
+ return -1;
+ }
+ }
+ return TEE_SUCCESS;
+}
+
+TEE_Result mem_rw_rand_pos_test(uint8_t* start, size_t len)
+{
+ DMSG("test range:%p, len:%d", start, len);
+ if (len<0x100000){
+ return mem_rw_test(start, len);
+ }
+ int i = 0;
+ size_t rand_pos;
+ uint8_t* new_start=start;
+ size_t new_len;
+ size_t rest_len;
+ TEE_Result res=TEE_SUCCESS;
+ for(i=0; i<10; i++){
+ TEE_GenerateRandom(&rand_pos, sizeof(rand_pos));
+ rand_pos = rand_pos%len;
+ DMSG("Generated rand position:%x", rand_pos);
+ new_start = start+rand_pos;
+ rest_len = (start+len)-new_start;
+ new_len = rand_pos & (MAX_RW_LEN-1);
+ new_len = new_len > len ? new_len%len : new_len;
+ new_len = new_len > rest_len ? rest_len : new_len;
+ res = mem_rw_test(new_start, new_len);
+ if (res!=TEE_SUCCESS){
+ break;
+ }
+ }
+ return res;
+}
+
+static TEE_Result map_mem(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc;
+ uint64_t va;
+ rc = TEE_MapPhysicalMemory(0x47000000, 0x1000000, 0, &va);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va);
+ DMSG("Read back va address value:%x", *(uint64_t*)va);
+ mem_rw_test((uint8_t*)va, 0x1000000);
+ rc = TEE_UnmapPhysicalMemory(va);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va);
+ // This should abort.
+ // DMSG("Read back va address value:%x", *(uint64_t*)va);
+ return rc;
+}
+
+void get_mem_para(uint32_t param_types, TEE_Param params[4], uint64_t* start, size_t* len, uint32_t* attr)
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT,
+ TEE_PARAM_TYPE_VALUE_INOUT,
+ TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_VALUE_INPUT);
+
+ DMSG("has been called");
+
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+ DMSG("0: 0x%x 1:0x%x 2:0x%x, 3:0x%x", params[0].value.a, params[1].value.a, params[2].value.a, params[3].value.a);
+ uint64_t tmp = (uint64_t)(params[3].value.a)<<32;
+ *start = tmp | params[0].value.a;
+ *len = params[1].value.a;
+ *attr = params[2].value.a;
+ DMSG("start addr: 0x%llx, len:%d, attr:%x", *start, *len, *attr);
+}
+
+static TEE_Result mpu_test(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc;
+ uint64_t va;
+ rc = TEE_EMIMPUProtect(0x47000000, 0x10000, 1);
+ DMSG("TEE_EMIMPUProtect res: %x", rc);
+
+ rc = TEE_EMIMPUUnprotect(0x47000000);
+ DMSG("TEE_EMIMPUUnprotect res: %x", rc);
+ return rc;
+}
+
+static TEE_Result mpu_protect_test(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc;
+ uint64_t pa;
+ size_t len;
+ uint32_t attr;
+ get_mem_para(param_types, params, &pa, &len, &attr);
+ rc = TEE_EMIMPUProtect(pa, len, attr);
+ DMSG("TEE_EMIMPUProtect res: %x", rc);
+ return rc;
+}
+
+
+static TEE_Result mpu_unprotect_test(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc;
+ uint64_t pa;
+ size_t len;
+ uint32_t attr;
+ get_mem_para(param_types, params, &pa, &len, &attr);
+ rc = TEE_EMIMPUUnprotect(pa);
+ DMSG("TEE_EMIMPUUnprotect res: %x", rc);
+ return rc;
+}
+
+static TEE_Result mem_map_random_test(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc;
+ uint64_t pa;
+ size_t len;
+ uint32_t attr;
+ get_mem_para(param_types, params, &pa, &len, &attr);
+ uint64_t va;
+ rc = TEE_MapPhysicalMemory(pa, len, attr, &va);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va);
+ rc = mem_rw_rand_pos_test(va, len);
+ DMSG("mem_rw_rand_pos_test res: %x", rc);
+ if (rc){
+ return rc;
+ }
+ rc = TEE_UnmapPhysicalMemory(va);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va);
+ return rc;
+}
+
+static TEE_Result mem_map_simple_test(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc;
+ uint64_t pa;
+ size_t len;
+ uint32_t attr;
+ int i =0;
+ get_mem_para(param_types, params, &pa, &len, &attr);
+ uint64_t va;
+ uint32_t* va_off;
+ uint32_t* va_a;
+ rc = TEE_MapPhysicalMemory(pa, len, attr, &va);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va);
+ va_a = (uint32_t*)va;
+ for (i=0; i<64; i++){
+ va_a[i] = i;
+ }
+ for (i=0; i<64; i++){
+ DMSG("addr: %p, val:%d", (&va_a[i]), va_a[i]);
+ }
+ va_off = va_a+64;
+ for (i=0; i<64; i++){
+ DMSG("addr: %p, val:%d", (&va_off[i]), va_off[i]);
+ }
+ return rc;
+}
+
+static TEE_Result mem_map_test(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc;
+ uint64_t pa;
+ size_t len;
+ uint32_t attr;
+ get_mem_para(param_types, params, &pa, &len, &attr);
+ uint64_t va;
+ DMSG("TEE_MapPhysicalMemory pa: %llx", pa);
+ rc = TEE_MapPhysicalMemory(pa, len, attr, &va);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va);
+ rc = mem_rw_rand_pos_test(va, len);
+ DMSG("mem_rw_rand_pos_test res: %x", rc);
+ return rc;
+}
+
+static TEE_Result mem_unmap_test(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc;
+ uint64_t va;
+ size_t len;
+ uint32_t attr;
+ get_mem_para(param_types, params, &va, &len, &attr);
+ rc = TEE_UnmapPhysicalMemory(va);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va);
+ return rc;
+}
+
+static TEE_Result mem_map_twice_test(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc, rc0;
+ uint64_t pa;
+ size_t len;
+ uint32_t attr;
+ get_mem_para(param_types, params, &pa, &len, &attr);
+ uint64_t va1;
+ uint64_t va2;
+ size_t len1 = len/2;
+
+ rc = TEE_MapPhysicalMemory(pa, len1, attr, &va1);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va1);
+ rc = mem_rw_rand_pos_test(va1, len1);
+ DMSG("mem_rw_rand_pos_test res: %x", rc);
+ if (rc){
+ return rc;
+ }
+ rc = TEE_UnmapPhysicalMemory(va1);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va1);
+ //
+ rc = TEE_MapPhysicalMemory(pa+len1, len1, attr, &va2);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va2);
+ rc = mem_rw_rand_pos_test(va2, len1);
+ DMSG("mem_rw_rand_pos_test res: %x", rc);
+ if (rc){
+ return rc;
+ }
+ rc = TEE_UnmapPhysicalMemory(va2);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va2);
+ return rc;
+}
+static TEE_Result mem_map_two_region(uint32_t param_types,
+ TEE_Param params[4])
+{
+ DMSG("has been called");
+ TEE_Result rc, rc0;
+ uint64_t pa;
+ size_t len;
+ uint32_t attr;
+ get_mem_para(param_types, params, &pa, &len, &attr);
+ uint64_t va1;
+ uint64_t va2;
+ size_t len1 = len/2;
+
+ rc = TEE_MapPhysicalMemory(pa, len1, attr, &va1);
+ DMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc, va1);
+ rc0 = TEE_MapPhysicalMemory(pa+len1, len1, attr, &va2);
+ //The seconde map should be fail.
+ EMSG("TEE_MapPhysicalMemory res: %x, va: %p", rc0, va2);
+
+ rc = TEE_UnmapPhysicalMemory(va1);
+ DMSG("TEE_UnmapPhysicalMemory res: %x, va: %p", rc, va1);
+ return rc0;
+}
+
+/*
+ * Called when a TA is invoked. sess_ctx hold that value that was
+ * assigned by TA_OpenSessionEntryPoint(). The rest of the paramters
+ * comes from normal world.
+ */
+TEE_Result TA_InvokeCommandEntryPoint(void __maybe_unused *sess_ctx,
+ uint32_t cmd_id,
+ uint32_t param_types, TEE_Param params[4])
+{
+ (void)&sess_ctx; /* Unused parameter */
+
+ switch (cmd_id) {
+ case TA_VM_MAP_CMD_MPU:
+ return mpu_test(param_types, params);
+ case TA_VM_MAP_CMD_MPU_PROTECT:
+ return mpu_protect_test(param_types, params);
+ case TA_VM_MAP_CMD_MPU_UNPROTECT:
+ return mpu_unprotect_test(param_types, params);
+ case TA_VM_MAP_CMD_MAP_MEM:
+ return map_mem(param_types, params);
+ case TA_VM_MAP_CMD_MEM_MAP_RANDOM:
+ return mem_map_random_test(param_types, params);
+ case TA_VM_MAP_CMD_MEM_MAP_TWICE:
+ return mem_map_twice_test(param_types, params);
+ case TA_VM_MAP_CMD_MEM_MAP_TWO_REGION:
+ return mem_map_two_region(param_types, params);
+ case TA_VM_MAP_CMD_MEM_MAP:
+ return mem_map_test(param_types, params);
+ case TA_VM_MAP_CMD_MEM_UNMAP:
+ return mem_unmap_test(param_types, params);
+ case TA_VM_MAP_CMD_MEM_MAP_SIMPLE:
+ return mem_map_simple_test(param_types, params);
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/Android.mk
new file mode 100644
index 0000000..6361f9b
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/Android.mk
@@ -0,0 +1,2 @@
+LOCAL_PATH := $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/LICENSE b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/LICENSE
new file mode 100644
index 0000000..8e33c9f
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/LICENSE
@@ -0,0 +1,2 @@
+Different modules may have different LICENSE.
+Please reference LICENSE file for each module under current folder
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/Makefile
new file mode 100644
index 0000000..a91119d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/Makefile
@@ -0,0 +1,36 @@
+export V ?= 0
+
+LIBDIR := $(LIBDIR)
+BINDIR := $(BINDIR)
+INCDIR := $(INCDIR)
+TADIR := $(TADIR)
+
+SERVICE_LIST := $(subst /,,$(dir $(wildcard */Makefile)))
+
+.PHONY: all
+all: services prepare-for-rootfs
+
+.PHONY: clean
+clean: services-clean prepare-for-rootfs-clean
+
+services:
+ @for service in $(SERVICE_LIST); do \
+ $(MAKE) -C $$service CROSS_COMPILE="$(HOST_CROSS_COMPILE)" || exit -1; \
+ done
+
+services-clean:
+ @for service in $(SERVICE_LIST); do \
+ $(MAKE) -C $$service clean || exit -1; \
+ done
+
+prepare-for-rootfs: services
+ @echo "Nothing to do"
+
+prepare-for-rootfs-clean:
+ @rm -rf $(TA_OUTPUT_DIR)
+
+.PHONY: install
+install:
+ @for service in $(SERVICE_LIST); do \
+ $(MAKE) -C $$service install LIBDIR="${LIBDIR}" BINDIR="${BINDIR}" INCDIR="${INCDIR}" TADIR="$(TADIR)" || exit -1; \
+ done
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/Android.mk
new file mode 100644
index 0000000..92c855d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH := $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/LICENSE b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/LICENSE
new file mode 100644
index 0000000..12e3c07
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/LICENSE
@@ -0,0 +1,27 @@
+Unless it has its own copyright/license embedded in its body, each source file
+is subject to the following license terms:
+
+Copyright (c) 2018, Linaro Limited
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/Makefile
new file mode 100644
index 0000000..cd771ad
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/Makefile
@@ -0,0 +1,24 @@
+export V ?= 0
+
+# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE
+HOST_CROSS_COMPILE ?= $(CROSS_COMPILE)
+TA_CROSS_COMPILE ?= $(CROSS_COMPILE)
+LIBDIR ?= $(LIBDIR)
+BINDIR ?= $(BINDIR)
+BINDIR ?= $(INCDIR)
+TADIR ?= $(TADIR)
+
+.PHONY: all
+all:
+ $(MAKE) -C host CROSS_COMPILE="$(HOST_CROSS_COMPILE)" --no-builtin-variables
+ $(MAKE) -C ta CROSS_COMPILE="$(TA_CROSS_COMPILE)" LDFLAGS=""
+
+.PHONY: clean
+clean:
+ $(MAKE) -C host clean
+ $(MAKE) -C ta clean
+
+.PHONY: install
+install:
+ $(MAKE) -C host install LIBDIR="$(LIBDIR)" BINDIR="$(BINDIR)" INCDIR="$(INCDIR)"
+ $(MAKE) -C ta install TADIR="$(TADIR)"
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/README.md b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/README.md
new file mode 100644
index 0000000..ff04284
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/README.md
@@ -0,0 +1,8 @@
+# OP-TEE TA/Library for Secure Key Services (PKCS#11)
+
+This git repository contains both the Trusted Application and the client
+for the OP-TEE Secure Key Services (PKCS#11).
+
+Code is based on the current work-in-progress implementation started by
+Etienne Carriere <etienne.carriere@linaro.org>, which can be found at
+https://github.com/OP-TEE/optee_os/pull/2342.
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/config.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/config.mk
new file mode 100644
index 0000000..1280f8e
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/config.mk
@@ -0,0 +1,6 @@
+# Default output directory.
+# May be absolute, or relative to the optee_client source directory.
+O ?= out
+
+# To be used instead of $(O) in sub-directories
+OO := $(if $(filter /%,$(O)),$(O),$(CURDIR)/../$(O))
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/flags.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/flags.mk
new file mode 100644
index 0000000..c2f0e1c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/flags.mk
@@ -0,0 +1,32 @@
+#########################################################################
+# COMMON COMPILATION FLAGS #
+#########################################################################
+
+CROSS_COMPILE ?= arm-linux-gnueabihf-
+CC ?= $(CROSS_COMPILE)gcc
+AR ?= $(CROSS_COMPILE)ar
+
+CFLAGS := -Wall -Wbad-function-cast -Wcast-align \
+ -Werror-implicit-function-declaration -Wextra \
+ -Wfloat-equal -Wformat-nonliteral -Wformat-security \
+ -Wformat=2 -Winit-self -Wmissing-declarations \
+ -Wmissing-format-attribute -Wmissing-include-dirs \
+ -Wmissing-noreturn -Wmissing-prototypes -Wnested-externs \
+ -Wpointer-arith -Wshadow -Wstrict-prototypes \
+ -Wswitch-default -Wunsafe-loop-optimizations \
+ -Wwrite-strings -D_FILE_OFFSET_BITS=64
+ifeq ($(CFG_WERROR),y)
+CFLAGS += -Werror
+endif
+CFLAGS += -c -fPIC
+
+DEBUG ?= 0
+ifeq ($(DEBUG), 1)
+CFLAGS += -DDEBUG -O0 -g
+endif
+
+RM := rm -f
+
+define rmdir
+if [ -d "$(1)" ] ; then rmdir --ignore-fail-on-non-empty $(1) ; fi
+endef
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/Android.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/Android.mk
new file mode 100644
index 0000000..bfee020
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/Android.mk
@@ -0,0 +1,52 @@
+# Copyright 2006 The Android Open Source Project
+###############################################################################
+LOCAL_PATH:= $(call my-dir)
+###############################################################################
+
+## include variants like TA_DEV_KIT_DIR
+## and OPTEE_BIN
+INCLUDE_FOR_BUILD_TA := false
+include $(BUILD_OPTEE_MK)
+INCLUDE_FOR_BUILD_TA :=
+
+VERSION = $(shell git describe --always --dirty=-dev 2>/dev/null || echo Unknown)
+
+# TA_DEV_KIT_DIR must be set to non-empty value to
+# avoid the Android build scripts complaining about
+# includes pointing outside the Android source tree.
+# This var is expected to be set when OPTEE OS built.
+# We set the default value to an invalid path.
+TA_DEV_KIT_DIR ?= ../invalid_include_path
+
+-include $(TA_DEV_KIT_DIR)/host_include/conf.mk
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := src/pkcs11_api.c \
+ src/ck_debug.c \
+ src/ck_helpers.c \
+ src/invoke_ta.c \
+ src/pkcs11_token.c \
+ src/serializer.c \
+ src/serialize_ck.c \
+ src/pkcs11_processing.c
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
+
+LOCAL_CFLAGS += -D_GNU_SOURCE -fPIC
+
+LOCAL_SHARED_LIBRARIES := libteec
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(OPTEE_BIN)
+LOCAL_ADDITIONAL_DEPENDENCIES += fd02c9da-306c-48c7-a49c-bbd827ae86ee.ta
+
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
+
+LOCAL_MODULE := libsks
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(LOCAL_PATH)/../ta/ta.mk
+
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/CMakeLists.txt
new file mode 100644
index 0000000..40ce003
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/CMakeLists.txt
@@ -0,0 +1,76 @@
+project(sks C)
+
+set(PROJECT_VERSION "1.0.0")
+
+################################################################################
+# Packages
+################################################################################
+find_package(Threads REQUIRED)
+if(NOT THREADS_FOUND)
+ message(FATAL_ERROR "Threads not found")
+endif()
+
+include(GNUInstallDirs)
+
+################################################################################
+# Source files
+################################################################################
+set (SRC
+ src/pkcs11_api.c
+ src/ck_debug.c
+ src/ck_helpers.c
+ src/invoke_ta.c
+ src/pkcs11_token.c
+ src/serializer.c
+ src/serialize_ck.c
+ src/pkcs11_processing.c
+)
+
+################################################################################
+# Built library
+################################################################################
+add_library (sks SHARED ${SRC})
+
+set_target_properties (sks PROPERTIES
+ VERSION ${PROJECT_VERSION}
+ SOVERSION ${PROJECT_NAME}
+)
+
+################################################################################
+# Flags always set
+################################################################################
+target_compile_definitions (sks
+ PRIVATE -D_GNU_SOURCE
+ PRIVATE -DBINARY_PREFIX="LT"
+)
+
+################################################################################
+# Optional flags
+################################################################################
+
+################################################################################
+# Public and private header and library dependencies
+################################################################################
+target_include_directories(sks
+ PUBLIC include
+ PRIVATE src
+)
+
+target_include_directories(teec
+ PUBLIC include
+)
+
+target_link_libraries (sks
+ PRIVATE pthread
+ PRIVATE teec
+ PRIVATE m
+)
+
+################################################################################
+# Install targets
+################################################################################
+install (TARGETS sks
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}
+)
+
+add_subdirectory(include)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/Makefile
new file mode 100644
index 0000000..a46e445
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/Makefile
@@ -0,0 +1,76 @@
+include ../flags.mk
+include ../config.mk
+
+OUT_DIR := $(OO)/libsks
+
+.PHONY: all libsks clean install
+
+all: libsks
+
+LIB_NAME := libsks
+MAJOR_VERSION := 0
+MINOR_VERSION := 0
+
+LIB_MAJOR := $(LIB_NAME).so.$(MAJOR_VERSION)
+LIB_MAJ_MIN := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION)
+LIBSKS_SO_LIBRARY := $(LIB_MAJ_MIN)
+LIBSKS_AR_LIBRARY := $(LIB_NAME).a
+
+LIBSKS_SRC_DIR := src
+
+LIBSKS_SRCS = pkcs11_api.c
+LIBSKS_SRCS += ck_debug.c
+LIBSKS_SRCS += ck_helpers.c
+LIBSKS_SRCS += invoke_ta.c
+LIBSKS_SRCS += pkcs11_token.c
+LIBSKS_SRCS += serializer.c
+LIBSKS_SRCS += serialize_ck.c
+LIBSKS_SRCS += pkcs11_processing.c
+
+LIBSKS_INCLUDES = ${CURDIR}/include
+
+LIBSKS_CFLAGS := $(addprefix -I, $(LIBSKS_INCLUDES)) \
+ $(CFLAGS) -D_GNU_SOURCE -fPIC
+
+LIBSKS_LFLAGS := $(LDFLAGS) -L$(OUT_DIR)/../libteec -lteec
+
+LIBSKS_OBJ_DIR := $(OUT_DIR)
+LIBSKS_OBJS := $(patsubst %.c,$(LIBSKS_OBJ_DIR)/%.o, $(LIBSKS_SRCS))
+
+$(LIBSKS_OBJ_DIR)/%.o: ${LIBSKS_SRC_DIR}/%.c
+ $(VPREFIX)mkdir -p $(LIBSKS_OBJ_DIR)
+ @echo " CC $<"
+ $(VPREFIX)$(CC) $(LIBSKS_CFLAGS) -c $< -o $@
+
+libsks: $(OUT_DIR)/$(LIBSKS_SO_LIBRARY)
+
+$(OUT_DIR)/$(LIBSKS_SO_LIBRARY): $(LIBSKS_OBJS)
+ @echo " LINK $@"
+ $(VPREFIX)$(CC) -shared -o $@ $+ $(LIBSKS_LFLAGS)
+ @echo ""
+
+libsks: $(OUT_DIR)/$(LIBSKS_AR_LIBRARY)
+
+$(OUT_DIR)/$(LIBSKS_AR_LIBRARY): $(LIBSKS_OBJS)
+ @echo " AR $@"
+ $(VPREFIX)$(AR) rcs $@ $+
+
+libsks:
+ $(VPREFIX)ln -sf $(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_MAJOR)
+ $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME).so
+
+################################################################################
+# Cleaning up configuration
+################################################################################
+clean:
+ $(RM) $(LIBSKS_OBJS)
+ $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN)
+ $(RM) $(OUT_DIR)/$(LIB_MAJOR)
+ $(RM) $(OUT_DIR)/$(LIBSKS_SO_LIBRARY)
+ $(RM) $(OUT_DIR)/$(LIBSKS_AR_LIBRARY)
+ $(call rmdir,$(OUT_DIR))
+
+install: libsks
+ cp -f $(OUT_DIR)/$(LIBSKS_SO_LIBRARY) $(LIBDIR)/$(LIB_NAME).so
+ mkdir -p $(INCDIR)/libsks
+ cp -f ${CURDIR}/include/pkcs11.h $(INCDIR)/libsks/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/CMakeLists.txt b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/CMakeLists.txt
new file mode 100644
index 0000000..24344ec
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/CMakeLists.txt
@@ -0,0 +1,7 @@
+project (optee-cryptoki-headers C)
+
+FILE(GLOB INSTALL_HEADERS "*.h")
+
+add_library(${PROJECT_NAME} INTERFACE)
+
+install (FILES ${INSTALL_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/pkcs11.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/pkcs11.h
new file mode 100644
index 0000000..644d10c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/pkcs11.h
@@ -0,0 +1,1562 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
+
+#ifndef __PKCS11_H__
+#define __PKCS11_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * PKCS#11 Cryptoki API v2.40-errata01, See specification from:
+ * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/errata01/os/pkcs11-base-v2.40-errata01-os-complete.html
+ */
+
+typedef unsigned char CK_BYTE;
+typedef unsigned long int CK_ULONG;
+typedef long int CK_LONG;
+
+typedef CK_BYTE CK_CHAR;
+typedef CK_BYTE CK_UTF8CHAR;
+
+typedef CK_BYTE * CK_BYTE_PTR;
+typedef CK_ULONG * CK_ULONG_PTR;
+
+typedef CK_CHAR * CK_CHAR_PTR;
+typedef CK_UTF8CHAR * CK_UTF8CHAR_PTR;
+
+typedef void * CK_VOID_PTR;
+typedef CK_VOID_PTR * CK_VOID_PTR_PTR;
+
+typedef CK_BYTE CK_BBOOL;
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+typedef CK_ULONG CK_FLAGS;
+
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE 0
+
+typedef CK_ULONG CK_SESSION_HANDLE;
+typedef CK_SESSION_HANDLE * CK_SESSION_HANDLE_PTR;
+typedef CK_ULONG CK_OBJECT_HANDLE;
+typedef CK_OBJECT_HANDLE * CK_OBJECT_HANDLE_PTR;
+
+#define CK_INVALID_HANDLE 0
+
+typedef CK_ULONG CK_SLOT_ID;
+typedef CK_SLOT_ID * CK_SLOT_ID_PTR;
+
+typedef struct CK_VERSION CK_VERSION;
+typedef struct CK_VERSION * CK_VERSION_PTR;
+
+struct CK_VERSION {
+ CK_BYTE major;
+ CK_BYTE minor;
+};
+
+typedef struct CK_DATE CK_DATE;
+typedef struct CK_DATE * CK_DATE_PTR;
+
+struct CK_DATE {
+ CK_CHAR year[4];
+ CK_CHAR month[2];
+ CK_CHAR day[2];
+};
+
+/*
+ * PKCS#11 Objects attributes
+ */
+
+typedef CK_ULONG CK_ATTRIBUTE_TYPE;
+
+typedef struct CK_ATTRIBUTE CK_ATTRIBUTE;
+typedef struct CK_ATTRIBUTE * CK_ATTRIBUTE_PTR;
+
+struct CK_ATTRIBUTE {
+ CK_ATTRIBUTE_TYPE type;
+ CK_VOID_PTR pValue;
+ CK_ULONG ulValueLen;
+};
+
+/*
+ * Values for CK_ATTRIBUTE_TYPE
+ *
+ * This does not cover the full PKCS#11 IDs.
+ */
+#define CKF_ARRAY_ATTRIBUTE (1U << 30)
+#define CKA_VENDOR_DEFINED (1U << 31)
+#define CKA_CLASS 0x0000
+#define CKA_TOKEN 0x0001
+#define CKA_PRIVATE 0x0002
+#define CKA_LABEL 0x0003
+#define CKA_APPLICATION 0x0010
+#define CKA_VALUE 0x0011
+#define CKA_OBJECT_ID 0x0012
+#define CKA_CERTIFICATE_TYPE 0x0080
+#define CKA_ISSUER 0x0081
+#define CKA_SERIAL_NUMBER 0x0082
+#define CKA_AC_ISSUER 0x0083
+#define CKA_OWNER 0x0084
+#define CKA_ATTR_TYPES 0x0085
+#define CKA_TRUSTED 0x0086
+#define CKA_CERTIFICATE_CATEGORY 0x0087
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x0088
+#define CKA_URL 0x0089
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x008a
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x008b
+#define CKA_NAME_HASH_ALGORITHM 0x008c
+#define CKA_CHECK_VALUE 0x0090
+#define CKA_KEY_TYPE 0x0100
+#define CKA_SUBJECT 0x0101
+#define CKA_ID 0x0102
+#define CKA_SENSITIVE 0x0103
+#define CKA_ENCRYPT 0x0104
+#define CKA_DECRYPT 0x0105
+#define CKA_WRAP 0x0106
+#define CKA_UNWRAP 0x0107
+#define CKA_SIGN 0x0108
+#define CKA_SIGN_RECOVER 0x0109
+#define CKA_VERIFY 0x010a
+#define CKA_VERIFY_RECOVER 0x010b
+#define CKA_DERIVE 0x010c
+#define CKA_START_DATE 0x0110
+#define CKA_END_DATE 0x0111
+#define CKA_MODULUS 0x0120
+#define CKA_MODULUS_BITS 0x0121
+#define CKA_PUBLIC_EXPONENT 0x0122
+#define CKA_PRIVATE_EXPONENT 0x0123
+#define CKA_PRIME_1 0x0124
+#define CKA_PRIME_2 0x0125
+#define CKA_EXPONENT_1 0x0126
+#define CKA_EXPONENT_2 0x0127
+#define CKA_COEFFICIENT 0x0128
+#define CKA_PUBLIC_KEY_INFO 0x0129
+#define CKA_PRIME 0x0130
+#define CKA_SUBPRIME 0x0131
+#define CKA_BASE 0x0132
+#define CKA_PRIME_BITS 0x0133
+#define CKA_SUBPRIME_BITS 0x0134
+#define CKA_VALUE_BITS 0x0160
+#define CKA_VALUE_LEN 0x0161
+#define CKA_EXTRACTABLE 0x0162
+#define CKA_LOCAL 0x0163
+#define CKA_NEVER_EXTRACTABLE 0x0164
+#define CKA_ALWAYS_SENSITIVE 0x0165
+#define CKA_KEY_GEN_MECHANISM 0x0166
+#define CKA_MODIFIABLE 0x0170
+#define CKA_COPYABLE 0x0171
+#define CKA_DESTROYABLE 0x0172
+#define CKA_EC_PARAMS 0x0180
+#define CKA_EC_POINT 0x0181
+#define CKA_ALWAYS_AUTHENTICATE 0x0202
+#define CKA_WRAP_WITH_TRUSTED 0x0210
+#define CKA_WRAP_TEMPLATE (0x0211 | CKF_ARRAY_ATTRIBUTE)
+#define CKA_UNWRAP_TEMPLATE (0x0212 | CKF_ARRAY_ATTRIBUTE)
+#define CKA_DERIVE_TEMPLATE (0x0213 | CKF_ARRAY_ATTRIBUTE)
+#define CKA_OTP_FORMAT 0x0220
+#define CKA_OTP_LENGTH 0x0221
+#define CKA_OTP_TIME_INTERVAL 0x0222
+#define CKA_OTP_USER_FRIENDLY_MODE 0x0223
+#define CKA_OTP_CHALLENGE_REQUIREMENT 0x0224
+#define CKA_OTP_TIME_REQUIREMENT 0x0225
+#define CKA_OTP_COUNTER_REQUIREMENT 0x0226
+#define CKA_OTP_PIN_REQUIREMENT 0x0227
+#define CKA_OTP_COUNTER 0x022e
+#define CKA_OTP_TIME 0x022f
+#define CKA_OTP_USER_IDENTIFIER 0x022a
+#define CKA_OTP_SERVICE_IDENTIFIER 0x022b
+#define CKA_OTP_SERVICE_LOGO 0x022c
+#define CKA_OTP_SERVICE_LOGO_TYPE 0x022d
+#define CKA_GOSTR3410_PARAMS 0x0250
+#define CKA_GOSTR3411_PARAMS 0x0251
+#define CKA_GOST28147_PARAMS 0x0252
+#define CKA_HW_FEATURE_TYPE 0x0300
+#define CKA_RESET_ON_INIT 0x0301
+#define CKA_HAS_RESET 0x0302
+#define CKA_PIXEL_X 0x0400
+#define CKA_PIXEL_Y 0x0401
+#define CKA_RESOLUTION 0x0402
+#define CKA_CHAR_ROWS 0x0403
+#define CKA_CHAR_COLUMNS 0x0404
+#define CKA_COLOR 0x0405
+#define CKA_BITS_PER_PIXEL 0x0406
+#define CKA_CHAR_SETS 0x0480
+#define CKA_ENCODING_METHODS 0x0481
+#define CKA_MIME_TYPES 0x0482
+#define CKA_MECHANISM_TYPE 0x0500
+#define CKA_REQUIRED_CMS_ATTRIBUTES 0x0501
+#define CKA_DEFAULT_CMS_ATTRIBUTES 0x0502
+#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x0503
+#define CKA_ALLOWED_MECHANISMS (0x0600 | CKF_ARRAY_ATTRIBUTE)
+
+/* Attribute CKA_CLASS refers to a CK_OBJECT_CLASS typed value */
+typedef CK_ULONG CK_OBJECT_CLASS;
+typedef CK_OBJECT_CLASS * CK_OBJECT_CLASS_PTR;
+
+/* Values for type CK_OBJECT_CLASS */
+#define CKO_VENDOR_DEFINED (1U << 31)
+#define CKO_DATA 0x0
+#define CKO_CERTIFICATE 0x1
+#define CKO_PUBLIC_KEY 0x2
+#define CKO_PRIVATE_KEY 0x3
+#define CKO_SECRET_KEY 0x4
+#define CKO_HW_FEATURE 0x5
+#define CKO_DOMAIN_PARAMETERS 0x6
+#define CKO_MECHANISM 0x7
+#define CKO_OTP_KEY 0x8
+
+/* Attribute CKA_KEY_TYPE refers to a CK_KEY_TYPE typed value */
+typedef CK_ULONG CK_KEY_TYPE;
+typedef CK_KEY_TYPE * CK_KEY_TYPE_PTR;
+
+/*
+ * Values for type CK_KEY_TYPE
+ *
+ * This does not cover the full PKCS#11 IDs.
+ */
+#define CKK_VENDOR_DEFINED (1U << 31)
+#define CKK_RSA 0x000
+#define CKK_DSA 0x001
+#define CKK_DH 0x002
+#define CKK_ECDSA 0x003
+#define CKK_EC 0x003
+#define CKK_GENERIC_SECRET 0x010
+#define CKK_DES 0x013
+#define CKK_DES2 0x014
+#define CKK_DES3 0x015
+#define CKK_AES 0x01f
+#define CKK_HOTP 0x023
+#define CKK_MD5_HMAC 0x027
+#define CKK_SHA_1_HMAC 0x028
+#define CKK_SHA256_HMAC 0x02b
+#define CKK_SHA384_HMAC 0x02c
+#define CKK_SHA512_HMAC 0x02d
+#define CKK_SHA224_HMAC 0x02e
+
+/* Attribute CKA_CERTIFICATE_TYPE refers to a CK_CERTIFICATE_TYPE typed value */
+typedef CK_ULONG CK_CERTIFICATE_TYPE;
+typedef CK_CERTIFICATE_TYPE * CK_CERTIFICATE_TYPE_PTR;
+
+/*
+ * Values for type CK_CERTIFICATE_TYPE
+ */
+#define CKC_VENDOR_DEFINED (1U << 31)
+#define CKC_X_509 0x000
+#define CKC_X_509_ATTR_CER 0x001
+#define CKC_WTLS 0x002
+
+/*
+ * Mechanisms
+ *
+ * Note: a mechanism can be referenced as object reference in some PKCS#11 API
+ * functions. In such case, the object hold attribute CKA_MECHANISM_TYPE which
+ * refers to a CK_MECHANISM_TYPE typed value that defines the target mechanism.
+ */
+
+typedef CK_ULONG CK_MECHANISM_TYPE;
+typedef CK_MECHANISM_TYPE * CK_MECHANISM_TYPE_PTR;
+
+/*
+ * Values for type CK_MECHANISM_TYPE
+ *
+ * This does not cover the full PKCS#11 IDs.
+ */
+#define CKM_VENDOR_DEFINED (1U << 31)
+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000
+#define CKM_RSA_PKCS 0x00001
+#define CKM_RSA_9796 0x00002
+#define CKM_RSA_X_509 0x00003
+#define CKM_SHA1_RSA_PKCS 0x00006
+#define CKM_RSA_PKCS_OAEP 0x00009
+#define CKM_RSA_PKCS_PSS 0x0000d
+#define CKM_SHA1_RSA_PKCS_PSS 0x0000e
+#define CKM_SHA256_RSA_PKCS 0x00040
+#define CKM_SHA384_RSA_PKCS 0x00041
+#define CKM_SHA512_RSA_PKCS 0x00042
+#define CKM_SHA256_RSA_PKCS_PSS 0x00043
+#define CKM_SHA384_RSA_PKCS_PSS 0x00044
+#define CKM_SHA512_RSA_PKCS_PSS 0x00045
+#define CKM_SHA224_RSA_PKCS 0x00046
+#define CKM_SHA224_RSA_PKCS_PSS 0x00047
+#define CKM_SHA512_224 0x00048
+#define CKM_SHA512_224_HMAC 0x00049
+#define CKM_SHA512_224_HMAC_GENERAL 0x0004a
+#define CKM_SHA512_224_KEY_DERIVATION 0x0004b
+#define CKM_SHA512_256 0x0004c
+#define CKM_SHA512_256_HMAC 0x0004d
+#define CKM_SHA512_256_HMAC_GENERAL 0x0004e
+#define CKM_SHA512_256_KEY_DERIVATION 0x0004f
+#define CKM_DES_KEY_GEN 0x00120
+#define CKM_DES_ECB 0x00121
+#define CKM_DES_CBC 0x00122
+#define CKM_DES_MAC 0x00123
+#define CKM_DES_MAC_GENERAL 0x00124
+#define CKM_DES_CBC_PAD 0x00125
+#define CKM_DES3_ECB 0x00132
+#define CKM_DES3_CBC 0x00133
+#define CKM_DES3_MAC 0x00134
+#define CKM_DES3_MAC_GENERAL 0x00135
+#define CKM_DES3_CBC_PAD 0x00136
+#define CKM_DES3_CMAC_GENERAL 0x00137
+#define CKM_DES3_CMAC 0x00138
+#define CKM_MD5 0x00210
+#define CKM_MD5_HMAC 0x00211
+#define CKM_MD5_HMAC_GENERAL 0x00212
+#define CKM_SHA_1 0x00220
+#define CKM_SHA_1_HMAC 0x00221
+#define CKM_SHA_1_HMAC_GENERAL 0x00222
+#define CKM_SHA256 0x00250
+#define CKM_SHA256_HMAC 0x00251
+#define CKM_SHA256_HMAC_GENERAL 0x00252
+#define CKM_SHA224 0x00255
+#define CKM_SHA224_HMAC 0x00256
+#define CKM_SHA224_HMAC_GENERAL 0x00257
+#define CKM_SHA384 0x00260
+#define CKM_SHA384_HMAC 0x00261
+#define CKM_SHA384_HMAC_GENERAL 0x00262
+#define CKM_SHA512 0x00270
+#define CKM_SHA512_HMAC 0x00271
+#define CKM_SHA512_HMAC_GENERAL 0x00272
+#define CKM_HOTP_KEY_GEN 0x00290
+#define CKM_HOTP 0x00291
+#define CKM_GENERIC_SECRET_KEY_GEN 0x00350
+#define CKM_MD5_KEY_DERIVATION 0x00390
+#define CKM_MD2_KEY_DERIVATION 0x00391
+#define CKM_SHA1_KEY_DERIVATION 0x00392
+#define CKM_SHA256_KEY_DERIVATION 0x00393
+#define CKM_SHA384_KEY_DERIVATION 0x00394
+#define CKM_SHA512_KEY_DERIVATION 0x00395
+#define CKM_SHA224_KEY_DERIVATION 0x00396
+#define CKM_EC_KEY_PAIR_GEN 0x01040
+#define CKM_ECDSA 0x01041
+#define CKM_ECDSA_SHA1 0x01042
+#define CKM_ECDSA_SHA224 0x01043
+#define CKM_ECDSA_SHA256 0x01044
+#define CKM_ECDSA_SHA384 0x01045
+#define CKM_ECDSA_SHA512 0x01046
+#define CKM_ECDH1_DERIVE 0x01050
+#define CKM_ECDH1_COFACTOR_DERIVE 0x01051
+#define CKM_ECMQV_DERIVE 0x01052
+#define CKM_ECDH_AES_KEY_WRAP 0x01053
+#define CKM_RSA_AES_KEY_WRAP 0x01054
+#define CKM_AES_KEY_GEN 0x01080
+#define CKM_AES_ECB 0x01081
+#define CKM_AES_CBC 0x01082
+#define CKM_AES_MAC 0x01083
+#define CKM_AES_MAC_GENERAL 0x01084
+#define CKM_AES_CBC_PAD 0x01085
+#define CKM_AES_CTR 0x01086
+#define CKM_AES_GCM 0x01087
+#define CKM_AES_CCM 0x01088
+#define CKM_AES_CTS 0x01089
+#define CKM_AES_CMAC 0x0108a
+#define CKM_AES_CMAC_GENERAL 0x0108b
+#define CKM_AES_XCBC_MAC 0x0108c
+#define CKM_AES_XCBC_MAC_96 0x0108d
+#define CKM_AES_GMAC 0x0108e
+#define CKM_DES3_ECB_ENCRYPT_DATA 0x01102
+#define CKM_DES3_CBC_ENCRYPT_DATA 0x01103
+#define CKM_AES_ECB_ENCRYPT_DATA 0x01104
+#define CKM_AES_CBC_ENCRYPT_DATA 0x01105
+#define CKM_AES_KEY_WRAP 0x02109
+#define CKM_AES_KEY_WRAP_PAD 0x0210a
+#define CKM_EC_KEY_PAIR_IMPORT 0x03000
+#define CKM_DUMP_LOG 0x03100
+
+
+#define CKM_MTK_HSM_EXT (CKM_VENDOR_DEFINED | (1U << 30))
+#define CKM_MTK_HSM_SHA1 (CKM_MTK_HSM_EXT | CKM_SHA_1)
+#define CKM_MTK_HSM_SHA224 (CKM_MTK_HSM_EXT | CKM_SHA224)
+#define CKM_MTK_HSM_SHA256 (CKM_MTK_HSM_EXT | CKM_SHA256)
+#define CKM_MTK_HSM_SHA384 (CKM_MTK_HSM_EXT | CKM_SHA384)
+#define CKM_MTK_HSM_SHA512 (CKM_MTK_HSM_EXT | CKM_SHA512)
+#define CKM_MTK_HSM_SHA256_HMAC (CKM_MTK_HSM_EXT | CKM_SHA256_HMAC)
+#define CKM_MTK_HSM_SHA384_HMAC (CKM_MTK_HSM_EXT | CKM_SHA384_HMAC)
+#define CKM_MTK_HSM_ECDSA (CKM_MTK_HSM_EXT | CKM_ECDSA)
+#define CKM_MTK_HSM_ECDSA_SHA1 (CKM_MTK_HSM_EXT | CKM_ECDSA_SHA1)
+#define CKM_MTK_HSM_ECDSA_SHA224 (CKM_MTK_HSM_EXT | CKM_ECDSA_SHA224)
+#define CKM_MTK_HSM_ECDSA_SHA256 (CKM_MTK_HSM_EXT | CKM_ECDSA_SHA256)
+#define CKM_MTK_HSM_ECDSA_SHA384 (CKM_MTK_HSM_EXT | CKM_ECDSA_SHA384)
+#define CKM_MTK_HSM_ECDSA_SHA512 (CKM_MTK_HSM_EXT | CKM_ECDSA_SHA512)
+#define CKM_MTK_HSM_AES_ECB (CKM_MTK_HSM_EXT | CKM_AES_ECB)
+#define CKM_MTK_HSM_AES_CBC (CKM_MTK_HSM_EXT | CKM_AES_CBC)
+#define CKM_MTK_HSM_AES_CTR (CKM_MTK_HSM_EXT | CKM_AES_CTR)
+#define CKM_MTK_HSM_AES_GCM (CKM_MTK_HSM_EXT | CKM_AES_GCM)
+#define CKM_MTK_HSM_AES_CMAC (CKM_MTK_HSM_EXT | CKM_AES_CMAC)
+#define CKM_MTK_HSM_AES_KEY_GEN (CKM_MTK_HSM_EXT | CKM_AES_KEY_GEN)
+#define CKM_MTK_HSM_EC_KEY_PAIR_GEN (CKM_MTK_HSM_EXT | CKM_EC_KEY_PAIR_GEN)
+#define CKM_MTK_HSM_EC_KEY_PAIR_IMPORT (CKM_MTK_HSM_EXT | CKM_EC_KEY_PAIR_IMPORT)
+#define CKM_MTK_HSM_DUMP_LOG (CKM_MTK_HSM_EXT | CKM_DUMP_LOG)
+
+
+typedef struct CK_MECHANISM_INFO CK_MECHANISM_INFO;
+typedef struct CK_MECHANISM_INFO * CK_MECHANISM_INFO_PTR;
+
+struct CK_MECHANISM_INFO {
+ CK_ULONG ulMinKeySize;
+ CK_ULONG ulMaxKeySize;
+ CK_FLAGS flags;
+};
+
+/* Flags for field flags of struct ck_mechanism_info */
+#define CKF_HW (1U << 0)
+#define CKF_ENCRYPT (1U << 8)
+#define CKF_DECRYPT (1U << 9)
+#define CKF_DIGEST (1U << 10)
+#define CKF_SIGN (1U << 11)
+#define CKF_SIGN_RECOVER (1U << 12)
+#define CKF_VERIFY (1U << 13)
+#define CKF_VERIFY_RECOVER (1U << 14)
+#define CKF_GENERATE (1U << 15)
+#define CKF_GENERATE_KEY_PAIR (1U << 16)
+#define CKF_WRAP (1U << 17)
+#define CKF_UNWRAP (1U << 18)
+#define CKF_DERIVE (1U << 19)
+#define CKF_EC_F_P (1U << 20)
+#define CKF_EC_F_2M (1U << 21)
+#define CKF_EC_ECPARAMETERS (1U << 22)
+#define CKF_EC_NAMEDCURVE (1U << 23)
+#define CKF_EC_UNCOMPRESS (1U << 24)
+#define CKF_EC_COMPRESS (1U << 25)
+#define CKF_EXTENSION (1U << 31)
+
+/*
+ * Mechanism parameter structures
+ *
+ * This does not cover the whole mechanism parameter structures defined by
+ * the PKCS#11. To be updated when needed.
+ */
+
+typedef struct CK_MECHANISM CK_MECHANISM;
+typedef struct CK_MECHANISM * CK_MECHANISM_PTR;
+
+struct CK_MECHANISM {
+ CK_MECHANISM_TYPE mechanism;
+ CK_VOID_PTR pParameter;
+ CK_ULONG ulParameterLen;
+};
+
+/* Key diversification identifiers */
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* Values for type CK_EC_KDF_TYPE */
+#define CKD_NULL 0x0001
+#define CKD_SHA1_KDF 0x0002
+#define CKD_SHA1_KDF_ASN1 0x0003
+#define CKD_SHA1_KDF_CONCATENATE 0x0004
+#define CKD_SHA224_KDF 0x0005
+#define CKD_SHA256_KDF 0x0006
+#define CKD_SHA384_KDF 0x0007
+#define CKD_SHA512_KDF 0x0008
+#define CKD_CPDIVERSIFY_KDF 0x0009
+
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+/* Values for type CK_RSA_PKCS_MGF_TYPE */
+#define CKG_MGF1_SHA1 0x0001UL
+#define CKG_MGF1_SHA224 0x0005UL
+#define CKG_MGF1_SHA256 0x0002UL
+#define CKG_MGF1_SHA384 0x0003UL
+#define CKG_MGF1_SHA512 0x0004UL
+
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+/* Values for type CK_RSA_PKCS_OAEP_SOURCE_TYPE */
+#define CKZ_DATA_SPECIFIED 0x0001UL
+
+/* MAC General parameters */
+typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
+typedef CK_MAC_GENERAL_PARAMS * CK_MAC_GENERAL_PARAMS_PTR;
+
+/*
+ * AES derivation by ECB encryption parameters: uses the generic
+ * structure CK_KEY_DERIVATION_STRING_DATA.
+ */
+typedef struct CK_KEY_DERIVATION_STRING_DATA CK_KEY_DERIVATION_STRING_DATA;
+typedef struct CK_KEY_DERIVATION_STRING_DATA * \
+ CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+struct CK_KEY_DERIVATION_STRING_DATA {
+ CK_BYTE_PTR pData;
+ CK_ULONG ulLen;
+};
+
+/* AES derivation by CBC encryption parameters */
+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS *
+ CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+};
+
+/* AES CTR parameters */
+typedef struct CK_AES_CTR_PARAMS CK_AES_CTR_PARAMS;
+typedef struct CK_AES_CTR_PARAMS * CK_AES_CTR_PARAMS_PTR;
+
+struct CK_AES_CTR_PARAMS {
+ CK_ULONG ulCounterBits;
+ CK_BYTE cb[16];
+};
+
+/* AES GCM parameters */
+typedef struct CK_GCM_PARAMS CK_GCM_PARAMS;
+typedef struct CK_GCM_PARAMS * CK_GCM_PARAMS_PTR;
+
+struct CK_GCM_PARAMS {
+ CK_BYTE_PTR pIv;
+ CK_ULONG ulIvLen;
+ CK_ULONG ulIvBits;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulTagBits;
+};
+
+/* AES CCM parameters */
+typedef struct CK_CCM_PARAMS CK_CCM_PARAMS;
+typedef struct CK_CCM_PARAMS * CK_CCM_PARAMS_PTR;
+
+struct CK_CCM_PARAMS {
+ CK_ULONG ulDataLen;
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceLen;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulMACLen;
+};
+
+/*
+ * Elliptic curve Diffie-Hellman key derivation
+ * Elliptic curve Diffie-Hellman cofactor key derivation parameters
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS CK_ECDH1_DERIVE_PARAMS;
+typedef struct CK_ECDH1_DERIVE_PARAMS * CK_ECDH1_DERIVE_PARAMS_PTR;
+
+struct CK_ECDH1_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+};
+
+/* Parameters for CKM_ECDH_AES_KEY_WRAP */
+typedef struct CK_ECDH_AES_KEY_WRAP_PARAMS CK_ECDH_AES_KEY_WRAP_PARAMS;
+typedef struct CK_ECDH_AES_KEY_WRAP_PARAMS * CK_ECDH_AES_KEY_WRAP_PARAMS_PTR;
+
+struct CK_ECDH_AES_KEY_WRAP_PARAMS {
+ CK_ULONG ulAESKeyBits;
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+};
+
+/* Parameters for CKM_RSA_PKCS_OAEP */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS CK_RSA_PKCS_OAEP_PARAMS;
+typedef struct CK_RSA_PKCS_OAEP_PARAMS * CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+};
+
+/* Parameters for CKM_RSA_PKCS_PSS */
+typedef struct CK_RSA_PKCS_PSS_PARAMS CK_RSA_PKCS_PSS_PARAMS;
+typedef struct CK_RSA_PKCS_PSS_PARAMS * CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+struct CK_RSA_PKCS_PSS_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_ULONG sLen;
+};
+
+/* Parameters for CKM_RSA_AES_KEY_WRAP */
+typedef struct CK_RSA_AES_KEY_WRAP_PARAMS CK_RSA_AES_KEY_WRAP_PARAMS;
+typedef struct CK_RSA_AES_KEY_WRAP_PARAMS * CK_RSA_AES_KEY_WRAP_PARAMS_PTR;
+
+struct CK_RSA_AES_KEY_WRAP_PARAMS {
+ CK_ULONG ulAESKeyBits;
+ CK_RSA_PKCS_OAEP_PARAMS_PTR pOAEPParams;
+};
+
+
+/*
+ * PKCS#11 return values
+ */
+typedef CK_ULONG CK_RV;
+
+/* Values for type CK_RV */
+#define CKR_VENDOR_DEFINED (1U << 31)
+#define CKR_OK 0x0000
+#define CKR_CANCEL 0x0001
+#define CKR_HOST_MEMORY 0x0002
+#define CKR_SLOT_ID_INVALID 0x0003
+#define CKR_GENERAL_ERROR 0x0005
+#define CKR_FUNCTION_FAILED 0x0006
+#define CKR_ARGUMENTS_BAD 0x0007
+#define CKR_NO_EVENT 0x0008
+#define CKR_NEED_TO_CREATE_THREADS 0x0009
+#define CKR_CANT_LOCK 0x000a
+#define CKR_ATTRIBUTE_READ_ONLY 0x0010
+#define CKR_ATTRIBUTE_SENSITIVE 0x0011
+#define CKR_ATTRIBUTE_TYPE_INVALID 0x0012
+#define CKR_ATTRIBUTE_VALUE_INVALID 0x0013
+#define CKR_ACTION_PROHIBITED 0x001b
+#define CKR_DATA_INVALID 0x0020
+#define CKR_DATA_LEN_RANGE 0x0021
+#define CKR_DEVICE_ERROR 0x0030
+#define CKR_DEVICE_MEMORY 0x0031
+#define CKR_DEVICE_REMOVED 0x0032
+#define CKR_ENCRYPTED_DATA_INVALID 0x0040
+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x0041
+#define CKR_FUNCTION_CANCELED 0x0050
+#define CKR_FUNCTION_NOT_PARALLEL 0x0051
+#define CKR_FUNCTION_NOT_SUPPORTED 0x0054
+#define CKR_KEY_HANDLE_INVALID 0x0060
+#define CKR_KEY_SIZE_RANGE 0x0062
+#define CKR_KEY_TYPE_INCONSISTENT 0x0063
+#define CKR_KEY_NOT_NEEDED 0x0064
+#define CKR_KEY_CHANGED 0x0065
+#define CKR_KEY_NEEDED 0x0066
+#define CKR_KEY_INDIGESTIBLE 0x0067
+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x0068
+#define CKR_KEY_NOT_WRAPPABLE 0x0069
+#define CKR_KEY_UNEXTRACTABLE 0x006a
+#define CKR_MECHANISM_INVALID 0x0070
+#define CKR_MECHANISM_PARAM_INVALID 0x0071
+#define CKR_OBJECT_HANDLE_INVALID 0x0082
+#define CKR_OPERATION_ACTIVE 0x0090
+#define CKR_OPERATION_NOT_INITIALIZED 0x0091
+#define CKR_PIN_INCORRECT 0x00a0
+#define CKR_PIN_INVALID 0x00a1
+#define CKR_PIN_LEN_RANGE 0x00a2
+#define CKR_PIN_EXPIRED 0x00a3
+#define CKR_PIN_LOCKED 0x00a4
+#define CKR_SESSION_CLOSED 0x00b0
+#define CKR_SESSION_COUNT 0x00b1
+#define CKR_SESSION_HANDLE_INVALID 0x00b3
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x00b4
+#define CKR_SESSION_READ_ONLY 0x00b5
+#define CKR_SESSION_EXISTS 0x00b6
+#define CKR_SESSION_READ_ONLY_EXISTS 0x00b7
+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x00b8
+#define CKR_SIGNATURE_INVALID 0x00c0
+#define CKR_SIGNATURE_LEN_RANGE 0x00c1
+#define CKR_TEMPLATE_INCOMPLETE 0x00d0
+#define CKR_TEMPLATE_INCONSISTENT 0x00d1
+#define CKR_TOKEN_NOT_PRESENT 0x00e0
+#define CKR_TOKEN_NOT_RECOGNIZED 0x00e1
+#define CKR_TOKEN_WRITE_PROTECTED 0x00e2
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x00f0
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x00f1
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x00f2
+#define CKR_USER_ALREADY_LOGGED_IN 0x0100
+#define CKR_USER_NOT_LOGGED_IN 0x0101
+#define CKR_USER_PIN_NOT_INITIALIZED 0x0102
+#define CKR_USER_TYPE_INVALID 0x0103
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x0104
+#define CKR_USER_TOO_MANY_TYPES 0x0105
+#define CKR_WRAPPED_KEY_INVALID 0x0110
+#define CKR_WRAPPED_KEY_LEN_RANGE 0x0112
+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x0113
+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x0114
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x0115
+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x0120
+#define CKR_RANDOM_NO_RNG 0x0121
+#define CKR_DOMAIN_PARAMS_INVALID 0x0130
+#define CKR_CURVE_NOT_SUPPORTED 0x0140
+#define CKR_BUFFER_TOO_SMALL 0x0150
+#define CKR_SAVED_STATE_INVALID 0x0160
+#define CKR_INFORMATION_SENSITIVE 0x0170
+#define CKR_STATE_UNSAVEABLE 0x0180
+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x0190
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x0191
+#define CKR_MUTEX_BAD 0x01a0
+#define CKR_MUTEX_NOT_LOCKED 0x01a1
+#define CKR_NEW_PIN_MODE 0x01b0
+#define CKR_NEXT_OTP 0x01b1
+#define CKR_EXCEEDED_MAX_ITERATIONS 0x01b5
+#define CKR_FIPS_SELF_TEST_FAILED 0x01b6
+#define CKR_LIBRARY_LOAD_FAILED 0x01b7
+#define CKR_PIN_TOO_WEAK 0x01b8
+#define CKR_PUBLIC_KEY_INVALID 0x01b9
+#define CKR_FUNCTION_REJECTED 0x0200
+
+/*
+ * PKCS#11 API functions
+ */
+
+/* Argument for C_GetInfo */
+typedef struct CK_INFO CK_INFO;
+typedef struct CK_INFO * CK_INFO_PTR;
+
+struct CK_INFO {
+ CK_VERSION cryptokiVersion;
+ CK_UTF8CHAR manufacturerID[32];
+ CK_FLAGS flags;
+ CK_UTF8CHAR libraryDescription[32];
+ CK_VERSION libraryVersion;
+};
+
+/* Argument for C_GetSlotInfo */
+typedef struct CK_SLOT_INFO CK_SLOT_INFO;
+typedef struct CK_SLOT_INFO * CK_SLOT_INFO_PTR;
+
+struct CK_SLOT_INFO {
+ CK_UTF8CHAR slotDescription[64];
+ CK_UTF8CHAR manufacturerID[32];
+ CK_FLAGS flags;
+ CK_VERSION hardwareVersion;
+ CK_VERSION firmwareVersion;
+};
+
+/* Values for field flags of struct ck_slot_info */
+#define CKF_TOKEN_PRESENT (1U << 0)
+#define CKF_REMOVABLE_DEVICE (1U << 1)
+#define CKF_HW_SLOT (1U << 2)
+
+/* Argument for C_GetTokenInfo */
+typedef struct CK_TOKEN_INFO CK_TOKEN_INFO;
+typedef struct CK_TOKEN_INFO * CK_TOKEN_INFO_PTR;
+
+struct CK_TOKEN_INFO {
+ CK_UTF8CHAR label[32];
+ CK_UTF8CHAR manufacturerID[32];
+ CK_UTF8CHAR model[16];
+ CK_CHAR serialNumber[16];
+ CK_FLAGS flags;
+ CK_ULONG ulMaxSessionCount;
+ CK_ULONG ulSessionCount;
+ CK_ULONG ulMaxRwSessionCount;
+ CK_ULONG ulRwSessionCount;
+ CK_ULONG ulMaxPinLen;
+ CK_ULONG ulMinPinLen;
+ CK_ULONG ulTotalPublicMemory;
+ CK_ULONG ulFreePublicMemory;
+ CK_ULONG ulTotalPrivateMemory;
+ CK_ULONG ulFreePrivateMemory;
+ CK_VERSION hardwareVersion;
+ CK_VERSION firmwareVersion;
+ CK_CHAR utcTime[16];
+};
+
+/* Values for field flags of struct ck_token_info */
+#define CKF_RNG (1U << 0)
+#define CKF_WRITE_PROTECTED (1U << 1)
+#define CKF_LOGIN_REQUIRED (1U << 2)
+#define CKF_USER_PIN_INITIALIZED (1U << 3)
+#define CKF_RESTORE_KEY_NOT_NEEDED (1U << 5)
+#define CKF_CLOCK_ON_TOKEN (1U << 6)
+#define CKF_PROTECTED_AUTHENTICATION_PATH (1U << 8)
+#define CKF_DUAL_CRYPTO_OPERATIONS (1U << 9)
+#define CKF_TOKEN_INITIALIZED (1U << 10)
+#define CKF_SECONDARY_AUTHENTICATION (1U << 11)
+#define CKF_USER_PIN_COUNT_LOW (1U << 16)
+#define CKF_USER_PIN_FINAL_TRY (1U << 17)
+#define CKF_USER_PIN_LOCKED (1U << 18)
+#define CKF_USER_PIN_TO_BE_CHANGED (1U << 19)
+#define CKF_SO_PIN_COUNT_LOW (1U << 20)
+#define CKF_SO_PIN_FINAL_TRY (1U << 21)
+#define CKF_SO_PIN_LOCKED (1U << 22)
+#define CKF_SO_PIN_TO_BE_CHANGED (1U << 23)
+#define CKF_ERROR_STATE (1U << 24)
+
+/* Argument for C_GetSessionInfo */
+typedef struct CK_SESSION_INFO CK_SESSION_INFO;
+typedef struct CK_SESSION_INFO * CK_SESSION_INFO_PTR;
+
+typedef CK_ULONG CK_STATE;
+
+/* Values for CK_STATE */
+#define CKS_RO_PUBLIC_SESSION 0
+#define CKS_RO_USER_FUNCTIONS 1
+#define CKS_RW_PUBLIC_SESSION 2
+#define CKS_RW_USER_FUNCTIONS 3
+#define CKS_RW_SO_FUNCTIONS 4
+
+struct CK_SESSION_INFO {
+ CK_SLOT_ID slotID;
+ CK_STATE state;
+ CK_FLAGS flags;
+ CK_ULONG ulDeviceError;
+};
+
+/* Values for field flags of struct ck_session_info */
+#define CKF_RW_SESSION (1U << 1)
+#define CKF_SERIAL_SESSION (1U << 2)
+
+/* Argument for C_Login */
+typedef CK_ULONG CK_USER_TYPE;
+
+/* Values for CK_USER_TYPE */
+#define CKU_SO 0
+#define CKU_USER 1
+#define CKU_CONTEXT_SPECIFIC 2
+
+/* Values for argument flags of C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK 1
+
+/* Argument for CK_NOTIFY typed callback function */
+typedef CK_ULONG CK_NOTIFICATION;
+
+/* Values for CK_NOTIFICATION */
+#define CKN_SURRENDER 0
+#define CKN_OTP_CHANGED 1
+
+/* Callback handler types */
+typedef CK_RV (* CK_NOTIFY)(CK_SESSION_HANDLE hSession,
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication);
+typedef CK_RV (* CK_CREATEMUTEX)(CK_VOID_PTR_PTR ppMutex);
+typedef CK_RV (* CK_DESTROYMUTEX)(CK_VOID_PTR pMutex);
+typedef CK_RV (* CK_LOCKMUTEX)(CK_VOID_PTR pMutex);
+typedef CK_RV (* CK_UNLOCKMUTEX)(CK_VOID_PTR pMutex);
+
+/* Argument for C_GetFunctionList */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+typedef struct CK_FUNCTION_LIST * CK_FUNCTION_LIST_PTR;
+typedef struct CK_FUNCTION_LIST ** CK_FUNCTION_LIST_PTR_PTR;
+
+struct CK_FUNCTION_LIST {
+ CK_VERSION version;
+ CK_RV (*C_Initialize)(
+ CK_VOID_PTR init_args);
+ CK_RV (*C_Finalize)(
+ CK_VOID_PTR res);
+ CK_RV (*C_GetInfo)(
+ CK_INFO_PTR info);
+ CK_RV (*C_GetFunctionList)(
+ CK_FUNCTION_LIST_PTR_PTR list);
+ CK_RV (*C_GetSlotList)(
+ CK_BBOOL token_present,
+ CK_SLOT_ID_PTR slots,
+ CK_ULONG_PTR count);
+ CK_RV (*C_GetSlotInfo)(
+ CK_SLOT_ID slot,
+ CK_SLOT_INFO_PTR info);
+ CK_RV (*C_GetTokenInfo)(
+ CK_SLOT_ID slot,
+ CK_TOKEN_INFO_PTR info);
+ CK_RV (*C_GetMechanismList)(
+ CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE_PTR mechanisms,
+ CK_ULONG_PTR count);
+ CK_RV (*C_GetMechanismInfo)(
+ CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR info);
+ CK_RV (*C_InitToken)(
+ CK_SLOT_ID slot,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len,
+ CK_UTF8CHAR_PTR label);
+ CK_RV (*C_InitPIN)(
+ CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len);
+ CK_RV (*C_SetPIN)(
+ CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR old,
+ CK_ULONG old_len,
+ CK_UTF8CHAR_PTR new,
+ CK_ULONG new_len);
+ CK_RV (*C_OpenSession)(CK_SLOT_ID slot,
+ CK_FLAGS flags,
+ CK_VOID_PTR cookie,
+ CK_NOTIFY callback,
+ CK_SESSION_HANDLE_PTR session);
+ CK_RV (*C_CloseSession)(
+ CK_SESSION_HANDLE session);
+ CK_RV (*C_CloseAllSessions)(
+ CK_SLOT_ID slot);
+ CK_RV (*C_GetSessionInfo)(
+ CK_SESSION_HANDLE session,
+ CK_SESSION_INFO_PTR info);
+ CK_RV (*C_GetOperationState)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR state,
+ CK_ULONG_PTR state_len);
+ CK_RV (*C_SetOperationState)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR state,
+ CK_ULONG state_len,
+ CK_OBJECT_HANDLE ciph_key,
+ CK_OBJECT_HANDLE auth_key);
+ CK_RV (*C_Login)(
+ CK_SESSION_HANDLE session,
+ CK_USER_TYPE user_type,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len);
+ CK_RV (*C_Logout)(
+ CK_SESSION_HANDLE session);
+ CK_RV (*C_CreateObject)(
+ CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR obj);
+ CK_RV (*C_CopyObject)(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_obj);
+ CK_RV (*C_DestroyObject)(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj);
+ CK_RV (*C_GetObjectSize)(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ULONG_PTR out_size);
+ CK_RV (*C_GetAttributeValue)(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count);
+ CK_RV (*C_SetAttributeValue)(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count);
+ CK_RV (*C_FindObjectsInit)(
+ CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count);
+ CK_RV (*C_FindObjects)(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE_PTR obj,
+ CK_ULONG max_count,
+ CK_ULONG_PTR count);
+ CK_RV (*C_FindObjectsFinal)(
+ CK_SESSION_HANDLE session);
+ CK_RV (*C_EncryptInit)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+ CK_RV (*C_Encrypt)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_EncryptUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_EncryptFinal)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_DecryptInit)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+ CK_RV (*C_Decrypt)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_DecryptUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_DecryptFinal)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_DigestInit)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism);
+ CK_RV (*C_Digest)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_DigestUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len);
+ CK_RV (*C_DigestKey)(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE key);
+ CK_RV (*C_DigestFinal)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR digest,
+ CK_ULONG_PTR len);
+ CK_RV (*C_SignInit)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+ CK_RV (*C_Sign)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_SignUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len);
+ CK_RV (*C_SignFinal)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_SignRecoverInit)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+ CK_RV (*C_SignRecover)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_VerifyInit)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+ CK_RV (*C_Verify)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR sign,
+ CK_ULONG sign_len);
+ CK_RV (*C_VerifyUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len);
+ CK_RV (*C_VerifyFinal)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR sign,
+ CK_ULONG sign_len);
+ CK_RV (*C_VerifyRecoverInit)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+ CK_RV (*C_VerifyRecover)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_DigestEncryptUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_DecryptDigestUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_SignEncryptUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_DecryptVerifyUpdate)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+ CK_RV (*C_GenerateKey)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_key);
+ CK_RV (*C_GenerateKeyPair)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_OBJECT_HANDLE_PTR pub_key,
+ CK_OBJECT_HANDLE_PTR priv_key);
+ CK_RV (*C_WrapKey)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE wrap_key,
+ CK_OBJECT_HANDLE key,
+ CK_BYTE_PTR wrapped_key,
+ CK_ULONG_PTR wrapped_key_len);
+ CK_RV (*C_UnwrapKey)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE unwrap_key,
+ CK_BYTE_PTR wrapped_key,
+ CK_ULONG wrapped_key_len,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_key);
+ CK_RV (*C_DeriveKey)(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE derived_key,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_key);
+ CK_RV (*C_SeedRandom)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR seed,
+ CK_ULONG len);
+ CK_RV (*C_GenerateRandom)(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG len);
+ CK_RV (*C_GetFunctionStatus)(
+ CK_SESSION_HANDLE sessin);
+ CK_RV (*C_CancelFunction)(
+ CK_SESSION_HANDLE session);
+ CK_RV (*C_WaitForSlotEvent)(
+ CK_FLAGS flags,
+ CK_SLOT_ID_PTR slot,
+ CK_VOID_PTR rsv);
+};
+
+/* Optional init_args structure for C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS CK_C_INITIALIZE_ARGS;
+typedef struct CK_C_INITIALIZE_ARGS * CK_C_INITIALIZE_ARGS_PTR;
+
+struct CK_C_INITIALIZE_ARGS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ CK_VOID_PTR reserved;
+};
+
+/* Flags for field flags of struct ck_c_initialize_args */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1U << 0)
+#define CKF_OS_LOCKING_OK (1U << 1)
+
+CK_RV C_Initialize(
+ CK_VOID_PTR init_args);
+
+CK_RV C_Finalize(
+ CK_VOID_PTR res);
+
+CK_RV C_GetInfo(
+ CK_INFO_PTR info);
+
+CK_RV C_GetFunctionList(
+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
+
+CK_RV C_GetSlotList(
+ CK_BBOOL token_present,
+ CK_SLOT_ID_PTR slots,
+ CK_ULONG_PTR count);
+
+CK_RV C_GetSlotInfo(
+ CK_SLOT_ID slot,
+ CK_SLOT_INFO_PTR info);
+
+CK_RV C_InitToken(
+ CK_SLOT_ID slot,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len,
+ CK_UTF8CHAR_PTR label);
+
+CK_RV C_GetTokenInfo(
+ CK_SLOT_ID slot,
+ CK_TOKEN_INFO_PTR info);
+
+CK_RV C_GetMechanismList(
+ CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE_PTR mechanisms,
+ CK_ULONG_PTR count);
+
+CK_RV C_GetMechanismInfo(
+ CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR info);
+
+CK_RV C_OpenSession(
+ CK_SLOT_ID slot,
+ CK_FLAGS flags,
+ CK_VOID_PTR cookie,
+ CK_NOTIFY callback,
+ CK_SESSION_HANDLE_PTR session);
+
+CK_RV C_CloseSession(
+ CK_SESSION_HANDLE session);
+
+CK_RV C_CloseAllSessions(
+ CK_SLOT_ID slot);
+
+CK_RV C_GetSessionInfo(
+ CK_SESSION_HANDLE session,
+ CK_SESSION_INFO_PTR info);
+
+CK_RV C_InitPIN(
+ CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len);
+
+CK_RV C_SetPIN(
+ CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR old,
+ CK_ULONG old_len,
+ CK_UTF8CHAR_PTR new,
+ CK_ULONG new_len);
+
+CK_RV C_Login(
+ CK_SESSION_HANDLE session,
+ CK_USER_TYPE user_type,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len);
+
+CK_RV C_Logout(
+ CK_SESSION_HANDLE session);
+
+CK_RV C_GetOperationState(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR state,
+ CK_ULONG_PTR state_len);
+
+CK_RV C_SetOperationState(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR state,
+ CK_ULONG state_len,
+ CK_OBJECT_HANDLE ciph_key,
+ CK_OBJECT_HANDLE auth_key);
+
+CK_RV C_CreateObject(
+ CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR obj);
+
+CK_RV C_CopyObject(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_obj);
+
+CK_RV C_DestroyObject(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj);
+
+CK_RV C_GetObjectSize(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ULONG_PTR out_size);
+
+CK_RV C_GetAttributeValue(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count);
+
+CK_RV C_SetAttributeValue(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count);
+
+CK_RV C_FindObjectsInit(
+ CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count);
+
+CK_RV C_FindObjects(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE_PTR obj,
+ CK_ULONG max_count,
+ CK_ULONG_PTR count);
+
+CK_RV C_FindObjectsFinal(
+ CK_SESSION_HANDLE session);
+
+CK_RV C_EncryptInit(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+
+CK_RV C_Encrypt(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_EncryptUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_EncryptFinal(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_DecryptInit(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+
+CK_RV C_Decrypt(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_DecryptUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_DecryptFinal(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_DigestInit(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism);
+
+CK_RV C_Digest(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_DigestUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len);
+
+CK_RV C_DigestKey(
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE key);
+
+CK_RV C_DigestFinal(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR digest,
+ CK_ULONG_PTR len);
+
+CK_RV C_SignInit(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+
+CK_RV C_Sign(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_SignUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len);
+
+CK_RV C_SignFinal(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_SignRecoverInit(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+
+CK_RV C_SignRecover(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_VerifyInit(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+
+CK_RV C_Verify(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR sign,
+ CK_ULONG sign_len);
+
+CK_RV C_VerifyUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len);
+
+CK_RV C_VerifyFinal(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR sign,
+ CK_ULONG sign_len);
+
+CK_RV C_VerifyRecoverInit(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key);
+
+CK_RV C_VerifyRecover(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_DigestEncryptUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_DecryptDigestUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_SignEncryptUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_DecryptVerifyUpdate(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV C_GenerateKey(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_key);
+
+CK_RV C_GenerateKeyPair(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_OBJECT_HANDLE_PTR pub_key,
+ CK_OBJECT_HANDLE_PTR priv_key);
+
+CK_RV C_WrapKey(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE wrap_key,
+ CK_OBJECT_HANDLE key,
+ CK_BYTE_PTR wrapped_key,
+ CK_ULONG_PTR wrapped_key_len);
+
+CK_RV C_UnwrapKey(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE unwrap_key,
+ CK_BYTE_PTR wrapped_key,
+ CK_ULONG wrapped_key_len,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_key);
+
+CK_RV C_DeriveKey(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE derived_key,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_key);
+
+CK_RV C_SeedRandom(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR seed,
+ CK_ULONG len);
+
+CK_RV C_GenerateRandom(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG len);
+
+CK_RV C_GetFunctionStatus(
+ CK_SESSION_HANDLE session);
+
+CK_RV C_CancelFunction(
+ CK_SESSION_HANDLE session);
+
+CK_RV C_WaitForSlotEvent(
+ CK_FLAGS flags,
+ CK_SLOT_ID_PTR slot,
+ CK_VOID_PTR rsv);
+
+CK_RV C_ImportKey(
+ CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG_PTR keyblob_length);
+
+CK_RV C_ImportKeyPair(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG_PTR keyblob_length);
+
+CK_RV C_ExportKey(
+ CK_SESSION_HANDLE session,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG keybloblength,
+ CK_BYTE_PTR pubkey,
+ CK_ULONG_PTR pubkeylength);
+
+CK_RV C_Utils(
+ CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__PKCS11_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/sks_ck_debug.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/sks_ck_debug.h
new file mode 100644
index 0000000..68d49c0
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/sks_ck_debug.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __SKS_CK_DEBUG_H
+#define __SKS_CK_DEBUG_H
+
+#include <pkcs11.h>
+
+/* Return a pointer to a string buffer of "CKA_xxx\0" attribute ID */
+const char *cka2str(CK_ATTRIBUTE_TYPE id);
+
+/* Return a pointer to a string buffer of "CKR_xxx\0" return value ID */
+const char *ckr2str(CK_RV id);
+
+/* Return a pointer to a string buffer of "CKM_xxx\0" mechanism ID */
+const char *ckm2str(CK_MECHANISM_TYPE id);
+
+/* Allocate and return a string descripbing the enabled flags */
+char *ck_slot_flag2str(CK_ULONG flags);
+char *ck_token_flag2str(CK_ULONG flags);
+char *ck_mecha_flag2str(CK_ULONG flags);
+
+const char *ckclass2str(CK_ULONG id);
+const char *cktype2str(CK_ULONG id, CK_ULONG class);
+
+const char *skscmd2str(unsigned int id);
+
+#endif /*__SKS_CK_DEBUG_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/sks_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/sks_ta.h
new file mode 120000
index 0000000..e5512c9
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/include/sks_ta.h
@@ -0,0 +1 @@
+../../ta/include/sks_ta.h
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_debug.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_debug.c
new file mode 100644
index 0000000..0637e12
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_debug.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sks_ta.h>
+#include <sks_ck_debug.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "local_utils.h"
+
+#define CK2STR_ENTRY(label) { .id = label, .string = #label }
+
+struct ck2str {
+ CK_ULONG id;
+ const char *string;
+};
+
+/*
+ * Return a pointer to a string buffer of "CKA_xxx\0" attribute ID
+ */
+static struct ck2str cka2str_table[] = {
+ /* OP-TEE SKS ID representing a not-yet defined value */
+ /* Standard CK attributes */
+ CK2STR_ENTRY(CKA_CLASS),
+ CK2STR_ENTRY(CKA_TOKEN),
+ CK2STR_ENTRY(CKA_PRIVATE),
+ CK2STR_ENTRY(CKA_LABEL),
+ CK2STR_ENTRY(CKA_APPLICATION),
+ CK2STR_ENTRY(CKA_VALUE),
+ CK2STR_ENTRY(CKA_OBJECT_ID),
+ CK2STR_ENTRY(CKA_CERTIFICATE_TYPE),
+ CK2STR_ENTRY(CKA_ISSUER),
+ CK2STR_ENTRY(CKA_SERIAL_NUMBER),
+ CK2STR_ENTRY(CKA_AC_ISSUER),
+ CK2STR_ENTRY(CKA_OWNER),
+ CK2STR_ENTRY(CKA_ATTR_TYPES),
+ CK2STR_ENTRY(CKA_TRUSTED),
+ CK2STR_ENTRY(CKA_CERTIFICATE_CATEGORY),
+ CK2STR_ENTRY(CKA_JAVA_MIDP_SECURITY_DOMAIN),
+ CK2STR_ENTRY(CKA_URL),
+ CK2STR_ENTRY(CKA_HASH_OF_SUBJECT_PUBLIC_KEY),
+ CK2STR_ENTRY(CKA_HASH_OF_ISSUER_PUBLIC_KEY),
+ CK2STR_ENTRY(CKA_NAME_HASH_ALGORITHM),
+ CK2STR_ENTRY(CKA_CHECK_VALUE),
+ CK2STR_ENTRY(CKA_KEY_TYPE),
+ CK2STR_ENTRY(CKA_SUBJECT),
+ CK2STR_ENTRY(CKA_ID),
+ CK2STR_ENTRY(CKA_SENSITIVE),
+ CK2STR_ENTRY(CKA_ENCRYPT),
+ CK2STR_ENTRY(CKA_DECRYPT),
+ CK2STR_ENTRY(CKA_WRAP),
+ CK2STR_ENTRY(CKA_UNWRAP),
+ CK2STR_ENTRY(CKA_SIGN),
+ CK2STR_ENTRY(CKA_SIGN_RECOVER),
+ CK2STR_ENTRY(CKA_VERIFY),
+ CK2STR_ENTRY(CKA_VERIFY_RECOVER),
+ CK2STR_ENTRY(CKA_DERIVE),
+ CK2STR_ENTRY(CKA_START_DATE),
+ CK2STR_ENTRY(CKA_END_DATE),
+ CK2STR_ENTRY(CKA_MODULUS),
+ CK2STR_ENTRY(CKA_MODULUS_BITS),
+ CK2STR_ENTRY(CKA_PUBLIC_EXPONENT),
+ CK2STR_ENTRY(CKA_PRIVATE_EXPONENT),
+ CK2STR_ENTRY(CKA_PRIME_1),
+ CK2STR_ENTRY(CKA_PRIME_2),
+ CK2STR_ENTRY(CKA_EXPONENT_1),
+ CK2STR_ENTRY(CKA_EXPONENT_2),
+ CK2STR_ENTRY(CKA_COEFFICIENT),
+ CK2STR_ENTRY(CKA_PUBLIC_KEY_INFO),
+ CK2STR_ENTRY(CKA_PRIME),
+ CK2STR_ENTRY(CKA_SUBPRIME),
+ CK2STR_ENTRY(CKA_BASE),
+ CK2STR_ENTRY(CKA_PRIME_BITS),
+ CK2STR_ENTRY(CKA_SUBPRIME_BITS),
+ CK2STR_ENTRY(CKA_VALUE_BITS),
+ CK2STR_ENTRY(CKA_VALUE_LEN),
+ CK2STR_ENTRY(CKA_EXTRACTABLE),
+ CK2STR_ENTRY(CKA_LOCAL),
+ CK2STR_ENTRY(CKA_NEVER_EXTRACTABLE),
+ CK2STR_ENTRY(CKA_ALWAYS_SENSITIVE),
+ CK2STR_ENTRY(CKA_KEY_GEN_MECHANISM),
+ CK2STR_ENTRY(CKA_MODIFIABLE),
+ CK2STR_ENTRY(CKA_COPYABLE),
+ CK2STR_ENTRY(CKA_DESTROYABLE),
+ CK2STR_ENTRY(CKA_EC_PARAMS),
+ CK2STR_ENTRY(CKA_EC_POINT),
+ CK2STR_ENTRY(CKA_ALWAYS_AUTHENTICATE),
+ CK2STR_ENTRY(CKA_WRAP_WITH_TRUSTED),
+ CK2STR_ENTRY(CKA_WRAP_TEMPLATE),
+ CK2STR_ENTRY(CKA_UNWRAP_TEMPLATE),
+ CK2STR_ENTRY(CKA_DERIVE_TEMPLATE),
+ CK2STR_ENTRY(CKA_OTP_FORMAT),
+ CK2STR_ENTRY(CKA_OTP_LENGTH),
+ CK2STR_ENTRY(CKA_OTP_TIME_INTERVAL),
+ CK2STR_ENTRY(CKA_OTP_USER_FRIENDLY_MODE),
+ CK2STR_ENTRY(CKA_OTP_CHALLENGE_REQUIREMENT),
+ CK2STR_ENTRY(CKA_OTP_TIME_REQUIREMENT),
+ CK2STR_ENTRY(CKA_OTP_COUNTER_REQUIREMENT),
+ CK2STR_ENTRY(CKA_OTP_PIN_REQUIREMENT),
+ CK2STR_ENTRY(CKA_OTP_COUNTER),
+ CK2STR_ENTRY(CKA_OTP_TIME),
+ CK2STR_ENTRY(CKA_OTP_USER_IDENTIFIER),
+ CK2STR_ENTRY(CKA_OTP_SERVICE_IDENTIFIER),
+ CK2STR_ENTRY(CKA_OTP_SERVICE_LOGO),
+ CK2STR_ENTRY(CKA_OTP_SERVICE_LOGO_TYPE),
+ CK2STR_ENTRY(CKA_GOSTR3410_PARAMS),
+ CK2STR_ENTRY(CKA_GOSTR3411_PARAMS),
+ CK2STR_ENTRY(CKA_GOST28147_PARAMS),
+ CK2STR_ENTRY(CKA_HW_FEATURE_TYPE),
+ CK2STR_ENTRY(CKA_RESET_ON_INIT),
+ CK2STR_ENTRY(CKA_HAS_RESET),
+ CK2STR_ENTRY(CKA_PIXEL_X),
+ CK2STR_ENTRY(CKA_PIXEL_Y),
+ CK2STR_ENTRY(CKA_RESOLUTION),
+ CK2STR_ENTRY(CKA_CHAR_ROWS),
+ CK2STR_ENTRY(CKA_CHAR_COLUMNS),
+ CK2STR_ENTRY(CKA_COLOR),
+ CK2STR_ENTRY(CKA_BITS_PER_PIXEL),
+ CK2STR_ENTRY(CKA_CHAR_SETS),
+ CK2STR_ENTRY(CKA_ENCODING_METHODS),
+ CK2STR_ENTRY(CKA_MIME_TYPES),
+ CK2STR_ENTRY(CKA_MECHANISM_TYPE),
+ CK2STR_ENTRY(CKA_REQUIRED_CMS_ATTRIBUTES),
+ CK2STR_ENTRY(CKA_DEFAULT_CMS_ATTRIBUTES),
+ CK2STR_ENTRY(CKA_SUPPORTED_CMS_ATTRIBUTES),
+ CK2STR_ENTRY(CKA_ALLOWED_MECHANISMS),
+ CK2STR_ENTRY(CKA_VENDOR_DEFINED),
+};
+
+const char *cka2str(CK_ATTRIBUTE_TYPE id)
+{
+ static const char vendor_range[] = "<unknwon-vendor-defined>";
+ static const char unknown[] = "<unknown-identifier>";
+ const int count = sizeof(cka2str_table) / sizeof(struct ck2str);
+ int n;
+
+ for (n = 0; n < count; n++) {
+ if (id == cka2str_table[n].id)
+ return cka2str_table[n].string;
+ }
+
+ if (id > CKA_VENDOR_DEFINED)
+ return vendor_range;
+
+ return unknown;
+}
+
+/*
+ * ckr2str - Return a pointer to a string buffer of "CKR_xxx\0" return value ID
+ */
+static struct ck2str ckr2str_table[] = {
+ CK2STR_ENTRY(CKR_OK),
+ CK2STR_ENTRY(CKR_CANCEL),
+ CK2STR_ENTRY(CKR_HOST_MEMORY),
+ CK2STR_ENTRY(CKR_SLOT_ID_INVALID),
+ CK2STR_ENTRY(CKR_GENERAL_ERROR),
+ CK2STR_ENTRY(CKR_FUNCTION_FAILED),
+ CK2STR_ENTRY(CKR_ARGUMENTS_BAD),
+ CK2STR_ENTRY(CKR_NO_EVENT),
+ CK2STR_ENTRY(CKR_NEED_TO_CREATE_THREADS),
+ CK2STR_ENTRY(CKR_CANT_LOCK),
+ CK2STR_ENTRY(CKR_ATTRIBUTE_READ_ONLY),
+ CK2STR_ENTRY(CKR_ATTRIBUTE_SENSITIVE),
+ CK2STR_ENTRY(CKR_ATTRIBUTE_TYPE_INVALID),
+ CK2STR_ENTRY(CKR_ATTRIBUTE_VALUE_INVALID),
+ CK2STR_ENTRY(CKR_ACTION_PROHIBITED),
+ CK2STR_ENTRY(CKR_DATA_INVALID),
+ CK2STR_ENTRY(CKR_DATA_LEN_RANGE),
+ CK2STR_ENTRY(CKR_DEVICE_ERROR),
+ CK2STR_ENTRY(CKR_DEVICE_MEMORY),
+ CK2STR_ENTRY(CKR_DEVICE_REMOVED),
+ CK2STR_ENTRY(CKR_ENCRYPTED_DATA_INVALID),
+ CK2STR_ENTRY(CKR_ENCRYPTED_DATA_LEN_RANGE),
+ CK2STR_ENTRY(CKR_FUNCTION_CANCELED),
+ CK2STR_ENTRY(CKR_FUNCTION_NOT_PARALLEL),
+ CK2STR_ENTRY(CKR_FUNCTION_NOT_SUPPORTED),
+ CK2STR_ENTRY(CKR_KEY_HANDLE_INVALID),
+ CK2STR_ENTRY(CKR_KEY_SIZE_RANGE),
+ CK2STR_ENTRY(CKR_KEY_TYPE_INCONSISTENT),
+ CK2STR_ENTRY(CKR_KEY_NOT_NEEDED),
+ CK2STR_ENTRY(CKR_KEY_CHANGED),
+ CK2STR_ENTRY(CKR_KEY_NEEDED),
+ CK2STR_ENTRY(CKR_KEY_INDIGESTIBLE),
+ CK2STR_ENTRY(CKR_KEY_FUNCTION_NOT_PERMITTED),
+ CK2STR_ENTRY(CKR_KEY_NOT_WRAPPABLE),
+ CK2STR_ENTRY(CKR_KEY_UNEXTRACTABLE),
+ CK2STR_ENTRY(CKR_MECHANISM_INVALID),
+ CK2STR_ENTRY(CKR_MECHANISM_PARAM_INVALID),
+ CK2STR_ENTRY(CKR_OBJECT_HANDLE_INVALID),
+ CK2STR_ENTRY(CKR_OPERATION_ACTIVE),
+ CK2STR_ENTRY(CKR_OPERATION_NOT_INITIALIZED),
+ CK2STR_ENTRY(CKR_PIN_INCORRECT),
+ CK2STR_ENTRY(CKR_PIN_INVALID),
+ CK2STR_ENTRY(CKR_PIN_LEN_RANGE),
+ CK2STR_ENTRY(CKR_PIN_EXPIRED),
+ CK2STR_ENTRY(CKR_PIN_LOCKED),
+ CK2STR_ENTRY(CKR_SESSION_CLOSED),
+ CK2STR_ENTRY(CKR_SESSION_COUNT),
+ CK2STR_ENTRY(CKR_SESSION_HANDLE_INVALID),
+ CK2STR_ENTRY(CKR_SESSION_PARALLEL_NOT_SUPPORTED),
+ CK2STR_ENTRY(CKR_SESSION_READ_ONLY),
+ CK2STR_ENTRY(CKR_SESSION_EXISTS),
+ CK2STR_ENTRY(CKR_SESSION_READ_ONLY_EXISTS),
+ CK2STR_ENTRY(CKR_SESSION_READ_WRITE_SO_EXISTS),
+ CK2STR_ENTRY(CKR_SIGNATURE_INVALID),
+ CK2STR_ENTRY(CKR_SIGNATURE_LEN_RANGE),
+ CK2STR_ENTRY(CKR_TEMPLATE_INCOMPLETE),
+ CK2STR_ENTRY(CKR_TEMPLATE_INCONSISTENT),
+ CK2STR_ENTRY(CKR_TOKEN_NOT_PRESENT),
+ CK2STR_ENTRY(CKR_TOKEN_NOT_RECOGNIZED),
+ CK2STR_ENTRY(CKR_TOKEN_WRITE_PROTECTED),
+ CK2STR_ENTRY(CKR_UNWRAPPING_KEY_HANDLE_INVALID),
+ CK2STR_ENTRY(CKR_UNWRAPPING_KEY_SIZE_RANGE),
+ CK2STR_ENTRY(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT),
+ CK2STR_ENTRY(CKR_USER_ALREADY_LOGGED_IN),
+ CK2STR_ENTRY(CKR_USER_NOT_LOGGED_IN),
+ CK2STR_ENTRY(CKR_USER_PIN_NOT_INITIALIZED),
+ CK2STR_ENTRY(CKR_USER_TYPE_INVALID),
+ CK2STR_ENTRY(CKR_USER_ANOTHER_ALREADY_LOGGED_IN),
+ CK2STR_ENTRY(CKR_USER_TOO_MANY_TYPES),
+ CK2STR_ENTRY(CKR_WRAPPED_KEY_INVALID),
+ CK2STR_ENTRY(CKR_WRAPPED_KEY_LEN_RANGE),
+ CK2STR_ENTRY(CKR_WRAPPING_KEY_HANDLE_INVALID),
+ CK2STR_ENTRY(CKR_WRAPPING_KEY_SIZE_RANGE),
+ CK2STR_ENTRY(CKR_WRAPPING_KEY_TYPE_INCONSISTENT),
+ CK2STR_ENTRY(CKR_RANDOM_SEED_NOT_SUPPORTED),
+ CK2STR_ENTRY(CKR_RANDOM_NO_RNG),
+ CK2STR_ENTRY(CKR_DOMAIN_PARAMS_INVALID),
+ CK2STR_ENTRY(CKR_CURVE_NOT_SUPPORTED),
+ CK2STR_ENTRY(CKR_BUFFER_TOO_SMALL),
+ CK2STR_ENTRY(CKR_SAVED_STATE_INVALID),
+ CK2STR_ENTRY(CKR_INFORMATION_SENSITIVE),
+ CK2STR_ENTRY(CKR_STATE_UNSAVEABLE),
+ CK2STR_ENTRY(CKR_CRYPTOKI_NOT_INITIALIZED),
+ CK2STR_ENTRY(CKR_CRYPTOKI_ALREADY_INITIALIZED),
+ CK2STR_ENTRY(CKR_MUTEX_BAD),
+ CK2STR_ENTRY(CKR_MUTEX_NOT_LOCKED),
+ CK2STR_ENTRY(CKR_NEW_PIN_MODE),
+ CK2STR_ENTRY(CKR_NEXT_OTP),
+ CK2STR_ENTRY(CKR_EXCEEDED_MAX_ITERATIONS),
+ CK2STR_ENTRY(CKR_FIPS_SELF_TEST_FAILED),
+ CK2STR_ENTRY(CKR_LIBRARY_LOAD_FAILED),
+ CK2STR_ENTRY(CKR_PIN_TOO_WEAK),
+ CK2STR_ENTRY(CKR_PUBLIC_KEY_INVALID),
+ CK2STR_ENTRY(CKR_FUNCTION_REJECTED),
+ CK2STR_ENTRY(CKR_VENDOR_DEFINED),
+};
+
+const char *ckr2str(CK_RV id)
+{
+ static const char vendor[] = "(vendor-defined)";
+ static const char unknown[] = "(unknown)";
+ const int count = sizeof(ckr2str_table) / sizeof(struct ck2str);
+ int n;
+
+ for (n = 0; n < count; n++) {
+ if (id == ckr2str_table[n].id)
+ return ckr2str_table[n].string;
+ }
+
+ if (id >= CKR_VENDOR_DEFINED)
+ return vendor;
+
+ return unknown;
+}
+
+/*
+ * ckr2str - Return a pointer to a string buffer of "CKM_xxx\0" mechanism ID
+ *
+ * This does not cover the whole IDs defined by the PKCS#11. To be updated
+ * when needed.
+ */
+static struct ck2str ckm2str_table[] = {
+ CK2STR_ENTRY(CKM_RSA_PKCS_KEY_PAIR_GEN),
+ CK2STR_ENTRY(CKM_RSA_PKCS),
+ CK2STR_ENTRY(CKM_RSA_9796),
+ CK2STR_ENTRY(CKM_RSA_X_509),
+ CK2STR_ENTRY(CKM_SHA1_RSA_PKCS),
+ CK2STR_ENTRY(CKM_RSA_PKCS_OAEP),
+ CK2STR_ENTRY(CKM_RSA_PKCS_PSS),
+ CK2STR_ENTRY(CKM_SHA1_RSA_PKCS_PSS),
+ CK2STR_ENTRY(CKM_SHA256_RSA_PKCS),
+ CK2STR_ENTRY(CKM_SHA384_RSA_PKCS),
+ CK2STR_ENTRY(CKM_SHA512_RSA_PKCS),
+ CK2STR_ENTRY(CKM_SHA256_RSA_PKCS_PSS),
+ CK2STR_ENTRY(CKM_SHA384_RSA_PKCS_PSS),
+ CK2STR_ENTRY(CKM_SHA512_RSA_PKCS_PSS),
+ CK2STR_ENTRY(CKM_SHA224_RSA_PKCS),
+ CK2STR_ENTRY(CKM_SHA224_RSA_PKCS_PSS),
+ CK2STR_ENTRY(CKM_SHA512_224),
+ CK2STR_ENTRY(CKM_SHA512_224_HMAC),
+ CK2STR_ENTRY(CKM_SHA512_224_HMAC_GENERAL),
+ CK2STR_ENTRY(CKM_SHA512_224_KEY_DERIVATION),
+ CK2STR_ENTRY(CKM_SHA512_256),
+ CK2STR_ENTRY(CKM_SHA512_256_HMAC),
+ CK2STR_ENTRY(CKM_SHA512_256_HMAC_GENERAL),
+ CK2STR_ENTRY(CKM_SHA512_256_KEY_DERIVATION),
+ CK2STR_ENTRY(CKM_MD5_HMAC),
+ CK2STR_ENTRY(CKM_MD5_HMAC_GENERAL),
+ CK2STR_ENTRY(CKM_SHA_1),
+ CK2STR_ENTRY(CKM_SHA_1_HMAC),
+ CK2STR_ENTRY(CKM_SHA_1_HMAC_GENERAL),
+ CK2STR_ENTRY(CKM_SHA256),
+ CK2STR_ENTRY(CKM_SHA256_HMAC),
+ CK2STR_ENTRY(CKM_SHA256_HMAC_GENERAL),
+ CK2STR_ENTRY(CKM_SHA224),
+ CK2STR_ENTRY(CKM_SHA224_HMAC),
+ CK2STR_ENTRY(CKM_SHA224_HMAC_GENERAL),
+ CK2STR_ENTRY(CKM_SHA384),
+ CK2STR_ENTRY(CKM_SHA384_HMAC),
+ CK2STR_ENTRY(CKM_SHA384_HMAC_GENERAL),
+ CK2STR_ENTRY(CKM_SHA512),
+ CK2STR_ENTRY(CKM_SHA512_HMAC),
+ CK2STR_ENTRY(CKM_SHA512_HMAC_GENERAL),
+ CK2STR_ENTRY(CKM_HOTP_KEY_GEN),
+ CK2STR_ENTRY(CKM_HOTP),
+ CK2STR_ENTRY(CKM_GENERIC_SECRET_KEY_GEN),
+ CK2STR_ENTRY(CKM_SHA1_KEY_DERIVATION),
+ CK2STR_ENTRY(CKM_SHA256_KEY_DERIVATION),
+ CK2STR_ENTRY(CKM_SHA384_KEY_DERIVATION),
+ CK2STR_ENTRY(CKM_SHA512_KEY_DERIVATION),
+ CK2STR_ENTRY(CKM_SHA224_KEY_DERIVATION),
+ CK2STR_ENTRY(CKM_EC_KEY_PAIR_GEN),
+ CK2STR_ENTRY(CKM_ECDSA),
+ CK2STR_ENTRY(CKM_ECDSA_SHA1),
+ CK2STR_ENTRY(CKM_ECDSA_SHA224),
+ CK2STR_ENTRY(CKM_ECDSA_SHA256),
+ CK2STR_ENTRY(CKM_ECDSA_SHA384),
+ CK2STR_ENTRY(CKM_ECDSA_SHA512),
+ CK2STR_ENTRY(CKM_ECDH1_DERIVE),
+ CK2STR_ENTRY(CKM_ECDH1_COFACTOR_DERIVE),
+ CK2STR_ENTRY(CKM_ECMQV_DERIVE),
+ CK2STR_ENTRY(CKM_ECDH_AES_KEY_WRAP),
+ CK2STR_ENTRY(CKM_RSA_AES_KEY_WRAP),
+ CK2STR_ENTRY(CKM_AES_KEY_GEN),
+ CK2STR_ENTRY(CKM_AES_ECB),
+ CK2STR_ENTRY(CKM_AES_CBC),
+ CK2STR_ENTRY(CKM_AES_MAC),
+ CK2STR_ENTRY(CKM_AES_MAC_GENERAL),
+ CK2STR_ENTRY(CKM_AES_CBC_PAD),
+ CK2STR_ENTRY(CKM_AES_CTR),
+ CK2STR_ENTRY(CKM_AES_GCM),
+ CK2STR_ENTRY(CKM_AES_CCM),
+ CK2STR_ENTRY(CKM_AES_CTS),
+ CK2STR_ENTRY(CKM_AES_CMAC),
+ CK2STR_ENTRY(CKM_AES_CMAC_GENERAL),
+ CK2STR_ENTRY(CKM_AES_XCBC_MAC),
+ CK2STR_ENTRY(CKM_AES_XCBC_MAC_96),
+ CK2STR_ENTRY(CKM_AES_GMAC),
+ CK2STR_ENTRY(CKM_DES3_ECB_ENCRYPT_DATA),
+ CK2STR_ENTRY(CKM_DES3_CBC_ENCRYPT_DATA),
+ CK2STR_ENTRY(CKM_AES_ECB_ENCRYPT_DATA),
+ CK2STR_ENTRY(CKM_AES_CBC_ENCRYPT_DATA),
+ CK2STR_ENTRY(CKM_AES_KEY_WRAP),
+ CK2STR_ENTRY(CKM_AES_KEY_WRAP_PAD),
+ CK2STR_ENTRY(CKM_MD5),
+ CK2STR_ENTRY(CKM_SHA_1),
+ CK2STR_ENTRY(CKM_SHA224),
+ CK2STR_ENTRY(CKM_SHA256),
+ CK2STR_ENTRY(CKM_SHA384),
+ CK2STR_ENTRY(CKM_SHA512),
+ CK2STR_ENTRY(CKM_DES_KEY_GEN),
+ CK2STR_ENTRY(CKM_DES_ECB),
+ CK2STR_ENTRY(CKM_DES_CBC),
+ CK2STR_ENTRY(CKM_DES_MAC),
+ CK2STR_ENTRY(CKM_DES_MAC_GENERAL),
+ CK2STR_ENTRY(CKM_DES_CBC_PAD),
+ CK2STR_ENTRY(CKM_VENDOR_DEFINED),
+};
+
+const char *ckm2str(CK_MECHANISM_TYPE id)
+{
+ static const char vendor[] = "(vendor-defined)";
+ static const char unknown[] = "(unknown)";
+ const int count = sizeof(ckm2str_table) / sizeof(struct ck2str);
+ int n;
+
+ for (n = 0; n < count; n++) {
+ if (id == ckm2str_table[n].id)
+ return ckm2str_table[n].string;
+ }
+
+ if (id >= CKM_VENDOR_DEFINED)
+ return vendor;
+
+ return unknown;
+}
+
+static struct ck2str skscmd2str_table[] = {
+ CK2STR_ENTRY(SKS_CMD_PING),
+ CK2STR_ENTRY(SKS_CMD_CK_SLOT_LIST),
+ CK2STR_ENTRY(SKS_CMD_CK_SLOT_INFO),
+ CK2STR_ENTRY(SKS_CMD_CK_TOKEN_INFO),
+ CK2STR_ENTRY(SKS_CMD_CK_MECHANISM_IDS),
+ CK2STR_ENTRY(SKS_CMD_CK_MECHANISM_INFO),
+ CK2STR_ENTRY(SKS_CMD_CK_INIT_TOKEN),
+ CK2STR_ENTRY(SKS_CMD_CK_INIT_PIN),
+ CK2STR_ENTRY(SKS_CMD_CK_SET_PIN),
+ CK2STR_ENTRY(SKS_CMD_CK_OPEN_RO_SESSION),
+ CK2STR_ENTRY(SKS_CMD_CK_OPEN_RW_SESSION),
+ CK2STR_ENTRY(SKS_CMD_CK_CLOSE_SESSION),
+ CK2STR_ENTRY(SKS_CMD_CK_SESSION_INFO),
+ CK2STR_ENTRY(SKS_CMD_IMPORT_OBJECT),
+ CK2STR_ENTRY(SKS_CMD_DESTROY_OBJECT),
+ CK2STR_ENTRY(SKS_CMD_ENCRYPT_INIT),
+ CK2STR_ENTRY(SKS_CMD_DECRYPT_INIT),
+ CK2STR_ENTRY(SKS_CMD_ENCRYPT_UPDATE),
+ CK2STR_ENTRY(SKS_CMD_DECRYPT_UPDATE),
+ CK2STR_ENTRY(SKS_CMD_DECRYPT_FINAL),
+ CK2STR_ENTRY(SKS_CMD_ENCRYPT_FINAL),
+};
+
+const char *skscmd2str(unsigned int id)
+{
+ static const char unknown[] = "<invalid-command-id>";
+ const int count = sizeof(skscmd2str_table) / sizeof(struct ck2str);
+ int n;
+
+ for (n = 0; n < count; n++) {
+ if (id == skscmd2str_table[n].id)
+ return skscmd2str_table[n].string;
+ }
+
+ return unknown;
+}
+
+static struct ck2str slotflag2str_table[] = {
+ CK2STR_ENTRY(CKF_TOKEN_PRESENT),
+ CK2STR_ENTRY(CKF_REMOVABLE_DEVICE),
+ CK2STR_ENTRY(CKF_HW_SLOT),
+};
+
+static const char *slot_flags2str(CK_ULONG flags)
+{
+ const int count = sizeof(slotflag2str_table) / sizeof(struct ck2str);
+ int n;
+
+ for (n = 0; n < count; n++) {
+ if (flags & slotflag2str_table[n].id)
+ return slotflag2str_table[n].string;
+ }
+
+ return NULL;
+}
+
+static struct ck2str tokenflag2str_table[] = {
+ CK2STR_ENTRY(CKF_RNG),
+ CK2STR_ENTRY(CKF_WRITE_PROTECTED),
+ CK2STR_ENTRY(CKF_LOGIN_REQUIRED),
+ CK2STR_ENTRY(CKF_USER_PIN_INITIALIZED),
+ CK2STR_ENTRY(CKF_RESTORE_KEY_NOT_NEEDED),
+ CK2STR_ENTRY(CKF_CLOCK_ON_TOKEN),
+ CK2STR_ENTRY(CKF_PROTECTED_AUTHENTICATION_PATH),
+ CK2STR_ENTRY(CKF_DUAL_CRYPTO_OPERATIONS),
+ CK2STR_ENTRY(CKF_TOKEN_INITIALIZED),
+ CK2STR_ENTRY(CKF_SECONDARY_AUTHENTICATION),
+ CK2STR_ENTRY(CKF_USER_PIN_COUNT_LOW),
+ CK2STR_ENTRY(CKF_USER_PIN_FINAL_TRY),
+ CK2STR_ENTRY(CKF_USER_PIN_LOCKED),
+ CK2STR_ENTRY(CKF_USER_PIN_TO_BE_CHANGED),
+ CK2STR_ENTRY(CKF_SO_PIN_COUNT_LOW),
+ CK2STR_ENTRY(CKF_SO_PIN_FINAL_TRY),
+ CK2STR_ENTRY(CKF_SO_PIN_LOCKED),
+ CK2STR_ENTRY(CKF_SO_PIN_TO_BE_CHANGED),
+ CK2STR_ENTRY(CKF_ERROR_STATE),
+};
+
+static const char *token_flags2str(CK_ULONG flags)
+{
+ const int count = sizeof(tokenflag2str_table) / sizeof(struct ck2str);
+ int n;
+
+ for (n = 0; n < count; n++) {
+ if (flags & tokenflag2str_table[n].id)
+ return tokenflag2str_table[n].string;
+ }
+
+ return NULL;
+}
+
+static struct ck2str mechaflag2str_table[] = {
+ CK2STR_ENTRY(CKF_HW),
+ CK2STR_ENTRY(CKF_ENCRYPT),
+ CK2STR_ENTRY(CKF_DECRYPT),
+ CK2STR_ENTRY(CKF_DIGEST),
+ CK2STR_ENTRY(CKF_SIGN),
+ CK2STR_ENTRY(CKF_SIGN_RECOVER),
+ CK2STR_ENTRY(CKF_VERIFY),
+ CK2STR_ENTRY(CKF_VERIFY_RECOVER),
+ CK2STR_ENTRY(CKF_GENERATE),
+ CK2STR_ENTRY(CKF_GENERATE_KEY_PAIR),
+ CK2STR_ENTRY(CKF_WRAP),
+ CK2STR_ENTRY(CKF_UNWRAP),
+ CK2STR_ENTRY(CKF_DERIVE),
+ CK2STR_ENTRY(CKF_EC_F_P),
+ CK2STR_ENTRY(CKF_EC_F_2M),
+ CK2STR_ENTRY(CKF_EC_ECPARAMETERS),
+ CK2STR_ENTRY(CKF_EC_NAMEDCURVE),
+ CK2STR_ENTRY(CKF_EC_UNCOMPRESS),
+ CK2STR_ENTRY(CKF_EC_COMPRESS),
+ CK2STR_ENTRY(CKF_EXTENSION),
+};
+
+static const char *mecha_flags2str(CK_ULONG flags)
+{
+ const int count = sizeof(mechaflag2str_table) / sizeof(struct ck2str);
+ int n;
+
+ for (n = 0; n < count; n++) {
+ if (flags & mechaflag2str_table[n].id)
+ return mechaflag2str_table[n].string;
+ }
+
+ return NULL;
+}
+
+enum ck_debug_flag_type {
+ CKDBG_SLOT,
+ CKDBG_TOKEN,
+ CKDBG_KEY,
+ CKDBG_CERTIF,
+ CKDBG_MECHA,
+};
+
+static char *__flag2str(CK_ULONG flags, enum ck_debug_flag_type type)
+{
+ char *str = NULL;
+ size_t size = 0;
+ int mask = 1;
+
+ for (mask = 1; flags && mask; flags &= ~mask, mask = mask << 1) {
+ char const *label = NULL;
+ size_t label_size;
+ char *nstr;
+
+ if (!(flags & mask))
+ continue;
+
+ switch(type) {
+ case CKDBG_SLOT:
+ label = slot_flags2str(mask);
+ break;
+ case CKDBG_TOKEN:
+ label = token_flags2str(mask);
+ break;
+ case CKDBG_MECHA:
+ label = mecha_flags2str(mask);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (!label)
+ continue;
+
+ /* 4 digit prefix "CKF_" is not dumped */
+ if (!memcmp(label, "CKF_", 4))
+ label += 4;
+
+ /* Extra space digit */
+ label_size = strlen(label) + 1;
+
+ /* Always allocate 1 more digit for terminal '\0' */
+ nstr = realloc(str, size + label_size + 1);
+ if (!nstr) {
+ free(str);
+ return NULL;
+ }
+
+ snprintf(nstr + size, label_size + 1, "%s ", label);
+ str = nstr;
+ size += label_size;
+ }
+
+ return str;
+}
+
+char *ck_slot_flag2str(CK_ULONG flags)
+{
+ return __flag2str(flags, CKDBG_SLOT);
+}
+
+char *ck_token_flag2str(CK_ULONG flags)
+{
+ return __flag2str(flags, CKDBG_TOKEN);
+}
+
+char *ck_mecha_flag2str(CK_ULONG flags)
+{
+ return __flag2str(flags, CKDBG_MECHA);
+}
+
+static struct ck2str class2str_table[] = {
+ CK2STR_ENTRY(CKO_DATA),
+ CK2STR_ENTRY(CKO_CERTIFICATE),
+ CK2STR_ENTRY(CKO_PUBLIC_KEY),
+ CK2STR_ENTRY(CKO_PRIVATE_KEY),
+ CK2STR_ENTRY(CKO_SECRET_KEY),
+ CK2STR_ENTRY(CKO_HW_FEATURE),
+ CK2STR_ENTRY(CKO_DOMAIN_PARAMETERS),
+ CK2STR_ENTRY(CKO_MECHANISM),
+ CK2STR_ENTRY(CKO_OTP_KEY),
+ CK2STR_ENTRY(CKO_VENDOR_DEFINED),
+};
+
+const char *ckclass2str(CK_ULONG id)
+{
+ const int count = sizeof(class2str_table) / sizeof(struct ck2str);
+ int n;
+
+ for (n = 0; n < count; n++)
+ if (id == class2str_table[n].id)
+ return class2str_table[n].string;
+
+ return NULL;
+}
+
+static struct ck2str symkey2str_table[] = {
+ CK2STR_ENTRY(CKK_RSA),
+ CK2STR_ENTRY(CKK_DSA),
+ CK2STR_ENTRY(CKK_DH),
+ CK2STR_ENTRY(CKK_ECDSA),
+ CK2STR_ENTRY(CKK_EC),
+ CK2STR_ENTRY(CKK_GENERIC_SECRET),
+ CK2STR_ENTRY(CKK_DES),
+ CK2STR_ENTRY(CKK_DES2),
+ CK2STR_ENTRY(CKK_DES3),
+ CK2STR_ENTRY(CKK_AES),
+ CK2STR_ENTRY(CKK_HOTP),
+ CK2STR_ENTRY(CKK_MD5_HMAC),
+ CK2STR_ENTRY(CKK_SHA_1_HMAC),
+ CK2STR_ENTRY(CKK_SHA256_HMAC),
+ CK2STR_ENTRY(CKK_SHA384_HMAC),
+ CK2STR_ENTRY(CKK_SHA512_HMAC),
+ CK2STR_ENTRY(CKK_SHA224_HMAC),
+ CK2STR_ENTRY(CKK_VENDOR_DEFINED),
+};
+
+const char *cktype2str(CK_ULONG id, CK_ULONG class)
+{
+ int count;
+ struct ck2str *table;
+ int n;
+
+ switch (class) {
+ case CKO_DATA:
+ /* No type for data object */
+ return NULL;
+ case CKO_SECRET_KEY:
+ count = sizeof(symkey2str_table);
+ table = symkey2str_table;
+ break;
+ case CKO_MECHANISM:
+ return ckm2str(id);
+ case CKO_CERTIFICATE:
+ case CKO_DOMAIN_PARAMETERS:
+ case CKO_HW_FEATURE:
+ case CKO_PUBLIC_KEY:
+ case CKO_PRIVATE_KEY:
+ case CKO_OTP_KEY:
+ /* Not supported */
+ return NULL;
+ default:
+ /* Unknwon */
+ return NULL;
+ }
+
+ count /= sizeof(struct ck2str);
+ for (n = 0; n < count; n++)
+ if (id == table[n].id)
+ return table[n].string;
+
+ return NULL;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_helpers.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_helpers.c
new file mode 100644
index 0000000..212793f
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_helpers.c
@@ -0,0 +1,903 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ck_helpers.h"
+#include "local_utils.h"
+
+/*
+ * SKS TA returns Cryptoki like information structure.
+ * These routine convert the SKS format structure and bit flags
+ * from/into Cryptoki format structures and bit flags.
+ */
+#define MEMCPY_FIELD(_dst, _src, _f) \
+ do { \
+ memcpy((_dst)->_f, (_src)->_f, sizeof((_dst)->_f)); \
+ if (sizeof((_dst)->_f) != sizeof((_src)->_f)) \
+ return CKR_GENERAL_ERROR; \
+ } while (0)
+
+#define MEMCPY_VERSION(_dst, _src, _f) \
+ do { \
+ memcpy(&(_dst)->_f, (_src)->_f, sizeof(CK_VERSION)); \
+ if (sizeof(CK_VERSION) != sizeof((_src)->_f)) \
+ return CKR_GENERAL_ERROR; \
+ } while (0)
+
+static CK_RV sks2ck_all_slot_flags(CK_SLOT_INFO_PTR ck_info,
+ struct sks_slot_info *sks_info)
+{
+ CK_FLAGS ck_flag;
+ uint32_t sks_mask;
+
+ ck_info->flags = 0;
+ for (sks_mask = 1; sks_mask; sks_mask <<= 1) {
+
+ /* Skip sks token flags without a CK equilavent */
+ if (sks2ck_slot_flag(&ck_flag, sks_mask))
+ continue;
+
+ if (sks_info->flags & sks_mask)
+ ck_info->flags |= ck_flag;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV sks2ck_slot_info(CK_SLOT_INFO_PTR ck_info,
+ struct sks_slot_info *sks_info)
+{
+ CK_RV rv;
+
+ MEMCPY_FIELD(ck_info, sks_info, slotDescription);
+ MEMCPY_FIELD(ck_info, sks_info, manufacturerID);
+
+ rv = sks2ck_all_slot_flags(ck_info, sks_info);
+ if (rv)
+ return rv;
+
+ MEMCPY_VERSION(ck_info, sks_info, hardwareVersion);
+ MEMCPY_VERSION(ck_info, sks_info, firmwareVersion);
+
+ return CKR_OK;
+}
+
+static CK_RV sks2ck_all_token_flags(CK_TOKEN_INFO_PTR ck_info,
+ struct sks_token_info *sks_info)
+{
+ CK_FLAGS ck_flag;
+ uint32_t sks_mask;
+
+ ck_info->flags = 0;
+ for (sks_mask = 1; sks_mask; sks_mask <<= 1) {
+
+ /* Skip sks token flags without a CK equilavent */
+ if (sks2ck_token_flag(&ck_flag, sks_mask))
+ continue;
+
+ if (sks_info->flags & sks_mask)
+ ck_info->flags |= ck_flag;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV sks2ck_token_info(CK_TOKEN_INFO_PTR ck_info,
+ struct sks_token_info *sks_info)
+{
+ CK_RV rv;
+
+ MEMCPY_FIELD(ck_info, sks_info, label);
+ MEMCPY_FIELD(ck_info, sks_info, manufacturerID);
+ MEMCPY_FIELD(ck_info, sks_info, model);
+ MEMCPY_FIELD(ck_info, sks_info, serialNumber);
+
+ rv = sks2ck_all_token_flags(ck_info, sks_info);
+ if (rv)
+ return rv;
+
+ ck_info->ulMaxSessionCount = sks_info->ulMaxSessionCount;
+ ck_info->ulSessionCount = sks_info->ulSessionCount;
+ ck_info->ulMaxRwSessionCount = sks_info->ulMaxRwSessionCount;
+ ck_info->ulRwSessionCount = sks_info->ulRwSessionCount;
+ ck_info->ulMaxPinLen = sks_info->ulMaxPinLen;
+ ck_info->ulMinPinLen = sks_info->ulMinPinLen;
+ ck_info->ulTotalPublicMemory = sks_info->ulTotalPublicMemory;
+ ck_info->ulFreePublicMemory = sks_info->ulFreePublicMemory;
+ ck_info->ulTotalPrivateMemory = sks_info->ulTotalPrivateMemory;
+ ck_info->ulFreePrivateMemory = sks_info->ulFreePrivateMemory;
+ MEMCPY_VERSION(ck_info, sks_info, hardwareVersion);
+ MEMCPY_VERSION(ck_info, sks_info, firmwareVersion);
+ MEMCPY_FIELD(ck_info, sks_info, utcTime);
+
+ return CKR_OK;
+}
+
+CK_RV sks2ck_session_info(CK_SESSION_INFO_PTR ck_info,
+ struct sks_session_info *sks_info)
+{
+ ck_info->slotID = sks_info->slot_id;
+ ck_info->state = sks_info->state;
+ ck_info->flags = sks_info->flags;
+ ck_info->ulDeviceError = sks_info->error_code;
+
+ return CKR_OK;
+}
+
+/*
+ * Helpers for CK/SKS conversions: tables of identifiers
+ *
+ * Define conversion tables between Cryptoki IDs and SKS 32bit IDs.
+ * By convention, Cryptoki variable types CK_<XYZ> (i.e CK_ATTRIBUTE_TYPE)
+ * are registered through DECLARE_CK2SKS_FUNCTIONS(<xyz>); in ck_helpers.h
+ * and locally through DEFINE_CK2SKS_FUNCTIONS(<xyz>) in this source file.
+ *
+ * In the above description, <xyz> is the lower case equivalent of <XYZ>
+ * in Cryptoki variable type definition label. I.e, for type CK_ATTRIBUTE_TYPE:
+ *
+ * In header file:
+ * DECLARE_CK2SKS_FUNCTIONS(attribute_type);
+ * In source file:
+ * static const struct ck2sks attribute_type[] = {
+ * CK2SKS_ID_BRACE(CKA_CLASS, SKS_CKA_CLASS),
+ * CK2SKS_ID_BRACE(CKA_TOKEN, SKS_CKA_TOKEN),
+ * ...
+ * };
+ * DEFINE_CK2SKS_FUNCTIONS(attribute_type, CK_ATTRIBUTE_TYPE)
+ *
+ * The above code snipet declares and defines functions ck2sks_attribute_type()
+ * and sks2ck_attribute_type() using ID conversion array attribute type
+ * defines in the source file.
+ *
+ * Some Cryptoki variables types have mutliple ID enumerations that would
+ * conflict if merged into a single ID valid list. For exmaple the flag type
+ * CK_FLAGS is used by Cryptoki to enumerate mechanism flags, token flags and
+ * more. This implementation defines specific tables per ID scope.
+ * I.e:
+ * mechanism_flags for CKF_<FOO> related to mechanism flags.
+ * token_flags for CKF_<FOO> related to token flags.
+ */
+struct ck2sks {
+ CK_ULONG ck;
+ uint32_t sks;
+ // TODO: string for both IDs
+};
+
+/*
+ * Macros to define the SKS identifier relate to a Cryptoki identifier.
+ * Use CK2SKS_ID() when SKS identifier label is SKS_<CK-label>.
+ * Use CK2SKS_BRACE() when specific SKS identifier regarding Cryptoki CK label.
+ */
+#define CK2SKS_ID(ck_id) { .ck = ck_id, .sks = SKS_ ## ck_id }
+#define CK2SKS_ID_BRACE(ck_id, sks_id) { .ck = ck_id, .sks = sks_id }
+
+#define SKS2CK(out, in, conv) sks2ck(out, in, conv, ARRAY_SIZE(conv))
+#define CK2SKS(out, in, conv) ck2sks(out, in, conv, ARRAY_SIZE(conv))
+
+#define DEFINE_CK2SKS_FUNCTIONS(_conv_table, _ck_typeof) \
+ uint32_t ck2sks_ ## _conv_table(_ck_typeof ck) \
+ { \
+ uint32_t id; \
+ \
+ if (CK2SKS(&id, ck, _conv_table)) \
+ return SKS_UNDEFINED_ID; \
+ \
+ return id; \
+ } \
+ CK_RV sks2ck_ ## _conv_table(_ck_typeof *ck, uint32_t sks) \
+ { \
+ if (SKS2CK(ck, sks, _conv_table)) \
+ return CKR_GENERAL_ERROR; \
+ \
+ return CKR_OK; \
+ }
+
+static int sks2ck(CK_ULONG *out, uint32_t id,
+ const struct ck2sks *conv, size_t count)
+{
+ size_t n;
+
+ for (n = 0; n < count; n++) {
+ if (id == conv[n].sks) {
+ *out = conv[n].ck;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int ck2sks(uint32_t *out, CK_ULONG id,
+ const struct ck2sks *conv, size_t count)
+{
+ size_t n;
+
+ for (n = 0; n < count; n++) {
+ if (id == conv[n].ck) {
+ *out = conv[n].sks;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Identifiers conversion tables and related functions definitions.
+ * Generic way goes:
+ *
+ * static const struct ck2sks <foo>[] = {
+ * CK2SKS_ID_BRACE(CK[<X>]_<Y>),
+ * CK2SKS_ID_BRACE(CK[<X>]_<Y>, SKS_<Z>),
+ * };
+ *
+ * DEFINE_CK2SKS_FUNCTIONS(<foo>, CK_<related-type-label>)
+ */
+static const struct ck2sks slot_flag[] = {
+ CK2SKS_ID_BRACE(CKF_TOKEN_PRESENT, SKS_CKFS_TOKEN_PRESENT),
+ CK2SKS_ID_BRACE(CKF_REMOVABLE_DEVICE, SKS_CKFS_REMOVABLE_DEVICE),
+ CK2SKS_ID_BRACE(CKF_HW_SLOT, SKS_CKFS_HW_SLOT),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(slot_flag, CK_FLAGS)
+
+static const struct ck2sks token_flag[] = {
+ CK2SKS_ID_BRACE(CKF_RNG,
+ SKS_CKFT_RNG),
+ CK2SKS_ID_BRACE(CKF_WRITE_PROTECTED,
+ SKS_CKFT_WRITE_PROTECTED),
+ CK2SKS_ID_BRACE(CKF_LOGIN_REQUIRED,
+ SKS_CKFT_LOGIN_REQUIRED),
+ CK2SKS_ID_BRACE(CKF_USER_PIN_INITIALIZED,
+ SKS_CKFT_USER_PIN_INITIALIZED),
+ CK2SKS_ID_BRACE(CKF_RESTORE_KEY_NOT_NEEDED,
+ SKS_CKFT_RESTORE_KEY_NOT_NEEDED),
+ CK2SKS_ID_BRACE(CKF_CLOCK_ON_TOKEN,
+ SKS_CKFT_CLOCK_ON_TOKEN),
+ CK2SKS_ID_BRACE(CKF_PROTECTED_AUTHENTICATION_PATH,
+ SKS_CKFT_PROTECTED_AUTHENTICATION_PATH),
+ CK2SKS_ID_BRACE(CKF_DUAL_CRYPTO_OPERATIONS,
+ SKS_CKFT_DUAL_CRYPTO_OPERATIONS),
+ CK2SKS_ID_BRACE(CKF_TOKEN_INITIALIZED,
+ SKS_CKFT_TOKEN_INITIALIZED),
+ CK2SKS_ID_BRACE(CKF_USER_PIN_COUNT_LOW,
+ SKS_CKFT_USER_PIN_COUNT_LOW),
+ CK2SKS_ID_BRACE(CKF_USER_PIN_FINAL_TRY,
+ SKS_CKFT_USER_PIN_FINAL_TRY),
+ CK2SKS_ID_BRACE(CKF_USER_PIN_LOCKED,
+ SKS_CKFT_USER_PIN_LOCKED),
+ CK2SKS_ID_BRACE(CKF_USER_PIN_TO_BE_CHANGED,
+ SKS_CKFT_USER_PIN_TO_BE_CHANGED),
+ CK2SKS_ID_BRACE(CKF_SO_PIN_COUNT_LOW,
+ SKS_CKFT_SO_PIN_COUNT_LOW),
+ CK2SKS_ID_BRACE(CKF_SO_PIN_FINAL_TRY,
+ SKS_CKFT_SO_PIN_FINAL_TRY),
+ CK2SKS_ID_BRACE(CKF_SO_PIN_LOCKED,
+ SKS_CKFT_SO_PIN_LOCKED),
+ CK2SKS_ID_BRACE(CKF_SO_PIN_TO_BE_CHANGED,
+ SKS_CKFT_SO_PIN_TO_BE_CHANGED),
+ CK2SKS_ID_BRACE(CKF_ERROR_STATE,
+ SKS_CKFT_ERROR_STATE),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(token_flag, CK_FLAGS)
+
+static const struct ck2sks attribute_type[] = {
+ CK2SKS_ID(CKA_CLASS),
+ CK2SKS_ID(CKA_KEY_TYPE),
+ CK2SKS_ID(CKA_VALUE),
+ CK2SKS_ID(CKA_VALUE_LEN),
+ CK2SKS_ID(CKA_LABEL),
+ CK2SKS_ID(CKA_WRAP_TEMPLATE),
+ CK2SKS_ID(CKA_UNWRAP_TEMPLATE),
+ CK2SKS_ID(CKA_DERIVE_TEMPLATE),
+ CK2SKS_ID(CKA_START_DATE),
+ CK2SKS_ID(CKA_END_DATE),
+ CK2SKS_ID(CKA_OBJECT_ID),
+ CK2SKS_ID(CKA_APPLICATION),
+ CK2SKS_ID(CKA_MECHANISM_TYPE),
+ CK2SKS_ID(CKA_ID),
+ CK2SKS_ID(CKA_ALLOWED_MECHANISMS),
+ CK2SKS_ID(CKA_EC_PARAMS),
+ CK2SKS_ID(CKA_EC_POINT),
+ CK2SKS_ID(CKA_MODULUS),
+ CK2SKS_ID(CKA_MODULUS_BITS),
+ CK2SKS_ID(CKA_PUBLIC_EXPONENT),
+ CK2SKS_ID(CKA_PRIVATE_EXPONENT),
+ CK2SKS_ID(CKA_PRIME_1),
+ CK2SKS_ID(CKA_PRIME_2),
+ CK2SKS_ID(CKA_EXPONENT_1),
+ CK2SKS_ID(CKA_EXPONENT_2),
+ CK2SKS_ID(CKA_COEFFICIENT),
+ CK2SKS_ID(CKA_SUBJECT),
+ CK2SKS_ID(CKA_PUBLIC_KEY_INFO),
+ CK2SKS_ID(CKA_CERTIFICATE_TYPE),
+ CK2SKS_ID(CKA_CERTIFICATE_CATEGORY),
+ CK2SKS_ID(CKA_ISSUER),
+ CK2SKS_ID(CKA_SERIAL_NUMBER),
+ CK2SKS_ID(CKA_URL),
+ CK2SKS_ID(CKA_HASH_OF_SUBJECT_PUBLIC_KEY),
+ CK2SKS_ID(CKA_HASH_OF_ISSUER_PUBLIC_KEY),
+ CK2SKS_ID(CKA_NAME_HASH_ALGORITHM),
+ CK2SKS_ID(CKA_KEY_GEN_MECHANISM),
+ /* Below are boolean attributes */
+ CK2SKS_ID(CKA_TOKEN),
+ CK2SKS_ID(CKA_PRIVATE),
+ CK2SKS_ID(CKA_TRUSTED),
+ CK2SKS_ID(CKA_SENSITIVE),
+ CK2SKS_ID(CKA_ENCRYPT),
+ CK2SKS_ID(CKA_DECRYPT),
+ CK2SKS_ID(CKA_WRAP),
+ CK2SKS_ID(CKA_UNWRAP),
+ CK2SKS_ID(CKA_SIGN),
+ CK2SKS_ID(CKA_SIGN_RECOVER),
+ CK2SKS_ID(CKA_VERIFY),
+ CK2SKS_ID(CKA_VERIFY_RECOVER),
+ CK2SKS_ID(CKA_DERIVE),
+ CK2SKS_ID(CKA_EXTRACTABLE),
+ CK2SKS_ID(CKA_LOCAL),
+ CK2SKS_ID(CKA_NEVER_EXTRACTABLE),
+ CK2SKS_ID(CKA_ALWAYS_SENSITIVE),
+ CK2SKS_ID(CKA_MODIFIABLE),
+ CK2SKS_ID(CKA_COPYABLE),
+ CK2SKS_ID(CKA_DESTROYABLE),
+ CK2SKS_ID(CKA_ALWAYS_AUTHENTICATE),
+ CK2SKS_ID(CKA_WRAP_WITH_TRUSTED),
+ /* Specifc SKS attribute IDs */
+ CK2SKS_ID_BRACE(CK_VENDOR_INVALID_ID, SKS_UNDEFINED_ID),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(attribute_type, CK_ATTRIBUTE_TYPE)
+
+static const struct ck2sks mechanism_type[] = {
+ CK2SKS_ID(CKM_MD5),
+ CK2SKS_ID(CKM_SHA_1),
+ CK2SKS_ID(CKM_SHA224),
+ CK2SKS_ID(CKM_SHA256),
+ CK2SKS_ID(CKM_SHA384),
+ CK2SKS_ID(CKM_SHA512),
+
+ CK2SKS_ID(CKM_AES_ECB),
+ CK2SKS_ID(CKM_AES_CBC),
+ CK2SKS_ID(CKM_AES_CBC_PAD),
+ CK2SKS_ID(CKM_AES_CTR),
+ CK2SKS_ID(CKM_AES_GCM),
+ CK2SKS_ID(CKM_AES_CCM),
+ CK2SKS_ID(CKM_AES_CTS),
+ CK2SKS_ID(CKM_AES_GMAC),
+ CK2SKS_ID(CKM_AES_CMAC),
+ CK2SKS_ID(CKM_AES_CMAC_GENERAL),
+ CK2SKS_ID(CKM_AES_ECB_ENCRYPT_DATA),
+ CK2SKS_ID(CKM_AES_CBC_ENCRYPT_DATA),
+ CK2SKS_ID(CKM_AES_KEY_GEN),
+ CK2SKS_ID(CKM_AES_XCBC_MAC),
+
+ CK2SKS_ID(CKM_GENERIC_SECRET_KEY_GEN),
+
+ CK2SKS_ID(CKM_MD5_HMAC),
+ CK2SKS_ID(CKM_SHA_1_HMAC),
+ CK2SKS_ID(CKM_SHA224_HMAC),
+ CK2SKS_ID(CKM_SHA256_HMAC),
+ CK2SKS_ID(CKM_SHA384_HMAC),
+ CK2SKS_ID(CKM_SHA512_HMAC),
+
+ CK2SKS_ID(CKM_EC_KEY_PAIR_GEN),
+ CK2SKS_ID(CKM_ECDSA),
+ CK2SKS_ID(CKM_ECDSA_SHA1),
+ CK2SKS_ID(CKM_ECDSA_SHA224),
+ CK2SKS_ID(CKM_ECDSA_SHA256),
+ CK2SKS_ID(CKM_ECDSA_SHA384),
+ CK2SKS_ID(CKM_ECDSA_SHA512),
+ CK2SKS_ID(CKM_ECDH1_DERIVE),
+ CK2SKS_ID(CKM_ECDH1_COFACTOR_DERIVE),
+ CK2SKS_ID(CKM_ECMQV_DERIVE),
+ CK2SKS_ID(CKM_ECDH_AES_KEY_WRAP),
+
+ CK2SKS_ID(CKM_RSA_PKCS_KEY_PAIR_GEN),
+ CK2SKS_ID(CKM_RSA_PKCS),
+ CK2SKS_ID(CKM_RSA_9796),
+ CK2SKS_ID(CKM_RSA_X_509),
+ CK2SKS_ID(CKM_SHA1_RSA_PKCS),
+ CK2SKS_ID(CKM_RSA_PKCS_OAEP),
+ CK2SKS_ID(CKM_RSA_PKCS_PSS),
+ CK2SKS_ID(CKM_SHA1_RSA_PKCS_PSS),
+ CK2SKS_ID(CKM_SHA256_RSA_PKCS),
+ CK2SKS_ID(CKM_SHA384_RSA_PKCS),
+ CK2SKS_ID(CKM_SHA512_RSA_PKCS),
+ CK2SKS_ID(CKM_SHA256_RSA_PKCS_PSS),
+ CK2SKS_ID(CKM_SHA384_RSA_PKCS_PSS),
+ CK2SKS_ID(CKM_SHA512_RSA_PKCS_PSS),
+ CK2SKS_ID(CKM_SHA224_RSA_PKCS),
+ CK2SKS_ID(CKM_SHA224_RSA_PKCS_PSS),
+ CK2SKS_ID(CKM_RSA_AES_KEY_WRAP),
+
+ CK2SKS_ID(CKM_DES_KEY_GEN),
+ CK2SKS_ID(CKM_DES_ECB),
+ CK2SKS_ID(CKM_DES_CBC),
+ CK2SKS_ID(CKM_DES_MAC),
+ CK2SKS_ID(CKM_DES_MAC_GENERAL),
+ CK2SKS_ID(CKM_DES_CBC_PAD),
+
+ CK2SKS_ID(CKM_MTK_HSM_AES_ECB),
+ CK2SKS_ID(CKM_MTK_HSM_AES_CBC),
+ CK2SKS_ID(CKM_MTK_HSM_AES_CTR),
+ CK2SKS_ID(CKM_MTK_HSM_AES_GCM),
+ CK2SKS_ID(CKM_MTK_HSM_AES_CMAC),
+ CK2SKS_ID(CKM_MTK_HSM_SHA256_HMAC),
+ CK2SKS_ID(CKM_MTK_HSM_SHA384_HMAC),
+ CK2SKS_ID(CKM_MTK_HSM_ECDSA),
+ CK2SKS_ID(CKM_MTK_HSM_ECDSA_SHA1),
+ CK2SKS_ID(CKM_MTK_HSM_ECDSA_SHA224),
+ CK2SKS_ID(CKM_MTK_HSM_ECDSA_SHA256),
+ CK2SKS_ID(CKM_MTK_HSM_ECDSA_SHA384),
+ CK2SKS_ID(CKM_MTK_HSM_ECDSA_SHA512),
+ CK2SKS_ID(CKM_MTK_HSM_SHA1),
+ CK2SKS_ID(CKM_MTK_HSM_SHA224),
+ CK2SKS_ID(CKM_MTK_HSM_SHA256),
+ CK2SKS_ID(CKM_MTK_HSM_SHA384),
+ CK2SKS_ID(CKM_MTK_HSM_SHA512),
+ CK2SKS_ID(CKM_MTK_HSM_AES_KEY_GEN),
+ CK2SKS_ID(CKM_MTK_HSM_EC_KEY_PAIR_GEN),
+ CK2SKS_ID(CKM_MTK_HSM_EC_KEY_PAIR_IMPORT),
+ CK2SKS_ID(CKM_MTK_HSM_DUMP_LOG),
+
+ CK2SKS_ID_BRACE(CK_VENDOR_INVALID_ID, SKS_UNDEFINED_ID),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(mechanism_type, CK_MECHANISM_TYPE)
+
+static const struct ck2sks mechanism_flag[] = {
+ CK2SKS_ID_BRACE(CKF_HW, SKS_CKFM_HW),
+ CK2SKS_ID_BRACE(CKF_ENCRYPT, SKS_CKFM_ENCRYPT),
+ CK2SKS_ID_BRACE(CKF_DECRYPT, SKS_CKFM_DECRYPT),
+ CK2SKS_ID_BRACE(CKF_DIGEST, SKS_CKFM_DIGEST),
+ CK2SKS_ID_BRACE(CKF_SIGN, SKS_CKFM_SIGN),
+ CK2SKS_ID_BRACE(CKF_SIGN_RECOVER, SKS_CKFM_SIGN_RECOVER),
+ CK2SKS_ID_BRACE(CKF_VERIFY, SKS_CKFM_VERIFY),
+ CK2SKS_ID_BRACE(CKF_VERIFY_RECOVER, SKS_CKFM_VERIFY_RECOVER),
+ CK2SKS_ID_BRACE(CKF_GENERATE, SKS_CKFM_GENERATE),
+ CK2SKS_ID_BRACE(CKF_GENERATE_KEY_PAIR, SKS_CKFM_GENERATE_PAIR),
+ CK2SKS_ID_BRACE(CKF_WRAP, SKS_CKFM_WRAP),
+ CK2SKS_ID_BRACE(CKF_UNWRAP, SKS_CKFM_UNWRAP),
+ CK2SKS_ID_BRACE(CKF_DERIVE, SKS_CKFM_DERIVE),
+ CK2SKS_ID_BRACE(CKF_EC_F_P, SKS_CKFM_EC_F_P),
+ CK2SKS_ID_BRACE(CKF_EC_F_2M, SKS_CKFM_EC_F_2M),
+ CK2SKS_ID_BRACE(CKF_EC_ECPARAMETERS, SKS_CKFM_EC_ECPARAMETERS),
+ CK2SKS_ID_BRACE(CKF_EC_NAMEDCURVE, SKS_CKFM_EC_NAMEDCURVE),
+ CK2SKS_ID_BRACE(CKF_EC_UNCOMPRESS, SKS_CKFM_EC_UNCOMPRESS),
+ CK2SKS_ID_BRACE(CKF_EC_COMPRESS, SKS_CKFM_EC_COMPRESS),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(mechanism_flag, CK_FLAGS)
+
+static const struct ck2sks object_class[] = {
+ CK2SKS_ID(CKO_SECRET_KEY),
+ CK2SKS_ID(CKO_PUBLIC_KEY),
+ CK2SKS_ID(CKO_PRIVATE_KEY),
+ CK2SKS_ID(CKO_OTP_KEY),
+ CK2SKS_ID(CKO_CERTIFICATE),
+ CK2SKS_ID(CKO_DATA),
+ CK2SKS_ID(CKO_DOMAIN_PARAMETERS),
+ CK2SKS_ID(CKO_HW_FEATURE),
+ CK2SKS_ID(CKO_MECHANISM),
+ CK2SKS_ID_BRACE(CK_VENDOR_INVALID_ID, SKS_UNDEFINED_ID),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(object_class, CK_OBJECT_CLASS)
+
+static const struct ck2sks key_type[] = {
+ CK2SKS_ID(CKK_AES),
+ CK2SKS_ID(CKK_GENERIC_SECRET),
+ CK2SKS_ID(CKK_MD5_HMAC),
+ CK2SKS_ID(CKK_SHA_1_HMAC),
+ CK2SKS_ID(CKK_SHA224_HMAC),
+ CK2SKS_ID(CKK_SHA256_HMAC),
+ CK2SKS_ID(CKK_SHA384_HMAC),
+ CK2SKS_ID(CKK_SHA512_HMAC),
+ CK2SKS_ID(CKK_RSA),
+ CK2SKS_ID(CKK_EC),
+ CK2SKS_ID(CKK_DSA),
+ CK2SKS_ID(CKK_DH),
+ CK2SKS_ID(CKK_DES),
+ CK2SKS_ID(CKK_DES2),
+ CK2SKS_ID(CKK_DES3),
+ CK2SKS_ID_BRACE(CK_VENDOR_INVALID_ID, SKS_UNDEFINED_ID),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(key_type, CK_KEY_TYPE)
+
+static const struct ck2sks certificate_type[] = {
+ CK2SKS_ID(CKC_X_509),
+ CK2SKS_ID(CKC_X_509_ATTR_CER),
+ CK2SKS_ID(CKC_WTLS),
+ CK2SKS_ID_BRACE(CK_VENDOR_INVALID_ID, SKS_UNDEFINED_ID),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(certificate_type, CK_CERTIFICATE_TYPE)
+
+static const struct ck2sks ec_kdf_type[] = {
+ CK2SKS_ID(CKD_NULL),
+ CK2SKS_ID(CKD_SHA1_KDF),
+ CK2SKS_ID(CKD_SHA1_KDF_ASN1),
+ CK2SKS_ID(CKD_SHA1_KDF_CONCATENATE),
+ CK2SKS_ID(CKD_SHA224_KDF),
+ CK2SKS_ID(CKD_SHA256_KDF),
+ CK2SKS_ID(CKD_SHA384_KDF),
+ CK2SKS_ID(CKD_SHA512_KDF),
+ CK2SKS_ID(CKD_CPDIVERSIFY_KDF),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(ec_kdf_type, CK_EC_KDF_TYPE)
+
+static const struct ck2sks rsa_pkcs_mgf_type[] = {
+ CK2SKS_ID(CKG_MGF1_SHA1),
+ CK2SKS_ID(CKG_MGF1_SHA224),
+ CK2SKS_ID(CKG_MGF1_SHA256),
+ CK2SKS_ID(CKG_MGF1_SHA384),
+ CK2SKS_ID(CKG_MGF1_SHA512),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(rsa_pkcs_mgf_type, CK_RSA_PKCS_MGF_TYPE)
+
+static const struct ck2sks rsa_pkcs_oaep_source_type[] = {
+ CK2SKS_ID(CKZ_DATA_SPECIFIED),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(rsa_pkcs_oaep_source_type, CK_RSA_PKCS_OAEP_SOURCE_TYPE)
+
+static const struct ck2sks user_type[] = {
+ CK2SKS_ID(CKU_SO),
+ CK2SKS_ID(CKU_USER),
+ CK2SKS_ID(CKU_CONTEXT_SPECIFIC),
+};
+
+DEFINE_CK2SKS_FUNCTIONS(user_type, CK_USER_TYPE)
+
+static const struct ck2sks error_code[] = {
+ CK2SKS_ID(CKR_OK),
+ CK2SKS_ID(CKR_GENERAL_ERROR),
+ CK2SKS_ID(CKR_DEVICE_MEMORY),
+ CK2SKS_ID(CKR_ARGUMENTS_BAD),
+ CK2SKS_ID(CKR_BUFFER_TOO_SMALL),
+ CK2SKS_ID(CKR_FUNCTION_FAILED),
+ CK2SKS_ID(CKR_ATTRIBUTE_TYPE_INVALID),
+ CK2SKS_ID(CKR_ATTRIBUTE_VALUE_INVALID),
+ CK2SKS_ID(CKR_OBJECT_HANDLE_INVALID),
+ CK2SKS_ID(CKR_KEY_HANDLE_INVALID),
+ CK2SKS_ID(CKR_MECHANISM_INVALID),
+ CK2SKS_ID(CKR_SLOT_ID_INVALID),
+ CK2SKS_ID(CKR_SESSION_HANDLE_INVALID),
+ CK2SKS_ID(CKR_PIN_INCORRECT),
+ CK2SKS_ID(CKR_PIN_LOCKED),
+ CK2SKS_ID(CKR_PIN_EXPIRED),
+ CK2SKS_ID(CKR_PIN_INVALID),
+ CK2SKS_ID(CKR_OPERATION_ACTIVE),
+ CK2SKS_ID(CKR_KEY_FUNCTION_NOT_PERMITTED),
+ CK2SKS_ID(CKR_KEY_TYPE_INCONSISTENT),
+ CK2SKS_ID(CKR_OPERATION_NOT_INITIALIZED),
+ CK2SKS_ID(CKR_SESSION_READ_ONLY),
+ CK2SKS_ID(CKR_MECHANISM_PARAM_INVALID),
+ CK2SKS_ID(CKR_TOKEN_WRITE_PROTECTED),
+ CK2SKS_ID(CKR_TOKEN_NOT_PRESENT),
+ CK2SKS_ID(CKR_TOKEN_NOT_RECOGNIZED),
+ CK2SKS_ID(CKR_ACTION_PROHIBITED),
+ CK2SKS_ID(CKR_ATTRIBUTE_READ_ONLY),
+ CK2SKS_ID(CKR_PIN_TOO_WEAK),
+ CK2SKS_ID(CKR_CURVE_NOT_SUPPORTED),
+ CK2SKS_ID(CKR_DOMAIN_PARAMS_INVALID),
+ CK2SKS_ID(CKR_USER_ALREADY_LOGGED_IN),
+ CK2SKS_ID(CKR_USER_ANOTHER_ALREADY_LOGGED_IN),
+ CK2SKS_ID(CKR_USER_NOT_LOGGED_IN),
+ CK2SKS_ID(CKR_USER_PIN_NOT_INITIALIZED),
+ CK2SKS_ID(CKR_USER_TOO_MANY_TYPES),
+ CK2SKS_ID(CKR_USER_TYPE_INVALID),
+ CK2SKS_ID(CKR_SESSION_READ_ONLY_EXISTS),
+ CK2SKS_ID(CKR_SESSION_READ_WRITE_SO_EXISTS),
+ CK2SKS_ID(CKR_SESSION_EXISTS),
+ CK2SKS_ID(CKR_TEMPLATE_INCOMPLETE),
+ CK2SKS_ID(CKR_TEMPLATE_INCONSISTENT),
+ CK2SKS_ID(CKR_SIGNATURE_INVALID),
+ CK2SKS_ID(CKR_ATTRIBUTE_SENSITIVE),
+ CK2SKS_ID(CKR_SIGNATURE_LEN_RANGE),
+ CK2SKS_ID(CKR_DATA_LEN_RANGE),
+ CK2SKS_ID(CKR_ENCRYPTED_DATA_LEN_RANGE),
+ CK2SKS_ID_BRACE(CK_VENDOR_INVALID_ID, SKS_UNDEFINED_ID),
+};
+
+CK_RV sks2ck_rv(uint32_t sks)
+{
+ CK_ULONG rv;
+
+ if (SKS2CK(&rv, sks, error_code))
+ return CKR_GENERAL_ERROR;
+
+ return (CK_RV)rv;
+}
+
+CK_RV teec2ck_rv(TEEC_Result res)
+{
+ switch (res) {
+ case TEEC_SUCCESS:
+ return CKR_OK;
+ case TEEC_ERROR_OUT_OF_MEMORY:
+ return CKR_DEVICE_MEMORY;
+ case TEEC_ERROR_BAD_PARAMETERS:
+ return CKR_ARGUMENTS_BAD;
+ case TEEC_ERROR_SHORT_BUFFER:
+ return CKR_BUFFER_TOO_SMALL;
+ default:
+ return CKR_FUNCTION_FAILED;
+ }
+}
+/* Convert a array of mechanism type from sks into CK_MECHANIMS_TYPE */
+CK_RV sks2ck_mechanism_type_list(CK_MECHANISM_TYPE *dst,
+ void *src, size_t count)
+{
+ CK_MECHANISM_TYPE *ck = dst;
+ char *sks = src;
+ size_t n;
+ uint32_t proc;
+
+ for (n = 0; n < count; n++, sks += sizeof(uint32_t), ck++) {
+ memcpy(&proc, sks, sizeof(proc));
+ if (sks2ck_mechanism_type(ck, proc))
+ return CKR_MECHANISM_INVALID;
+ }
+
+ return CKR_OK;
+}
+
+/* Convert structure CK_MECHANIMS_INFO from sks to ck (3 ulong fields) */
+CK_RV sks2ck_mechanism_info(CK_MECHANISM_INFO *info, void *src)
+{
+ struct sks_mechanism_info sks;
+ CK_FLAGS ck_flag;
+ uint32_t mask;
+ CK_RV rv;
+
+ memcpy(&sks, src, sizeof(sks));
+
+ info->ulMinKeySize = sks.min_key_size;
+ info->ulMaxKeySize = sks.max_key_size;
+
+ info->flags = 0;
+ for (mask = 1; mask; mask <<= 1) {
+ if (!(sks.flags & mask))
+ continue;
+
+ rv = sks2ck_mechanism_flag(&ck_flag, mask);
+ if (rv)
+ return rv;
+
+ info->flags |= ck_flag;
+ }
+
+ return CKR_OK;
+}
+
+/*
+ * Helper functions to analyse CK fields
+ */
+size_t ck_attr_is_class(uint32_t id)
+{
+ if (id == CKA_CLASS)
+ return sizeof(CK_ULONG);
+ else
+ return 0;
+}
+
+size_t ck_attr_is_type(uint32_t id)
+{
+ switch (id) {
+ case CKA_CERTIFICATE_TYPE:
+ case CKA_KEY_TYPE:
+ case CKA_HW_FEATURE_TYPE:
+ case CKA_MECHANISM_TYPE:
+ case CKA_KEY_GEN_MECHANISM:
+ return sizeof(CK_ULONG);
+ default:
+ return 0;
+ }
+}
+int sks_object_has_boolprop(uint32_t class)
+{
+ switch (class) {
+ case SKS_CKO_DATA:
+ case SKS_CKO_CERTIFICATE:
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_DOMAIN_PARAMETERS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+int sks_class_has_type(uint32_t class)
+{
+ switch (class) {
+ case SKS_CKO_CERTIFICATE:
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_MECHANISM:
+ case SKS_CKO_HW_FEATURE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+uint32_t ck2sks_type_in_class(CK_ULONG ck, CK_ULONG class)
+{
+ switch (class) {
+ case CKO_DATA:
+ return 0;
+ case CKO_SECRET_KEY:
+ case CKO_PUBLIC_KEY:
+ case CKO_PRIVATE_KEY:
+ case CKO_OTP_KEY:
+ return ck2sks_key_type(ck);
+ case CKO_MECHANISM:
+ return ck2sks_mechanism_type(ck);
+ case CKO_CERTIFICATE:
+ return ck2sks_certificate_type(ck);
+ default:
+ return SKS_UNDEFINED_ID;
+ }
+}
+
+CK_RV sks2ck_type_in_class(CK_ULONG *ck, uint32_t sks, CK_ULONG class)
+{
+ switch (class) {
+ case SKS_CKO_DATA:
+ return CKR_NO_EVENT;
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ case SKS_CKO_OTP_KEY:
+ return sks2ck_key_type(ck, sks);
+ case SKS_CKO_MECHANISM:
+ return sks2ck_mechanism_type(ck, sks);
+ case SKS_CKO_CERTIFICATE:
+ return sks2ck_certificate_type(ck, sks);
+ default:
+ return CKR_GENERAL_ERROR;
+ }
+}
+
+CK_RV ck_add_object_class(CK_ATTRIBUTE_PTR attrs, CK_ULONG_PTR count,
+ CK_ATTRIBUTE_PTR *attrs_new_p,CK_OBJECT_CLASS cka_class)
+{
+ size_t n;
+ CK_ULONG count_new = *count;
+ CK_ATTRIBUTE_PTR attrs_new = NULL;
+ CK_OBJECT_CLASS_PTR object_class_p = NULL;
+ int object_class_present = 0;
+ CK_RV rv;
+
+ for (n = 0; n < *count; n++) {
+ if (attrs[n].type == CKA_CLASS) {
+ object_class_present = 1;
+ break;
+ }
+ }
+ if (!object_class_present)
+ count_new++;
+
+ attrs_new = malloc(count_new * sizeof(CK_ATTRIBUTE));
+ if (attrs_new == NULL)
+ return CKR_HOST_MEMORY;
+
+ memcpy(attrs_new, attrs, (*count) * sizeof(CK_ATTRIBUTE));
+
+ if (object_class_present) {
+ rv = CKR_OK;
+ goto bail;
+ }
+
+ object_class_p = malloc(sizeof(CK_OBJECT_CLASS));
+ if (object_class_p == NULL) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ *object_class_p = cka_class;
+ attrs_new[count_new - 1].type = CKA_CLASS;
+ attrs_new[count_new - 1].pValue = object_class_p;
+ attrs_new[count_new - 1].ulValueLen = sizeof(CK_OBJECT_CLASS);
+ rv = CKR_OK;
+
+bail:
+ if (rv == CKR_OK) {
+ if(*attrs_new_p == attrs)
+ free(attrs);
+ *attrs_new_p = attrs_new;
+ *count = count_new;
+ } else {
+ if (attrs_new)
+ free(attrs_new);
+ if (object_class_p)
+ free(object_class_p);
+ }
+
+ return rv;
+}
+
+CK_RV ck_guess_key_type(CK_MECHANISM_PTR mecha,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG_PTR count,
+ CK_ATTRIBUTE_PTR *attrs_new_p)
+{
+ size_t n;
+ CK_ULONG count_new = *count;
+ CK_ATTRIBUTE_PTR attrs_new = NULL;
+ CK_KEY_TYPE_PTR key_type_p = NULL;
+ int key_type_present = 0;
+ CK_RV rv;
+
+ for (n = 0; n < *count; n++) {
+ if (attrs[n].type == CKA_KEY_TYPE) {
+ key_type_present = 1;
+ break;
+ }
+ }
+ if (!key_type_present)
+ count_new++;
+
+ attrs_new = malloc(count_new * sizeof(CK_ATTRIBUTE));
+ if (attrs_new == NULL)
+ return CKR_HOST_MEMORY;
+
+ memcpy(attrs_new, attrs, (*count) * sizeof(CK_ATTRIBUTE));
+
+ if (key_type_present) {
+ rv = CKR_OK;
+ goto bail;
+ }
+
+ key_type_p = malloc(sizeof(CK_KEY_TYPE));
+ if (key_type_p == NULL) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ switch (mecha->mechanism) {
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ *key_type_p = CKK_RSA;
+ attrs_new[count_new - 1].type = CKA_KEY_TYPE;
+ attrs_new[count_new - 1].pValue = key_type_p;
+ attrs_new[count_new - 1].ulValueLen = sizeof(CK_KEY_TYPE);
+ rv = CKR_OK;
+ break;
+ case CKM_EC_KEY_PAIR_GEN:
+ case CKM_MTK_HSM_EC_KEY_PAIR_GEN:
+ case CKM_MTK_HSM_EC_KEY_PAIR_IMPORT:
+ *key_type_p = CKK_EC;
+ attrs_new[count_new - 1].type = CKA_KEY_TYPE;
+ attrs_new[count_new - 1].pValue = key_type_p;
+ attrs_new[count_new - 1].ulValueLen = sizeof(CK_KEY_TYPE);
+ rv = CKR_OK;
+ break;
+ default:
+ rv = CKR_TEMPLATE_INCOMPLETE;
+ break;
+ }
+
+bail:
+ if (rv == CKR_OK) {
+ *attrs_new_p = attrs_new;
+ *count = count_new;
+ } else {
+ if (attrs_new)
+ free(attrs_new);
+ if (key_type_p)
+ free(key_type_p);
+ }
+
+ return rv;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_helpers.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_helpers.h
new file mode 100644
index 0000000..1695c3c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/ck_helpers.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __HELPERS_CK_H
+#define __HELPERS_CK_H
+
+#include <pkcs11.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <sks_ta.h>
+#include <tee_client_api.h>
+
+/*
+ * SKS reserves vendor ID 0xffffffff to represent an invalid ID
+ * (attribute class, type, ...)
+ */
+#define CK_VENDOR_INVALID_ID 0xffffffffUL
+#define SKS_CK_VENDOR_INVALID_ID 0xffffffffUL
+
+/* Helper for sks2ck_xxx() and ck2sks_xxx() helper declaration */
+#define DECLARE_CK2SKS_FUNCTIONS(_label, _ck_typeof) \
+ uint32_t ck2sks_ ## _label(_ck_typeof ck); \
+ CK_RV sks2ck_ ## _label(_ck_typeof *ck, uint32_t sks)
+
+DECLARE_CK2SKS_FUNCTIONS(slot_flag, CK_FLAGS);
+DECLARE_CK2SKS_FUNCTIONS(token_flag, CK_FLAGS);
+DECLARE_CK2SKS_FUNCTIONS(user_type, CK_USER_TYPE);
+DECLARE_CK2SKS_FUNCTIONS(attribute_type, CK_ATTRIBUTE_TYPE);
+DECLARE_CK2SKS_FUNCTIONS(mechanism_type, CK_MECHANISM_TYPE);
+DECLARE_CK2SKS_FUNCTIONS(mechanism_flag, CK_FLAGS);
+DECLARE_CK2SKS_FUNCTIONS(object_class, CK_OBJECT_CLASS);
+DECLARE_CK2SKS_FUNCTIONS(key_type, CK_KEY_TYPE);
+DECLARE_CK2SKS_FUNCTIONS(ec_kdf_type, CK_EC_KDF_TYPE);
+DECLARE_CK2SKS_FUNCTIONS(rsa_pkcs_mgf_type, CK_RSA_PKCS_MGF_TYPE);
+DECLARE_CK2SKS_FUNCTIONS(rsa_pkcs_oaep_source_type,
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE);
+DECLARE_CK2SKS_FUNCTIONS(certificate_type, CK_CERTIFICATE_TYPE);
+
+/*
+ * Convert structure struct sks_token_info retreived from TA into a
+ * cryptoki API compliant CK_TOKEN_INFO structure.
+ *
+ * struct sks_token_info is defined in the SKS TA API.
+ */
+CK_RV sks2ck_token_info(CK_TOKEN_INFO_PTR ck_info,
+ struct sks_token_info *sks_info);
+CK_RV sks2ck_slot_info(CK_SLOT_INFO_PTR ck_info,
+ struct sks_slot_info *sks_info);
+CK_RV sks2ck_session_info(CK_SESSION_INFO_PTR ck_info,
+ struct sks_session_info *sks_info);
+
+/* Backward compat on deprecated functions */
+static inline CK_RV sks2ck_attribute_id(CK_ATTRIBUTE_TYPE *ck, uint32_t sks)
+{
+ return sks2ck_attribute_type(ck, sks);
+}
+
+static inline uint32_t ck2sks_attribute_id(CK_ATTRIBUTE_TYPE ck)
+{
+ return ck2sks_attribute_type(ck);
+}
+
+static inline CK_RV sks2ck_class(CK_OBJECT_CLASS *ck, uint32_t sks)
+{
+ return sks2ck_object_class(ck, sks);
+}
+
+static inline uint32_t ck2sks_class(CK_OBJECT_CLASS ck)
+{
+ return ck2sks_object_class(ck);
+}
+
+CK_RV sks2ck_mechanism_type_list(CK_MECHANISM_TYPE *dst, void *sks,
+ size_t count);
+CK_RV sks2ck_mechanism_info(CK_MECHANISM_INFO *info, void *sks);
+
+uint32_t ck2sks_type_in_class(CK_ULONG ck, CK_ULONG class);
+CK_RV sks2ck_type_in_class(CK_ULONG *ck, uint32_t sks, CK_ULONG class);
+
+int sks_attr2boolprop_shift(CK_ULONG attr);
+
+CK_RV sks2ck_rv(uint32_t sks);
+CK_RV teec2ck_rv(TEEC_Result res);
+
+/*
+ * Helper functions to analyse CK fields
+ */
+size_t ck_attr_is_class(uint32_t attribute_id);
+size_t ck_attr_is_type(uint32_t attribute_id);
+int ck_attr2boolprop_shift(CK_ULONG attr);
+
+int sks_object_has_boolprop(uint32_t class);
+int sks_class_has_type(uint32_t class);
+
+/*
+ * Try to guess key type if mechanism is key generation
+ *
+ * @mech: Referecn to mechanism
+ * @attrs; Reference to input object attributes
+ * @count: number of attributes for the object, output value may be incremented
+ * @attrs_new_p: Referenece to output attributes, always defines the key type
+ *
+ * This may be needed because some tools (e.g.: pkcs11-tool) may not specify
+ * some attributes as key type when these can be assumed from the mechanism
+ * type.
+ *
+ * The function allocates memory for a copy of the attributes since it could
+ * be increased when adding the missing attribute. Caller is responsible from
+ * freeing the output attribute references.
+ */
+CK_RV ck_guess_key_type(CK_MECHANISM_PTR mecha,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG_PTR count,
+ CK_ATTRIBUTE_PTR *attrs_new_p);
+
+CK_RV ck_add_object_class(CK_ATTRIBUTE_PTR attrs, CK_ULONG_PTR count,
+ CK_ATTRIBUTE_PTR *attrs_new_p,CK_OBJECT_CLASS cka_class);
+
+#endif /*__HELPERS_CK_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/invoke_ta.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/invoke_ta.c
new file mode 100644
index 0000000..9bace12
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/invoke_ta.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <pkcs11.h>
+#include <sks_ta.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ck_helpers.h"
+#include "invoke_ta.h"
+#include "local_utils.h"
+
+/*
+ * All requests (invocation of the SKS) currently go through a
+ * single GPD TEE session toward the SKS TA.
+ */
+struct sks_primary_context {
+ TEEC_Context context;
+ TEEC_Session session;
+};
+
+static struct sks_primary_context primary_ctx;
+static struct sks_invoke primary_invoke;
+
+static int open_primary_context(void)
+{
+ TEEC_UUID uuid = TA_SKS_UUID;
+ uint32_t origin;
+ TEEC_Result res;
+
+ /* TODO: mutex */
+ if (primary_invoke.session)
+ return 0;
+
+ res = TEEC_InitializeContext(NULL, &primary_ctx.context);
+ if (res != TEEC_SUCCESS) {
+ LOG_ERROR("TEEC init context failed\n");
+ return -1;
+ }
+
+ /* TODO: application could provide a knwon login ID */
+ res = TEEC_OpenSession(&primary_ctx.context, &primary_ctx.session,
+ &uuid, TEEC_LOGIN_PUBLIC, NULL, NULL, &origin);
+ if (res != TEEC_SUCCESS) {
+ LOG_ERROR("TEEC open session failed %x from %d\n", res, origin);
+ TEEC_FinalizeContext(&primary_ctx.context);
+ return -1;
+ }
+
+ primary_invoke.context = &primary_ctx.context;
+ primary_invoke.session = &primary_ctx.session;
+
+ return 0;
+}
+
+static void close_primary_context(void)
+{
+ /* TODO: mutex */
+ if (!primary_invoke.session)
+ return;
+
+ TEEC_CloseSession(&primary_ctx.session);
+ TEEC_FinalizeContext(&primary_ctx.context);
+ primary_invoke.context = NULL;
+ primary_invoke.session = NULL;
+}
+
+static struct sks_invoke *get_invoke_context(struct sks_invoke *sks_ctx)
+{
+ struct sks_invoke *ctx = sks_ctx;
+
+ if (open_primary_context())
+ return NULL;
+
+ if (!ctx)
+ return &primary_invoke;
+
+ if (!ctx->context)
+ ctx->context = primary_invoke.context;
+ if (!ctx->session)
+ ctx->session = primary_invoke.session;
+
+ return ctx;
+}
+
+static TEEC_Context *teec_ctx(struct sks_invoke *sks_ctx)
+{
+ return (TEEC_Context *)sks_ctx->context;
+}
+
+static TEEC_Session *teec_sess(struct sks_invoke *sks_ctx)
+{
+ return (TEEC_Session *)sks_ctx->session;
+}
+
+TEEC_SharedMemory *sks_alloc_shm(struct sks_invoke *sks_ctx,
+ size_t size, int in, int out)
+{
+ struct sks_invoke *ctx = get_invoke_context(sks_ctx);
+ TEEC_SharedMemory *shm;
+
+ if (!ctx || (!in && !out))
+ return NULL;
+
+ shm = calloc(1, sizeof(TEEC_SharedMemory));
+ if (!shm)
+ return NULL;
+
+ shm->size = size;
+
+ if (in)
+ shm->flags |= TEEC_MEM_INPUT;
+ if (out)
+ shm->flags |= TEEC_MEM_OUTPUT;
+
+ if (TEEC_AllocateSharedMemory(teec_ctx(ctx), shm)) {
+ free(shm);
+ return NULL;
+ }
+
+ return shm;
+}
+
+TEEC_SharedMemory *sks_register_shm(struct sks_invoke *sks_ctx,
+ void *buf, size_t size, int in, int out)
+{
+ struct sks_invoke *ctx = get_invoke_context(sks_ctx);
+ TEEC_SharedMemory *shm;
+
+ if (!ctx || (!in && !out))
+ return NULL;
+
+ shm = calloc(1, sizeof(TEEC_SharedMemory));
+ if (!shm)
+ return NULL;
+
+ shm->buffer = buf;
+ shm->size = size;
+
+ if (in)
+ shm->flags |= TEEC_MEM_INPUT;
+ if (out)
+ shm->flags |= TEEC_MEM_OUTPUT;
+
+ if (TEEC_RegisterSharedMemory(teec_ctx(ctx), shm)) {
+ free(shm);
+ return NULL;
+ }
+
+ return shm;
+}
+
+void sks_free_shm(TEEC_SharedMemory *shm)
+{
+ TEEC_ReleaseSharedMemory(shm);
+ free(shm);
+}
+
+#define DIR_IN 1
+#define DIR_OUT 0
+#define DIR_NONE -1
+
+static CK_RV invoke_ta(struct sks_invoke *sks_ctx, unsigned long cmd,
+ void *ctrl, size_t ctrl_sz,
+ void *io1, size_t *io1_sz, int io1_dir,
+ void *io2, size_t *io2_sz, int io2_dir)
+{
+ struct sks_invoke *ctx = get_invoke_context(sks_ctx);
+ uint32_t command = (uint32_t)cmd;
+ TEEC_Operation op;
+ uint32_t origin;
+ TEEC_Result res;
+ TEEC_SharedMemory *ctrl_shm = ctrl;
+ TEEC_SharedMemory *io1_shm = io1;
+ TEEC_SharedMemory *io2_shm = io2;
+ uint32_t sks_rc;
+
+ memset(&op, 0, sizeof(op));
+
+ /*
+ * Command control field: TEE invocation parameter #0
+ */
+ if (ctrl && ctrl_sz) {
+ op.params[0].tmpref.buffer = ctrl;
+ op.params[0].tmpref.size = ctrl_sz;
+ op.paramTypes |= TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT,
+ 0, 0, 0);
+ }
+ if (ctrl && !ctrl_sz) {
+ op.params[0].memref.parent = ctrl_shm;
+ op.paramTypes |= TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, 0, 0, 0);
+ }
+
+ /*
+ * IO data TEE invocation parameter #1
+ */
+ if (io1_sz && (io1_dir == DIR_OUT || (io1_dir == DIR_IN && *io1_sz))) {
+ op.params[1].tmpref.buffer = io1;
+ op.params[1].tmpref.size = *io1_sz;
+ op.paramTypes |= TEEC_PARAM_TYPES(0, io1_dir == DIR_IN ?
+ TEEC_MEMREF_TEMP_INPUT :
+ TEEC_MEMREF_TEMP_OUTPUT,
+ 0, 0);
+ }
+ if (io1_dir != DIR_NONE && !io1_sz && io1) {
+ op.params[1].memref.parent = io1_shm;
+ op.paramTypes |= TEEC_PARAM_TYPES(0, TEEC_MEMREF_WHOLE, 0, 0);
+ }
+
+ /*
+ * IO data TEE invocation parameter #2
+ */
+ if (io2_sz && (io2_dir == DIR_OUT || (io2_dir == DIR_IN && *io2_sz))) {
+ op.params[2].tmpref.buffer = io2;
+ op.params[2].tmpref.size = *io2_sz;
+ op.paramTypes |= TEEC_PARAM_TYPES(0, 0, io2_dir == DIR_IN ?
+ TEEC_MEMREF_TEMP_INPUT :
+ TEEC_MEMREF_TEMP_OUTPUT,
+ 0);
+ }
+ if (io2_dir != DIR_NONE && !io2_sz && io2) {
+ op.params[2].memref.parent = io2_shm;
+ op.paramTypes |= TEEC_PARAM_TYPES(0, 0, TEEC_MEMREF_WHOLE, 0);
+ }
+
+
+ /*
+ * Invoke the TEE and update output buffer size on exit.
+ * Too short buffers are treated as positive errors.
+ */
+ res = TEEC_InvokeCommand(teec_sess(ctx), command, &op, &origin);
+ if (res) {
+ if (res == TEEC_ERROR_SHORT_BUFFER) {
+ if (io1_dir == DIR_OUT && io1_sz)
+ *io1_sz = op.params[1].tmpref.size;
+ if (io2_dir == DIR_OUT && io2_sz)
+ *io2_sz = op.params[2].tmpref.size;
+ }
+
+ return teec2ck_rv(res);
+ }
+
+ /* Get SKS return value from ctrl buffer, if none we expect success */
+ if (ctrl &&
+ ((ctrl_sz && op.params[0].tmpref.size == sizeof(uint32_t)) ||
+ (!ctrl_sz && op.params[0].memref.size == sizeof(uint32_t)))) {
+ memcpy(&sks_rc, ctrl, sizeof(uint32_t));
+ } else {
+ sks_rc = SKS_CKR_OK;
+ }
+
+ if (sks_rc == SKS_CKR_OK || sks_rc == SKS_CKR_BUFFER_TOO_SMALL) {
+ if (io1_dir == DIR_OUT && io1_sz)
+ *io1_sz = op.params[1].tmpref.size;
+ if (io2_dir == DIR_OUT && io2_sz)
+ *io2_sz = op.params[2].tmpref.size;
+ }
+
+ return sks2ck_rv(sks_rc);
+}
+
+CK_RV ck_invoke_ta(struct sks_invoke *sks_ctx,
+ unsigned long cmd,
+ void *ctrl, size_t ctrl_sz)
+{
+ return invoke_ta(sks_ctx, cmd, ctrl, ctrl_sz,
+ NULL, NULL, DIR_NONE,
+ NULL, NULL, DIR_NONE);
+}
+
+CK_RV ck_invoke_ta_in(struct sks_invoke *sks_ctx,
+ unsigned long cmd,
+ void *ctrl, size_t ctrl_sz,
+ void *in, size_t in_sz)
+{
+ return invoke_ta(sks_ctx, cmd, ctrl, ctrl_sz,
+ in, &in_sz, DIR_IN,
+ NULL, NULL, DIR_NONE);
+}
+
+
+CK_RV ck_invoke_ta_in_out(struct sks_invoke *sks_ctx,
+ unsigned long cmd,
+ void *ctrl, size_t ctrl_sz,
+ void *in, size_t in_sz,
+ void *out, size_t *out_sz)
+{
+ return invoke_ta(sks_ctx, cmd, ctrl, ctrl_sz,
+ in, &in_sz, DIR_IN,
+ out, out_sz, DIR_OUT);
+}
+
+CK_RV ck_invoke_ta_in_in(struct sks_invoke *sks_ctx,
+ unsigned long cmd,
+ void *ctrl, size_t ctrl_sz,
+ void *in, size_t in_sz,
+ void *in2, size_t in2_sz)
+{
+ return invoke_ta(sks_ctx, cmd, ctrl, ctrl_sz,
+ in, &in_sz, DIR_IN,
+ in2, &in2_sz, DIR_IN);
+}
+
+void sks_invoke_terminate(void)
+{
+ close_primary_context();
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/invoke_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/invoke_ta.h
new file mode 100644
index 0000000..42d5d88
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/invoke_ta.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __INVOKE_TA_H
+#define __INVOKE_TA_H
+
+#include <pkcs11.h>
+#include <tee_client_api.h>
+
+/*
+ * structure stored in CK session so it calls through the right
+ * GPD TEE session. TEEC type as abstract through void pointers
+ * to prevent CK messing with TEEC API.
+ *
+ * The structure must be reset to zero prior being used.
+ */
+struct sks_invoke {
+ void *context;
+ void *session;
+};
+
+/**
+ * alloc_shm - Allocate memory in the TEE SHM (in, out or in/out)
+ *
+ * @owner - Supplied TEE session or NULL
+ * @size - allocated size in byte
+ *
+ * Return a shm reference or NULL on failure.
+ *
+ * Allocate input SHM on behalf of supplied TEE context.
+ * If the supplied context is not initialized, init it through
+ * the primary TEE context.
+ * If there is no supplied context (ctx is NULL), allocate
+ * on behalf of the primary TEE session context.
+ */
+TEEC_SharedMemory *sks_alloc_shm(struct sks_invoke *ctx,
+ size_t size, int in, int out);
+
+static inline TEEC_SharedMemory *sks_alloc_shm_in(struct sks_invoke *ctx,
+ size_t size)
+{
+ return sks_alloc_shm(ctx, size, 1, 0);
+}
+static inline TEEC_SharedMemory *sks_alloc_shm_out(struct sks_invoke *ctx,
+ size_t size)
+{
+ return sks_alloc_shm(ctx, size, 0, 1);
+}
+static inline TEEC_SharedMemory *sks_alloc_shm_inout(struct sks_invoke *ctx,
+ size_t size)
+{
+ return sks_alloc_shm(ctx, size, 1, 1);
+}
+
+/**
+ * register_shm - Register buffer as TEE SHM memory (in, out or in/out)
+ *
+ * @owner - Supplied TEE session or NULL
+ * @buffer - pointer to the buffer to be registered
+ * @size - allocated size in byte
+ *
+ * Return a shm reference or NULL on failure.
+ *
+ * Allocate input SHM on behalf of supplied TEE context.
+ * If the supplied context is not initialized, init it through
+ * the primary TEE context.
+ * If there is no supplied context (ctx is NULL), allocate
+ * on behalf of the primary TEE session context.
+ */
+TEEC_SharedMemory *sks_register_shm(struct sks_invoke *ctx, void *buf,
+ size_t size, int in, int out);
+
+static inline TEEC_SharedMemory *sks_register_shm_in(struct sks_invoke *ctx,
+ void *buf, size_t size)
+{
+ return sks_register_shm(ctx, buf, size, 1, 0);
+}
+static inline TEEC_SharedMemory *sks_register_shm_out(struct sks_invoke *ctx,
+ void *buf, size_t size)
+{
+ return sks_register_shm(ctx, buf, size, 0, 1);
+}
+static inline TEEC_SharedMemory *sks_register_shm_inout(struct sks_invoke *ctx,
+ void *buf, size_t size)
+{
+ return sks_register_shm(ctx, buf, size, 1, 1);
+}
+
+/**
+ * free_shm - Release allocated or registered emory in the TEE SHM
+ *
+ * @shm - memory reference
+ */
+void sks_free_shm(TEEC_SharedMemory *shm);
+
+/**
+ * ck_invoke_ta*() - Invoke a SKS request to the TEE
+ * ck_invoke_ta_in() - Invoke a SKS request to the TEE
+ * ck_invoke_ta_in_out() - Invoke a SKS request to the TEE
+ * ck_invoke_ta_in_in() - Invoke a SKS request to the TEE
+ *
+ * @ctx - supplied TEE session context
+ * @cmd - SKS TA command ID
+ * @ctrl - command serialized input arguments. Shm, buffer or NULL pointer.
+ * @ctrl_sz - byte size of ctrl if ctrl is a buffer pointer
+ * @in - input to-be-processed data. Shm, buffer or NULL pointer.
+ * @in_sz - byte size of @in if @in is a buffer pointer
+ * @in_in - 1 if input, 0 if output, meaningless if @in is a Shm reference
+ * @out - output data. Shm, buffer or NULL pointer.
+ * @out_sz - byte size of @out if @out is a buffer pointer
+ * @out_in - 1 if input, 0 if output, meaningless if @out is a Shm reference
+ * @in2 - secondary input to-be-processed data. Shm, buffer or NULL pointer.
+ * @in2_sz - byte size of @in2 if @in2 is a buffer pointer
+ * @in2_in - 1 if input, 0 if output, meaningless if @in2 is a Shm reference
+ *
+ * Return a CK_RV return value.
+ *
+ * Allocate input SHM on behalf of supplied TEE context.
+ * If the supplied context is not initialized, init it through
+ * the primary TEE context.
+ * If there is no supplied context (ctx is NULL), allocate
+ * on behalf of the primary TEE session context.
+ *
+ * ctrl, in and out can be NULL pointer (no related data), buffer pointer
+ * (related data are stored in a memory buffer not registered as TEE SHM)
+ * or a SHM reference (related data are stored in a buffer registered as
+ * TEE SHM).
+ * ctrl_sz, in_sz and out_sz are null if the related reference is a SHM buffer
+ * and are not null if the related reference is a non SHM buffer. Note that
+ * out_sz is a pointer.
+ */
+
+CK_RV ck_invoke_ta(struct sks_invoke *sks_ctx,
+ unsigned long cmd,
+ void *ctrl, size_t ctrl_sz);
+
+CK_RV ck_invoke_ta_in(struct sks_invoke *sks_ctx,
+ unsigned long cmd,
+ void *ctrl, size_t ctrl_sz,
+ void *in, size_t in_sz);
+
+CK_RV ck_invoke_ta_in_out(struct sks_invoke *sks_ctx,
+ unsigned long cmd,
+ void *ctrl, size_t ctrl_sz,
+ void *in, size_t in_sz,
+ void *out, size_t *out_sz);
+
+CK_RV ck_invoke_ta_in_in(struct sks_invoke *sks_ctx,
+ unsigned long cmd,
+ void *ctrl, size_t ctrl_sz,
+ void *in, size_t in_sz,
+ void *in2, size_t in2_sz);
+
+/* sks_invoke_terminate - Release all allocated invocation resources */
+void sks_invoke_terminate(void);
+
+#endif /*__INVOKE_TA_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/local_utils.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/local_utils.h
new file mode 100644
index 0000000..2242959
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/local_utils.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#ifndef __LOCAL_UTILS_H
+#define __LOCAL_UTILS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LOG_ERROR(...) printf(__VA_ARGS__)
+#define LOG_INFO(...) printf(__VA_ARGS__)
+#define LOG_DEBUG(...) printf(__VA_ARGS__)
+
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
+
+#endif /*__LOCAL_UTILS_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_api.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_api.c
new file mode 100644
index 0000000..20e8008
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_api.c
@@ -0,0 +1,2346 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <assert.h>
+#include <pkcs11.h>
+#include <stdlib.h>
+
+#include "invoke_ta.h"
+#include "local_utils.h"
+#include "pkcs11_processing.h"
+#include "pkcs11_token.h"
+#include "ck_helpers.h"
+
+static int lib_inited;
+
+#define REGISTER_CK_FUNCTION(_function) ._function = _function
+#define DO_NOT_REGISTER_CK_FUNCTION(_function) ._function = NULL
+
+static const CK_FUNCTION_LIST libsks_function_list = {
+ .version = {
+ .major = 2,
+ .minor = 40,
+ },
+ REGISTER_CK_FUNCTION(C_Initialize),
+ REGISTER_CK_FUNCTION(C_Finalize),
+ REGISTER_CK_FUNCTION(C_GetInfo),
+ REGISTER_CK_FUNCTION(C_GetFunctionList),
+ REGISTER_CK_FUNCTION(C_GetSlotList),
+ REGISTER_CK_FUNCTION(C_GetSlotInfo),
+ REGISTER_CK_FUNCTION(C_GetTokenInfo),
+ REGISTER_CK_FUNCTION(C_GetMechanismList),
+ REGISTER_CK_FUNCTION(C_GetMechanismInfo),
+ REGISTER_CK_FUNCTION(C_InitToken),
+ REGISTER_CK_FUNCTION(C_InitPIN),
+ REGISTER_CK_FUNCTION(C_SetPIN),
+ REGISTER_CK_FUNCTION(C_OpenSession),
+ REGISTER_CK_FUNCTION(C_CloseSession),
+ REGISTER_CK_FUNCTION(C_CloseAllSessions),
+ REGISTER_CK_FUNCTION(C_GetSessionInfo),
+ REGISTER_CK_FUNCTION(C_GetOperationState),
+ REGISTER_CK_FUNCTION(C_SetOperationState),
+ REGISTER_CK_FUNCTION(C_Login),
+ REGISTER_CK_FUNCTION(C_Logout),
+ REGISTER_CK_FUNCTION(C_CreateObject),
+ REGISTER_CK_FUNCTION(C_CopyObject),
+ REGISTER_CK_FUNCTION(C_DestroyObject),
+ REGISTER_CK_FUNCTION(C_GetObjectSize),
+ REGISTER_CK_FUNCTION(C_GetAttributeValue),
+ REGISTER_CK_FUNCTION(C_SetAttributeValue),
+ REGISTER_CK_FUNCTION(C_FindObjectsInit),
+ REGISTER_CK_FUNCTION(C_FindObjects),
+ REGISTER_CK_FUNCTION(C_FindObjectsFinal),
+ REGISTER_CK_FUNCTION(C_EncryptInit),
+ REGISTER_CK_FUNCTION(C_Encrypt),
+ REGISTER_CK_FUNCTION(C_EncryptUpdate),
+ REGISTER_CK_FUNCTION(C_EncryptFinal),
+ REGISTER_CK_FUNCTION(C_DecryptInit),
+ REGISTER_CK_FUNCTION(C_Decrypt),
+ REGISTER_CK_FUNCTION(C_DecryptUpdate),
+ REGISTER_CK_FUNCTION(C_DecryptFinal),
+ REGISTER_CK_FUNCTION(C_DigestInit),
+ REGISTER_CK_FUNCTION(C_Digest),
+ REGISTER_CK_FUNCTION(C_DigestUpdate),
+ REGISTER_CK_FUNCTION(C_DigestKey),
+ REGISTER_CK_FUNCTION(C_DigestFinal),
+ REGISTER_CK_FUNCTION(C_SignInit),
+ REGISTER_CK_FUNCTION(C_Sign),
+ REGISTER_CK_FUNCTION(C_SignUpdate),
+ REGISTER_CK_FUNCTION(C_SignFinal),
+ REGISTER_CK_FUNCTION(C_SignRecoverInit),
+ REGISTER_CK_FUNCTION(C_SignRecover),
+ REGISTER_CK_FUNCTION(C_VerifyInit),
+ REGISTER_CK_FUNCTION(C_Verify),
+ REGISTER_CK_FUNCTION(C_VerifyUpdate),
+ REGISTER_CK_FUNCTION(C_VerifyFinal),
+ REGISTER_CK_FUNCTION(C_VerifyRecoverInit),
+ REGISTER_CK_FUNCTION(C_VerifyRecover),
+ REGISTER_CK_FUNCTION(C_DigestEncryptUpdate),
+ REGISTER_CK_FUNCTION(C_DecryptDigestUpdate),
+ REGISTER_CK_FUNCTION(C_SignEncryptUpdate),
+ REGISTER_CK_FUNCTION(C_DecryptVerifyUpdate),
+ REGISTER_CK_FUNCTION(C_GenerateKey),
+ REGISTER_CK_FUNCTION(C_GenerateKeyPair),
+ REGISTER_CK_FUNCTION(C_WrapKey),
+ REGISTER_CK_FUNCTION(C_UnwrapKey),
+ REGISTER_CK_FUNCTION(C_DeriveKey),
+ REGISTER_CK_FUNCTION(C_SeedRandom),
+ REGISTER_CK_FUNCTION(C_GenerateRandom),
+ REGISTER_CK_FUNCTION(C_GetFunctionStatus),
+ REGISTER_CK_FUNCTION(C_CancelFunction),
+ REGISTER_CK_FUNCTION(C_WaitForSlotEvent),
+};
+
+/*
+ * List of all PKCS#11 cryptoki API functions implemented
+ */
+
+CK_RV C_Initialize(CK_VOID_PTR init_args)
+{
+ (void)init_args;
+ CK_C_INITIALIZE_ARGS_PTR args = NULL;
+
+ if (init_args) {
+ args = (CK_C_INITIALIZE_ARGS_PTR)init_args;
+ /* Reserved must be set to NULL in this version of PKCS#11 */
+ if (args->reserved)
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if (lib_inited)
+ return CKR_CRYPTOKI_ALREADY_INITIALIZED;
+
+ lib_inited = 1;
+ return CKR_OK;
+}
+
+CK_RV C_Finalize(CK_VOID_PTR res)
+{
+ (void)res;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ /* Reserved must be set to NULL in this version of PKCS#11 */
+ if (res)
+ return CKR_ARGUMENTS_BAD;
+
+ sks_invoke_terminate();
+
+ lib_inited = 0;
+
+ return CKR_OK;
+}
+
+CK_RV C_GetInfo(CK_INFO_PTR info)
+{
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (!info)
+ return CKR_ARGUMENTS_BAD;
+
+ return sks_ck_get_info(info);
+}
+
+CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
+{
+ if (!ppFunctionList)
+ return CKR_ARGUMENTS_BAD;
+
+ /* Discard the const attribute when exporting the list address */
+ *ppFunctionList = (void *)&libsks_function_list;
+
+ return CKR_OK;
+}
+
+CK_RV C_GetSlotList(CK_BBOOL token_present,
+ CK_SLOT_ID_PTR slots,
+ CK_ULONG_PTR count)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_slot_get_list(token_present, slots, count);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetSlotInfo(CK_SLOT_ID slot,
+ CK_SLOT_INFO_PTR info)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_slot_get_info(slot, info);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_SLOT_ID_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_InitToken(CK_SLOT_ID slot,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len,
+ CK_UTF8CHAR_PTR label)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_init_token(slot, pin, pin_len, label);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_PIN_INCORRECT:
+ case CKR_PIN_LOCKED:
+ case CKR_SESSION_EXISTS:
+ case CKR_SLOT_ID_INVALID:
+ case CKR_TOKEN_NOT_PRESENT:
+ case CKR_TOKEN_NOT_RECOGNIZED:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetTokenInfo(CK_SLOT_ID slot,
+ CK_TOKEN_INFO_PTR info)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_token_get_info(slot, info);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_SLOT_ID_INVALID:
+ case CKR_TOKEN_NOT_PRESENT:
+ case CKR_TOKEN_NOT_RECOGNIZED:
+ case CKR_ARGUMENTS_BAD:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetMechanismList(CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE_PTR mechanisms,
+ CK_ULONG_PTR count)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_token_mechanism_ids(slot, mechanisms, count);
+
+ switch (rv) {
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_SLOT_ID_INVALID:
+ case CKR_TOKEN_NOT_PRESENT:
+ case CKR_TOKEN_NOT_RECOGNIZED:
+ case CKR_ARGUMENTS_BAD:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetMechanismInfo(CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR info)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_token_mechanism_info(slot, type, info);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_MECHANISM_INVALID:
+ case CKR_OK:
+ case CKR_SLOT_ID_INVALID:
+ case CKR_TOKEN_NOT_PRESENT:
+ case CKR_TOKEN_NOT_RECOGNIZED:
+ case CKR_ARGUMENTS_BAD:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_OpenSession(CK_SLOT_ID slot,
+ CK_FLAGS flags,
+ CK_VOID_PTR cookie,
+ CK_NOTIFY callback,
+ CK_SESSION_HANDLE_PTR session)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (flags & ~(CKF_RW_SESSION | CKF_SERIAL_SESSION))
+ return CKR_ARGUMENTS_BAD;
+
+ /* Specific mandated flag */
+ if (!(flags & CKF_SERIAL_SESSION))
+ return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+
+ rv = sks_ck_open_session(slot, flags, cookie, callback, session);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_SESSION_COUNT:
+ case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
+ case CKR_SESSION_READ_WRITE_SO_EXISTS:
+ case CKR_SLOT_ID_INVALID:
+ case CKR_TOKEN_NOT_PRESENT:
+ case CKR_TOKEN_NOT_RECOGNIZED:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_ARGUMENTS_BAD:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_CloseSession(CK_SESSION_HANDLE session)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_close_session(session);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_CloseAllSessions(CK_SLOT_ID slot)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_close_all_sessions(slot);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_SLOT_ID_INVALID:
+ case CKR_TOKEN_NOT_PRESENT:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetSessionInfo(CK_SESSION_HANDLE session,
+ CK_SESSION_INFO_PTR info)
+{
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return sks_ck_get_session_info(session, info);
+}
+
+CK_RV C_InitPIN(CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_init_pin(session, pin, pin_len);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_PIN_INVALID:
+ case CKR_PIN_LEN_RANGE:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_USER_NOT_LOGGED_IN:
+ case CKR_ARGUMENTS_BAD:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_SetPIN(CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR old,
+ CK_ULONG old_len,
+ CK_UTF8CHAR_PTR new,
+ CK_ULONG new_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_set_pin(session, old, old_len, new, new_len);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_MECHANISM_INVALID:
+ case CKR_OK:
+ case CKR_PIN_INCORRECT:
+ case CKR_PIN_INVALID:
+ case CKR_PIN_LEN_RANGE:
+ case CKR_PIN_LOCKED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_ARGUMENTS_BAD:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_Login(CK_SESSION_HANDLE session,
+ CK_USER_TYPE user_type,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len)
+
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_login(session, user_type, pin, pin_len);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_PIN_INCORRECT:
+ case CKR_PIN_LOCKED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY_EXISTS:
+ case CKR_USER_ALREADY_LOGGED_IN:
+ case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
+ case CKR_USER_PIN_NOT_INITIALIZED:
+ case CKR_USER_TOO_MANY_TYPES:
+ case CKR_USER_TYPE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_Logout(CK_SESSION_HANDLE session)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = sks_ck_logout(session);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetOperationState(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR state,
+ CK_ULONG_PTR state_len)
+{
+ (void)session;
+ (void)state;
+ (void)state_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_SetOperationState(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR state,
+ CK_ULONG state_len,
+ CK_OBJECT_HANDLE ciph_key,
+ CK_OBJECT_HANDLE auth_key)
+{
+ (void)session;
+ (void)state;
+ (void)state_len;
+ (void)ciph_key;
+ (void)auth_key;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_CreateObject(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR phObject)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_create_object(session, attribs, count, phObject);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_READ_ONLY:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_CURVE_NOT_SUPPORTED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_DOMAIN_PARAMS_INVALID:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_TEMPLATE_INCOMPLETE:
+ case CKR_TEMPLATE_INCONSISTENT:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_CopyObject(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_obj)
+{
+ (void)session;
+ (void)obj;
+ (void)attribs;
+ (void)count;
+ (void)new_obj;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_DestroyObject(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_destroy_object(session, obj);
+
+ switch (rv) {
+ case CKR_ACTION_PROHIBITED:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OBJECT_HANDLE_INVALID:
+ case CKR_OK:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetObjectSize(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ULONG_PTR out_size)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_get_object_size(session, obj, out_size);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_INFORMATION_SENSITIVE:
+ case CKR_OBJECT_HANDLE_INVALID:
+ case CKR_OK:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetAttributeValue(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_get_attribute_value(session, obj, attribs, count);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_SENSITIVE:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_OBJECT_HANDLE_INVALID:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_SetAttributeValue(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count)
+{
+ (void)session;
+ (void)obj;
+ (void)attribs;
+ (void)count;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_FindObjectsInit(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_find_objects_init(session, attribs, count);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_FindObjects(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE_PTR obj,
+ CK_ULONG max_count,
+ CK_ULONG_PTR count)
+
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_find_objects(session, obj, max_count, count);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE session)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_find_objects_final(session);
+
+ switch (rv) {
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_EncryptInit(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_encdecrypt_init(session, mechanism, key, CK_FALSE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_Encrypt(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_encdecrypt_oneshot(session, in, in_len, out, out_len, CK_FALSE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_EncryptUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_encdecrypt_update(session, in, in_len, out, out_len, CK_FALSE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_EncryptFinal(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_encdecrypt_final(session, out, out_len, CK_FALSE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_DecryptInit(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_encdecrypt_init(session, mechanism, key, CK_TRUE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_Decrypt(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_encdecrypt_oneshot(session, in, in_len, out, out_len, CK_TRUE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_ENCRYPTED_DATA_INVALID:
+ case CKR_ENCRYPTED_DATA_LEN_RANGE:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_DecryptUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_encdecrypt_update(session, in, in_len, out, out_len, CK_TRUE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_ENCRYPTED_DATA_INVALID:
+ case CKR_ENCRYPTED_DATA_LEN_RANGE:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_DecryptFinal(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_encdecrypt_final(session, out, out_len, CK_TRUE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_ENCRYPTED_DATA_INVALID:
+ case CKR_ENCRYPTED_DATA_LEN_RANGE:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+
+CK_RV C_DigestInit(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_digest_init(session, mechanism);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_Digest(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_digest_oneshot(session, in, in_len, out, out_len);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_DigestUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_digest_update(session, in, in_len);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_DigestKey(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE key)
+{
+ (void)session;
+ (void)key;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_DigestFinal(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR digest,
+ CK_ULONG_PTR len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_digest_final(session, digest, len);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_SignInit(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_signverify_init(session, mechanism, key, CK_TRUE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_Sign(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_signverify_oneshot(session, in, in_len, out, out_len, CK_TRUE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_INVALID:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ case CKR_FUNCTION_REJECTED:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_SignUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_signverify_update(session, in, in_len, CK_TRUE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_SignFinal(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_signverify_final(session, out, out_len, CK_TRUE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_BUFFER_TOO_SMALL:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ case CKR_FUNCTION_REJECTED:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_SignRecoverInit(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ (void)session;
+ (void)mechanism;
+ (void)key;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_SignRecover(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ (void)session;
+ (void)in;
+ (void)in_len;
+ (void)out;
+ (void)out_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_VerifyInit(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ CK_RV rv;
+
+ rv = ck_signverify_init(session, mechanism, key, CK_FALSE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_Verify(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG out_len)
+{
+ CK_RV rv;
+ CK_ULONG out_size = out_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_signverify_oneshot(session, in, in_len, out, &out_size,
+ CK_FALSE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_INVALID:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SIGNATURE_INVALID:
+ case CKR_SIGNATURE_LEN_RANGE:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_VerifyUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_signverify_update(session, in, in_len, CK_FALSE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_VerifyFinal(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR sign,
+ CK_ULONG sign_len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_signverify_final(session, sign, &sign_len, CK_FALSE);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_DATA_LEN_RANGE:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_OPERATION_NOT_INITIALIZED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SIGNATURE_INVALID:
+ case CKR_SIGNATURE_LEN_RANGE:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ (void)session;
+ (void)mechanism;
+ (void)key;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_VerifyRecover(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ (void)session;
+ (void)in;
+ (void)in_len;
+ (void)out;
+ (void)out_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ (void)session;
+ (void)in;
+ (void)in_len;
+ (void)out;
+ (void)out_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ (void)session;
+ (void)in;
+ (void)in_len;
+ (void)out;
+ (void)out_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+
+CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ (void)session;
+ (void)in;
+ (void)in_len;
+ (void)out;
+ (void)out_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ (void)session;
+ (void)in;
+ (void)in_len;
+ (void)out;
+ (void)out_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_GenerateKey(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR handle)
+{
+ CK_RV rv;
+ CK_ATTRIBUTE_PTR attribs_n = NULL;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_add_object_class(attribs, &count,
+ &attribs_n, CKO_SECRET_KEY);
+ if (rv != CKR_OK) {
+ if (attribs_n)
+ free(attribs_n);
+ return rv;
+ }
+
+ rv = ck_generate_key(session, mechanism, attribs_n, count, handle);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_READ_ONLY:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_CURVE_NOT_SUPPORTED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_TEMPLATE_INCOMPLETE:
+ case CKR_TEMPLATE_INCONSISTENT:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ if (attribs_n)
+ free(attribs_n);
+ return rv;
+}
+
+CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_OBJECT_HANDLE_PTR pub_key,
+ CK_OBJECT_HANDLE_PTR priv_key)
+{
+ CK_RV rv;
+ CK_ATTRIBUTE_PTR pub_attribs_n = NULL;
+ CK_ATTRIBUTE_PTR priv_attribs_n = NULL;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (!mechanism || !pub_key || !priv_key)
+ return CKR_ARGUMENTS_BAD;
+
+ if (pub_count && !pub_attribs)
+ return CKR_ARGUMENTS_BAD;
+
+ if (priv_count && !priv_attribs)
+ return CKR_ARGUMENTS_BAD;
+
+
+ rv = ck_guess_key_type(mechanism, pub_attribs, &pub_count,
+ &pub_attribs_n);
+ if (rv != CKR_OK)
+ goto bail;
+
+ rv = ck_add_object_class(pub_attribs_n, &pub_count,
+ &pub_attribs_n, CKO_PUBLIC_KEY);
+ if (rv != CKR_OK)
+ goto bail;
+
+ rv = ck_guess_key_type(mechanism, priv_attribs, &priv_count,
+ &priv_attribs_n);
+ if (rv != CKR_OK)
+ goto bail;
+
+ rv = ck_add_object_class(priv_attribs_n, &priv_count,
+ &priv_attribs_n, CKO_PRIVATE_KEY);
+ if (rv != CKR_OK)
+ goto bail;
+
+ rv = ck_generate_key_pair(session, mechanism, pub_attribs_n, pub_count,
+ priv_attribs_n, priv_count, pub_key, priv_key);
+
+bail:
+ if (pub_attribs_n)
+ free(pub_attribs_n);
+ if (priv_attribs_n)
+ free(priv_attribs_n);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_READ_ONLY:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_CURVE_NOT_SUPPORTED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_DOMAIN_PARAMS_INVALID:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_TEMPLATE_INCOMPLETE:
+ case CKR_TEMPLATE_INCONSISTENT:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_WrapKey(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE wrap_key,
+ CK_OBJECT_HANDLE key,
+ CK_BYTE_PTR wrapped_key,
+ CK_ULONG_PTR wrapped_key_len)
+{
+ (void)session;
+ (void)mechanism;
+ (void)wrap_key;
+ (void)key;
+ (void)wrapped_key;
+ (void)wrapped_key_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_UnwrapKey(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE unwrap_key,
+ CK_BYTE_PTR wrapped_key,
+ CK_ULONG wrapped_key_len,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_key)
+{
+ (void)session;
+ (void)mechanism;
+ (void)unwrap_key;
+ (void)wrapped_key;
+ (void)wrapped_key_len;
+ (void)attribs;
+ (void)count;
+ (void)new_key;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_DeriveKey(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE derived_key,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR key_handle)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_derive_key(session, mechanism, derived_key, attribs, count,
+ key_handle);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_READ_ONLY:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_CURVE_NOT_SUPPORTED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_DOMAIN_PARAMS_INVALID:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_KEY_HANDLE_INVALID:
+ case CKR_KEY_SIZE_RANGE:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_TEMPLATE_INCOMPLETE:
+ case CKR_TEMPLATE_INCONSISTENT:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_SeedRandom(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR seed,
+ CK_ULONG len)
+{
+ (void)session;
+ (void)seed;
+ (void)len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV C_GenerateRandom(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG len)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_generate_random(session, out, len);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_READ_ONLY:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_GENERAL_ERROR:
+ case CKR_OK:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE session)
+{
+ (void)session;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+CK_RV C_CancelFunction(CK_SESSION_HANDLE session)
+{
+ (void)session;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+
+CK_RV C_WaitForSlotEvent(CK_FLAGS flags,
+ CK_SLOT_ID_PTR slot,
+ CK_VOID_PTR rsv)
+{
+ (void)flags;
+ (void)slot;
+ (void)rsv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+
+CK_RV C_ImportKey(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG_PTR keyblob_length)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_import_key(session, attribs, count, keyblob, keyblob_length);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_READ_ONLY:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_CURVE_NOT_SUPPORTED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_DOMAIN_PARAMS_INVALID:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_OK:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_TEMPLATE_INCOMPLETE:
+ case CKR_TEMPLATE_INCONSISTENT:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_ImportKeyPair(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG_PTR keyblob_length)
+{
+ CK_RV rv;
+ CK_ATTRIBUTE_PTR pub_attribs_n = NULL;
+ CK_ATTRIBUTE_PTR priv_attribs_n = NULL;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (!mechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ if (!keyblob || !keyblob_length)
+ return CKR_ARGUMENTS_BAD;
+
+ if (pub_count && !pub_attribs)
+ return CKR_ARGUMENTS_BAD;
+
+ if (priv_count && !priv_attribs)
+ return CKR_ARGUMENTS_BAD;
+
+
+ rv = ck_guess_key_type(mechanism, pub_attribs, &pub_count,
+ &pub_attribs_n);
+ if (rv != CKR_OK)
+ goto bail;
+
+ rv = ck_add_object_class(pub_attribs_n, &pub_count,
+ &pub_attribs_n, CKO_PUBLIC_KEY);
+ if (rv != CKR_OK)
+ goto bail;
+
+ rv = ck_guess_key_type(mechanism, priv_attribs, &priv_count,
+ &priv_attribs_n);
+ if (rv != CKR_OK)
+ goto bail;
+
+ rv = ck_add_object_class(priv_attribs_n, &priv_count,
+ &priv_attribs_n, CKO_PRIVATE_KEY);
+ if (rv != CKR_OK)
+ goto bail;
+
+ rv = ck_import_key_pair(session, mechanism, pub_attribs_n, pub_count,
+ priv_attribs_n, priv_count, keyblob, keyblob_length);
+
+bail:
+ if (pub_attribs_n)
+ free(pub_attribs_n);
+ if (priv_attribs_n)
+ free(priv_attribs_n);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_ATTRIBUTE_READ_ONLY:
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ case CKR_CURVE_NOT_SUPPORTED:
+ case CKR_DEVICE_ERROR:
+ case CKR_DEVICE_MEMORY:
+ case CKR_DEVICE_REMOVED:
+ case CKR_DOMAIN_PARAMS_INVALID:
+ case CKR_FUNCTION_CANCELED:
+ case CKR_FUNCTION_FAILED:
+ case CKR_GENERAL_ERROR:
+ case CKR_HOST_MEMORY:
+ case CKR_MECHANISM_INVALID:
+ case CKR_MECHANISM_PARAM_INVALID:
+ case CKR_OK:
+ case CKR_OPERATION_ACTIVE:
+ case CKR_PIN_EXPIRED:
+ case CKR_SESSION_CLOSED:
+ case CKR_SESSION_HANDLE_INVALID:
+ case CKR_SESSION_READ_ONLY:
+ case CKR_TEMPLATE_INCOMPLETE:
+ case CKR_TEMPLATE_INCONSISTENT:
+ case CKR_TOKEN_WRITE_PROTECTED:
+ case CKR_USER_NOT_LOGGED_IN:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_ExportKey(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG keybloblength,
+ CK_BYTE_PTR pubkey,
+ CK_ULONG_PTR pubkeylength)
+{
+ CK_RV rv;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ rv = ck_export_key(session, keyblob, keybloblength, pubkey, pubkeylength);
+
+ switch (rv) {
+ case CKR_ARGUMENTS_BAD:
+ case CKR_GENERAL_ERROR:
+ case CKR_OK:
+ break;
+ default:
+ assert(!rv);
+ }
+
+ return rv;
+}
+
+CK_RV C_Utils(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+
+{
+ CK_RV rv;
+ CK_ULONG out_size = out_len;
+
+ if (!lib_inited)
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (!mechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = ck_utils(session, mechanism, in, in_len, out, &out_size);
+
+ return rv;
+}
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_processing.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_processing.c
new file mode 100644
index 0000000..987b502
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_processing.c
@@ -0,0 +1,1048 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sks_ta.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tee_client_api.h>
+
+#include "pkcs11_processing.h"
+#include "invoke_ta.h"
+#include "serializer.h"
+#include "serialize_ck.h"
+
+static struct sks_invoke *ck_session2sks_ctx(CK_SESSION_HANDLE session)
+{
+ (void)session;
+ // TODO: find back the invocation context from the session handle
+ // Until we do that, let's use the default invacation context.
+ return NULL;
+}
+
+CK_RV ck_create_object(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR handle)
+{
+ CK_RV rv;
+ struct serializer obj;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+ uint32_t key_handle;
+ uint32_t session_handle = session;
+ size_t key_handle_size = sizeof(key_handle);
+
+ if (!attribs || !count || !handle)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = serialize_ck_attributes(&obj, attribs, count);
+ if (rv)
+ goto bail;
+
+ /* ctrl = [session-handle][headed-serialized-attributes] */
+ ctrl_size = sizeof(uint32_t) + obj.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), obj.buffer, obj.size);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_IMPORT_OBJECT, ctrl, ctrl_size,
+ NULL, 0, &key_handle, &key_handle_size);
+ if (rv)
+ goto bail;
+
+ *handle = key_handle;
+
+bail:
+ release_serial_object(&obj);
+ free(ctrl);
+ return rv;
+}
+
+CK_RV ck_destroy_object(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj)
+{
+ uint32_t ctrl[2] = { (uint32_t)session, (uint32_t)obj };
+
+ return ck_invoke_ta(ck_session2sks_ctx(session),
+ SKS_CMD_DESTROY_OBJECT, ctrl, sizeof(ctrl));
+}
+
+CK_RV ck_digest_init(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism)
+{
+ CK_RV rv;
+ struct serializer obj;
+ uint32_t session_handle = session;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+
+ if (!mechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = serialize_ck_mecha_params(&obj, mechanism);
+ if (rv)
+ return rv;
+
+ /* params = [session-handle][key-handle][serialized-mechanism-blob] */
+ ctrl_size = sizeof(uint32_t) + obj.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), obj.buffer, obj.size);
+
+ rv = ck_invoke_ta(ck_session2sks_ctx(session), SKS_CMD_DIGEST_INIT,
+ ctrl, ctrl_size);
+
+bail:
+ release_serial_object(&obj);
+ free(ctrl);
+ return rv;
+}
+
+CK_RV ck_digest_update(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *in_buf = in;
+ size_t in_size = in_len;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_DIGEST_UPDATE,
+ &ctrl, ctrl_size, in_buf, in_buf ? in_size : 0,
+ NULL, NULL);
+
+ return rv;
+}
+
+CK_RV ck_digest_oneshot(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *in_buf = in;
+ size_t in_size = in_len;
+ void *out_buf = out;
+ size_t out_size;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ if (!out_len)
+ out_size = 0;
+ else
+ out_size = *out_len;
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_DIGEST_ONESHOT,
+ &ctrl, ctrl_size, in_buf, in_buf ? in_size : 0,
+ out_buf, out_len ? &out_size : NULL);
+
+ if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
+ *out_len = out_size;
+
+ if (out_len && !out_buf && rv == CKR_BUFFER_TOO_SMALL)
+ rv = CKR_OK;
+
+ return rv;
+}
+
+CK_RV ck_digest_final(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *out_buf = out;
+ size_t out_size;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ if (!out_len)
+ out_size = 0;
+ else
+ out_size = *out_len;
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_DIGEST_FINAL,
+ &ctrl, ctrl_size,
+ NULL, 0,
+ out_buf, out_len);
+
+ if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
+ *out_len = out_size;
+
+ return rv;
+}
+
+
+CK_RV ck_encdecrypt_init(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key,
+ int decrypt)
+{
+ CK_RV rv;
+ struct serializer obj;
+ uint32_t session_handle = session;
+ uint32_t key_handle = key;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+
+ if (!mechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = serialize_ck_mecha_params(&obj, mechanism);
+ if (rv)
+ return rv;
+
+ /* params = [session-handle][key-handle][serialized-mechanism-blob] */
+ ctrl_size = 2 * sizeof(uint32_t) + obj.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), &key_handle, sizeof(uint32_t));
+ memcpy(ctrl + 2 * sizeof(uint32_t), obj.buffer, obj.size);
+
+ rv = ck_invoke_ta(ck_session2sks_ctx(session), decrypt ?
+ SKS_CMD_DECRYPT_INIT : SKS_CMD_ENCRYPT_INIT,
+ ctrl, ctrl_size);
+
+bail:
+ release_serial_object(&obj);
+ free(ctrl);
+ return rv;
+}
+
+CK_RV ck_encdecrypt_update(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len,
+ int decrypt)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *in_buf = in;
+ size_t in_size = in_len;
+ void *out_buf = out;
+ size_t out_size;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ if (!out_len)
+ out_size = 0;
+ else
+ out_size = *out_len;
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session), decrypt ?
+ SKS_CMD_DECRYPT_UPDATE :
+ SKS_CMD_ENCRYPT_UPDATE,
+ &ctrl, ctrl_size, in_buf, in_buf ? in_size : 0,
+ out_buf, out_len ? &out_size : NULL);
+
+ if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
+ *out_len = out_size;
+
+ return rv;
+}
+
+CK_RV ck_encdecrypt_oneshot(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len,
+ int decrypt)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *in_buf = in;
+ size_t in_size = in_len;
+ void *out_buf = out;
+ size_t out_size;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ if (!out_len)
+ out_size = 0;
+ else
+ out_size = *out_len;
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session), decrypt ?
+ SKS_CMD_DECRYPT_ONESHOT :
+ SKS_CMD_ENCRYPT_ONESHOT,
+ &ctrl, ctrl_size, in_buf, in_buf ? in_size : 0,
+ out_buf, out_len ? &out_size : NULL);
+
+ if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
+ *out_len = out_size;
+
+ if (out_len && !out_buf && rv == CKR_BUFFER_TOO_SMALL)
+ rv = CKR_OK;
+
+ return rv;
+}
+
+CK_RV ck_encdecrypt_final(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len,
+ int decrypt)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *out_buf = out;
+ size_t out_size;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ if (!out_len)
+ out_size = 0;
+ else
+ out_size = *out_len;
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session), decrypt ?
+ SKS_CMD_DECRYPT_FINAL : SKS_CMD_ENCRYPT_FINAL,
+ &ctrl, ctrl_size, NULL, 0,
+ out_buf, out_len ? &out_size : NULL);
+
+ if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
+ *out_len = out_size;
+
+ return rv;
+}
+
+CK_RV ck_generate_key(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR handle)
+{
+ CK_RV rv;
+ struct serializer smecha;
+ struct serializer sattr;
+ uint32_t session_handle = session;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+ uint32_t key_handle;
+ size_t key_handle_size = sizeof(key_handle);
+
+ if (!mechanism || !handle)
+ return CKR_ARGUMENTS_BAD;
+
+ if (count && !attribs)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = serialize_ck_mecha_params(&smecha, mechanism);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_attributes(&sattr, attribs, count);
+ if (rv)
+ goto bail;
+
+ /* ctrl = [session-handle][serialized-mecha][serialized-attributes] */
+ ctrl_size = sizeof(uint32_t) + smecha.size + sattr.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), smecha.buffer, smecha.size);
+ memcpy(ctrl + sizeof(uint32_t) + smecha.size, sattr.buffer, sattr.size);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_GENERATE_SYMM_KEY, ctrl, ctrl_size,
+ NULL, 0, &key_handle, &key_handle_size);
+ if (rv)
+ goto bail;
+
+ *handle = key_handle;
+
+bail:
+ free(ctrl);
+ release_serial_object(&smecha);
+ release_serial_object(&sattr);
+ return rv;
+}
+
+CK_RV ck_generate_key_pair(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_OBJECT_HANDLE_PTR pub_key,
+ CK_OBJECT_HANDLE_PTR priv_key)
+{
+ CK_RV rv;
+ struct serializer smecha;
+ struct serializer pub_sattr;
+ struct serializer priv_sattr;
+ priv_sattr.buffer = NULL;
+ uint32_t session_handle = session;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+ uint32_t key_handle[2];
+ size_t key_handle_size = sizeof(key_handle);
+
+ if (!mechanism || !pub_key || !priv_key)
+ return CKR_ARGUMENTS_BAD;
+
+
+ rv = serialize_ck_mecha_params(&smecha, mechanism);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_attributes(&pub_sattr, pub_attribs, pub_count);
+ if (rv)
+ goto bail;
+
+ rv = serialize_ck_attributes(&priv_sattr, priv_attribs, priv_count);
+ if (rv)
+ goto bail;
+
+ /* ctrl = [session-handle][serial-mecha][serial-pub][serial-priv] */
+ ctrl_size = sizeof(uint32_t) + smecha.size + pub_sattr.size +
+ priv_sattr.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t),
+ smecha.buffer, smecha.size);
+ memcpy(ctrl + sizeof(uint32_t) + smecha.size,
+ pub_sattr.buffer, pub_sattr.size);
+ memcpy(ctrl + sizeof(uint32_t) + smecha.size + pub_sattr.size,
+ priv_sattr.buffer, priv_sattr.size);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_GENERATE_KEY_PAIR, ctrl, ctrl_size,
+ NULL, 0, &key_handle[0], &key_handle_size);
+
+ if (key_handle_size != sizeof(key_handle))
+ rv = CKR_GENERAL_ERROR;
+ if (rv)
+ goto bail;
+
+ *pub_key = key_handle[0];
+ *priv_key = key_handle[1];
+
+bail:
+ free(ctrl);
+ release_serial_object(&smecha);
+ release_serial_object(&pub_sattr);
+ release_serial_object(&priv_sattr);
+ return rv;
+}
+
+CK_RV ck_signverify_init(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key,
+ int sign)
+{
+ CK_RV rv;
+ struct serializer obj;
+ uint32_t session_handle = session;
+ uint32_t key_handle = key;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+
+ rv = serialize_ck_mecha_params(&obj, mechanism);
+ if (rv)
+ return rv;
+
+ /* params = [session-handle][key-handle][serialized-mechanism-blob] */
+ ctrl_size = 2 * sizeof(uint32_t) + obj.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), &key_handle, sizeof(uint32_t));
+ memcpy(ctrl + 2 * sizeof(uint32_t), obj.buffer, obj.size);
+
+ rv = ck_invoke_ta(ck_session2sks_ctx(session), sign ?
+ SKS_CMD_SIGN_INIT : SKS_CMD_VERIFY_INIT,
+ ctrl, ctrl_size);
+
+bail:
+ free(ctrl);
+ release_serial_object(&obj);
+ return rv;
+}
+
+CK_RV ck_signverify_update(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ int sign)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *in_buf = in;
+ size_t in_size = in_len;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ rv = ck_invoke_ta_in(ck_session2sks_ctx(session), sign ?
+ SKS_CMD_SIGN_UPDATE : SKS_CMD_VERIFY_UPDATE,
+ &ctrl, ctrl_size, in_buf, in_size);
+
+ return rv;
+}
+
+CK_RV ck_signverify_oneshot(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR sign_ref,
+ CK_ULONG_PTR sign_len,
+ int sign)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *in_buf = in;
+ size_t in_size = in_len;
+ void *sign_buf = sign_ref;
+ size_t sign_size;
+ uint8_t dummy_buf[1];
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ if (!sign_len)
+ sign_size = 0;
+ else
+ sign_size = *sign_len;
+
+ if (!sign_buf) {
+ sign_buf = dummy_buf;
+ sign_size = sizeof(dummy_buf);
+ }
+
+ if (sign)
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_SIGN_ONESHOT,
+ &ctrl, ctrl_size, in_buf, in_size,
+ sign_buf, &sign_size);
+ else
+ rv = ck_invoke_ta_in_in(ck_session2sks_ctx(session),
+ SKS_CMD_VERIFY_ONESHOT,
+ &ctrl, ctrl_size, in_buf, in_size,
+ sign_buf, sign_size);
+
+ if (sign && sign_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
+ *sign_len = sign_size;
+
+ if (sign && !sign_ref && rv == CKR_BUFFER_TOO_SMALL)
+ rv = CKR_OK;
+
+ return rv;
+}
+
+CK_RV ck_signverify_final(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR sign_ref,
+ CK_ULONG_PTR sign_len,
+ int sign)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *sign_buf = sign_ref;
+ size_t sign_size = sign_len ? *sign_len : 0;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ if (sign)
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_SIGN_FINAL, &ctrl, ctrl_size,
+ NULL, 0, sign_buf,
+ sign_buf ? &sign_size : NULL);
+ else
+ rv = ck_invoke_ta_in(ck_session2sks_ctx(session),
+ SKS_CMD_VERIFY_FINAL,
+ &ctrl, ctrl_size, sign_buf, sign_size);
+
+ if (sign && sign_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL))
+ *sign_len = sign_size;
+
+ return rv;
+}
+
+CK_RV ck_find_objects_init(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count)
+{
+ CK_RV rv;
+ uint32_t session_handle = session;
+ struct serializer obj;
+ char *ctrl;
+ size_t ctrl_size;
+
+ rv = serialize_ck_attributes(&obj, attribs, count);
+ if (rv)
+ return rv;
+
+ /* ctrl = [session-handle][headed-serialized-attributes] */
+ ctrl_size = sizeof(uint32_t) + obj.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), obj.buffer, obj.size);
+
+ rv = ck_invoke_ta(ck_session2sks_ctx(session),
+ SKS_CMD_FIND_OBJECTS_INIT, ctrl, ctrl_size);
+
+bail:
+ release_serial_object(&obj);
+ free(ctrl);
+ return rv;
+}
+
+CK_RV ck_find_objects(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE_PTR obj,
+ CK_ULONG max_count,
+ CK_ULONG_PTR count)
+
+{
+ CK_RV rv;
+ uint32_t ctrl[1] = { session };
+ uint32_t *handles;
+ size_t handles_size = max_count * sizeof(uint32_t);
+ CK_ULONG n;
+ CK_ULONG last;
+
+ handles = malloc(handles_size);
+ if (!handles)
+ return CKR_HOST_MEMORY;
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_FIND_OBJECTS, ctrl, sizeof(ctrl),
+ NULL, 0, handles, &handles_size);
+
+ if (rv)
+ goto bail;
+
+ last = handles_size / sizeof(uint32_t);
+ *count = last;
+
+ for (n = 0; n < last; n++) {
+ obj[n] = handles[n];
+ }
+
+bail:
+ free(handles);
+ return rv;
+
+}
+
+CK_RV ck_find_objects_final(CK_SESSION_HANDLE session)
+{
+ CK_RV rv;
+ uint32_t ctrl[1] = { session };
+
+ rv = ck_invoke_ta(ck_session2sks_ctx(session),
+ SKS_CMD_FIND_OBJECTS_FINAL, ctrl, sizeof(ctrl));
+
+ return rv;
+}
+
+CK_RV ck_derive_key(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE parent_handle,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR out_handle)
+{
+ CK_RV rv;
+ struct serializer smecha;
+ struct serializer sattr;
+ uint32_t session_handle = session;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+ uint32_t parent_key_handle = parent_handle;
+ uint32_t key_handle;
+ size_t key_handle_size = sizeof(key_handle);
+
+ rv = serialize_ck_mecha_params(&smecha, mechanism);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_attributes(&sattr, attribs, count);
+ if (rv)
+ goto bail;
+
+ /* ctrl = [session][serialized-mecha][parent-key][key-attributes] */
+ ctrl_size = 2 * sizeof(uint32_t) + smecha.size + sattr.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), smecha.buffer, smecha.size);
+ memcpy(ctrl + sizeof(uint32_t) + smecha.size,
+ &parent_key_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t) + smecha.size + sizeof(uint32_t),
+ sattr.buffer, sattr.size);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_DERIVE_KEY, ctrl, ctrl_size,
+ NULL, 0, &key_handle, &key_handle_size);
+ if (rv)
+ goto bail;
+
+ *out_handle = key_handle;
+
+bail:
+ free(ctrl);
+ release_serial_object(&smecha);
+ release_serial_object(&sattr);
+ return rv;
+}
+
+
+CK_RV ck_generate_random(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG len)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *out_buf = out;
+ size_t out_size = len;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_GENERATE_RANDOM,
+ &ctrl, ctrl_size, NULL, 0,
+ out_buf, &out_size);
+ return rv;
+}
+
+CK_RV ck_get_object_size(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ULONG_PTR out_size)
+{
+ CK_RV rv;
+ uint32_t ctrl[2] = { (uint32_t)session, (uint32_t)obj };
+ uint32_t obj_size = 0;
+ size_t size = sizeof(obj_size);
+
+ if (!out_size)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_GET_OBJECT_SIZE, ctrl,
+ sizeof(ctrl), NULL, 0, &obj_size,
+ &size);
+ if (rv)
+ return rv;
+
+ if (obj_size == SKS_CK_UNAVAILABLE_INFORMATION)
+ *out_size = CK_UNAVAILABLE_INFORMATION;
+ else
+ *out_size = obj_size;
+
+ return rv;
+}
+
+CK_RV ck_get_attribute_value(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count)
+{
+ CK_RV rv;
+ struct serializer sattr;
+ uint32_t session_handle = session;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+ uint8_t *out = NULL;
+ size_t out_size;
+ uint32_t obj_handle = obj;
+ size_t handle_size = sizeof(obj_handle);
+
+ if (!attribs)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = serialize_ck_attributes(&sattr, attribs, count);
+ if (rv)
+ goto bail;
+
+ /* ctrl = [session][obj-handle][attributes] */
+ ctrl_size = sizeof(uint32_t) + handle_size + sattr.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+ /* out = [attributes] */
+ out_size = sattr.size;
+ out = malloc(out_size);
+ if (!out){
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), &obj_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t) + handle_size, sattr.buffer, sattr.size);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_GET_ATTRIBUTE_VALUE, ctrl, ctrl_size,
+ NULL, 0, out, &out_size);
+ if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL)
+ goto bail;
+
+ rv = deserialize_ck_attributes(out, attribs, count);
+
+bail:
+ free(ctrl);
+ release_serial_object(&sattr);
+
+ return rv;
+}
+
+CK_RV ck_import_key(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG_PTR keyblob_length)
+{
+ CK_RV rv;
+ struct serializer obj;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+ void *blob_buf = keyblob;
+ uint32_t session_handle = session;
+
+ if (!attribs || !count || !keyblob_length || !keyblob)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = serialize_ck_attributes(&obj, attribs, count);
+ if (rv)
+ goto bail;
+ /* ctrl = [session-handle][headed-serialized-attributes] */
+ ctrl_size = sizeof(uint32_t) + obj.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), obj.buffer, obj.size);
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_IMPORT_KEY, ctrl, ctrl_size,
+ NULL, 0, blob_buf, keyblob_length);
+ if (rv)
+ goto bail;
+bail:
+ release_serial_object(&obj);
+ free(ctrl);
+ return rv;
+}
+
+
+CK_RV ck_import_key_pair(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG_PTR keyblob_length)
+{
+ CK_RV rv;
+ struct serializer smecha;
+ struct serializer pub_sattr;
+ struct serializer priv_sattr;
+ priv_sattr.buffer = NULL;
+ uint32_t session_handle = session;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+ uint32_t key_handle[2];
+ size_t key_handle_size = sizeof(key_handle);
+
+ if (!mechanism || !keyblob || !keyblob_length)
+ return CKR_ARGUMENTS_BAD;
+
+
+ rv = serialize_ck_mecha_params(&smecha, mechanism);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_attributes(&pub_sattr, pub_attribs, pub_count);
+ if (rv)
+ goto bail;
+
+ rv = serialize_ck_attributes(&priv_sattr, priv_attribs, priv_count);
+ if (rv)
+ goto bail;
+
+ /* ctrl = [session-handle][serial-mecha][serial-pub][serial-priv] */
+ ctrl_size = sizeof(uint32_t) + smecha.size + pub_sattr.size +
+ priv_sattr.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t),
+ smecha.buffer, smecha.size);
+ memcpy(ctrl + sizeof(uint32_t) + smecha.size,
+ pub_sattr.buffer, pub_sattr.size);
+ memcpy(ctrl + sizeof(uint32_t) + smecha.size + pub_sattr.size,
+ priv_sattr.buffer, priv_sattr.size);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_IMPORT_KEY_PAIR, ctrl, ctrl_size,
+ NULL, 0, keyblob, keyblob_length);
+
+ if (rv)
+ goto bail;
+
+bail:
+ free(ctrl);
+ release_serial_object(&smecha);
+ release_serial_object(&pub_sattr);
+ release_serial_object(&priv_sattr);
+ return rv;
+}
+
+CK_RV ck_export_key(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG keybloblength,
+ CK_BYTE_PTR pubkey,
+ CK_ULONG_PTR pubkeylength)
+{
+ CK_RV rv;
+ uint32_t ctrl;
+ size_t ctrl_size;
+ void *in_buf = keyblob;
+ size_t in_size = keybloblength;
+ void *out_buf = pubkey;
+ size_t out_size = *pubkeylength;
+
+ if (!keyblob || !pubkey || !pubkeylength)
+ return CKR_ARGUMENTS_BAD;
+
+ /* params = [session-handle] */
+ ctrl = session;
+ ctrl_size = sizeof(ctrl);
+
+ rv = ck_invoke_ta_in_out(ck_session2sks_ctx(session),
+ SKS_CMD_EXPORT_KEY,
+ &ctrl, ctrl_size, in_buf, in_size,
+ out_buf, &out_size);
+
+ if (rv == CKR_OK)
+ *pubkeylength = out_size;
+
+ return rv;
+}
+
+CK_RV ck_utils(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len)
+{
+ CK_RV rv;
+ struct serializer obj;
+ uint32_t session_handle = session;
+ char *ctrl = NULL;
+ size_t ctrl_size;
+
+ (void)in;
+ (void)in_len;
+ (void)out;
+ (void)out_len;
+
+ if (!mechanism)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = serialize_ck_mecha_params(&obj, mechanism);
+ if (rv)
+ return rv;
+
+ ctrl_size = sizeof(uint32_t) + obj.size;
+ ctrl = malloc(ctrl_size);
+ if (!ctrl) {
+ rv = CKR_HOST_MEMORY;
+ goto bail;
+ }
+
+ memcpy(ctrl, &session_handle, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), obj.buffer, obj.size);
+
+ rv = ck_invoke_ta(ck_session2sks_ctx(session), SKS_CMD_UTILS,
+ ctrl, ctrl_size);
+
+bail:
+ release_serial_object(&obj);
+ free(ctrl);
+ return rv;
+}
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_processing.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_processing.h
new file mode 100644
index 0000000..467db93
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_processing.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __PKCS11_PROCESSING_H
+#define __PKCS11_PROCESSING_H
+
+#include <pkcs11.h>
+
+CK_RV ck_create_object(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR phObject);
+
+CK_RV ck_destroy_object(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj);
+
+CK_RV ck_digest_init(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism);
+
+CK_RV ck_digest_update(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len);
+
+CK_RV ck_digest_oneshot(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV ck_digest_final(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+
+CK_RV ck_encdecrypt_init(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key,
+ int decrypt);
+
+CK_RV ck_encdecrypt_update(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len,
+ int decrypt);
+
+CK_RV ck_encdecrypt_oneshot(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len,
+ int decrypt);
+
+CK_RV ck_encdecrypt_final(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len,
+ int decrypt);
+
+CK_RV ck_generate_key(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR handle);
+
+CK_RV ck_signverify_init(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key,
+ int sign);
+
+CK_RV ck_signverify_update(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ int sign);
+
+CK_RV ck_signverify_oneshot(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len,
+ int sign);
+
+CK_RV ck_signverify_final(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len,
+ int sign);
+
+CK_RV ck_find_objects_init(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count);
+
+CK_RV ck_find_objects(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE_PTR obj,
+ CK_ULONG max_count,
+ CK_ULONG_PTR count);
+
+CK_RV ck_find_objects_final(CK_SESSION_HANDLE session);
+
+CK_RV ck_generate_key_pair(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_OBJECT_HANDLE_PTR pub_key,
+ CK_OBJECT_HANDLE_PTR priv_key);
+
+CK_RV ck_derive_key(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE parent_handle,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR key_handle);
+
+CK_RV ck_generate_random(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR out,
+ CK_ULONG len);
+
+CK_RV ck_get_object_size(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ULONG_PTR out_size);
+
+CK_RV ck_get_attribute_value(CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count);
+
+CK_RV ck_import_key(CK_SESSION_HANDLE session,
+ CK_ATTRIBUTE_PTR attribs,
+ CK_ULONG count,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG_PTR keyblob_length);
+
+CK_RV ck_import_key_pair(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR pub_attribs,
+ CK_ULONG pub_count,
+ CK_ATTRIBUTE_PTR priv_attribs,
+ CK_ULONG priv_count,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG_PTR keyblob_length);
+
+CK_RV ck_export_key(CK_SESSION_HANDLE session,
+ CK_BYTE_PTR keyblob,
+ CK_ULONG keybloblength,
+ CK_BYTE_PTR pubkey,
+ CK_ULONG_PTR pubkeylength);
+
+CK_RV ck_utils(CK_SESSION_HANDLE session,
+ CK_MECHANISM_PTR mechanism,
+ CK_BYTE_PTR in,
+ CK_ULONG in_len,
+ CK_BYTE_PTR out,
+ CK_ULONG_PTR out_len);
+#endif /*__PKCS11_PROCESSING_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_token.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_token.c
new file mode 100644
index 0000000..d0685a5
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_token.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <pkcs11.h>
+#include <sks_ck_debug.h>
+#include <sks_ta.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ck_helpers.h"
+#include "invoke_ta.h"
+#include "local_utils.h"
+#include "pkcs11_token.h"
+
+#define SKS_CRYPTOKI_SLOT_MANUFACTURER "Linaro"
+
+#define PADDED_STRING_COPY(_dst, _src) \
+ do { \
+ memset((char *)_dst, ' ', sizeof(_dst)); \
+ strncpy((char *)_dst, _src, strlen(_src)); \
+ memset((char *)_dst, '\0', sizeof(_src)); \
+ } while (0)
+
+/**
+ * sks_ck_get_info - implementation of C_GetInfo
+ */
+int sks_ck_get_info(CK_INFO_PTR info)
+{
+ const CK_VERSION ck_version = { 2, 40 };
+ const char manuf_id[] = SKS_CRYPTOKI_SLOT_MANUFACTURER; // TODO slot?
+ const CK_FLAGS flags = 0; /* must be zero per the PKCS#11 2.40 */
+ const char lib_description[] = "OP-TEE SKS Cryptoki library";
+ const CK_VERSION lib_version = { 0, 0 };
+
+ info->cryptokiVersion = ck_version;
+ PADDED_STRING_COPY(info->manufacturerID, manuf_id);
+ info->flags = flags;
+ PADDED_STRING_COPY(info->libraryDescription, lib_description);
+ info->libraryVersion = lib_version;
+
+ return CKR_OK;
+}
+
+/**
+ * slot_get_info - implementation of C_GetSlotList
+ */
+CK_RV sks_ck_slot_get_list(CK_BBOOL present,
+ CK_SLOT_ID_PTR slots, CK_ULONG_PTR count)
+{
+ TEEC_SharedMemory *shm;
+ size_t size = 0;
+ CK_RV rv = CKR_GENERAL_ERROR;
+ unsigned int n;
+
+ /* Discard present: all are present */
+ (void)present;
+
+ if (!count)
+ return CKR_ARGUMENTS_BAD;
+
+ if (ck_invoke_ta_in_out(NULL, SKS_CMD_CK_SLOT_LIST, NULL, 0,
+ NULL, 0, NULL, &size) != CKR_BUFFER_TOO_SMALL)
+ return CKR_DEVICE_ERROR;
+
+ if (!slots || *count < (size / sizeof(uint32_t))) {
+ *count = size / sizeof(uint32_t);
+ if (!slots)
+ return CKR_OK;
+
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ shm = sks_alloc_shm_out(NULL, size);
+ if (!shm)
+ return CKR_HOST_MEMORY;
+
+ if (ck_invoke_ta_in_out(NULL, SKS_CMD_CK_SLOT_LIST, NULL, 0,
+ NULL, 0, shm, NULL) != CKR_OK) {
+ rv = CKR_DEVICE_ERROR;
+ goto bail;
+ }
+
+ for (n = 0; n < (size / sizeof(uint32_t)); n++)
+ slots[n] = *((uint32_t *)shm->buffer + n);
+
+ *count = size / sizeof(uint32_t);
+ rv = CKR_OK;
+bail:
+ sks_free_shm(shm);
+ return rv;
+
+}
+
+/**
+ * slot_get_info - implementation of C_GetSlotInfo
+ */
+int sks_ck_slot_get_info(CK_SLOT_ID slot, CK_SLOT_INFO_PTR info)
+{
+ uint32_t ctrl[1] = { slot };
+ CK_SLOT_INFO *ck_info = info;
+ struct sks_slot_info sks_info;
+ size_t out_size = sizeof(sks_info);
+ CK_RV rv = CKR_GENERAL_ERROR;
+
+ if (!info)
+ return CKR_ARGUMENTS_BAD;
+
+ rv = ck_invoke_ta_in_out(NULL, SKS_CMD_CK_SLOT_INFO, &ctrl,
+ sizeof(ctrl), NULL, 0, &sks_info, &out_size);
+ if (rv)
+ return rv;
+
+ if (sks2ck_slot_info(ck_info, &sks_info)) {
+ LOG_ERROR("unexpected bad token info structure\n");
+ return CKR_DEVICE_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+/**
+ * slot_get_info - implementation of C_GetTokenInfo
+ */
+CK_RV sks_ck_token_get_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info)
+{
+ uint32_t ctrl[1] = { slot };
+ CK_TOKEN_INFO *ck_info = info;
+ TEEC_SharedMemory *shm;
+ size_t size;
+ CK_RV rv = CKR_GENERAL_ERROR;
+
+ if (!info)
+ return CKR_ARGUMENTS_BAD;
+
+ ctrl[0] = (uint32_t)slot;
+ size = 0;
+ if (ck_invoke_ta_in_out(NULL, SKS_CMD_CK_TOKEN_INFO, ctrl, sizeof(ctrl),
+ NULL, 0, NULL, &size) != CKR_BUFFER_TOO_SMALL)
+ return CKR_DEVICE_ERROR;
+
+ shm = sks_alloc_shm_out(NULL, size);
+ if (!shm)
+ return CKR_HOST_MEMORY;
+
+ ctrl[0] = (uint32_t)slot;
+ rv = ck_invoke_ta_in_out(NULL, SKS_CMD_CK_TOKEN_INFO,
+ ctrl, sizeof(ctrl), NULL, 0, shm, NULL);
+ if (rv)
+ goto bail;
+
+ if (shm->size < sizeof(struct sks_token_info)) {
+ LOG_ERROR("unexpected bad token info size\n");
+ rv = CKR_DEVICE_ERROR;
+ goto bail;
+ }
+
+ rv = sks2ck_token_info(ck_info, shm->buffer);
+
+bail:
+ sks_free_shm(shm);
+
+ return rv;
+}
+
+/**
+ * sks_ck_init_token - implementation of C_InitToken
+ */
+CK_RV sks_ck_init_token(CK_SLOT_ID slot,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len,
+ CK_UTF8CHAR_PTR label)
+{
+ uint32_t sks_slot = slot;
+ uint32_t sks_pin_len = pin_len;
+ size_t ctrl_size = 2 * sizeof(uint32_t) + sks_pin_len +
+ 32 * sizeof(uint8_t);
+ char *ctrl;
+ size_t offset;
+
+ if (!pin || !label)
+ return CKR_ARGUMENTS_BAD;
+
+ ctrl = malloc(ctrl_size);
+ if (!ctrl)
+ return CKR_HOST_MEMORY;
+
+ memcpy(ctrl, &sks_slot, sizeof(uint32_t));
+ offset = sizeof(uint32_t);
+
+ memcpy(ctrl + offset, &sks_pin_len, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+
+ memcpy(ctrl + offset, pin, sks_pin_len);
+ offset += sks_pin_len;
+
+ memcpy(ctrl + offset, label, 32 * sizeof(uint8_t));
+
+ return ck_invoke_ta(NULL, SKS_CMD_CK_INIT_TOKEN, ctrl, ctrl_size);
+}
+
+/**
+ * sks_ck_token_mechanism_ids - implementation of C_GetMechanismList
+ */
+CK_RV sks_ck_token_mechanism_ids(CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE_PTR mechanisms,
+ CK_ULONG_PTR count)
+{
+ uint32_t ctrl[1] = { slot };
+ size_t outsize = 0;
+ void *outbuf = NULL;
+ CK_RV rv;
+
+ if (!count)
+ return CKR_ARGUMENTS_BAD;
+
+ if (mechanisms) {
+ outsize = *count * sizeof(uint32_t);
+ outbuf = malloc(outsize);
+ if (!outbuf)
+ return CKR_HOST_MEMORY;
+ }
+
+ rv = ck_invoke_ta_in_out(NULL, SKS_CMD_CK_MECHANISM_IDS,
+ &ctrl, sizeof(ctrl),
+ NULL, 0, outbuf, &outsize);
+
+ if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) {
+ *count = outsize / sizeof(uint32_t);
+ }
+ if (!mechanisms && rv == CKR_BUFFER_TOO_SMALL) {
+ rv = CKR_OK;
+ goto bail;
+ }
+ if (rv) {
+ goto bail;
+ }
+
+ if (sks2ck_mechanism_type_list(mechanisms, outbuf, *count)) {
+ LOG_ERROR("unexpected bad mechanism_type list\n");
+ rv = CKR_DEVICE_ERROR;
+ }
+
+bail:
+ free(outbuf);
+
+ return rv;
+}
+
+/**
+ * sks_ck_token_mechanism_info - implementation of C_GetMechanismInfo
+ */
+CK_RV sks_ck_token_mechanism_info(CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR info)
+{
+ CK_RV rv;
+ uint32_t ctrl[2];
+ struct sks_mechanism_info outbuf;
+ size_t outsize = sizeof(outbuf);
+
+ if (!info)
+ return CKR_ARGUMENTS_BAD;
+
+ ctrl[0] = (uint32_t)slot;
+ ctrl[1] = ck2sks_mechanism_type(type);
+ if (ctrl[1] == SKS_UNDEFINED_ID) {
+ LOG_DEBUG("mechanism is not support by this library\n");
+ return CKR_MECHANISM_INVALID;
+ }
+
+ /* info is large enought, for sure */
+ rv = ck_invoke_ta_in_out(NULL, SKS_CMD_CK_MECHANISM_INFO,
+ &ctrl, sizeof(ctrl),
+ NULL, 0, &outbuf, &outsize);
+ if (rv)
+ return rv;
+
+ if (sks2ck_mechanism_info(info, &outbuf)) {
+ LOG_ERROR("unexpected bad mechanism info structure\n");
+ rv = CKR_DEVICE_ERROR;
+ }
+ return rv;
+}
+
+/**
+ * sks_ck_open_session - implementation of C_OpenSession
+ */
+CK_RV sks_ck_open_session(CK_SLOT_ID slot,
+ CK_FLAGS flags,
+ CK_VOID_PTR cookie,
+ CK_NOTIFY callback,
+ CK_SESSION_HANDLE_PTR session)
+{
+ uint32_t ctrl[1] = { slot };
+ unsigned long cmd;
+ uint32_t handle;
+ size_t out_sz = sizeof(handle);
+ CK_RV rv;
+
+ if (!session)
+ return CKR_ARGUMENTS_BAD;
+
+ if (cookie || callback) {
+ LOG_ERROR("C_OpenSession does not handle callback yet\n");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ if (flags & CKF_RW_SESSION)
+ cmd = SKS_CMD_CK_OPEN_RW_SESSION;
+ else
+ cmd = SKS_CMD_CK_OPEN_RO_SESSION;
+
+ rv = ck_invoke_ta_in_out(NULL, cmd, &ctrl, sizeof(ctrl),
+ NULL, 0, &handle, &out_sz);
+ if (rv)
+ return rv;
+
+ *session = handle;
+
+ return CKR_OK;
+}
+
+CK_RV sks_ck_close_session(CK_SESSION_HANDLE session)
+{
+ uint32_t ctrl[1] = { (uint32_t)session };
+
+ return ck_invoke_ta(NULL, SKS_CMD_CK_CLOSE_SESSION,
+ &ctrl, sizeof(ctrl));
+}
+
+/**
+ * sks_ck_close_all_sessions - implementation of C_CloseAllSessions
+ */
+CK_RV sks_ck_close_all_sessions(CK_SLOT_ID slot)
+{
+ uint32_t ctrl[1] = { (uint32_t)slot };
+
+ return ck_invoke_ta(NULL, SKS_CMD_CK_CLOSE_ALL_SESSIONS,
+ &ctrl, sizeof(ctrl));
+}
+
+/**
+ * sks_ck_get_session_info - implementation of C_GetSessionInfo
+ */
+CK_RV sks_ck_get_session_info(CK_SESSION_HANDLE session,
+ CK_SESSION_INFO_PTR info)
+{
+ uint32_t ctrl[1] = { (uint32_t)session };
+ CK_SESSION_INFO *s_info = info;
+ TEEC_SharedMemory *shm = NULL;
+ CK_RV rv = CKR_GENERAL_ERROR;
+ size_t info_size = sizeof(struct sks_session_info);
+
+ if (!info)
+ return CKR_ARGUMENTS_BAD;
+
+ shm = sks_alloc_shm_out(NULL, info_size);
+ if (!shm)
+ return CKR_HOST_MEMORY;
+
+ rv = ck_invoke_ta_in_out(NULL, SKS_CMD_CK_SESSION_INFO,
+ &ctrl, sizeof(ctrl),
+ NULL, 0, shm, NULL);
+ if (rv)
+ goto bail;
+
+ if (shm->size < info_size) {
+ LOG_ERROR("unexpected bad session info size\n");
+ rv = CKR_DEVICE_ERROR;
+ goto bail;
+ }
+
+ rv = sks2ck_session_info(s_info, shm->buffer);
+
+bail:
+ sks_free_shm(shm);
+
+ return rv;
+}
+
+/**
+ * sks_ck_init_pin - implementation of C_InitPIN
+ */
+CK_RV sks_ck_init_pin(CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+{
+ uint32_t sks_session = session;
+ uint32_t sks_pin_len = pin_len;
+ size_t ctrl_size = 2 * sizeof(uint32_t) + sks_pin_len;
+ char *ctrl;
+
+ ctrl = malloc(ctrl_size);
+ if (!ctrl)
+ return CKR_HOST_MEMORY;
+
+ memcpy(ctrl, &sks_session, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), &sks_pin_len, sizeof(uint32_t));
+ memcpy(ctrl + 2 * sizeof(uint32_t), pin, sks_pin_len);
+
+ return ck_invoke_ta(NULL, SKS_CMD_INIT_PIN, ctrl, ctrl_size);
+}
+
+/**
+ * sks_ck_set_pin - implementation of C_SetPIN
+ */
+CK_RV sks_ck_set_pin(CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR old, CK_ULONG old_len,
+ CK_UTF8CHAR_PTR new, CK_ULONG new_len)
+{
+ uint32_t sks_session = session;
+ uint32_t sks_old_len = old_len;
+ uint32_t sks_new_len = new_len;
+ size_t ctrl_size = 3 * sizeof(uint32_t) + sks_old_len + sks_new_len;
+ char *ctrl;
+ size_t offset;
+
+ ctrl = malloc(ctrl_size);
+ if (!ctrl)
+ return CKR_HOST_MEMORY;
+
+ memcpy(ctrl, &sks_session, sizeof(uint32_t));
+ offset = sizeof(uint32_t);
+
+ memcpy(ctrl + offset, &sks_old_len, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+
+ memcpy(ctrl + offset, old, sks_old_len);
+ offset += sks_old_len;
+
+ memcpy(ctrl + offset, &sks_new_len, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+
+ memcpy(ctrl + offset, new, sks_new_len);
+
+ return ck_invoke_ta(NULL, SKS_CMD_SET_PIN, ctrl, ctrl_size);
+}
+
+/**
+ * sks_ck_login - implementation of C_Login
+ */
+CK_RV sks_ck_login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type,
+ CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+
+{
+ uint32_t sks_session = session;
+ uint32_t sks_user = ck2sks_user_type(user_type);
+ uint32_t sks_pin_len = pin_len;
+ size_t ctrl_size = 3 * sizeof(uint32_t) + sks_pin_len;
+ char *ctrl;
+
+ ctrl = malloc(ctrl_size);
+ if (!ctrl)
+ return CKR_HOST_MEMORY;
+
+ memcpy(ctrl, &sks_session, sizeof(uint32_t));
+ memcpy(ctrl + sizeof(uint32_t), &sks_user, sizeof(uint32_t));
+ memcpy(ctrl + 2 * sizeof(uint32_t), &sks_pin_len, sizeof(uint32_t));
+ memcpy(ctrl + 3 * sizeof(uint32_t), pin, sks_pin_len);
+
+ return ck_invoke_ta(NULL, SKS_CMD_LOGIN, ctrl, ctrl_size);
+}
+
+/**
+ * sks_ck_logout - implementation of C_Logout
+ */
+CK_RV sks_ck_logout(CK_SESSION_HANDLE session)
+{
+ uint32_t sks_session = session;
+ size_t ctrl_size = sizeof(uint32_t);
+ char *ctrl;
+
+ ctrl = malloc(ctrl_size);
+ if (!ctrl)
+ return CKR_HOST_MEMORY;
+
+ memcpy(ctrl, &sks_session, sizeof(uint32_t));
+
+ return ck_invoke_ta(NULL, SKS_CMD_LOGOUT, ctrl, ctrl_size);
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_token.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_token.h
new file mode 100644
index 0000000..56e7a00
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/pkcs11_token.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __PKCS11_TOKEN_H
+#define __PKCS11_TOKEN_H
+
+#include <pkcs11.h>
+
+#include "invoke_ta.h"
+
+int sks_ck_get_info(CK_INFO_PTR info);
+CK_RV sks_ck_slot_get_list(CK_BBOOL present,
+ CK_SLOT_ID_PTR slots, CK_ULONG_PTR count);
+int sks_ck_slot_get_info(CK_SLOT_ID slot, CK_SLOT_INFO_PTR info);
+CK_RV sks_ck_token_get_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info);
+
+CK_RV sks_ck_token_mechanism_ids(CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE_PTR mechanisms,
+ CK_ULONG_PTR count);
+
+CK_RV sks_ck_token_mechanism_info(CK_SLOT_ID slot,
+ CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR info);
+
+CK_RV sks_ck_init_token(CK_SLOT_ID slot,
+ CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len,
+ CK_UTF8CHAR_PTR label);
+
+CK_RV sks_ck_open_session(CK_SLOT_ID slot,
+ CK_FLAGS flags,
+ CK_VOID_PTR cookie,
+ CK_NOTIFY callback,
+ CK_SESSION_HANDLE_PTR session);
+CK_RV sks_ck_close_session(CK_SESSION_HANDLE session);
+CK_RV sks_ck_close_all_sessions(CK_SLOT_ID slot);
+CK_RV sks_ck_get_session_info(CK_SESSION_HANDLE session,
+ CK_SESSION_INFO_PTR info);
+
+CK_RV sks_ck_init_pin(CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR pin, CK_ULONG pin_len);
+CK_RV sks_ck_set_pin(CK_SESSION_HANDLE session,
+ CK_UTF8CHAR_PTR old, CK_ULONG old_len,
+ CK_UTF8CHAR_PTR new, CK_ULONG new_len);
+CK_RV sks_ck_login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type,
+ CK_UTF8CHAR_PTR pin, CK_ULONG pin_len);
+CK_RV sks_ck_logout(CK_SESSION_HANDLE session);
+
+#endif /*__PKCS11_TOKEN_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serialize_ck.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serialize_ck.c
new file mode 100644
index 0000000..1b5eeb0
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serialize_ck.c
@@ -0,0 +1,1192 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <pkcs11.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sks_ck_debug.h>
+#include <sks_ta.h>
+
+#include "ck_helpers.h"
+#include "local_utils.h"
+#include "serializer.h"
+#include "serialize_ck.h"
+
+/*
+ * Generic way of serializing CK keys, certif, mechanism parameters, ...
+ * In cryptoki 2.40 parameters are almost all packaged as struture below:
+ */
+struct ck_ref {
+ CK_ULONG id;
+ CK_BYTE_PTR ptr;
+ CK_ULONG len;
+};
+
+#if 0
+/*
+ * Append cryptoki generic buffer reference structure into a sks serial
+ * object.
+ *
+ * ck_ref points to a structure aligned CK reference (attributes or else)
+ */
+static CK_RV serialize_ck_ref(struct serializer *obj, void *ck_ref)
+{
+ struct ck_ref *ref = ck_ref;
+ CK_RV rv;
+
+ rv = serialize_ck_ulong(obj, ref->id);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_ulong(obj, ref->len);
+ if (rv)
+ return rv;
+
+ rv = serialize_buffer(obj, ref->ptr, ref->len);
+ if (rv)
+ return rv;
+
+ obj->item_count++;
+
+ return rv;
+}
+
+/*
+ * ck_ref points to a structure aligned CK reference (attributes or else)
+ *
+ * Same as serialize_ck_ref but reference is a ULONG so the blob size
+ * to be set accoring to the 32bit/64bit configuration of target CK ABI.
+ */
+static CK_RV serialize_ulong_ck_ref(struct serializer *obj, void *ck_ref)
+{
+ struct ck_ref *ref = ck_ref;
+ CK_ULONG ck_value;
+ uint32_t sks_value;
+ CK_RV rv;
+
+ rv = serialize_ck_ulong(obj, ref->id);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_ulong(obj, sizeof(sks_value));
+ if (rv)
+ return rv;
+
+ memcpy(&ck_value, ref->ptr, sizeof(CK_ULONG));
+ sks_value = ck_value;
+
+ rv = serialize_buffer(obj, &sks_value, sizeof(sks_value));
+ if (rv)
+ return rv;
+
+ obj->item_count++;
+
+ return rv;
+}
+#endif
+
+/*
+ * This is for attributes that contains data memory indirections.
+ * In other words, an attributes that defines a list of attributes.
+ * They are identified from the attribute type CKA_...
+ *
+ * @obj - ref used to track the serial object being created
+ * @attribute - pointer to a structure aligned of the CK_ATTRIBUTE struct
+ */
+static CK_RV serialize_indirect_attribute(struct serializer *obj,
+ CK_ATTRIBUTE_PTR attribute)
+{
+ CK_ATTRIBUTE_PTR attr;
+ CK_ULONG count;
+ CK_RV rv;
+ struct serializer obj2;
+
+ switch (attribute->type) {
+ /* These are serialized each seperately */
+ case CKA_WRAP_TEMPLATE:
+ case CKA_UNWRAP_TEMPLATE:
+ count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE);
+ attr = (CK_ATTRIBUTE_PTR)attribute->pValue;
+ break;
+ default:
+ return CKR_NO_EVENT;
+ }
+
+ /* Create a serialized object for the content */
+ rv = serialize_ck_attributes(&obj2, attr, count);
+ if (rv)
+ return rv;
+
+ /*
+ * Append the created serialized object into target object:
+ * [attrib-id][byte-size][attributes-data]
+ */
+ rv = serialize_32b(obj, ck2sks_attribute_type(attribute->type));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, obj2.size);
+ if (rv)
+ return rv;
+
+ rv = serialize_buffer(obj, obj2.buffer, obj2.size);
+ if (rv)
+ return rv;
+
+ obj->item_count++;
+
+ return rv;
+}
+
+static CK_RV deserialize_indirect_attribute(struct sks_attribute_head *obj,
+ CK_ATTRIBUTE_PTR attribute)
+{
+ CK_ULONG count;
+ CK_ATTRIBUTE_PTR attr;
+ CK_RV rv;
+
+ switch (attribute->type) {
+ /* These are serialized each seperately */
+ case CKA_WRAP_TEMPLATE:
+ case CKA_UNWRAP_TEMPLATE:
+ count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE);
+ attr = (CK_ATTRIBUTE_PTR)attribute->pValue;
+ break;
+ default:
+ return CKR_GENERAL_ERROR;
+ }
+
+ /*
+ * deserialize_ck_attributes expects sks_attribute_head,
+ * not sks_object_head, so we need to correct the pointer
+ */
+ rv = deserialize_ck_attributes(obj->data, attr, count);
+ return rv;
+}
+
+static int ck_attr_is_ulong(CK_ATTRIBUTE_TYPE attribute_id)
+{
+ return (ck_attr_is_class(attribute_id) ||
+ ck_attr_is_type(attribute_id) ||
+ attribute_id == CKA_VALUE_LEN ||
+ attribute_id == CKA_CERTIFICATE_CATEGORY ||
+ attribute_id == CKA_NAME_HASH_ALGORITHM ||
+ attribute_id == CKA_MODULUS_BITS);
+}
+
+static CK_RV serialize_ck_attribute(struct serializer *obj, CK_ATTRIBUTE *attr)
+{
+ uint32_t sks_id = SKS_UNDEFINED_ID;
+ uint32_t sks_size = 0;
+ uint32_t sks_data32;
+ void *sks_pdata;
+ int sks_pdata_alloced = 0;
+ CK_ULONG ck_ulong = 0; /* keep compiler happy */
+ CK_RV rv;
+ unsigned int n;
+ unsigned int m;
+
+ /* Expect only those from the identification table */
+ sks_id = ck2sks_attribute_type(attr->type);
+ if (sks_id == SKS_UNDEFINED_ID)
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+
+ if (ck_attr_is_ulong(attr->type)) {
+ /* PKCS#11 CK_ULONG are use */
+ if (attr->ulValueLen != sizeof(CK_ULONG))
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+
+ memcpy(&ck_ulong, attr->pValue, sizeof(ck_ulong));
+ }
+
+ switch (attr->type) {
+ case CKA_CLASS:
+ sks_data32 = ck2sks_object_class(ck_ulong);
+ sks_pdata = &sks_data32;
+ sks_size = sizeof(uint32_t);
+ break;
+
+ case CKA_KEY_TYPE:
+ sks_data32 = ck2sks_key_type(ck_ulong);
+ sks_pdata = &sks_data32;
+ sks_size = sizeof(uint32_t);
+ break;
+
+ case CKA_CERTIFICATE_TYPE:
+ sks_data32 = ck2sks_certificate_type(ck_ulong);
+ sks_pdata = &sks_data32;
+ sks_size = sizeof(uint32_t);
+ break;
+
+ case CKA_WRAP_TEMPLATE:
+ case CKA_UNWRAP_TEMPLATE:
+ return serialize_indirect_attribute(obj, attr);
+
+ case CKA_ALLOWED_MECHANISMS:
+ n = attr->ulValueLen / sizeof(CK_ULONG);
+ sks_size = n * sizeof(uint32_t);
+ sks_pdata = malloc(sks_size);
+ if (!sks_pdata)
+ return CKR_HOST_MEMORY;
+
+ sks_pdata_alloced = 1;
+
+ for (m = 0; m < n; m++) {
+ CK_MECHANISM_TYPE *type = attr->pValue;
+
+ sks_data32 = ck2sks_mechanism_type(type[m]);
+ if (sks_data32 == SKS_UNDEFINED_ID) {
+ free(sks_pdata);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ ((uint32_t *)sks_pdata)[m] = sks_data32;
+ }
+ break;
+
+ /* Attributes which data value do not need conversion (aside ulong) */
+ default:
+ if (ck_attr_is_ulong(attr->type)) {
+ sks_data32 = (uint32_t)ck_ulong;
+ sks_pdata = &sks_data32;
+ sks_size = sizeof(uint32_t);
+ } else {
+ sks_pdata = attr->pValue;
+ sks_size = attr->ulValueLen;
+ }
+ break;
+ }
+
+ rv = serialize_32b(obj, sks_id);
+ if (rv)
+ goto bail;
+
+ rv = serialize_32b(obj, sks_size);
+ if (rv)
+ goto bail;
+
+ rv = serialize_buffer(obj, sks_pdata, sks_size);
+ if (rv)
+ goto bail;
+
+ obj->item_count++;
+
+bail:
+ if (sks_pdata_alloced)
+ free(sks_pdata);
+
+ return rv;
+}
+
+#ifdef SKS_WITH_GENERIC_ATTRIBS_IN_HEAD
+static CK_RV get_class(struct serializer *obj, struct ck_ref *ref)
+{
+ CK_ULONG ck_value;
+ uint32_t sks_value;
+
+ if (ref->len != sizeof(ck_value))
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ memcpy(&ck_value, ref->ptr, sizeof(ck_value));
+
+ sks_value = ck2sks_object_class(ck_value);
+
+ if (sks_value == SKS_UNDEFINED_ID)
+ return CKR_TEMPLATE_INCONSISTENT; // TODO: errno
+
+ if (obj->object == SKS_UNDEFINED_ID)
+ obj->object = sks_value;
+
+ if (obj->object != sks_value) {
+ printf("Attribute %s redefined\n", cka2str(ref->id));
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV get_type(struct serializer *obj, struct ck_ref *ref,
+ CK_ULONG class)
+{
+ CK_ULONG ck_value;
+ uint32_t sks_value;
+
+ if (ref->len != sizeof(ck_value))
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ memcpy(&ck_value, ref->ptr, sizeof(ck_value));
+
+ sks_value = ck2sks_type_in_class(ck_value, class);
+
+ if (sks_value == SKS_UNDEFINED_ID)
+ return CKR_TEMPLATE_INCONSISTENT; // TODO: errno
+
+ if (obj->type == SKS_UNDEFINED_ID)
+ obj->type = sks_value;
+
+ if (obj->type != sks_value) {
+ printf("Attribute %s redefined\n",
+ cktype2str(ck_value, class));
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return CKR_OK;
+}
+
+#ifdef /* SKS_WITH_BOOLPROP_ATTRIBS_IN_HEAD */
+static CK_RV get_boolprop(struct serializer *obj,
+ struct ck_ref *ref, uint32_t *sanity)
+{
+ int shift;
+ uint32_t mask;
+ uint32_t value;
+ uint32_t *boolprop_ptr;
+ uint32_t *sanity_ptr;
+ CK_BBOOL bbool;
+
+ /* Get the boolean property shift position and value */
+ shift = ck_attr2boolprop_shift(ref->id);
+ if (shift < 0)
+ return CKR_NO_EVENT;
+
+ if (shift >= SKS_MAX_BOOLPROP_SHIFT)
+ return CKR_FUNCTION_FAILED;
+
+ memcpy(&bbool, ref->ptr, sizeof(bbool));
+
+ mask = 1 << (shift % 32);
+ if (bbool == CK_TRUE)
+ value = mask;
+ else
+ value = 0;
+
+ /* Locate the current config value for the boolean property */
+ boolprop_ptr = obj->boolprop + (shift / 32);
+ sanity_ptr = sanity + (shift / 32);
+
+ /* Error if already set to a different boolean value */
+ if ((*sanity_ptr & mask) && value != (*boolprop_ptr & mask)) {
+ printf("Attribute %s redefined\n", cka2str(ref->id));
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ *sanity_ptr |= mask;
+ if (value)
+ *boolprop_ptr |= mask;
+ else
+ *boolprop_ptr &= ~mask;
+
+ return CKR_OK;
+}
+#endif /* SKS_WITH_BOOLPROP_ATTRIBS_IN_HEAD */
+
+/*
+ * Extract object generic attributes
+ * - all objects must provide at least a class
+ * - some classes expect a type
+ * - some classes can define generic boolean attributes (boolprops)
+ */
+static CK_RV serialize_generic_attributes(struct serializer *obj,
+ CK_ATTRIBUTE_PTR attributes,
+ CK_ULONG count)
+{
+ struct ck_ref *ref;
+ size_t n;
+ uint32_t sanity[SKS_MAX_BOOLPROP_ARRAY] = { 0 };
+ CK_RV rv = CKR_OK;
+ CK_ULONG class;
+
+ for (ref = (struct ck_ref *)attributes, n = 0; n < count; n++, ref++) {
+ if (ck_attr_is_class(ref->id))
+ rv = get_class(obj, ref);
+ if (rv)
+ return rv;
+ }
+
+ rv = sks2ck_object_class(&class, obj->object);
+ if (rv)
+ return rv;
+
+ for (ref = (struct ck_ref *)attributes, n = 0; n < count; n++, ref++) {
+ if (ck_attr_is_type(ref->id)) {
+ rv = get_type(obj, ref, class);
+ if (rv)
+ return rv;
+
+ continue;
+ }
+
+#ifdef SKS_WITH_BOOLPROP_ATTRIBS_IN_HEAD
+ if (sks_object_has_boolprop(obj->object) &&
+ ck_attr2boolprop_shift(ref->id) >= 0) {
+ rv = get_boolprop(obj, ref, sanity);
+ if (rv == CKR_NO_EVENT)
+ rv = CKR_OK;
+
+ if (rv)
+ return rv;
+
+ continue;
+ }
+#endif
+ }
+
+ return rv;
+}
+
+static int ck_attr_is_generic(CK_ULONG attribute_id)
+{
+ return (ck_attr_is_class(attribute_id) ||
+#ifdef SKS_WITH_BOOLPROP_ATTRIBS_IN_HEAD
+ (ck_attr2boolprop_shift(attribute_id) >= 0) ||
+#endif
+ ck_attr_is_type(attribute_id));
+}
+#endif /* SKS_WITH_GENERIC_ATTRIBS_IN_HEAD */
+
+/* CK attribute reference arguments are list of attribute item */
+CK_RV serialize_ck_attributes(struct serializer *obj,
+ CK_ATTRIBUTE_PTR attributes, CK_ULONG count)
+{
+ CK_ATTRIBUTE_PTR cur_attr = attributes;
+ CK_ULONG n = count;
+ CK_RV rv = CKR_OK;
+
+ rv = init_serial_object(obj);
+ if (rv)
+ return rv;
+
+#ifdef SKS_WITH_GENERIC_ATTRIBS_IN_HEAD
+ rv = serialize_generic_attributes(obj, attributes, count);
+ if (rv)
+ goto out;
+#endif
+
+ for (; n; n--, cur_attr++) {
+ CK_ATTRIBUTE attr;
+
+ memcpy(&attr, cur_attr, sizeof(attr));
+
+#ifdef SKS_WITH_GENERIC_ATTRIBS_IN_HEAD
+ if (ck_attr_is_generic(attr.type))
+ continue;
+#endif
+
+ rv = serialize_ck_attribute(obj, &attr);
+ if (rv)
+ goto out;
+ }
+
+out:
+ if (rv)
+ release_serial_object(obj);
+ else
+ finalize_serial_object(obj);
+
+ return rv;
+}
+
+static CK_RV deserialize_ck_attribute(struct sks_attribute_head *in,
+ CK_ATTRIBUTE_PTR out)
+{
+ CK_ULONG ck_ulong;
+ uint32_t sks_data32 = 0;
+ size_t n;
+ CK_RV rv;
+
+ rv = sks2ck_attribute_type(&(out->type), in->id);
+ if (rv)
+ return rv;
+
+ if (out->ulValueLen < in->size) {
+ out->ulValueLen = in->size;
+ return CKR_OK;
+ }
+
+ if (!out->pValue)
+ return CKR_OK;
+
+ /* Specific ulong encoded as 32bit in SKS TA API */
+ if (ck_attr_is_ulong(out->type)) {
+ if (out->ulValueLen != sizeof(CK_ULONG))
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+
+ memcpy(&sks_data32, in->data, sizeof(uint32_t));
+ }
+
+ switch (out->type) {
+ case CKA_CLASS:
+ rv = sks2ck_object_class(&ck_ulong, sks_data32);
+ if (rv)
+ return rv;
+ memcpy(out->pValue, &ck_ulong, sizeof(CK_ULONG));
+ break;
+
+ case CKA_KEY_TYPE:
+ rv = sks2ck_key_type(&ck_ulong, sks_data32);
+ if (rv)
+ return rv;
+ memcpy(out->pValue, &ck_ulong, sizeof(CK_ULONG));
+ break;
+
+ case CKA_CERTIFICATE_TYPE:
+ rv = sks2ck_certificate_type(&ck_ulong, sks_data32);
+ if (rv)
+ return rv;
+ memcpy(out->pValue, &ck_ulong, sizeof(CK_ULONG));
+ break;
+
+ case CKA_KEY_GEN_MECHANISM:
+ memcpy(&sks_data32, in->data, sizeof(uint32_t));
+ if (sks_data32 == SKS_CK_UNAVAILABLE_INFORMATION)
+ ck_ulong = CK_UNAVAILABLE_INFORMATION;
+ else
+ ck_ulong = sks_data32;
+ memcpy(out->pValue, &ck_ulong, sizeof(CK_ULONG));
+ rv = CKR_OK;
+ break;
+
+ case CKA_WRAP_TEMPLATE:
+ case CKA_UNWRAP_TEMPLATE:
+ rv = deserialize_indirect_attribute(in, out->pValue);
+ break;
+
+ case CKA_ALLOWED_MECHANISMS:
+ n = out->ulValueLen / sizeof(CK_ULONG);
+ rv = sks2ck_mechanism_type_list(out->pValue, in->data, n);
+ break;
+
+ /* Attributes which data value do not need conversion (aside ulong) */
+ default:
+ memcpy(out->pValue, in->data, in->size);
+ rv = CKR_OK;
+ break;
+ }
+
+ return rv;
+}
+
+CK_RV deserialize_ck_attributes(uint8_t *in, CK_ATTRIBUTE_PTR attributes,
+ CK_ULONG count)
+{
+ CK_ATTRIBUTE_PTR cur_attr = attributes;
+ CK_ULONG n;
+ CK_RV rv = CKR_OK;
+ uint8_t *curr_head = in;
+ size_t len;
+
+ curr_head += sizeof(struct sks_object_head);
+
+#ifdef SKS_WITH_GENERIC_ATTRIBS_IN_HEAD
+#error Not supported.
+#endif
+
+ for (n = count; n > 0; n--, cur_attr++, curr_head += len) {
+ struct sks_attribute_head *cli_ref =
+ (struct sks_attribute_head *)(void *)curr_head;
+
+ len = sizeof(*cli_ref);
+ /*
+ * Can't trust size becuase it was set to reflect
+ * required buffer.
+ */
+ if (cur_attr->pValue)
+ len += cli_ref->size;
+
+ rv = deserialize_ck_attribute(cli_ref, cur_attr);
+ if (rv)
+ goto out;
+ }
+
+out:
+ return rv;
+}
+
+/*
+ * Serialization of CK mechanism parameters
+ *
+ * Most mechanism have no parameters.
+ * Some mechanism have a single 32bit parameter.
+ * Some mechanism have a specific parameter structure which may contain
+ * indirected data (data referred by a buffer pointer).
+ *
+ * Below are each structure specific mechanisms parameters.
+ *
+ * Be careful that CK_ULONG based types translate to 32bit sks ulong fields.
+ */
+
+/*
+ * typedef struct CK_AES_CTR_PARAMS {
+ * CK_ULONG ulCounterBits;
+ * CK_BYTE cb[16];
+ * } CK_AES_CTR_PARAMS;
+ */
+static CK_RV serialize_mecha_aes_ctr(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_AES_CTR_PARAMS_PTR param = mecha->pParameter;
+ CK_RV rv;
+ uint32_t size;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ size = sizeof(uint32_t) + sizeof(param->cb);
+ rv = serialize_32b(obj, size);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_ulong(obj, param->ulCounterBits);
+ if (rv)
+ return rv;
+
+ rv = serialize_buffer(obj, param->cb, sizeof(param->cb));
+ if (rv)
+ return rv;
+
+ return rv;
+}
+
+/*
+ * typedef struct CK_GCM_PARAMS {
+ * CK_BYTE_PTR pIv;
+ * CK_ULONG ulIvLen;
+ * CK_ULONG ulIvBits; -> unused (deprecated?)
+ * CK_BYTE_PTR pAAD;
+ * CK_ULONG ulAADLen;
+ * CK_ULONG ulTagBits;
+ * } CK_GCM_PARAMS;
+ *
+ * Serialized:
+ * [uint32_t mechanism_id]
+ * [uint32_t parameters_byte_size = 3 * 8 + IV size + AAD size]
+ * [uint32_t iv_byte_size]
+ * [uint8_t iv[iv_byte_size]]
+ * [uint32_t aad_byte_size]
+ * [uint8_t aad[aad_byte_size]]
+ * [uint32_t tag_bit_size]
+ */
+static CK_RV serialize_mecha_aes_gcm(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_GCM_PARAMS_PTR param = mecha->pParameter;
+ CK_RV rv;
+ CK_ULONG aad_len;
+
+ /* AAD is not manadatory */
+ if (param->pAAD)
+ aad_len = param->ulAADLen;
+ else
+ aad_len = 0;
+
+ if (!param->pIv)
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, 3 * sizeof(uint32_t) +
+ param->ulIvLen + aad_len);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_ulong(obj, param->ulIvLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_buffer(obj, param->pIv, param->ulIvLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_ulong(obj, aad_len);
+ if (rv)
+ return rv;
+
+ rv = serialize_buffer(obj, param->pAAD, aad_len);
+ if (rv)
+ return rv;
+
+ return serialize_ck_ulong(obj, param->ulTagBits);
+}
+
+/*
+ * typedef struct CK_CCM_PARAMS {
+ * CK_ULONG ulDataLen;
+ * CK_BYTE_PTR pNonce;
+ * CK_ULONG ulNonceLen;
+ * CK_BYTE_PTR pAAD;
+ * CK_ULONG ulAADLen;
+ * CK_ULONG ulMACLen;
+ *} CK_CCM_PARAMS;
+ */
+static CK_RV serialize_mecha_aes_ccm(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_CCM_PARAMS_PTR param = mecha->pParameter;
+ CK_RV rv;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, 4 * sizeof(uint32_t) +
+ param->ulNonceLen + param->ulAADLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_ulong(obj, param->ulDataLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_ulong(obj, param->ulNonceLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_buffer(obj, param->pNonce, param->ulNonceLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_ck_ulong(obj, param->ulAADLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_buffer(obj, param->pAAD, param->ulAADLen);
+ if (rv)
+ return rv;
+
+ return serialize_ck_ulong(obj, param->ulMACLen);
+}
+
+static CK_RV serialize_mecha_aes_iv(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ uint32_t iv_size = mecha->ulParameterLen;
+ CK_RV rv;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, iv_size);
+ if (rv)
+ return rv;
+
+ return serialize_buffer(obj, mecha->pParameter, mecha->ulParameterLen);
+}
+
+static CK_RV serialize_mecha_ulong_param(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_RV rv;
+ uint32_t sks_data;
+ CK_ULONG ck_data;
+
+ memcpy(&ck_data, mecha->pParameter, mecha->ulParameterLen);
+ sks_data = ck_data;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ return serialize_32b(obj, sks_data);
+}
+
+static CK_RV serialize_mecha_ecdh1_derive_param(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_ECDH1_DERIVE_PARAMS *params = mecha->pParameter;
+ CK_RV rv;
+ size_t params_size = 3 * sizeof(uint32_t) + params->ulSharedDataLen +
+ params->ulPublicDataLen;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params_size);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, ck2sks_ec_kdf_type(params->kdf));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params->ulSharedDataLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_buffer(obj, params->pSharedData,
+ params->ulSharedDataLen);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params->ulPublicDataLen);
+ if (rv)
+ return rv;
+
+ return serialize_buffer(obj, params->pPublicData,
+ params->ulPublicDataLen);
+}
+
+static CK_RV serialize_mecha_ecdh_aes_key_wrap_param(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_ECDH_AES_KEY_WRAP_PARAMS *params = mecha->pParameter;
+ CK_RV rv;
+ size_t params_size = 3 * sizeof(uint32_t) + params->ulSharedDataLen;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params_size);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params->ulAESKeyBits);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, ck2sks_ec_kdf_type(params->kdf));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params->ulSharedDataLen);
+ if (rv)
+ return rv;
+
+ return serialize_buffer(obj, params->pSharedData,
+ params->ulSharedDataLen);
+}
+
+static CK_RV serialize_mecha_rsa_oaep_param(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_RSA_PKCS_OAEP_PARAMS *params = mecha->pParameter;
+ CK_RV rv;
+ size_t params_size = 4 * sizeof(uint32_t) + params->ulSourceDataLen;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params_size);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, ck2sks_mechanism_type(params->hashAlg));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, ck2sks_rsa_pkcs_mgf_type(params->mgf));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj,
+ ck2sks_rsa_pkcs_oaep_source_type(params->source));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params->ulSourceDataLen);
+ if (rv)
+ return rv;
+
+ return serialize_buffer(obj, params->pSourceData,
+ params->ulSourceDataLen);
+}
+
+static CK_RV serialize_mecha_rsa_pss_param(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_RSA_PKCS_PSS_PARAMS *params = mecha->pParameter;
+ CK_RV rv;
+ size_t params_size = 3 * sizeof(uint32_t);
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params_size);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, ck2sks_mechanism_type(params->hashAlg));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, ck2sks_rsa_pkcs_mgf_type(params->mgf));
+ if (rv)
+ return rv;
+
+ return serialize_32b(obj, params->sLen);
+}
+
+static CK_RV serialize_mecha_rsa_aes_key_wrap_param(struct serializer *obj,
+ CK_MECHANISM_PTR mecha)
+{
+ CK_RSA_AES_KEY_WRAP_PARAMS *params = mecha->pParameter;
+ CK_RSA_PKCS_OAEP_PARAMS *oaep_p = params->pOAEPParams;
+ CK_RV rv;
+ size_t params_size = 5 * sizeof(uint32_t) + params->pOAEPParams->ulSourceDataLen;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params_size);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, params->ulAESKeyBits);
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, ck2sks_mechanism_type(oaep_p->hashAlg));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, ck2sks_rsa_pkcs_mgf_type(oaep_p->mgf));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj,
+ ck2sks_rsa_pkcs_oaep_source_type(oaep_p->source));
+ if (rv)
+ return rv;
+
+ rv = serialize_32b(obj, oaep_p->ulSourceDataLen);
+ if (rv)
+ return rv;
+
+ return serialize_buffer(obj, oaep_p->pSourceData,
+ oaep_p->ulSourceDataLen);
+}
+
+/**
+ * serialize_ck_mecha_params - serialize a mechanism type & params
+ *
+ * @obj - serializer used to track the serialization
+ * @mechanism - pointer of the in structure aligned CK_MECHANISM.
+ *
+ * Serialized content:
+ * [sks-mechanism-type][sks-mechanism-param-blob]
+ *
+ * [sks-mechanism-param-blob] depends on mechanism type ID, see
+ * serialize_mecha_XXX().
+ */
+CK_RV serialize_ck_mecha_params(struct serializer *obj,
+ CK_MECHANISM_PTR mechanism)
+{
+ CK_MECHANISM mecha;
+ CK_RV rv;
+
+ memset(obj, 0, sizeof(*obj));
+
+ obj->object = SKS_CKO_MECHANISM;
+
+ memcpy(&mecha, mechanism, sizeof(mecha));
+ obj->type = ck2sks_mechanism_type(mecha.mechanism);
+ if (obj->type == SKS_UNDEFINED_ID)
+ return CKR_MECHANISM_INVALID;
+
+ switch (mecha.mechanism) {
+ case CKM_GENERIC_SECRET_KEY_GEN:
+ case CKM_AES_KEY_GEN:
+ case CKM_AES_ECB:
+ case CKM_AES_CMAC:
+ case CKM_MD5_HMAC:
+ case CKM_SHA_1_HMAC:
+ case CKM_SHA224_HMAC:
+ case CKM_SHA256_HMAC:
+ case CKM_SHA384_HMAC:
+ case CKM_SHA512_HMAC:
+ case CKM_AES_XCBC_MAC:
+ case CKM_AES_XCBC_MAC_96:
+ case CKM_EC_KEY_PAIR_GEN:
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ case CKM_ECDSA:
+ case CKM_ECDSA_SHA1:
+ case CKM_ECDSA_SHA224:
+ case CKM_ECDSA_SHA256:
+ case CKM_ECDSA_SHA384:
+ case CKM_ECDSA_SHA512:
+ case CKM_RSA_PKCS:
+ case CKM_RSA_9796:
+ case CKM_RSA_X_509:
+ case CKM_SHA1_RSA_PKCS:
+ case CKM_SHA256_RSA_PKCS:
+ case CKM_SHA384_RSA_PKCS:
+ case CKM_SHA512_RSA_PKCS:
+ case CKM_SHA224_RSA_PKCS:
+ case CKM_DES_KEY_GEN:
+ case CKM_MTK_HSM_AES_ECB:
+ case CKM_MTK_HSM_AES_CMAC:
+ case CKM_MTK_HSM_SHA256_HMAC:
+ case CKM_MTK_HSM_SHA384_HMAC:
+ case CKM_MTK_HSM_ECDSA:
+ case CKM_MTK_HSM_ECDSA_SHA1:
+ case CKM_MTK_HSM_ECDSA_SHA224:
+ case CKM_MTK_HSM_ECDSA_SHA256:
+ case CKM_MTK_HSM_ECDSA_SHA384:
+ case CKM_MTK_HSM_ECDSA_SHA512:
+ case CKM_MTK_HSM_SHA1:
+ case CKM_MTK_HSM_SHA224:
+ case CKM_MTK_HSM_SHA256:
+ case CKM_MTK_HSM_SHA384:
+ case CKM_MTK_HSM_SHA512:
+ case CKM_MTK_HSM_AES_KEY_GEN:
+ case CKM_MTK_HSM_EC_KEY_PAIR_GEN:
+ case CKM_MTK_HSM_EC_KEY_PAIR_IMPORT:
+ case CKM_MTK_HSM_DUMP_LOG:
+ /* No parameter expected, size shall be 0 */
+ if (mechanism->ulParameterLen)
+ return CKR_MECHANISM_PARAM_INVALID;
+
+ rv = serialize_32b(obj, obj->type);
+ if (rv)
+ return rv;
+
+ return serialize_32b(obj, 0);
+
+ case CKM_AES_CMAC_GENERAL:
+ return serialize_mecha_ulong_param(obj, &mecha);
+
+ case CKM_AES_CBC:
+ case CKM_AES_CBC_PAD:
+ case CKM_AES_CTS:
+ case CKM_MTK_HSM_AES_CBC:
+ return serialize_mecha_aes_iv(obj, &mecha);
+
+ case CKM_AES_CTR:
+ case CKM_MTK_HSM_AES_CTR:
+ return serialize_mecha_aes_ctr(obj, &mecha);
+
+ case CKM_AES_CCM:
+ return serialize_mecha_aes_ccm(obj, &mecha);
+
+ case CKM_AES_GCM:
+ case CKM_MTK_HSM_AES_GCM:
+ return serialize_mecha_aes_gcm(obj, &mecha);
+
+ case CKM_ECDH1_DERIVE:
+ case CKM_ECDH1_COFACTOR_DERIVE:
+ return serialize_mecha_ecdh1_derive_param(obj, &mecha);
+
+ case CKM_ECDH_AES_KEY_WRAP:
+ return serialize_mecha_ecdh_aes_key_wrap_param(obj, &mecha);
+
+ case CKM_RSA_PKCS_OAEP:
+ return serialize_mecha_rsa_oaep_param(obj, &mecha);
+
+ case CKM_RSA_PKCS_PSS:
+ case CKM_SHA1_RSA_PKCS_PSS:
+ case CKM_SHA256_RSA_PKCS_PSS:
+ case CKM_SHA384_RSA_PKCS_PSS:
+ case CKM_SHA512_RSA_PKCS_PSS:
+ case CKM_SHA224_RSA_PKCS_PSS:
+ return serialize_mecha_rsa_pss_param(obj, &mecha);
+
+ case CKM_RSA_AES_KEY_WRAP:
+ return serialize_mecha_rsa_aes_key_wrap_param(obj, &mecha);
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+}
+
+/*
+ * Debug: dump CK attribute array to output trace
+ */
+
+static CK_RV trace_attributes(char *prefix, void *src, void *end)
+{
+ size_t next = 0;
+ char *prefix2;
+ size_t prefix_len = strlen(prefix);
+ char *cur = src;
+
+ /* append 4 spaces to the prefix */
+ prefix2 = malloc(prefix_len + 1 + 4) ;
+ memcpy(prefix2, prefix, prefix_len + 1);
+ memset(prefix2 + prefix_len, ' ', 4);
+ *(prefix2 + prefix_len + 1 + 4) = '\0';
+
+ for (; cur < (char *)end; cur += next) {
+ struct sks_attribute_head ref;
+
+ memcpy(&ref, cur, sizeof(ref));
+ next = sizeof(ref) + ref.size;
+
+ LOG_DEBUG("%s attr 0x%" PRIx32 " (%" PRIu32" byte) : %02x %02x %02x %02x ...\n",
+ prefix, ref.id, ref.size,
+ *((char *)cur + sizeof(ref) + 0),
+ *((char *)cur + sizeof(ref) + 1),
+ *((char *)cur + sizeof(ref) + 2),
+ *((char *)cur + sizeof(ref) + 3));
+
+ switch (ref.id) {
+ case SKS_CKA_WRAP_TEMPLATE:
+ case SKS_CKA_UNWRAP_TEMPLATE:
+ serial_trace_attributes_from_head(prefix2,
+ cur + sizeof(ref));
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* sanity */
+ if (cur != (char *)end) {
+ LOG_ERROR("unexpected none alignement\n");
+ }
+
+ free(prefix2);
+ return CKR_OK;
+}
+
+CK_RV serial_trace_attributes_from_head(char *prefix, void *ref)
+{
+ struct sks_object_head head;
+ char *pre;
+ CK_RV rv;
+
+ memcpy(&head, ref, sizeof(head));
+
+ pre = calloc(1, prefix ? strlen(prefix) + 2 : 2) ;
+ if (!pre)
+ return CKR_HOST_MEMORY;
+ if (prefix)
+ memcpy(pre, prefix, strlen(prefix));
+
+ LOG_INFO("%s,--- (serial object) Attributes list --------\n", pre);
+ LOG_INFO("%s| %" PRIu32 " item(s) - %" PRIu32 " bytes\n", pre,
+ head.attrs_count, head.attrs_size);
+
+ pre[prefix ? strlen(prefix) + 1 : 0] = '|';
+
+ rv = trace_attributes(pre, (char *)ref + sizeof(head),
+ (char *)ref + sizeof(head) + head.attrs_size);
+ if (rv)
+ goto bail;
+
+ LOG_INFO("%s`-----------------------\n", prefix ? prefix : "");
+
+bail:
+ free(pre);
+ return rv;
+}
+
+CK_RV serial_trace_attributes(char *prefix, struct serializer *obj)
+{
+ return serial_trace_attributes_from_head(prefix, obj->buffer);
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serialize_ck.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serialize_ck.h
new file mode 100644
index 0000000..09c2b61
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serialize_ck.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __SERIALIZE_CK_H
+#define __SERIALIZE_CK_H
+
+#include <pkcs11.h>
+#include "serializer.h"
+
+/* Create (and allocate) a serial object for CK_ATTRIBUTE array */
+CK_RV serialize_ck_attributes(struct serializer *obj,
+ CK_ATTRIBUTE_PTR attributes, CK_ULONG count);
+
+/* Convert SKS attributes back to CK_ATTRIBUTE array */
+CK_RV deserialize_ck_attributes(uint8_t *in,
+ CK_ATTRIBUTE_PTR attributes, CK_ULONG count);
+
+/* Create (and allocate) a serial object for CK_MECHANISM array */
+CK_RV serialize_ck_mecha_params(struct serializer *obj,
+ CK_MECHANISM_PTR mechanisms);
+
+/* Log content of a serialized object */
+CK_RV serial_trace_attributes(char *prefix, struct serializer *obj);
+CK_RV serial_trace_attributes_from_head(char *prefix, void *ref);
+
+#endif /*__SERIALIZE_CK_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serializer.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serializer.c
new file mode 100644
index 0000000..eeaefda
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serializer.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sks_ta.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ck_helpers.h"
+#include "local_utils.h"
+#include "serializer.h"
+
+CK_RV init_serial_object(struct serializer *obj)
+{
+ struct sks_object_head head;
+
+ memset(obj, 0, sizeof(*obj));
+ obj->object = SKS_UNDEFINED_ID;
+ obj->type = SKS_UNDEFINED_ID;
+
+ /* Init head to all ones, will be set at finalize_serial_object */
+ memset(&head, 0xFF, sizeof(head));
+ return serialize_buffer(obj, &head, sizeof(head));
+}
+
+void finalize_serial_object(struct serializer *obj)
+{
+ struct sks_object_head head;
+
+ memset(&head, 0xFF, sizeof(head));
+
+#ifdef SKS_WITH_GENERIC_ATTRIBS_IN_HEAD
+fsdf fsd fsdf sdf
+ head.object = obj->object;
+ head.type = obj->type;
+#ifdef SKS_WITH_BOOLPROP_ATTRIBS_IN_HEAD
+ head.boolpropl = *((uint32_t *)obj->boolprop);
+ head.boolproph = *((uint32_t *)obj->boolprop + 1);
+#endif
+#endif
+ head.attrs_size = obj->size - sizeof(head);
+ head.attrs_count = obj->item_count;
+ memcpy(obj->buffer, &head, sizeof(head));
+}
+
+void release_serial_object(struct serializer *obj)
+{
+ free(obj->buffer);
+ obj->buffer = NULL;
+}
+
+/**
+ * serialize - append data in a serialized buffer
+ *
+ * Serialize data in provided buffer.
+ * Ensure 64byte alignement of appended data in the buffer.
+ */
+static CK_RV serialize(char **bstart, size_t *blen, void *data, size_t len)
+{
+ char *buf;
+ size_t nlen;
+
+ nlen = *blen + len;
+
+ buf = realloc(*bstart, nlen);
+ if (!buf)
+ return CKR_HOST_MEMORY;
+
+ memcpy(buf + *blen, data, len);
+
+ *blen = nlen;
+ *bstart = buf;
+
+ return CKR_OK;
+}
+
+CK_RV serialize_buffer(struct serializer *obj, void *data, size_t size)
+{
+ return serialize(&obj->buffer, &obj->size, data, size);
+}
+
+CK_RV serialize_32b(struct serializer *obj, uint32_t data)
+{
+ uint32_t data32 = data;
+
+ return serialize_buffer(obj, &data32, sizeof(uint32_t));
+}
+
+CK_RV serialize_ck_ulong(struct serializer *obj, CK_ULONG data)
+{
+ uint32_t data32 = data;
+
+ return serialize_buffer(obj, &data32, sizeof(data32));
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serializer.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serializer.h
new file mode 100644
index 0000000..2cdd7ce
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/host/src/serializer.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __SERIALIZER_H
+#define __SERIALIZER_H
+
+#include <pkcs11.h>
+#include <sks_ta.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#define SKS_MAX_BOOLPROP_SHIFT 64
+#define SKS_MAX_BOOLPROP_ARRAY (SKS_MAX_BOOLPROP_SHIFT / sizeof(uint32_t))
+
+/*
+ * Struct used to create the buffer storing the serialized data.
+ * Contains some fields to help parsing content (type/boolprops).
+ */
+struct serializer {
+ char *buffer; /* serial buffer base address */
+ size_t size; /* serial buffer current byte size */
+ size_t item_count; /* number of items in entry table */
+ uint32_t object;
+ uint32_t type;
+ uint32_t boolprop[SKS_MAX_BOOLPROP_ARRAY];
+};
+
+size_t get_serial_object_size(struct serializer *obj);
+
+/* Init/finalize/release a serializer object */
+CK_RV init_serial_object(struct serializer *obj);
+void finalize_serial_object(struct serializer *obj);
+void release_serial_object(struct serializer *obj);
+
+CK_RV serialize_buffer(struct serializer *obj, void *data, size_t size);
+CK_RV serialize_32b(struct serializer *obj, uint32_t data);
+CK_RV serialize_ck_ulong(struct serializer *obj, CK_ULONG data);
+
+/*
+ * Tools on already serialized object: input referenc is the serial object
+ * head address.
+ */
+
+/* Return the size of the serial blob head or 0 on error */
+size_t sizeof_serial_head(void *ref);
+
+/* Return the size of a serial object (head + attributes size) */
+size_t get_serial_size(void *ref);
+
+/* Return the class of the object or the invalid ID if not found */
+uint32_t serial_get_class(void *ref);
+
+/* Return the type of the object or the invalid ID if not found */
+uint32_t serial_get_type(void *ref);
+
+/* Get the location of target the attribute data and size */
+CK_RV serial_get_attribute_ptr(void *ref, uint32_t attribute,
+ void **attr, size_t *attr_size);
+
+/* Get target the attribute data content */
+CK_RV serial_get_attribute(void *ref, uint32_t attribute,
+ void *attr, size_t *attr_size);
+
+/*
+ * Same serial_get_attributes() in case an attribute is defined several
+ * times in the object (i.e several string identifiers for a single object)
+ * TODO.
+ */
+CK_RV serial_get_attribute_multi(void *ref, uint32_t attribute,
+ void *attr, size_t *attr_size);
+
+#endif /*__SERIALIZER_H*/
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/Makefile b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/Makefile
new file mode 100644
index 0000000..98a546f
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/Makefile
@@ -0,0 +1,22 @@
+# The UUID for the Trusted Application
+BINARY=fd02c9da-306c-48c7-a49c-bbd827ae86ee
+
+ifdef TA_CROSS_COMPILE
+CROSS_COMPILE ?= $(TA_CROSS_COMPILE)
+endif
+export CROSS_COMPILE
+
+CFG_TEE_TA_LOG_LEVEL ?= 2
+CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
+
+-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
+clean:
+ @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
+ @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
+endif
+
+.PHONY: install
+install:
+ cp $(BINARY).ta $(TADIR)/
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/hsm_job.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/hsm_job.h
new file mode 100644
index 0000000..9298849
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/hsm_job.h
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef __HSM_JOB_H__
+#define __HSM_JOB_H__
+
+typedef struct job_sturct_t
+{
+ uint32_t job_id;
+ uint32_t inputPtr;
+ uint32_t inputLength;
+ uint32_t secondaryInputPtr;
+ uint32_t secondaryInputLength;
+ uint32_t tertiaryInputPtr;
+ uint32_t tertiaryInputLength;
+ uint32_t outputPtr;
+ uint32_t outputLength;
+ uint32_t secondaryOutputPtr;
+ uint32_t secondaryOutputLength;
+ uint32_t cryptoKeyId;
+ uint32_t retValPtr;
+ uint16_t event_id;
+ uint16_t priority;
+ uint16_t keyLength;
+ uint8_t service;
+ uint8_t family;
+ uint8_t mode;
+ uint8_t operation_mode;
+
+} job_struct;
+
+#endif //__HSM_JOB_H__
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/hsm_mbox_if.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/hsm_mbox_if.h
new file mode 100644
index 0000000..6585f86
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/hsm_mbox_if.h
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __HSM_MBOX_IF_H__
+#define __HSM_MBOX_IF_H__
+
+#include <stdint.h>
+#include "hsm_job.h"
+
+#define HSM_IF_OK (0)
+#define HSM_IF_ERR_FAIL (-1)
+#define HSM_IF_ERR_TX_TIMEOUT (-2)
+
+#define FALSE 0
+#define TRUE 1
+
+#define PTA_MBOX_UUID {0x598e9628, 0xf233, 0x4c83, {0x8d, 0x4c, 0xbd, 0x2f, 0x0a, 0xd4, 0xb2, 0xe4}}
+
+#define PTA_CMD_HSM_GEN_KEY_PAIR 1
+#define PTA_CMD_HSM_GEN_SYMM_KEY 2
+#define PTA_CMD_HSM_GET_KEY_BLOB 3
+#define PTA_CMD_HSM_GET_KEY_TABLE 4
+#define PTA_CMD_HSM_REBUILD_KEY_TABLE 5
+#define PTA_CMD_HSM_REBUILD_KEY_BLOB 6
+#define PTA_CMD_HSM_IMPORT_KEY 7
+#define PTA_CMD_HSM_EXPORT_KEY 8
+#define PTA_CMD_HSM_SEND_JOB 9
+#define PTA_CMD_HSM_DUMP_LOG 10
+#define PTA_CMD_HSM_DELETE_KEY 11
+
+#endif //__HSM_MBOX_IF_H__
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/mtk_crypto.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/mtk_crypto.h
new file mode 100644
index 0000000..c541a63
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/mtk_crypto.h
@@ -0,0 +1,244 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef _TEST_CRYPTO_H_
+#define _TEST_CRYPTO_H_
+
+#include <stdint.h>
+
+#define HSM_TA_DEBUG 1
+
+#define COMMANDID_TEST_0 (0x56)
+#define COMMANDID_TEST_1 (0x78)
+#define COMMANDID_SKS_TA (0xDD)
+
+enum Crypto_OperationModeType
+{
+ CRYPTO_OPERATIONMODE_INVALID = 0x00,
+ CRYPTO_OPERATIONMODE_START = 0x01,
+ CRYPTO_OPERATIONMODE_UPDATE = 0x02,
+ CRYPTO_OPERATIONMODE_STREAMSTART = 0x03,
+ CRYPTO_OPERATIONMODE_FINISH = 0x04,
+ CRYPTO_OPERATIONMODE_SINGLECALL = 0x05,
+};
+
+enum Crypto_ServiceInfoType
+{
+ CRYPTO_HASH = 0x00,
+ CRYPTO_MACGENERATE = 0x01,
+ CRYPTO_MACVERIFY = 0x02,
+ CRYPTO_ENCRYPT = 0x03,
+ CRYPTO_DECRYPT = 0x04,
+
+// CRYPTO_AEADENCRYPT = 0x05,
+// CRYPTO_AEADDECRYPT = 0x06,
+
+ CRYPTO_SIGNATUREGENERATE = 0x07,
+ CRYPTO_SIGNATUREVERIFY = 0x08,
+ CRYPTO_SECCOUNTERINCREMENT = 0x09,
+ CRYPTO_SECCOUNTERREAD = 0x0A,
+ CRYPTO_RANDOMGENERATE = 0x0B,
+};
+
+enum Crypto_VerifyResultType
+{
+ CRYPTO_E_VER_OK = 0x00,
+ CRYPTO_E_VER_NOT_OK = 0x01,
+};
+
+enum Crypto_JobStateType
+{
+ CRYPTO_JOBSTATE_IDLE = 0x00,
+ CRYPTO_JOBSTATE_ACTIVE = 0x01,
+};
+
+struct Crypto_JobPrimitiveInputOutputType
+{
+ /*const*/ uint8_t *inputPtr;
+ uint32_t inputLength;
+ /*const*/ uint8_t *secondaryInputPtr;
+ uint32_t secondaryInputLength;
+ /*const*/ uint8_t *tertiaryInputPtr;
+ uint32_t tertiaryInputLength;
+ uint8_t *outputPtr;
+ uint32_t *outputLengthPtr;
+ uint8_t *secondaryOutputPtr;
+ uint32_t *secondaryOutputLengthPtr;
+ uint64_t input64;
+ enum Crypto_VerifyResultType *verifyPtr; // Ptr to
+ uint64_t *output64Ptr;
+ enum Crypto_OperationModeType mode;
+};
+
+enum Crypto_AlgorithmFamilyType
+{
+ CRYPTO_ALGOFAM_NOT_SET = 0x00,
+ CRYPTO_ALGOFAM_SHA1 = 0x01,
+ CRYPTO_ALGOFAM_SHA2_224 = 0x02,
+ CRYPTO_ALGOFAM_SHA2_256 = 0x03,
+ CRYPTO_ALGOFAM_SHA2_384 = 0x04,
+ CRYPTO_ALGOFAM_SHA2_512 = 0x05,
+ CRYPTO_ALGOFAM_AES = 0x14,
+ CRYPTO_ALGOFAM_ECCNIST = 0x19,
+ CRYPTO_ALGOFAM_SECURECOUNTER = 0x1A,
+ CRYPTO_ALGOFAM_RNG = 0x1B,
+};
+
+enum Crypto_AlgorithmModeType
+{
+ CRYPTO_ALGOMODE_NOT_SET = 0x00,
+ CRYPTO_ALGOMODE_ECB = 0x01,
+ CRYPTO_ALGOMODE_CBC = 0x02,
+ CRYPTO_ALGOMODE_CTR = 0x05,
+ CRYPTO_ALGOMODE_GCM = 0x06,
+ CRYPTO_ALGOMODE_XTS = 0x07,
+ CRYPTO_ALGOMODE_HMAC = 0x0F,
+ CRYPTO_ALGOMODE_CMAC = 0x10,
+ CRYPTO_ALGOMODE_GMAC = 0x11,
+ CRYPTO_ALGOMODE_CTRDRBG = 0x12,
+};
+
+struct Crypto_AlgorithmInfoType
+{
+ enum Crypto_AlgorithmFamilyType family;
+ enum Crypto_AlgorithmFamilyType secondaryFamily;
+ uint32_t keyLength;
+ enum Crypto_AlgorithmModeType mode;
+};
+
+struct Crypto_PrimitiveInfoType
+{
+ /*const*/ uint32_t resultLength;
+ /*const*/ enum Crypto_ServiceInfoType service;
+ /*const*/ struct Crypto_AlgorithmInfoType algorithm;
+};
+
+enum Crypto_ProcessingType
+{
+ CRYPTO_PROCESSING_ASYNC = 0x00,
+ CRYPTO_PROCESSING_SYNC = 0x01,
+};
+
+struct Crypto_JobPrimitiveInfoType
+{
+ /*const*/ uint32_t callbackId;
+ /*const*/ struct Crypto_PrimitiveInfoType *primitiveInfo;
+ /*const*/ uint32_t secureCounterId;
+ /*const*/ uint32_t cryIfKeyId;
+ /*const*/ enum Crypto_ProcessingType processingType;
+ /*const*/ uint8_t callbackUpdateNotification; // A boolean value
+};
+
+struct Crypto_JobInfoType
+{
+ /*const*/ uint32_t jobId;
+ /*const*/ uint32_t jobPriority;
+};
+
+struct Crypto_JobType
+{
+ /*const*/ uint32_t jobId;
+ enum Crypto_JobStateType jobState;
+ struct Crypto_JobPrimitiveInputOutputType jobPrimitiveInputOutput;
+ /*const*/ struct Crypto_JobPrimitiveInfoType *jobPrimitiveInfo;
+ /*const*/ struct Crypto_JobInfoType *jobInfo;
+ uint32_t cryptoKeyId;
+};
+
+typedef enum Std_ReturnType_t
+{
+ E_OK_1 = 0x00,
+ E_NOT_OK_1 = 0x01,
+ CRYPTO_E_BUSY = 0x02,
+ CRYPTO_E_SMALL_BUFFER = 0x03,
+ CRYPTO_E_ENTROPY_EXHAUSTION = 0x04,
+ CRYPTO_E_QUEUE_FULL = 0x05,
+ CRYPTO_E_KEY_READ_FAIL = 0x06,
+ CRYPTO_E_KEY_WRITE_FAIL = 0x07,
+ CRYPTO_E_KEY_NOT_AVAILABLE = 0x08,
+ CRYPTO_E_KEY_NOT_VALID = 0x09,
+ CRYPTO_E_KEY_SIZE_MISMATCH = 0x0A,
+ CRYPTO_E_COUNTER_OVERFLOW = 0x0B,
+ CRYPTO_E_JOB_CANCELED = 0x0C,
+} Std_ReturnType;
+
+struct Mtk_JobPrimitiveInfoType
+{
+ uint32_t callbackId;
+ struct Crypto_PrimitiveInfoType primitiveInfo;
+ uint32_t secureCounterId;
+ uint32_t cryIfKeyId;
+ enum Crypto_ProcessingType processingType;
+ uint8_t callbackUpdateNotification; // A boolean value
+};
+
+struct Mtk_JobPrimitiveInputOutputType
+{
+ uint8_t *inputPtr; // V -> P
+ uint32_t inputLength;
+ uint8_t *secondaryInputPtr; // V -> P
+ uint32_t secondaryInputLength;
+ uint8_t *tertiaryInputPtr; // V -> P
+ uint32_t tertiaryInputLength;
+ uint8_t *outputPtr; // V -> P
+ uint32_t outputLength;
+ uint8_t *secondaryOutputPtr; // V -> P
+ uint32_t secondaryOutputLength;
+// uint64_t input64;
+// enum Crypto_VerifyResultType *verifyPtr; // Ptr to
+// uint64_t *output64Ptr;
+// enum Crypto_OperationModeType mode;
+};
+
+struct Mtk_JobType
+{
+ uint32_t jobId;
+ enum Crypto_JobStateType jobState;
+ struct Mtk_JobPrimitiveInputOutputType jobPrimitiveInputOutput;
+ struct Mtk_JobPrimitiveInfoType jobPrimitiveInfo;
+ struct Crypto_JobInfoType jobInfo;
+ uint32_t cryptoKeyId;
+};
+
+uint8_t Mtk_ProcessJob // Std_ReturnType
+(
+ uint32_t objectId,
+ struct Mtk_JobType *job
+);
+
+
+#endif /* _TEST_CRYPTO_H_ */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/processor.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/processor.h
new file mode 100644
index 0000000..517b32a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/processor.h
@@ -0,0 +1,48 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef _PROCESSOR_H_
+#define _PROCESSOR_H_
+
+enum CPU_SERIAL {
+ CPU_SERIAL_CA53,
+ CPU_SERIAL_HSM,
+ CPU_SERIAL_CNT,
+ CPU_SERIAL_INVALID,
+};
+
+#endif /* _PROCESSOR_H_ */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/sks_internal_abi.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/sks_internal_abi.h
new file mode 100644
index 0000000..7c6ff89
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/sks_internal_abi.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __SKS_INTERNAL_ABI_H
+#define __SKS_INTERNAL_ABI_H
+
+/* Internal format is based on the API IDs */
+#include <sks_ta.h>
+#include <stddef.h>
+
+
+/**
+ * Serialization of object attributes
+ *
+ * An object is defined by the list of its attributes among which identifiers
+ * for the type of the object (symmetric key, asymmetric key, ...) and the
+ * object value (i.e the AES key value). In the end, an object is a list of
+ * attributes.
+ *
+ * SKS uses a serialized format for defining the attributes of an object. The
+ * attributes content starts with a header structure header followed by each
+ * attributes, stored in serialized fields:
+ * - the 32bit identifier of the attribute
+ * - the 32bit value attribute byte size
+ * - the effective value of the attribute (variable size)
+ */
+struct sks_ref {
+ uint32_t id;
+ uint32_t size;
+ uint8_t data[];
+};
+
+/*
+ * Header of a serialised memory object inside SKS TA.
+ *
+ * @attrs_size; byte size of the serialized data
+ * @attrs_count; number of items in the blob
+ * @class - object class id (from CK literature): key, certif, etc...
+ * @type - object type id, per class, i.e aes or des3 in the key class.
+ * @boolpropl - 32bit bitmask storing boolean properties #0 to #31.
+ * @boolproph - 32bit bitmask storing boolean properties #32 to #64.
+ * @attrs - then starts the blob binary data
+ */
+struct sks_attrs_head {
+ uint32_t attrs_size;
+ uint32_t attrs_count;
+#ifdef SKS_SHEAD_WITH_TYPE
+ uint32_t class;
+ uint32_t type;
+#endif
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ uint32_t boolpropl;
+ uint32_t boolproph;
+#endif
+ uint8_t attrs[];
+};
+
+#endif /*__SKS_INTERNAL_ABI_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/sks_ta.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/sks_ta.h
new file mode 100644
index 0000000..ce9917c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/sks_ta.h
@@ -0,0 +1,1139 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#ifndef __SKS_TA_H__
+#define __SKS_TA_H__
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#define TA_SKS_UUID { 0xfd02c9da, 0x306c, 0x48c7, \
+ { 0xa4, 0x9c, 0xbb, 0xd8, 0x27, 0xae, 0x86, 0xee } }
+
+/* SKS trusted application version information */
+#define SKS_VERSION_ID0 0
+#define SKS_VERSION_ID1 0
+
+/*
+ * SKS_CMD_PING Acknowledge TA presence and return TA version info
+ *
+ * Optional invocation parameter:
+ *
+ * [out] memref[2] = [
+ * 32bit version0 value,
+ * 32bit version1 value
+ * ]
+ */
+#define SKS_CMD_PING 0x00000000
+
+/*
+ * SKS_CMD_CK_SLOT_LIST - Get the table of the valid slot IDs
+ *
+ * [out] memref[2] = 32bit array slot_ids[slot counts]
+ *
+ * The TA instance may represent several PKCS#11 slots and associated tokens.
+ * This command relates the PKCS#11 API function C_GetSlotList and return the
+ * valid IDs recognized by the trusted application.
+ */
+#define SKS_CMD_CK_SLOT_LIST 0x00000001
+
+/*
+ * SKS_CMD_CK_SLOT_INFO - Get cryptoki structured slot information
+ *
+ * [in] memref[0] = 32bit slot ID
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = (struct sks_ck_slot_info)info
+ *
+ * The TA instance may represent several PKCS#11 slots and associated tokens.
+ * This command relates the PKCS#11 API function C_GetSlotInfo and return the
+ * information about the target slot.
+ */
+#define SKS_CMD_CK_SLOT_INFO 0x00000002
+
+#define SKS_SLOT_DESC_SIZE 64
+#define SKS_SLOT_MANUFACTURER_SIZE 32
+#define SKS_SLOT_VERSION_SIZE 2
+
+struct sks_slot_info {
+ uint8_t slotDescription[SKS_SLOT_DESC_SIZE];
+ uint8_t manufacturerID[SKS_SLOT_MANUFACTURER_SIZE];
+ uint32_t flags;
+ uint8_t hardwareVersion[SKS_SLOT_VERSION_SIZE];
+ uint8_t firmwareVersion[SKS_SLOT_VERSION_SIZE];
+};
+
+/*
+ * Values for sks_token_info::flags.
+ * SKS_CKFS_<x> corresponds to cryptoki flag CKF_<x> related to slot flags.
+ */
+#define SKS_CKFS_TOKEN_PRESENT (1U << 0)
+#define SKS_CKFS_REMOVABLE_DEVICE (1U << 1)
+#define SKS_CKFS_HW_SLOT (1U << 2)
+
+/*
+ * SKS_CMD_CK_TOKEN_INFO - Get cryptoki structured token information
+ *
+ * [in] memref[0] = 32bit slot ID
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = (struct sks_ck_token_info)info
+ *
+ * The TA instance may represent several PKCS#11 slots and associated tokens.
+ * This command relates the PKCS#11 API function C_GetTokenInfo and return the
+ * information about the target represented token.
+ */
+#define SKS_CMD_CK_TOKEN_INFO 0x00000003
+
+#define SKS_TOKEN_LABEL_SIZE 32
+#define SKS_TOKEN_MANUFACTURER_SIZE 32
+#define SKS_TOKEN_MODEL_SIZE 16
+#define SKS_TOKEN_SERIALNUM_SIZE 16
+
+struct sks_token_info {
+ uint8_t label[SKS_TOKEN_LABEL_SIZE];
+ uint8_t manufacturerID[SKS_TOKEN_MANUFACTURER_SIZE];
+ uint8_t model[SKS_TOKEN_MODEL_SIZE];
+ uint8_t serialNumber[SKS_TOKEN_SERIALNUM_SIZE];
+ uint32_t flags;
+ uint32_t ulMaxSessionCount;
+ uint32_t ulSessionCount;
+ uint32_t ulMaxRwSessionCount;
+ uint32_t ulRwSessionCount;
+ uint32_t ulMaxPinLen;
+ uint32_t ulMinPinLen;
+ uint32_t ulTotalPublicMemory;
+ uint32_t ulFreePublicMemory;
+ uint32_t ulTotalPrivateMemory;
+ uint32_t ulFreePrivateMemory;
+ uint8_t hardwareVersion[2];
+ uint8_t firmwareVersion[2];
+ uint8_t utcTime[16];
+};
+
+/*
+ * Values for sks_token_info::flags.
+ * SKS_CKFT_<x> corresponds to cryptoki CKF_<x> related to token flags.
+ */
+#define SKS_CKFT_RNG (1U << 0)
+#define SKS_CKFT_WRITE_PROTECTED (1U << 1)
+#define SKS_CKFT_LOGIN_REQUIRED (1U << 2)
+#define SKS_CKFT_USER_PIN_INITIALIZED (1U << 3)
+#define SKS_CKFT_RESTORE_KEY_NOT_NEEDED (1U << 4)
+#define SKS_CKFT_CLOCK_ON_TOKEN (1U << 5)
+#define SKS_CKFT_PROTECTED_AUTHENTICATION_PATH (1U << 6)
+#define SKS_CKFT_DUAL_CRYPTO_OPERATIONS (1U << 7)
+#define SKS_CKFT_TOKEN_INITIALIZED (1U << 8)
+#define SKS_CKFT_USER_PIN_COUNT_LOW (1U << 9)
+#define SKS_CKFT_USER_PIN_FINAL_TRY (1U << 10)
+#define SKS_CKFT_USER_PIN_LOCKED (1U << 11)
+#define SKS_CKFT_USER_PIN_TO_BE_CHANGED (1U << 12)
+#define SKS_CKFT_SO_PIN_COUNT_LOW (1U << 13)
+#define SKS_CKFT_SO_PIN_FINAL_TRY (1U << 14)
+#define SKS_CKFT_SO_PIN_LOCKED (1U << 15)
+#define SKS_CKFT_SO_PIN_TO_BE_CHANGED (1U << 16)
+#define SKS_CKFT_ERROR_STATE (1U << 17)
+
+/*
+ * SKS_CMD_CK_MECHANISM_IDS - Get list of the supported mechanisms
+ *
+ * [in] memref[0] = 32bit slot ID
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = 32bit array mechanism IDs
+ *
+ * This commands relates to the PKCS#11 API function C_GetMechanismList.
+ */
+#define SKS_CMD_CK_MECHANISM_IDS 0x00000004
+
+/*
+ * SKS_CMD_CK_MECHANISM_INFO - Get information on a specific mechanism
+ *
+ * [in] memref[0] = [
+ * 32bit slot ID,
+ * 32bit mechanism ID
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = (struct sks_mecha_info)info
+ *
+ * This commands relates to the PKCS#11 API function C_GetMechanismInfo.
+ */
+#define SKS_CMD_CK_MECHANISM_INFO 0x00000005
+
+struct sks_mechanism_info {
+ uint32_t min_key_size;
+ uint32_t max_key_size;
+ uint32_t flags;
+};
+
+/*
+ * Values for sks_mechanism_info::flags.
+ * SKS_CKFM_<x> strictly matches cryptoki CKF_<x> related to mechanism flags.
+ */
+#define SKS_CKFM_HW (1U << 0)
+#define SKS_CKFM_ENCRYPT (1U << 8)
+#define SKS_CKFM_DECRYPT (1U << 9)
+#define SKS_CKFM_DIGEST (1U << 10)
+#define SKS_CKFM_SIGN (1U << 11)
+#define SKS_CKFM_SIGN_RECOVER (1U << 12)
+#define SKS_CKFM_VERIFY (1U << 13)
+#define SKS_CKFM_VERIFY_RECOVER (1U << 14)
+#define SKS_CKFM_GENERATE (1U << 15)
+#define SKS_CKFM_GENERATE_PAIR (1U << 16)
+#define SKS_CKFM_WRAP (1U << 17)
+#define SKS_CKFM_UNWRAP (1U << 18)
+#define SKS_CKFM_DERIVE (1U << 19)
+#define SKS_CKFM_EC_F_P (1U << 20)
+#define SKS_CKFM_EC_F_2M (1U << 21)
+#define SKS_CKFM_EC_ECPARAMETERS (1U << 22)
+#define SKS_CKFM_EC_NAMEDCURVE (1U << 23)
+#define SKS_CKFM_EC_UNCOMPRESS (1U << 24)
+#define SKS_CKFM_EC_COMPRESS (1U << 25)
+
+/*
+ * SKS_CMD_CK_INIT_TOKEN - Initialize PKCS#11 token
+ *
+ * [in] memref[0] = [
+ * 32bit slot ID,
+ * 32bit PIN length,
+ * 8bit array PIN[PIN length],
+ * 8bit array label[32]
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * This commands relates to the PKCS#11 API function C_InitToken().
+ */
+#define SKS_CMD_CK_INIT_TOKEN 0x00000006
+
+/*
+ * SKS_CMD_CK_INIT_PIN - Initialize PKCS#11 token PIN
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit PIN length,
+ * 8bit array PIN[PIN length]
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * This commands relates to the PKCS#11 API function C_InitPIN().
+ */
+#define SKS_CMD_CK_INIT_PIN 0x00000007
+
+/*
+ * SKS_CMD_CK_SET_PIN - Set PKCS#11 token PIN
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit old_pin_length,
+ * 8bit array old_pin[old_pin_length],
+ * 32bit new_pin_length,
+ * 8bit array new_pin[new_pin_length]
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * This commands relates to the PKCS#11 API function C_SetPIN()
+ */
+#define SKS_CMD_CK_SET_PIN 0x00000008
+
+/*
+ * SKS_CMD_CK_OPEN_RO_SESSION - Open read-only session
+ *
+ * [in] memref[0] = 32bit slot ID
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[0] = 32bit session handle
+ *
+ * This commands relates to the PKCS#11 API function C_OpenSession() for a
+ * read-only session.
+ */
+#define SKS_CMD_CK_OPEN_RO_SESSION 0x00000009
+
+/*
+ * SKS_CMD_CK_OPEN_RW_SESSION - Open read/write session
+ *
+ * [in] memref[0] = 32bit slot
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[0] = 32bit session handle
+ *
+ * This commands relates to the PKCS#11 API function C_OpenSession() for a
+ * read/write session.
+ */
+#define SKS_CMD_CK_OPEN_RW_SESSION 0x0000000a
+
+/*
+ * SKS_CMD_CK_CLOSE_SESSION - Close an opened session
+ *
+ * [in] memref[0] = 32bit session handle
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * This commands relates to the PKCS#11 API function C_CloseSession().
+ */
+#define SKS_CMD_CK_CLOSE_SESSION 0x0000000b
+
+/*
+ * SKS_CMD_CK_SESSION_INFO - Get Cryptoki information on a session
+ *
+ * [in] memref[0] = 32bit session handle
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = (struct sks_ck_session_info)info
+ *
+ * This commands relates to the PKCS#11 API function C_GetSessionInfo().
+ */
+#define SKS_CMD_CK_SESSION_INFO 0x0000000c
+
+/*
+ * Values for sks_session_info::state.
+ * SKS_CKSS_<x> strictly matches cryptoki CKS_<x> related to session state.
+ */
+#define SKS_CKSS_RO_PUBLIC_SESSION 0
+#define SKS_CKSS_RO_USER_FUNCTIONS 1
+#define SKS_CKSS_RW_PUBLIC_SESSION 2
+#define SKS_CKSS_RW_USER_FUNCTIONS 3
+#define SKS_CKSS_RW_SO_FUNCTIONS 4
+
+struct sks_session_info {
+ uint32_t slot_id;
+ uint32_t state;
+ uint32_t flags;
+ uint32_t error_code;
+};
+
+/*
+ * Values for sks_session_info::flags.
+ * SKS_CKFS_<x> strictly matches cryptoki CKF_<x> related to session flags.
+ */
+#define SKS_CKFS_RW_SESSION (1U << 1)
+#define SKS_CKFS_SERIAL_SESSION (1U << 2)
+
+/*
+ * SKS_CMD_CK_CLOSE_ALL_SESSIONS - Close all client sessions on slot/token
+ *
+ * [in] memref[0] = 32bit slot
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * This commands relates to the PKCS#11 API function C_CloseAllSessions().
+ */
+#define SKS_CMD_CK_CLOSE_ALL_SESSIONS 0x0000000d
+
+/*
+ * SKS_CMD_IMPORT_OBJECT - Import a raw object in the session or token
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * (struct sks_object_head)attribs + attributes data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = 32bit object handle
+ *
+ * This commands relates to the PKCS#11 API function C_CreateObject().
+ */
+#define SKS_CMD_IMPORT_OBJECT 0x0000000e
+
+/**
+ * Serialization of object attributes
+ */
+
+/*
+ * sks_object_head - Header of object whose data are serialized in memory
+ *
+ * An object in made of several attributes. Attributes are store one next to
+ * the other with byte alignment as serialized byte arrays. Appended
+ * attributes byte arrays are prepend with this header structure that
+ * defines the number of attribute items and the overall byte size of the
+ * attrs byte array.
+ *
+ * @attrs_size - byte size of whole byte array attrs[]
+ * @attrs_count - number of attribute items stored in attrs[]
+ * @attrs - then starts the attributes data
+ */
+struct sks_object_head {
+ uint32_t attrs_size;
+ uint32_t attrs_count;
+ uint8_t attrs[];
+};
+
+/*
+ * Attribute reference in the TA ABI. Each attribute start with the header
+ * structure followed by the attribute value, its byte size being defined
+ * in the attribute header.
+ *
+ * @id - the 32bit identifier of the attribute, see SKS_CKA_<x>
+ * @size - the 32bit value attribute byte size
+ * @data - then starts the attribute value
+ */
+struct sks_attribute_head {
+ uint32_t id;
+ uint32_t size;
+ uint8_t data[];
+};
+
+/*
+ * SKS_CMD_DESTROY_OBJECT - Destroy an object
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit object handle
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * This commands relates to the PKCS#11 API function C_DestroyObject().
+ */
+#define SKS_CMD_DESTROY_OBJECT 0x0000000f
+
+/*
+ * SKS_CMD_ENCRYPT_INIT - Initialize encryption processing
+ * SKS_CMD_DECRYPT_INIT - Initialize decryption processing
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * (struct sks_attribute_head)mechanism + mecha parameters
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * These commands relate to the PKCS#11 API functions C_EncryptInit() and
+ * C_DecryptInit.
+ */
+#define SKS_CMD_ENCRYPT_INIT 0x00000010
+#define SKS_CMD_DECRYPT_INIT 0x00000011
+
+/*
+ * SKS_CMD_ENCRYPT_UPDATE - Update encryption processing
+ * SKS_CMD_DECRYPT_UPDATE - Update decryption processing
+ *
+ * [in] memref[0] = 32bit session handle
+ * [in] memref[1] = input data to be processed
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = output processed data
+ *
+ * These commands relate to the PKCS#11 API functions C_EncryptUpdate() and
+ * C_DecryptUpdate.
+ */
+#define SKS_CMD_ENCRYPT_UPDATE 0x00000012
+#define SKS_CMD_DECRYPT_UPDATE 0x00000013
+
+/*
+ * SKS_CMD_ENCRYPT_FINAL - Finalize encryption processing
+ * SKS_CMD_DECRYPT_FINAL - Finalize decryption processing
+ *
+ * [in] memref[0] = 32bit session handle
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = output processed data
+ *
+ * These commands relate to the PKCS#11 API functions C_EncryptFinal() and
+ * C_DecryptFinal.
+ */
+#define SKS_CMD_ENCRYPT_FINAL 0x00000014
+#define SKS_CMD_DECRYPT_FINAL 0x00000015
+
+/*
+ * SKS_CMD_GENERATE_SYMM_KEY - Generate a symmetric key
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * (struct sks_attribute_head)mechanism + mecha parameters,
+ * (struct sks_object_head)attribs + attributes data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = 32bit key handle
+ *
+ * This command relates to the PKCS#11 API functions C_GenerateKey().
+ */
+#define SKS_CMD_GENERATE_SYMM_KEY 0x00000016
+
+/*
+ * SKS_CMD_SIGN_INIT - Initialize a signature computation processing
+ * SKS_CMD_VERIFY_INIT - Initialize a signature verification processing
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit key handle,
+ * (struct sks_attribute_head)mechanism + mecha parameters,
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * These commands relate to the PKCS#11 API functions C_SignInit() and
+ * C_VerifyInit.
+ */
+#define SKS_CMD_SIGN_INIT 0x00000017
+#define SKS_CMD_VERIFY_INIT 0x00000018
+
+/*
+ * SKS_CMD_SIGN_UPDATE - Update a signature computation processing
+ * SKS_CMD_VERIFY_UPDATE - Update a signature verification processing
+ *
+ * [in] memref[0] = 32bit session handle
+ * [in] memref[1] = input data to be processed
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * These commands relate to the PKCS#11 API functions C_SignUpdate() and
+ * C_VerifyUpdate.
+ */
+#define SKS_CMD_SIGN_UPDATE 0x00000019
+#define SKS_CMD_VERIFY_UPDATE 0x0000001a
+
+/*
+ * SKS_CMD_SIGN_FINAL - Finalize a signature computation processing
+ * SKS_CMD_VERIFY_FINAL - Finalize a signature verification processing
+ *
+ * [in] memref[0] = 32bit session handle
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = output processed data
+ *
+ * These commands relate to the PKCS#11 API functions C_SignFinal() and
+ * C_VerifyFinal.
+ */
+#define SKS_CMD_SIGN_FINAL 0x0000001b
+#define SKS_CMD_VERIFY_FINAL 0x0000001c
+
+/*
+ * SKS_CMD_FIND_OBJECTS_INIT - Initialize a objects search
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * (struct sks_object_head)attribs + attributes data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * This command relates to the PKCS#11 API function C_FindOjectsInit().
+ */
+#define SKS_CMD_FIND_OBJECTS_INIT 0x0000001d
+
+/*
+ * SKS_CMD_FIND_OBJECTS - Get handles of matching objects
+ *
+ * [in] memref[0] = 32bit session handle
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = 32bit array object_handle_array[N]
+ *
+ * This command relates to the PKCS#11 API function C_FindOjects().
+ * The size of object_handle_array depends output buffer size
+ * provided by the client.
+ */
+#define SKS_CMD_FIND_OBJECTS 0x0000001e
+
+/*
+ * SKS_CMD_FIND_OBJECTS_FINAL - Finalize current objects search
+ *
+ * [in] memref[0] = 32bit session handle
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * This command relates to the PKCS#11 API function C_FindOjectsFinal().
+ */
+#define SKS_CMD_FIND_OBJECTS_FINAL 0x0000001f
+
+/*
+ * SKS_CMD_GET_OBJECT_SIZE - Get size used by object in the TEE
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit key handle
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = 32bit object_byte_size
+ */
+#define SKS_CMD_GET_OBJECT_SIZE 0x00000020
+
+/*
+ * SKS_CMD_GET_ATTRIBUTE_VALUE - Get the value of object attribute(s)
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit object handle,
+ * (struct sks_object_head)attribs + attributes data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = (struct sks_object_head)attribs + attributes data
+ */
+#define SKS_CMD_GET_ATTRIBUTE_VALUE 0x00000021
+
+/*
+ * SKS_CMD_SET_ATTRIBUTE_VALUE - Set the value for object attribute(s)
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit object handle,
+ * (struct sks_object_head)attribs + attributes data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = (struct sks_object_head)attribs + attributes data
+ */
+#define SKS_CMD_SET_ATTRIBUTE_VALUE 0x00000022
+
+/*
+ * SKS_CMD_DERIVE_KEY - Derive a key from already provisioned parent key
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * (struct sks_attribute_head)mechanism + mecha parameters,
+ * 32bit key handle,
+ * (struct sks_object_head)attribs + attributes data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = 32bit object handle
+ */
+#define SKS_CMD_DERIVE_KEY 0x00000023
+
+/*
+ * SKS_CMD_INIT_PIN - Initialize user PIN
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit PIN byte size,
+ * byte arrays: PIN data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ */
+#define SKS_CMD_INIT_PIN 0x00000024
+
+/*
+ * SKS_CMD_SET_PIN - Change user PIN
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit old PIN byte size,
+ * byte arrays: PIN data
+ * 32bit new PIN byte size,
+ * byte arrays: new PIN data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ */
+#define SKS_CMD_SET_PIN 0x00000025
+
+/*
+ * SKS_CMD_LOGIN - Initialize user PIN
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit user identifier,
+ * 32bit PIN byte size,
+ * byte arrays: PIN data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ */
+#define SKS_CMD_LOGIN 0x00000026
+
+/*
+ * Values for user identifier parameter in SKS_CMD_LOGIN
+ */
+#define SKS_CKU_SO 0x000
+#define SKS_CKU_USER 0x001
+#define SKS_CKU_CONTEXT_SPECIFIC 0x002
+
+/*
+ * SKS_CMD_LOGOUT - Log out from token
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit PIN byte size,
+ * byte array: PIN data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ */
+#define SKS_CMD_LOGOUT 0x00000027
+
+/*
+ * SKS_CMD_GENERATE_KEY_PAIR - Generate an asymmetric key pair
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * (struct sks_attribute_head)mechanism + mecha parameters,
+ * (struct sks_object_head)pubkey_attribs + attributes data
+ * (struct sks_object_head)privkeyattribs + attributes data
+ * ]
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = [
+ * 32bit public key handle,
+ * 32bit prive key handle
+ * ]
+ *
+ * This command relates to the PKCS#11 API functions C_GenerateKeyPair().
+ */
+#define SKS_CMD_GENERATE_KEY_PAIR 0x00000028
+
+/*
+ * SKS_CMD_ENCRYPT_ONESHOT - Update and finalize encryption processing
+ * SKS_CMD_DECRYPT_ONESHOT - Update and finalize decryption processing
+ *
+ * [in] memref[0] = 32bit session handle
+ * [in] memref[1] = input data to be processed
+ * [out] memref[0] = 32bit fine grain return code
+ * [out] memref[2] = output processed data
+ *
+ * These commands relate to the PKCS#11 API functions C_EncryptUpdate() and
+ * C_DecryptUpdate.
+ */
+#define SKS_CMD_ENCRYPT_ONESHOT 0x00000029
+#define SKS_CMD_DECRYPT_ONESHOT 0x0000002a
+
+/*
+ * SKS_CMD_SIGN_ONESHOT - Update and finalize a signature computation
+ * SKS_CMD_VERIFY_ONESHOT - Update and finalize a signature verification
+ *
+ * [in] memref[0] = 32bit session handle
+ * [in] memref[1] = input data to be processed
+ * [out] memref[0] = 32bit fine grain return code
+ *
+ * These commands relate to the PKCS#11 API functions C_SignUpdate() and
+ * C_VerifyUpdate.
+ */
+#define SKS_CMD_SIGN_ONESHOT 0x0000002b
+#define SKS_CMD_VERIFY_ONESHOT 0x0000002c
+
+#define SKS_CMD_DIGEST_INIT 0x0000002d
+#define SKS_CMD_DIGEST_ONESHOT 0x0000002e
+#define SKS_CMD_DIGEST_UPDATE 0x0000002f
+#define SKS_CMD_DIGEST_FINAL 0x00000030
+
+#define SKS_CMD_GENERATE_RANDOM 0x00000031
+
+#define SKS_CMD_IMPORT_KEY 0x00000032
+#define SKS_CMD_IMPORT_KEY_PAIR 0x00000033
+#define SKS_CMD_EXPORT_KEY 0x00000034
+
+#define SKS_CMD_UTILS 0x00000035
+
+/*
+ * Command return codes
+ * SKS_CKR_<x> relates cryptoki CKR_<x> in meaning if not in value.
+ */
+#define SKS_CKR_OK 0x00000000
+#define SKS_CKR_GENERAL_ERROR 0x00000001
+#define SKS_CKR_DEVICE_MEMORY 0x00000002
+#define SKS_CKR_ARGUMENTS_BAD 0x00000003
+#define SKS_CKR_BUFFER_TOO_SMALL 0x00000004
+#define SKS_CKR_FUNCTION_FAILED 0x00000005
+#define SKS_CKR_SIGNATURE_INVALID 0x00000007
+#define SKS_CKR_ATTRIBUTE_TYPE_INVALID 0x00000008
+#define SKS_CKR_ATTRIBUTE_VALUE_INVALID 0x00000009
+#define SKS_CKR_OBJECT_HANDLE_INVALID 0x0000000a
+#define SKS_CKR_KEY_HANDLE_INVALID 0x0000000b
+#define SKS_CKR_MECHANISM_INVALID 0x0000000c
+#define SKS_CKR_SESSION_HANDLE_INVALID 0x0000000d
+#define SKS_CKR_SLOT_ID_INVALID 0x0000000e
+#define SKS_CKR_MECHANISM_PARAM_INVALID 0x0000000f
+#define SKS_CKR_TEMPLATE_INCONSISTENT 0x00000010
+#define SKS_CKR_TEMPLATE_INCOMPLETE 0x00000011
+#define SKS_CKR_PIN_INCORRECT 0x00000012
+#define SKS_CKR_PIN_LOCKED 0x00000013
+#define SKS_CKR_PIN_EXPIRED 0x00000014
+#define SKS_CKR_PIN_INVALID 0x00000015
+#define SKS_CKR_PIN_LEN_RANGE 0x00000016
+#define SKS_CKR_SESSION_EXISTS 0x00000017
+#define SKS_CKR_SESSION_READ_ONLY 0x00000018
+#define SKS_CKR_SESSION_READ_WRITE_SO_EXISTS 0x00000019
+#define SKS_CKR_OPERATION_ACTIVE 0x0000001a
+#define SKS_CKR_KEY_FUNCTION_NOT_PERMITTED 0x0000001b
+#define SKS_CKR_OPERATION_NOT_INITIALIZED 0x0000001c
+#define SKS_CKR_TOKEN_WRITE_PROTECTED 0x0000001d
+#define SKS_CKR_TOKEN_NOT_PRESENT 0x0000001e
+#define SKS_CKR_TOKEN_NOT_RECOGNIZED 0x0000001f
+#define SKS_CKR_ACTION_PROHIBITED 0x00000020
+#define SKS_CKR_ATTRIBUTE_READ_ONLY 0x00000021
+#define SKS_CKR_PIN_TOO_WEAK 0x00000022
+#define SKS_CKR_CURVE_NOT_SUPPORTED 0x00000023
+#define SKS_CKR_DOMAIN_PARAMS_INVALID 0x00000024
+#define SKS_CKR_USER_ALREADY_LOGGED_IN 0x00000025
+#define SKS_CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000026
+#define SKS_CKR_USER_NOT_LOGGED_IN 0x00000027
+#define SKS_CKR_USER_PIN_NOT_INITIALIZED 0x00000028
+#define SKS_CKR_USER_TOO_MANY_TYPES 0x00000029
+#define SKS_CKR_USER_TYPE_INVALID 0x0000002a
+#define SKS_CKR_SESSION_READ_ONLY_EXISTS 0x0000002b
+#define SKS_CKR_KEY_SIZE_RANGE 0x0000002c
+#define SKS_CKR_ATTRIBUTE_SENSITIVE 0x0000002d
+#define SKS_CKR_SIGNATURE_LEN_RANGE 0x0000002e
+#define SKS_CKR_KEY_TYPE_INCONSISTENT 0x0000002f
+#define SKS_CKR_DATA_LEN_RANGE 0x00000030
+#define SKS_CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000031
+
+/* Status without strict equivalence in Cryptoki API */
+#define SKS_NOT_FOUND 0x00001000
+#define SKS_NOT_IMPLEMENTED 0x00001001
+
+/* Attribute specific values */
+#define SKS_CK_UNAVAILABLE_INFORMATION ((uint32_t)0xFFFFFFFF)
+#define SKS_UNDEFINED_ID SKS_CK_UNAVAILABLE_INFORMATION
+#define SKS_FALSE 0
+#define SKS_TRUE 1
+
+/*
+ * Attribute identifiers
+ * Valid values for struct sks_attribute_head::id
+ *
+ * SKS_ATTR_<x> corresponds to cryptoki CKA_<x>.
+ * Value range [0 63] is reserved to boolean value attributes.
+ */
+#define SKS_BOOLPROPS_BASE 0x00000000
+#define SKS_CKA_TOKEN 0x00000000
+#define SKS_CKA_PRIVATE 0x00000001
+#define SKS_CKA_TRUSTED 0x00000002
+#define SKS_CKA_SENSITIVE 0x00000003
+#define SKS_CKA_ENCRYPT 0x00000004
+#define SKS_CKA_DECRYPT 0x00000005
+#define SKS_CKA_WRAP 0x00000006
+#define SKS_CKA_UNWRAP 0x00000007
+#define SKS_CKA_SIGN 0x00000008
+#define SKS_CKA_SIGN_RECOVER 0x00000009
+#define SKS_CKA_VERIFY 0x0000000a
+#define SKS_CKA_VERIFY_RECOVER 0x0000000b
+#define SKS_CKA_DERIVE 0x0000000c
+#define SKS_CKA_EXTRACTABLE 0x0000000d
+#define SKS_CKA_LOCAL 0x0000000e
+#define SKS_CKA_NEVER_EXTRACTABLE 0x0000000f
+#define SKS_CKA_ALWAYS_SENSITIVE 0x00000010
+#define SKS_CKA_MODIFIABLE 0x00000011
+#define SKS_CKA_COPYABLE 0x00000012
+#define SKS_CKA_DESTROYABLE 0x00000013
+#define SKS_CKA_ALWAYS_AUTHENTICATE 0x00000014
+#define SKS_CKA_WRAP_WITH_TRUSTED 0x00000015
+/* Last boolean property ID (value is 63) is reserved */
+#define SKS_BOOLPROPS_LAST SKS_CKA_WRAP_WITH_TRUSTED
+#define SKS_BOOLPROPS_END 0x0000003F
+#define SKS_BOOLPROPH_FLAG BIT(31)
+
+#define SKS_CKA_LABEL 0x00000040
+#define SKS_CKA_VALUE 0x00000041
+#define SKS_CKA_VALUE_LEN 0x00000042
+#define SKS_CKA_WRAP_TEMPLATE 0x00000043
+#define SKS_CKA_UNWRAP_TEMPLATE 0x00000044
+#define SKS_CKA_DERIVE_TEMPLATE 0x00000045
+#define SKS_CKA_START_DATE 0x00000046
+#define SKS_CKA_END_DATE 0x00000047
+#define SKS_CKA_OBJECT_ID 0x00000048
+#define SKS_CKA_APPLICATION 0x00000049
+#define SKS_CKA_MECHANISM_TYPE 0x0000004a
+#define SKS_CKA_ID 0x0000004b
+#define SKS_CKA_ALLOWED_MECHANISMS 0x0000004c
+#define SKS_CKA_CLASS 0x0000004d
+#define SKS_CKA_KEY_TYPE 0x0000004e
+#define SKS_CKA_EC_POINT 0x0000004f
+#define SKS_CKA_EC_PARAMS 0x00000050
+#define SKS_CKA_MODULUS 0x00000051
+#define SKS_CKA_MODULUS_BITS 0x00000052
+#define SKS_CKA_PUBLIC_EXPONENT 0x00000053
+#define SKS_CKA_PRIVATE_EXPONENT 0x00000054
+#define SKS_CKA_PRIME_1 0x00000055
+#define SKS_CKA_PRIME_2 0x00000056
+#define SKS_CKA_EXPONENT_1 0x00000057
+#define SKS_CKA_EXPONENT_2 0x00000058
+#define SKS_CKA_COEFFICIENT 0x00000059
+#define SKS_CKA_SUBJECT 0x0000005a
+#define SKS_CKA_PUBLIC_KEY_INFO 0x0000005b
+#define SKS_CKA_CERTIFICATE_TYPE 0x0000005c
+#define SKS_CKA_CERTIFICATE_CATEGORY 0x0000005d
+#define SKS_CKA_ISSUER 0x0000005e
+#define SKS_CKA_SERIAL_NUMBER 0x0000005f
+#define SKS_CKA_URL 0x00000060
+#define SKS_CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x00000061
+#define SKS_CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x00000062
+#define SKS_CKA_NAME_HASH_ALGORITHM 0x00000063
+#define SKS_CKA_KEY_GEN_MECHANISM 0x00000064
+#define SKS_CKA_HSM_KEY_ID 0x00000065
+#define SKS_CKA_HSM_KEY_LEN 0x00000066
+
+/*
+ * Valid values for attribute SKS_CKA_CLASS
+ * SKS_CKO_<x> corresponds to cryptoki CKO_<x>.
+ */
+#define SKS_CKO_SECRET_KEY 0x000
+#define SKS_CKO_PUBLIC_KEY 0x001
+#define SKS_CKO_PRIVATE_KEY 0x002
+#define SKS_CKO_OTP_KEY 0x003
+#define SKS_CKO_CERTIFICATE 0x004
+#define SKS_CKO_DATA 0x005
+#define SKS_CKO_DOMAIN_PARAMETERS 0x006
+#define SKS_CKO_HW_FEATURE 0x007
+#define SKS_CKO_MECHANISM 0x008
+
+/*
+ * Valid values for attribute SKS_CKA_KEY_TYPE
+ * SKS_CKK_<x> corresponds to cryptoki CKK_<x> related to symmetric keys
+ */
+#define SKS_CKK_AES 0x000
+#define SKS_CKK_GENERIC_SECRET 0x001
+#define SKS_CKK_MD5_HMAC 0x002
+#define SKS_CKK_SHA_1_HMAC 0x003
+#define SKS_CKK_SHA224_HMAC 0x004
+#define SKS_CKK_SHA256_HMAC 0x005
+#define SKS_CKK_SHA384_HMAC 0x006
+#define SKS_CKK_SHA512_HMAC 0x007
+#define SKS_CKK_EC 0x008
+#define SKS_CKK_RSA 0x009
+#define SKS_CKK_DSA 0x00a
+#define SKS_CKK_DH 0x00b
+#define SKS_CKK_DES 0x00c
+#define SKS_CKK_DES2 0x00d
+#define SKS_CKK_DES3 0x00e
+
+/*
+ * Valid values for attribute SKS_CKA_CERTIFICATE_TYPE
+ * SKS_CKC_<x> corresponds to cryptoki CKC_<x>.
+ */
+#define SKS_CKC_X_509 0x000
+#define SKS_CKC_X_509_ATTR_CER 0x001
+#define SKS_CKC_WTLS 0x002
+
+/*
+ * Valid values for attribute SKS_CKA_MECHANISM_TYPE
+ * SKS_CKM_<x> corresponds to cryptoki CKM_<x>.
+ */
+#define SKS_CKM_AES_ECB 0x000
+#define SKS_CKM_AES_CBC 0x001
+#define SKS_CKM_AES_CBC_PAD 0x002
+#define SKS_CKM_AES_CTS 0x003
+#define SKS_CKM_AES_CTR 0x004
+#define SKS_CKM_AES_GCM 0x005
+#define SKS_CKM_AES_CCM 0x006
+#define SKS_CKM_AES_GMAC 0x007
+#define SKS_CKM_AES_CMAC 0x008
+#define SKS_CKM_AES_CMAC_GENERAL 0x009
+#define SKS_CKM_AES_ECB_ENCRYPT_DATA 0x00a
+#define SKS_CKM_AES_CBC_ENCRYPT_DATA 0x00b
+#define SKS_CKM_AES_KEY_GEN 0x00c
+#define SKS_CKM_GENERIC_SECRET_KEY_GEN 0x00d
+#define SKS_CKM_MD5_HMAC 0x00e
+#define SKS_CKM_SHA_1_HMAC 0x00f
+#define SKS_CKM_SHA224_HMAC 0x010
+#define SKS_CKM_SHA256_HMAC 0x011
+#define SKS_CKM_SHA384_HMAC 0x012
+#define SKS_CKM_SHA512_HMAC 0x013
+#define SKS_CKM_AES_XCBC_MAC 0x014
+#define SKS_CKM_EC_KEY_PAIR_GEN 0x015
+#define SKS_CKM_ECDSA 0x016
+#define SKS_CKM_ECDSA_SHA1 0x017
+#define SKS_CKM_ECDSA_SHA224 0x018 /* /!\ CK !PKCS#11 */
+#define SKS_CKM_ECDSA_SHA256 0x019 /* /!\ CK !PKCS#11 */
+#define SKS_CKM_ECDSA_SHA384 0x01a /* /!\ CK !PKCS#11 */
+#define SKS_CKM_ECDSA_SHA512 0x01b /* /!\ CK !PKCS#11 */
+#define SKS_CKM_ECDH1_DERIVE 0x01c
+#define SKS_CKM_ECDH1_COFACTOR_DERIVE 0x01d
+#define SKS_CKM_ECMQV_DERIVE 0x01e
+#define SKS_CKM_ECDH_AES_KEY_WRAP 0x01f
+#define SKS_CKM_RSA_PKCS_KEY_PAIR_GEN 0x020
+#define SKS_CKM_RSA_PKCS 0x021
+#define SKS_CKM_RSA_9796 0x022
+#define SKS_CKM_RSA_X_509 0x023
+#define SKS_CKM_SHA1_RSA_PKCS 0x024
+#define SKS_CKM_RSA_PKCS_OAEP 0x025
+#define SKS_CKM_SHA1_RSA_PKCS_PSS 0x026
+#define SKS_CKM_SHA256_RSA_PKCS 0x027
+#define SKS_CKM_SHA384_RSA_PKCS 0x028
+#define SKS_CKM_SHA512_RSA_PKCS 0x029
+#define SKS_CKM_SHA256_RSA_PKCS_PSS 0x02a
+#define SKS_CKM_SHA384_RSA_PKCS_PSS 0x02b
+#define SKS_CKM_SHA512_RSA_PKCS_PSS 0x02c
+#define SKS_CKM_SHA224_RSA_PKCS 0x02d
+#define SKS_CKM_SHA224_RSA_PKCS_PSS 0x02e
+#define SKS_CKM_RSA_AES_KEY_WRAP 0x02f
+#define SKS_CKM_RSA_PKCS_PSS 0x030
+#define SKS_CKM_MD5 0x031
+#define SKS_CKM_SHA_1 0x032
+#define SKS_CKM_SHA224 0x033
+#define SKS_CKM_SHA256 0x034
+#define SKS_CKM_SHA384 0x035
+#define SKS_CKM_SHA512 0x036
+#define SKS_CKM_DH_PKCS_DERIVE 0x037
+#define SKS_CKM_DES_KEY_GEN 0x038
+#define SKS_CKM_DES_ECB 0x039
+#define SKS_CKM_DES_CBC 0x040
+#define SKS_CKM_DES_MAC 0x041
+#define SKS_CKM_DES_MAC_GENERAL 0x042
+#define SKS_CKM_DES_CBC_PAD 0x043
+#define SKS_CKM_EC_KEY_PAIR_IMPORT 0x044
+#define SKS_CKM_DUMP_LOG 0x045
+
+
+#define SKS_CKM_MTK_HSM_EXT 0x20000
+#define SKS_CKM_MTK_HSM_AES_ECB (SKS_CKM_MTK_HSM_EXT | SKS_CKM_AES_ECB)
+#define SKS_CKM_MTK_HSM_AES_CBC (SKS_CKM_MTK_HSM_EXT | SKS_CKM_AES_CBC)
+#define SKS_CKM_MTK_HSM_AES_CTR (SKS_CKM_MTK_HSM_EXT | SKS_CKM_AES_CTR)
+#define SKS_CKM_MTK_HSM_AES_GCM (SKS_CKM_MTK_HSM_EXT | SKS_CKM_AES_GCM)
+#define SKS_CKM_MTK_HSM_AES_CMAC (SKS_CKM_MTK_HSM_EXT | SKS_CKM_AES_CMAC)
+#define SKS_CKM_MTK_HSM_SHA256_HMAC (SKS_CKM_MTK_HSM_EXT | SKS_CKM_SHA256_HMAC)
+#define SKS_CKM_MTK_HSM_SHA384_HMAC (SKS_CKM_MTK_HSM_EXT | SKS_CKM_SHA384_HMAC)
+#define SKS_CKM_MTK_HSM_ECDSA (SKS_CKM_MTK_HSM_EXT | SKS_CKM_ECDSA)
+#define SKS_CKM_MTK_HSM_ECDSA_SHA1 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_ECDSA_SHA1)
+#define SKS_CKM_MTK_HSM_ECDSA_SHA224 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_ECDSA_SHA224)
+#define SKS_CKM_MTK_HSM_ECDSA_SHA256 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_ECDSA_SHA256)
+#define SKS_CKM_MTK_HSM_ECDSA_SHA384 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_ECDSA_SHA384)
+#define SKS_CKM_MTK_HSM_ECDSA_SHA512 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_ECDSA_SHA512)
+#define SKS_CKM_MTK_HSM_SHA1 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_SHA_1)
+#define SKS_CKM_MTK_HSM_SHA224 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_SHA224)
+#define SKS_CKM_MTK_HSM_SHA256 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_SHA256)
+#define SKS_CKM_MTK_HSM_SHA384 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_SHA384)
+#define SKS_CKM_MTK_HSM_SHA512 (SKS_CKM_MTK_HSM_EXT | SKS_CKM_SHA512)
+#define SKS_CKM_MTK_HSM_AES_KEY_GEN (SKS_CKM_MTK_HSM_EXT | SKS_CKM_AES_KEY_GEN)
+#define SKS_CKM_MTK_HSM_GENERIC_SECRET_KEY_GEN (SKS_CKM_MTK_HSM_EXT | SKS_CKM_GENERIC_SECRET_KEY_GEN)
+#define SKS_CKM_MTK_HSM_EC_KEY_PAIR_GEN (SKS_CKM_MTK_HSM_EXT | SKS_CKM_EC_KEY_PAIR_GEN)
+#define SKS_CKM_MTK_HSM_EC_KEY_PAIR_IMPORT (SKS_CKM_MTK_HSM_EXT | SKS_CKM_EC_KEY_PAIR_IMPORT)
+#define SKS_CKM_MTK_HSM_DUMP_LOG (SKS_CKM_MTK_HSM_EXT | SKS_CKM_DUMP_LOG)
+
+/* SKS added IDs for operation without cryptoki mechanism ID defined */
+#define SKS_PROCESSING_IMPORT 0x1000
+#define SKS_PROCESSING_COPY 0x1001
+
+/*
+ * Valid values key differentiation function identifiers
+ * SKS_CKD_<x> reltaes to cryptoki CKD_<x>.
+ */
+#define SKS_CKD_NULL 0x0000UL
+#define SKS_CKD_SHA1_KDF 0x0001UL
+#define SKS_CKD_SHA1_KDF_ASN1 0x0002UL
+#define SKS_CKD_SHA1_KDF_CONCATENATE 0x0003UL
+#define SKS_CKD_SHA224_KDF 0x0004UL
+#define SKS_CKD_SHA256_KDF 0x0005UL
+#define SKS_CKD_SHA384_KDF 0x0006UL
+#define SKS_CKD_SHA512_KDF 0x0007UL
+#define SKS_CKD_CPDIVERSIFY_KDF 0x0008UL
+
+/*
+ * Valid values MG function identifiers
+ * SKS_CKG_<x> reltaes to cryptoki CKG_<x>.
+ */
+#define SKS_CKG_MGF1_SHA1 0x0001UL
+#define SKS_CKG_MGF1_SHA224 0x0005UL
+#define SKS_CKG_MGF1_SHA256 0x0002UL
+#define SKS_CKG_MGF1_SHA384 0x0003UL
+#define SKS_CKG_MGF1_SHA512 0x0004UL
+
+/*
+ * Valid values for RSA PKCS/OAEP source type identifier
+ * SKS_CKZ_<x> reltaes to cryptoki CKZ_<x>.
+ */
+#define SKS_CKZ_DATA_SPECIFIED 0x0001UL
+
+/*
+ * Processing parameters
+ *
+ * These can hardly be described by ANSI-C structures since the byte size of
+ * some fields of the structure are specified by a previous field in the
+ * structure. Therefore the format of the parameter binary data for each
+ * supported processing is defined here from this comment rather than using
+ * C structures.
+ *
+ * Processing parameters are used as argument the C_EncryptInit and friends
+ * using the struct sks_attribute_head format where field 'type' is the SKS
+ * processing ID and field 'size' is the parameter byte size. Below is shown
+ * the head structure struct sks_attribute_head fields and the trailling data
+ * that are the effective parameters binary blob for the target
+ * processing/mechanism.
+ *
+ * AES ECB
+ * head: 32bit: type = SKS_CKM_AES_ECB
+ * 32bit: params byte size = 0
+ *
+ * AES CBC, CBC_NOPAD and CTS
+ * head: 32bit: type = SKS_CKM_AES_CBC
+ * or SKS_CKM_AES_CBC_PAD
+ * or SKS_CKM_AES_CTS
+ * 32bit: params byte size = 16
+ * params: 16byte: IV
+ *
+ * AES CTR, params relates to struct CK_AES_CTR_PARAMS.
+ * head: 32bit: type = SKS_CKM_AES_CTR
+ * 32bit: params byte size = 20
+ * params: 32bit: counter bit increment
+ * 16byte: IV
+ *
+ * AES GCM, params relates to struct CK_AES_GCM_PARAMS.
+ * head: 32bit: type = SKS_CKM_AES_GCM
+ * 32bit: params byte size
+ * params: 32bit: IV_byte_size
+ * byte array: IV (IV_byte_size bytes)
+ * 32bit: AAD_byte_size
+ * byte array: AAD data (AAD_byte_size bytes)
+ * 32bit: tag bit size
+ *
+ * AES CCM, params relates to struct CK_AES_CCM_PARAMS.
+ * head: 32bit: type = SKS_CKM_AES_CCM
+ * 32bit: params byte size
+ * params: 32bit: data_byte_size
+ * 32bit: nonce_byte_size
+ * byte array: nonce data (nonce_byte_size bytes)
+ * 32bit: AAD_byte_size
+ * byte array: AAD data (AAD_byte_size bytes)
+ * 32bit: MAC byte size
+ *
+ * AES GMAC
+ * head: 32bit: type = SKS_CKM_AES_GMAC
+ * 32bit: params byte size = 12
+ * params: 12byte: IV
+ *
+ * AES CMAC with general length, params relates to struct CK_MAC_GENERAL_PARAMS.
+ * head: 32bit: type = SKS_CKM_AES_CMAC_GENERAL
+ * 32bit: params byte size = 12
+ * params: 32bit: byte size of the output CMAC data
+ *
+ * AES CMAC fixed size (16byte CMAC)
+ * head: 32bit: type = SKS_CKM_AES_CMAC_GENERAL
+ * 32bit: size = 0
+ *
+ * AES derive by ECB, params relates to struct CK_KEY_DERIVATION_STRING_DATA.
+ * head: 32bit: type = SKS_CKM_AES_ECB_ENCRYPT_DATA
+ * 32bit: params byte size
+ * params: 32bit: byte size of the data to encrypt
+ * byte array: data to encrypt
+ *
+ * AES derive by CBC, params relates to struct CK_AES_CBC_ENCRYPT_DATA_PARAMS.
+ * head: 32bit: type = SKS_CKM_AES_CBC_ENCRYPT_DATA
+ * 32bit: params byte size
+ * params: 16byte: IV
+ * 32bit: byte size of the data to encrypt
+ * byte array: data to encrypt
+ *
+ * AES and generic secret generation
+ * head: 32bit: type = SKS_CKM_AES_KEY_GEN
+ * or SKS_CKM_GENERIC_SECRET_KEY_GEN
+ * 32bit: size = 0
+ *
+ * ECDH, params relates to struct CK_ECDH1_DERIVE_PARAMS.
+ * head: 32bit: type = SKS_CKM_ECDH1_DERIVE
+ * or SKS_CKM_ECDH1_COFACTOR_DERIVE
+ * 32bit: params byte size
+ * params: 32bit: key derivation function (SKS_CKD_xxx)
+ * 32bit: byte size of the shared data
+ * byte array: shared data
+ * 32bit: byte: size of the public data
+ * byte array: public data
+ *
+ * AES key wrap by ECDH, params relates to struct CK_ECDH_AES_KEY_WRAP_PARAMS.
+ * head: 32bit: type = SKS_CKM_ECDH_AES_KEY_WRAP
+ * 32bit: params byte size
+ * params: 32bit: bit size of the AES key
+ * 32bit: key derivation function (SKS_CKD_xxx)
+ * 32bit: byte size of the shared data
+ * byte array: shared data
+ *
+ * RSA_PKCS (pre-hashed payload)
+ * head: 32bit: type = SKS_CKM_RSA_PKCS
+ * 32bit: size = 0
+ *
+ * RSA PKCS OAEP, params relates to struct CK_RSA_PKCS_OAEP_PARAMS.
+ * head: 32bit: type = SKS_CKM_RSA_PKCS_OAEP
+ * 32bit: params byte size
+ * params: 32bit: hash algorithm identifier (SKS_CK_M_xxx)
+ * 32bit: CK_RSA_PKCS_MGF_TYPE
+ * 32bit: CK_RSA_PKCS_OAEP_SOURCE_TYPE
+ * 32bit: byte size of the source data
+ * byte array: source data
+ *
+ * RSA PKCS PSS, params relates to struct CK_RSA_PKCS_PSS_PARAMS.
+ * head: 32bit: type = SKS_CKM_RSA_PKCS_PSS
+ * or SKS_CKM_SHA256_RSA_PKCS_PSS
+ * or SKS_CKM_SHA384_RSA_PKCS_PSS
+ * or SKS_CKM_SHA512_RSA_PKCS_PSS
+ * 32bit: params byte size
+ * params: 32bit: hash algorithm identifier (SKS_CK_M_xxx)
+ * 32bit: CK_RSA_PKCS_MGF_TYPE
+ * 32bit: byte size of the salt in the PSS encoding
+ *
+ * AES key wrapping by RSA, params relates to struct CK_RSA_AES_KEY_WRAP_PARAMS.
+ * head: 32bit: type = CKM_RSA_AES_KEY_WRAP
+ * 32bit: params byte size
+ * params: 32bit: bit size of the AES key
+ * 32bit: hash algorithm identifier (SKS_CK_M_xxx)
+ * 32bit: CK_RSA_PKCS_MGF_TYPE
+ * 32bit: CK_RSA_PKCS_OAEP_SOURCE_TYPE
+ * 32bit: byte size of the source data
+ * byte array: source data
+ */
+
+#endif /*__SKS_TA_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/system_event.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/system_event.h
new file mode 100644
index 0000000..79f9fa8
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/include/system_event.h
@@ -0,0 +1,81 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef _SYSTEM_EVENT_H_
+#define _SYSTEM_EVENT_H_
+
+#include "processor.h"
+#include <stdint.h>
+
+#define MBOX_ENTRY_SIZE 16U
+#define MBOX_HEADER_SIZE 1U
+#define MBOX_DATA_SIZE (MBOX_ENTRY_SIZE - MBOX_HEADER_SIZE)
+
+/* Puts SYSTEM EVENT ID */
+enum sys_event_id {
+ /* Please keep this on the top */
+ SYS_EVENT_MSG_ACK,
+
+ /* Please puts the events from here */
+ SYS_EVENT_CLI,
+ SYS_EVENT_CLI_REQ,
+
+ SYS_EVENT_CRY_AES_SHA, // <-- Crypto event START
+ SYS_EVENT_CRY_ECC,
+ SYS_EVENT_CRY_TRNG,
+ SYS_EVENT_CANCEL_JOB, // <-- Crypto event END
+
+ SYS_EVENT_JOB_MGMT,
+ SYS_EVENT_KEY_MANAGEMENT,
+ SYS_EVENT_HSM_CONTROL,
+
+ SYS_EVENT_CNT,
+};
+
+/* system management */
+struct sys_event {
+ uint8_t event_id;
+ enum CPU_SERIAL cpu_serial;
+ uint32_t priority;
+
+ union system_data {
+ uint32_t data[MBOX_DATA_SIZE];
+ /* Put your struct here */
+ } data;
+};
+
+#endif /* _SYSTEM_EVENT_H_ */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/attributes.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/attributes.c
new file mode 100644
index 0000000..a6e9fcf
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/attributes.c
@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <compiler.h>
+#include <sks_internal_abi.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string_ext.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <trace.h>
+#include <util.h>
+
+#include "attributes.h"
+#include "sks_helpers.h"
+#include "serializer.h"
+
+uint32_t init_attributes_head(struct sks_attrs_head **head)
+{
+ *head = TEE_Malloc(sizeof(struct sks_attrs_head), TEE_MALLOC_FILL_ZERO);
+ if (!*head)
+ return SKS_MEMORY;
+
+#ifdef SKS_SHEAD_WITH_TYPE
+ (*head)->class = SKS_UNDEFINED_ID;
+ (*head)->type = SKS_UNDEFINED_ID;
+#endif
+
+ return SKS_OK;
+}
+
+#if defined(SKS_SHEAD_WITH_TYPE) || defined(SKS_SHEAD_WITH_BOOLPROPS)
+static bool attribute_is_in_head(uint32_t attribute)
+{
+#ifdef SKS_SHEAD_WITH_TYPE
+ if (attribute == SKS_CKA_CLASS || sks_attr_is_type(attribute))
+ return true;
+#endif
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ if (sks_attr2boolprop_shift(attribute) >= 0)
+ return true;
+#endif
+
+ return false;
+}
+#endif
+
+uint32_t add_attribute(struct sks_attrs_head **head,
+ uint32_t attribute, void *data, size_t size)
+{
+ size_t buf_len = sizeof(struct sks_attrs_head) + (*head)->attrs_size;
+ uint32_t rv = 0;
+ uint32_t data32 = 0;
+ char **bstart = (void *)head;
+ int __maybe_unused shift = 0;
+
+#ifdef SKS_SHEAD_WITH_TYPE
+ if (attribute == SKS_CKA_CLASS || sks_attr_is_type(attribute)) {
+ assert(size == sizeof(uint32_t));
+
+ TEE_MemMove(attribute == SKS_CKA_CLASS ?
+ &(*head)->class : &(*head)->type,
+ data, sizeof(uint32_t));
+
+ return SKS_OK;
+ }
+#endif
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ shift = sks_attr2boolprop_shift(attribute);
+ if (head_contains_boolprops(*head) && shift >= 0) {
+ uint32_t mask = shift < 32 ? BIT(shift) : BIT(shift - 32);
+ uint32_t val = *(uint8_t *)data ? mask : 0;
+
+ if (size != sizeof(uint8_t)) {
+ EMSG("Invalid size %zu", size);
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ if (shift < 32)
+ (*head)->boolpropl = ((*head)->boolpropl & ~mask) | val;
+ else
+ (*head)->boolproph = ((*head)->boolproph & ~mask) | val;
+
+ return SKS_OK;
+ }
+#endif
+
+ data32 = attribute;
+ rv = serialize(bstart, &buf_len, &data32, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ data32 = size;
+ rv = serialize(bstart, &buf_len, &data32, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialize(bstart, &buf_len, data, size);
+ if (rv)
+ return rv;
+
+ /* Alloced buffer is always 64byte align, safe for us */
+ head = (void *)bstart;
+ (*head)->attrs_size += 2 * sizeof(uint32_t) + size;
+ (*head)->attrs_count++;
+
+ return rv;
+}
+
+uint32_t remove_attribute(struct sks_attrs_head **head, uint32_t attribute)
+{
+ struct sks_attrs_head *h = *head;
+ char *cur = NULL;
+ char *end = NULL;
+ size_t next_off = 0;
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ /* Can't remove an attribute that is defined in the head */
+ if (head_contains_boolprops(*head) && attribute_is_in_head(attribute)) {
+ EMSG("Can't remove attribute from the head");
+ return SKS_FAILED;
+ }
+#endif
+
+ /* Let's find the target attribute */
+ cur = (char *)h + sizeof(struct sks_attrs_head);
+ end = cur + h->attrs_size;
+ for (; cur < end; cur += next_off) {
+ struct sks_ref sks_ref;
+
+ TEE_MemMove(&sks_ref, cur, sizeof(sks_ref));
+ next_off = sizeof(sks_ref) + sks_ref.size;
+
+ if (sks_ref.id != attribute)
+ continue;
+
+ TEE_MemMove(cur, cur + next_off, end - (cur + next_off));
+
+ h->attrs_count--;
+ h->attrs_size -= next_off;
+ end -= next_off;
+ next_off = 0;
+ return SKS_OK;
+ }
+
+ DMSG("SKS_VALUE not found");
+ return SKS_NOT_FOUND;
+}
+
+uint32_t remove_attribute_check(struct sks_attrs_head **head, uint32_t attribute,
+ size_t max_check)
+{
+ struct sks_attrs_head *h = *head;
+ char *cur = NULL;
+ char *end = NULL;
+ size_t next_off = 0;
+ size_t found = 0;
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ /* Can't remove an attribute that is defined in the head */
+ if (head_contains_boolprops(*head) && attribute_is_in_head(attribute)) {
+ EMSG("Can't remove attribute from the head");
+ TEE_Panic(0);
+ }
+#endif
+
+ /* Let's find the target attribute */
+ cur = (char *)h + sizeof(struct sks_attrs_head);
+ end = cur + h->attrs_size;
+ for (; cur < end; cur += next_off) {
+ struct sks_ref sks_ref;
+
+ TEE_MemMove(&sks_ref, cur, sizeof(sks_ref));
+ next_off = sizeof(sks_ref) + sks_ref.size;
+
+ if (sks_ref.id != attribute)
+ continue;
+
+ found++;
+ if (found > max_check) {
+ DMSG("Too many attribute occurrences");
+ return SKS_FAILED;
+ }
+
+ TEE_MemMove(cur, cur + next_off, end - (cur + next_off));
+
+ h->attrs_count--;
+ h->attrs_size -= next_off;
+ end -= next_off;
+ next_off = 0;
+ }
+
+ /* sanity */
+ if (cur != end) {
+ EMSG("Bad end address");
+ return SKS_ERROR;
+ }
+
+ if (!found) {
+ EMSG("SKS_VALUE not found");
+ return SKS_FAILED;
+
+ }
+
+ return SKS_OK;
+}
+
+void get_attribute_ptrs(struct sks_attrs_head *head, uint32_t attribute,
+ void **attr, uint32_t *attr_size, size_t *count)
+{
+ char *cur = (char *)head + sizeof(struct sks_attrs_head);
+ char *end = cur + head->attrs_size;
+ size_t next_off = 0;
+ size_t max_found = *count;
+ size_t found = 0;
+ void **attr_ptr = attr;
+ uint32_t *attr_size_ptr = attr_size;
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ /* Can't return a pointer to a boolprop attribute */
+ if (head_contains_boolprops(head) && attribute_is_in_head(attribute)) {
+ EMSG("Can't get pointer to an attribute in the head");
+ TEE_Panic(0);
+ }
+#endif
+
+ for (; cur < end; cur += next_off) {
+ /* Structure aligned copy of the sks_ref in the object */
+ struct sks_ref sks_ref;
+
+ TEE_MemMove(&sks_ref, cur, sizeof(sks_ref));
+ next_off = sizeof(sks_ref) + sks_ref.size;
+
+ if (sks_ref.id != attribute)
+ continue;
+
+ found++;
+
+ if (!max_found)
+ continue; /* only count matching attributes */
+
+ if (attr)
+ *attr_ptr++ = cur + sizeof(sks_ref);
+
+ if (attr_size)
+ *attr_size_ptr++ = sks_ref.size;
+
+ if (found == max_found)
+ break;
+ }
+
+ /* Sanity */
+ if (cur > end) {
+ DMSG("Exceeding serial object length");
+ TEE_Panic(0);
+ }
+
+ *count = found;
+}
+
+uint32_t get_attribute_ptr(struct sks_attrs_head *head, uint32_t attribute,
+ void **attr_ptr, uint32_t *attr_size)
+{
+ size_t count = 1;
+
+#ifdef SKS_SHEAD_WITH_TYPE
+
+ if (attribute == SKS_CKA_CLASS) {
+ if (attr_size)
+ *attr_size = sizeof(uint32_t);
+ if (attr_ptr)
+ *attr_ptr = &head->class;
+
+ return SKS_OK;
+ }
+ if (attribute == SKS_CKA_KEY_TYPE) {
+ if (attr_size)
+ *attr_size = sizeof(uint32_t);
+ if (attr_ptr)
+ *attr_ptr = &head->type;
+
+ return SKS_OK;
+ }
+#endif
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ if (head_contains_boolprops(head) &&
+ sks_attr2boolprop_shift(attribute) >= 0)
+ TEE_Panic(0);
+#endif
+
+ get_attribute_ptrs(head, attribute, attr_ptr, attr_size, &count);
+
+ if (!count)
+ return SKS_NOT_FOUND;
+
+ if (count != 1)
+ return SKS_ERROR;
+
+ return SKS_OK;
+}
+
+uint32_t get_attribute(struct sks_attrs_head *head, uint32_t attribute,
+ void *attr, uint32_t *attr_size)
+{
+ uint32_t rc = 0;
+ void *attr_ptr = NULL;
+ uint32_t size = 0;
+ uint8_t __maybe_unused bbool = 0;
+ int __maybe_unused shift = 0;
+
+#ifdef SKS_SHEAD_WITH_TYPE
+ if (attribute == SKS_CKA_CLASS) {
+ size = sizeof(uint32_t);
+ attr_ptr = &head->class;
+ goto found;
+ }
+
+ if (attribute == SKS_CKA_KEY_TYPE) {
+ size = sizeof(uint32_t);
+ attr_ptr = &head->type;
+ goto found;
+ }
+#endif
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ shift = sks_attr2boolprop_shift(attribute);
+ if (head_contains_boolprops(head) && shift >= 0) {
+ uint32_t *boolprop = NULL;
+
+ boolprop = (shift < 32) ? &head->boolpropl : &head->boolproph;
+ bbool = (*boolprop & (1 << (shift % 32))) ? SKS_TRUE : SKS_FALSE;
+
+ size = sizeof(uint8_t);
+ attr_ptr = &bbool;
+ goto found;
+ }
+#endif
+ rc = get_attribute_ptr(head, attribute, &attr_ptr, &size);
+ if (rc == SKS_OK)
+ goto found;
+
+ return rc;
+
+found:
+ if (attr_size && *attr_size != size) {
+ *attr_size = size;
+ /* This reuses buffer-to-small for any bad size matching */
+ return SKS_SHORT_BUFFER;
+ }
+
+ if (attr)
+ TEE_MemMove(attr, attr_ptr, size);
+
+ if (attr_size)
+ *attr_size = size;
+
+ return SKS_OK;
+}
+
+bool get_bool(struct sks_attrs_head *head, uint32_t attribute)
+{
+ uint32_t __maybe_unused rc = 0;
+ uint8_t bbool = 0;
+ uint32_t size = sizeof(bbool);
+ int __maybe_unused shift = 0;
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ shift = sks_attr2boolprop_shift(attribute);
+ if (shift < 0)
+ TEE_Panic(SKS_NOT_FOUND);
+
+ if (head_contains_boolprops(head)) {
+ if (shift > 31)
+ return head->boolproph & BIT(shift - 32);
+ else
+ return head->boolpropl & BIT(shift);
+ }
+#endif
+
+ rc = get_attribute(head, attribute, &bbool, &size);
+
+ if (rc == SKS_NOT_FOUND)
+ return false;
+
+ assert(rc == SKS_OK);
+ return !!bbool;
+}
+
+bool attributes_match_reference(struct sks_attrs_head *candidate,
+ struct sks_attrs_head *ref)
+{
+ size_t count = ref->attrs_count;
+ unsigned char *ref_attr = ref->attrs;
+ uint32_t rc = 0;
+
+ if (!ref->attrs_count) {
+ DMSG("Empty reference: no match");
+ return false;
+ }
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ /*
+ * All boolprops attributes must be explicitly defined
+ * as an attribute reference in the reference object.
+ */
+ assert(!head_contains_boolprops(ref));
+#endif
+
+ for (count = 0; count < ref->attrs_count; count++) {
+ struct sks_ref sks_ref;
+ void *found = NULL;
+ uint32_t size = 0;
+ int shift = 0;
+
+ TEE_MemMove(&sks_ref, ref_attr, sizeof(sks_ref));
+
+ shift = sks_attr2boolprop_shift(sks_ref.id);
+ if (shift >= 0) {
+
+ bool bb_ref = get_bool(ref, sks_ref.id);
+ bool bb_candidate = get_bool(candidate, sks_ref.id);
+
+ if (bb_ref != bb_candidate) {
+ return false;
+ }
+ } else {
+ rc = get_attribute_ptr(candidate, sks_ref.id,
+ &found, &size);
+
+ if (rc || !found || size != sks_ref.size ||
+ TEE_MemCompare(ref_attr + sizeof(sks_ref),
+ found, size)) {
+ return false;
+ }
+ }
+
+ ref_attr += sizeof(sks_ref) + sks_ref.size;
+ }
+
+ return true;
+}
+
+/*
+ * Debug: dump CK attribute array to output trace
+ */
+#define ATTR_TRACE_FMT "%s attr %s / %s\t(0x%04" PRIx32 " %" PRIu32 "-byte"
+#define ATTR_FMT_0BYTE ATTR_TRACE_FMT ")"
+#define ATTR_FMT_1BYTE ATTR_TRACE_FMT ": %02x)"
+#define ATTR_FMT_2BYTE ATTR_TRACE_FMT ": %02x %02x)"
+#define ATTR_FMT_3BYTE ATTR_TRACE_FMT ": %02x %02x %02x)"
+#define ATTR_FMT_4BYTE ATTR_TRACE_FMT ": %02x %02x %02x %02x)"
+#define ATTR_FMT_ARRAY ATTR_TRACE_FMT ": %02x %02x %02x %02x ...)"
+
+static uint32_t __trace_attributes(char *prefix, void *src, void *end)
+{
+ size_t next_off = 0;
+ char *prefix2 = NULL;
+ size_t prefix_len = strlen(prefix);
+ char *cur = src;
+
+ /* append 4 spaces to the prefix plus terminal '\0' */
+ prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO);
+ if (!prefix2)
+ return SKS_MEMORY;
+
+ TEE_MemMove(prefix2, prefix, prefix_len + 1);
+ TEE_MemFill(prefix2 + prefix_len, ' ', 4);
+ *(prefix2 + prefix_len + 4) = '\0';
+
+ for (; cur < (char *)end; cur += next_off) {
+ struct sks_ref sks_ref;
+ uint8_t data[4] = { 0 };
+
+ TEE_MemMove(&sks_ref, cur, sizeof(sks_ref));
+ TEE_MemMove(&data[0], cur + sizeof(sks_ref),
+ MIN(sks_ref.size, sizeof(data)));
+
+ next_off = sizeof(sks_ref) + sks_ref.size;
+
+ switch (sks_ref.size) {
+ case 0:
+ IMSG_RAW(ATTR_FMT_0BYTE,
+ prefix, sks2str_attr(sks_ref.id), "*",
+ sks_ref.id, sks_ref.size);
+ break;
+ case 1:
+ IMSG_RAW(ATTR_FMT_1BYTE,
+ prefix, sks2str_attr(sks_ref.id),
+ sks2str_attr_value(sks_ref.id, sks_ref.size,
+ cur + sizeof(sks_ref)),
+ sks_ref.id, sks_ref.size, data[0]);
+ break;
+ case 2:
+ IMSG_RAW(ATTR_FMT_2BYTE,
+ prefix, sks2str_attr(sks_ref.id),
+ sks2str_attr_value(sks_ref.id, sks_ref.size,
+ cur + sizeof(sks_ref)),
+ sks_ref.id, sks_ref.size, data[0], data[1]);
+ break;
+ case 3:
+ IMSG_RAW(ATTR_FMT_3BYTE,
+ prefix, sks2str_attr(sks_ref.id),
+ sks2str_attr_value(sks_ref.id, sks_ref.size,
+ cur + sizeof(sks_ref)),
+ sks_ref.id, sks_ref.size,
+ data[0], data[1], data[2]);
+ break;
+ case 4:
+ IMSG_RAW(ATTR_FMT_4BYTE,
+ prefix, sks2str_attr(sks_ref.id),
+ sks2str_attr_value(sks_ref.id, sks_ref.size,
+ cur + sizeof(sks_ref)),
+ sks_ref.id, sks_ref.size,
+ data[0], data[1], data[2], data[3]);
+ break;
+ default:
+ IMSG_RAW(ATTR_FMT_ARRAY,
+ prefix, sks2str_attr(sks_ref.id),
+ sks2str_attr_value(sks_ref.id, sks_ref.size,
+ cur + sizeof(sks_ref)),
+ sks_ref.id, sks_ref.size,
+ data[0], data[1], data[2], data[3]);
+ break;
+ }
+
+ switch (sks_ref.id) {
+ case SKS_CKA_WRAP_TEMPLATE:
+ case SKS_CKA_UNWRAP_TEMPLATE:
+ case SKS_CKA_DERIVE_TEMPLATE:
+ trace_attributes(prefix2,
+ (void *)(cur + sizeof(sks_ref)));
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Sanity */
+ if (cur != (char *)end) {
+ EMSG("Warning: unexpected alignment in object attributes");
+ }
+
+ TEE_Free(prefix2);
+ return SKS_OK;
+}
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+static void trace_boolprops(const char *prefix, struct sks_attrs_head *head)
+{
+ size_t __maybe_unused n = 0;
+
+ for (n = 0; n <= SKS_BOOLPROPS_LAST; n++) {
+ bool bp = n < 32 ? !!(head->boolpropl & BIT(n)) :
+ !!(head->boolproph & BIT(n - 32));
+
+ IMSG_RAW("%s| attr %s / %s (0x%" PRIx32 ")",
+ prefix, sks2str_attr(n), bp ? "TRUE" : "FALSE", n);
+ }
+}
+#endif
+
+uint32_t trace_attributes(const char *prefix, void *ref)
+{
+ struct sks_attrs_head head;
+ char *pre = NULL;
+ uint32_t rc = 0;
+ size_t __maybe_unused n = 0;
+
+ TEE_MemMove(&head, ref, sizeof(head));
+
+ pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO);
+ if (!pre)
+ return SKS_MEMORY;
+ if (prefix)
+ TEE_MemMove(pre, prefix, strlen(prefix));
+
+ IMSG_RAW("%s,--- (serial object) Attributes list --------", pre);
+ IMSG_RAW("%s| %" PRIu32 " item(s) - %" PRIu32 " bytes",
+ pre, head.attrs_count, head.attrs_size);
+#ifdef SKS_SHEAD_WITH_TYPE
+ IMSG_RAW("%s| class (0x%" PRIx32 ") %s type (0x%" PRIx32 ") %s",
+ pre, head.class, sks2str_class(head.class),
+ head.type, sks2str_type(head.type, head.class));
+#endif
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ if (head_contains_boolprops(&head))
+ trace_boolprops(pre, &head);
+#endif
+
+ pre[prefix ? strlen(prefix) : 0] = '|';
+ rc = __trace_attributes(pre, (char *)ref + sizeof(head),
+ (char *)ref + sizeof(head) + head.attrs_size);
+ if (rc)
+ goto bail;
+
+ IMSG_RAW("%s`-----------------------", prefix ? prefix : "");
+
+bail:
+ TEE_Free(pre);
+ return rc;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/attributes.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/attributes.h
new file mode 100644
index 0000000..f602c3e
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/attributes.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __ATTRIBUTES_H
+#define __ATTRIBUTES_H
+
+#include <assert.h>
+#include <sks_internal_abi.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "sks_helpers.h"
+
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+static inline void set_attributes_in_head(struct sks_attrs_head *head)
+{
+ head->boolproph |= SKS_BOOLPROPH_FLAG;
+}
+
+static inline bool head_contains_boolprops(struct sks_attrs_head __unused *head)
+{
+ return head->boolproph & SKS_BOOLPROPH_FLAG;
+}
+#endif
+
+/*
+ * Allocation a reference for a serialized attributes.
+ * Can be freed from a simple TEE_Free(reference);
+ *
+ * Return a SKS_OK on success or a SKS return code.
+ */
+uint32_t init_attributes_head(struct sks_attrs_head **head);
+
+/*
+ * Update serialized attributes to add an entry. Can relocate the attribute
+ * list buffer.
+ *
+ * Return a SKS_OK on success or a SKS return code.
+ */
+uint32_t add_attribute(struct sks_attrs_head **head,
+ uint32_t attribute, void *data, size_t size);
+
+/*
+ * Update serialized attributes to remove an entry. Can relocate the attribute
+ * list buffer. Only 1 instance of the entry is expected (TODO factory with _check)
+ *
+ * Return a SKS_OK on success or a SKS return code.
+ */
+uint32_t remove_attribute(struct sks_attrs_head **head, uint32_t attrib);
+
+/*
+ * Update serialized attributes to remove an entry. Can relocate the attribute
+ * list buffer. If attribute ID is find several times, remove all of them.
+ *
+ * Return a SKS_OK on success or a SKS return code.
+ */
+uint32_t remove_attribute_check(struct sks_attrs_head **head, uint32_t attribute,
+ size_t max_check);
+
+/*
+ * If *count == 0, count and return in *count the number of attributes matching
+ * the input attribute ID.
+ *
+ * If *count != 0, return the address and size of the attributes found, up to
+ * the occurrence number *count. attr and attr_size and expected large
+ * enough. attr is the output array of the values found. attr_size is the
+ * output array of the size of each values found.
+ *
+ * If attr_size != NULL, return in in *attr_size attribute value size.
+ * If attr != NULL return in *attr the address in memory of the attribute value.
+ */
+void get_attribute_ptrs(struct sks_attrs_head *head, uint32_t attribute,
+ void **attr, uint32_t *attr_size, size_t *count);
+
+/*
+ * If attributes is not found return SKS_NOT_FOUND.
+ * If attr_size != NULL, return in in *attr_size attribute value size.
+ * If attr != NULL return in *attr the address in memory of the attribute value.
+ *
+ * Return a SKS_OK or SKS_NOT_FOUND on success, or a SKS return code.
+ */
+uint32_t get_attribute_ptr(struct sks_attrs_head *head, uint32_t attribute,
+ void **attr_ptr, uint32_t *attr_size);
+/*
+ * If attribute is not found, return SKS_NOT_FOUND.
+ * If attr_size != NULL, check *attr_size matches attributes size of return
+ * SKS_SHORT_BUFFER with expected size in *attr_size.
+ * If attr != NULL and attr_size is NULL or gives expected buffer size,
+ * copy attribute value into attr.
+ *
+ * Return a SKS_OK or SKS_NOT_FOUND on success, or a SKS return code.
+ */
+uint32_t get_attribute(struct sks_attrs_head *head, uint32_t attribute,
+ void *attr, uint32_t *attr_size);
+
+static inline uint32_t get_u32_attribute(struct sks_attrs_head *head,
+ uint32_t attribute, uint32_t *attr)
+{
+ uint32_t size = sizeof(uint32_t);
+ uint32_t rv = get_attribute(head, attribute, attr, &size);
+
+ if (size != sizeof(uint32_t))
+ return SKS_ERROR;
+
+ return rv;
+}
+
+/*
+ * Return true all attributes from the reference are found and match value
+ * in the candidate attribute list.
+ *
+ * Return a SKS_OK on success, or a SKS return code.
+ */
+bool attributes_match_reference(struct sks_attrs_head *ref,
+ struct sks_attrs_head *candidate);
+
+/*
+ * Some helpers
+ */
+static inline size_t attributes_size(struct sks_attrs_head *head)
+{
+ return sizeof(struct sks_attrs_head) + head->attrs_size;
+}
+
+#ifdef SKS_SHEAD_WITH_TYPE
+static inline uint32_t get_class(struct sks_attrs_head *head)
+{
+ return head->class;
+}
+
+static inline uint32_t get_type(struct sks_attrs_head *head)
+{
+ return head->type;
+}
+#else
+static inline uint32_t get_class(struct sks_attrs_head *head)
+{
+ uint32_t class;
+ uint32_t size = sizeof(class);
+
+ if (get_attribute(head, SKS_CKA_CLASS, &class, &size))
+ return SKS_UNDEFINED_ID;
+
+ return class;
+}
+static inline uint32_t get_type(struct sks_attrs_head *head)
+{
+ uint32_t type;
+ uint32_t size = sizeof(type);
+
+ if (get_attribute(head, SKS_CKA_KEY_TYPE, &type, &size))
+ return SKS_UNDEFINED_ID;
+
+ return type;
+}
+#endif
+
+bool get_bool(struct sks_attrs_head *head, uint32_t attribute);
+
+/* Debug: dump object attributes to IMSG() trace console */
+uint32_t trace_attributes(const char *prefix, void *ref);
+
+#endif /*__ATTRIBUTES_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/entry.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/entry.c
new file mode 100644
index 0000000..ea0f035
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/entry.c
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <compiler.h>
+#include <sks_ta.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include "handle.h"
+#include "object.h"
+#include "pkcs11_token.h"
+#include "processing.h"
+#include "sks_helpers.h"
+
+#include "processing_mtk_key.h"
+
+/* Client session context: currently only use the allocated address */
+struct tee_session {
+ int foo;
+};
+
+
+TEE_Result TA_CreateEntryPoint(void)
+{
+ if (pkcs11_init())
+ return TEE_ERROR_SECURITY;
+
+ mtk_rebuild_key_table();
+
+ return TEE_SUCCESS;
+}
+
+void TA_DestroyEntryPoint(void)
+{
+ pkcs11_deinit();
+}
+
+TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
+ TEE_Param __unused params[4],
+ void **tee_session)
+{
+ uintptr_t client = register_client();
+
+ if (!client)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ *tee_session = (void *)client;
+
+ return TEE_SUCCESS;
+}
+
+void TA_CloseSessionEntryPoint(void *tee_session)
+{
+ unregister_client((uintptr_t)tee_session);
+}
+
+static uint32_t entry_ping(TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t *ver = NULL;
+
+ if (ctrl || in)
+ return SKS_BAD_PARAM;
+
+ if (!out)
+ return SKS_OK;
+
+ if (out->memref.size < 2 * sizeof(uint32_t))
+ return SKS_SHORT_BUFFER;
+
+ if ((uintptr_t)out->memref.buffer & 0x03UL)
+ return SKS_BAD_PARAM;
+
+ ver = (uint32_t *)out->memref.buffer;
+ *ver = SKS_VERSION_ID0;
+ *(ver + 1) = SKS_VERSION_ID1;
+
+ return SKS_OK;
+}
+
+
+/*
+ * Entry point for SKS TA commands
+ *
+ * ABI: param#0 is the control buffer with serialized arguments.
+ * param#1 is an input/output data buffer
+ * param#2 is an input/output data buffer (also used to return handles)
+ * param#3 is not used
+ *
+ * Param#0 ctrl, if defined is an in/out buffer, is used to send back to
+ * the client a Cryptoki status ID that supersedes the TEE result code which
+ * will be force to TEE_SUCCESS. Note that some Cryptoki error status are
+ * sent straight through TEE result code. See sks2tee_noerr().
+ */
+TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd,
+ uint32_t ptypes,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ TEE_Param *ctrl = NULL;
+ TEE_Param *p1_in = NULL;
+ TEE_Param __maybe_unused *p1_out = NULL;
+ TEE_Param *p2_in = NULL;
+ TEE_Param *p2_out = NULL;
+ uintptr_t teesess = (uintptr_t)tee_session;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ uint32_t rc = 0;
+
+ /* param#0: input buffer with request serialized arguments */
+ switch (TEE_PARAM_TYPE_GET(ptypes, 0)) {
+ case TEE_PARAM_TYPE_NONE:
+ break;
+ case TEE_PARAM_TYPE_MEMREF_INPUT:
+ case TEE_PARAM_TYPE_MEMREF_INOUT:
+ ctrl = ¶ms[0];
+ break;
+ default:
+ goto bad_types;
+ }
+
+ /* param#1: input data buffer */
+ switch (TEE_PARAM_TYPE_GET(ptypes, 1)) {
+ case TEE_PARAM_TYPE_NONE:
+ break;
+ case TEE_PARAM_TYPE_MEMREF_INPUT:
+ p1_in = ¶ms[1];
+ break;
+ case TEE_PARAM_TYPE_MEMREF_OUTPUT:
+ p1_out = ¶ms[1];
+ break;
+ case TEE_PARAM_TYPE_MEMREF_INOUT:
+ p1_in = ¶ms[1];
+ p1_out = ¶ms[1];
+ break;
+ default:
+ goto bad_types;
+ }
+
+ /* param#2: input or output data buffer */
+ switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
+ case TEE_PARAM_TYPE_NONE:
+ break;
+ case TEE_PARAM_TYPE_MEMREF_INPUT:
+ p2_in = ¶ms[2];
+ break;
+ case TEE_PARAM_TYPE_MEMREF_OUTPUT:
+ p2_out = ¶ms[2];
+ break;
+ case TEE_PARAM_TYPE_MEMREF_INOUT:
+ p2_in = ¶ms[2];
+ p2_out = ¶ms[2];
+ break;
+ default:
+ goto bad_types;
+ }
+
+ /* param#3: unused */
+ switch (TEE_PARAM_TYPE_GET(ptypes, 3)) {
+ case TEE_PARAM_TYPE_NONE:
+ break;
+ default:
+ goto bad_types;
+ }
+
+ DMSG("%s ctrl %" PRIu32 "@%p, %s %" PRIu32 "@%p, %s %" PRIu32 "@%p",
+ sks2str_skscmd(cmd),
+ ctrl ? ctrl->memref.size : 0, ctrl ? ctrl->memref.buffer : 0,
+ p1_out ? "out" : (p1_in ? "in" : "---"),
+ p1_out ? p1_out->memref.size : (p1_in ? p1_in->memref.size : 0),
+ p1_out ? p1_out->memref.buffer :
+ (p1_in ? p1_in->memref.buffer : NULL),
+ p2_out ? "out" : (p2_in ? "in" : "---"),
+ p2_out ? p2_out->memref.size : (p2_in ? p2_in->memref.size : 0),
+ p2_out ? p2_out->memref.buffer :
+ (p2_in ? p2_in->memref.buffer : NULL));
+
+ switch (cmd) {
+ case SKS_CMD_PING:
+ rc = entry_ping(ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_CK_SLOT_LIST:
+ rc = entry_ck_slot_list(ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_CK_SLOT_INFO:
+ rc = entry_ck_slot_info(ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_CK_TOKEN_INFO:
+ rc = entry_ck_token_info(ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_CK_INIT_TOKEN:
+ rc = entry_ck_token_initialize(ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_CK_MECHANISM_IDS:
+ rc = entry_ck_token_mecha_ids(ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_CK_MECHANISM_INFO:
+ rc = entry_ck_token_mecha_info(ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_CK_OPEN_RO_SESSION:
+ rc = entry_ck_token_ro_session(teesess, ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_CK_OPEN_RW_SESSION:
+ rc = entry_ck_token_rw_session(teesess, ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_CK_CLOSE_SESSION:
+ rc = entry_ck_token_close_session(teesess, ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_CK_CLOSE_ALL_SESSIONS:
+ rc = entry_ck_token_close_all(teesess, ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_CK_SESSION_INFO:
+ rc = entry_ck_token_session_info(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_IMPORT_OBJECT:
+ rc = entry_import_object(teesess, ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_DESTROY_OBJECT:
+ rc = entry_destroy_object(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_DIGEST_INIT:
+ rc = entry_digesting_init(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_DIGEST);
+ break;
+
+ case SKS_CMD_DIGEST_UPDATE:
+ rc = entry_digesting_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_DIGEST,
+ SKS_FUNC_STEP_UPDATE);
+ break;
+
+ case SKS_CMD_DIGEST_ONESHOT:
+ rc = entry_digesting_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_DIGEST,
+ SKS_FUNC_STEP_ONESHOT);
+ break;
+
+ case SKS_CMD_DIGEST_FINAL:
+ rc = entry_digesting_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_DIGEST,
+ SKS_FUNC_STEP_FINAL);
+ break;
+
+ case SKS_CMD_ENCRYPT_INIT:
+ rc = entry_processing_init(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_ENCRYPT);
+ break;
+ case SKS_CMD_DECRYPT_INIT:
+ rc = entry_processing_init(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_DECRYPT);
+ break;
+ case SKS_CMD_ENCRYPT_UPDATE:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_ENCRYPT,
+ SKS_FUNC_STEP_UPDATE);
+ break;
+ case SKS_CMD_DECRYPT_UPDATE:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_DECRYPT,
+ SKS_FUNC_STEP_UPDATE);
+ break;
+ case SKS_CMD_ENCRYPT_ONESHOT:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_ENCRYPT,
+ SKS_FUNC_STEP_ONESHOT);
+ break;
+ case SKS_CMD_DECRYPT_ONESHOT:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_DECRYPT,
+ SKS_FUNC_STEP_ONESHOT);
+ break;
+ case SKS_CMD_ENCRYPT_FINAL:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_ENCRYPT,
+ SKS_FUNC_STEP_FINAL);
+ break;
+ case SKS_CMD_DECRYPT_FINAL:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_DECRYPT,
+ SKS_FUNC_STEP_FINAL);
+ break;
+
+ case SKS_CMD_GENERATE_SYMM_KEY:
+ rc = entry_generate_secret(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_SIGN_INIT:
+ rc = entry_processing_init(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_SIGN);
+ break;
+ case SKS_CMD_VERIFY_INIT:
+ rc = entry_processing_init(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_VERIFY);
+ break;
+ case SKS_CMD_SIGN_ONESHOT:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_SIGN,
+ SKS_FUNC_STEP_ONESHOT);
+ break;
+ case SKS_CMD_VERIFY_ONESHOT:
+ rc = entry_verify_oneshot(teesess, ctrl, p1_in, p2_in,
+ SKS_FUNCTION_VERIFY,
+ SKS_FUNC_STEP_ONESHOT);
+ break;
+ case SKS_CMD_SIGN_UPDATE:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_SIGN,
+ SKS_FUNC_STEP_UPDATE);
+ break;
+ case SKS_CMD_VERIFY_UPDATE:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_VERIFY,
+ SKS_FUNC_STEP_UPDATE);
+ break;
+ case SKS_CMD_SIGN_FINAL:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_SIGN,
+ SKS_FUNC_STEP_FINAL);
+ break;
+ case SKS_CMD_VERIFY_FINAL:
+ rc = entry_processing_step(teesess, ctrl, p1_in, p2_out,
+ SKS_FUNCTION_VERIFY,
+ SKS_FUNC_STEP_FINAL);
+ break;
+
+ case SKS_CMD_FIND_OBJECTS_INIT:
+ rc = entry_find_objects_init(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_FIND_OBJECTS:
+ rc = entry_find_objects(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_FIND_OBJECTS_FINAL:
+ rc = entry_find_objects_final(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_GET_OBJECT_SIZE:
+ rc = entry_get_object_size(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_GET_ATTRIBUTE_VALUE:
+ rc = entry_get_attribute_value(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_INIT_PIN:
+ rc = entry_init_pin(teesess, ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_SET_PIN:
+ rc = entry_set_pin(teesess, ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_LOGIN:
+ rc = entry_login(teesess, ctrl, p1_in, p2_out);
+ break;
+ case SKS_CMD_LOGOUT:
+ rc = entry_logout(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_GENERATE_KEY_PAIR:
+ rc = entry_generate_key_pair(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_DERIVE_KEY:
+ rc = entry_derive_key(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_GENERATE_RANDOM:
+ rc = entry_generate_random(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_IMPORT_KEY:
+ rc = entry_import_key(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_IMPORT_KEY_PAIR:
+ rc = entry_import_key_pair(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_EXPORT_KEY:
+ rc = entry_export_key_pair(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ case SKS_CMD_UTILS:
+ rc = entry_utils(teesess, ctrl, p1_in, p2_out);
+ break;
+
+ default:
+ EMSG("Command ID 0x%x is not supported", cmd);
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ if (TEE_PARAM_TYPE_GET(ptypes, 0) == TEE_PARAM_TYPE_MEMREF_INOUT &&
+ ctrl->memref.size >= sizeof(uint32_t) &&
+ !((uintptr_t)ctrl->memref.buffer & 0x03UL)) {
+
+ TEE_MemMove(ctrl->memref.buffer, &rc, sizeof(uint32_t));
+ ctrl->memref.size = sizeof(uint32_t);
+
+ res = sks2tee_noerr(rc);
+
+ DMSG("SKS TA exit: %s rc 0x%08" PRIx32 "/%s",
+ sks2str_skscmd(cmd), rc, sks2str_rc(rc));
+ } else {
+ res = sks2tee_error(rc);
+ DMSG("SKS TA exit: %s rc 0x%08" PRIx32 "/%s, TEE rc %" PRIx32,
+ sks2str_skscmd(cmd), rc, sks2str_rc(rc), res);
+ }
+
+ return res;
+
+bad_types:
+ DMSG("Bad parameter types used at SKS TA entry:");
+ DMSG("- parameter #0: formatted input request buffer or none");
+ DMSG("- parameter #1: processed input data buffer or none");
+ DMSG("- parameter #2: processed output data buffer or none");
+ DMSG("- parameter #3: none");
+ return TEE_ERROR_BAD_PARAMETERS;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/handle.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/handle.c
new file mode 100644
index 0000000..045989e
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/handle.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdlib.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include "handle.h"
+
+/*
+ * Define the initial capacity of the database. It should be a low number
+ * multiple of 2 since some databases a likely to only use a few handles.
+ * Since the algorithm is to doubles up when growing it shouldn't cause a
+ * noticeable overhead on large databases.
+ */
+#define HANDLE_DB_INITIAL_MAX_PTRS 4
+
+void handle_db_init(struct handle_db *db)
+{
+ TEE_MemFill(db, 0, sizeof(*db));
+}
+
+void handle_db_destroy(struct handle_db *db)
+{
+ if (db) {
+ TEE_Free(db->ptrs);
+ db->ptrs = NULL;
+ db->max_ptrs = 0;
+ }
+}
+
+uint32_t handle_get(struct handle_db *db, void *ptr)
+{
+ uint32_t n = 0;
+ void *p = NULL;
+ uint32_t new_max_ptrs = 0;
+
+ if (!db || !ptr)
+ return 0;
+
+ /* Try to find an empty location (index 0 is reserved as invalid) */
+ for (n = 1; n < db->max_ptrs; n++) {
+ if (!db->ptrs[n]) {
+ db->ptrs[n] = ptr;
+ return n;
+ }
+ }
+
+ /* No location available, grow the ptrs array */
+ if (db->max_ptrs)
+ new_max_ptrs = db->max_ptrs * 2;
+ else
+ new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS;
+
+ if (new_max_ptrs > SIZE_MAX/sizeof(void *))
+ return 0;
+
+ p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *));
+ if (!p)
+ return 0;
+ db->ptrs = p;
+ TEE_MemFill(db->ptrs + db->max_ptrs, 0,
+ (new_max_ptrs - db->max_ptrs) * sizeof(void *));
+ db->max_ptrs = new_max_ptrs;
+
+ /* Since n stopped at db->max_ptrs there is an empty location there */
+ db->ptrs[n] = ptr;
+ return n;
+}
+
+void *handle_put(struct handle_db *db, uint32_t handle)
+{
+ void *p = NULL;
+
+ if (!db || !handle || handle >= db->max_ptrs)
+ return NULL;
+
+ p = db->ptrs[handle];
+ db->ptrs[handle] = NULL;
+ return p;
+}
+
+void *handle_lookup(struct handle_db *db, uint32_t handle)
+{
+ if (!db || !handle || handle >= db->max_ptrs)
+ return NULL;
+
+ return db->ptrs[handle];
+}
+
+uint32_t handle_lookup_handle(struct handle_db *db, void *ptr)
+{
+ uint32_t n = 0;
+
+ if (ptr) {
+ for (n = 1; n < db->max_ptrs; n++) {
+ if (db->ptrs[n] == ptr) {
+ return n;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/handle.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/handle.h
new file mode 100644
index 0000000..8ba4726
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/handle.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __HANDLE_H
+#define __HANDLE_H
+
+#include <stddef.h>
+
+struct handle_db {
+ void **ptrs;
+ uint32_t max_ptrs;
+};
+
+#define HANDLE_DB_INITIALIZER { NULL, 0 }
+
+/*
+ * Initialize the handle database
+ */
+void handle_db_init(struct handle_db *db);
+
+/*
+ * Free all internal data structures of the database, but does not free
+ * the db pointer. The database is safe to reuse after it's destroyed, it
+ * just be empty again.
+ */
+void handle_db_destroy(struct handle_db *db);
+
+/*
+ * Allocate a new handle and assigns the supplied pointer to it,
+ * ptr must not be NULL.
+ * The function returns
+ * >= 0 on success and
+ * -1 on failure
+ */
+uint32_t handle_get(struct handle_db *db, void *ptr);
+
+/*
+ * Deallocate a handle. Returns the associated pointer of the handle
+ * the the handle was valid or NULL if it's invalid.
+ */
+void *handle_put(struct handle_db *db, uint32_t handle);
+
+/*
+ * Return the associated pointer of the handle if the handle is a valid
+ * handle.
+ * Returns NULL on failure.
+ */
+void *handle_lookup(struct handle_db *db, uint32_t handle);
+
+/* Return the handle associated to a pointer if found, else return 0 */
+uint32_t handle_lookup_handle(struct handle_db *db, void *ptr);
+
+#endif /*__HANDLE_H*/
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/mtk_key.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/mtk_key.h
new file mode 100644
index 0000000..9c9de1d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/mtk_key.h
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef __MTK_KEY_H__
+#define __MTK_KEY_H__
+
+#include <stdint.h>
+
+// #define PTA_GPT_TEST_PTA_UUID { 0x472567ad, 0xa180, 0x402c, \
+// { 0x50, 0x95, 0x7b, 0x4e, 0xd3, 0xe0, 0x5e, 0x83 } }
+
+#define PTA_MBOX_UUID {0x598e9628, 0xf233, 0x4c83, {0x8d, 0x4c, 0xbd, 0x2f, 0x0a, 0xd4, 0xb2, 0xe4}}
+
+/* command IDs to PTA */
+#define PTA_CMD_HSM_GEN_KEY_PAIR 1
+#define PTA_CMD_HSM_GEN_SYMM_KEY 2
+#define PTA_CMD_HSM_GET_KEY_BLOB 3
+#define PTA_CMD_HSM_GET_KEY_TABLE 4
+#define PTA_CMD_HSM_REBUILD_KEY_TABLE 5
+#define PTA_CMD_HSM_REBUILD_KEY_BLOB 6
+#define PTA_CMD_HSM_IMPORT_KEY 7
+#define PTA_CMD_HSM_EXPORT_KEY 8
+#define PTA_CMD_HSM_SEND_JOB 9
+#define PTA_CMD_HSM_DUMP_LOG 10
+#define PTA_CMD_HSM_DELETE_KEY 11
+
+/* The return value of key management in HSM */
+#define KM_OK (0)
+#define KM_FAIL (-1)
+#define KM_ERROR_BAD_ARGUMENTS (-2)
+#define KM_ERROR_GET_SLOT_FAIL (-3)
+#define KM_ERROR_RESOURCE_ALLOCATE_FAIL (-4)
+#define KM_ERROR_DEBLOB_FAIL (-5)
+#define KM_ERROR_ENBLOB_FAIL (-6)
+#define KM_ERROR_INVALID_CURVE (-7)
+#define KM_ERROR_UECC_FAIL (-8)
+#define KM_ERROR_SET_KEY_FAIL (-9)
+#define KM_ERROR_GET_KEY_FAIL (-10)
+#define KM_ERROR_INTERNAL_ERROR (-11)
+#define KM_ERROR_INVALID_ECC_KEY_PAIR (-12)
+
+#define MAX_KEY_NUMS (25)
+
+#define KEY_ALGO_ID_AES 1
+#define KEY_ALGO_ID_ECC 2
+
+#define MAX_BLOB_SIZE (256)
+#define BLOB_HEADER_SIZE (sizeof(key_blob_header))
+#define BLOB_MAC_SIZE (16)
+
+
+typedef struct key_blob_header_t
+{
+ uint32_t id;
+ uint32_t algorithm;
+ uint32_t body_size;
+} key_blob_header;
+
+typedef struct key_wrapper
+{
+ uint32_t size;
+ uint32_t addr32;
+} key_wrapper;
+
+typedef struct key_slot
+{
+ uint32_t valid;
+ uint32_t id;
+ uint32_t algorithm;
+ key_wrapper key_w;
+} key_slot;
+
+/* This structure must be consistent with the one in HSM side */
+typedef struct key_table_t
+{
+ uint32_t is_rebuild_done;
+ uint32_t nkeys;
+ key_slot slot[MAX_KEY_NUMS];
+} key_table;
+
+/* This enum must be consistent with the one in HSM side */
+typedef enum uECC_curve_id
+{
+ UECC_CURVE_ID_UNSUPPORT,
+ UECC_CURVE_ID_SECP160R1,
+ UECC_CURVE_ID_SECP192R1,
+ UECC_CURVE_ID_SECP224R1,
+ UECC_CURVE_ID_SECP256R1,
+ UECC_CURVE_ID_SECP256K1,
+ UECC_CURVE_ID_SECP384R1,
+} uECC_curve_id;
+
+typedef struct ecc_keypair_datastruct
+{
+ uECC_curve_id curve_id;
+ uint8_t public[96];
+ uint8_t private[48];
+ uint8_t reserved[12];
+} ecc_keypair_datastruct;
+
+#endif /*__MTK_KEY_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/object.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/object.c
new file mode 100644
index 0000000..2dd50d6
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/object.c
@@ -0,0 +1,874 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <inttypes.h>
+#include <sks_internal_abi.h>
+#include <string_ext.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include "attributes.h"
+#include "handle.h"
+#include "object.h"
+#include "pkcs11_attributes.h"
+#include "pkcs11_token.h"
+#include "processing.h"
+#include "sanitize_object.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+struct sks_object *sks_handle2object(uint32_t handle,
+ struct pkcs11_session *session)
+{
+ return handle_lookup(&session->object_handle_db, handle);
+}
+
+uint32_t sks_object2handle(struct sks_object *obj,
+ struct pkcs11_session *session)
+{
+ return handle_lookup_handle(&session->object_handle_db, obj);
+}
+
+/* Currently handle pkcs11 sessions and tokens */
+
+static struct object_list *get_session_objects(void *session)
+{
+ /* Currently supporting only pkcs11 session */
+ struct pkcs11_session *ck_session = session;
+
+ return pkcs11_get_session_objects(ck_session);
+}
+
+static struct ck_token *get_session_token(void *session)
+{
+ /* Currently supporting only pkcs11 session */
+ struct pkcs11_session *ck_session = session;
+
+ return pkcs11_session2token(ck_session);
+}
+
+/* Release resources of a non persistent object */
+static void cleanup_volatile_obj_ref(struct sks_object *obj)
+{
+ if (!obj)
+ return;
+
+ if (obj->key_handle != TEE_HANDLE_NULL)
+ TEE_FreeTransientObject(obj->key_handle);
+
+ if (obj->attribs_hdl != TEE_HANDLE_NULL) {
+ TEE_CloseObject(obj->attribs_hdl);
+ }
+
+ TEE_Free(obj->attributes);
+ TEE_Free(obj->uuid);
+ TEE_Free(obj);
+}
+
+
+/* Release resources of a persistent object including volatile resources */
+void cleanup_persistent_object(struct sks_object *obj,
+ struct ck_token *token)
+{
+ TEE_Result res;
+
+ if (!obj)
+ return;
+
+ /* Open handle with write properties to destroy the object */
+ if (obj->attribs_hdl != TEE_HANDLE_NULL) {
+ TEE_CloseObject(obj->attribs_hdl);
+ }
+
+ res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
+ obj->uuid, sizeof(TEE_UUID),
+ TEE_DATA_FLAG_ACCESS_WRITE_META,
+ &obj->attribs_hdl);
+ assert(!res);
+ if (res)
+ goto out;
+
+ TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl);
+
+out:
+ obj->attribs_hdl = TEE_HANDLE_NULL;
+ destroy_object_uuid(token, obj);
+
+ LIST_REMOVE(obj, link);
+
+ cleanup_volatile_obj_ref(obj);
+}
+
+/*
+ * destroy_object - destroy an SKS object
+ *
+ * @session - session requesting object destruction
+ * @object - reference to the sks object
+ * @session_object_only - true is only session object shall be destroyed
+ */
+void destroy_object(struct pkcs11_session *session,
+ struct sks_object *obj,
+ bool session_only)
+{
+#ifdef DEBUG
+ trace_attributes("[destroy]", obj->attributes);
+ if (obj->uuid)
+ MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid);
+#endif
+
+ /* Remove from session list only if was published */
+ if (obj->link.le_next || obj->link.le_prev)
+ LIST_REMOVE(obj, link);
+
+ if (session_only) {
+ /* Destroy object due to session closure */
+ handle_put(&session->object_handle_db,
+ sks_object2handle(obj, session));
+ cleanup_volatile_obj_ref(obj);
+
+ return;
+ }
+
+ /* Destroy target object (persistent or not) */
+ if (get_bool(obj->attributes, SKS_CKA_TOKEN)) {
+ assert(obj->uuid);
+ /* Try twice otherwise panic! */
+ if (unregister_persistent_object(session->token, obj->uuid) &&
+ unregister_persistent_object(session->token, obj->uuid))
+ TEE_Panic(0);
+
+ cleanup_persistent_object(obj, session->token);
+ handle_put(&session->object_handle_db,
+ sks_object2handle(obj, session));
+ } else {
+ handle_put(&session->object_handle_db,
+ sks_object2handle(obj, session));
+ cleanup_volatile_obj_ref(obj);
+ }
+}
+
+static struct sks_object *create_object_instance(struct sks_attrs_head *head)
+{
+ struct sks_object *obj = NULL;
+
+ obj = TEE_Malloc(sizeof(struct sks_object), TEE_MALLOC_FILL_ZERO);
+ if (!obj)
+ return NULL;
+
+ obj->key_handle = TEE_HANDLE_NULL;
+ obj->attribs_hdl = TEE_HANDLE_NULL;
+ obj->attributes = head;
+
+ return obj;
+}
+
+struct sks_object *create_token_object_instance(struct sks_attrs_head *head,
+ TEE_UUID *uuid)
+{
+ struct sks_object *obj = create_object_instance(head);
+
+ if (!obj)
+ return NULL;
+
+ obj->uuid = uuid;
+
+ return obj;
+}
+
+/*
+ * create_object - create an SKS object from its attributes and value
+ *
+ * @session - session requesting object creation
+ * @attributes - reference to serialized attributes
+ * @handle - generated handle for the created object
+ */
+uint32_t create_object(void *sess, struct sks_attrs_head *head,
+ uint32_t *out_handle)
+{
+ uint32_t rv = 0;
+ TEE_Result res = TEE_SUCCESS;
+ struct sks_object *obj = NULL;
+ struct pkcs11_session *session = (struct pkcs11_session *)sess;
+ uint32_t obj_handle = 0;
+
+#ifdef DEBUG
+ trace_attributes("[create]", head);
+#endif
+
+ /*
+ * We do not check the key attributes. At this point, key attributes
+ * are expected consistent and reliable.
+ */
+
+ obj = create_object_instance(head);
+ if (!obj)
+ return SKS_MEMORY;
+
+ /* Create a handle for the object in the session database */
+ obj_handle = handle_get(&session->object_handle_db, obj);
+ if (!obj_handle) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ if (get_bool(obj->attributes, SKS_CKA_TOKEN)) {
+ /*
+ * Get an ID for the persistent object
+ * Create the file
+ * Register the object in the persistent database
+ * (move the full sequence to persisent_db.c?)
+ */
+ size_t size = attributes_size(obj->attributes);
+
+ rv = create_object_uuid(get_session_token(session), obj);
+ if (rv)
+ goto bail;
+
+ res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
+ obj->uuid, sizeof(TEE_UUID),
+ TEE_DATA_FLAG_ACCESS_READ |
+ TEE_DATA_FLAG_ACCESS_WRITE |
+ TEE_DATA_FLAG_ACCESS_WRITE_META,
+ TEE_HANDLE_NULL,
+ obj->attributes, size,
+ &obj->attribs_hdl);
+ if (res) {
+ rv = tee2sks_error(res);
+ goto bail;
+ }
+
+ rv = register_persistent_object(get_session_token(session),
+ obj->uuid);
+ if (rv)
+ goto bail;
+
+ LIST_INSERT_HEAD(&session->token->object_list, obj, link);
+ } else {
+ rv = SKS_OK;
+ LIST_INSERT_HEAD(get_session_objects(session), obj, link);
+ }
+
+
+ *out_handle = obj_handle;
+
+bail:
+ if (rv) {
+ handle_put(&session->object_handle_db, obj_handle);
+ if (get_bool(obj->attributes, SKS_CKA_TOKEN))
+ cleanup_persistent_object(obj, session->token);
+ else
+ cleanup_volatile_obj_ref(obj);
+ }
+
+ return rv;
+}
+
+uint32_t entry_destroy_object(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ uint32_t object_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_object *object = NULL;
+ uint32_t rv = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ object = sks_handle2object(object_handle, session);
+ if (!object)
+ return SKS_BAD_PARAM;
+
+ destroy_object(session, object, false);
+ handle_put(&session->object_handle_db, object_handle);
+
+ IMSG("SKSs%" PRIu32 ": destroy object 0x%" PRIx32,
+ session_handle, object_handle);
+
+ return rv;
+}
+
+static uint32_t token_obj_matches_ref(struct sks_attrs_head *req_attrs,
+ struct sks_object *obj)
+{
+ uint32_t rv = 0;
+
+ if (!obj->attributes)
+ return SKS_NOT_FOUND;
+
+ if (!attributes_match_reference(obj->attributes, req_attrs))
+ return SKS_NOT_FOUND;
+
+ rv = SKS_OK;
+
+ return rv;
+}
+
+static void release_find_obj_context(struct pkcs11_session *session,
+ struct pkcs11_find_objects *find_ctx)
+{
+ size_t idx = 0;
+
+ if (!find_ctx)
+ return;
+
+ /* Release handles not yet published to client */
+ idx = find_ctx->next;
+ if (idx < find_ctx->temp_start)
+ idx = find_ctx->temp_start;
+
+ for (;idx < find_ctx->count; idx++)
+ handle_put(&session->object_handle_db, find_ctx->handles[idx]);
+
+ TEE_Free(find_ctx->attributes);
+ TEE_Free(find_ctx->handles);
+ TEE_Free(find_ctx);
+}
+
+/* TODO : not finished */
+uint32_t check_key_object_not_generated(struct pkcs11_session *session,
+ struct sks_attrs_head *req_attrs)
+{
+ uint32_t rv = SKS_OK;
+ struct sks_object *obj = NULL;
+ uint32_t *id_ptr = NULL;
+ uint32_t id_len = 0;
+
+ if (req_attrs == NULL)
+ return SKS_BAD_PARAM;
+
+ rv = get_attribute_ptr(req_attrs, SKS_CKA_ID, &id_ptr, &id_len);
+ if (rv) {
+ IMSG("[%s][%d] no SKS_CKA_ID in attributes!\n", __FUNCTION__, __LINE__);
+ goto bail;
+ }
+
+
+ return SKS_OK;
+bail:
+ return rv;
+}
+
+/*
+ * Entry for command SKS_CMD_FIND_OBJECTS_INIT
+ */
+uint32_t entry_find_objects_init(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_object_head *template = NULL;
+ struct sks_attrs_head *req_attrs = NULL;
+ struct sks_object *obj = NULL;
+ struct pkcs11_find_objects *find_ctx = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session) {
+ rv = SKS_CKR_SESSION_HANDLE_INVALID;
+ goto bail;
+ }
+
+ /* Search objects only if no operation is on-going */
+ if (session_is_active(session)) {
+ rv = SKS_CKR_OPERATION_ACTIVE;
+ goto bail;
+ }
+
+ if (session->find_ctx) {
+ EMSG("Active object search already in progress");
+ rv = SKS_FAILED;
+ goto bail;
+ }
+
+ /* Must zero init the structure */
+ find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO);
+ if (!find_ctx) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ rv = sanitize_client_object(&req_attrs, template,
+ sizeof(*template) + template->attrs_size);
+ if (rv)
+ goto bail;
+
+ TEE_Free(template);
+ template = NULL;
+
+ switch (get_class(req_attrs)) {
+ case SKS_UNDEFINED_ID:
+ /* Unspecified class searches among data objects */
+ case SKS_CKO_CERTIFICATE:
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ case SKS_CKO_DATA:
+ break;
+ default:
+ EMSG("Find object of class %s (%u) is not supported",
+ sks2str_class(get_class(req_attrs)),
+ get_class(req_attrs));
+ rv = SKS_CKR_ARGUMENTS_BAD;
+ goto bail;
+
+ }
+
+ /*
+ * Scan all objects (sessions and persistent ones) and set a list of
+ * candidates that match caller attributes. First scan all current
+ * session objects (that are visible to the session). Then scan all
+ * remaining persistent object for which no session object handle was
+ * published to the client.
+ */
+
+ LIST_FOREACH(obj, &session->object_list, link) {
+ uint32_t *handles = NULL;
+
+ rv = check_access_attrs_against_token(session, obj->attributes);
+ if (rv)
+ continue;
+
+ if (!attributes_match_reference(obj->attributes, req_attrs))
+ continue;
+
+ handles = TEE_Realloc(find_ctx->handles,
+ (find_ctx->count + 1) * sizeof(*handles));
+ if (!handles) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+ find_ctx->handles = handles;
+
+ *(find_ctx->handles + find_ctx->count) =
+ sks_object2handle(obj, session);
+ find_ctx->count++;
+ }
+
+ /* Remaining handles are those not yet published by the session */
+ find_ctx->temp_start = find_ctx->count;
+
+
+ LIST_FOREACH(obj, &session->token->object_list, link) {
+ uint32_t obj_handle = 0;
+ uint32_t *handles = NULL;
+
+ /*
+ * If there are no attributes specified, we return
+ * every object
+ */
+ if (req_attrs->attrs_count) {
+ rv = token_obj_matches_ref(req_attrs, obj);
+ if (rv == SKS_NOT_FOUND)
+ continue;
+ if (rv != SKS_OK)
+ goto bail;
+ }
+
+ // rv = check_access_attrs_against_token(session, obj->attributes);
+ // if (rv)
+ // continue;
+
+ /* Object may not yet be published in the session */
+ obj_handle = sks_object2handle(obj, session);
+ if (!obj_handle) {
+ obj_handle = handle_get(&session->object_handle_db,
+ obj);
+ if (!obj_handle) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+ }
+
+ handles = TEE_Realloc(find_ctx->handles,
+ (find_ctx->count + 1) * sizeof(*handles));
+ if (!handles) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ /* Store object handle for later publishing */
+ find_ctx->handles = handles;
+ *(handles + find_ctx->count) = obj_handle;
+ find_ctx->count++;
+ }
+
+ if (rv == SKS_NOT_FOUND)
+ rv = SKS_OK;
+
+ /* Save target attributes to search (if needed later) */
+ find_ctx->attributes = req_attrs;
+ req_attrs = NULL;
+ session->find_ctx = find_ctx;
+ find_ctx = NULL;
+ rv = SKS_OK;
+
+bail:
+ TEE_Free(req_attrs);
+ TEE_Free(template);
+ release_find_obj_context(session, find_ctx);
+
+ return rv;
+}
+
+/*
+ * Entry for command SKS_CMD_FIND_OBJECTS
+ */
+uint32_t entry_find_objects(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct pkcs11_find_objects *ctx = NULL;
+ uint32_t *out_handles = NULL;
+ size_t out_count = 0;
+ size_t count = 0;
+ size_t idx = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ out_count = out->memref.size / sizeof(uint32_t);
+ out_handles = (uint32_t *)(uintptr_t)out->memref.buffer;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ ctx = session->find_ctx;
+
+ /*
+ * TODO: should we check again if these handles are valid?
+ */
+ if (!ctx)
+ return SKS_CKR_OPERATION_NOT_INITIALIZED;
+
+ for (count = 0, idx = ctx->next; idx < ctx->count; idx++, count++) {
+ struct sks_object *obj = NULL;
+
+ if (count >= out_count)
+ break;
+
+ *(out_handles + count) = *(ctx->handles + idx);
+ ctx->next = idx + 1;
+
+ if (idx < session->find_ctx->temp_start)
+ continue;
+
+ /* Newly published handles: store in session list */
+ obj = handle_lookup(&session->object_handle_db,
+ *(ctx->handles + idx));
+ if (!obj)
+ TEE_Panic(0);
+
+ }
+
+ /* Update output buffer according the number of handles provided */
+ out->memref.size = count * sizeof(uint32_t);
+
+ IMSG("SKSs%" PRIu32 ": finding objects", session_handle);
+
+ return SKS_OK;
+}
+
+void release_session_find_obj_context(struct pkcs11_session *session)
+{
+ release_find_obj_context(session, session->find_ctx);
+ session->find_ctx = NULL;
+}
+
+/*
+ * Entry for command SKS_CMD_FIND_OBJECTS_FINAL
+ */
+uint32_t entry_find_objects_final(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 9;
+ struct pkcs11_session *session = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ if (!session->find_ctx)
+ return SKS_CKR_OPERATION_NOT_INITIALIZED;
+
+ release_session_find_obj_context(session);
+
+ return SKS_OK;
+}
+
+
+/*
+ * Entry for command SKS_CMD_GET_OBJECT_SIZE
+ */
+uint32_t entry_get_object_size(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ uint32_t object_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_object *object = NULL;
+ uint32_t rv = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < sizeof(uint32_t))
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ object = sks_handle2object(object_handle, session);
+ if (!object)
+ return SKS_CKR_OBJECT_HANDLE_INVALID;
+
+ *(uint32_t *)out->memref.buffer = SKS_CK_UNAVAILABLE_INFORMATION;
+ out->memref.size = sizeof(uint32_t);
+
+ return rv;
+}
+
+/*
+ * Entry for command SKS_CMD_GET_ATTRIBUTE_VALUE
+ */
+uint32_t entry_get_attribute_value(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_object_head *template = NULL;
+ struct sks_object *obj = NULL;
+ uint32_t object_handle = 0;
+ char *cur = NULL;
+ size_t len = 0;
+ char *end = NULL;
+ bool attr_sensitive = 0;
+ bool attr_type_invalid = 0;
+ bool buffer_too_small = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session) {
+ rv = SKS_CKR_SESSION_HANDLE_INVALID;
+ goto bail;
+ }
+
+ obj = sks_handle2object(object_handle, session);
+ if (!obj) {
+ rv = SKS_CKR_OBJECT_HANDLE_INVALID;
+ goto bail;
+ }
+
+ rv = check_access_attrs_against_token(session, obj->attributes);
+ if (rv) {
+ rv = SKS_CKR_OBJECT_HANDLE_INVALID;
+ goto bail;
+ }
+
+ /* iterate over attributes and set their values */
+ /*
+ * 1. If the specified attribute (i.e., the attribute specified by the
+ * type field) for the object cannot be revealed because the object is
+ * sensitive or unextractable, then the ulValueLen field in that triple
+ * is modified to hold the value CK_UNAVAILABLE_INFORMATION.
+ *
+ * 2. Otherwise, if the specified value for the object is invalid (the
+ * object does not possess such an attribute), then the ulValueLen field
+ * in that triple is modified to hold the value
+ * CK_UNAVAILABLE_INFORMATION.
+ *
+ * 3. Otherwise, if the pValue field has the value NULL_PTR, then the
+ * ulValueLen field is modified to hold the exact length of the
+ * specified attribute for the object.
+ *
+ * 4. Otherwise, if the length specified in ulValueLen is large enough
+ * to hold the value of the specified attribute for the object, then
+ * that attribute is copied into the buffer located at pValue, and the
+ * ulValueLen field is modified to hold the exact length of the
+ * attribute.
+ *
+ * 5. Otherwise, the ulValueLen field is modified to hold the value
+ * CK_UNAVAILABLE_INFORMATION.
+ */
+ cur = (char *)template + sizeof(struct sks_object_head);
+ end = cur + template->attrs_size;
+
+ for (; cur < end; cur += len) {
+ struct sks_attribute_head *cli_ref_orgi;
+ struct sks_attribute_head tmp;
+ struct sks_attribute_head *cli_ref;
+
+ cli_ref_orgi = (struct sks_attribute_head *)(void *)cur;
+ TEE_MemMove(&tmp,cli_ref_orgi,sizeof(tmp));
+
+ len = sizeof(tmp)+tmp.size;
+ cli_ref = TEE_Malloc(len,TEE_USER_MEM_HINT_NO_FILL_ZERO);
+
+ if (!cli_ref) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ TEE_MemMove(cli_ref,cli_ref_orgi,len);
+
+ /* Check 1. */
+ if (!attribute_is_exportable(cli_ref, obj)) {
+ cli_ref->size = SKS_CK_UNAVAILABLE_INFORMATION;
+ attr_sensitive = 1;
+ continue;
+ }
+
+ /*
+ * We assume that if size is 0, pValue was NULL, so we return
+ * the size of the required buffer for it (3., 4.)
+ */
+ rv = get_attribute(obj->attributes, cli_ref->id,
+ cli_ref->size ? cli_ref->data : NULL,
+ &(cli_ref->size));
+ /* Check 2. */
+ switch (rv) {
+ case SKS_OK:
+ break;
+ case SKS_NOT_FOUND:
+ cli_ref->size = SKS_CK_UNAVAILABLE_INFORMATION;
+ attr_type_invalid = 1;
+ break;
+ case SKS_SHORT_BUFFER:
+ buffer_too_small = 1;
+ break;
+ default:
+ rv = SKS_ERROR;
+ TEE_MemMove(cli_ref_orgi,cli_ref,len);
+ TEE_Free(cli_ref);
+ goto bail;
+ }
+
+ TEE_MemMove(cli_ref_orgi,cli_ref,len);
+ TEE_Free(cli_ref);
+ }
+
+ /*
+ * If case 1 applies to any of the requested attributes, then the call
+ * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to
+ * any of the requested attributes, then the call should return the
+ * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the
+ * requested attributes, then the call should return the value
+ * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes
+ * is applicable, Cryptoki may return any of them. Only if none of them
+ * applies to any of the requested attributes will CKR_OK be returned.
+ */
+
+ rv = SKS_OK;
+ if (attr_sensitive)
+ rv = SKS_CKR_ATTRIBUTE_SENSITIVE;
+ if (attr_type_invalid)
+ rv = SKS_CKR_ATTRIBUTE_TYPE_INVALID;
+ if (buffer_too_small)
+ rv = SKS_CKR_BUFFER_TOO_SMALL;
+
+ /* Move updated template to out buffer */
+ TEE_MemMove(out->memref.buffer, template, out->memref.size);
+
+ IMSG("SKSs%" PRIu32 ": get attributes 0x%" PRIx32,
+ session_handle, object_handle);
+
+bail:
+ TEE_Free(template);
+ template = NULL;
+
+ return rv;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/object.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/object.h
new file mode 100644
index 0000000..31d93a7
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/object.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#ifndef __SKS_OBJECT_H__
+#define __SKS_OBJECT_H__
+
+#include <sks_internal_abi.h>
+#include <sys/queue.h>
+#include <tee_internal_api.h>
+
+struct pkcs11_session;
+struct ck_token;
+
+struct sks_object {
+ LIST_ENTRY(sks_object) link;
+ /* pointer to the serialized object attributes */
+ void *attributes;
+ TEE_ObjectHandle key_handle; /* Valid handle for TEE operations */
+ uint32_t key_type; /* TEE type of key_handle */
+
+ /* These are for persistent/token objects */
+ TEE_UUID *uuid;
+ TEE_ObjectHandle attribs_hdl;
+};
+
+LIST_HEAD(object_list, sks_object);
+
+struct sks_object *sks_handle2object(uint32_t client_handle,
+ struct pkcs11_session *session);
+
+uint32_t sks_object2handle(struct sks_object *obj,
+ struct pkcs11_session *session);
+
+struct sks_object *create_token_object_instance(struct sks_attrs_head *head,
+ TEE_UUID *uuid);
+
+uint32_t create_object(void *session, struct sks_attrs_head *attributes,
+ uint32_t *handle);
+
+void cleanup_persistent_object(struct sks_object *obj,
+ struct ck_token *token);
+
+void destroy_object(struct pkcs11_session *session, struct sks_object *object,
+ bool session_object_only);
+
+/*
+ * Entry function called from the SKS command parser
+ */
+uint32_t entry_destroy_object(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_find_objects_init(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_find_objects(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_find_objects_final(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_get_object_size(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_get_attribute_value(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+void release_session_find_obj_context(struct pkcs11_session *session);
+
+uint32_t check_key_object_not_generated(struct pkcs11_session *session,
+ struct sks_attrs_head *req_attrs);
+
+#endif /*__SKS_OBJECT_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/persistent_token.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/persistent_token.c
new file mode 100644
index 0000000..2f112ff
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/persistent_token.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <sks_ta.h>
+#include <string.h>
+#include <string_ext.h>
+#include <tee_internal_api_extensions.h>
+#include <util.h>
+
+#include "pkcs11_token.h"
+#include "sks_helpers.h"
+
+/*
+ * Token persistent objects
+ *
+ * The persistent objects are each identified by a UUID.
+ * The persistent object database stores the list of the UUIDs registered. For
+ * each it is expected that a file of ID "UUID" is store in the OP-TEE secure
+ * storage.
+ */
+
+/* 'X' will be replaced by the token decimal id (up to 9!) */
+#define TOKEN_DB_FILE_BASE "token.db.X"
+
+void close_persistent_db(struct ck_token *token)
+{
+ int n = 0;
+
+ for (n = 0; n < SKS_MAX_USERS; n++) {
+ TEE_CloseObject(token->pin_hdl[n]);
+ token->pin_hdl[n] = TEE_HANDLE_NULL;
+ }
+
+ TEE_CloseObject(token->db_hdl);
+ token->db_hdl = TEE_HANDLE_NULL;
+}
+
+int update_persistent_db(struct ck_token *token, size_t offset, size_t size)
+{
+ unsigned int token_id = get_token_id(token);
+ char file[] = TOKEN_DB_FILE_BASE;
+ uint8_t *field = (uint8_t *)token->db_main + offset;
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ if (snprintf(file + sizeof(file) - 2, 2, "%1d", token_id) >= 2)
+ TEE_Panic(0);
+
+ if (token->db_hdl == TEE_HANDLE_NULL)
+ return 1;
+
+ res = TEE_SeekObjectData(token->db_hdl, offset, TEE_DATA_SEEK_SET);
+ if (res)
+ return tee2sks_error(res);
+
+ res = TEE_WriteObjectData(token->db_hdl, field, size);
+ if (res)
+ return tee2sks_error(res);
+
+ return 0;
+}
+
+static void init_pin_keys(struct ck_token *token, unsigned int uid)
+{
+ TEE_Result res = TEE_ERROR_GENERIC;
+ unsigned int token_id = get_token_id(token);
+ TEE_ObjectHandle *key_hdl = &token->pin_hdl[uid];
+ char file[32] = { 0 };
+
+ assert(token_id < 10 && uid < 10);
+
+ if (snprintf(file, 32, "token.db.%1d-pin%1d", token_id, uid) >= 32)
+ TEE_Panic(0);
+
+ res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
+ file, sizeof(file), 0, key_hdl);
+ if (res == TEE_SUCCESS) {
+ DMSG("PIN key found");
+ return;
+ }
+
+ if (res == TEE_ERROR_ITEM_NOT_FOUND) {
+ TEE_Attribute attr;
+ TEE_ObjectHandle hdl = TEE_HANDLE_NULL;
+ uint8_t pin_key[16] = { 0 };
+
+ TEE_MemFill(&attr, 0, sizeof(attr));
+
+ TEE_GenerateRandom(pin_key, sizeof(pin_key));
+ TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE,
+ pin_key, sizeof(pin_key));
+
+ res = TEE_AllocateTransientObject(TEE_TYPE_AES, 128, &hdl);
+ if (res)
+ TEE_Panic(0);
+
+ res = TEE_PopulateTransientObject(hdl, &attr, 1);
+ if (res)
+ TEE_Panic(0);
+
+ res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
+ file, sizeof(file), 0,
+ hdl,
+ pin_key, sizeof(pin_key),
+ key_hdl);
+ if (res)
+ TEE_Panic(0);
+
+ TEE_FreeTransientObject(hdl);
+ return;
+ }
+
+ TEE_Panic(0);
+}
+
+/* UUID for persistent object */
+uint32_t create_object_uuid(struct ck_token *token __unused,
+ struct sks_object *obj)
+{
+ assert(!obj->uuid);
+
+ obj->uuid = TEE_Malloc(sizeof(TEE_UUID),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!obj->uuid)
+ return SKS_MEMORY;
+
+ TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID));
+
+ /*
+ * TODO: check uuid against already registered one (in persistent
+ * database) and the pending created uuids (not already registered
+ * if any).
+ */
+ return SKS_OK;
+}
+
+void destroy_object_uuid(struct ck_token *token __unused,
+ struct sks_object *obj)
+{
+ if (!obj->uuid)
+ return;
+
+ /* TODO: check uuid is not still registered in persistent db ? */
+ TEE_Free(obj->uuid);
+ obj->uuid = NULL;
+}
+
+uint32_t get_persistent_objects_list(struct ck_token *token,
+ TEE_UUID *array, size_t *size)
+{
+ size_t out_size = *size;
+
+ *size = token->db_objs->count * sizeof(TEE_UUID);
+
+ if (out_size < *size)
+ return SKS_SHORT_BUFFER;
+
+ if (array)
+ TEE_MemMove(array, token->db_objs->uuids, *size);
+
+ return SKS_OK;
+}
+
+uint32_t unregister_persistent_object(struct ck_token *token, TEE_UUID *uuid)
+{
+ int index = 0;
+ int count = 0;
+ struct token_persistent_objs *ptr;
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ if (!uuid)
+ return SKS_OK;
+
+ for (index = (int)(token->db_objs->count) - 1; index >= 0; index--) {
+ if (!TEE_MemCompare(token->db_objs->uuids + index,
+ uuid, sizeof(TEE_UUID)))
+ break;
+ }
+
+ if (index < 0) {
+ EMSG("Cannot unregister an invalid persistent object");
+ return SKS_NOT_FOUND;
+ }
+
+ ptr = TEE_Malloc(sizeof(struct token_persistent_objs) +
+ ((token->db_objs->count - 1) * sizeof(TEE_UUID)),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!ptr)
+ return SKS_MEMORY;
+
+ res = TEE_SeekObjectData(token->db_hdl,
+ sizeof(struct token_persistent_main),
+ TEE_DATA_SEEK_SET);
+ if (res) {
+ EMSG("Failed to read database");
+ TEE_Free(ptr);
+ return tee2sks_error(res);
+ }
+
+ TEE_MemMove(ptr, token->db_objs,
+ sizeof(struct token_persistent_objs) +
+ index * sizeof(TEE_UUID));
+
+ ptr->count--;
+ count = ptr->count - index;
+
+ TEE_MemMove(&ptr->uuids[index],
+ &token->db_objs->uuids[index + 1],
+ count * sizeof(TEE_UUID));
+
+ res = TEE_WriteObjectData(token->db_hdl, ptr,
+ sizeof(struct token_persistent_objs) +
+ ptr->count * sizeof(TEE_UUID));
+ if (res) {
+ EMSG("Failed to update database");
+ TEE_Free(ptr);
+ return tee2sks_error(res);
+ }
+
+ TEE_Free(token->db_objs);
+ token->db_objs = ptr;
+
+ return SKS_OK;
+}
+
+uint32_t register_persistent_object(struct ck_token *token, TEE_UUID *uuid)
+{
+ int count = 0;
+ void *ptr = NULL;
+ size_t __maybe_unused size = 0;
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ for (count = (int)token->db_objs->count - 1; count >= 0; count--)
+ if (!TEE_MemCompare(token->db_objs->uuids + count, uuid,
+ sizeof(TEE_UUID)))
+ TEE_Panic(0);
+
+ count = token->db_objs->count;
+ ptr = TEE_Realloc(token->db_objs,
+ sizeof(struct token_persistent_objs) +
+ ((count + 1) * sizeof(TEE_UUID)));
+ if (!ptr)
+ return SKS_MEMORY;
+
+ token->db_objs = ptr;
+ TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID));
+
+ size = sizeof(struct token_persistent_main) +
+ sizeof(struct token_persistent_objs) +
+ count * sizeof(TEE_UUID);
+
+ res = TEE_TruncateObjectData(token->db_hdl, size + sizeof(TEE_UUID));
+ if (res)
+ return tee2sks_error(res);
+
+ res = TEE_SeekObjectData(token->db_hdl,
+ sizeof(struct token_persistent_main),
+ TEE_DATA_SEEK_SET);
+ if (res)
+ return tee2sks_error(res);
+
+ token->db_objs->count++;
+
+ res = TEE_WriteObjectData(token->db_hdl, token->db_objs,
+ sizeof(struct token_persistent_objs) +
+ token->db_objs->count * sizeof(TEE_UUID));
+ if (res) {
+ token->db_objs->count--;
+ return tee2sks_error(res);
+ }
+
+ return SKS_OK;
+}
+
+static uint32_t token_load_obj_attribs(struct sks_object *obj)
+{
+ uint32_t rv = 0;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ TEE_ObjectHandle hdl = obj->attribs_hdl;
+ TEE_ObjectInfo info;
+ struct sks_attrs_head *attr = NULL;
+ uint32_t read_bytes = 0;
+
+ if (hdl != TEE_HANDLE_NULL) {
+ IMSG("Handle attributes already set for this object");
+ return SKS_OK;
+ }
+
+ res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
+ obj->uuid, sizeof(*obj->uuid),
+ TEE_DATA_FLAG_ACCESS_READ,
+ &hdl);
+ if (res) {
+ EMSG("OpenPersistent failed 0x%" PRIx32, res);
+ return tee2sks_error(res);
+ }
+
+ TEE_MemFill(&info, 0, sizeof(info));
+ res = TEE_GetObjectInfo1(hdl, &info);
+ if (res) {
+ EMSG("GetObjectInfo failed 0x%" PRIx32, res);
+ rv = tee2sks_error(res);
+ goto bail;
+ }
+
+ attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO);
+ if (!attr) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes);
+ if (!res) {
+ res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET);
+ if (res)
+ EMSG("Seek to 0 failed 0x%" PRIx32, res);
+ }
+
+ if (res) {
+ rv = tee2sks_error(res);
+ EMSG("Read %" PRIu32 " bytes, failed 0x%" PRIx32,
+ read_bytes, res);
+ goto bail;
+ }
+ if (read_bytes != info.dataSize) {
+ EMSG("Read %" PRIu32 " bytes, expected 0x%" PRIu32,
+ read_bytes, info.dataSize);
+ rv = SKS_ERROR;
+ goto bail;
+ }
+
+ obj->attributes = attr;
+ attr = NULL;
+ obj->attribs_hdl = hdl;
+ hdl = TEE_HANDLE_NULL;
+ rv = SKS_OK;
+
+bail:
+ TEE_Free(attr);
+ if (obj->attribs_hdl == TEE_HANDLE_NULL && hdl != TEE_HANDLE_NULL) {
+ TEE_CloseObject(hdl);
+ }
+
+ return rv;
+}
+
+/*
+ * Return the token instance, either initialized from reset or initialized
+ * from the token persistent state if found.
+ */
+struct ck_token *init_token_db(unsigned int token_id)
+{
+ struct ck_token *token = get_token(token_id);
+ TEE_Result res = TEE_ERROR_GENERIC;
+ char db_file[] = TOKEN_DB_FILE_BASE;
+ TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
+ /* Copy persistent database: main db and object db */
+ struct token_persistent_main *db_main = NULL;
+ struct token_persistent_objs *db_objs = NULL;
+ int n = 0;
+ void *ptr = NULL;
+
+ if (!token)
+ return NULL;
+
+ for (n = 0; n < SKS_MAX_USERS; n++)
+ init_pin_keys(token, n);
+
+ LIST_INIT(&token->object_list);
+
+ db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO);
+ db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO);
+ if (!db_main || !db_objs)
+ goto error;
+
+ /* Persistent object ID is the string with last char replaced */
+ if (snprintf(db_file + sizeof(db_file) - 2, 2, "%1d", token_id) >= 2)
+ TEE_Panic(0);
+
+ res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
+ db_file, sizeof(db_file),
+ TEE_DATA_FLAG_ACCESS_READ |
+ TEE_DATA_FLAG_ACCESS_WRITE,
+ &db_hdl);
+ if (res == TEE_SUCCESS) {
+ uint32_t size = 0;
+ size_t idx = 0;
+
+ IMSG("SKSt%u: load db", token_id);
+
+ size = sizeof(*db_main);
+ res = TEE_ReadObjectData(db_hdl, db_main, size, &size);
+ if (res || size != sizeof(*db_main))
+ TEE_Panic(0);
+
+ size = sizeof(*db_objs);
+ res = TEE_ReadObjectData(db_hdl, db_objs, size, &size);
+ if (res || size != sizeof(*db_objs))
+ TEE_Panic(0);
+
+ if (db_objs->count > (SIZE_MAX - size)/sizeof(TEE_UUID))
+ goto error;
+
+ size += db_objs->count * sizeof(TEE_UUID);
+ ptr = TEE_Realloc(db_objs, size);
+ if (!ptr)
+ goto error;
+
+ db_objs = ptr;
+ size -= sizeof(struct token_persistent_objs);
+ res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size, &size);
+ if (res || size != (db_objs->count * sizeof(TEE_UUID)))
+ TEE_Panic(0);
+
+ for (idx = 0; idx < db_objs->count; idx++) {
+ /* Create an empty object instance */
+ struct sks_object *obj = NULL;
+ TEE_UUID *uuid = NULL;
+
+ uuid = TEE_Malloc(sizeof(TEE_UUID),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!uuid)
+ goto error;
+
+ TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid));
+
+ obj = create_token_object_instance(NULL, uuid);
+ if (!obj){
+ TEE_Free(uuid);
+ TEE_Panic(0);
+ }
+
+ if (token_load_obj_attribs(obj) != SKS_OK)
+ EMSG("Unable to load object attributes from db");
+
+ LIST_INSERT_HEAD(&token->object_list, obj, link);
+ }
+
+ } else if (res == TEE_ERROR_ITEM_NOT_FOUND) {
+
+ IMSG("SKSt%u: init db", token_id);
+
+ TEE_MemFill(db_main, 0, sizeof(*db_main));
+ TEE_MemFill(db_main->label, '*', sizeof(db_main->label));
+
+ /*
+ * Not supported:
+ * SKS_TOKEN_FULLY_RESTORABLE
+ * TODO: check these:
+ * SKS_TOKEN_HAS_CLOCK => related to TEE time secure level
+ */
+ db_main->flags = SKS_CKFT_SO_PIN_TO_BE_CHANGED |
+ SKS_CKFT_USER_PIN_TO_BE_CHANGED |
+ SKS_CKFT_RNG |
+ SKS_CKFT_DUAL_CRYPTO_OPERATIONS |
+ SKS_CKFT_LOGIN_REQUIRED;
+
+ /* 2 files: persistent state + persistent object references */
+ res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
+ db_file, sizeof(db_file),
+ TEE_DATA_FLAG_ACCESS_READ |
+ TEE_DATA_FLAG_ACCESS_WRITE,
+ TEE_HANDLE_NULL,
+ db_main, sizeof(*db_main),
+ &db_hdl);
+ if (res)
+ TEE_Panic(0);
+
+ res = TEE_TruncateObjectData(db_hdl, sizeof(*db_main) +
+ sizeof(*db_objs));
+ if (res)
+ TEE_Panic(0);
+
+ res = TEE_SeekObjectData(db_hdl, sizeof(*db_main),
+ TEE_DATA_SEEK_SET);
+ if (res)
+ TEE_Panic(0);
+
+ db_objs->count = 0;
+ res = TEE_WriteObjectData(db_hdl, db_objs, sizeof(*db_objs));
+ if (res)
+ TEE_Panic(0);
+
+ } else {
+ /* Can't do anything... */
+ return NULL;
+ }
+
+ token->db_main = db_main;
+ token->db_objs = db_objs;
+ token->db_hdl = db_hdl;
+ TEE_SeekObjectData(token->db_hdl, 0, TEE_DATA_SEEK_SET);
+
+ return token;
+
+error:
+ TEE_Free(db_main);
+ TEE_Free(db_objs);
+ if (db_hdl != TEE_HANDLE_NULL)
+ TEE_CloseObject(db_hdl);
+
+ return NULL;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_attributes.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_attributes.c
new file mode 100644
index 0000000..0a1052c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_attributes.c
@@ -0,0 +1,1829 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <sks_internal_abi.h>
+#include <sks_ta.h>
+#include <string_ext.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <util.h>
+
+#include "attributes.h"
+#include "handle.h"
+#include "object.h"
+#include "pkcs11_attributes.h"
+#include "pkcs11_token.h"
+#include "processing.h"
+#include "sanitize_object.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+/* Byte size of CKA_ID attribute when generated locally */
+#define SKS_CKA_DEFAULT_SIZE 16
+
+struct pkcs11_mechachism_modes {
+ uint32_t id;
+ uint32_t flags;
+ bool available;
+ bool one_shot;
+};
+
+/*
+ * SKS_CKFM_EC_F_P
+ * SKS_CKFM_EC_F_2M
+ * SKS_CKFM_EC_ECPARAMETERS
+ * SKS_CKFM_EC_NAMEDCURVE
+ * SKS_CKFM_EC_UNCOMPRESS
+ * SKS_CKFM_EC_COMPRESS
+ */
+#define SKS_ECM 0
+
+/* SKS_CKFM_HW: need to ask core one HW support of the mechanisms */
+#define SKS_M(_label, _dig, _enc, _dec, _sig, _ver, \
+ _sr, _vr, _der, _wra, _unw, _gen, _gpa, _1s) \
+ { \
+ .id = SKS_CKM_ ## _label, \
+ .one_shot = _1s, \
+ .flags = (_enc ? SKS_CKFM_ENCRYPT : 0) | \
+ (_dec ? SKS_CKFM_DECRYPT : 0) | \
+ (_dig ? SKS_CKFM_DIGEST : 0) | \
+ (_sig ? SKS_CKFM_SIGN : 0) | \
+ (_sr ? SKS_CKFM_SIGN_RECOVER : 0) | \
+ (_ver ? SKS_CKFM_VERIFY : 0) | \
+ (_vr ? SKS_CKFM_VERIFY_RECOVER : 0) | \
+ (_gen ? SKS_CKFM_GENERATE : 0) | \
+ (_gpa ? SKS_CKFM_GENERATE_PAIR : 0) | \
+ (_wra ? SKS_CKFM_WRAP : 0) | \
+ (_unw ? SKS_CKFM_UNWRAP : 0) | \
+ (_der ? SKS_CKFM_DERIVE : 0) | \
+ SKS_ECM, \
+ }
+
+static const __maybe_unused struct pkcs11_mechachism_modes pkcs11_modes[] = {
+ /*
+ * PKCS#11 directives on mechanism support for the several processing
+ * modes.
+ * 1: One shot processing only --------.
+ * Gp: Generate secret pair --------. |
+ * Ge: Generate secret value ----. | |
+ * Wr|Uw: Wrap/Unwrap -------. | | |
+ * Dr: Derive ----------. | | | |
+ * Sr|Vr: SignRecover/VerifyRecov --. | | | | |
+ * Si|Ve: Sign/Verify --------. | | | | | |
+ * En|De: Encrypt/Decrypt | | | | | | |
+ * Di: Digest -----. | | | | | | | |
+ * | / \ / \ / \ | / \ | | |
+ * Mechanism Di|En|De|Si|Ve|Sr|Vr|Dr|Wr|Uw|Ge|Gp|1
+ */
+ SKS_M(AES_ECB, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(AES_CBC, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(AES_CBC_PAD, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(AES_CTS, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(AES_CTR, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(AES_GCM, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(AES_CCM, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(AES_GMAC, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0),
+ SKS_M(AES_CMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(AES_CMAC_GENERAL, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(AES_ECB_ENCRYPT_DATA, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0),
+ SKS_M(AES_CBC_ENCRYPT_DATA, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0),
+ SKS_M(AES_KEY_GEN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0),
+
+ SKS_M(MTK_HSM_AES_KEY_GEN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0),
+
+ SKS_M(MTK_HSM_AES_ECB, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(MTK_HSM_AES_CBC, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(MTK_HSM_AES_CTR, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(MTK_HSM_AES_GCM, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(MTK_HSM_AES_CMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ /* Mechanism Di|En|De|Si|Ve|Sr|Vr|Dr|Wr|Uw|Ge|Gp|1 */
+ SKS_M(GENERIC_SECRET_KEY_GEN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0),
+ SKS_M(MD5_HMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA_1_HMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA224_HMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA256_HMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA384_HMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA512_HMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(AES_XCBC_MAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(MTK_HSM_SHA256_HMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(MTK_HSM_SHA384_HMAC, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ /* Mechanism Di|En|De|Si|Ve|Sr|Vr|Dr|Wr|Uw|Ge|Gp|1 */
+ SKS_M(EC_KEY_PAIR_GEN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0),
+ SKS_M(ECDSA, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1),
+ SKS_M(ECDSA_SHA1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(ECDSA_SHA224, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(ECDSA_SHA256, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(ECDSA_SHA384, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(ECDSA_SHA512, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(ECDH1_DERIVE, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0),
+ SKS_M(ECDH1_COFACTOR_DERIVE, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0),
+ SKS_M(ECMQV_DERIVE, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0),
+ SKS_M(ECDH_AES_KEY_WRAP, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ SKS_M(MTK_HSM_ECDSA, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1),
+ SKS_M(MTK_HSM_ECDSA_SHA1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1),
+ SKS_M(MTK_HSM_ECDSA_SHA224, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1),
+ SKS_M(MTK_HSM_ECDSA_SHA256, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1),
+ SKS_M(MTK_HSM_ECDSA_SHA384, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1),
+ SKS_M(MTK_HSM_ECDSA_SHA512, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1),
+ SKS_M(MTK_HSM_EC_KEY_PAIR_GEN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0),
+ /* Mechanism Di|En|De|Si|Ve|Sr|Vr|Dr|Wr|Uw|Ge|Gp|1 */
+ SKS_M(RSA_PKCS_KEY_PAIR_GEN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0),
+ SKS_M(RSA_PKCS, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1),
+ SKS_M(RSA_PKCS_PSS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1),
+ SKS_M(RSA_PKCS_OAEP, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1),
+ SKS_M(RSA_9796, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1),
+ SKS_M(RSA_X_509, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1),
+ SKS_M(SHA1_RSA_PKCS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0),
+ SKS_M(SHA1_RSA_PKCS_PSS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA256_RSA_PKCS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA384_RSA_PKCS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA512_RSA_PKCS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA256_RSA_PKCS_PSS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA384_RSA_PKCS_PSS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA512_RSA_PKCS_PSS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA224_RSA_PKCS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA224_RSA_PKCS_PSS, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(RSA_AES_KEY_WRAP, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
+ /* Mechanism Di|En|De|Si|Ve|Sr|Vr|Dr|Wr|Uw|Ge|Gp|1 */
+ SKS_M(MD5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA_1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA224, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA256, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA384, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ SKS_M(SHA512, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ /*
+ * Mechanism Di|En|De|Si|Ve|Sr|Vr|Dr|Wr|Uw|Ge|Gp|1
+ * | \_/ \_/ \_/ | \_/ | | |
+ * Di: Digest -----' | | | | | | | |
+ * En|De: Encrypt/Decrypt | | | | | | |
+ * Si|Ve: Sign/Verify --------' | | | | | |
+ * Sr|Vr: SignUpdate/VerifyRecover -' | | | | |
+ * Dr: Derive ----------' | | | |
+ * Wr|Uw: Wrap/Unwrap -------' | | |
+ * Ge: Generate secret value ----' | |
+ * Gp: Generate secret pair --------' |
+ * 1: One shot processing only --------'
+ */
+};
+
+static uint32_t sks_function2ckfm(enum processing_func function)
+{
+ switch (function) {
+ case SKS_FUNCTION_DIGEST:
+ return SKS_CKFM_DIGEST;
+ case SKS_FUNCTION_GENERATE:
+ return SKS_CKFM_GENERATE;
+ case SKS_FUNCTION_GENERATE_PAIR:
+ return SKS_CKFM_GENERATE_PAIR;
+ case SKS_FUNCTION_DERIVE:
+ return SKS_CKFM_DERIVE;
+ case SKS_FUNCTION_WRAP:
+ return SKS_CKFM_WRAP;
+ case SKS_FUNCTION_UNWRAP:
+ return SKS_CKFM_UNWRAP;
+ case SKS_FUNCTION_ENCRYPT:
+ return SKS_CKFM_ENCRYPT;
+ case SKS_FUNCTION_DECRYPT:
+ return SKS_CKFM_DECRYPT;
+ case SKS_FUNCTION_SIGN:
+ return SKS_CKFM_SIGN;
+ case SKS_FUNCTION_VERIFY:
+ return SKS_CKFM_VERIFY;
+ case SKS_FUNCTION_SIGN_RECOVER:
+ return SKS_CKFM_SIGN_RECOVER;
+ case SKS_FUNCTION_VERIFY_RECOVER:
+ return SKS_CKFM_VERIFY_RECOVER;
+ default:
+ return 0;
+ }
+}
+
+int check_pkcs11_mechanism_flags(uint32_t mechanism_type, uint32_t flags)
+{
+ size_t n = 0;
+ uint32_t test_flags = flags & (SKS_CKFM_ENCRYPT | SKS_CKFM_DECRYPT |
+ SKS_CKFM_DERIVE | SKS_CKFM_DIGEST |
+ SKS_CKFM_SIGN | SKS_CKFM_SIGN_RECOVER |
+ SKS_CKFM_VERIFY | SKS_CKFM_VERIFY_RECOVER |
+ SKS_CKFM_GENERATE | SKS_CKFM_GENERATE_PAIR |
+ SKS_CKFM_WRAP | SKS_CKFM_UNWRAP);
+
+ for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) {
+ if (pkcs11_modes[n].id == mechanism_type) {
+ if (test_flags & ~pkcs11_modes[n].flags) {
+ EMSG("%s flags: 0x%" PRIx32 " vs 0x%" PRIx32,
+ sks2str_proc(mechanism_type),
+ test_flags, pkcs11_modes[n].flags);
+ }
+ return test_flags & ~pkcs11_modes[n].flags;
+ }
+ }
+
+ return 1;
+}
+
+uint32_t check_mechanism_against_processing(struct pkcs11_session *session,
+ uint32_t mechanism_type,
+ enum processing_func function,
+ enum processing_step step)
+{
+ size_t n = 0;
+ bool allowed = false;
+
+ switch (step) {
+ case SKS_FUNC_STEP_INIT:
+ switch (function) {
+ case SKS_FUNCTION_IMPORT:
+ case SKS_FUNCTION_COPY:
+ case SKS_FUNCTION_MODIFY:
+ case SKS_FUNCTION_DESTROY:
+ return SKS_OK;
+ default:
+ for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) {
+ if (pkcs11_modes[n].id == mechanism_type) {
+ allowed = pkcs11_modes[n].flags &
+ sks_function2ckfm(function);
+ break;
+ }
+ }
+ break;
+ }
+ break;
+
+ case SKS_FUNC_STEP_ONESHOT:
+ case SKS_FUNC_STEP_UPDATE:
+ if (session->processing->always_authen &&
+ !session->processing->relogged)
+ return SKS_CKR_USER_NOT_LOGGED_IN;
+
+ if (!session->processing->updated) {
+ allowed = true;
+ } else {
+ for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) {
+ if (pkcs11_modes[n].id == mechanism_type) {
+ allowed = !pkcs11_modes[n].one_shot;
+ break;
+ }
+ }
+ }
+ break;
+
+ case SKS_FUNC_STEP_FINAL:
+ if (session->processing->always_authen &&
+ !session->processing->relogged)
+ return SKS_CKR_USER_NOT_LOGGED_IN;
+
+ return SKS_OK;
+
+ default:
+ TEE_Panic(step);
+ break;
+ }
+
+ if (!allowed)
+ EMSG("Processing %s (%" PRIx32 ") not permitted (%u/%u)",
+ sks2str_proc(mechanism_type), mechanism_type,
+ function, step);
+
+ return allowed ? SKS_OK : SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+}
+
+/*
+ * Object default boolean attributes as per PKCS#11
+ */
+static uint8_t *pkcs11_object_default_boolprop(uint32_t attribute)
+{
+ static const uint8_t bool_true = 1;
+ static const uint8_t bool_false = 0;
+
+ switch (attribute) {
+ /* As per PKCS#11 default value */
+ case SKS_CKA_MODIFIABLE:
+ case SKS_CKA_COPYABLE:
+ case SKS_CKA_DESTROYABLE:
+ case SKS_CKA_SIGN:
+ case SKS_CKA_VERIFY:
+ return (uint8_t *)&bool_true;
+ case SKS_CKA_TOKEN:
+ case SKS_CKA_PRIVATE:
+ case SKS_CKA_SENSITIVE: /* TODO: symkey false, privkey: token specific */
+ /* Token specific default value */
+ case SKS_CKA_DERIVE:
+ case SKS_CKA_ENCRYPT:
+ case SKS_CKA_DECRYPT:
+ case SKS_CKA_SIGN_RECOVER:
+ case SKS_CKA_VERIFY_RECOVER:
+ case SKS_CKA_WRAP:
+ case SKS_CKA_UNWRAP:
+ case SKS_CKA_EXTRACTABLE:
+ case SKS_CKA_WRAP_WITH_TRUSTED:
+ case SKS_CKA_ALWAYS_AUTHENTICATE:
+ case SKS_CKA_TRUSTED:
+ return (uint8_t *)&bool_false;
+ default:
+ DMSG("No default for boolprop attribute 0x%" PRIx32, attribute);
+ TEE_Panic(0); // FIXME: errno
+ }
+
+ /* Keep compiler happy */
+ return NULL;
+}
+
+/*
+ * Object expects several boolean attributes to be set to a default value
+ * or to a validate client configuration value. This function append the input
+ * attribute (id/size/value) in the serialized object.
+ */
+static uint32_t pkcs11_import_object_boolprop(struct sks_attrs_head **out,
+ struct sks_attrs_head *template,
+ uint32_t attribute)
+{
+ uint32_t rv = 0;
+ uint8_t bbool = 0;
+ uint32_t size = sizeof(uint8_t);
+ void *attr = NULL;
+
+ rv = get_attribute(template, attribute, &bbool, &size);
+ if (rv || !bbool)
+ attr = pkcs11_object_default_boolprop(attribute);
+ else
+ attr = &bbool;
+
+ /* Boolean attributes are 1byte in the ABI, no alignment issue */
+ return add_attribute(out, attribute, attr, sizeof(uint8_t));
+}
+
+static uint32_t set_mandatory_boolprops(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp,
+ uint32_t const *bp, size_t bp_count)
+{
+ uint32_t rv = SKS_OK;
+ size_t n = 0;
+
+ for (n = 0; n < bp_count; n++) {
+ rv = pkcs11_import_object_boolprop(out, temp, bp[n]);
+ if (rv)
+ return rv;
+ }
+
+ return rv;
+}
+
+static uint32_t calculate_modulus_bits(void* modulus, size_t size)
+{
+ uint32_t bits;
+ int mask, i;
+ uint8_t *modules_p;
+
+ bits = size * 8;
+ mask = 0x80;
+ modules_p = (uint8_t *)modulus;
+
+ for (i = 0; bits && (modules_p[i] & mask) == 0; bits--)
+ {
+ mask >>= 1;
+ if (mask == 0)
+ {
+ i++;
+ mask = 0x80;
+ }
+ }
+
+ return bits;
+}
+
+static uint32_t __unused set_mandatory_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp,
+ uint32_t const *bp, size_t bp_count)
+{
+ uint32_t rv = SKS_OK;
+ size_t n = 0;
+
+ for (n = 0; n < bp_count; n++) {
+ uint32_t size = 0;
+ void *value = NULL;
+ uint32_t value_ = 0;
+
+ if (get_attribute_ptr(temp, bp[n], &value, &size)) {
+ /* FIXME: currently set attribute as empty. Fail? */
+ size = 0;
+
+ if(bp[n] == SKS_CKA_MODULUS_BITS) {
+ void* modulus_ptr = NULL;
+ uint32_t modulus_size = 0;
+ if(!get_attribute_ptr(temp, SKS_CKA_MODULUS, &modulus_ptr, &modulus_size)) {
+ value_ = calculate_modulus_bits(modulus_ptr, modulus_size);
+ value = &value_;
+ size = sizeof(value_);
+ }
+ }
+ }
+
+ rv = add_attribute(out, bp[n], value, size);
+ if (rv)
+ return rv;
+ }
+
+ return rv;
+}
+
+static uint32_t set_optional_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp,
+ uint32_t const *bp, size_t bp_count)
+{
+ uint32_t rv = SKS_OK;
+ size_t n = 0;
+
+ for (n = 0; n < bp_count; n++) {
+ uint32_t size = 0;
+ void *value = NULL;
+
+ if (get_attribute_ptr(temp, bp[n], &value, &size))
+ continue;
+
+ rv = add_attribute(out, bp[n], value, size);
+ if (rv)
+ return rv;
+ }
+
+ return rv;
+}
+
+/*
+ * Below are listed the mandated or optional expected attributes for
+ * PKCS#11 storage objects.
+ *
+ * Note: boolprops (mandated boolean attributes) SKS_CKA_ALWAYS_SENSITIVE,
+ * and SKS_CKA_NEVER_EXTRACTABLE are set by the token, not provided
+ * in the client template.
+ */
+
+/* PKCS#11 specification for any object (session/token) of the storage */
+static const uint32_t pkcs11_any_object_boolprops[] = {
+ SKS_CKA_TOKEN, SKS_CKA_PRIVATE,
+ SKS_CKA_MODIFIABLE, SKS_CKA_COPYABLE, SKS_CKA_DESTROYABLE,
+};
+static const uint32_t pkcs11_any_object_mandated[] = {
+ SKS_CKA_LABEL,
+};
+/* PKCS#11 specification for raw data object (+pkcs11_any_object_xxx) */
+const uint32_t pkcs11_raw_data_optional[] = {
+ SKS_CKA_OBJECT_ID, SKS_CKA_APPLICATION, SKS_CKA_VALUE,
+};
+/* PKCS#11 specification for any key object (+pkcs11_any_object_xxx) */
+static const uint32_t pkcs11_any_key_boolprops[] = {
+ SKS_CKA_DERIVE,
+};
+static const uint32_t pkcs11_any_key_optional[] = {
+ SKS_CKA_ID,
+ SKS_CKA_START_DATE, SKS_CKA_END_DATE,
+ SKS_CKA_ALLOWED_MECHANISMS,
+};
+/* PKCS#11 specification for any symmetric key (+pkcs11_any_key_xxx) */
+static const uint32_t pkcs11_symm_key_boolprops[] = {
+ SKS_CKA_ENCRYPT, SKS_CKA_DECRYPT, SKS_CKA_SIGN, SKS_CKA_VERIFY,
+ SKS_CKA_WRAP, SKS_CKA_UNWRAP,
+ SKS_CKA_SENSITIVE, SKS_CKA_EXTRACTABLE,
+ SKS_CKA_WRAP_WITH_TRUSTED, SKS_CKA_TRUSTED,
+};
+static const uint32_t pkcs11_symm_key_optional[] = {
+ SKS_CKA_WRAP_TEMPLATE, SKS_CKA_UNWRAP_TEMPLATE, SKS_CKA_DERIVE_TEMPLATE,
+ SKS_CKA_VALUE, SKS_CKA_VALUE_LEN,
+};
+/* PKCS#11 specification for any asymmetric public key (+pkcs11_any_key_xxx) */
+static const uint32_t pkcs11_public_key_boolprops[] = {
+ SKS_CKA_ENCRYPT, SKS_CKA_VERIFY, SKS_CKA_VERIFY_RECOVER, SKS_CKA_WRAP,
+ SKS_CKA_TRUSTED,
+};
+static const uint32_t pkcs11_public_key_mandated[] = {
+ SKS_CKA_SUBJECT
+};
+static const uint32_t pkcs11_public_key_optional[] = {
+ SKS_CKA_WRAP_TEMPLATE, SKS_CKA_PUBLIC_KEY_INFO,
+};
+/* PKCS#11 specification for any asymmetric private key (+pkcs11_any_key_xxx) */
+static const uint32_t pkcs11_private_key_boolprops[] = {
+ SKS_CKA_DECRYPT, SKS_CKA_SIGN, SKS_CKA_SIGN_RECOVER,
+ SKS_CKA_UNWRAP,
+ SKS_CKA_SENSITIVE, SKS_CKA_EXTRACTABLE,
+ SKS_CKA_WRAP_WITH_TRUSTED, SKS_CKA_ALWAYS_AUTHENTICATE,
+};
+static const uint32_t pkcs11_private_key_mandated[] = {
+ SKS_CKA_SUBJECT
+};
+static const uint32_t pkcs11_private_key_optional[] = {
+ SKS_CKA_UNWRAP_TEMPLATE, SKS_CKA_PUBLIC_KEY_INFO,
+};
+/* PKCS#11 specification for any RSA key (+pkcs11_public/private_key_xxx) */
+static const uint32_t pkcs11_rsa_public_key_mandated[] = {
+ SKS_CKA_MODULUS_BITS,
+};
+static const uint32_t pkcs11_rsa_public_key_optional[] = {
+ SKS_CKA_MODULUS, SKS_CKA_PUBLIC_EXPONENT,
+};
+static const uint32_t pkcs11_rsa_private_key_optional[] = {
+ SKS_CKA_MODULUS, SKS_CKA_PUBLIC_EXPONENT, SKS_CKA_PRIVATE_EXPONENT,
+ SKS_CKA_PRIME_1, SKS_CKA_PRIME_2,
+ SKS_CKA_EXPONENT_1, SKS_CKA_EXPONENT_2, SKS_CKA_COEFFICIENT,
+};
+/* PKCS#11 specification for any EC key (+pkcs11_public/private_key_xxx) */
+static const uint32_t pkcs11_ec_public_key_mandated[] = {
+ SKS_CKA_EC_PARAMS,
+};
+static const uint32_t pkcs11_ec_public_key_optional[] = {
+ SKS_CKA_EC_POINT, SKS_CKA_VALUE, SKS_CKA_VALUE_LEN
+};
+static const uint32_t pkcs11_ec_private_key_mandated[] = {
+ SKS_CKA_EC_PARAMS,
+};
+static const uint32_t pkcs11_ec_private_key_optional[] = {
+ SKS_CKA_VALUE, SKS_CKA_EC_POINT, SKS_CKA_VALUE_LEN
+};
+/* PKCS#11 specification for certificate (+pkcs11_any_object_xxx) */
+static const uint32_t pkcs11_cert_boolprops[] = {
+ SKS_CKA_TRUSTED,
+};
+static const uint32_t pkcs11_cert_mandated[] = {
+ SKS_CKA_CERTIFICATE_CATEGORY,
+};
+static const uint32_t pkcs11_cert_optional[] = {
+ SKS_CKA_START_DATE, SKS_CKA_END_DATE,
+ SKS_CKA_PUBLIC_KEY_INFO,
+};
+static const uint32_t pkcs11_cert_x509_mandated[] = {
+ SKS_CKA_SUBJECT,
+};
+static const uint32_t pkcs11_cert_x509_optional[] = {
+ SKS_CKA_ID, SKS_CKA_ISSUER, SKS_CKA_SERIAL_NUMBER,
+ SKS_CKA_VALUE, SKS_CKA_URL,
+ SKS_CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
+ SKS_CKA_HASH_OF_ISSUER_PUBLIC_KEY,
+ SKS_CKA_NAME_HASH_ALGORITHM,
+};
+
+static uint32_t create_pkcs11_storage_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp)
+{
+ uint32_t const *boolprops = &pkcs11_any_object_boolprops[0];
+ uint32_t const *mandated = &pkcs11_any_object_mandated[0];
+ size_t boolprops_count = ARRAY_SIZE(pkcs11_any_object_boolprops);
+ size_t mandated_count = ARRAY_SIZE(pkcs11_any_object_mandated);
+ uint32_t class = 0;
+ uint32_t rv = 0;
+
+ init_attributes_head(out);
+#ifdef SKS_SHEAD_WITH_BOOLPROPS
+ set_attributes_in_head(*out);
+#endif
+
+ /* Object class is mandatory */
+ class = get_class(temp);
+ if (class == SKS_UNDEFINED_ID) {
+ EMSG("Class attribute not found");
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ rv = add_attribute(out, SKS_CKA_CLASS, &class, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = set_mandatory_boolprops(out, temp, boolprops, boolprops_count);
+ if (rv)
+ return rv;
+
+ return set_mandatory_attributes(out, temp, mandated, mandated_count);
+}
+
+static uint32_t create_pkcs11_genkey_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp)
+{
+ uint32_t const *boolprops = &pkcs11_any_key_boolprops[0];
+ uint32_t const *optional = &pkcs11_any_key_optional[0];
+ size_t boolprops_count = ARRAY_SIZE(pkcs11_any_key_boolprops);
+ size_t optional_count = ARRAY_SIZE(pkcs11_any_key_optional);
+ uint32_t type = 0;
+ uint32_t rv = 0;
+
+ rv = create_pkcs11_storage_attributes(out, temp);
+ if (rv)
+ return rv;
+
+ type = get_type(temp);
+ if (type == SKS_UNDEFINED_ID) {
+ EMSG("Key type attribute not found");
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ rv = add_attribute(out, SKS_CKA_KEY_TYPE, &type, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = set_mandatory_boolprops(out, temp, boolprops, boolprops_count);
+ if (rv)
+ return rv;
+
+ return set_optional_attributes(out, temp, optional, optional_count);
+}
+
+static uint32_t create_pkcs11_symm_key_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp)
+{
+ uint32_t const *boolprops = &pkcs11_symm_key_boolprops[0];
+ uint32_t const *optional = &pkcs11_symm_key_optional[0];
+ size_t boolprops_count = ARRAY_SIZE(pkcs11_symm_key_boolprops);
+ size_t optional_count = ARRAY_SIZE(pkcs11_symm_key_optional);
+ uint32_t rv = 0;
+
+ assert(get_class(temp) == SKS_CKO_SECRET_KEY);
+
+ rv = create_pkcs11_genkey_attributes(out, temp);
+ if (rv)
+ return rv;
+
+ assert(get_class(*out) == SKS_CKO_SECRET_KEY);
+
+ switch (get_type(*out)) {
+ case SKS_CKK_GENERIC_SECRET:
+ case SKS_CKK_AES:
+ case SKS_CKK_MD5_HMAC:
+ case SKS_CKK_SHA_1_HMAC:
+ case SKS_CKK_SHA256_HMAC:
+ case SKS_CKK_SHA384_HMAC:
+ case SKS_CKK_SHA512_HMAC:
+ case SKS_CKK_SHA224_HMAC:
+ break;
+ default:
+ EMSG("Invalid key type (0x%" PRIx32 ", %s)",
+ get_type(*out), sks2str_key_type(get_type(*out)));
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ rv = set_mandatory_boolprops(out, temp, boolprops, boolprops_count);
+ if (rv)
+ return rv;
+
+ return set_optional_attributes(out, temp, optional, optional_count);
+}
+
+static uint32_t create_pkcs11_data_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp)
+{
+ uint32_t rv = 0;
+
+ assert(get_class(temp) == SKS_CKO_DATA);
+
+ rv = create_pkcs11_storage_attributes(out, temp);
+ if (rv)
+ return rv;
+
+ assert(get_class(*out) == SKS_CKO_DATA);
+
+ rv = set_optional_attributes(out, temp,
+ &pkcs11_raw_data_optional[0],
+ ARRAY_SIZE(pkcs11_raw_data_optional));
+
+ return rv;
+}
+
+static uint32_t create_pkcs11_pub_key_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp)
+{
+ uint32_t rv = 0;
+ uint32_t const *boolprops = &pkcs11_public_key_boolprops[0];
+ uint32_t const *mandated = &pkcs11_public_key_mandated[0];
+ uint32_t const *optional = &pkcs11_public_key_optional[0];
+ size_t boolprops_count = ARRAY_SIZE(pkcs11_public_key_boolprops);
+ size_t mandated_count = ARRAY_SIZE(pkcs11_public_key_mandated);
+ size_t optional_count = ARRAY_SIZE(pkcs11_public_key_optional);
+
+ assert(get_class(temp) == SKS_CKO_PUBLIC_KEY);
+
+ rv = create_pkcs11_genkey_attributes(out, temp);
+ if (rv)
+ return rv;
+
+ assert(get_class(*out) == SKS_CKO_PUBLIC_KEY);
+
+ rv = set_mandatory_boolprops(out, temp, boolprops, boolprops_count);
+ if (rv)
+ return rv;
+
+ rv = set_mandatory_attributes(out, temp, mandated, mandated_count);
+ if (rv)
+ return rv;
+
+ rv = set_optional_attributes(out, temp, optional, optional_count);
+ if (rv)
+ return rv;
+
+ switch (get_type(*out)) {
+ case SKS_CKK_RSA:
+ boolprops = NULL;
+ mandated = &pkcs11_rsa_public_key_mandated[0];
+ optional = &pkcs11_rsa_public_key_optional[0];
+ boolprops_count = 0;
+ mandated_count = ARRAY_SIZE(pkcs11_rsa_public_key_mandated);
+ optional_count = ARRAY_SIZE(pkcs11_rsa_public_key_optional);
+ break;
+ case SKS_CKK_EC:
+ boolprops = NULL;
+ mandated = &pkcs11_ec_public_key_mandated[0];
+ optional = &pkcs11_ec_public_key_optional[0];
+ boolprops_count = 0;
+ mandated_count = ARRAY_SIZE(pkcs11_ec_public_key_mandated);
+ optional_count = ARRAY_SIZE(pkcs11_ec_public_key_optional);
+ break;
+ default:
+ EMSG("Invalid key type (0x%" PRIx32 ", %s)",
+ get_type(*out), sks2str_key_type(get_type(*out)));
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ rv = set_mandatory_boolprops(out, temp, boolprops, boolprops_count);
+ if (rv)
+ return rv;
+
+ rv = set_mandatory_attributes(out, temp, mandated, mandated_count);
+ if (rv)
+ return rv;
+
+ return set_optional_attributes(out, temp, optional, optional_count);
+}
+
+static uint32_t create_pkcs11_priv_key_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp)
+{
+ uint32_t const *boolprops = &pkcs11_private_key_boolprops[0];
+ uint32_t const *mandated = &pkcs11_private_key_mandated[0];
+ uint32_t const *optional = &pkcs11_private_key_optional[0];
+ size_t boolprops_count = ARRAY_SIZE(pkcs11_private_key_boolprops);
+ size_t mandated_count = ARRAY_SIZE(pkcs11_private_key_mandated);
+ size_t optional_count = ARRAY_SIZE(pkcs11_private_key_optional);
+ uint32_t rv = 0;
+
+ assert(get_class(temp) == SKS_CKO_PRIVATE_KEY);
+
+ rv = create_pkcs11_genkey_attributes(out, temp);
+ if (rv)
+ return rv;
+
+ assert(get_class(*out) == SKS_CKO_PRIVATE_KEY);
+
+ rv = set_mandatory_boolprops(out, temp, boolprops, boolprops_count);
+ if (rv)
+ return rv;
+
+ rv = set_mandatory_attributes(out, temp, mandated, mandated_count);
+ if (rv)
+ return rv;
+
+ rv = set_optional_attributes(out, temp, optional, optional_count);
+ if (rv)
+ return rv;
+
+ switch (get_type(*out)) {
+ case SKS_CKK_RSA:
+ boolprops = NULL;
+ mandated = NULL;
+ optional = &pkcs11_rsa_private_key_optional[0];
+ boolprops_count = 0;
+ mandated_count = 0;
+ optional_count = ARRAY_SIZE(pkcs11_rsa_private_key_optional);
+ break;
+ case SKS_CKK_EC:
+ boolprops = NULL;
+ mandated = &pkcs11_ec_private_key_mandated[0];
+ optional = &pkcs11_ec_private_key_optional[0];
+ boolprops_count = 0;
+ mandated_count = ARRAY_SIZE(pkcs11_ec_private_key_mandated);
+ optional_count = ARRAY_SIZE(pkcs11_ec_private_key_optional);
+ break;
+ default:
+ EMSG("Invalid key type (0x%" PRIx32 ", %s)",
+ get_type(*out), sks2str_key_type(get_type(*out)));
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ rv = set_mandatory_boolprops(out, temp, boolprops, boolprops_count);
+ if (rv)
+ return rv;
+
+ rv = set_mandatory_attributes(out, temp, mandated, mandated_count);
+ if (rv)
+ return rv;
+
+ return set_optional_attributes(out, temp, optional, optional_count);
+}
+
+static uint32_t create_pkcs11_cert_attributes(struct sks_attrs_head **out,
+ struct sks_attrs_head *temp)
+{
+ uint32_t const *boolprops = &pkcs11_cert_boolprops[0];
+ uint32_t const *mandated = &pkcs11_cert_mandated[0];
+ uint32_t const *optional = &pkcs11_cert_optional[0];
+ size_t boolprops_count = ARRAY_SIZE(pkcs11_cert_boolprops);
+ size_t mandated_count = ARRAY_SIZE(pkcs11_cert_mandated);
+ size_t optional_count = ARRAY_SIZE(pkcs11_cert_optional);
+ uint32_t type = 0;
+ uint32_t size = 0;
+ void *value = NULL;
+ uint32_t rv = 0;
+
+ assert(get_class(temp) == SKS_CKO_CERTIFICATE);
+
+ rv = create_pkcs11_storage_attributes(out, temp);
+ if (rv)
+ return rv;
+
+ rv = set_mandatory_boolprops(out, temp, boolprops, boolprops_count);
+ if (rv)
+ return rv;
+
+ rv = set_mandatory_attributes(out, temp, mandated, mandated_count);
+ if (rv)
+ return rv;
+
+ rv = set_optional_attributes(out, temp, optional, optional_count);
+ if (rv)
+ return rv;
+
+ type = get_type(temp);
+ switch (type) {
+ case SKS_CKC_X_509:
+ mandated = &pkcs11_cert_x509_mandated[0];
+ optional = &pkcs11_cert_x509_optional[0];
+ mandated_count = ARRAY_SIZE(pkcs11_cert_x509_mandated);
+ optional_count = ARRAY_SIZE(pkcs11_cert_x509_optional);
+
+ rv = get_attribute_ptr(temp, SKS_CKA_URL, &value, &size);
+ if (rv || !size) {
+ /* CKA_URL not available */
+ rv = get_attribute_ptr(temp, SKS_CKA_VALUE,
+ &value, &size);
+ if (rv || !size) {
+ EMSG("CKA_VALUE must be non-empty");
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ } else {
+ /* CKA_URL available, check for hashes */
+ rv = get_attribute_ptr(temp,
+ SKS_CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
+ &value, &size);
+ if (rv || !size) {
+ EMSG("CKA_HASH_OF_SUBJECT_PUBLIC_KEY empty");
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ rv = get_attribute_ptr(temp,
+ SKS_CKA_HASH_OF_ISSUER_PUBLIC_KEY,
+ &value, &size);
+ if (rv || !size) {
+ EMSG("CKA_HASH_OF_ISSUER_PUBLIC_KEY empty");
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+ break;
+ default:
+ EMSG("Invalid certificate type (0x%" PRIx32 ", %s)",
+ type, sks2str_certificate_type(type));
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ rv = add_attribute(out, SKS_CKA_CERTIFICATE_TYPE,
+ &type, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ /* TODO: CKA_CHECK_VALUE */
+ /* TODO: CKA_PUBLIC_KEY_INFO */
+
+ rv = set_mandatory_attributes(out, temp, mandated, mandated_count);
+ if (rv)
+ return rv;
+
+ return set_optional_attributes(out, temp, optional, optional_count);
+}
+
+/*
+ * Create an attribute list for a new object from a template and a parent
+ * object (optional) for an object generation function (generate, copy,
+ * derive...).
+ *
+ * PKCS#11 directives on the supplied template:
+ * - template has an invalid attribute ID: return ATTRIBUTE_TYPE_INVALID
+ * - template has an invalid value for an attribute: return ATTRIBUTE_VALID_INVALID
+ * - template has value for a read-only attribute: return ATTRIBUTE_READ_ONLY
+ * - template+default+parent => still miss an attribute: return TEMPLATE_INCONSISTENT
+ *
+ * INFO on SKS_CMD_COPY_OBJECT:
+ * - parent SKS_CKA_COPYIABLE=false => return ACTION_PROHIBITED.
+ * - template can specify SKS_CKA_TOKEN, SKS_CKA_PRIVATE, SKS_CKA_MODIFIABLE,
+ * SKS_CKA_DESTROYABLE.
+ * - SENSITIVE can change from false to true, not from true to false.
+ * - LOCAL is the parent LOCAL
+ */
+uint32_t create_attributes_from_template(struct sks_attrs_head **out,
+ void *template, size_t template_size,
+ uint32_t proc_id,
+ struct sks_attrs_head *parent,
+ enum processing_func function)
+{
+ struct sks_attrs_head *temp = NULL;
+ struct sks_attrs_head *attrs = NULL;
+ uint32_t rv = 0;
+ uint32_t key_gen_m = 0;
+ uint8_t local = 0;
+ uint8_t always_sensitive = 0;
+ uint8_t never_extract = 0;
+ uint32_t class = SKS_UNDEFINED_ID;
+ uint32_t type = SKS_UNDEFINED_ID;
+
+#ifdef DEBUG /* Sanity: check function argument */
+ trace_attributes_from_api_head("template", template, template_size);
+ switch (function) {
+ case SKS_FUNCTION_GENERATE:
+ case SKS_FUNCTION_GENERATE_PAIR:
+ case SKS_FUNCTION_IMPORT:
+ break;
+ case SKS_FUNCTION_DERIVE:
+ trace_attributes("parent", parent);
+ break;
+ default:
+ TEE_Panic(TEE_ERROR_NOT_SUPPORTED);
+ }
+#endif
+
+ rv = sanitize_client_object(&temp, template, template_size);
+ if (rv)
+ goto bail;
+
+ /* If class/type not defined, match from mechanism */
+ if (get_class(temp) == SKS_UNDEFINED_ID &&
+ get_type(temp) == SKS_UNDEFINED_ID) {
+ switch (proc_id) {
+ case SKS_CKM_GENERIC_SECRET_KEY_GEN:
+ class = SKS_CKO_SECRET_KEY;
+ type = SKS_CKK_GENERIC_SECRET;
+ break;
+ case SKS_CKM_AES_KEY_GEN:
+ class = SKS_CKO_SECRET_KEY;
+ type = SKS_CKK_AES;
+ break;
+ case SKS_CKM_EC_KEY_PAIR_GEN:
+ type = SKS_CKK_DH;
+ break;
+ case SKS_CKM_RSA_PKCS_KEY_PAIR_GEN:
+ type = SKS_CKK_RSA;
+ break;
+ default:
+ EMSG("Unable to define class/type from mechanism");
+ rv = SKS_CKR_TEMPLATE_INCOMPLETE;
+ goto bail;
+ }
+ if (class != SKS_UNDEFINED_ID)
+ add_attribute(&temp, SKS_CKA_CLASS,
+ &class, sizeof(uint32_t));
+ if (type != SKS_UNDEFINED_ID)
+ add_attribute(&temp, SKS_CKA_KEY_TYPE,
+ &type, sizeof(uint32_t));
+ }
+
+ if (!sanitize_consistent_class_and_type(temp)) {
+ EMSG("inconsistent class/type");
+ rv = SKS_CKR_TEMPLATE_INCONSISTENT;
+ goto bail;
+ }
+
+ switch (get_class(temp)) {
+ case SKS_CKO_DATA:
+ rv = create_pkcs11_data_attributes(&attrs, temp);
+ break;
+ case SKS_CKO_SECRET_KEY:
+ rv = create_pkcs11_symm_key_attributes(&attrs, temp);
+ break;
+ case SKS_CKO_PUBLIC_KEY:
+ rv = create_pkcs11_pub_key_attributes(&attrs, temp);
+ break;
+ case SKS_CKO_PRIVATE_KEY:
+ rv = create_pkcs11_priv_key_attributes(&attrs, temp);
+ break;
+ case SKS_CKO_CERTIFICATE:
+ rv = create_pkcs11_cert_attributes(&attrs, temp);
+ break;
+ default:
+ DMSG("Invalid object class 0x%" PRIx32 "/%s",
+ get_class(temp), sks2str_class(get_class(temp)));
+ rv = SKS_CKR_TEMPLATE_INCONSISTENT;
+ break;
+ }
+ if (rv)
+ goto bail;
+
+ switch (get_class(attrs)) {
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ case SKS_CKO_PUBLIC_KEY:
+ assert(get_attribute(attrs, SKS_CKA_LOCAL, NULL, NULL) ==
+ SKS_NOT_FOUND);
+
+ local = SKS_FALSE;
+ always_sensitive = SKS_FALSE;
+ never_extract = SKS_FALSE;
+
+ switch (function) {
+ case SKS_FUNCTION_GENERATE:
+ always_sensitive = get_bool(attrs, SKS_CKA_SENSITIVE);
+ never_extract = !get_bool(attrs, SKS_CKA_EXTRACTABLE);
+ local = SKS_TRUE;
+ break;
+ case SKS_FUNCTION_GENERATE_PAIR:
+ local = SKS_TRUE;
+ break;
+ case SKS_FUNCTION_DERIVE:
+ always_sensitive =
+ get_bool(parent, SKS_CKA_ALWAYS_SENSITIVE) &&
+ get_bool(attrs, SKS_CKA_SENSITIVE);
+ never_extract =
+ get_bool(parent, SKS_CKA_NEVER_EXTRACTABLE) &&
+ !get_bool(attrs, SKS_CKA_EXTRACTABLE);
+ break;
+ case SKS_FUNCTION_COPY:
+ always_sensitive =
+ get_bool(parent, SKS_CKA_ALWAYS_SENSITIVE) &&
+ get_bool(attrs, SKS_CKA_SENSITIVE);
+ never_extract =
+ get_bool(parent, SKS_CKA_NEVER_EXTRACTABLE) &&
+ !get_bool(attrs, SKS_CKA_EXTRACTABLE);
+ local = get_bool(parent, SKS_CKA_LOCAL);
+ break;
+ default:
+ break;
+ }
+
+ rv = add_attribute(&attrs, SKS_CKA_LOCAL,
+ &local, sizeof(local));
+ if (rv)
+ goto bail;
+
+ /* TODO: Set valid key gen mechanism when local */
+ if (local == SKS_FALSE) {
+ key_gen_m = SKS_CK_UNAVAILABLE_INFORMATION;
+ rv = add_attribute(&attrs, SKS_CKA_KEY_GEN_MECHANISM,
+ &key_gen_m, sizeof(key_gen_m));
+ if (rv)
+ goto bail;
+ }
+
+ rv = add_attribute(&attrs, SKS_CKA_ALWAYS_SENSITIVE,
+ &always_sensitive, sizeof(always_sensitive));
+ if (rv)
+ goto bail;
+
+ rv = add_attribute(&attrs, SKS_CKA_NEVER_EXTRACTABLE,
+ &never_extract, sizeof(never_extract));
+ if (rv)
+ goto bail;
+
+ break;
+
+ default:
+ break;
+ }
+
+ *out = attrs;
+
+#ifdef DEBUG
+ trace_attributes("object", attrs);
+#endif
+
+bail:
+ TEE_Free(temp);
+ if (rv)
+ TEE_Free(attrs);
+
+ return rv;
+}
+
+static uint32_t check_attrs_misc_integrity(struct sks_attrs_head *head)
+{
+ /* FIXME: is it useful? */
+ if (get_bool(head, SKS_CKA_NEVER_EXTRACTABLE) &&
+ get_bool(head, SKS_CKA_EXTRACTABLE)) {
+ DMSG("Never/Extractable attributes mismatch %d/%d",
+ get_bool(head, SKS_CKA_NEVER_EXTRACTABLE),
+ get_bool(head, SKS_CKA_EXTRACTABLE));
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ if (get_bool(head, SKS_CKA_ALWAYS_SENSITIVE) &&
+ !get_bool(head, SKS_CKA_SENSITIVE)) {
+ DMSG("Sensitive/always attributes mismatch %d/%d",
+ get_bool(head, SKS_CKA_SENSITIVE),
+ get_bool(head, SKS_CKA_ALWAYS_SENSITIVE));
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return SKS_OK;
+}
+
+/*
+ * Check access to object against authentication to token
+ */
+uint32_t check_access_attrs_against_token(struct pkcs11_session *session,
+ struct sks_attrs_head *head)
+{
+ bool private = true;
+
+ switch(get_class(head)) {
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_CERTIFICATE:
+ case SKS_CKO_DATA:
+ if (!get_bool(head, SKS_CKA_PRIVATE))
+ private = false;
+ break;
+ case SKS_CKO_PRIVATE_KEY:
+ break;
+ default:
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+
+ if (private && pkcs11_session_is_public(session)) {
+ DMSG("Private object access from a public session");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+
+ /*
+ * TODO: START_DATE and END_DATE: complies with current time?
+ */
+ return SKS_OK;
+}
+
+/*
+ * Check the attributes of a to-be-created object matches the token state
+ */
+uint32_t check_created_attrs_against_token(struct pkcs11_session *session,
+ struct sks_attrs_head *head)
+{
+ uint32_t rc = 0;
+
+ rc = check_attrs_misc_integrity(head);
+ if (rc)
+ return rc;
+
+ if (get_bool(head, SKS_CKA_TRUSTED) &&
+ !pkcs11_session_is_security_officer(session)) {
+ DMSG("Can't create trusted object");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+
+ if (get_bool(head, SKS_CKA_TOKEN) &&
+ !pkcs11_session_is_read_write(session)) {
+ DMSG("Can't create persistent object");
+ return SKS_CKR_SESSION_READ_ONLY;
+ }
+
+ /*
+ * TODO: START_DATE and END_DATE: complies with current time?
+ */
+ return SKS_OK;
+}
+
+/*
+ * Check the attributes of new secret match the requirements of the parent key.
+ */
+uint32_t check_created_attrs_against_parent_key(
+ uint32_t proc_id __unused,
+ struct sks_attrs_head *parent __unused,
+ struct sks_attrs_head *head __unused)
+{
+ /*
+ * TODO
+ * Depends on the processing§/mechanism used.
+ * Wrapping: check head vs parent key WRAP_TEMPLATE attribute.
+ * Unwrapping: check head vs parent key UNWRAP_TEMPLATE attribute.
+ * Derive: check head vs parent key DERIVE_TEMPLATE attribute (late comer?).
+ */
+ return SKS_ERROR;
+}
+
+#define DMSG_BAD_BBOOL(attr, proc, head) \
+ do { \
+ uint8_t __maybe_unused bvalue = 0; \
+ \
+ DMSG("%s issue for %s: %sfound, value %d", \
+ sks2str_attr(attr), \
+ sks2str_proc(proc), \
+ get_attribute(head, attr, &bvalue, NULL) ? \
+ "not " : "", \
+ bvalue); \
+ } while (0)
+
+/*
+ * Check the attributes of a new secret match the processing/mechanism
+ * used to create it.
+ *
+ * @proc_id - SKS_CKM__xxx
+ * @subproc_id - boolean attribute id as encrypt/decrypt/sign/verify,
+ * if applicable to proc_id.
+ * @head - head of the attributes of the to-be-created object.
+ */
+uint32_t check_created_attrs_against_processing(uint32_t proc_id,
+ struct sks_attrs_head *head)
+{
+ uint8_t bbool = 0;
+
+ /*
+ * Processing that do not create secrets are not expected to call
+ * this function which would panic.
+ */
+ /*
+ * FIXME: really need to check LOCAL here, it was safely set from
+ * create_attributes_from_template().
+ */
+ switch (proc_id) {
+ case SKS_PROCESSING_IMPORT:
+ case SKS_CKM_ECDH1_DERIVE:
+ case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ case SKS_CKM_DH_PKCS_DERIVE:
+ if (get_class(head) != SKS_CKO_CERTIFICATE &&
+ get_class(head) != SKS_CKO_DATA &&
+ (get_attribute(head, SKS_CKA_LOCAL, &bbool, NULL) ||
+ bbool)) {
+ DMSG_BAD_BBOOL(SKS_CKA_LOCAL, proc_id, head);
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ break;
+ case SKS_CKM_GENERIC_SECRET_KEY_GEN:
+ case SKS_CKM_AES_KEY_GEN:
+ case SKS_CKM_EC_KEY_PAIR_GEN:
+ case SKS_CKM_RSA_PKCS_KEY_PAIR_GEN:
+ case SKS_CKM_MTK_HSM_AES_KEY_GEN:
+ case SKS_CKM_MTK_HSM_EC_KEY_PAIR_GEN:
+ case SKS_CKM_MTK_HSM_EC_KEY_PAIR_IMPORT:
+ if (get_attribute(head, SKS_CKA_LOCAL, &bbool, NULL) ||
+ !bbool) {
+ DMSG_BAD_BBOOL(SKS_CKA_LOCAL, proc_id, head);
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ break;
+ default:
+ TEE_Panic(proc_id);
+ break;
+ }
+
+ switch (proc_id) {
+ case SKS_CKM_GENERIC_SECRET_KEY_GEN:
+ if (get_type(head) != SKS_CKK_GENERIC_SECRET)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ break;
+ case SKS_CKM_AES_KEY_GEN:
+ if (get_type(head) != SKS_CKK_AES)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ break;
+ case SKS_CKM_EC_KEY_PAIR_GEN:
+ if (get_type(head) != SKS_CKK_EC)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ break;
+ case SKS_CKM_RSA_PKCS_KEY_PAIR_GEN:
+ if (get_type(head) != SKS_CKK_RSA)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ break;
+ case SKS_CKM_ECDH1_DERIVE:
+ case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ case SKS_CKM_DH_PKCS_DERIVE:
+ if (get_class(head) != SKS_CKO_SECRET_KEY)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ break;
+ case SKS_PROCESSING_IMPORT:
+ default:
+ break;
+ }
+
+ return SKS_OK;
+}
+
+void pkcs11_max_min_key_size(uint32_t key_type, uint32_t *max_key_size,
+ uint32_t *min_key_size, bool bit_size_only)
+{
+ uint32_t mult = bit_size_only ? 8 : 1;
+
+ switch (key_type) {
+ case SKS_CKK_GENERIC_SECRET:
+ *min_key_size = 1; /* in bits */
+ *max_key_size = 4096; /* in bits */
+ break;
+ case SKS_CKK_MD5_HMAC:
+ *min_key_size = 16 * mult;
+ *max_key_size = 16 * mult;
+ break;
+ case SKS_CKK_SHA_1_HMAC:
+ *min_key_size = 20 * mult;
+ *max_key_size = 20 * mult;
+ break;
+ case SKS_CKK_SHA224_HMAC:
+ *min_key_size = 28 * mult;
+ *max_key_size = 28 * mult;
+ break;
+ case SKS_CKK_SHA256_HMAC:
+ *min_key_size = 32 * mult;
+ *max_key_size = 32 * mult;
+ break;
+ case SKS_CKK_SHA384_HMAC:
+ *min_key_size = 48 * mult;
+ *max_key_size = 48 * mult;
+ break;
+ case SKS_CKK_SHA512_HMAC:
+ *min_key_size = 64 * mult;
+ *max_key_size = 64 * mult;
+ break;
+ case SKS_CKK_AES:
+ *min_key_size = 16 * mult;
+ *max_key_size = 32 * mult;
+ break;
+ case SKS_CKK_EC:
+ *min_key_size = 192; /* in bits */
+ *max_key_size = 521; /* in bits */
+ break;
+ case SKS_CKK_RSA:
+ case SKS_CKK_DSA:
+ case SKS_CKK_DH:
+ *min_key_size = 256; /* in bits */
+ *max_key_size = 4096; /* in bits */
+ break;
+ default:
+ TEE_Panic(key_type);
+ break;
+ }
+}
+
+uint32_t check_created_attrs(struct sks_attrs_head *key1,
+ struct sks_attrs_head *key2)
+{
+ struct sks_attrs_head *secret = NULL;
+ struct sks_attrs_head *private = NULL;
+ struct sks_attrs_head *public = NULL;
+ uint32_t max_key_size = 0;
+ uint32_t min_key_size = 0;
+ uint32_t key_length = 0;
+ uint32_t rv = 0;
+
+ switch (get_class(key1)) {
+ case SKS_CKO_SECRET_KEY:
+ secret = key1;
+ break;
+ case SKS_CKO_PUBLIC_KEY:
+ public = key1;
+ break;
+ case SKS_CKO_PRIVATE_KEY:
+ private = key1;
+ break;
+ default:
+ return SKS_CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if (key2) {
+ switch (get_class(key2)) {
+ case SKS_CKO_PUBLIC_KEY:
+ public = key2;
+ if (private == key1)
+ break;
+
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ case SKS_CKO_PRIVATE_KEY:
+ private = key2;
+ if (public == key1)
+ break;
+
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ default:
+ return SKS_CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if (get_type(private) != get_type(public))
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ if (secret) {
+ switch (get_type(secret)) {
+ case SKS_CKK_AES:
+ case SKS_CKK_GENERIC_SECRET:
+ case SKS_CKK_MD5_HMAC:
+ case SKS_CKK_SHA_1_HMAC:
+ case SKS_CKK_SHA224_HMAC:
+ case SKS_CKK_SHA256_HMAC:
+ case SKS_CKK_SHA384_HMAC:
+ case SKS_CKK_SHA512_HMAC:
+ break;
+ default:
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ /* Get key size */
+ rv = get_u32_attribute(secret, SKS_CKA_VALUE_LEN, &key_length);
+ if (rv)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ if (public) {
+ switch (get_type(public)) {
+ case SKS_CKK_RSA:
+ case SKS_CKK_DSA:
+ case SKS_CKK_DH:
+ /* Get key size */
+ rv = get_u32_attribute(public, SKS_CKA_MODULUS_BITS,
+ &key_length);
+ if (rv)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ break;
+ case SKS_CKK_EC:
+ break;
+ default:
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+ if (private) {
+ switch (get_type(private)) {
+ case SKS_CKK_RSA:
+ case SKS_CKK_DSA:
+ case SKS_CKK_DH:
+ /* Get key size, if key pair public carries bit size */
+ if (public)
+ break;
+
+ rv = get_u32_attribute(private, SKS_CKA_MODULUS_BITS,
+ &key_length);
+ if (rv)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ break;
+ case SKS_CKK_EC:
+ /* No need to get key size */
+ break;
+ default:
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+
+ /*
+ * Check key size for symmetric keys and RSA keys
+ * EC is bound to domains, no need to check here.
+ */
+ switch (get_type(key1)) {
+ case SKS_CKK_EC:
+ return SKS_OK;
+ default:
+ break;
+ }
+
+ pkcs11_max_min_key_size(get_type(key1),
+ &max_key_size, &min_key_size, false);
+
+ if (key_length < min_key_size || key_length > max_key_size) {
+ EMSG("Length %" PRIu32 " vs range [%" PRIu32 " %" PRIu32 "]",
+ key_length, min_key_size, max_key_size);
+ return SKS_CKR_KEY_SIZE_RANGE;
+ }
+
+ return SKS_OK;
+}
+
+/* Check processing ID against attribute ALLOWED_PROCESSINGS if any */
+static bool parent_key_complies_allowed_processings(uint32_t proc_id,
+ struct sks_attrs_head *head)
+{
+ char *attr = NULL;
+ uint32_t size = 0;
+ uint32_t proc = 0;
+ size_t count = 0;
+
+ /* Check only if restricted allowed mechanisms list is defined */
+ if (get_attribute_ptr(head, SKS_CKA_ALLOWED_MECHANISMS,
+ (void *)&attr, &size) != SKS_OK) {
+ return true;
+ }
+
+ for (count = size / sizeof(uint32_t); count; count--) {
+ TEE_MemMove(&proc, attr, sizeof(uint32_t));
+ attr += sizeof(uint32_t);
+
+ if (proc == proc_id)
+ return true;
+ }
+
+ DMSG("can't find %s in allowed list", sks2str_proc(proc_id));
+ return false;
+}
+
+/*
+ * Check the attributes of the parent secret (key) used in the processing
+ * do match the target processing.
+ *
+ * @proc_id - SKS_CKM_xxx
+ * @subproc_id - boolean attribute encrypt or decrypt or sign or verify, if
+ * applicable to proc_id.
+ * @head - head of the attributes of parent object.
+ */
+uint32_t check_parent_attrs_against_processing(uint32_t proc_id,
+ enum processing_func function,
+ struct sks_attrs_head *head)
+{
+ uint32_t __maybe_unused rc = 0;
+ uint32_t key_class = get_class(head);
+ uint32_t key_type = get_type(head);
+
+ if (function == SKS_FUNCTION_ENCRYPT &&
+ !get_bool(head, SKS_CKA_ENCRYPT)) {
+ DMSG("encrypt not permitted");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ if (function == SKS_FUNCTION_DECRYPT &&
+ !get_bool(head, SKS_CKA_DECRYPT)) {
+ DMSG("decrypt not permitted");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ if (function == SKS_FUNCTION_SIGN &&
+ !get_bool(head, SKS_CKA_SIGN)) {
+ DMSG("sign not permitted");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ if (function == SKS_FUNCTION_VERIFY &&
+ !get_bool(head, SKS_CKA_VERIFY)) {
+ DMSG("verify not permitted");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ if (function == SKS_FUNCTION_WRAP &&
+ !get_bool(head, SKS_CKA_WRAP)) {
+ DMSG("wrap not permitted");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ if (function == SKS_FUNCTION_UNWRAP &&
+ !get_bool(head, SKS_CKA_UNWRAP)) {
+ DMSG("unwrap not permitted");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ if (function == SKS_FUNCTION_DERIVE &&
+ !get_bool(head, SKS_CKA_DERIVE)) {
+ DMSG("derive not permitted");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+
+ /* Check processing complies for parent key family */
+ switch (proc_id) {
+ case SKS_CKM_AES_ECB:
+ case SKS_CKM_AES_CBC:
+ case SKS_CKM_AES_CBC_PAD:
+ case SKS_CKM_AES_CTS:
+ case SKS_CKM_AES_CTR:
+ case SKS_CKM_AES_GCM:
+ case SKS_CKM_AES_CCM:
+ case SKS_CKM_AES_CMAC:
+ case SKS_CKM_AES_CMAC_GENERAL:
+ case SKS_CKM_AES_XCBC_MAC:
+ case SKS_CKM_MTK_HSM_AES_ECB:
+ case SKS_CKM_MTK_HSM_AES_CBC:
+ case SKS_CKM_MTK_HSM_AES_CTR:
+ case SKS_CKM_MTK_HSM_AES_GCM:
+ case SKS_CKM_MTK_HSM_AES_CMAC:
+ if (key_class == SKS_CKO_SECRET_KEY &&
+ key_type == SKS_CKK_AES)
+ break;
+
+ DMSG("%s invalid key %s/%s", sks2str_proc(proc_id),
+ sks2str_class(key_class), sks2str_key_type(key_type));
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ case SKS_CKM_MD5_HMAC:
+ case SKS_CKM_SHA_1_HMAC:
+ case SKS_CKM_SHA224_HMAC:
+ case SKS_CKM_SHA256_HMAC:
+ case SKS_CKM_SHA384_HMAC:
+ case SKS_CKM_SHA512_HMAC:
+ case SKS_CKM_MTK_HSM_SHA256_HMAC:
+ case SKS_CKM_MTK_HSM_SHA384_HMAC:
+ if (key_class != SKS_CKO_SECRET_KEY)
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ if (key_type == SKS_CKK_GENERIC_SECRET)
+ break;
+
+ switch (proc_id) {
+ case SKS_CKM_MD5_HMAC:
+ if (key_type == SKS_CKK_MD5_HMAC)
+ break;
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ case SKS_CKM_SHA_1_HMAC:
+ if (key_type == SKS_CKK_SHA_1_HMAC)
+ break;
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case SKS_CKM_SHA224_HMAC:
+ if (key_type == SKS_CKK_SHA224_HMAC)
+ break;
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case SKS_CKM_SHA256_HMAC:
+ case SKS_CKM_MTK_HSM_SHA256_HMAC:
+ if (key_type == SKS_CKK_SHA256_HMAC)
+ break;
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case SKS_CKM_SHA384_HMAC:
+ case SKS_CKM_MTK_HSM_SHA384_HMAC:
+ if (key_type == SKS_CKK_SHA384_HMAC)
+ break;
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case SKS_CKM_SHA512_HMAC:
+ if (key_type == SKS_CKK_SHA512_HMAC)
+ break;
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ default:
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+ case SKS_CKM_ECDSA:
+ case SKS_CKM_ECDSA_SHA1:
+ case SKS_CKM_ECDSA_SHA224:
+ case SKS_CKM_ECDSA_SHA256:
+ case SKS_CKM_ECDSA_SHA384:
+ case SKS_CKM_ECDSA_SHA512:
+ case SKS_CKM_ECDH1_DERIVE:
+ case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ case SKS_CKM_ECMQV_DERIVE:
+ case SKS_CKM_ECDH_AES_KEY_WRAP:
+ case SKS_CKM_MTK_HSM_ECDSA:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA1:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA224:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA256:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA384:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA512:
+ if (key_type != SKS_CKK_EC) {
+ EMSG("Invalid key %s for mechanism %s",
+ sks2str_type(key_type, key_class),
+ sks2str_proc(proc_id));
+ return SKS_CKR_KEY_TYPE_INCONSISTENT;
+ }
+ if (key_class != SKS_CKO_PUBLIC_KEY &&
+ key_class != SKS_CKO_PRIVATE_KEY) {
+ EMSG("Invalid key class for mechanism %s",
+ sks2str_proc(proc_id));
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+ case SKS_CKM_RSA_PKCS:
+ case SKS_CKM_RSA_9796:
+ case SKS_CKM_RSA_X_509:
+ case SKS_CKM_SHA1_RSA_PKCS:
+ case SKS_CKM_RSA_PKCS_OAEP:
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS:
+ case SKS_CKM_SHA384_RSA_PKCS:
+ case SKS_CKM_SHA512_RSA_PKCS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ case SKS_CKM_RSA_AES_KEY_WRAP:
+ if (key_type != SKS_CKK_RSA) {
+ EMSG("Invalid key %s for mechanism %s",
+ sks2str_type(key_type, key_class),
+ sks2str_proc(proc_id));
+ return SKS_CKR_KEY_TYPE_INCONSISTENT;
+ }
+ if (key_class != SKS_CKO_PUBLIC_KEY &&
+ key_class != SKS_CKO_PRIVATE_KEY) {
+ EMSG("Invalid key class for mechanism %s",
+ sks2str_proc(proc_id));
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA1:
+ case SKS_CKM_MTK_HSM_SHA224:
+ case SKS_CKM_MTK_HSM_SHA256:
+ case SKS_CKM_MTK_HSM_SHA384:
+ case SKS_CKM_MTK_HSM_SHA512:
+ case SKS_CKM_MTK_HSM_AES_KEY_GEN:
+ case SKS_CKM_MTK_HSM_EC_KEY_PAIR_GEN:
+ case SKS_CKM_MTK_HSM_EC_KEY_PAIR_IMPORT:
+ break;
+
+ default:
+ DMSG("Invalid processing 0x%" PRIx32 " (%s)", proc_id,
+ sks2str_proc(proc_id));
+ return SKS_CKR_MECHANISM_INVALID;
+ }
+ if (!parent_key_complies_allowed_processings(proc_id, head)) {
+ DMSG("Allowed mechanism failed");
+ return SKS_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ return SKS_OK;
+}
+
+bool object_is_private(struct sks_attrs_head *head)
+{
+ if (get_class(head) == SKS_CKO_PRIVATE_KEY)
+ return true;
+
+ if (get_bool(head, SKS_CKA_PRIVATE))
+ return true;
+
+ return false;
+}
+
+/*
+ * Add a CKA ID attribute to an object or paired object if missing.
+ * If 2 objects are provided and at least 1 does not have a CKA_ID,
+ * the 2 objects will have the same CKA_ID attribute.
+ *
+ * @attrs1 - Object
+ * @attrs2 - Object paired to attrs1 or NULL
+ * Return an SKS return code
+ */
+uint32_t add_missing_attribute_id(struct sks_attrs_head **attrs1,
+ struct sks_attrs_head **attrs2)
+{
+ uint32_t rv = 0;
+ void *id1 = NULL;
+ uint32_t id1_size = 0;
+ void *id2 = NULL;
+ uint32_t id2_size = 0;
+
+ rv = get_attribute_ptr(*attrs1, SKS_CKA_ID, &id1, &id1_size);
+ if (rv) {
+ if (rv != SKS_NOT_FOUND)
+ return rv;
+ id1 = NULL;
+ }
+
+ if (attrs2) {
+ rv = get_attribute_ptr(*attrs2, SKS_CKA_ID, &id2, &id2_size);
+ if (rv) {
+ if (rv != SKS_NOT_FOUND)
+ return rv;
+ id2 = NULL;
+ }
+
+ if (id1 && id2)
+ return SKS_OK;
+
+ if (id1 && !id2)
+ return add_attribute(attrs2, SKS_CKA_ID, id1, id1_size);
+
+ if (!id1 && id2)
+ return add_attribute(attrs1, SKS_CKA_ID, id2, id2_size);
+ } else {
+ if (id1)
+ return SKS_OK;
+ }
+
+ id1_size = SKS_CKA_DEFAULT_SIZE;
+ id1 = TEE_Malloc(id1_size, 0);
+ if (!id1)
+ return SKS_MEMORY;
+
+ TEE_GenerateRandom(id1, (uint32_t)id1_size);
+
+ rv = add_attribute(attrs1, SKS_CKA_ID, id1, id1_size);
+ if (rv == SKS_OK && attrs2)
+ rv = add_attribute(attrs2, SKS_CKA_ID, id1, id1_size);
+
+ TEE_Free(id1);
+
+ return rv;
+}
+
+bool attribute_is_exportable(struct sks_attribute_head *req_attr,
+ struct sks_object *obj)
+{
+ uint8_t boolval = 0;
+ uint32_t boolsize = 0;
+ uint32_t rv = 0;
+
+ switch (req_attr->id) {
+ case SKS_CKA_PRIVATE_EXPONENT:
+ case SKS_CKA_PRIME_1:
+ case SKS_CKA_PRIME_2:
+ case SKS_CKA_EXPONENT_1:
+ case SKS_CKA_EXPONENT_2:
+ case SKS_CKA_COEFFICIENT:
+ boolsize = sizeof(boolval);
+ rv = get_attribute(obj->attributes, SKS_CKA_EXTRACTABLE,
+ &boolval, &boolsize);
+ if (rv || boolval == SKS_FALSE)
+ return false;
+
+ boolsize = sizeof(boolval);
+ rv = get_attribute(obj->attributes, SKS_CKA_SENSITIVE,
+ &boolval, &boolsize);
+ if (rv || boolval == SKS_TRUE)
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_attributes.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_attributes.h
new file mode 100644
index 0000000..dad8414
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_attributes.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __PKCS11_ATTRIBUTE_H
+#define __PKCS11_ATTRIBUTE_H
+
+#include <inttypes.h>
+
+#include "serializer.h"
+
+/*
+ * PKCS#11 directives on object attributes.
+ * Those with a '*' are optional, other must be defined, either by caller
+ * or by some known default value.
+ *
+ * [all] objects: class
+ *
+ * [stored] objects: persistent, need_authen, modifiable, copyable,
+ * destroyable, label*.
+ *
+ * [data] objects: [all], [stored], application_id*, object_id*, value.
+ *
+ * [key] objects: [all], [stored], type, id*, start_date/end_date*,
+ * derive, local, allowed_mechanisms*.
+ *
+ * [symm-key]: [key], sensitive, encrypt, decrypt, sign, verify, wrap,
+ * unwrap, extractable, wrap_with_trusted, trusted,
+ * wrap_template, unwrap_template, derive_template.
+ */
+
+/*
+ * Utils to check compliance of attributes at various processing steps.
+ * Any processing operation is exclusively one of the following.
+ *
+ * Case 1: Create a secret from some local random value (C_CreateKey & friends)
+ * - client provides a attributes list template, pkcs11 complete with default
+ * attribute values. Object is created if attributes are consistent and
+ * comply token/session stte.
+ * - SKS sequence:
+ * - check/set token/session state
+ * - create a attribute list from client template and default values.
+ * - check new secret attributes complies requested mechanism .
+ * - check new secret attributes complies token/session state.
+ * - Generate the value for the secret.
+ * - Set some runtime attributes in the new secret.
+ * - Register the new secret and return a handle for it.
+
+ *
+ * Case 2: Create a secret from a client clear data (C_CreateObject)
+ * - client provides a attributes list template, pkcs11 complete with default
+ * attribute values. Object is created if attributes are consistent and
+ * comply token/session state.
+ * - check/set token/session state
+ * - create a attribute list from client template and default values.
+ * - check new secret attributes complies requested mechanism (raw-import).
+ * - check new secret attributes complies token/session state.
+ * - Set some runtime attributes in the new secret.
+ * - Register the new secret and return a handle for it.
+
+ * Case 3: Use a secret for data processing
+ * - client provides a mechanism ID and the secret handle.
+ * - SKS checks mechanism and secret comply, if mechanism and token/session
+ * state comply and last if secret and token/session state comply.
+ * - check/set token/session state
+ * - check secret's parent attributes complies requested processing.
+ * - check secret's parent attributes complies token/session state.
+ * - check new secret attributes complies secret's parent attributes.
+ * - check new secret attributes complies requested mechanism.
+ * - check new secret attributes complies token/session state.
+ *
+ * Case 4: Create a secret from a client template and a secret's parent
+ * (i.e derive a symmetric key)
+ * - client args: new-key template, mechanism ID, parent-key handle.
+ * - SKS create a new-key attribute list based on template + default values +
+ * inheritance from the parent key attributes.
+ * - SKS checks:
+ * - token/session state
+ * - parent-key vs mechanism
+ * - parent-key vs token/session state
+ * - parent-key vs new-key
+ * - new-key vs mechanism
+ * - new-key vs token/session state
+ * - then do processing
+ * - then finalize object creation
+ */
+
+enum processing_func {
+ SKS_FUNCTION_DIGEST,
+ SKS_FUNCTION_GENERATE,
+ SKS_FUNCTION_GENERATE_PAIR,
+ SKS_FUNCTION_DERIVE,
+ SKS_FUNCTION_WRAP,
+ SKS_FUNCTION_UNWRAP,
+ SKS_FUNCTION_ENCRYPT,
+ SKS_FUNCTION_DECRYPT,
+ SKS_FUNCTION_SIGN,
+ SKS_FUNCTION_VERIFY,
+ SKS_FUNCTION_SIGN_RECOVER,
+ SKS_FUNCTION_VERIFY_RECOVER,
+ SKS_FUNCTION_IMPORT,
+ SKS_FUNCTION_COPY,
+ SKS_FUNCTION_MODIFY,
+ SKS_FUNCTION_DESTROY,
+};
+
+enum processing_step {
+ SKS_FUNC_STEP_INIT,
+ SKS_FUNC_STEP_ONESHOT,
+ SKS_FUNC_STEP_UPDATE,
+ SKS_FUNC_STEP_FINAL,
+};
+
+struct sks_attrs_head;
+struct pkcs11_session;
+
+/* Create an attribute list for a new object (TODO: add parent attribs) */
+uint32_t create_attributes_from_template(struct sks_attrs_head **out,
+ void *template, size_t template_size,
+ uint32_t proc_id,
+ struct sks_attrs_head *parent,
+ enum processing_func func);
+
+/*
+ * The various checks to be performed before a processing:
+ * - create an new object in the current token state
+ * - use a parent object in the processing
+ * - use a mechanism with provided configuration
+ */
+uint32_t check_created_attrs_against_token(struct pkcs11_session *session,
+ struct sks_attrs_head *head);
+
+uint32_t check_created_attrs_against_parent_key(uint32_t proc_id,
+ struct sks_attrs_head *parent,
+ struct sks_attrs_head *head);
+
+uint32_t check_created_attrs_against_processing(uint32_t proc_id,
+ struct sks_attrs_head *head);
+
+uint32_t check_created_attrs(struct sks_attrs_head *key1,
+ struct sks_attrs_head *key2);
+
+uint32_t check_parent_attrs_against_processing(uint32_t proc_id,
+ enum processing_func func,
+ struct sks_attrs_head *head);
+
+uint32_t check_access_attrs_against_token(struct pkcs11_session *session,
+ struct sks_attrs_head *head);
+
+uint32_t check_mechanism_against_processing(struct pkcs11_session *session,
+ uint32_t mechanism_type,
+ enum processing_func function,
+ enum processing_step step);
+
+int check_pkcs11_mechanism_flags(uint32_t mechanism_type, uint32_t flags);
+
+bool object_is_private(struct sks_attrs_head *head);
+
+void pkcs11_max_min_key_size(uint32_t key_type, uint32_t *max_key_size,
+ uint32_t *min_key_size, bool bit_size_only);
+
+bool attribute_is_exportable(struct sks_attribute_head *req_attr,
+ struct sks_object *obj);
+
+uint32_t add_missing_attribute_id(struct sks_attrs_head **attrs1,
+ struct sks_attrs_head **attrs2);
+
+#endif /*__PKCS11_ATTRIBUTE_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_token.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_token.c
new file mode 100644
index 0000000..640af88
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_token.c
@@ -0,0 +1,1752 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <assert.h>
+#include <sks_ta.h>
+#include <string.h>
+#include <string_ext.h>
+#include <sys/queue.h>
+#include <tee_internal_api_extensions.h>
+#include <util.h>
+
+#include "attributes.h"
+#include "handle.h"
+#include "pkcs11_token.h"
+#include "pkcs11_attributes.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+#include "processing_mtk_key.h"
+
+/* ID is token index */
+#define TOKEN_COUNT CFG_SKS_TA_TOKEN_COUNT
+
+/* Static allocation of tokens runtime instances (reset to 0 at load) */
+struct ck_token ck_token[TOKEN_COUNT];
+
+static struct client_list pkcs11_client_list;
+
+static void close_ck_session(struct pkcs11_session *session);
+
+/* Static allocation of tokens runtime instances */
+struct ck_token *get_token(unsigned int token_id)
+{
+ if (token_id >= TOKEN_COUNT)
+ return NULL;
+
+ return &ck_token[token_id];
+}
+
+unsigned int get_token_id(struct ck_token *token)
+{
+ assert(token >= ck_token && token < &ck_token[TOKEN_COUNT]);
+
+ return token - ck_token;
+}
+
+/* Client */
+struct pkcs11_client *tee_session2client(uintptr_t tee_session)
+{
+ struct pkcs11_client *client;
+
+ TAILQ_FOREACH(client, &pkcs11_client_list, link) {
+ if (client == (void *)tee_session)
+ return client;
+ }
+
+ return NULL;
+}
+
+uintptr_t register_client(void)
+{
+ struct pkcs11_client *client = NULL;
+
+ client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO);
+ if (!client)
+ return 0;
+
+ TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link);
+ TAILQ_INIT(&client->session_list);
+ handle_db_init(&client->session_handle_db);
+
+ return (uintptr_t)(void *)client;
+}
+
+void unregister_client(uintptr_t tee_session)
+{
+ struct pkcs11_client *client = tee_session2client(tee_session);
+ struct pkcs11_session *session = NULL;
+ struct pkcs11_session *next = NULL;
+
+ if (!client) {
+ EMSG("Unexpected invalid TEE session handle");
+ return;
+ }
+
+ TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) {
+ close_ck_session(session);
+ }
+
+ TAILQ_REMOVE(&pkcs11_client_list, client, link);
+ handle_db_destroy(&client->session_handle_db);
+ TEE_Free(client);
+}
+
+static int pkcs11_token_init(unsigned int id)
+{
+ struct ck_token *token = init_token_db(id);
+
+ if (!token)
+ return 1;
+
+ if (token->state != PKCS11_TOKEN_RESET) {
+ /* Token is already in a valid state */
+ return 0;
+ }
+
+ /* Initialize the token runtime state */
+ token->state = PKCS11_TOKEN_READ_WRITE;
+ token->session_count = 0;
+ token->rw_session_count = 0;
+
+ return 0;
+}
+
+int pkcs11_init(void)
+{
+ unsigned int id = 0;
+
+ for (id = 0; id < TOKEN_COUNT; id++)
+ if (pkcs11_token_init(id))
+ return 1;
+
+ TAILQ_INIT(&pkcs11_client_list);
+
+ return 0;
+}
+
+void pkcs11_deinit(void)
+{
+ unsigned int id = 0;
+
+ for (id = 0; id < TOKEN_COUNT; id++)
+ close_persistent_db(get_token(id));
+}
+
+bool pkcs11_session_is_read_write(struct pkcs11_session *session)
+{
+ switch (session->state) {
+ case PKCS11_SESSION_PUBLIC_READ_WRITE:
+ case PKCS11_SESSION_USER_READ_WRITE:
+ case PKCS11_SESSION_SO_READ_WRITE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool pkcs11_session_is_security_officer(struct pkcs11_session *session)
+{
+ return session->state == PKCS11_SESSION_SO_READ_WRITE;
+}
+
+bool pkcs11_session_is_user(struct pkcs11_session *session)
+{
+ return session->state == PKCS11_SESSION_USER_READ_WRITE ||
+ session->state == PKCS11_SESSION_USER_READ_ONLY;
+}
+
+bool pkcs11_session_is_public(struct pkcs11_session *session)
+{
+ return session->state == PKCS11_SESSION_PUBLIC_READ_WRITE ||
+ session->state == PKCS11_SESSION_PUBLIC_READ_ONLY;
+}
+
+struct pkcs11_session *sks_handle2session(uint32_t handle,
+ uintptr_t tee_session)
+{
+ struct pkcs11_client *client = tee_session2client(tee_session);
+
+ return handle_lookup(&client->session_handle_db, handle);
+}
+
+/*
+ * Currently not support dual operations.
+ */
+int set_processing_state(struct pkcs11_session *session,
+ enum processing_func function,
+ struct sks_object *obj1, struct sks_object *obj2)
+{
+ enum pkcs11_proc_state state;
+ struct active_processing *proc = NULL;
+
+ TEE_MemFill(&state, 0, sizeof(state));
+
+ if (session->processing)
+ return SKS_CKR_OPERATION_ACTIVE;
+
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ state = PKCS11_SESSION_ENCRYPTING;
+ break;
+ case SKS_FUNCTION_DECRYPT:
+ state = PKCS11_SESSION_DECRYPTING;
+ break;
+ case SKS_FUNCTION_SIGN:
+ state = PKCS11_SESSION_SIGNING;
+ break;
+ case SKS_FUNCTION_VERIFY:
+ state = PKCS11_SESSION_VERIFYING;
+ break;
+ case SKS_FUNCTION_DIGEST:
+ state = PKCS11_SESSION_DIGESTING;
+ break;
+ case SKS_FUNCTION_DERIVE:
+ state = PKCS11_SESSION_READY;
+ break;
+ default:
+ TEE_Panic(function);
+ return -1;
+ }
+
+ proc = TEE_Malloc(sizeof(*proc), TEE_MALLOC_FILL_ZERO);
+ if (!proc)
+ return SKS_MEMORY;
+
+ /* Boolean are default to false and pointers to NULL */
+ proc->state = state;
+ proc->tee_op_handle = TEE_HANDLE_NULL;
+
+ if (obj1 && get_bool(obj1->attributes, SKS_CKA_ALWAYS_AUTHENTICATE))
+ proc->always_authen = true;
+
+ if (obj2 && get_bool(obj2->attributes, SKS_CKA_ALWAYS_AUTHENTICATE))
+ proc->always_authen = true;
+
+ session->processing = proc;
+
+ return SKS_OK;
+}
+
+static void cipher_pin(TEE_ObjectHandle key_handle, uint8_t *buf, size_t len)
+{
+ uint8_t iv[16] = { 0 };
+ uint32_t size = len;
+ TEE_OperationHandle tee_op_handle = TEE_HANDLE_NULL;
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ res = TEE_AllocateOperation(&tee_op_handle,
+ TEE_ALG_AES_CBC_NOPAD,
+ TEE_MODE_ENCRYPT, 128);
+ if (res)
+ TEE_Panic(0);
+
+ res = TEE_SetOperationKey(tee_op_handle, key_handle);
+ if (res)
+ TEE_Panic(0);
+
+ TEE_CipherInit(tee_op_handle, iv, sizeof(iv));
+
+ res = TEE_CipherDoFinal(tee_op_handle, buf, len, buf, &size);
+ if (res || size != SKS_TOKEN_PIN_SIZE)
+ TEE_Panic(0);
+
+ TEE_FreeOperation(tee_op_handle);
+}
+
+/* ctrl=[slot-id][pin-size][pin][label], in=unused, out=unused */
+uint32_t entry_ck_token_initialize(TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t token_id = 0;
+ uint32_t pin_size = 0;
+ void *pin = NULL;
+ char label[SKS_TOKEN_LABEL_SIZE + 1] = { 0 };
+ struct ck_token *token;
+ uint8_t *cpin = NULL;
+ int pin_rc = 0;
+ struct pkcs11_client *client;
+ struct sks_object *obj = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ token = get_token(token_id);
+ if (!token)
+ return SKS_CKR_SLOT_ID_INVALID;
+
+ rv = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ if (pin_size < 8 || pin_size > SKS_TOKEN_PIN_SIZE)
+ return SKS_CKR_PIN_LEN_RANGE;
+
+ rv = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &label, SKS_TOKEN_LABEL_SIZE);
+ if (rv)
+ return rv;
+
+ if (token->db_main->flags & SKS_CKFT_SO_PIN_LOCKED) {
+ IMSG("SKSt%u: SO PIN locked", token_id);
+ return SKS_CKR_PIN_LOCKED;
+ }
+
+ TAILQ_FOREACH(client, &pkcs11_client_list, link) {
+ if (!TAILQ_EMPTY(&client->session_list)) {
+ return SKS_CKR_SESSION_EXISTS;
+ }
+ }
+
+ cpin = TEE_Malloc(SKS_TOKEN_PIN_SIZE, TEE_MALLOC_FILL_ZERO);
+ if (!cpin) {
+ return SKS_MEMORY;
+ }
+
+ TEE_MemMove(cpin, pin, pin_size);
+ cipher_pin(token->pin_hdl[0], cpin, SKS_TOKEN_PIN_SIZE);
+
+ if (!token->db_main->so_pin_size) {
+ TEE_MemMove(token->db_main->so_pin, cpin, SKS_TOKEN_PIN_SIZE);
+ token->db_main->so_pin_size = pin_size;
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ so_pin),
+ sizeof(token->db_main->so_pin));
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ so_pin_size),
+ sizeof(token->db_main->so_pin_size));
+
+ goto inited;
+ }
+
+ pin_rc = 0;
+ if (token->db_main->so_pin_size != pin_size)
+ pin_rc = 1;
+ if (buf_compare_ct(token->db_main->so_pin, cpin, SKS_TOKEN_PIN_SIZE))
+ pin_rc = 1;
+
+ if (pin_rc) {
+ token->db_main->flags |= SKS_CKFT_SO_PIN_COUNT_LOW;
+ token->db_main->so_pin_count++;
+
+ if (token->db_main->so_pin_count == 6)
+ token->db_main->flags |= SKS_CKFT_SO_PIN_FINAL_TRY;
+ if (token->db_main->so_pin_count == 7)
+ token->db_main->flags |= SKS_CKFT_SO_PIN_LOCKED;
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ flags),
+ sizeof(token->db_main->flags));
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ so_pin_count),
+ sizeof(token->db_main->so_pin_count));
+
+ TEE_Free(cpin);
+ return SKS_CKR_PIN_INCORRECT;
+ }
+
+ token->db_main->flags &= ~(SKS_CKFT_SO_PIN_COUNT_LOW |
+ SKS_CKFT_SO_PIN_FINAL_TRY);
+ token->db_main->so_pin_count = 0;
+
+inited:
+ TEE_MemMove(token->db_main->label, label, SKS_TOKEN_LABEL_SIZE);
+ token->db_main->flags |= SKS_CKFT_TOKEN_INITIALIZED;
+ /* Reset user PIN */
+ token->db_main->user_pin_size = 0;
+ token->db_main->flags &= ~(SKS_CKFT_USER_PIN_INITIALIZED |
+ SKS_CKFT_USER_PIN_COUNT_LOW |
+ SKS_CKFT_USER_PIN_FINAL_TRY |
+ SKS_CKFT_USER_PIN_LOCKED |
+ SKS_CKFT_USER_PIN_TO_BE_CHANGED);
+
+ update_persistent_db(token, 0, sizeof(*token->db_main));
+
+ /* Remove all persistent objects */
+ if (token->db_objs && token->db_objs->count > 0) {
+ while (!LIST_EMPTY(&token->object_list)) {
+ obj = LIST_FIRST(&token->object_list);
+#ifdef DEBUG
+ MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid);
+#endif
+ mtk_delete_key(obj);
+ unregister_persistent_object(token, obj->uuid);
+ cleanup_persistent_object(obj, token);
+ }
+ }
+
+ label[SKS_TOKEN_LABEL_SIZE] = '\0';
+ IMSG("SKSt%" PRIu32 ": initialized \"%s\"", token_id, label);
+
+ TEE_Free(cpin);
+
+ return SKS_OK;
+}
+
+uint32_t entry_ck_slot_list(TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ const size_t out_size = sizeof(uint32_t) * TOKEN_COUNT;
+ uint32_t *id = NULL;
+ unsigned int n = 0;
+
+ if (ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < out_size) {
+ out->memref.size = out_size;
+ return SKS_SHORT_BUFFER;
+ }
+
+ /* FIXME: we could support unaligment buffers */
+ if ((uintptr_t)out->memref.buffer & 0x03UL)
+ return SKS_BAD_PARAM;
+
+ for (id = out->memref.buffer, n = 0; n < TOKEN_COUNT; n++, id++)
+ *id = (uint32_t)n;
+
+ out->memref.size = out_size;
+
+ return SKS_OK;
+}
+
+uint32_t entry_ck_slot_info(TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t token_id = 0;
+ struct ck_token *token = NULL;
+ const char desc[] = SKS_CRYPTOKI_SLOT_DESCRIPTION;
+ const char manuf[] = SKS_CRYPTOKI_SLOT_MANUFACTURER;
+ const char hwver[2] = SKS_CRYPTOKI_SLOT_HW_VERSION;
+ const char fwver[2] = SKS_CRYPTOKI_SLOT_FW_VERSION;
+ struct sks_slot_info info;
+ char dev_uuid[37]; /* UUID as string */
+ TEE_UUID dev_id;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+ TEE_MemFill(&info, 0, sizeof(info));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < sizeof(struct sks_slot_info)) {
+ out->memref.size = sizeof(struct sks_slot_info);
+ return SKS_SHORT_BUFFER;
+ }
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ token = get_token(token_id);
+ if (!token)
+ return SKS_CKR_SLOT_ID_INVALID;
+
+ TEE_MemFill(&info, 0, sizeof(info));
+
+ /* Set slot description to the device UUID if available */
+ if (TEE_GetPropertyAsUUID(TEE_PROPSET_TEE_IMPLEMENTATION,
+ "gpd.tee.deviceID", &dev_id) == TEE_SUCCESS) {
+ snprintf(dev_uuid, sizeof(dev_uuid),
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ dev_id.timeLow, dev_id.timeMid,
+ dev_id.timeHiAndVersion,
+ dev_id.clockSeqAndNode[0], dev_id.clockSeqAndNode[1],
+ dev_id.clockSeqAndNode[2], dev_id.clockSeqAndNode[3],
+ dev_id.clockSeqAndNode[4], dev_id.clockSeqAndNode[5],
+ dev_id.clockSeqAndNode[6], dev_id.clockSeqAndNode[7]);
+ PADDED_STRING_COPY(info.slotDescription, dev_uuid);
+ } else {
+ PADDED_STRING_COPY(info.slotDescription, desc);
+ }
+ PADDED_STRING_COPY(info.manufacturerID, manuf);
+
+ info.flags |= SKS_CKFS_TOKEN_PRESENT;
+ info.flags |= SKS_CKFS_REMOVABLE_DEVICE;
+ info.flags &= ~SKS_CKFS_HW_SLOT;
+
+ TEE_MemMove(&info.hardwareVersion, &hwver, sizeof(hwver));
+ TEE_MemMove(&info.firmwareVersion, &fwver, sizeof(fwver));
+
+ out->memref.size = sizeof(struct sks_slot_info);
+ TEE_MemMove(out->memref.buffer, &info, out->memref.size);
+
+ return SKS_OK;
+}
+
+uint32_t entry_ck_token_info(TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t token_id = 0;
+ struct ck_token *token = NULL;
+ const char manuf[] = SKS_CRYPTOKI_TOKEN_MANUFACTURER;
+ const char model[] = SKS_CRYPTOKI_TOKEN_MODEL;
+ const char hwver[] = SKS_CRYPTOKI_TOKEN_HW_VERSION;
+ const char fwver[] = SKS_CRYPTOKI_TOKEN_FW_VERSION;
+ char sernu[] = SKS_CRYPTOKI_TOKEN_SERIAL_NUMBER;
+ struct sks_token_info info;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+ TEE_MemFill(&info, 0, sizeof(info));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < sizeof(struct sks_token_info)) {
+ out->memref.size = sizeof(struct sks_token_info);
+ return SKS_SHORT_BUFFER;
+ }
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ token = get_token(token_id);
+ if (!token)
+ return SKS_CKR_SLOT_ID_INVALID;
+
+ if (snprintf(sernu + sizeof(sernu) - 2, 2, "%1d", token_id) >= 2)
+ TEE_Panic(0);
+
+ TEE_MemFill(&info, 0, sizeof(info));
+
+ PADDED_STRING_COPY(info.label, token->db_main->label);
+ PADDED_STRING_COPY(info.manufacturerID, manuf);
+ PADDED_STRING_COPY(info.model, model);
+ PADDED_STRING_COPY(info.serialNumber, sernu);
+
+ info.flags = token->db_main->flags;
+
+ /* TODO */
+ info.ulMaxSessionCount = ~0;
+ info.ulSessionCount = token->session_count;
+ info.ulMaxRwSessionCount = ~0;
+ info.ulRwSessionCount = token->rw_session_count;
+ /* TODO */
+ info.ulMaxPinLen = 128;
+ info.ulMinPinLen = 10;
+ /* TODO */
+ info.ulTotalPublicMemory = ~0;
+ info.ulFreePublicMemory = ~0;
+ info.ulTotalPrivateMemory = ~0;
+ info.ulFreePrivateMemory = ~0;
+
+ TEE_MemMove(&info.hardwareVersion, &hwver, sizeof(hwver));
+ TEE_MemMove(&info.firmwareVersion, &fwver, sizeof(hwver));
+
+ // TODO: get time and convert from reference into YYYYMMDDhhmmss/UTC
+ TEE_MemFill(info.utcTime, 0, sizeof(info.utcTime));
+
+ /* Return to caller with data */
+ out->memref.size = sizeof(struct sks_token_info);
+ TEE_MemMove(out->memref.buffer, &info, out->memref.size);
+
+ return SKS_OK;
+}
+
+uint32_t entry_ck_token_mecha_ids(TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t token_id = 0;
+ struct ck_token *token = NULL;
+ uint32_t mechanisms_count = (uint32_t)get_supported_mechanisms(NULL, 0);
+ size_t __maybe_unused count = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ token = get_token(token_id);
+ if (!token)
+ return SKS_CKR_SLOT_ID_INVALID;
+
+ if (out->memref.size < mechanisms_count * sizeof(uint32_t)) {
+ out->memref.size = mechanisms_count * sizeof(uint32_t);
+ return SKS_SHORT_BUFFER;
+ }
+
+ out->memref.size = sizeof(uint32_t) *
+ get_supported_mechanisms(out->memref.buffer, mechanisms_count);
+
+ assert(out->memref.size == mechanisms_count * sizeof(uint32_t));
+
+#ifdef DEBUG
+ for (count = 0; count < mechanisms_count; count++) {
+ IMSG("SKSt%" PRIu32 ": mechanism 0x%04" PRIx32 ": %s",
+ token_id, ((uint32_t *)out->memref.buffer)[count],
+ sks2str_proc(((uint32_t *)out->memref.buffer)[count]));
+ }
+#endif
+
+ return SKS_OK;
+}
+
+static uint32_t supported_mechanism_info_flag(uint32_t proc_id)
+{
+ uint32_t flags = 0;
+
+ switch (proc_id) {
+ case SKS_CKM_GENERIC_SECRET_KEY_GEN:
+ case SKS_CKM_AES_KEY_GEN:
+ flags = SKS_CKFM_GENERATE;
+ break;
+ case SKS_CKM_AES_ECB:
+ case SKS_CKM_AES_CBC:
+ case SKS_CKM_AES_CBC_PAD:
+ case SKS_CKM_AES_CTR:
+ case SKS_CKM_AES_CTS:
+ case SKS_CKM_AES_GCM:
+ case SKS_CKM_AES_CCM:
+ flags = SKS_CKFM_ENCRYPT | SKS_CKFM_DECRYPT |
+ SKS_CKFM_WRAP | SKS_CKFM_UNWRAP;
+ break;
+ case SKS_CKM_AES_GMAC:
+ flags = SKS_CKFM_SIGN | SKS_CKFM_VERIFY | SKS_CKFM_DERIVE;
+ break;
+ case SKS_CKM_AES_CMAC:
+ case SKS_CKM_AES_CMAC_GENERAL:
+ case SKS_CKM_MD5_HMAC:
+ case SKS_CKM_SHA_1_HMAC:
+ case SKS_CKM_SHA224_HMAC:
+ case SKS_CKM_SHA256_HMAC:
+ case SKS_CKM_SHA384_HMAC:
+ case SKS_CKM_SHA512_HMAC:
+ case SKS_CKM_AES_XCBC_MAC:
+ flags = SKS_CKFM_SIGN | SKS_CKFM_VERIFY;
+ break;
+ case SKS_CKM_AES_ECB_ENCRYPT_DATA:
+ case SKS_CKM_AES_CBC_ENCRYPT_DATA:
+ flags = SKS_CKFM_DERIVE;
+ break;
+ case SKS_CKM_EC_KEY_PAIR_GEN:
+ case SKS_CKM_RSA_PKCS_KEY_PAIR_GEN:
+ flags = SKS_CKFM_GENERATE_PAIR;
+ break;
+ case SKS_CKM_ECDSA:
+ case SKS_CKM_ECDSA_SHA1:
+ case SKS_CKM_ECDSA_SHA224:
+ case SKS_CKM_ECDSA_SHA256:
+ case SKS_CKM_ECDSA_SHA384:
+ case SKS_CKM_ECDSA_SHA512:
+ flags = SKS_CKFM_SIGN | SKS_CKFM_VERIFY;
+ break;
+ case SKS_CKM_ECDH1_DERIVE:
+ case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ case SKS_CKM_ECMQV_DERIVE:
+ flags = SKS_CKFM_DERIVE;
+ break;
+ case SKS_CKM_ECDH_AES_KEY_WRAP:
+ flags = SKS_CKFM_WRAP | SKS_CKFM_UNWRAP;
+ break;
+ case SKS_CKM_RSA_PKCS:
+ case SKS_CKM_RSA_X_509:
+ flags = SKS_CKFM_ENCRYPT | SKS_CKFM_DECRYPT |
+ SKS_CKFM_SIGN | SKS_CKFM_VERIFY |
+ SKS_CKFM_SIGN_RECOVER | SKS_CKFM_VERIFY_RECOVER |
+ SKS_CKFM_WRAP | SKS_CKFM_UNWRAP;
+ break;
+ case SKS_CKM_RSA_9796:
+ flags = SKS_CKFM_SIGN | SKS_CKFM_VERIFY |
+ SKS_CKFM_SIGN_RECOVER | SKS_CKFM_VERIFY_RECOVER;
+ break;
+
+ case SKS_CKM_RSA_PKCS_OAEP:
+ flags = SKS_CKFM_ENCRYPT | SKS_CKFM_DECRYPT |
+ SKS_CKFM_WRAP | SKS_CKFM_UNWRAP;
+ break;
+ case SKS_CKM_RSA_PKCS_PSS:
+ case SKS_CKM_SHA1_RSA_PKCS:
+ case SKS_CKM_SHA224_RSA_PKCS:
+ case SKS_CKM_SHA256_RSA_PKCS:
+ case SKS_CKM_SHA384_RSA_PKCS:
+ case SKS_CKM_SHA512_RSA_PKCS:
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ flags = SKS_CKFM_SIGN | SKS_CKFM_VERIFY;
+ break;
+ case SKS_CKM_RSA_AES_KEY_WRAP:
+ flags = SKS_CKFM_WRAP | SKS_CKFM_UNWRAP;
+ break;
+ default:
+ TEE_Panic(proc_id);
+ break;
+ }
+
+ assert(check_pkcs11_mechanism_flags(proc_id, flags) == 0);
+
+ return flags;
+}
+
+static void supported_mechanism_key_size(uint32_t proc_id,
+ uint32_t *min_key_size,
+ uint32_t *max_key_size,
+ bool bit_size_only)
+{
+ uint32_t mult = bit_size_only ? 8 : 1;
+
+ switch (proc_id) {
+ case SKS_CKM_GENERIC_SECRET_KEY_GEN:
+ *min_key_size = 1; /* in bits */
+ *max_key_size = 4096; /* in bits */
+ break;
+ case SKS_CKM_MD5_HMAC:
+ *min_key_size = 16 * mult;
+ *max_key_size = 16 * mult;
+ break;
+ case SKS_CKM_SHA_1_HMAC:
+ *min_key_size = 20 * mult;
+ *max_key_size = 20 * mult;
+ break;
+ case SKS_CKM_SHA224_HMAC:
+ *min_key_size = 28 * mult;
+ *max_key_size = 28 * mult;
+ break;
+ case SKS_CKM_SHA256_HMAC:
+ *min_key_size = 32 * mult;
+ *max_key_size = 32 * mult;
+ break;
+ case SKS_CKM_SHA384_HMAC:
+ *min_key_size = 48 * mult;
+ *max_key_size = 48 * mult;
+ break;
+ case SKS_CKM_SHA512_HMAC:
+ *min_key_size = 64 * mult;
+ *max_key_size = 64 * mult;
+ break;
+ case SKS_CKM_AES_XCBC_MAC:
+ *min_key_size = 28 * mult;
+ *max_key_size = 28 * mult;
+ break;
+ case SKS_CKM_AES_KEY_GEN:
+ case SKS_CKM_AES_ECB:
+ case SKS_CKM_AES_CBC:
+ case SKS_CKM_AES_CBC_PAD:
+ case SKS_CKM_AES_CTR:
+ case SKS_CKM_AES_CTS:
+ case SKS_CKM_AES_GCM:
+ case SKS_CKM_AES_CCM:
+ case SKS_CKM_AES_GMAC:
+ case SKS_CKM_AES_CMAC:
+ case SKS_CKM_AES_CMAC_GENERAL:
+ *min_key_size = 16 * mult;
+ *max_key_size = 32 * mult;
+ break;
+ case SKS_CKM_EC_KEY_PAIR_GEN:
+ case SKS_CKM_ECDSA:
+ case SKS_CKM_ECDSA_SHA1:
+ case SKS_CKM_ECDSA_SHA224:
+ case SKS_CKM_ECDSA_SHA256:
+ case SKS_CKM_ECDSA_SHA384:
+ case SKS_CKM_ECDSA_SHA512:
+ case SKS_CKM_ECDH1_DERIVE:
+ case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ case SKS_CKM_ECMQV_DERIVE:
+ case SKS_CKM_ECDH_AES_KEY_WRAP:
+ *min_key_size = 160; /* in bits */
+ *max_key_size = 521; /* in bits */
+ break;
+ case SKS_CKM_RSA_PKCS_KEY_PAIR_GEN:
+ case SKS_CKM_RSA_PKCS:
+ case SKS_CKM_RSA_9796:
+ case SKS_CKM_RSA_X_509:
+ case SKS_CKM_SHA1_RSA_PKCS:
+ case SKS_CKM_RSA_PKCS_OAEP:
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS:
+ case SKS_CKM_SHA384_RSA_PKCS:
+ case SKS_CKM_SHA512_RSA_PKCS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ *min_key_size = 256; /* in bits */
+ *max_key_size = 4096; /* in bits */
+ break;
+ default:
+ *min_key_size = 0;
+ *max_key_size = 0;
+ break;
+ }
+}
+
+uint32_t entry_ck_token_mecha_info(TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t token_id = 0;
+ uint32_t type = 0;
+ struct ck_token *token = NULL;
+ struct sks_mechanism_info *info = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &type, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ token = get_token(token_id);
+ if (!token)
+ return SKS_CKR_SLOT_ID_INVALID;
+
+ if (!mechanism_is_supported(type))
+ return SKS_CKR_MECHANISM_INVALID;
+
+ if (out->memref.size < sizeof(info)) {
+ out->memref.size = sizeof(info);
+ return SKS_SHORT_BUFFER;
+ }
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ info = (struct sks_mechanism_info *)out->memref.buffer;
+
+ info->flags = supported_mechanism_info_flag(type);
+
+ supported_mechanism_key_size(type, &info->min_key_size,
+ &info->max_key_size, false);
+
+ out->memref.size = sizeof(struct sks_mechanism_info);
+
+ IMSG("SKSt%" PRIu32 ": mechanism 0x%" PRIx32 " info", token_id, type);
+
+ return SKS_OK;
+}
+
+/* Select the read-only/read-write state for session login state */
+static void set_session_state(struct pkcs11_client *client,
+ struct pkcs11_session *session, bool readonly)
+{
+ struct pkcs11_session *sess = NULL;
+ enum pkcs11_session_state state = PKCS11_SESSION_RESET;
+
+ /*
+ * No need to check all client session, only the first session on
+ * target token gives client login configuration.
+ */
+ TAILQ_FOREACH(sess, &client->session_list, link) {
+ assert(sess != session);
+
+ if (sess->token != session->token)
+ continue;
+
+ switch (sess->state) {
+ case PKCS11_SESSION_PUBLIC_READ_WRITE:
+ case PKCS11_SESSION_PUBLIC_READ_ONLY:
+ state = PKCS11_SESSION_PUBLIC_READ_WRITE;
+ break;
+ case PKCS11_SESSION_USER_READ_WRITE:
+ case PKCS11_SESSION_USER_READ_ONLY:
+ state = PKCS11_SESSION_USER_READ_WRITE;
+ break;
+ case PKCS11_SESSION_SO_READ_WRITE:
+ state = PKCS11_SESSION_SO_READ_WRITE;
+ break;
+ default:
+ TEE_Panic(0);
+ }
+ break;
+ }
+
+ switch (state) {
+ case PKCS11_SESSION_USER_READ_WRITE:
+ session->state = readonly ? PKCS11_SESSION_USER_READ_ONLY :
+ PKCS11_SESSION_USER_READ_WRITE;
+ break;
+ case PKCS11_SESSION_SO_READ_WRITE:
+ /* SO cannot open read-only sessions */
+ if (readonly)
+ TEE_Panic(0);
+
+ session->state = PKCS11_SESSION_PUBLIC_READ_ONLY;
+ break;
+ default:
+ session->state = readonly ? PKCS11_SESSION_PUBLIC_READ_ONLY :
+ PKCS11_SESSION_PUBLIC_READ_WRITE;
+ break;
+ }
+}
+
+static void session_login_user(struct pkcs11_session *session)
+{
+ struct pkcs11_client *client = tee_session2client(session->tee_session);
+ struct pkcs11_session *sess = NULL;
+
+ TAILQ_FOREACH(sess, &client->session_list, link) {
+ if (sess->token != session->token)
+ continue;
+
+ if (pkcs11_session_is_read_write(sess))
+ sess->state = PKCS11_SESSION_USER_READ_WRITE;
+ else
+ sess->state = PKCS11_SESSION_USER_READ_ONLY;
+ }
+}
+
+static void session_login_so(struct pkcs11_session *session)
+{
+ struct pkcs11_client *client = tee_session2client(session->tee_session);
+ struct pkcs11_session *sess = NULL;
+
+ TAILQ_FOREACH(sess, &client->session_list, link) {
+ if (sess->token != session->token)
+ continue;
+
+ if (pkcs11_session_is_read_write(sess))
+ sess->state = PKCS11_SESSION_SO_READ_WRITE;
+ else
+ TEE_Panic(0);
+ }
+}
+
+static void session_logout(struct pkcs11_session *session)
+{
+ struct pkcs11_client *client = tee_session2client(session->tee_session);
+ struct pkcs11_session *sess = NULL;
+ struct sks_object *obj = NULL;
+
+ TAILQ_FOREACH(sess, &client->session_list, link) {
+ if (sess->token != session->token)
+ continue;
+
+ LIST_FOREACH(obj, &sess->object_list, link) {
+ if (!object_is_private(obj->attributes))
+ continue;
+
+ destroy_object(sess, obj, true);
+ handle_put(&sess->object_handle_db,
+ sks_object2handle(obj, sess));
+ }
+
+ if (pkcs11_session_is_read_write(sess))
+ sess->state = PKCS11_SESSION_PUBLIC_READ_WRITE;
+ else
+ sess->state = PKCS11_SESSION_PUBLIC_READ_ONLY;
+ }
+}
+
+/* ctrl=[slot-id], in=unused, out=[session-handle] */
+static uint32_t open_ck_session(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out, bool readonly)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t token_id = 0;
+ struct ck_token *token = NULL;
+ struct pkcs11_session *session = NULL;
+ struct pkcs11_client *client = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < sizeof(uint32_t)) {
+ out->memref.size = sizeof(uint32_t);
+ return SKS_SHORT_BUFFER;
+ }
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ token = get_token(token_id);
+ if (!token)
+ return SKS_CKR_SLOT_ID_INVALID;
+
+ if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY) {
+ return SKS_CKR_TOKEN_WRITE_PROTECTED;
+ }
+
+ client = tee_session2client(tee_session);
+ if (!client) {
+ EMSG("Unexpected invalid TEE session handle");
+ return SKS_FAILED;
+ }
+
+ if (readonly) {
+ TAILQ_FOREACH(session, &client->session_list, link) {
+ if (session->state == PKCS11_SESSION_SO_READ_WRITE) {
+ return SKS_CKR_SESSION_READ_WRITE_SO_EXISTS;
+ }
+ }
+ }
+
+ session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO);
+ if (!session)
+ return SKS_MEMORY;
+
+ session->handle = handle_get(&client->session_handle_db, session);
+ if (!session->handle) {
+ TEE_Free(session);
+ return SKS_MEMORY;
+ }
+
+ session->tee_session = tee_session;
+ session->token = token;
+ session->client = client;
+
+ LIST_INIT(&session->object_list);
+ handle_db_init(&session->object_handle_db);
+
+ set_session_state(client, session, readonly);
+
+ TAILQ_INSERT_HEAD(&client->session_list, session, link);
+
+ session->token->session_count++;
+ if (!readonly)
+ session->token->rw_session_count++;
+
+ *(uint32_t *)out->memref.buffer = session->handle;
+ out->memref.size = sizeof(uint32_t);
+
+ IMSG("SKSs%" PRIu32 ": open", session->handle);
+
+ return SKS_OK;
+}
+
+/* ctrl=[slot-id], in=unused, out=[session-handle] */
+uint32_t entry_ck_token_ro_session(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ return open_ck_session(tee_session, ctrl, in, out, true);
+}
+
+/* ctrl=[slot-id], in=unused, out=[session-handle] */
+uint32_t entry_ck_token_rw_session(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ return open_ck_session(tee_session, ctrl, in, out, false);
+}
+
+static void close_ck_session(struct pkcs11_session *session)
+{
+ release_active_processing(session);
+
+ /* No need to put object handles, the whole database is destroyed */
+ while (!LIST_EMPTY(&session->object_list)) {
+ destroy_object(session, LIST_FIRST(&session->object_list),
+ true);
+ }
+
+ release_session_find_obj_context(session);
+
+ TAILQ_REMOVE(&session->client->session_list, session, link);
+ handle_put(&session->client->session_handle_db, session->handle);
+ handle_db_destroy(&session->object_handle_db);
+
+ // If no more session, next opened one will simply be Public login
+
+ session->token->session_count--;
+ if (pkcs11_session_is_read_write(session))
+ session->token->rw_session_count--;
+
+ TEE_Free(session);
+
+ IMSG("SKSs%" PRIu32 ": close", session->handle);
+}
+
+/* ctrl=[session-handle], in=unused, out=unused */
+uint32_t entry_ck_token_close_session(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out || ctrl->memref.size < sizeof(uint32_t))
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ close_ck_session(session);
+
+ return SKS_OK;
+}
+
+uint32_t entry_ck_token_close_all(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t token_id = 0;
+ struct ck_token *token = NULL;
+ struct pkcs11_session *session = NULL;
+ struct pkcs11_session *next = NULL;
+ struct pkcs11_client *client = tee_session2client(tee_session);
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ token = get_token(token_id);
+ if (!token)
+ return SKS_CKR_SLOT_ID_INVALID;
+
+ IMSG("SKSt%" PRIu32 ": close sessions", token_id);
+
+ TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) {
+ if (session->token == token)
+ close_ck_session(session);
+ }
+
+ return SKS_OK;
+}
+
+/* ctrl=[session-handle], in=unused, out=[session-info] */
+uint32_t entry_ck_token_session_info(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_session_info info;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+ TEE_MemFill(&info, 0, sizeof(info));
+
+ if (!ctrl || in || !out || ctrl->memref.size < sizeof(uint32_t))
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ if (out->memref.size < sizeof(struct sks_session_info)) {
+ out->memref.size = sizeof(struct sks_session_info);
+ return SKS_SHORT_BUFFER;
+ }
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ info.slot_id = get_token_id(session->token);
+ switch (session->state) {
+ case PKCS11_SESSION_PUBLIC_READ_WRITE:
+ info.state = SKS_CKSS_RW_PUBLIC_SESSION;
+ break;
+ case PKCS11_SESSION_PUBLIC_READ_ONLY:
+ info.state = SKS_CKSS_RO_PUBLIC_SESSION;
+ break;
+ case PKCS11_SESSION_USER_READ_WRITE:
+ info.state = SKS_CKSS_RW_USER_FUNCTIONS;
+ break;
+ case PKCS11_SESSION_USER_READ_ONLY:
+ info.state = SKS_CKSS_RO_USER_FUNCTIONS;
+ break;
+ case PKCS11_SESSION_SO_READ_WRITE:
+ info.state = SKS_CKSS_RW_SO_FUNCTIONS;
+ break;
+ default:
+ TEE_Panic(0);
+ }
+ info.flags = SKS_CKFS_SERIAL_SESSION;
+ if (session->state == PKCS11_SESSION_USER_READ_WRITE ||
+ session->state == PKCS11_SESSION_PUBLIC_READ_WRITE)
+ info.flags |= SKS_CKFS_RW_SESSION;
+ info.error_code = 0;
+
+ /* Return to caller with data */
+ TEE_MemMove(out->memref.buffer, &info, sizeof(info));
+
+ return SKS_OK;
+}
+
+static uint32_t set_pin(struct pkcs11_session *session,
+ uint8_t *new_pin, size_t new_pin_size,
+ uint32_t user_type)
+{
+ uint8_t *cpin = NULL;
+ uint32_t *pin_count = NULL;
+ uint32_t *pin_size = NULL;
+ uint8_t *pin = NULL;
+ TEE_ObjectHandle pin_key_hdl;
+ uint32_t flag_mask = 0;
+
+ TEE_MemFill(&pin_key_hdl, 0, sizeof(pin_key_hdl));
+
+ if (session->token->db_main->flags & SKS_CKFT_WRITE_PROTECTED)
+ return SKS_CKR_TOKEN_WRITE_PROTECTED;
+
+ if (!pkcs11_session_is_read_write(session))
+ return SKS_CKR_SESSION_READ_ONLY;
+
+ if (new_pin_size < 8 || new_pin_size > SKS_TOKEN_PIN_SIZE)
+ return SKS_CKR_PIN_LEN_RANGE;
+
+ switch (user_type) {
+ case SKS_CKU_SO:
+ pin = session->token->db_main->so_pin;
+ pin_size = &session->token->db_main->so_pin_size;
+ pin_count = &session->token->db_main->so_pin_count;
+ pin_key_hdl = session->token->pin_hdl[0];
+ flag_mask = SKS_CKFT_SO_PIN_COUNT_LOW |
+ SKS_CKFT_SO_PIN_FINAL_TRY |
+ SKS_CKFT_SO_PIN_LOCKED |
+ SKS_CKFT_SO_PIN_TO_BE_CHANGED;
+ break;
+ case SKS_CKU_USER:
+ pin = session->token->db_main->user_pin;
+ pin_size = &session->token->db_main->user_pin_size;
+ pin_count = &session->token->db_main->user_pin_count;
+ pin_key_hdl = session->token->pin_hdl[1];
+ flag_mask = SKS_CKFT_USER_PIN_COUNT_LOW |
+ SKS_CKFT_USER_PIN_FINAL_TRY |
+ SKS_CKFT_USER_PIN_LOCKED |
+ SKS_CKFT_USER_PIN_TO_BE_CHANGED;
+ break;
+ default:
+ return SKS_FAILED;
+ }
+
+ cpin = TEE_Malloc(SKS_TOKEN_PIN_SIZE, TEE_MALLOC_FILL_ZERO);
+ if (!cpin)
+ return SKS_MEMORY;
+
+ TEE_MemMove(cpin, new_pin, new_pin_size);
+
+ cipher_pin(pin_key_hdl, cpin, SKS_TOKEN_PIN_SIZE);
+
+ TEE_MemMove(pin, cpin, SKS_TOKEN_PIN_SIZE);
+ *pin_size = new_pin_size;
+ *pin_count = 0;
+
+ session->token->db_main->flags &= ~flag_mask;
+
+ if (user_type == SKS_CKU_USER)
+ session->token->db_main->flags |= SKS_CKFT_USER_PIN_INITIALIZED;
+
+ // Paranoia: Check unmodified old content is still valid
+ update_persistent_db(session->token,
+ 0, sizeof(*session->token->db_main));
+
+ TEE_Free(cpin);
+
+ return SKS_OK;
+}
+
+/* ctrl=[session-handle][pin-size]{pin-arrays], in=unused, out=unused */
+uint32_t entry_init_pin(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ uint32_t pin_size = 0;
+ void *pin = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ if (!pkcs11_session_is_security_officer(session))
+ return SKS_CKR_USER_NOT_LOGGED_IN;
+
+ rv = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
+ if (rv)
+ return rv;
+
+ assert(session->token->db_main->flags & SKS_CKFT_TOKEN_INITIALIZED);
+
+ IMSG("SKSs%" PRIu32 ": init PIN", session_handle);
+
+ return set_pin(session, pin, pin_size, SKS_CKU_USER);
+}
+
+static uint32_t check_so_pin(struct pkcs11_session *session,
+ uint8_t *pin, size_t pin_size)
+{
+ struct ck_token *token = session->token;
+ uint8_t *cpin = NULL;
+ int pin_rc = 0;
+
+ /* Note: intentional return code USER_PIN_NOT_INITIALIZED */
+ if (!token->db_main->so_pin_size ||
+ !(token->db_main->flags & SKS_CKFT_TOKEN_INITIALIZED))
+ return SKS_CKR_USER_PIN_NOT_INITIALIZED;
+
+ if (token->db_main->flags & SKS_CKFT_SO_PIN_LOCKED)
+ return SKS_CKR_PIN_LOCKED;
+
+ cpin = TEE_Malloc(SKS_TOKEN_PIN_SIZE, TEE_MALLOC_FILL_ZERO);
+ if (!cpin)
+ return SKS_MEMORY;
+
+ if (pin_size > SKS_TOKEN_PIN_SIZE) {
+ TEE_Free(cpin);
+ return SKS_BAD_PARAM;
+ }
+
+ TEE_MemMove(cpin, pin, pin_size);
+ cipher_pin(token->pin_hdl[0], cpin, SKS_TOKEN_PIN_SIZE);
+
+ pin_rc = 0;
+
+ if (token->db_main->so_pin_size != pin_size)
+ pin_rc = 1;
+
+ if (buf_compare_ct(token->db_main->so_pin, cpin, SKS_TOKEN_PIN_SIZE))
+ pin_rc = 1;
+
+ TEE_Free(cpin);
+
+ if (pin_rc) {
+ token->db_main->flags |= SKS_CKFT_SO_PIN_COUNT_LOW;
+ token->db_main->so_pin_count++;
+
+ if (token->db_main->so_pin_count == 6)
+ token->db_main->flags |= SKS_CKFT_SO_PIN_FINAL_TRY;
+ if (token->db_main->so_pin_count == 7)
+ token->db_main->flags |= SKS_CKFT_SO_PIN_LOCKED;
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ flags),
+ sizeof(token->db_main->flags));
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ so_pin_count),
+ sizeof(token->db_main->so_pin_count));
+
+ if (token->db_main->flags & SKS_CKFT_SO_PIN_LOCKED)
+ return SKS_CKR_PIN_LOCKED;
+
+ return SKS_CKR_PIN_INCORRECT;
+ }
+
+ if (token->db_main->so_pin_count) {
+ token->db_main->so_pin_count = 0;
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ so_pin_count),
+ sizeof(token->db_main->so_pin_count));
+ }
+
+ if (token->db_main->flags & (SKS_CKFT_SO_PIN_COUNT_LOW |
+ SKS_CKFT_SO_PIN_FINAL_TRY)) {
+ token->db_main->flags &= ~(SKS_CKFT_SO_PIN_COUNT_LOW |
+ SKS_CKFT_SO_PIN_FINAL_TRY);
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ flags),
+ sizeof(token->db_main->flags));
+ }
+
+ return SKS_OK;
+}
+
+static uint32_t check_user_pin(struct pkcs11_session *session,
+ uint8_t *pin, size_t pin_size)
+{
+ struct ck_token *token = session->token;
+ uint8_t *cpin = NULL;
+ int pin_rc = 0;
+
+ if (!token->db_main->user_pin_size ||
+ !(token->db_main->flags & SKS_CKFT_USER_PIN_INITIALIZED))
+ return SKS_CKR_USER_PIN_NOT_INITIALIZED;
+
+ if (token->db_main->flags & SKS_CKFT_USER_PIN_LOCKED)
+ return SKS_CKR_PIN_LOCKED;
+
+ cpin = TEE_Malloc(SKS_TOKEN_PIN_SIZE, TEE_MALLOC_FILL_ZERO);
+ if (!cpin)
+ return SKS_MEMORY;
+
+ if (pin_size > SKS_TOKEN_PIN_SIZE) {
+ TEE_Free(cpin);
+ return SKS_BAD_PARAM;
+ }
+
+ TEE_MemMove(cpin, pin, pin_size);
+ cipher_pin(token->pin_hdl[1], cpin, SKS_TOKEN_PIN_SIZE);
+
+ pin_rc = 0;
+
+ if (token->db_main->user_pin_size != pin_size)
+ pin_rc = 1;
+
+ if (buf_compare_ct(token->db_main->user_pin, cpin, SKS_TOKEN_PIN_SIZE))
+ pin_rc = 1;
+
+ TEE_Free(cpin);
+
+ if (pin_rc) {
+ token->db_main->flags |= SKS_CKFT_USER_PIN_COUNT_LOW;
+ token->db_main->user_pin_count++;
+
+ if (token->db_main->user_pin_count == 6)
+ token->db_main->flags |= SKS_CKFT_USER_PIN_FINAL_TRY;
+ if (token->db_main->user_pin_count == 7)
+ token->db_main->flags |= SKS_CKFT_USER_PIN_LOCKED;
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ flags),
+ sizeof(token->db_main->flags));
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ user_pin_count),
+ sizeof(token->db_main->user_pin_count));
+
+ if (token->db_main->flags & SKS_CKFT_USER_PIN_LOCKED)
+ return SKS_CKR_PIN_LOCKED;
+
+ return SKS_CKR_PIN_INCORRECT;
+ }
+
+ if (token->db_main->user_pin_count) {
+ token->db_main->user_pin_count = 0;
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ user_pin_count),
+ sizeof(token->db_main->user_pin_count));
+ }
+
+ if (token->db_main->flags & (SKS_CKFT_USER_PIN_COUNT_LOW |
+ SKS_CKFT_USER_PIN_FINAL_TRY)) {
+ token->db_main->flags &= ~(SKS_CKFT_USER_PIN_COUNT_LOW |
+ SKS_CKFT_USER_PIN_FINAL_TRY);
+
+ update_persistent_db(token,
+ offsetof(struct token_persistent_main,
+ flags),
+ sizeof(token->db_main->flags));
+ }
+
+ return SKS_OK;
+}
+
+/* ctrl=[session][old-size]{old-pin][pin-size]{pin], in=unused, out=unused */
+uint32_t entry_set_pin(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ uint32_t old_pin_size = 0;
+ uint32_t pin_size = 0;
+ void *old_pin = NULL;
+ void *pin = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &old_pin_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get_ptr(&ctrlargs, &old_pin, old_pin_size);
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ if (!pkcs11_session_is_read_write(session))
+ return SKS_CKR_SESSION_READ_ONLY;
+
+ if (pkcs11_session_is_security_officer(session)) {
+ if (!(session->token->db_main->flags &
+ SKS_CKFT_TOKEN_INITIALIZED))
+ return SKS_ERROR;
+
+ rv = check_so_pin(session, old_pin, old_pin_size);
+ if (rv)
+ return rv;
+
+ return set_pin(session, pin, pin_size, SKS_CKU_SO);
+ }
+
+ if (!(session->token->db_main->flags & SKS_CKFT_USER_PIN_INITIALIZED))
+ return SKS_ERROR;
+
+ rv = check_user_pin(session, old_pin, old_pin_size);
+ if (rv)
+ return rv;
+
+ IMSG("SKSs%" PRIu32 ": set PIN", session_handle);
+
+ return set_pin(session, pin, pin_size, SKS_CKU_USER);
+}
+
+/* ctrl=[session][user_type][pin-size]{pin], in=unused, out=unused */
+uint32_t entry_login(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct pkcs11_session *sess = NULL;
+ struct pkcs11_client *client = NULL;
+ uint32_t user_type = 0;
+ uint32_t pin_size = 0;
+ void *pin = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ rv = serialargs_get(&ctrlargs, &user_type, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get_ptr(&ctrlargs, &pin, pin_size);
+ if (rv)
+ return rv;
+
+ client = tee_session2client(tee_session);
+
+ switch (user_type) {
+ case SKS_CKU_SO:
+ if (pkcs11_session_is_security_officer(session))
+ return SKS_CKR_USER_ALREADY_LOGGED_IN;
+
+ if (pkcs11_session_is_user(session))
+ return SKS_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ TAILQ_FOREACH(sess, &client->session_list, link)
+ if (sess->token == session->token &&
+ !pkcs11_session_is_read_write(sess))
+ return SKS_CKR_SESSION_READ_ONLY_EXISTS;
+
+ TAILQ_FOREACH(client, &pkcs11_client_list, link) {
+ TAILQ_FOREACH(sess, &client->session_list, link) {
+ if (sess->token == session->token &&
+ !pkcs11_session_is_public(sess))
+ return SKS_CKR_USER_TOO_MANY_TYPES;
+ }
+ }
+
+ rv = check_so_pin(session, pin, pin_size);
+ if (rv == SKS_OK)
+ session_login_so(session);
+
+ break;
+
+ case SKS_CKU_USER:
+ if (pkcs11_session_is_security_officer(session))
+ return SKS_CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ if (pkcs11_session_is_user(session))
+ return SKS_CKR_USER_ALREADY_LOGGED_IN;
+
+ // TODO: check all client: if SO or user logged, we can return
+ // CKR_USER_TOO_MANY_TYPES.
+
+ rv = check_user_pin(session, pin, pin_size);
+ if (rv == SKS_OK)
+ session_login_user(session);
+
+ break;
+
+ case SKS_CKU_CONTEXT_SPECIFIC:
+ if (!session_is_active(session) ||
+ !session->processing->always_authen)
+ return SKS_CKR_OPERATION_NOT_INITIALIZED;
+
+ if (pkcs11_session_is_public(session))
+ return SKS_CKR_FUNCTION_FAILED;
+
+ assert(pkcs11_session_is_user(session) ||
+ pkcs11_session_is_security_officer(session));
+
+ if (pkcs11_session_is_security_officer(session))
+ rv = check_so_pin(session, pin, pin_size);
+ else
+ rv = check_user_pin(session, pin, pin_size);
+
+ session->processing->relogged = (rv == SKS_OK);
+
+ if (rv == SKS_CKR_PIN_LOCKED)
+ session_logout(session);
+
+ break;
+
+ default:
+ return SKS_CKR_USER_TYPE_INVALID;
+ }
+
+ if (!rv)
+ IMSG("SKSs%" PRIu32 ": login", session_handle);
+
+ return rv;
+}
+
+/* ctrl=[session], in=unused, out=unused */
+uint32_t entry_logout(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ if (pkcs11_session_is_public(session))
+ return SKS_CKR_USER_NOT_LOGGED_IN;
+
+ session_logout(session);
+
+ IMSG("SKSs%" PRIu32 ": logout", session_handle);
+
+ return SKS_OK;
+}
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_token.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_token.h
new file mode 100644
index 0000000..cf2e8fa
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/pkcs11_token.h
@@ -0,0 +1,348 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+#ifndef __SKS_PKCS11_TOKEN_H__
+#define __SKS_PKCS11_TOKEN_H__
+
+#include <sys/queue.h>
+#include <tee_internal_api.h>
+
+#include "handle.h"
+#include "object.h"
+#include "pkcs11_attributes.h"
+
+/* Hard coded description */
+#define SKS_CRYPTOKI_TOKEN_LABEL "op-tee pkcs#11 token (dev...)"
+#define SKS_CRYPTOKI_TOKEN_MANUFACTURER "Linaro"
+#define SKS_CRYPTOKI_TOKEN_MODEL "OP-TEE SKS TA"
+#define SKS_CRYPTOKI_TOKEN_SERIAL_NUMBER "0000000000000000"
+#define SKS_CRYPTOKI_TOKEN_HW_VERSION { 0, 0 }
+#define SKS_CRYPTOKI_TOKEN_FW_VERSION { 0, 0 }
+
+#define SKS_CRYPTOKI_SLOT_DESCRIPTION "OP-TEE SKS TA"
+#define SKS_CRYPTOKI_SLOT_MANUFACTURER SKS_CRYPTOKI_TOKEN_MANUFACTURER
+#define SKS_CRYPTOKI_SLOT_HW_VERSION SKS_CRYPTOKI_TOKEN_HW_VERSION
+#define SKS_CRYPTOKI_SLOT_FW_VERSION SKS_CRYPTOKI_TOKEN_FW_VERSION
+
+#define PADDED_STRING_COPY(_dst, _src) \
+ do { \
+ TEE_MemFill((char *)(_dst), ' ', sizeof(_dst)); \
+ TEE_MemMove((char *)(_dst), (_src), \
+ MIN(strlen((char *)(_src)), sizeof(_dst))); \
+ } while (0)
+
+enum pkcs11_token_state {
+ PKCS11_TOKEN_RESET = 0,
+ PKCS11_TOKEN_READ_WRITE,
+ PKCS11_TOKEN_READ_ONLY,
+};
+
+enum pkcs11_session_state {
+ PKCS11_SESSION_RESET = 0,
+ PKCS11_SESSION_PUBLIC_READ_WRITE,
+ PKCS11_SESSION_PUBLIC_READ_ONLY,
+ PKCS11_SESSION_USER_READ_WRITE,
+ PKCS11_SESSION_USER_READ_ONLY,
+ PKCS11_SESSION_SO_READ_WRITE,
+};
+
+TAILQ_HEAD(client_list, pkcs11_client);
+TAILQ_HEAD(session_list, pkcs11_session);
+
+#define SKS_MAX_USERS 2
+#define SKS_TOKEN_PIN_SIZE 128
+
+/*
+ * Persistent state of the token
+ *
+ * @version - currently unused...
+ * @label - pkcs11 formatted token label, set by client
+ * @flags - pkcs11 token flags
+ * @so_pin_count - counter on security officer login failure
+ * @so_pin_size - byte size of the provisioned SO PIN
+ * @so_pin - stores the SO PIN
+ * @user_pin_count - counter on user login failure
+ * @user_pin_size - byte size of the provisioned user PIN
+ * @user_pin - stores the user PIN
+ */
+struct token_persistent_main {
+ uint32_t version;
+
+ uint8_t label[SKS_TOKEN_LABEL_SIZE];
+ uint32_t flags;
+
+ uint32_t so_pin_count;
+ uint32_t so_pin_size;
+ uint8_t so_pin[SKS_TOKEN_PIN_SIZE];
+
+ uint32_t user_pin_count;
+ uint32_t user_pin_size;
+ uint8_t user_pin[SKS_TOKEN_PIN_SIZE];
+};
+
+/*
+ * Persistent objects in the token
+ *
+ * @count - number of object stored in the token
+ * @uudis - start of object references/UUIDs (@count items)
+ */
+struct token_persistent_objs {
+ uint32_t count;
+ TEE_UUID uuids[];
+};
+
+/*
+ * Runtime state of the token, complies with pkcs11
+ *
+ * @login_state - Pkcs11 login is public, user, SO or custom
+ * @db_hld - TEE handle on the persistent database object or TEE_HANDLE_NULL
+ * @pin_hld - TEE handles on PIN ciphering keys
+ * @db_main - Volatile copy of the persistent main database
+ * @session_count - Counter for opened Pkcs11 sessions
+ * @rw_session_count - Count for opened Pkcs11 read/write sessions
+ * @session_state - Login state of the token
+ * @session_list - Head of the list of the sessions owned by the token
+ */
+struct ck_token {
+ enum pkcs11_token_state state;
+ uint32_t session_count;
+ uint32_t rw_session_count;
+
+ struct object_list object_list;
+
+ TEE_ObjectHandle db_hdl; /* Opened handle to persistent database */
+ TEE_ObjectHandle pin_hdl[SKS_MAX_USERS]; /* Opened handle to PIN keys */
+ struct token_persistent_main *db_main; /* Copy persistent database */
+ struct token_persistent_objs *db_objs; /* Copy persistent database */
+};
+
+/*
+ * A session can enter a processing state (encrypt, decrypt, digest, ...
+ * only from the initialized state. A session must return the initialized
+ * state (from a processing finalization request) before entering another
+ * processing state.
+ */
+enum pkcs11_proc_state {
+ PKCS11_SESSION_READY = 0, /* No active processing/operation */
+ PKCS11_SESSION_ENCRYPTING,
+ PKCS11_SESSION_DECRYPTING,
+ PKCS11_SESSION_DIGESTING,
+ PKCS11_SESSION_DIGESTING_ENCRYPTING, /* case C_DigestEncryptUpdate */
+ PKCS11_SESSION_DECRYPTING_DIGESTING, /* case C_DecryptDigestUpdate */
+ PKCS11_SESSION_SIGNING,
+ PKCS11_SESSION_SIGNING_ENCRYPTING, /* case C_SignEncryptUpdate */
+ PKCS11_SESSION_VERIFYING,
+ PKCS11_SESSION_DECRYPTING_VERIFYING, /* case C_DecryptVerifyUpdate */
+ PKCS11_SESSION_SIGNING_RECOVER,
+ PKCS11_SESSION_VERIFYING_RECOVER,
+};
+
+/*
+ * Context of the active processing in the session
+ *
+ * @state - ongoing active processing function or ready state
+ * @mecha_type - mechanism type of the active processing
+ * @updated - true once an active operation is updated
+ * @relogged - true once client logged since last operation update
+ * @always_authen - true if user need to login before each use
+ * @tee_op_handle - handle on active crypto operation or TEE_HANDLE_NULL
+ * @extra_ctx - context for the active processing
+ */
+#define AES_BLOCK_SIZE (16)
+#define SHA_MAX_OUTPUT_SIZE (64)
+#define SHA_MAX_BLOCK_SIZE (128)
+typedef struct
+{
+ uint8_t algorithm;
+ uint8_t CBC_IV[AES_BLOCK_SIZE];
+ uint8_t CTR[AES_BLOCK_SIZE];
+ uint8_t CMAC_Buf[AES_BLOCK_SIZE];
+ uint8_t SHA_IV[SHA_MAX_OUTPUT_SIZE];
+ uint8_t SHA_buf[SHA_MAX_BLOCK_SIZE];
+ uint32_t SHA_remain_len;
+ uint8_t isFirstUpdate;
+ uint8_t H[AES_BLOCK_SIZE];
+ uint8_t J0[AES_BLOCK_SIZE];
+ uint8_t S[AES_BLOCK_SIZE];
+ uint32_t add_len;
+ uint32_t total_len;
+
+ vaddr_t key1;
+ uint32_t key1_len;
+ uint32_t key1_id;
+ vaddr_t key2;
+ uint32_t key2_len;
+ uint32_t key2_id;
+
+} MTK_HSM_State;
+
+struct active_processing {
+ enum pkcs11_proc_state state;
+ uint32_t mecha_type;
+ bool always_authen;
+ bool relogged;
+ bool updated;
+ // TODO: end time for object usage
+ TEE_OperationHandle tee_op_handle;
+ TEE_OperationHandle extra_op_handle;
+ MTK_HSM_State *mtk_hsm_handle;
+ void *extra_ctx;
+};
+
+/*
+ * Pkcs11 objects search context
+ *
+ * @attributes - matching attributes list searched (null if no search)
+ * @count - number of matching handle found
+ * @handles - array of handle of matching objects (published handles)
+ * @next - index of the next object handle to return to FindObject
+ * @temp_start - index of the trailing not yet published handles
+ */
+struct pkcs11_find_objects {
+ void *attributes;
+ size_t count;
+ uint32_t *handles;
+ size_t next;
+ size_t temp_start;
+};
+
+/*
+ * Structure tracking client applications
+ *
+ * TODO: rename pkcs11_client into sks_client
+ *
+ * @link - chained list of registered client applications
+ * @sessions - list of the PKCS11 sessions opened by the client application
+ */
+struct pkcs11_client {
+ TAILQ_ENTRY(pkcs11_client) link;
+ struct session_list session_list;
+ struct handle_db session_handle_db;
+};
+
+/*
+ * Structure tracking the PKCS#11 sessions
+ *
+ * @link - list of the session belonging to a client
+ * @tee_session - TEE session handle used by PKCS11 session client
+ * @client - client the session belongs to (FIXME: redundant with tee_session)
+ * @token - token this session belongs to
+ * @handle - identifier of the session published to the client
+ * @object_list - entry of the session objects list
+ * @object_handle_db - database for object handles published by the session
+ * @state - R/W SO, R/W user, RO user, R/W public, RO public.
+ * @find_ctx - point to active search context (null if no active search)
+ */
+struct pkcs11_session {
+ TAILQ_ENTRY(pkcs11_session) link;
+ uintptr_t tee_session;
+ struct pkcs11_client *client;
+ struct ck_token *token;
+ uint32_t handle;
+ struct object_list object_list;
+ struct handle_db object_handle_db;
+ enum pkcs11_session_state state;
+ struct active_processing *processing;
+ struct pkcs11_find_objects *find_ctx;
+};
+
+/* Initialize static token instance(s) from default/persistent database */
+int pkcs11_init(void);
+void pkcs11_deinit(void);
+
+/* Return token instance from token identifier */
+struct ck_token *get_token(unsigned int token_id);
+
+/* Return token identified from token instance address */
+unsigned int get_token_id(struct ck_token *token);
+
+/* Initialize target token database */
+struct ck_token *init_token_db(unsigned int token_id);
+
+/* Persistent database update */
+int update_persistent_db(struct ck_token *token, size_t offset, size_t size);
+void close_persistent_db(struct ck_token *token);
+
+/* Token persistent objects */
+uint32_t create_object_uuid(struct ck_token *token, struct sks_object *obj);
+void destroy_object_uuid(struct ck_token *token, struct sks_object *obj);
+uint32_t unregister_persistent_object(struct ck_token *token, TEE_UUID *uuid);
+uint32_t register_persistent_object(struct ck_token *token, TEE_UUID *uuid);
+uint32_t get_persistent_objects_list(struct ck_token *token,
+ TEE_UUID *array, size_t *size);
+
+/*
+ * Pkcs11 session support
+ */
+struct pkcs11_client *tee_session2client(uintptr_t tee_session);
+uintptr_t register_client(void);
+void unregister_client(uintptr_t tee_session);
+
+void ck_token_close_tee_session(uintptr_t tee_session);
+struct pkcs11_session *sks_handle2session(uint32_t handle,
+ uintptr_t tee_session);
+
+static inline bool session_is_active(struct pkcs11_session *session)
+{
+ return session->processing != NULL;
+}
+
+int set_processing_state(struct pkcs11_session *session,
+ enum processing_func function,
+ struct sks_object *obj1, struct sks_object *obj2);
+
+bool pkcs11_session_is_read_write(struct pkcs11_session *session);
+bool pkcs11_session_is_public(struct pkcs11_session *session);
+bool pkcs11_session_is_user(struct pkcs11_session *session);
+bool pkcs11_session_is_security_officer(struct pkcs11_session *session);
+
+static inline
+struct object_list *pkcs11_get_session_objects(struct pkcs11_session *session)
+{
+ return &session->object_list;
+}
+
+static inline
+struct ck_token *pkcs11_session2token(struct pkcs11_session *session)
+{
+ return session->token;
+}
+
+/*
+ * Entry point for the TA commands
+ */
+uint32_t entry_ck_slot_list(TEE_Param *ctrl, TEE_Param *in, TEE_Param *out);
+uint32_t entry_ck_slot_info(TEE_Param *ctrl, TEE_Param *in, TEE_Param *out);
+uint32_t entry_ck_token_info(TEE_Param *ctrl, TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_ck_token_initialize(TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_ck_token_mecha_ids(TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_ck_token_mecha_info(TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_ck_token_ro_session(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+uint32_t entry_ck_token_rw_session(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+uint32_t entry_ck_token_close_session(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+uint32_t entry_ck_token_close_all(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+uint32_t entry_ck_token_session_info(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_init_pin(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+uint32_t entry_set_pin(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+uint32_t entry_login(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+uint32_t entry_logout(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+#endif /*__SKS_PKCS11_TOKEN_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing.c
new file mode 100644
index 0000000..c051855
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing.c
@@ -0,0 +1,1875 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <assert.h>
+#include <sks_internal_abi.h>
+#include <sks_ta.h>
+#include <string.h>
+#include <tee_api_defines.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <util.h>
+
+#include "attributes.h"
+#include "object.h"
+#include "pkcs11_token.h"
+#include "pkcs11_attributes.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+#include "processing_mtk_hsm.h"
+#include "processing_mtk_key.h"
+
+static uint32_t get_ready_session(struct pkcs11_session **sess,
+ uint32_t session_handle,
+ uintptr_t tee_session)
+{
+ struct pkcs11_session *session = NULL;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ if (session_is_active(session))
+ return SKS_CKR_OPERATION_ACTIVE;
+
+ *sess = session;
+
+ return SKS_OK;
+}
+
+static bool func_matches_state(enum processing_func function,
+ enum pkcs11_proc_state state)
+{
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ return (state == PKCS11_SESSION_ENCRYPTING ||
+ state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
+ state == PKCS11_SESSION_SIGNING_ENCRYPTING);
+ case SKS_FUNCTION_DECRYPT:
+ return (state == PKCS11_SESSION_DECRYPTING ||
+ state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
+ state == PKCS11_SESSION_DECRYPTING_VERIFYING);
+ case SKS_FUNCTION_DIGEST:
+ return (state == PKCS11_SESSION_DIGESTING ||
+ state == PKCS11_SESSION_DIGESTING_ENCRYPTING);
+ case SKS_FUNCTION_SIGN:
+ return (state == PKCS11_SESSION_SIGNING ||
+ state == PKCS11_SESSION_SIGNING_ENCRYPTING);
+ case SKS_FUNCTION_VERIFY:
+ return (state == PKCS11_SESSION_VERIFYING ||
+ state == PKCS11_SESSION_DECRYPTING_VERIFYING);
+ case SKS_FUNCTION_SIGN_RECOVER:
+ return state == PKCS11_SESSION_SIGNING_RECOVER;
+ case SKS_FUNCTION_VERIFY_RECOVER:
+ return state == PKCS11_SESSION_SIGNING_RECOVER;
+ default:
+ TEE_Panic(function);
+ return false;
+ }
+}
+
+static uint32_t get_active_session(struct pkcs11_session **sess,
+ uint32_t session_handle,
+ uintptr_t tee_session,
+ enum processing_func function)
+{
+ struct pkcs11_session *session = NULL;
+ uint32_t rv = SKS_CKR_OPERATION_NOT_INITIALIZED;
+
+ session = sks_handle2session(session_handle, tee_session);
+ if (!session)
+ return SKS_CKR_SESSION_HANDLE_INVALID;
+
+ if (session->processing &&
+ func_matches_state(function, session->processing->state)) {
+ *sess = session;
+ rv = SKS_OK;
+ }
+
+ return rv;
+}
+
+void release_active_processing(struct pkcs11_session *session)
+{
+ if (!session->processing)
+ return;
+
+ switch (session->processing->mecha_type) {
+ case SKS_CKM_AES_CTR:
+ tee_release_ctr_operation(session->processing);
+ break;
+ case SKS_CKM_AES_GCM:
+ tee_release_gcm_operation(session->processing);
+ break;
+ case SKS_CKM_AES_CCM:
+ tee_release_ccm_operation(session->processing);
+ break;
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ tee_release_rsa_pss_operation(session->processing);
+ break;
+ default:
+ break;
+ }
+
+ if (session->processing->mtk_hsm_handle != TEE_HANDLE_NULL) {
+ TEE_Free(session->processing->mtk_hsm_handle);
+ session->processing->mtk_hsm_handle = TEE_HANDLE_NULL;
+ }
+
+ if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
+ TEE_FreeOperation(session->processing->tee_op_handle);
+ session->processing->tee_op_handle = TEE_HANDLE_NULL;
+ }
+
+ if (session->processing->extra_op_handle != TEE_HANDLE_NULL) {
+ TEE_FreeOperation(session->processing->extra_op_handle);
+ session->processing->extra_op_handle = TEE_HANDLE_NULL;
+ }
+
+ TEE_Free(session->processing);
+ session->processing = NULL;
+}
+
+uint32_t entry_import_object(uintptr_t tee_session,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attrs_head *head = NULL;
+ struct sks_object_head *template = NULL;
+ size_t template_size = 0;
+ uint32_t obj_handle = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ /*
+ * Collect the arguments of the request
+ */
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < sizeof(uint32_t)) {
+ out->memref.size = sizeof(uint32_t);
+ return SKS_SHORT_BUFFER;
+ }
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, tee_session);
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ goto bail;
+
+ template_size = sizeof(*template) + template->attrs_size;
+
+ /*
+ * Prepare a clean initial state for the requested object attributes.
+ * Free temporary template once done.
+ */
+ rv = create_attributes_from_template(&head, template, template_size,
+ SKS_UNDEFINED_ID, NULL,
+ SKS_FUNCTION_IMPORT);
+ TEE_Free(template);
+ template = NULL;
+ if (rv)
+ goto bail;
+
+ /*
+ * Check target object attributes match target processing
+ * Check target object attributes match token state
+ */
+ rv = check_created_attrs_against_processing(SKS_PROCESSING_IMPORT,
+ head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_token(session, head);
+ if (rv)
+ goto bail;
+
+ /*
+ * TODO: test object (will check all expected attributes are in place
+ */
+
+ /*
+ * At this stage the object is almost created: all its attributes are
+ * referenced in @head, including the key value and are assume
+ * reliable. Now need to register it and get a handle for it.
+ */
+ rv = create_object(session, head, &obj_handle);
+ if (rv)
+ goto bail;
+
+ /*
+ * Now obj_handle (through the related struct sks_object instance)
+ * owns the serialised buffer that holds the object attributes.
+ * We reset attrs->buffer to NULL as serializer object is no more
+ * the attributes buffer owner.
+ */
+ head = NULL;
+
+ TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(uint32_t));
+ out->memref.size = sizeof(uint32_t);
+
+ IMSG("SKSs%" PRIu32 ": import object 0x%" PRIx32,
+ session_handle, obj_handle);
+
+bail:
+ TEE_Free(template);
+ TEE_Free(head);
+
+ return rv;
+}
+
+size_t get_object_key_bit_size(struct sks_object *obj)
+{
+ void *a_ptr = NULL;
+ uint32_t a_size = 0;
+ struct sks_attrs_head *attrs = obj->attributes;
+
+ switch (get_type(attrs)) {
+ case SKS_CKK_AES:
+ case SKS_CKK_GENERIC_SECRET:
+ case SKS_CKK_MD5_HMAC:
+ case SKS_CKK_SHA_1_HMAC:
+ case SKS_CKK_SHA224_HMAC:
+ case SKS_CKK_SHA256_HMAC:
+ case SKS_CKK_SHA384_HMAC:
+ case SKS_CKK_SHA512_HMAC:
+ if (get_attribute_ptr(attrs, SKS_CKA_VALUE, NULL, &a_size))
+ return 0;
+
+ return a_size * 8;
+
+ case SKS_CKK_RSA:
+ if (get_attribute_ptr(attrs, SKS_CKA_MODULUS, NULL, &a_size))
+ return 0;
+
+ return a_size * 8;
+
+ case SKS_CKK_EC:
+ if (get_attribute_ptr(attrs, SKS_CKA_EC_PARAMS,
+ &a_ptr, &a_size))
+ return 0;
+
+ return ec_params2tee_keysize(a_ptr, a_size);
+
+ default:
+ TEE_Panic(0);
+ return 0;
+ }
+}
+
+static uint32_t generate_random_key_value(struct sks_attrs_head **head)
+{
+ uint32_t rv = 0;
+ void *data;
+ uint32_t data_size;
+ uint32_t value_len;
+ void *value;
+ int keyid = 0;
+
+ if (!*head)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+
+ rv = get_attribute_ptr(*head, SKS_CKA_VALUE_LEN, &data, &data_size);
+ if (rv || data_size != sizeof(uint32_t)) {
+ DMSG("%s", rv ? "No attribute value_len found" :
+ "Invalid size for attribute VALUE_LEN");
+ return SKS_CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ TEE_MemMove(&value_len, data, data_size);
+
+ if (get_type(*head) == SKS_CKK_GENERIC_SECRET)
+ value_len = (value_len + 7) / 8;
+
+ value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!value)
+ return SKS_MEMORY;
+
+ TEE_GenerateRandom(value, value_len);
+
+ rv = add_attribute(head, SKS_CKA_VALUE, value, value_len);
+
+ TEE_Free(value);
+
+ return rv;
+}
+
+static uint32_t generate_hsm_key(struct sks_attrs_head **head)
+{
+ uint32_t rv = 0;
+ void *data;
+ uint32_t data_size;
+ uint32_t value_len;
+ void *value;
+ int keyid = 0;
+
+ if (!*head)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+
+ rv = get_attribute_ptr(*head, SKS_CKA_VALUE_LEN, &data, &data_size);
+ if (rv || data_size != sizeof(uint32_t)) {
+ DMSG("%s", rv ? "No attribute value_len found" :
+ "Invalid size for attribute VALUE_LEN");
+ return SKS_CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ TEE_MemMove(&value_len, data, data_size);
+
+ if (get_type(*head) == SKS_CKK_GENERIC_SECRET)
+ value_len = (value_len + 7) / 8;
+
+ rv = mtk_generate_symmetric_key(value_len, &keyid);
+ if (rv)
+ return SKS_CKR_GENERAL_ERROR;
+
+ rv = add_attribute(head, SKS_CKA_HSM_KEY_ID, &keyid, sizeof(keyid));
+ if (rv)
+ return SKS_CKR_GENERAL_ERROR;
+
+ rv = add_attribute(head, SKS_CKA_HSM_KEY_LEN, &value_len, sizeof(value_len));
+ if (rv )
+ return SKS_CKR_GENERAL_ERROR;
+
+ return rv;
+}
+
+uint32_t entry_generate_secret(uintptr_t tee_session,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attribute_head *proc_params = NULL;
+ struct sks_attrs_head *head = NULL;
+ struct sks_object_head *template = NULL;
+ size_t template_size = 0;
+ uint32_t obj_handle = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < sizeof(uint32_t)) {
+ out->memref.size = sizeof(uint32_t);
+ return SKS_SHORT_BUFFER;
+ }
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, tee_session);
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
+ if (rv)
+ goto bail;
+
+ switch (proc_params->id) {
+ case SKS_CKM_GENERIC_SECRET_KEY_GEN:
+ case SKS_CKM_AES_KEY_GEN:
+ case SKS_CKM_MTK_HSM_AES_KEY_GEN:
+ break;
+ default:
+ rv = SKS_CKR_MECHANISM_INVALID;
+ goto bail;
+ }
+
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ goto bail;
+
+ template_size = sizeof(*template) + template->attrs_size;
+
+ rv = check_mechanism_against_processing(session, proc_params->id,
+ SKS_FUNCTION_GENERATE,
+ SKS_FUNC_STEP_INIT);
+ if (rv)
+ goto bail;
+
+ /*
+ * Prepare a clean initial state for the requested object attributes.
+ * Free temporary template once done.
+ */
+ rv = create_attributes_from_template(&head, template, template_size,
+ proc_params->id, NULL,
+ SKS_FUNCTION_GENERATE);
+ if (rv)
+ goto bail;
+
+ TEE_Free(template);
+ template = NULL;
+
+ rv = check_created_attrs(head, NULL);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_processing(proc_params->id, head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_token(session, head);
+ if (rv)
+ goto bail;
+
+ /* TODO : Not finished */
+ // rv = check_key_object_not_generated(session, head);
+ // if (rv)
+ // {
+ // IMSG("[%s][%d] check_key_object_not_generated\n", __FUNCTION__, __LINE__);
+ // goto bail;
+ // }
+
+ /*
+ * Execute target processing and add value as attribute SKS_CKA_VALUE.
+ * Symm key generation: depends on target processing to be used.
+ */
+ switch (proc_params->id) {
+ case SKS_CKM_GENERIC_SECRET_KEY_GEN:
+ case SKS_CKM_AES_KEY_GEN:
+ /* Generate random of size specified by attribute VALUE_LEN */
+ rv = generate_random_key_value(&head);
+ if (rv)
+ goto bail;
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_KEY_GEN:
+ rv = generate_hsm_key(&head);
+ if (rv)
+ goto bail;
+ break;
+ default:
+ rv = SKS_CKR_MECHANISM_INVALID;
+ goto bail;
+ }
+
+ TEE_Free(proc_params);
+ proc_params = NULL;
+
+ /*
+ * Object is ready, register it and return a handle.
+ */
+ rv = create_object(session, head, &obj_handle);
+ if (rv)
+ goto bail;
+
+ /*
+ * Now obj_handle (through the related struct sks_object instance)
+ * owns the serialized buffer that holds the object attributes.
+ * We reset attrs->buffer to NULL as serializer object is no more
+ * the attributes buffer owner.
+ */
+ head = NULL;
+
+ TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(uint32_t));
+ out->memref.size = sizeof(uint32_t);
+
+ IMSG("SKSs%" PRIu32 ": generate secret 0x%" PRIx32,
+ session_handle, obj_handle);
+
+bail:
+ TEE_Free(proc_params);
+ TEE_Free(template);
+ TEE_Free(head);
+
+ return rv;
+}
+
+uint32_t alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
+ uint32_t attribute,
+ void **data, size_t *size)
+{
+ TEE_Result res = TEE_ERROR_GENERIC;
+ void *ptr = NULL;
+ uint32_t sz = 0;
+
+ res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
+ if (res != TEE_ERROR_SHORT_BUFFER)
+ return SKS_FAILED;
+
+ ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!ptr)
+ return SKS_MEMORY;
+
+ res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
+ if (res) {
+ TEE_Free(ptr);
+ } else {
+ *data = ptr;
+ *size = sz;
+ }
+
+ return tee2sks_error(res);
+}
+
+uint32_t tee2sks_add_attribute(struct sks_attrs_head **head, uint32_t sks_id,
+ TEE_ObjectHandle tee_obj, uint32_t tee_id)
+{
+ uint32_t rv = 0;
+ void *a_ptr = NULL;
+ size_t a_size = 0;
+
+ rv = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size);
+ if (rv)
+ goto bail;
+
+ rv = add_attribute(head, sks_id, a_ptr, a_size);
+
+ TEE_Free(a_ptr);
+
+bail:
+ if (rv)
+ EMSG("Failed TEE attribute 0x%" PRIx32 "for %s (0x%" PRIx32 ")",
+ tee_id, sks2str_attr(sks_id), sks_id);
+ return rv;
+}
+
+uint32_t entry_generate_key_pair(uintptr_t teesess,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attribute_head *proc_params = NULL;
+ struct sks_attrs_head *pub_head = NULL;
+ struct sks_attrs_head *priv_head = NULL;
+ struct sks_object_head *template = NULL;
+ size_t template_size = 0;
+ uint32_t pubkey_handle = 0;
+ uint32_t privkey_handle = 0;
+ uint32_t *hdl_ptr = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < 2 * sizeof(uint32_t))
+ return SKS_SHORT_BUFFER;
+
+ // FIXME: cleaner way to test alignment of out buffer
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, teesess);
+ if (rv)
+ return rv;
+
+ /* Get mechanism parameters */
+ rv = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
+ if (rv)
+ goto bail;
+
+ rv = check_mechanism_against_processing(session, proc_params->id,
+ SKS_FUNCTION_GENERATE_PAIR,
+ SKS_FUNC_STEP_INIT);
+ if (rv)
+ goto bail;
+
+ switch (proc_params->id) {
+ case SKS_CKM_EC_KEY_PAIR_GEN:
+ case SKS_CKM_RSA_PKCS_KEY_PAIR_GEN:
+ case SKS_CKM_MTK_HSM_EC_KEY_PAIR_GEN:
+ break;
+ default:
+ rv = SKS_CKR_MECHANISM_INVALID;
+ goto bail;
+ }
+
+ /* Get and check public key attributes */
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ goto bail;
+
+ template_size = sizeof(*template) + template->attrs_size;
+
+ rv = create_attributes_from_template(&pub_head, template, template_size,
+ proc_params->id, NULL,
+ SKS_FUNCTION_GENERATE_PAIR);
+ if (rv)
+ goto bail;
+
+ TEE_Free(template);
+ template = NULL;
+
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ goto bail;
+
+ template_size = sizeof(*template) + template->attrs_size;
+
+ rv = create_attributes_from_template(&priv_head, template, template_size,
+ proc_params->id, NULL,
+ SKS_FUNCTION_GENERATE_PAIR);
+ if (rv)
+ goto bail;
+
+ TEE_Free(template);
+ template = NULL;
+
+ /* Generate CKA_ID for keys if not specified by the templates */
+ rv = add_missing_attribute_id(&pub_head, &priv_head);
+ if (rv)
+ goto bail;
+
+ /* Check created object against processing and token state */
+ rv = check_created_attrs(pub_head, priv_head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_processing(proc_params->id, pub_head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_processing(proc_params->id, priv_head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_token(session, pub_head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_token(session, priv_head);
+ if (rv)
+ goto bail;
+
+ /* Generate key pair */
+ switch (proc_params->id) {
+ case SKS_CKM_EC_KEY_PAIR_GEN:
+ rv = generate_ec_keys(proc_params, &pub_head, &priv_head);
+ break;
+ case SKS_CKM_MTK_HSM_EC_KEY_PAIR_GEN:
+ rv = generate_hsm_ec_keys(proc_params, &pub_head, &priv_head);
+ break;
+ case SKS_CKM_RSA_PKCS_KEY_PAIR_GEN:
+ rv = generate_rsa_keys(proc_params, &pub_head, &priv_head);
+ break;
+ default:
+ rv = SKS_CKR_MECHANISM_INVALID;
+ break;
+ }
+ if (rv)
+ goto bail;
+
+ TEE_Free(proc_params);
+ proc_params = NULL;
+
+ /*
+ * Object is ready, register it and return a handle.
+ */
+ rv = create_object(session, pub_head, &pubkey_handle);
+ if (rv)
+ goto bail;
+
+ rv = create_object(session, priv_head, &privkey_handle);
+ if (rv)
+ goto bail;
+
+ /*
+ * Now obj_handle (through the related struct sks_object instance)
+ * owns the serialized buffer that holds the object attributes.
+ * We reset attrs->buffer to NULL as serializer object is no more
+ * the attributes buffer owner.
+ */
+ pub_head = NULL;
+ priv_head = NULL;
+ hdl_ptr = (uint32_t *)out->memref.buffer;
+
+ TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(uint32_t));
+ TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(uint32_t));
+ out->memref.size = 2 * sizeof(uint32_t);
+
+ IMSG("SKSs%" PRIu32 ": create key pair 0x%" PRIx32 "/0x%" PRIx32,
+ session_handle, privkey_handle, pubkey_handle);
+
+bail:
+ TEE_Free(proc_params);
+ TEE_Free(template);
+ TEE_Free(pub_head);
+ TEE_Free(priv_head);
+
+ return rv;
+}
+
+uint32_t entry_digesting_init(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attribute_head *proc_params = NULL;
+ struct sks_object *obj = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, tee_session);
+ if (rv)
+ return rv;
+
+ rv = set_processing_state(session, function, obj, NULL);
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
+ if (rv)
+ goto bail;
+
+ if (proc_params->id & SKS_CKM_MTK_HSM_EXT)
+ {
+ switch (proc_params->id)
+ {
+ case SKS_CKM_MTK_HSM_SHA1:
+ case SKS_CKM_MTK_HSM_SHA224:
+ case SKS_CKM_MTK_HSM_SHA256:
+ case SKS_CKM_MTK_HSM_SHA384:
+ case SKS_CKM_MTK_HSM_SHA512:
+ rv = mtk_SHA_init(session, proc_params);
+ break;
+
+ default:
+ rv = SKS_BAD_PARAM;
+ break;
+ }
+
+ if (rv == SKS_OK) {
+ session->processing->mecha_type = proc_params->id;
+ DMSG("SKSs%" PRIu32 ": init processing %s %s",
+ session_handle, sks2str_proc(proc_params->id),
+ sks2str_function(function));
+ } else {
+ EMSG(" entry_digesting_init FAIL!! \n");
+ }
+
+ goto bail;
+ }
+
+
+bail:
+ if (rv && session)
+ release_active_processing(session);
+
+ TEE_Free(proc_params);
+
+ return rv;
+}
+
+uint32_t entry_digesting_step(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step)
+{
+
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ uint32_t mecha_type = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_active_session(&session, session_handle, tee_session,
+ function);
+ if (rv)
+ return rv;
+
+ mecha_type = session->processing->mecha_type;
+ if (mecha_type & SKS_CKM_MTK_HSM_EXT)
+ {
+ switch (mecha_type)
+ {
+ case SKS_CKM_MTK_HSM_SHA1:
+ case SKS_CKM_MTK_HSM_SHA224:
+ case SKS_CKM_MTK_HSM_SHA256:
+ case SKS_CKM_MTK_HSM_SHA384:
+ case SKS_CKM_MTK_HSM_SHA512:
+ rv = mtk_SHA_step(mecha_type, session, in, out, function, step);
+ break;
+
+ default:
+ rv = SKS_BAD_PARAM;
+ break;
+ }
+
+ goto bail;
+ }
+
+bail:
+ switch (step) {
+ case SKS_FUNC_STEP_UPDATE:
+ if (rv != SKS_OK && rv != SKS_SHORT_BUFFER)
+ release_active_processing(session);
+ break;
+ default:
+ /* ONESHOT and FINAL terminates processing on success */
+ if (rv != SKS_SHORT_BUFFER)
+ release_active_processing(session);
+ break;
+ }
+
+ return rv;
+}
+
+
+/*
+ * entry_processing_init - Generic entry for initializing a processing
+ *
+ * @ctrl = [session-handle]
+ * @in = input data or none
+ * @out = output data or none
+ * @function - encrypt, decrypt, sign, verify, digest, ...
+ *
+ * The generic part come that all the commands uses the same
+ * input/output invocation parameters format (ctrl/in/out).
+ */
+uint32_t entry_processing_init(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attribute_head *proc_params = NULL;
+ uint32_t key_handle = 0;
+ struct sks_object *obj = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, tee_session);
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ obj = sks_handle2object(key_handle, session);
+ if (!obj)
+ return SKS_CKR_KEY_HANDLE_INVALID;
+
+ rv = set_processing_state(session, function, obj, NULL);
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
+ if (rv)
+ goto bail;
+
+ rv = check_mechanism_against_processing(session, proc_params->id,
+ function, SKS_FUNC_STEP_INIT);
+ if (rv)
+ goto bail;
+
+ rv = check_parent_attrs_against_processing(proc_params->id, function,
+ obj->attributes);
+ if (rv)
+ goto bail;
+
+ // rv = check_access_attrs_against_token(session, obj->attributes);
+ // if (rv)
+ // {
+ // IMSG("[%s][%d] rv %ld\n", __FUNCTION__, __LINE__, rv);
+ // goto bail;
+ // }
+
+ if (proc_params->id & SKS_CKM_MTK_HSM_EXT)
+ {
+ switch (proc_params->id)
+ {
+ case SKS_CKM_MTK_HSM_AES_ECB:
+ rv = mtk_AES_ECB_init(session, proc_params, obj);
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_CBC:
+ rv = mtk_AES_CBC_init(session, proc_params, obj);
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_CTR:
+ rv = mtk_AES_CTR_init(session, proc_params, obj);
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_GCM:
+ rv = mtk_AES_GCM_init(session, proc_params, obj);
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_CMAC:
+ rv = mtk_AES_CMAC_init(session, proc_params, obj);
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA256_HMAC:
+ case SKS_CKM_MTK_HSM_SHA384_HMAC:
+ rv = mtk_HMAC_init(session, proc_params, obj);
+ break;
+
+ case SKS_CKM_MTK_HSM_ECDSA:
+ rv = mtk_ECDSA_init(session, proc_params, obj);
+ break;
+
+ case SKS_CKM_MTK_HSM_ECDSA_SHA1:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA224:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA256:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA384:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA512:
+ rv = mtk_ECDSA_SHA_init(session, proc_params, obj);
+ break;
+
+ default:
+ rv = SKS_BAD_PARAM;
+ break;
+ }
+
+ if (rv == SKS_OK) {
+ session->processing->mecha_type = proc_params->id;
+ DMSG("SKSs%" PRIu32 ": init processing %s %s",
+ session_handle, sks2str_proc(proc_params->id),
+ sks2str_function(function));
+ } else {
+ EMSG(" entry_processing_init FAIL!! \n");
+ }
+
+ goto bail;
+ }
+
+ rv = SKS_CKR_MECHANISM_INVALID;
+ if (processing_is_tee_symm(proc_params->id)) {
+ rv = init_symm_operation(session, function, proc_params, obj);
+ }
+ if (processing_is_tee_asymm(proc_params->id)) {
+ rv = init_asymm_operation(session, function, proc_params, obj);
+ }
+ if (rv == SKS_OK) {
+ session->processing->mecha_type = proc_params->id;
+ IMSG("SKSs%" PRIu32 ": init processing %s %s",
+ session_handle, sks2str_proc(proc_params->id),
+ sks2str_function(function));
+ }
+
+bail:
+ if (rv && session)
+ release_active_processing(session);
+
+ TEE_Free(proc_params);
+
+ return rv;
+}
+
+/*
+ * entry_processing_step - Generic entry on active processing
+ *
+ * @ctrl = [session-handle]
+ * @in = input data or none
+ * @out = output data or none
+ * @function - encrypt, decrypt, sign, verify, digest, ...
+ * @step - update, oneshot, final
+ *
+ * The generic part come that all the commands uses the same
+ * input/output invocation parameters format (ctrl/in/out).
+ */
+uint32_t entry_processing_step(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ uint32_t mecha_type = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_active_session(&session, session_handle, tee_session,
+ function);
+ if (rv)
+ return rv;
+
+ // TODO: check user authen and object activation dates
+ rv = check_mechanism_against_processing(session, mecha_type,
+ function, step);
+ if (rv)
+ goto bail;
+
+
+ mecha_type = session->processing->mecha_type;
+ rv = check_mechanism_against_processing(session, mecha_type,
+ function, step);
+ if (rv)
+ goto bail;
+
+ if (mecha_type & SKS_CKM_MTK_HSM_EXT)
+ {
+ switch (mecha_type)
+ {
+ case SKS_CKM_MTK_HSM_AES_ECB:
+ rv = mtk_AES_ECB_step(session, in, out, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_CBC:
+ rv = mtk_AES_CBC_step(session, in, out, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_CTR:
+ rv = mtk_AES_CTR_step(session, in, out, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_GCM:
+ rv = mtk_AES_GCM_step(session, in, out, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_AES_CMAC:
+ rv = mtk_AES_CMAC_step(session, in, out, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA256_HMAC:
+ rv = mtk_SHA256_HMAC_step(session, in, out, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA384_HMAC:
+ rv = mtk_SHA384_HMAC_step(session, in, out, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_ECDSA:
+ rv = mtk_ECDSA_step(session, in, out, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_ECDSA_SHA1:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA224:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA256:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA384:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA512:
+ rv = mtk_ECDSA_SHA_step(session, in, out, function, step);
+ break;
+
+ default:
+ rv = SKS_BAD_PARAM;
+ break;
+ }
+
+ if (rv == SKS_OK) {
+ DMSG("SKSs%" PRIu32 ": init processing %s %s",
+ session_handle, sks2str_proc(mecha_type),
+ sks2str_function(function));
+ } else {
+ EMSG(" entry_processing_step FAIL!! \n");
+ }
+
+ goto bail;
+ }
+
+ rv = SKS_CKR_MECHANISM_INVALID;
+ if (processing_is_tee_symm(mecha_type)) {
+ rv = step_symm_operation(session, function, step, in, out);
+ }
+ if (processing_is_tee_asymm(mecha_type)) {
+ rv = step_asymm_operation(session, function, step, in, out);
+ }
+ if (rv == SKS_OK) {
+ session->processing->updated = true;
+ IMSG("SKSs%" PRIu32 ": processing %s %s",
+ session_handle, sks2str_proc(mecha_type),
+ sks2str_function(function));
+ }
+
+bail:
+ switch (step) {
+ case SKS_FUNC_STEP_UPDATE:
+ if (rv != SKS_OK && rv != SKS_SHORT_BUFFER)
+ release_active_processing(session);
+ break;
+ default:
+ /* ONESHOT and FINAL terminates processing on success */
+ if (rv != SKS_SHORT_BUFFER)
+ release_active_processing(session);
+ break;
+ }
+
+ return rv;
+}
+
+/*
+ * entry_verify_oneshot - Generic entry on active processing
+ *
+ * @ctrl = [session-handle]
+ * @in = input data or none
+ * @out = output data or none
+ * @function - encrypt, decrypt, sign, verify, digest, ...
+ * @step - update, oneshot, final
+ *
+ * The generic part come that all the commands uses the same
+ * input/output invocation parameters format (ctrl/in/out).
+ */
+uint32_t entry_verify_oneshot(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *in2,
+ enum processing_func function,
+ enum processing_step step)
+
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ uint32_t mecha_type = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ assert(function == SKS_FUNCTION_VERIFY);
+ if (!ctrl)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_active_session(&session, session_handle, tee_session,
+ function);
+ if (rv)
+ return rv;
+
+ // TODO: check user authen and object activation dates
+ rv = check_mechanism_against_processing(session, mecha_type,
+ function, step);
+ if (rv)
+ goto bail;
+
+
+ mecha_type = session->processing->mecha_type;
+ rv = check_mechanism_against_processing(session, mecha_type,
+ function, step);
+ if (rv)
+ goto bail;
+
+ if (mecha_type & SKS_CKM_MTK_HSM_EXT)
+ {
+ switch (mecha_type)
+ {
+ case SKS_CKM_MTK_HSM_AES_CMAC:
+ rv = mtk_AES_CMAC_step(session, in, in2, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA256_HMAC:
+ rv = mtk_SHA256_HMAC_step(session, in, in2, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA384_HMAC:
+ rv = mtk_SHA384_HMAC_step(session, in, in2, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_ECDSA:
+ rv = mtk_ECDSA_step(session, in, in2, function, step);
+ break;
+
+ case SKS_CKM_MTK_HSM_ECDSA_SHA1:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA224:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA256:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA384:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA512:
+ rv = mtk_ECDSA_SHA_step(session, in, in2, function, step);
+ break;
+
+ default:
+ rv = SKS_BAD_PARAM;
+ break;
+ }
+
+ goto bail;
+ }
+
+ rv = SKS_CKR_MECHANISM_INVALID;
+ if (processing_is_tee_symm(mecha_type)) {
+ rv = step_symm_operation(session, function, step, in, in2);
+ }
+ if (processing_is_tee_asymm(mecha_type)) {
+ rv = step_asymm_operation(session, function, step, in, in2);
+ }
+
+ IMSG("SKSs%" PRIu32 ": verify %s %s: %s", session_handle,
+ sks2str_proc(mecha_type), sks2str_function(function),
+ sks2str_rc(rv));
+
+bail:
+ if (rv != SKS_SHORT_BUFFER)
+ release_active_processing(session);
+
+ return rv;
+}
+
+uint32_t entry_derive_key(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attribute_head *proc_params = NULL;
+ uint32_t parent_handle = 0;
+ struct sks_object *parent_obj;
+ struct sks_attrs_head *head = NULL;
+ struct sks_object_head *template = NULL;
+ size_t template_size = 0;
+ uint32_t out_handle = 0;
+ uint32_t __maybe_unused mecha_id = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < sizeof(uint32_t)) {
+ out->memref.size = sizeof(uint32_t);
+ return SKS_SHORT_BUFFER;
+ }
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, tee_session);
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ parent_obj = sks_handle2object(parent_handle, session);
+ if (!parent_obj) {
+ rv = SKS_CKR_KEY_HANDLE_INVALID;
+ goto bail;
+ }
+
+ rv = set_processing_state(session, SKS_FUNCTION_DERIVE,
+ parent_obj, NULL);
+ if (rv)
+ goto bail;
+
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ goto bail;
+
+ template_size = sizeof(*template) + template->attrs_size;
+
+ rv = check_mechanism_against_processing(session, proc_params->id,
+ SKS_FUNCTION_DERIVE,
+ SKS_FUNC_STEP_INIT);
+ if (rv)
+ goto bail;
+
+ rv = create_attributes_from_template(&head, template, template_size,
+ proc_params->id, parent_obj->attributes,
+ SKS_FUNCTION_DERIVE);
+ if (rv)
+ goto bail;
+
+ TEE_Free(template);
+ template = NULL;
+
+ rv = check_created_attrs(head, NULL);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_processing(proc_params->id, head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_token(session, head);
+ if (rv)
+ goto bail;
+
+ // TODO: check_created_against_parent(session, parent, child);
+ // This can handle DERVIE_TEMPLATE attributes from the parent key.
+
+ rv = SKS_CKR_MECHANISM_INVALID;
+ if (processing_is_tee_symm(proc_params->id)) {
+ rv = init_symm_operation(session, SKS_FUNCTION_DERIVE,
+ proc_params, parent_obj);
+ if (rv)
+ goto bail;
+
+ rv = do_symm_derivation(session, proc_params,
+ parent_obj, &head);
+ }
+ if (processing_is_tee_asymm(proc_params->id)) {
+ rv = init_asymm_operation(session, SKS_FUNCTION_DERIVE,
+ proc_params, parent_obj);
+ if (rv)
+ goto bail;
+
+ rv = do_asymm_derivation(session, proc_params, &head);
+ }
+ if (rv)
+ goto bail;
+
+#if 0
+ /* Exaustive list */
+ switch (proc_params->id) {
+ case SKS_CKM_ECDH1_DERIVE: <--------------------------- TODO
+ //case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ case SKS_CKM_DH_PKCS_DERIVE: <--------------------------- TODO
+ case SKS_CKM_X9_42_DH_DERIVE:
+ case SKS_CKM_X9_42_DH_HYBRID_DERIVE:
+ case SKS_CKM_X9_42_MQV_DERIVE:
+ case SKS_CKM_AES_GMAC
+ case SKS_CKM_AES_ECB_ENCRYPT_DATA <------------------- TODO
+ case SKS_CKM_AES_CBC_ENCRYPT_DATA <------------------- TODO
+ case SKS_CKM_SHA1_KEY_DERIVATION
+ case SKS_CKM_SHA224_KEY_DERIVATION
+ case SKS_CKM_SHA256_KEY_DERIVATION
+ case SKS_CKM_SHA384_KEY_DERIVATION
+ case SKS_CKM_SHA512_KEY_DERIVATION
+ case SKS_CKM_SHA512_224_KEY_DERIVATION
+ case SKS_CKM_SHA512_256_KEY_DERIVATION
+ case SKS_CKM_SHA512_T_KEY_DERIVATION
+ // Exhaustive list is made of Camelia, Aria, Seed, KIP, GOSTR3410,
+ // DES, 3DES, SSL3, TLS12, TLS-KDF, WTLS and concatenate mechanisms.
+ case SKS_CKM_ECMQV_DERIVE:
+ }
+#endif
+
+ mecha_id = proc_params->id;
+ TEE_Free(proc_params);
+ proc_params = NULL;
+
+ /*
+ * Object is ready, register it and return a handle.
+ */
+ rv = create_object(session, head, &out_handle);
+ if (rv)
+ goto bail;
+
+ /*
+ * Now out_handle (through the related struct sks_object instance)
+ * owns the serialized buffer that holds the object attributes.
+ * We reset attrs->buffer to NULL as serializer object is no more
+ * the attributes buffer owner.
+ */
+ head = NULL;
+
+ TEE_MemMove(out->memref.buffer, &out_handle, sizeof(uint32_t));
+ out->memref.size = sizeof(uint32_t);
+
+ IMSG("SKSs%" PRIu32 ": derive key Ox%" PRIx32 ", %s",
+ session_handle, out_handle, sks2str_proc(mecha_id));
+
+bail:
+ release_active_processing(session);
+ TEE_Free(proc_params);
+ TEE_Free(template);
+ TEE_Free(head);
+
+ return rv;
+}
+
+
+uint32_t entry_generate_random(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = SKS_OK;
+
+
+ if (!ctrl || !out)
+ return SKS_BAD_PARAM;
+
+ rv = mtk_generate_random(out);
+
+ return rv;
+}
+
+static uint32_t import_hsm_symmetric_key(struct sks_attrs_head **head, uint8_t *keyblob, int *blobsize)
+{
+ uint32_t rv = 0;
+ int keyid = 0;
+ uint8_t *pkeybuffer = NULL;
+ int value_size = 0;
+ // int size = 0;
+
+ if (!*head || !keyblob)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+
+ rv = get_attribute_ptr(*head, SKS_CKA_VALUE, &pkeybuffer, &value_size);
+ if (rv) {
+ EMSG("[%s][%d] rv : %d\n", __FUNCTION__, __LINE__, rv);
+ return SKS_CKR_GENERAL_ERROR;
+ }
+
+ rv = mtk_import_key(pkeybuffer, value_size, &keyid, keyblob, blobsize, KEY_ALGO_ID_AES);
+ if (rv)
+ return SKS_CKR_GENERAL_ERROR;
+
+ IMSG("[%s][%d] keyid : 0x%x\n", __FUNCTION__, __LINE__, keyid);
+
+ rv = add_attribute(head, SKS_CKA_HSM_KEY_ID, &keyid, sizeof(keyid));
+ if (rv)
+ return SKS_CKR_GENERAL_ERROR;
+
+ rv = add_attribute(head, SKS_CKA_HSM_KEY_LEN, &value_size, sizeof(value_size));
+ if (rv )
+ return SKS_CKR_GENERAL_ERROR;
+
+
+ return rv;
+}
+
+
+uint32_t entry_import_key(uintptr_t tee_session,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attrs_head *head = NULL;
+ struct sks_object_head *template = NULL;
+ size_t template_size = 0;
+ uint32_t obj_handle = 0;
+ uint32_t key_type;
+ uint8_t *blobbuf = NULL;
+ uint32_t blobbufsize = 0;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ /*
+ * Collect the arguments of the request
+ */
+
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, tee_session);
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ goto bail;
+
+ template_size = sizeof(*template) + template->attrs_size;
+
+ /*
+ * Prepare a clean initial state for the requested object attributes.
+ * Free temporary template once done.
+ */
+ rv = create_attributes_from_template(&head, template, template_size,
+ SKS_UNDEFINED_ID, NULL,
+ SKS_FUNCTION_IMPORT);
+ TEE_Free(template);
+ template = NULL;
+ if (rv)
+ goto bail;
+
+ /*
+ * Check target object attributes match target processing
+ * Check target object attributes match token state
+ */
+ rv = check_created_attrs_against_processing(SKS_PROCESSING_IMPORT,
+ head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_token(session, head);
+ if (rv)
+ goto bail;
+
+
+ blobbuf = out->memref.buffer;
+ blobbufsize = out->memref.size;
+ key_type = get_type(head);
+ switch (key_type)
+ {
+ case SKS_CKK_AES:
+ case SKS_CKK_GENERIC_SECRET:
+ case SKS_CKK_SHA_1_HMAC:
+ case SKS_CKK_SHA224_HMAC:
+ case SKS_CKK_SHA256_HMAC:
+ case SKS_CKK_SHA384_HMAC:
+ case SKS_CKK_SHA512_HMAC:
+ rv = import_hsm_symmetric_key(&head, blobbuf, &blobbufsize);
+ break;
+ default:
+ EMSG("[%s][%d] unknown keytype : %d\n", __FUNCTION__, __LINE__, key_type);
+ rv = SKS_CKR_KEY_TYPE_INCONSISTENT;
+ break;
+ }
+
+ if (rv)
+ goto bail;
+ /*
+ * At this stage the object is almost created: all its attributes are
+ * referenced in @head, including the key value and are assume
+ * reliable. Now need to register it and get a handle for it.
+ */
+ rv = create_object(session, head, &obj_handle);
+ if (rv)
+ goto bail;
+
+ /*
+ * Now obj_handle (through the related struct sks_object instance)
+ * owns the serialised buffer that holds the object attributes.
+ * We reset attrs->buffer to NULL as serializer object is no more
+ * the attributes buffer owner.
+ */
+ head = NULL;
+
+ out->memref.size = blobbufsize;
+
+ IMSG("SKSs%" PRIu32 ": import object 0x%" PRIx32,
+ session_handle, obj_handle);
+bail:
+ TEE_Free(template);
+ TEE_Free(head);
+
+
+ return rv;
+}
+
+uint32_t entry_import_key_pair(uintptr_t teesess,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attribute_head *proc_params = NULL;
+ struct sks_attrs_head *pub_head = NULL;
+ struct sks_attrs_head *priv_head = NULL;
+ struct sks_object_head *template = NULL;
+ size_t template_size = 0;
+ uint32_t pubkey_handle = 0;
+ uint32_t privkey_handle = 0;
+ uint32_t *hdl_ptr = NULL;
+ uint32_t blobbuflength;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+ if (!ctrl || in || !out)
+ return SKS_BAD_PARAM;
+
+ if (out->memref.size < MAX_BLOB_SIZE)
+ return SKS_SHORT_BUFFER;
+
+ blobbuflength = out->memref.size;
+
+ // FIXME: cleaner way to test alignment of out buffer
+ if ((uintptr_t)out->memref.buffer & 0x3UL)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, teesess);
+ if (rv)
+ return rv;
+
+ /* Get mechanism parameters */
+ rv = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
+ if (rv)
+ goto bail;
+
+ switch (proc_params->id) {
+ case SKS_CKM_MTK_HSM_EC_KEY_PAIR_IMPORT:
+ break;
+ default:
+ rv = SKS_CKR_MECHANISM_INVALID;
+ goto bail;
+ }
+
+ /* Get and check public key attributes */
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ goto bail;
+
+ template_size = sizeof(*template) + template->attrs_size;
+ rv = create_attributes_from_template(&pub_head, template, template_size,
+ proc_params->id, NULL,
+ SKS_FUNCTION_GENERATE_PAIR);
+ if (rv)
+ goto bail;
+
+ TEE_Free(template);
+ template = NULL;
+
+ rv = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rv)
+ goto bail;
+
+ template_size = sizeof(*template) + template->attrs_size;
+ rv = create_attributes_from_template(&priv_head, template, template_size,
+ proc_params->id, NULL,
+ SKS_FUNCTION_GENERATE_PAIR);
+ if (rv)
+ goto bail;
+
+ TEE_Free(template);
+ template = NULL;
+
+ /* Generate CKA_ID for keys if not specified by the templates */
+ rv = add_missing_attribute_id(&pub_head, &priv_head);
+ if (rv)
+ goto bail;
+
+ /* Check created object against processing and token state */
+ rv = check_created_attrs(pub_head, priv_head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_processing(proc_params->id, pub_head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_processing(proc_params->id, priv_head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_token(session, pub_head);
+ if (rv)
+ goto bail;
+
+ rv = check_created_attrs_against_token(session, priv_head);
+ if (rv)
+ goto bail;
+
+ rv = import_hsm_ecc_keypair(&pub_head, &priv_head, out->memref.buffer, &blobbuflength);
+ if (rv)
+ goto bail;
+
+ TEE_Free(proc_params);
+ proc_params = NULL;
+
+ /*
+ * Object is ready, register it and return a handle.
+ */
+ rv = create_object(session, pub_head, &pubkey_handle);
+ if (rv)
+ goto bail;
+
+ rv = create_object(session, priv_head, &privkey_handle);
+ if (rv)
+ goto bail;
+
+ /*
+ * Now obj_handle (through the related struct sks_object instance)
+ * owns the serialized buffer that holds the object attributes.
+ * We reset attrs->buffer to NULL as serializer object is no more
+ * the attributes buffer owner.
+ */
+ pub_head = NULL;
+ priv_head = NULL;
+
+ out->memref.size = blobbuflength;
+
+ IMSG("SKSs%" PRIu32 ": create key pair 0x%" PRIx32 "/0x%" PRIx32,
+ session_handle, privkey_handle, pubkey_handle);
+
+bail:
+ TEE_Free(proc_params);
+ TEE_Free(template);
+ TEE_Free(pub_head);
+ TEE_Free(priv_head);
+
+ return rv;
+}
+
+
+uint32_t entry_export_key_pair(uintptr_t teesess,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ uint32_t mecha_type = 0;
+
+ uint8_t *keyblob;
+ uint32_t keybloblength;
+ uint8_t *pubkey;
+ uint32_t pubkeylength;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || !in || !out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ rv = get_ready_session(&session, session_handle, teesess);
+ if (rv)
+ goto bail;
+
+ keyblob = (uint8_t *)in->memref.buffer;
+ keybloblength = in->memref.size;
+ pubkey = (uint8_t *)out->memref.buffer;
+ pubkeylength = out->memref.size;
+
+ rv = mtk_export_key(keyblob, keybloblength, pubkey, &pubkeylength);
+ if (rv)
+ goto bail;
+
+ out->memref.size = pubkeylength;
+bail:
+
+ return rv;
+}
+
+
+uint32_t entry_utils(uintptr_t teesess,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out)
+{
+ uint32_t rv = 0;
+ struct serialargs ctrlargs;
+ uint32_t session_handle = 0;
+ struct pkcs11_session *session = NULL;
+ struct sks_attribute_head *proc_params = NULL;
+ struct sks_object *obj = NULL;
+
+ TEE_MemFill(&ctrlargs, 0, sizeof(ctrlargs));
+
+ if (!ctrl || in || out)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rv = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = get_ready_session(&session, session_handle, teesess);
+ if (rv)
+ return rv;
+
+ rv = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
+ if (rv)
+ goto bail;
+
+ if (proc_params->id & SKS_CKM_MTK_HSM_EXT)
+ {
+ switch (proc_params->id)
+ {
+ case SKS_CKM_MTK_HSM_DUMP_LOG:
+ rv = mtk_dump_hsm_log();
+ break;
+
+ default:
+ rv = SKS_BAD_PARAM;
+ break;
+ }
+
+ if (rv == SKS_OK) {
+ DMSG("SKSs%" PRIu32 ": init processing %s %s",
+ session_handle, sks2str_proc(proc_params->id),
+ sks2str_function(function));
+ } else {
+ EMSG(" entry_utils FAIL!! \n");
+ }
+
+ goto bail;
+ }
+
+
+bail:
+ if (rv && session)
+ release_active_processing(session);
+
+ TEE_Free(proc_params);
+
+ return rv;
+}
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing.h
new file mode 100644
index 0000000..dc7525f
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing.h
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#ifndef __SKS_PROCESSING_H__
+#define __SKS_PROCESSING_H__
+
+#include <tee_internal_api.h>
+#include <pkcs11_attributes.h>
+
+struct pkcs11_session;
+struct sks_object;
+struct active_processing;
+
+/*
+ * Entry points from SKS TA invocation commands
+ */
+
+uint32_t entry_import_object(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_generate_secret(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_generate_key_pair(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_digesting_init(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function);
+uint32_t entry_digesting_step(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step);
+
+uint32_t entry_processing_init(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function);
+
+uint32_t entry_processing_step(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step);
+
+/* verify_oneshot is specific since it get 2 input data buffers */
+uint32_t entry_verify_oneshot(uintptr_t tee_session, TEE_Param *ctrl,
+ TEE_Param *in1, TEE_Param *in2,
+ enum processing_func function,
+ enum processing_step step);
+
+uint32_t entry_derive_key(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_generate_random(uintptr_t teesess, TEE_Param *ctrl,
+ TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_import_key(uintptr_t tee_session,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_import_key_pair(uintptr_t tee_session,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_export_key_pair(uintptr_t teesess,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out);
+
+uint32_t entry_utils(uintptr_t teesess,
+ TEE_Param *ctrl, TEE_Param *in, TEE_Param *out);
+
+/*
+ * Util
+ */
+size_t get_object_key_bit_size(struct sks_object *obj);
+
+void release_active_processing(struct pkcs11_session *session);
+
+uint32_t alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
+ uint32_t attribute,
+ void **data, size_t *size);
+
+uint32_t tee2sks_add_attribute(struct sks_attrs_head **head, uint32_t sks_id,
+ TEE_ObjectHandle tee_obj, uint32_t tee_id);
+
+/*
+ * Symmetric crypto algorithm specific functions
+ */
+bool processing_is_tee_symm(uint32_t proc_id);
+
+uint32_t init_symm_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+
+uint32_t step_symm_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ enum processing_step step,
+ TEE_Param *io1, TEE_Param *io2);
+
+void tee_release_ctr_operation(struct active_processing *processing);
+uint32_t tee_init_ctr_operation(struct active_processing *processing,
+ void *proc_params, size_t params_size);
+
+uint32_t tee_ae_decrypt_update(struct active_processing *processing,
+ void *in, size_t in_size);
+
+uint32_t tee_ae_decrypt_final(struct active_processing *processing,
+ void *out, uint32_t *out_size);
+
+uint32_t tee_ae_encrypt_final(struct active_processing *processing,
+ void *out, uint32_t *out_size);
+
+void tee_release_ccm_operation(struct active_processing *processing);
+uint32_t tee_init_ccm_operation(struct active_processing *processing,
+ void *proc_params, size_t params_size);
+
+void tee_release_gcm_operation(struct active_processing *processing);
+uint32_t tee_init_gcm_operation(struct active_processing *processing,
+ void *proc_params, size_t params_size);
+
+/* Asymmetric key operations util */
+bool processing_is_tee_asymm(uint32_t proc_id);
+
+uint32_t init_asymm_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj);
+
+uint32_t do_symm_derivation(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *parent_key,
+ struct sks_attrs_head **head);
+
+uint32_t step_asymm_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ enum processing_step step,
+ TEE_Param *io1, TEE_Param *io2);
+
+uint32_t do_asymm_derivation(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_attrs_head **head);
+
+
+/*
+ * Elliptic curve crypto algorithm specific functions
+ */
+uint32_t load_tee_ec_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count,
+ struct sks_object *obj);
+
+size_t ec_params2tee_keysize(void *attr, size_t size);
+
+uint32_t ec_params2tee_curve(void *attr, size_t size);
+
+uint32_t sks2tee_algo_ecdh(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj);
+
+uint32_t sks2tee_ecdh_param_pub(struct sks_attribute_head *proc_params,
+ void **pub_data, size_t *pub_size);
+
+uint32_t sks2tee_algo_ecdsa(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj);
+
+uint32_t generate_ec_keys(struct sks_attribute_head *proc_params,
+ struct sks_attrs_head **pub_head,
+ struct sks_attrs_head **priv_head);
+
+uint32_t generate_hsm_ec_keys(struct sks_attribute_head *proc_params,
+ struct sks_attrs_head **pub_head,
+ struct sks_attrs_head **priv_head);
+
+uint32_t import_hsm_ecc_keypair(
+ struct sks_attrs_head **pub,
+ struct sks_attrs_head **priv,
+ uint8_t *keyblob,
+ int *blobsize);
+/*
+ * RSA crypto algorithm specific functions
+ */
+uint32_t load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count,
+ struct sks_object *obj);
+
+uint32_t sks2tee_proc_params_rsa_pss(struct active_processing *processing,
+ struct sks_attribute_head *proc_params);
+
+void tee_release_rsa_pss_operation(struct active_processing *processing);
+
+uint32_t sks2tee_algo_rsa_pss(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params);
+
+uint32_t sks2tee_algo_rsa_oaep(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params);
+
+uint32_t tee_init_rsa_aes_key_wrap_operation(struct active_processing *proc,
+ void *proc_params,
+ size_t params_size);
+
+uint32_t generate_rsa_keys(struct sks_attribute_head *proc_params,
+ struct sks_attrs_head **pub_head,
+ struct sks_attrs_head **priv_head);
+
+#endif /*__SKS_PROCESSING_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_aes.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_aes.c
new file mode 100644
index 0000000..abade0a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_aes.c
@@ -0,0 +1,659 @@
+/*
+ * Copyright (c) 2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <compiler.h>
+#include <util.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include "pkcs11_token.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+uint32_t tee_init_ctr_operation(struct active_processing *processing,
+ void *proc_params, size_t params_size)
+{
+ struct serialargs args;
+ uint32_t rv = 0;
+ /* CTR parameters */
+ uint32_t incr_counter = 0;
+ void *counter_bits = NULL;
+
+ TEE_MemFill(&args, 0, sizeof(args));
+
+ if (!proc_params)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&args, proc_params, params_size);
+
+ rv = serialargs_get(&args, &incr_counter, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get_ptr(&args, &counter_bits, 16);
+ if (rv)
+ goto bail;
+
+ if (incr_counter != 1) {
+ DMSG("Supports only 1 bit increment counter: %d",
+ incr_counter);
+ rv = SKS_CKR_MECHANISM_PARAM_INVALID;
+ goto bail;
+ }
+
+ TEE_CipherInit(processing->tee_op_handle, counter_bits, 16);
+
+ rv = SKS_OK;
+
+bail:
+ return rv;
+}
+
+void tee_release_ctr_operation(struct active_processing *processing __unused)
+{
+}
+
+/*
+ * Authenticated ciphering: (CCM / GCM)
+ *
+ * As per PKCS#11, CCM/GCM decrypt shall not revealed the data until the
+ * decryption is completed and the mac verified. The SKS TA must retain the
+ * ciphered data until the CCM finalization. To do so, arrays of decrypted
+ * data are allocated during AE update processing and copied into client
+ * buffer at AE finalization.
+ *
+ * As per PKCS#11, CCM/GCM decrypt expect the tag/mac data to be provided
+ * inside the input data for DecryptUpdate() and friends. But the DecryptFinal
+ * API does not provide input data reference hence we do not know which is the
+ * last call to DecryptUpdate() where last bytes are not ciphered data but the
+ * requested tag/mac byte. To handle this, the TA saves the last input data
+ * bytes (length is defined by the tag byte size) in the AE context and
+ * waits the DecryptFinal() to either treat these as data bytes or tag/mac
+ * bytes. Refer to pending_tag and pending_size in struct ae_aes_context.
+ */
+
+/*
+ * @size - byte size of the allocated buffer
+ * @data - pointer to allocated data
+ */
+struct out_data_ref {
+ size_t size;
+ void *data;
+};
+
+/*
+ * @tag_byte_len - tag size in byte
+ * @pending_tag - Input data that could be the appended tag
+ * @pending_size - Size of pending input data that could be the tag
+ * @out_data - Pointer to an array of output data references.
+ * @out_count - Number of buffer references in out_data
+ */
+struct ae_aes_context {
+ size_t tag_byte_len;
+ char *pending_tag;
+ size_t pending_size;
+ struct out_data_ref *out_data;
+ size_t out_count;
+};
+
+static void release_ae_aes_context(struct ae_aes_context *ctx)
+{
+ size_t n = 0;
+
+ for (n = 0; n < ctx->out_count; n++) {
+ TEE_Free(ctx->out_data[n].data);
+ }
+
+ TEE_Free(ctx->out_data);
+ ctx->out_data = NULL;
+ ctx->out_count = 0;
+
+ TEE_Free(ctx->pending_tag);
+ ctx->pending_tag = NULL;
+}
+
+uint32_t tee_ae_decrypt_update(struct active_processing *processing,
+ void *in, size_t in_size)
+{
+ struct ae_aes_context *ctx = processing->extra_ctx;
+ size_t data_len = 0;
+ uint32_t size = 0;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ uint32_t rv = 0;
+ char *ct = NULL;
+ uint32_t ct_size = 0;
+ void *ptr = NULL;
+
+ if (!in_size)
+ return SKS_OK;
+
+ if (!in)
+ return SKS_BAD_PARAM;
+
+ /*
+ * Save the last input bytes in case they are the tag
+ * bytes and not ciphered data bytes to be decrypted.
+ */
+
+ if (ctx->pending_size + in_size <= ctx->tag_byte_len) {
+ /*
+ * Data bytes are all potential tag bytes.
+ * We only need to update the pending_tag buffer,
+ * and cannot treat any byte as data byte.
+ */
+ TEE_MemMove(ctx->pending_tag + ctx->pending_size, in, in_size);
+
+ ctx->pending_size += in_size;
+
+ return SKS_OK;
+ }
+
+ /* Size of data that are not potential tag in pending and input data */
+ data_len = in_size + ctx->pending_size - ctx->tag_byte_len;
+
+ if (ctx->pending_size &&
+ (ctx->pending_size + in_size) >= ctx->tag_byte_len) {
+ /* Process pending tag bytes that are effective data byte */
+ uint32_t len = MIN(data_len, ctx->pending_size);
+
+ res = TEE_AEUpdate(processing->tee_op_handle,
+ ctx->pending_tag, len, NULL, &ct_size);
+
+ // TODO: explain this
+ if (res != TEE_ERROR_SHORT_BUFFER &&
+ (res != TEE_SUCCESS || ct_size)) {
+ rv = SKS_ERROR;
+ goto bail;
+ }
+
+ /*
+ * If output data to store (not revealed yet), redo with
+ * an allocated temporary reference.
+ */
+ if (ct_size) {
+ ct = TEE_Malloc(ct_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!ct) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ res = TEE_AEUpdate(processing->tee_op_handle,
+ ctx->pending_tag, len, ct, &ct_size);
+ if (res) {
+ rv = tee2sks_error(res);
+ goto bail;
+ }
+
+ /* Finally, no out data? Release temp buffer. */
+ if (!ct_size) {
+ TEE_Free(ct);
+ ct = NULL;
+ DMSG_RAW("\nWe expected some data!\n\n");
+ }
+ }
+
+ /* Save potential tag bytes for later */
+ TEE_MemMove(ctx->pending_tag, ctx->pending_tag + len,
+ ctx->pending_size - len);
+
+ ctx->pending_size -= len;
+ data_len -= len;
+ }
+
+ if (data_len) {
+ /* Process input data that are not potential tag bytes */
+ size = 0;
+ res = TEE_AEUpdate(processing->tee_op_handle,
+ in, data_len, NULL, &size);
+
+ if (res != TEE_ERROR_SHORT_BUFFER &&
+ (res != TEE_SUCCESS || size)) {
+ rv = SKS_ERROR;
+ goto bail;
+ }
+
+ if (size) {
+ ptr = TEE_Realloc(ct, ct_size + size);
+ if (!ptr) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+ ct = ptr;
+
+ res = TEE_AEUpdate(processing->tee_op_handle,
+ in, data_len, ct + ct_size, &size);
+ if (res) {
+ rv = tee2sks_error(res);
+ goto bail;
+ }
+
+ ct_size += size;
+ }
+ }
+
+ /* Update pending tag in context if any */
+ data_len = in_size - data_len;
+ if (data_len > (ctx->tag_byte_len - ctx->pending_size)) {
+ /* This could be asserted */
+ rv = SKS_ERROR;
+ goto bail;
+ }
+
+ if (data_len) {
+ TEE_MemMove(ctx->pending_tag + ctx->pending_size,
+ (char *)in + in_size - data_len, data_len);
+
+ ctx->pending_size += data_len;
+ }
+
+ /* Save output data reference in the context */
+ if (ct_size) {
+ ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) *
+ sizeof(struct out_data_ref));
+ if (!ptr) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+ ctx->out_data = ptr;
+ ctx->out_data[ctx->out_count].size = ct_size;
+ ctx->out_data[ctx->out_count].data = ct;
+ ctx->out_count++;
+ }
+
+ rv = SKS_OK;
+
+bail:
+ if (rv) {
+ TEE_Free(ct);
+ }
+
+ return rv;
+}
+
+static uint32_t reveale_ae_data(struct ae_aes_context *ctx,
+ void *out, uint32_t *out_size)
+{
+ size_t n = 0;
+ uint32_t req_size = 0;
+ char *out_ptr = out;
+
+ for (req_size = 0, n = 0; n < ctx->out_count; n++)
+ req_size += ctx->out_data[n].size;
+
+ if (*out_size < req_size) {
+ *out_size = req_size;
+ return SKS_SHORT_BUFFER;
+ }
+
+ if (!out_ptr)
+ return SKS_BAD_PARAM;
+
+ for (n = 0; n < ctx->out_count; n++) {
+ TEE_MemMove(out_ptr,
+ ctx->out_data[n].data, ctx->out_data[n].size);
+
+ TEE_Free(ctx->out_data[n].data);
+ out_ptr += ctx->out_data[n].size;
+ }
+
+ TEE_Free(ctx->out_data);
+ ctx->out_data = NULL;
+ ctx->out_count = 0;
+
+ *out_size = req_size;
+
+ return SKS_OK;
+}
+
+uint32_t tee_ae_decrypt_final(struct active_processing *processing,
+ void *out, uint32_t *out_size)
+{
+ struct ae_aes_context *ctx = processing->extra_ctx;
+ uint32_t rv = 0;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ uint32_t data_size = 0;
+ void *data_ptr = NULL;
+
+ if (!out_size) {
+ DMSG("Expect at least a buffer for the output data");
+ return SKS_BAD_PARAM;
+ }
+
+ /* Final is already completed, only need to output the data */
+ if (!ctx->pending_tag)
+ return reveale_ae_data(ctx, out, out_size);
+
+ if (ctx->pending_size != ctx->tag_byte_len) {
+ DMSG("Not enough samples: %zu/%zu",
+ ctx->pending_size, ctx->tag_byte_len);
+ return SKS_FAILED; // FIXME: CKR_ENCRYPTED_DATA_LEN_RANGE
+ }
+
+ data_size = 0;
+ res = TEE_AEDecryptFinal(processing->tee_op_handle,
+ NULL, 0, NULL, &data_size,
+ ctx->pending_tag, ctx->tag_byte_len);
+
+ if (res == TEE_ERROR_SHORT_BUFFER) {
+ data_ptr = TEE_Malloc(data_size,
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!data_ptr) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ res = TEE_AEDecryptFinal(processing->tee_op_handle,
+ NULL, 0, data_ptr, &data_size,
+ ctx->pending_tag, ctx->tag_byte_len);
+
+ if (!data_size) {
+ TEE_Free(data_ptr);
+ data_ptr = NULL;
+ DMSG_RAW("\nIs this expected from the Core API?\n\n");
+ }
+ }
+
+ /* AE decryption is completed */
+ TEE_Free(ctx->pending_tag);
+ ctx->pending_tag = NULL;
+
+ rv = tee2sks_error(res);
+ if (rv)
+ goto bail;
+
+ if (data_ptr) {
+ void *tmp_ptr = NULL;
+
+ tmp_ptr = TEE_Realloc(ctx->out_data,
+ (ctx->out_count + 1) *
+ sizeof(struct out_data_ref));
+ if (!tmp_ptr) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+ ctx->out_data = tmp_ptr;
+ ctx->out_data[ctx->out_count].size = data_size;
+ ctx->out_data[ctx->out_count].data = data_ptr;
+ ctx->out_count++;
+
+ data_ptr = NULL;
+ }
+
+ rv = reveale_ae_data(ctx, out, out_size);
+
+bail:
+ TEE_Free(data_ptr);
+
+ return rv;
+}
+
+uint32_t tee_ae_encrypt_final(struct active_processing *processing,
+ void *out, uint32_t *out_size)
+{
+ struct ae_aes_context *ctx = processing->extra_ctx;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ uint8_t *tag = NULL;
+ uint32_t tag_len = 0;
+ uint32_t size = 0;
+
+ if (!out || !out_size)
+ return SKS_BAD_PARAM;
+
+ /* Check the required sizes (warning: 2 output len: data + tag) */
+ res = TEE_AEEncryptFinal(processing->tee_op_handle,
+ NULL, 0, NULL, &size,
+ &tag, &tag_len);
+
+ if (tag_len != ctx->tag_byte_len ||
+ (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)) {
+ EMSG("Unexpected tag length %u/%zu or rc 0x%" PRIx32,
+ tag_len, ctx->tag_byte_len, res);
+ return SKS_ERROR;
+ }
+
+ if (*out_size < size + tag_len) {
+ *out_size = size + tag_len;
+ return SKS_SHORT_BUFFER;
+ }
+
+ /* Process data and tag input the client output buffer */
+ tag = (uint8_t *)out + size;
+
+ res = TEE_AEEncryptFinal(processing->tee_op_handle,
+ NULL, 0, out, &size, tag, &tag_len);
+
+ if (tag_len != ctx->tag_byte_len) {
+ EMSG("Unexpected tag length");
+ return SKS_ERROR;
+ }
+
+ if (!res)
+ *out_size = size + tag_len;
+
+ return tee2sks_error(res);
+}
+
+uint32_t tee_init_ccm_operation(struct active_processing *processing,
+ void *proc_params, size_t params_size)
+{
+ uint32_t rv = 0;
+ struct ae_aes_context *params = NULL;
+ struct serialargs args;
+ /* CCM parameters */
+ uint32_t data_len = 0;
+ uint32_t nonce_len = 0;
+ void *nonce = NULL;
+ uint32_t aad_len = 0;
+ void *aad = NULL;
+ uint32_t mac_len = 0;
+
+ TEE_MemFill(&args, 0, sizeof(args));
+
+ if (!proc_params)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&args, proc_params, params_size);
+
+ rv = serialargs_get(&args, &data_len, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get(&args, &nonce_len, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ // TODO: no need to copy nonce into secure world
+ rv = serialargs_alloc_and_get(&args, &nonce, nonce_len);
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get(&args, &aad_len, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ // TODO: no need to copy aad into secure world
+ rv = serialargs_alloc_and_get(&args, &aad, aad_len);
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get(&args, &mac_len, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ /* As per pkcs#11 mechanism specification */
+ if (data_len > 28 ||
+ !nonce_len || nonce_len > 15 ||
+ aad_len > 256 ||
+ mac_len < 4 || mac_len > 16 || mac_len & 1) {
+ DMSG("Invalid parameters: data_len %" PRIu32
+ ", nonce_len %" PRIu32 ", aad_len %" PRIu32
+ ", mac_len %" PRIu32, data_len, nonce_len,
+ aad_len, mac_len);
+ rv = SKS_CKR_MECHANISM_PARAM_INVALID;
+ goto bail;
+ }
+
+ params = TEE_Malloc(sizeof(struct ae_aes_context),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!params) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ params->tag_byte_len = mac_len;
+ params->out_count = 0;
+ params->pending_size = 0;
+ params->out_data = TEE_Malloc(sizeof(struct out_data_ref),
+ TEE_MALLOC_FILL_ZERO);
+ params->pending_tag = TEE_Malloc(mac_len,
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!params->out_data || !params->pending_tag) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ TEE_AEInit(processing->tee_op_handle, nonce, nonce_len, mac_len * 8,
+ aad_len, data_len);
+ if (aad_len)
+ TEE_AEUpdateAAD(processing->tee_op_handle, aad, aad_len);
+
+ /* Session processing owns the active processing params */
+ assert(!processing->extra_ctx);
+ processing->extra_ctx = params;
+
+ rv = SKS_OK;
+
+bail:
+ TEE_Free(nonce);
+ TEE_Free(aad);
+ if (rv && params) {
+ TEE_Free(params->out_data);
+ TEE_Free(params->pending_tag);
+ TEE_Free(params);
+ }
+ return rv;
+}
+
+void tee_release_ccm_operation(struct active_processing *processing)
+{
+ struct ae_aes_context *ctx = processing->extra_ctx;
+
+ release_ae_aes_context(ctx);
+ TEE_Free(processing->extra_ctx);
+ processing->extra_ctx = NULL;
+}
+
+/*
+ * GCM
+ */
+uint32_t tee_init_gcm_operation(struct active_processing *processing,
+ void *proc_params, size_t params_size)
+{
+ struct serialargs args;
+ uint32_t rv = 0;
+ uint32_t tag_len = 0;
+ struct ae_aes_context *params = NULL;
+ /* GCM parameters */
+ uint32_t iv_len = 0;
+ void *iv = NULL;
+ uint32_t aad_len = 0;
+ void *aad = NULL;
+ uint32_t tag_bitlen = 0;
+
+ TEE_MemFill(&args, 0, sizeof(args));
+
+ if (!proc_params)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&args, proc_params, params_size);
+
+ rv = serialargs_get(&args, &iv_len, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ // TODO: no need to copy iv into secure world
+ rv = serialargs_alloc_and_get(&args, &iv, iv_len);
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get(&args, &aad_len, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ // TODO: no need to copy aad into secure world
+ rv = serialargs_alloc_and_get(&args, &aad, aad_len);
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get(&args, &tag_bitlen, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ tag_len = ROUNDUP(tag_bitlen, 8) / 8;
+
+ /* As per pkcs#11 mechanism specification */
+ if (tag_bitlen > 128 ||
+ !iv_len || iv_len > 256) {
+ DMSG("Invalid parameters: tag_bit_len %" PRIu32
+ ", iv_len %" PRIu32, tag_bitlen, iv_len);
+ rv = SKS_CKR_MECHANISM_PARAM_INVALID;
+ goto bail;
+ }
+
+ params = TEE_Malloc(sizeof(struct ae_aes_context),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!params) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ /* Store the byte round up byte length for the tag */
+ params->tag_byte_len = tag_len;
+ params->out_count = 0;
+ params->pending_size = 0;
+ params->out_data = TEE_Malloc(sizeof(struct out_data_ref),
+ TEE_MALLOC_FILL_ZERO);
+ params->pending_tag = TEE_Malloc(tag_len,
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+
+ if (!params->out_data || !params->pending_tag) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ /* Session processing owns the active processing params */
+ assert(!processing->extra_ctx);
+ processing->extra_ctx = params;
+
+ TEE_AEInit(processing->tee_op_handle, iv, iv_len, tag_bitlen, 0, 0);
+
+ if (aad_len)
+ TEE_AEUpdateAAD(processing->tee_op_handle, aad, aad_len);
+
+ rv = SKS_OK;
+
+bail:
+ TEE_Free(iv);
+ TEE_Free(aad);
+ if (rv && params) {
+ TEE_Free(params->out_data);
+ TEE_Free(params->pending_tag);
+ TEE_Free(params);
+ }
+
+ return rv;
+}
+
+void tee_release_gcm_operation(struct active_processing *processing)
+{
+ struct ae_aes_context *ctx = processing->extra_ctx;
+
+ release_ae_aes_context(ctx);
+ TEE_Free(processing->extra_ctx);
+ processing->extra_ctx = NULL;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_asymm.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_asymm.c
new file mode 100644
index 0000000..aeb4eba
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_asymm.c
@@ -0,0 +1,839 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
+
+#include <assert.h>
+#include <compiler.h>
+#include <utee_defines.h>
+#include <tee_api_defines.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include "attributes.h"
+#include "pkcs11_token.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+bool processing_is_tee_asymm(uint32_t proc_id)
+{
+ switch (proc_id) {
+ /* RSA flavors */
+ case SKS_CKM_RSA_PKCS:
+ case SKS_CKM_RSA_PKCS_OAEP:
+ case SKS_CKM_SHA1_RSA_PKCS:
+ case SKS_CKM_SHA224_RSA_PKCS:
+ case SKS_CKM_SHA256_RSA_PKCS:
+ case SKS_CKM_SHA384_RSA_PKCS:
+ case SKS_CKM_SHA512_RSA_PKCS:
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ /* EC flavors */
+ case SKS_CKM_ECDSA:
+ case SKS_CKM_ECDSA_SHA1:
+ case SKS_CKM_ECDSA_SHA224:
+ case SKS_CKM_ECDSA_SHA256:
+ case SKS_CKM_ECDSA_SHA384:
+ case SKS_CKM_ECDSA_SHA512:
+ case SKS_CKM_ECDH1_DERIVE:
+ case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static uint32_t sks2tee_algorithm(uint32_t *tee_id,
+ enum processing_func function,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ static const uint32_t sks2tee_algo[][2] = {
+ /* RSA flavors */
+ { SKS_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5
+ /* TEE_ALG_RSASSA_PKCS1_V1_5 on signatures */ },
+ { SKS_CKM_RSA_PKCS_OAEP, 1 }, /* Need to look into params */
+ { SKS_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 },
+ { SKS_CKM_SHA224_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 },
+ { SKS_CKM_SHA256_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 },
+ { SKS_CKM_SHA384_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 },
+ { SKS_CKM_SHA512_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 },
+ { SKS_CKM_SHA1_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 },
+ { SKS_CKM_SHA224_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 },
+ { SKS_CKM_SHA256_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 },
+ { SKS_CKM_SHA384_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 },
+ { SKS_CKM_SHA512_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 },
+ /* EC flavors (Must find key size from the object) */
+ { SKS_CKM_ECDSA, 1 },
+ { SKS_CKM_ECDSA_SHA1, 1 },
+ { SKS_CKM_ECDSA_SHA224, 1 },
+ { SKS_CKM_ECDSA_SHA256, 1 },
+ { SKS_CKM_ECDSA_SHA384, 1 },
+ { SKS_CKM_ECDSA_SHA512, 1 },
+ { SKS_CKM_ECDH1_DERIVE, 1 },
+ { SKS_CKM_ECDH1_COFACTOR_DERIVE, 1 },
+ };
+ size_t end = sizeof(sks2tee_algo) / (2 * sizeof(uint32_t));
+ size_t n = 0;
+ uint32_t rv = 0;
+
+ for (n = 0; n < end; n++) {
+ if (proc_params->id == sks2tee_algo[n][0]) {
+ *tee_id = sks2tee_algo[n][1];
+ break;
+ }
+ }
+
+ switch (proc_params->id) {
+ case SKS_CKM_RSA_X_509:
+ case SKS_CKM_RSA_9796:
+ case SKS_CKM_RSA_PKCS_PSS:
+ EMSG("%s not supported by GPD TEE, need an alternative...",
+ sks2str_proc(proc_params->id));
+ break;
+ default:
+ break;
+ }
+
+ if (n == end)
+ return SKS_NOT_IMPLEMENTED;
+
+ switch (proc_params->id) {
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ rv = sks2tee_algo_rsa_pss(tee_id, proc_params);
+ break;
+ case SKS_CKM_RSA_PKCS_OAEP:
+ rv = sks2tee_algo_rsa_oaep(tee_id, proc_params);
+ break;
+ case SKS_CKM_ECDH1_DERIVE:
+ rv = sks2tee_algo_ecdh(tee_id, proc_params, obj);
+ break;
+ case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ return SKS_NOT_IMPLEMENTED;
+ case SKS_CKM_ECDSA:
+ case SKS_CKM_ECDSA_SHA1:
+ case SKS_CKM_ECDSA_SHA224:
+ case SKS_CKM_ECDSA_SHA256:
+ case SKS_CKM_ECDSA_SHA384:
+ case SKS_CKM_ECDSA_SHA512:
+ rv = sks2tee_algo_ecdsa(tee_id, proc_params, obj);
+ break;
+ default:
+ rv = SKS_OK;
+ break;
+ }
+
+ if (*tee_id == TEE_ALG_RSAES_PKCS1_V1_5 &&
+ (function == SKS_FUNCTION_SIGN || function == SKS_FUNCTION_VERIFY))
+ *tee_id = TEE_ALG_RSASSA_PKCS1_V1_5;
+
+ return rv;
+}
+
+static uint32_t sks2tee_algo_id(uint32_t sks_id)
+{
+ static const uint32_t sks2tee_algo[][2] = {
+ /* RSA flavors */
+ { SKS_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5
+ /* TEE_ALG_RSASSA_PKCS1_V1_5 on signatures */ },
+ { SKS_CKM_RSA_PKCS_OAEP, 1 }, /* Need to look into params */
+ { SKS_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 },
+ { SKS_CKM_SHA224_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 },
+ { SKS_CKM_SHA256_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 },
+ { SKS_CKM_SHA384_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 },
+ { SKS_CKM_SHA512_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 },
+ { SKS_CKM_SHA1_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 },
+ { SKS_CKM_SHA224_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 },
+ { SKS_CKM_SHA256_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 },
+ { SKS_CKM_SHA384_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 },
+ { SKS_CKM_SHA512_RSA_PKCS_PSS,
+ TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 },
+ /* EC flavors (Must find key size from the object) */
+ { SKS_CKM_ECDSA, 1 },
+ { SKS_CKM_ECDSA_SHA1, 1 },
+ { SKS_CKM_ECDSA_SHA224, 1 },
+ { SKS_CKM_ECDSA_SHA256, 1 },
+ { SKS_CKM_ECDSA_SHA384, 1 },
+ { SKS_CKM_ECDSA_SHA512, 1 },
+ { SKS_CKM_ECDH1_DERIVE, 1 },
+ { SKS_CKM_ECDH1_COFACTOR_DERIVE, 1 },
+ };
+ size_t end = sizeof(sks2tee_algo) / (2 * sizeof(uint32_t));
+ size_t n = 0;
+
+ for (n = 0; n < end; n++) {
+ if (sks_id == sks2tee_algo[n][0]) {
+ return sks2tee_algo[n][1];
+ }
+ }
+
+ switch (sks_id) {
+ case SKS_CKM_RSA_X_509:
+ case SKS_CKM_RSA_9796:
+ case SKS_CKM_RSA_PKCS_PSS:
+ EMSG("%s not supported by GPD TEE, need an alternative...",
+ sks2str_proc(sks_id));
+ break;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+static uint32_t sks2tee_key_type(uint32_t *tee_type, struct sks_object *obj,
+ enum processing_func function)
+{
+ uint32_t class = get_class(obj->attributes);
+ uint32_t type = get_type(obj->attributes);
+
+ switch (class) {
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ break;
+ default:
+ TEE_Panic(class);
+ break;
+ }
+
+ switch (type) {
+ case SKS_CKK_EC:
+ if (class == SKS_CKO_PRIVATE_KEY) {
+ *tee_type = (function == SKS_FUNCTION_DERIVE) ?
+ TEE_TYPE_ECDH_KEYPAIR :
+ TEE_TYPE_ECDSA_KEYPAIR;
+ } else {
+ *tee_type = (function == SKS_FUNCTION_DERIVE) ?
+ TEE_TYPE_ECDH_PUBLIC_KEY :
+ TEE_TYPE_ECDSA_PUBLIC_KEY;
+ }
+ break;
+ case SKS_CKK_RSA:
+ if (class == SKS_CKO_PRIVATE_KEY) {
+ *tee_type = TEE_TYPE_RSA_KEYPAIR;
+ } else {
+ *tee_type = TEE_TYPE_RSA_PUBLIC_KEY;
+ }
+ break;
+ default:
+ TEE_Panic(type);
+ break;
+ }
+
+ return SKS_OK;
+}
+
+static uint32_t allocate_tee_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ uint32_t size = (uint32_t)get_object_key_bit_size(obj);
+ uint32_t algo = 0;
+ uint32_t mode = 0;
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ assert(session->processing->tee_op_handle == TEE_HANDLE_NULL);
+
+ if (sks2tee_algorithm(&algo, function, proc_params, obj))
+ return SKS_FAILED;
+
+ sks2tee_mode(&mode, function);
+
+ res = TEE_AllocateOperation(&session->processing->tee_op_handle,
+ algo, mode, size);
+ switch (res) {
+ case TEE_ERROR_NOT_SUPPORTED:
+ return SKS_CKR_MECHANISM_INVALID;
+ case TEE_SUCCESS:
+ break;
+ default:
+ EMSG("TEE_AllocateOp. failed %" PRIx32 " %" PRIx32 " %" PRIx32,
+ algo, mode, size);
+ }
+
+ return tee2sks_error(res);
+}
+
+static uint32_t load_tee_key(struct pkcs11_session *session,
+ struct sks_object *obj,
+ enum processing_func function)
+{
+ TEE_Attribute *tee_attrs = NULL;
+ size_t tee_attrs_count = 0;
+ size_t object_size = 0;
+ uint32_t rv = 0;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ uint32_t __maybe_unused class = get_class(obj->attributes);
+ uint32_t type = get_type(obj->attributes);
+
+ assert(class == SKS_CKO_PUBLIC_KEY || class == SKS_CKO_PRIVATE_KEY);
+
+ if (obj->key_handle != TEE_HANDLE_NULL) {
+ switch (type) {
+ case SKS_CKK_RSA:
+ /* RSA loaded keys can be reused */
+ assert((obj->key_type == TEE_TYPE_RSA_PUBLIC_KEY &&
+ class == SKS_CKO_PUBLIC_KEY) ||
+ (obj->key_type == TEE_TYPE_RSA_KEYPAIR &&
+ class == SKS_CKO_PRIVATE_KEY));
+ goto key_ready;
+ case SKS_CKK_EC:
+ /* Reuse EC TEE key only if already DSA or DH */
+ switch (obj->key_type) {
+ case TEE_TYPE_ECDSA_PUBLIC_KEY:
+ case TEE_TYPE_ECDSA_KEYPAIR:
+ if (function != SKS_FUNCTION_DERIVE)
+ goto key_ready;
+ break;
+ case TEE_TYPE_ECDH_PUBLIC_KEY:
+ case TEE_TYPE_ECDH_KEYPAIR:
+ if (function == SKS_FUNCTION_DERIVE)
+ goto key_ready;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ TEE_FreeTransientObject(obj->key_handle);
+ obj->key_handle = TEE_HANDLE_NULL;
+ }
+
+ rv = sks2tee_key_type(&obj->key_type, obj, function);
+ if (rv)
+ return rv;
+
+ object_size = get_object_key_bit_size(obj);
+ if (!object_size)
+ return SKS_ERROR;
+
+ switch (type) {
+ case SKS_CKK_RSA:
+ rv = load_tee_rsa_key_attrs(&tee_attrs, &tee_attrs_count, obj);
+ break;
+ case SKS_CKK_EC:
+ rv = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj);
+ break;
+ default:
+ break;
+ }
+ if (rv)
+ return rv;
+
+ res = TEE_AllocateTransientObject(obj->key_type, object_size,
+ &obj->key_handle);
+ if (res) {
+ DMSG("TEE_AllocateTransientObject failed, 0x%" PRIx32, res);
+ return tee2sks_error(res);
+ }
+
+ res = TEE_PopulateTransientObject(obj->key_handle,
+ tee_attrs, tee_attrs_count);
+
+ TEE_Free(tee_attrs);
+
+ if (res) {
+ DMSG("TEE_PopulateTransientObject failed, 0x%" PRIx32, res);
+ goto error;
+ }
+
+key_ready:
+ res = TEE_SetOperationKey(session->processing->tee_op_handle,
+ obj->key_handle);
+ if (res) {
+ DMSG("TEE_SetOperationKey failed, 0x%" PRIx32, res);
+ goto error;
+ }
+
+ return tee2sks_error(res);
+
+error:
+ TEE_FreeTransientObject(obj->key_handle);
+ obj->key_handle = TEE_HANDLE_NULL;
+ return tee2sks_error(res);
+}
+
+static uint32_t tee_algo_to_tee_hash(uint32_t algo)
+{
+ switch (algo) {
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
+ case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
+ case TEE_ALG_SHA1:
+ case TEE_ALG_DSA_SHA1:
+ case TEE_ALG_HMAC_SHA1:
+ return TEE_ALG_SHA1;
+
+ case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
+ case TEE_ALG_MD5:
+ case TEE_ALG_HMAC_MD5:
+ return TEE_ALG_MD5;
+
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
+ case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
+ case TEE_ALG_SHA224:
+ case TEE_ALG_DSA_SHA224:
+ case TEE_ALG_HMAC_SHA224:
+ return TEE_ALG_SHA224;
+
+
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
+ case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
+ case TEE_ALG_SHA256:
+ case TEE_ALG_DSA_SHA256:
+ case TEE_ALG_HMAC_SHA256:
+ return TEE_ALG_SHA256;
+
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
+ case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
+ case TEE_ALG_SHA384:
+ case TEE_ALG_HMAC_SHA384:
+ return TEE_ALG_SHA384;
+
+ case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
+ case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
+ case TEE_ALG_SHA512:
+ case TEE_ALG_HMAC_SHA512:
+ return TEE_ALG_SHA512;
+
+ default:
+ return -1;
+ }
+
+ return -1;
+}
+
+static uint32_t init_tee_operation(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params)
+{
+ uint32_t rv = SKS_OK;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ uint32_t hash = -1;
+
+ switch (proc_params->id) {
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ rv = sks2tee_proc_params_rsa_pss(session->processing,
+ proc_params);
+ break;
+ default:
+ break;
+ }
+
+ hash = tee_algo_to_tee_hash(sks2tee_algo_id(proc_params->id));
+ if(hash != -1) {
+ res = TEE_AllocateOperation(&session->processing->extra_op_handle,hash,TEE_MODE_DIGEST,0);
+ if(res != TEE_SUCCESS)
+ rv = SKS_ERROR;
+ }
+ return rv;
+}
+
+uint32_t init_asymm_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ uint32_t rv = 0;
+
+ assert(processing_is_tee_asymm(proc_params->id));
+
+ rv = allocate_tee_operation(session, function, proc_params, obj);
+ if (rv)
+ return rv;
+
+ rv = load_tee_key(session, obj, function);
+ if (rv)
+ return rv;
+
+ return init_tee_operation(session, proc_params);
+}
+
+/*
+ * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation
+ *
+ * @session - current session
+ * @function -
+ * @step - step ID in the processing (oneshot, update,final)
+ * @in - input data reference #1
+ * @io2 - input/output data reference #2 (direction depends on function)
+ */
+uint32_t step_asymm_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ enum processing_step step,
+ TEE_Param *in, TEE_Param *io2)
+{
+ uint32_t rv = SKS_ERROR;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ void *in_buf = in ? in->memref.buffer : NULL;
+ size_t in_size = in ? in->memref.size : 0;
+ void *out_buf = io2 ? io2->memref.buffer : NULL;
+ uint32_t out_size = io2 ? io2->memref.size : 0;
+ void *in2_buf = io2 ? io2->memref.buffer : NULL;
+ uint32_t in2_size = io2 ? io2->memref.size : 0;
+ TEE_Attribute *tee_attrs = NULL;
+ size_t tee_attrs_count = 0;
+ uint32_t data32 = 0;
+ bool output_data = false;
+ struct active_processing *proc = session->processing;
+ TEE_OperationInfo opinfo;
+ uint8_t hash_value[TEE_SHA512_HASH_SIZE] = {0};
+ uint32_t hash_size = 0;
+
+ switch (step) {
+ case SKS_FUNC_STEP_ONESHOT:
+ case SKS_FUNC_STEP_UPDATE:
+ case SKS_FUNC_STEP_FINAL:
+ break;
+ default:
+ return SKS_ERROR;
+ }
+
+ /* TEE attribute(s) required by the operation */
+ switch (proc->mecha_type) {
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!tee_attrs) {
+ rv = SKS_MEMORY;
+ goto bail;
+ }
+
+ data32 = *(uint32_t *)proc->extra_ctx;
+ TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
+ TEE_ATTR_RSA_PSS_SALT_LENGTH,
+ data32, 0);
+ tee_attrs_count++;
+ break;
+ default:
+ break;
+ }
+
+ /* TEE attribute(s) required by the operation */
+ switch (proc->mecha_type) {
+ case SKS_CKM_ECDSA_SHA1:
+ case SKS_CKM_ECDSA_SHA224:
+ case SKS_CKM_ECDSA_SHA256:
+ case SKS_CKM_ECDSA_SHA384:
+ case SKS_CKM_ECDSA_SHA512:
+ if (step == SKS_FUNC_STEP_FINAL)
+ break;
+
+ EMSG("TODO: compute hash for later authentication");
+ rv = SKS_NOT_IMPLEMENTED;
+ goto bail;
+ default:
+ /* Other mechanism do not expect multi stage operation */
+ rv = SKS_ERROR;
+ break;
+ }
+
+ if (proc->extra_op_handle) {
+ TEE_DigestUpdate(proc->extra_op_handle, in_buf, in_size);
+ }
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ goto bail;
+
+ if (proc->extra_op_handle) {
+ TEE_DigestDoFinal(proc->extra_op_handle, NULL, 0, hash_value, &hash_size);
+ }
+ /*
+ * Finalize
+ */
+
+ switch (proc->mecha_type) {
+ case SKS_CKM_SHA1_RSA_PKCS:
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS:
+ case SKS_CKM_SHA256_RSA_PKCS:
+ case SKS_CKM_SHA384_RSA_PKCS:
+ case SKS_CKM_SHA512_RSA_PKCS:
+ switch (function) {
+ case SKS_FUNCTION_SIGN:
+ case SKS_FUNCTION_VERIFY:
+ in_buf = hash_value;
+ in_size = hash_size;
+ break;
+ default :
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* These ECDSA need to use the computed hash as input data */
+ switch (proc->mecha_type) {
+ case SKS_CKM_ECDSA:
+ /* Input size depends on the key size */
+ if (!in_size) {
+ rv = SKS_FAILED;
+ goto bail;
+ }
+ TEE_GetOperationInfo(proc->tee_op_handle, &opinfo);
+ switch (opinfo.algorithm) {
+ case TEE_ALG_ECDSA_P192:
+ if (in_size > 24)
+ in_size = 24;
+ break;
+ case TEE_ALG_ECDSA_P224:
+ if (in_size > 28)
+ in_size = 28;
+ break;
+ case TEE_ALG_ECDSA_P256:
+ if (in_size > 32)
+ in_size = 32;
+ break;
+ case TEE_ALG_ECDSA_P384:
+ if (in_size > 48)
+ in_size = 48;
+ break;
+ case TEE_ALG_ECDSA_P521:
+ if (in_size > 64)
+ in_size = 64;
+ break;
+ default:
+ rv = SKS_FAILED;
+ goto bail;
+ }
+ /* Validate second input buffer size if verify */
+ if (function == SKS_FUNCTION_VERIFY &&
+ in2_size != 2 * in_size) {
+ rv = SKS_CKR_SIGNATURE_LEN_RANGE;
+ goto bail;
+ }
+ break;
+ case SKS_CKM_ECDSA_SHA1:
+ in_buf = proc->extra_ctx;
+ in_size = 192;
+ break;
+ case SKS_CKM_ECDSA_SHA224:
+ in_buf = proc->extra_ctx;
+ in_size = 224;
+ break;
+ case SKS_CKM_ECDSA_SHA256:
+ in_buf = proc->extra_ctx;
+ in_size = 256;
+ break;
+ case SKS_CKM_ECDSA_SHA384:
+ in_buf = proc->extra_ctx;
+ in_size = 384;
+ break;
+ case SKS_CKM_ECDSA_SHA512:
+ in_buf = proc->extra_ctx;
+ in_size = 512;
+ break;
+ default:
+ if (step != SKS_FUNC_STEP_ONESHOT) {
+ rv = SKS_ERROR;
+ goto bail;
+ }
+ break;
+ }
+
+ switch (proc->mecha_type) {
+ case SKS_CKM_ECDSA:
+ case SKS_CKM_ECDSA_SHA1:
+ case SKS_CKM_ECDSA_SHA224:
+ case SKS_CKM_ECDSA_SHA256:
+ case SKS_CKM_ECDSA_SHA384:
+ case SKS_CKM_ECDSA_SHA512:
+ case SKS_CKM_RSA_PKCS:
+ case SKS_CKM_RSA_9796:
+ case SKS_CKM_RSA_X_509:
+ case SKS_CKM_SHA1_RSA_PKCS:
+ case SKS_CKM_RSA_PKCS_OAEP:
+ case SKS_CKM_RSA_PKCS_PSS:
+ case SKS_CKM_SHA1_RSA_PKCS_PSS:
+ case SKS_CKM_SHA256_RSA_PKCS_PSS:
+ case SKS_CKM_SHA384_RSA_PKCS_PSS:
+ case SKS_CKM_SHA512_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS_PSS:
+ case SKS_CKM_SHA224_RSA_PKCS:
+ case SKS_CKM_SHA256_RSA_PKCS:
+ case SKS_CKM_SHA384_RSA_PKCS:
+ case SKS_CKM_SHA512_RSA_PKCS:
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ // TODO: TEE_ALG_RSAES_PKCS1_OAEP_MGF1_xxx takes an
+ // optional argument TEE_ATTR_RSA_OAEP_LABEL.
+ res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
+ tee_attrs, tee_attrs_count,
+ in_buf, in_size,
+ out_buf, &out_size);
+ output_data = true;
+ rv = tee2sks_error(res);
+ break;
+
+ case SKS_FUNCTION_DECRYPT:
+ res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
+ tee_attrs, tee_attrs_count,
+ in_buf, in_size,
+ out_buf, &out_size);
+ output_data = true;
+ rv = tee2sks_error(res);
+ break;
+
+ case SKS_FUNCTION_SIGN:
+ res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
+ tee_attrs,
+ tee_attrs_count,
+ in_buf, in_size,
+ out_buf, &out_size);
+ output_data = true;
+ rv = tee2sks_error(res);
+ break;
+
+ case SKS_FUNCTION_VERIFY:
+ res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
+ tee_attrs,
+ tee_attrs_count,
+ in_buf, in_size,
+ in2_buf, in2_size);
+ rv = tee2sks_error(res);
+ break;
+
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+ default:
+ TEE_Panic(proc->mecha_type);
+ break;
+ }
+bail:
+ if (output_data && (rv == SKS_OK || rv == SKS_SHORT_BUFFER)) {
+ if (io2)
+ io2->memref.size = out_size;
+ else
+ rv = SKS_ERROR;
+ }
+
+ TEE_Free(tee_attrs);
+
+ return rv;
+}
+
+uint32_t do_asymm_derivation(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_attrs_head **head)
+{
+ uint32_t rv = SKS_ERROR;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ TEE_Attribute tee_attrs[2];
+ size_t tee_attrs_count = 0;
+ TEE_ObjectHandle out_handle = TEE_HANDLE_NULL;
+ void *a_ptr = NULL;
+ size_t a_size = 0;
+ uint32_t key_bit_size = 0;
+ uint32_t key_byte_size = 0;
+
+ TEE_MemFill(tee_attrs, 0, sizeof(tee_attrs));
+
+ rv = get_u32_attribute(*head, SKS_CKA_VALUE_LEN, &key_bit_size);
+ if (rv)
+ return rv;
+
+ if (get_type(*head) != SKS_CKK_GENERIC_SECRET)
+ key_bit_size *= 8;
+
+ key_byte_size = (key_bit_size + 7) / 8;
+
+ res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET,
+ key_byte_size * 8, &out_handle);
+ if (res) {
+ DMSG("TEE_AllocateTransientObject failed, 0x%" PRIx32, res);
+ return tee2sks_error(res);
+ }
+
+ switch (proc_params->id) {
+ case SKS_CKM_ECDH1_DERIVE:
+ case SKS_CKM_ECDH1_COFACTOR_DERIVE:
+ rv = sks2tee_ecdh_param_pub(proc_params, &a_ptr, &a_size);
+ if (rv)
+ goto bail;
+
+ // TODO: check size is the expected one (active proc key)
+ TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
+ TEE_ATTR_ECC_PUBLIC_VALUE_X,
+ a_ptr, a_size / 2);
+ tee_attrs_count++;
+
+ TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
+ TEE_ATTR_ECC_PUBLIC_VALUE_Y,
+ (char *)a_ptr + a_size / 2,
+ a_size / 2);
+ tee_attrs_count++;
+ break;
+ case SKS_CKM_DH_PKCS_DERIVE:
+ TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
+ TEE_ATTR_DH_PUBLIC_VALUE,
+ proc_params->data,
+ proc_params->size);
+ tee_attrs_count++;
+ break;
+ default:
+ TEE_Panic(proc_params->id);
+ break;
+ }
+
+ TEE_DeriveKey(session->processing->tee_op_handle,
+ &tee_attrs[0], tee_attrs_count, out_handle);
+
+ rv = alloc_get_tee_attribute_data(out_handle, TEE_ATTR_SECRET_VALUE,
+ &a_ptr, &a_size);
+ if (rv)
+ goto bail;
+
+ if (a_size * 8 < key_bit_size) {
+ rv = SKS_CKR_KEY_SIZE_RANGE;
+ } else {
+ rv = add_attribute(head, SKS_CKA_VALUE, a_ptr, key_byte_size);
+ }
+
+ TEE_Free(a_ptr);
+bail:
+ release_active_processing(session);
+ TEE_FreeTransientObject(out_handle);
+ return rv;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_ec.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_ec.c
new file mode 100644
index 0000000..66aa446
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_ec.c
@@ -0,0 +1,1493 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <assert.h>
+#include <sks_internal_abi.h>
+#include <sks_ta.h>
+#include <string.h>
+#include <tee_api_defines.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <util.h>
+
+#include "attributes.h"
+#include "object.h"
+#include "pkcs11_token.h"
+#include "pkcs11_attributes.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+#include "processing_mtk_key.h"
+
+/*
+ * DER encoded EC parameters, dumped from openssl tools using something like
+ * openssl ecparam -name secp224r1 -param-enc [explicit]|
+ * openssl asn1parse -noout -out /dev/stdout | od -t x1
+ */
+static const uint8_t prime192v1_name_der[] = {
+ 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x01,
+};
+static const uint8_t secp224r1_name_der[] = {
+ 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x21,
+};
+static const uint8_t prime256v1_name_der[] = {
+ 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
+};
+static const uint8_t secp384r1_name_der[] = {
+ 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22,
+};
+static const uint8_t secp521r1_name_der[] = {
+ 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23,
+};
+static const uint8_t brainpoolP160r1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x01,
+};
+static const uint8_t brainpoolP160t1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x02,
+};
+static const uint8_t brainpoolP192r1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x03,
+};
+static const uint8_t brainpoolP192t1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x04,
+};
+static const uint8_t brainpoolP224r1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x05,
+};
+static const uint8_t brainpoolP224t1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x06,
+};
+static const uint8_t brainpoolP256r1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07,
+};
+static const uint8_t brainpoolP256t1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x08,
+};
+static const uint8_t brainpoolP320r1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x09,
+};
+static const uint8_t brainpoolP320t1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0A,
+};
+static const uint8_t brainpoolP384r1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B,
+};
+static const uint8_t brainpoolP384t1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0C,
+};
+static const uint8_t brainpoolP512r1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D,
+};
+static const uint8_t brainpoolP512t1_name_der[] = {
+ 0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0E,
+};
+
+static const uint8_t secp224r1_oid_der[] = {
+ 0x30, 0x81, 0xDF, 0x02, 0x01, 0x01, 0x30, 0x28,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x1D, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x30, 0x53, 0x04, 0x1C, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0x04, 0x1C, 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04,
+ 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, 0x50, 0x44,
+ 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B,
+ 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4, 0x03, 0x15,
+ 0x00, 0xBD, 0x71, 0x34, 0x47, 0x99, 0xD5, 0xC7,
+ 0xFC, 0xDC, 0x45, 0xB5, 0x9F, 0xA3, 0xB9, 0xAB,
+ 0x8F, 0x6A, 0x94, 0x8B, 0xC5, 0x04, 0x39, 0x04,
+ 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F,
+ 0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3,
+ 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
+ 0x11, 0x5C, 0x1D, 0x21, 0xBD, 0x37, 0x63, 0x88,
+ 0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6,
+ 0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64,
+ 0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34,
+ 0x02, 0x1D, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13,
+ 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D, 0x02,
+ 0x01, 0x01,
+};
+
+static const uint8_t secp384r1_oid_der[] = {
+ 0x30, 0x82, 0x01, 0x57, 0x02, 0x01, 0x01, 0x30,
+ 0x3C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x01, 0x01, 0x02, 0x31, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x7B, 0x04,
+ 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFC, 0x04, 0x30, 0xB3, 0x31, 0x2F, 0xA7, 0xE2,
+ 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, 0xE3,
+ 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE,
+ 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8F, 0x50,
+ 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D, 0x8A,
+ 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3,
+ 0xEC, 0x2A, 0xEF, 0x03, 0x15, 0x00, 0xA3, 0x35,
+ 0x92, 0x6A, 0xA3, 0x19, 0xA2, 0x7A, 0x1D, 0x00,
+ 0x89, 0x6A, 0x67, 0x73, 0xA4, 0x82, 0x7A, 0xCD,
+ 0xAC, 0x73, 0x04, 0x61, 0x04, 0xAA, 0x87, 0xCA,
+ 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7,
+ 0x1E, 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B,
+ 0x62, 0x8B, 0xA7, 0x9B, 0x98, 0x59, 0xF7, 0x41,
+ 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2,
+ 0x5D, 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E,
+ 0x38, 0x72, 0x76, 0x0A, 0xB7, 0x36, 0x17, 0xDE,
+ 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98,
+ 0xBF, 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D,
+ 0xBD, 0x28, 0x9A, 0x14, 0x7C, 0xE9, 0xDA, 0x31,
+ 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1,
+ 0xCE, 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D,
+ 0x7C, 0x90, 0xEA, 0x0E, 0x5F, 0x02, 0x31, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF,
+ 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A,
+ 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t secp521r1_oid_der[] = {
+ 0x30, 0x82, 0x01, 0xC2, 0x02, 0x01, 0x01, 0x30,
+ 0x4D, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x01, 0x01, 0x02, 0x42, 0x01, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x81,
+ 0x9E, 0x04, 0x42, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x41, 0x51,
+ 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F,
+ 0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE,
+ 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3,
+ 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1,
+ 0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B,
+ 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, 0xBF, 0x07,
+ 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1,
+ 0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
+ 0x03, 0x15, 0x00, 0xD0, 0x9E, 0x88, 0x00, 0x29,
+ 0x1C, 0xB8, 0x53, 0x96, 0xCC, 0x67, 0x17, 0x39,
+ 0x32, 0x84, 0xAA, 0xA0, 0xDA, 0x64, 0xBA, 0x04,
+ 0x81, 0x85, 0x04, 0x00, 0xC6, 0x85, 0x8E, 0x06,
+ 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB,
+ 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81,
+ 0x39, 0x05, 0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF,
+ 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B, 0x5E,
+ 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1,
+ 0x27, 0xA2, 0xFF, 0xA8, 0xDE, 0x33, 0x48, 0xB3,
+ 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E,
+ 0x31, 0xC2, 0xE5, 0xBD, 0x66, 0x01, 0x18, 0x39,
+ 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C,
+ 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98,
+ 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68, 0x17,
+ 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97,
+ 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5,
+ 0x50, 0xB9, 0x01, 0x3F, 0xAD, 0x07, 0x61, 0x35,
+ 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88,
+ 0xBE, 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50, 0x02,
+ 0x42, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF,
+ 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7,
+ 0x09, 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89,
+ 0x9C, 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91,
+ 0x38, 0x64, 0x09, 0x02, 0x01, 0x01,
+};
+static const uint8_t prime192v1_oid_der[] = {
+ 0x30, 0x81, 0xC7, 0x02, 0x01, 0x01, 0x30, 0x24,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x19, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x4B, 0x04, 0x18,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
+ 0x04, 0x18, 0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C,
+ 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24,
+ 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46,
+ 0xB9, 0xB1, 0x03, 0x15, 0x00, 0x30, 0x45, 0xAE,
+ 0x6F, 0xC8, 0x42, 0x2F, 0x64, 0xED, 0x57, 0x95,
+ 0x28, 0xD3, 0x81, 0x20, 0xEA, 0xE1, 0x21, 0x96,
+ 0xD5, 0x04, 0x31, 0x04, 0x18, 0x8D, 0xA8, 0x0E,
+ 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB,
+ 0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD,
+ 0x82, 0xFF, 0x10, 0x12, 0x07, 0x19, 0x2B, 0x95,
+ 0xFF, 0xC8, 0xDA, 0x78, 0x63, 0x10, 0x11, 0xED,
+ 0x6B, 0x24, 0xCD, 0xD5, 0x73, 0xF9, 0x77, 0xA1,
+ 0x1E, 0x79, 0x48, 0x11, 0x02, 0x19, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36, 0x14,
+ 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31, 0x02,
+ 0x01, 0x01,
+};
+static const uint8_t __unused prime192v2_oid_der[] = {
+ 0x30, 0x81, 0xC7, 0x02, 0x01, 0x01, 0x30, 0x24,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x19, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x4B, 0x04, 0x18,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
+ 0x04, 0x18, 0xCC, 0x22, 0xD6, 0xDF, 0xB9, 0x5C,
+ 0x6B, 0x25, 0xE4, 0x9C, 0x0D, 0x63, 0x64, 0xA4,
+ 0xE5, 0x98, 0x0C, 0x39, 0x3A, 0xA2, 0x16, 0x68,
+ 0xD9, 0x53, 0x03, 0x15, 0x00, 0x31, 0xA9, 0x2E,
+ 0xE2, 0x02, 0x9F, 0xD1, 0x0D, 0x90, 0x1B, 0x11,
+ 0x3E, 0x99, 0x07, 0x10, 0xF0, 0xD2, 0x1A, 0xC6,
+ 0xB6, 0x04, 0x31, 0x04, 0xEE, 0xA2, 0xBA, 0xE7,
+ 0xE1, 0x49, 0x78, 0x42, 0xF2, 0xDE, 0x77, 0x69,
+ 0xCF, 0xE9, 0xC9, 0x89, 0xC0, 0x72, 0xAD, 0x69,
+ 0x6F, 0x48, 0x03, 0x4A, 0x65, 0x74, 0xD1, 0x1D,
+ 0x69, 0xB6, 0xEC, 0x7A, 0x67, 0x2B, 0xB8, 0x2A,
+ 0x08, 0x3D, 0xF2, 0xF2, 0xB0, 0x84, 0x7D, 0xE9,
+ 0x70, 0xB2, 0xDE, 0x15, 0x02, 0x19, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFE, 0x5F, 0xB1, 0xA7, 0x24, 0xDC,
+ 0x80, 0x41, 0x86, 0x48, 0xD8, 0xDD, 0x31, 0x02,
+ 0x01, 0x01,
+};
+static const uint8_t __unused prime192v3_oid_der[] = {
+ 0x30, 0x81, 0xC7, 0x02, 0x01, 0x01, 0x30, 0x24,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x19, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x4B, 0x04, 0x18,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
+ 0x04, 0x18, 0x22, 0x12, 0x3D, 0xC2, 0x39, 0x5A,
+ 0x05, 0xCA, 0xA7, 0x42, 0x3D, 0xAE, 0xCC, 0xC9,
+ 0x47, 0x60, 0xA7, 0xD4, 0x62, 0x25, 0x6B, 0xD5,
+ 0x69, 0x16, 0x03, 0x15, 0x00, 0xC4, 0x69, 0x68,
+ 0x44, 0x35, 0xDE, 0xB3, 0x78, 0xC4, 0xB6, 0x5C,
+ 0xA9, 0x59, 0x1E, 0x2A, 0x57, 0x63, 0x05, 0x9A,
+ 0x2E, 0x04, 0x31, 0x04, 0x7D, 0x29, 0x77, 0x81,
+ 0x00, 0xC6, 0x5A, 0x1D, 0xA1, 0x78, 0x37, 0x16,
+ 0x58, 0x8D, 0xCE, 0x2B, 0x8B, 0x4A, 0xEE, 0x8E,
+ 0x22, 0x8F, 0x18, 0x96, 0x38, 0xA9, 0x0F, 0x22,
+ 0x63, 0x73, 0x37, 0x33, 0x4B, 0x49, 0xDC, 0xB6,
+ 0x6A, 0x6D, 0xC8, 0xF9, 0x97, 0x8A, 0xCA, 0x76,
+ 0x48, 0xA9, 0x43, 0xB0, 0x02, 0x19, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x7A, 0x62, 0xD0, 0x31, 0xC8,
+ 0x3F, 0x42, 0x94, 0xF6, 0x40, 0xEC, 0x13, 0x02,
+ 0x01, 0x01,
+};
+static const uint8_t prime256v1_oid_der[] = {
+ 0x30, 0x81, 0xF7, 0x02, 0x01, 0x01, 0x30, 0x2C,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x5B, 0x04, 0x20,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
+ 0x04, 0x20, 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A,
+ 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98,
+ 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53,
+ 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2,
+ 0x60, 0x4B, 0x03, 0x15, 0x00, 0xC4, 0x9D, 0x36,
+ 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78,
+ 0xE1, 0x13, 0x9D, 0x26, 0xB7, 0x81, 0x9F, 0x7E,
+ 0x90, 0x04, 0x41, 0x04, 0x6B, 0x17, 0xD1, 0xF2,
+ 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
+ 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81,
+ 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45,
+ 0xD8, 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2,
+ 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
+ 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57,
+ 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68,
+ 0x37, 0xBF, 0x51, 0xF5, 0x02, 0x21, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC,
+ 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3,
+ 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, 0x02,
+ 0x01, 0x01,
+};
+static const uint8_t brainpoolP160r1_oid_der[] = {
+ 0x30, 0x81, 0x98, 0x02, 0x01, 0x01, 0x30, 0x20,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x15, 0x00, 0xE9, 0x5E, 0x4A, 0x5F,
+ 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0xC7, 0xAD,
+ 0x95, 0xB3, 0xD8, 0x13, 0x95, 0x15, 0x62, 0x0F,
+ 0x30, 0x2C, 0x04, 0x14, 0x34, 0x0E, 0x7B, 0xE2,
+ 0xA2, 0x80, 0xEB, 0x74, 0xE2, 0xBE, 0x61, 0xBA,
+ 0xDA, 0x74, 0x5D, 0x97, 0xE8, 0xF7, 0xC3, 0x00,
+ 0x04, 0x14, 0x1E, 0x58, 0x9A, 0x85, 0x95, 0x42,
+ 0x34, 0x12, 0x13, 0x4F, 0xAA, 0x2D, 0xBD, 0xEC,
+ 0x95, 0xC8, 0xD8, 0x67, 0x5E, 0x58, 0x04, 0x29,
+ 0x04, 0xBE, 0xD5, 0xAF, 0x16, 0xEA, 0x3F, 0x6A,
+ 0x4F, 0x62, 0x93, 0x8C, 0x46, 0x31, 0xEB, 0x5A,
+ 0xF7, 0xBD, 0xBC, 0xDB, 0xC3, 0x16, 0x67, 0xCB,
+ 0x47, 0x7A, 0x1A, 0x8E, 0xC3, 0x38, 0xF9, 0x47,
+ 0x41, 0x66, 0x9C, 0x97, 0x63, 0x16, 0xDA, 0x63,
+ 0x21, 0x02, 0x15, 0x00, 0xE9, 0x5E, 0x4A, 0x5F,
+ 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0x59, 0x91,
+ 0xD4, 0x50, 0x29, 0x40, 0x9E, 0x60, 0xFC, 0x09,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP160t1_oid_der[] = {
+ 0x30, 0x81, 0x98, 0x02, 0x01, 0x01, 0x30, 0x20,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x15, 0x00, 0xE9, 0x5E, 0x4A, 0x5F,
+ 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0xC7, 0xAD,
+ 0x95, 0xB3, 0xD8, 0x13, 0x95, 0x15, 0x62, 0x0F,
+ 0x30, 0x2C, 0x04, 0x14, 0xE9, 0x5E, 0x4A, 0x5F,
+ 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0xC7, 0xAD,
+ 0x95, 0xB3, 0xD8, 0x13, 0x95, 0x15, 0x62, 0x0C,
+ 0x04, 0x14, 0x7A, 0x55, 0x6B, 0x6D, 0xAE, 0x53,
+ 0x5B, 0x7B, 0x51, 0xED, 0x2C, 0x4D, 0x7D, 0xAA,
+ 0x7A, 0x0B, 0x5C, 0x55, 0xF3, 0x80, 0x04, 0x29,
+ 0x04, 0xB1, 0x99, 0xB1, 0x3B, 0x9B, 0x34, 0xEF,
+ 0xC1, 0x39, 0x7E, 0x64, 0xBA, 0xEB, 0x05, 0xAC,
+ 0xC2, 0x65, 0xFF, 0x23, 0x78, 0xAD, 0xD6, 0x71,
+ 0x8B, 0x7C, 0x7C, 0x19, 0x61, 0xF0, 0x99, 0x1B,
+ 0x84, 0x24, 0x43, 0x77, 0x21, 0x52, 0xC9, 0xE0,
+ 0xAD, 0x02, 0x15, 0x00, 0xE9, 0x5E, 0x4A, 0x5F,
+ 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0x59, 0x91,
+ 0xD4, 0x50, 0x29, 0x40, 0x9E, 0x60, 0xFC, 0x09,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP192r1_oid_der[] = {
+ 0x30, 0x81, 0xB0, 0x02, 0x01, 0x01, 0x30, 0x24,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x19, 0x00, 0xC3, 0x02, 0xF4, 0x1D,
+ 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x30,
+ 0x93, 0xD1, 0x8D, 0xB7, 0x8F, 0xCE, 0x47, 0x6D,
+ 0xE1, 0xA8, 0x62, 0x97, 0x30, 0x34, 0x04, 0x18,
+ 0x6A, 0x91, 0x17, 0x40, 0x76, 0xB1, 0xE0, 0xE1,
+ 0x9C, 0x39, 0xC0, 0x31, 0xFE, 0x86, 0x85, 0xC1,
+ 0xCA, 0xE0, 0x40, 0xE5, 0xC6, 0x9A, 0x28, 0xEF,
+ 0x04, 0x18, 0x46, 0x9A, 0x28, 0xEF, 0x7C, 0x28,
+ 0xCC, 0xA3, 0xDC, 0x72, 0x1D, 0x04, 0x4F, 0x44,
+ 0x96, 0xBC, 0xCA, 0x7E, 0xF4, 0x14, 0x6F, 0xBF,
+ 0x25, 0xC9, 0x04, 0x31, 0x04, 0xC0, 0xA0, 0x64,
+ 0x7E, 0xAA, 0xB6, 0xA4, 0x87, 0x53, 0xB0, 0x33,
+ 0xC5, 0x6C, 0xB0, 0xF0, 0x90, 0x0A, 0x2F, 0x5C,
+ 0x48, 0x53, 0x37, 0x5F, 0xD6, 0x14, 0xB6, 0x90,
+ 0x86, 0x6A, 0xBD, 0x5B, 0xB8, 0x8B, 0x5F, 0x48,
+ 0x28, 0xC1, 0x49, 0x00, 0x02, 0xE6, 0x77, 0x3F,
+ 0xA2, 0xFA, 0x29, 0x9B, 0x8F, 0x02, 0x19, 0x00,
+ 0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD,
+ 0xA7, 0xA3, 0x46, 0x2F, 0x9E, 0x9E, 0x91, 0x6B,
+ 0x5B, 0xE8, 0xF1, 0x02, 0x9A, 0xC4, 0xAC, 0xC1,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP192t1_oid_der[] = {
+ 0x30, 0x81, 0xB0, 0x02, 0x01, 0x01, 0x30, 0x24,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x19, 0x00, 0xC3, 0x02, 0xF4, 0x1D,
+ 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x30,
+ 0x93, 0xD1, 0x8D, 0xB7, 0x8F, 0xCE, 0x47, 0x6D,
+ 0xE1, 0xA8, 0x62, 0x97, 0x30, 0x34, 0x04, 0x18,
+ 0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD,
+ 0xA7, 0xA3, 0x46, 0x30, 0x93, 0xD1, 0x8D, 0xB7,
+ 0x8F, 0xCE, 0x47, 0x6D, 0xE1, 0xA8, 0x62, 0x94,
+ 0x04, 0x18, 0x13, 0xD5, 0x6F, 0xFA, 0xEC, 0x78,
+ 0x68, 0x1E, 0x68, 0xF9, 0xDE, 0xB4, 0x3B, 0x35,
+ 0xBE, 0xC2, 0xFB, 0x68, 0x54, 0x2E, 0x27, 0x89,
+ 0x7B, 0x79, 0x04, 0x31, 0x04, 0x3A, 0xE9, 0xE5,
+ 0x8C, 0x82, 0xF6, 0x3C, 0x30, 0x28, 0x2E, 0x1F,
+ 0xE7, 0xBB, 0xF4, 0x3F, 0xA7, 0x2C, 0x44, 0x6A,
+ 0xF6, 0xF4, 0x61, 0x81, 0x29, 0x09, 0x7E, 0x2C,
+ 0x56, 0x67, 0xC2, 0x22, 0x3A, 0x90, 0x2A, 0xB5,
+ 0xCA, 0x44, 0x9D, 0x00, 0x84, 0xB7, 0xE5, 0xB3,
+ 0xDE, 0x7C, 0xCC, 0x01, 0xC9, 0x02, 0x19, 0x00,
+ 0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD,
+ 0xA7, 0xA3, 0x46, 0x2F, 0x9E, 0x9E, 0x91, 0x6B,
+ 0x5B, 0xE8, 0xF1, 0x02, 0x9A, 0xC4, 0xAC, 0xC1,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP224r1_oid_der[] = {
+ 0x30, 0x81, 0xC8, 0x02, 0x01, 0x01, 0x30, 0x28,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x1D, 0x00, 0xD7, 0xC1, 0x34, 0xAA,
+ 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25,
+ 0x75, 0xD1, 0xD7, 0x87, 0xB0, 0x9F, 0x07, 0x57,
+ 0x97, 0xDA, 0x89, 0xF5, 0x7E, 0xC8, 0xC0, 0xFF,
+ 0x30, 0x3C, 0x04, 0x1C, 0x68, 0xA5, 0xE6, 0x2C,
+ 0xA9, 0xCE, 0x6C, 0x1C, 0x29, 0x98, 0x03, 0xA6,
+ 0xC1, 0x53, 0x0B, 0x51, 0x4E, 0x18, 0x2A, 0xD8,
+ 0xB0, 0x04, 0x2A, 0x59, 0xCA, 0xD2, 0x9F, 0x43,
+ 0x04, 0x1C, 0x25, 0x80, 0xF6, 0x3C, 0xCF, 0xE4,
+ 0x41, 0x38, 0x87, 0x07, 0x13, 0xB1, 0xA9, 0x23,
+ 0x69, 0xE3, 0x3E, 0x21, 0x35, 0xD2, 0x66, 0xDB,
+ 0xB3, 0x72, 0x38, 0x6C, 0x40, 0x0B, 0x04, 0x39,
+ 0x04, 0x0D, 0x90, 0x29, 0xAD, 0x2C, 0x7E, 0x5C,
+ 0xF4, 0x34, 0x08, 0x23, 0xB2, 0xA8, 0x7D, 0xC6,
+ 0x8C, 0x9E, 0x4C, 0xE3, 0x17, 0x4C, 0x1E, 0x6E,
+ 0xFD, 0xEE, 0x12, 0xC0, 0x7D, 0x58, 0xAA, 0x56,
+ 0xF7, 0x72, 0xC0, 0x72, 0x6F, 0x24, 0xC6, 0xB8,
+ 0x9E, 0x4E, 0xCD, 0xAC, 0x24, 0x35, 0x4B, 0x9E,
+ 0x99, 0xCA, 0xA3, 0xF6, 0xD3, 0x76, 0x14, 0x02,
+ 0xCD, 0x02, 0x1D, 0x00, 0xD7, 0xC1, 0x34, 0xAA,
+ 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25,
+ 0x75, 0xD0, 0xFB, 0x98, 0xD1, 0x16, 0xBC, 0x4B,
+ 0x6D, 0xDE, 0xBC, 0xA3, 0xA5, 0xA7, 0x93, 0x9F,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP224t1_oid_der[] = {
+ 0x30, 0x81, 0xC8, 0x02, 0x01, 0x01, 0x30, 0x28,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x1D, 0x00, 0xD7, 0xC1, 0x34, 0xAA,
+ 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25,
+ 0x75, 0xD1, 0xD7, 0x87, 0xB0, 0x9F, 0x07, 0x57,
+ 0x97, 0xDA, 0x89, 0xF5, 0x7E, 0xC8, 0xC0, 0xFF,
+ 0x30, 0x3C, 0x04, 0x1C, 0xD7, 0xC1, 0x34, 0xAA,
+ 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25,
+ 0x75, 0xD1, 0xD7, 0x87, 0xB0, 0x9F, 0x07, 0x57,
+ 0x97, 0xDA, 0x89, 0xF5, 0x7E, 0xC8, 0xC0, 0xFC,
+ 0x04, 0x1C, 0x4B, 0x33, 0x7D, 0x93, 0x41, 0x04,
+ 0xCD, 0x7B, 0xEF, 0x27, 0x1B, 0xF6, 0x0C, 0xED,
+ 0x1E, 0xD2, 0x0D, 0xA1, 0x4C, 0x08, 0xB3, 0xBB,
+ 0x64, 0xF1, 0x8A, 0x60, 0x88, 0x8D, 0x04, 0x39,
+ 0x04, 0x6A, 0xB1, 0xE3, 0x44, 0xCE, 0x25, 0xFF,
+ 0x38, 0x96, 0x42, 0x4E, 0x7F, 0xFE, 0x14, 0x76,
+ 0x2E, 0xCB, 0x49, 0xF8, 0x92, 0x8A, 0xC0, 0xC7,
+ 0x60, 0x29, 0xB4, 0xD5, 0x80, 0x03, 0x74, 0xE9,
+ 0xF5, 0x14, 0x3E, 0x56, 0x8C, 0xD2, 0x3F, 0x3F,
+ 0x4D, 0x7C, 0x0D, 0x4B, 0x1E, 0x41, 0xC8, 0xCC,
+ 0x0D, 0x1C, 0x6A, 0xBD, 0x5F, 0x1A, 0x46, 0xDB,
+ 0x4C, 0x02, 0x1D, 0x00, 0xD7, 0xC1, 0x34, 0xAA,
+ 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25,
+ 0x75, 0xD0, 0xFB, 0x98, 0xD1, 0x16, 0xBC, 0x4B,
+ 0x6D, 0xDE, 0xBC, 0xA3, 0xA5, 0xA7, 0x93, 0x9F,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP256r1_oid_der[] = {
+ 0x30, 0x81, 0xE0, 0x02, 0x01, 0x01, 0x30, 0x2C,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x21, 0x00, 0xA9, 0xFB, 0x57, 0xDB,
+ 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90,
+ 0x9D, 0x83, 0x8D, 0x72, 0x6E, 0x3B, 0xF6, 0x23,
+ 0xD5, 0x26, 0x20, 0x28, 0x20, 0x13, 0x48, 0x1D,
+ 0x1F, 0x6E, 0x53, 0x77, 0x30, 0x44, 0x04, 0x20,
+ 0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57,
+ 0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7,
+ 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C,
+ 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9,
+ 0x04, 0x20, 0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A,
+ 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9, 0xBB, 0xD7,
+ 0x7C, 0xBF, 0x95, 0x84, 0x16, 0x29, 0x5C, 0xF7,
+ 0xE1, 0xCE, 0x6B, 0xCC, 0xDC, 0x18, 0xFF, 0x8C,
+ 0x07, 0xB6, 0x04, 0x41, 0x04, 0x8B, 0xD2, 0xAE,
+ 0xB9, 0xCB, 0x7E, 0x57, 0xCB, 0x2C, 0x4B, 0x48,
+ 0x2F, 0xFC, 0x81, 0xB7, 0xAF, 0xB9, 0xDE, 0x27,
+ 0xE1, 0xE3, 0xBD, 0x23, 0xC2, 0x3A, 0x44, 0x53,
+ 0xBD, 0x9A, 0xCE, 0x32, 0x62, 0x54, 0x7E, 0xF8,
+ 0x35, 0xC3, 0xDA, 0xC4, 0xFD, 0x97, 0xF8, 0x46,
+ 0x1A, 0x14, 0x61, 0x1D, 0xC9, 0xC2, 0x77, 0x45,
+ 0x13, 0x2D, 0xED, 0x8E, 0x54, 0x5C, 0x1D, 0x54,
+ 0xC7, 0x2F, 0x04, 0x69, 0x97, 0x02, 0x21, 0x00,
+ 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
+ 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71,
+ 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
+ 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP256t1_oid_der[] = {
+ 0x30, 0x81, 0xE0, 0x02, 0x01, 0x01, 0x30, 0x2C,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x01,
+ 0x01, 0x02, 0x21, 0x00, 0xA9, 0xFB, 0x57, 0xDB,
+ 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90,
+ 0x9D, 0x83, 0x8D, 0x72, 0x6E, 0x3B, 0xF6, 0x23,
+ 0xD5, 0x26, 0x20, 0x28, 0x20, 0x13, 0x48, 0x1D,
+ 0x1F, 0x6E, 0x53, 0x77, 0x30, 0x44, 0x04, 0x20,
+ 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
+ 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
+ 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
+ 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x74,
+ 0x04, 0x20, 0x66, 0x2C, 0x61, 0xC4, 0x30, 0xD8,
+ 0x4E, 0xA4, 0xFE, 0x66, 0xA7, 0x73, 0x3D, 0x0B,
+ 0x76, 0xB7, 0xBF, 0x93, 0xEB, 0xC4, 0xAF, 0x2F,
+ 0x49, 0x25, 0x6A, 0xE5, 0x81, 0x01, 0xFE, 0xE9,
+ 0x2B, 0x04, 0x04, 0x41, 0x04, 0xA3, 0xE8, 0xEB,
+ 0x3C, 0xC1, 0xCF, 0xE7, 0xB7, 0x73, 0x22, 0x13,
+ 0xB2, 0x3A, 0x65, 0x61, 0x49, 0xAF, 0xA1, 0x42,
+ 0xC4, 0x7A, 0xAF, 0xBC, 0x2B, 0x79, 0xA1, 0x91,
+ 0x56, 0x2E, 0x13, 0x05, 0xF4, 0x2D, 0x99, 0x6C,
+ 0x82, 0x34, 0x39, 0xC5, 0x6D, 0x7F, 0x7B, 0x22,
+ 0xE1, 0x46, 0x44, 0x41, 0x7E, 0x69, 0xBC, 0xB6,
+ 0xDE, 0x39, 0xD0, 0x27, 0x00, 0x1D, 0xAB, 0xE8,
+ 0xF3, 0x5B, 0x25, 0xC9, 0xBE, 0x02, 0x21, 0x00,
+ 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
+ 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71,
+ 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
+ 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7,
+ 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP320r1_oid_der[] = {
+ 0x30, 0x82, 0x01, 0x10, 0x02, 0x01, 0x01, 0x30,
+ 0x34, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x01, 0x01, 0x02, 0x29, 0x00, 0xD3, 0x5E, 0x47,
+ 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78,
+ 0x5E, 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF,
+ 0xA6, 0xF6, 0xF4, 0x0D, 0xEF, 0x4F, 0x92, 0xB9,
+ 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12,
+ 0xB1, 0xF1, 0xB3, 0x2E, 0x27, 0x30, 0x54, 0x04,
+ 0x28, 0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0,
+ 0xF8, 0x83, 0xCC, 0xEB, 0xD4, 0x6D, 0x3F, 0x3B,
+ 0xB8, 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB, 0x79,
+ 0xDA, 0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9,
+ 0xF4, 0x92, 0xF3, 0x75, 0xA9, 0x7D, 0x86, 0x0E,
+ 0xB4, 0x04, 0x28, 0x52, 0x08, 0x83, 0x94, 0x9D,
+ 0xFD, 0xBC, 0x42, 0xD3, 0xAD, 0x19, 0x86, 0x40,
+ 0x68, 0x8A, 0x6F, 0xE1, 0x3F, 0x41, 0x34, 0x95,
+ 0x54, 0xB4, 0x9A, 0xCC, 0x31, 0xDC, 0xCD, 0x88,
+ 0x45, 0x39, 0x81, 0x6F, 0x5E, 0xB4, 0xAC, 0x8F,
+ 0xB1, 0xF1, 0xA6, 0x04, 0x51, 0x04, 0x43, 0xBD,
+ 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89,
+ 0xBC, 0xC4, 0x8E, 0xE5, 0xBF, 0xE6, 0xF2, 0x01,
+ 0x37, 0xD1, 0x0A, 0x08, 0x7E, 0xB6, 0xE7, 0x87,
+ 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, 0x10, 0xAF,
+ 0x8D, 0x0D, 0x39, 0xE2, 0x06, 0x11, 0x14, 0xFD,
+ 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40,
+ 0x93, 0x24, 0x7F, 0x77, 0x27, 0x5E, 0x07, 0x43,
+ 0xFF, 0xED, 0x11, 0x71, 0x82, 0xEA, 0xA9, 0xC7,
+ 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, 0xD3, 0x52,
+ 0x45, 0xD1, 0x69, 0x2E, 0x8E, 0xE1, 0x02, 0x29,
+ 0x00, 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F,
+ 0xB7, 0xE1, 0x3C, 0x78, 0x5E, 0xD2, 0x01, 0xE0,
+ 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12,
+ 0xA3, 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58,
+ 0xE9, 0x86, 0x91, 0x55, 0x5B, 0x44, 0xC5, 0x93,
+ 0x11, 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP320t1_oid_der[] = {
+ 0x30, 0x82, 0x01, 0x10, 0x02, 0x01, 0x01, 0x30,
+ 0x34, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x01, 0x01, 0x02, 0x29, 0x00, 0xD3, 0x5E, 0x47,
+ 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78,
+ 0x5E, 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF,
+ 0xA6, 0xF6, 0xF4, 0x0D, 0xEF, 0x4F, 0x92, 0xB9,
+ 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12,
+ 0xB1, 0xF1, 0xB3, 0x2E, 0x27, 0x30, 0x54, 0x04,
+ 0x28, 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F,
+ 0xB7, 0xE1, 0x3C, 0x78, 0x5E, 0xD2, 0x01, 0xE0,
+ 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D,
+ 0xEF, 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC,
+ 0x28, 0xFC, 0xD4, 0x12, 0xB1, 0xF1, 0xB3, 0x2E,
+ 0x24, 0x04, 0x28, 0xA7, 0xF5, 0x61, 0xE0, 0x38,
+ 0xEB, 0x1E, 0xD5, 0x60, 0xB3, 0xD1, 0x47, 0xDB,
+ 0x78, 0x20, 0x13, 0x06, 0x4C, 0x19, 0xF2, 0x7E,
+ 0xD2, 0x7C, 0x67, 0x80, 0xAA, 0xF7, 0x7F, 0xB8,
+ 0xA5, 0x47, 0xCE, 0xB5, 0xB4, 0xFE, 0xF4, 0x22,
+ 0x34, 0x03, 0x53, 0x04, 0x51, 0x04, 0x92, 0x5B,
+ 0xE9, 0xFB, 0x01, 0xAF, 0xC6, 0xFB, 0x4D, 0x3E,
+ 0x7D, 0x49, 0x90, 0x01, 0x0F, 0x81, 0x34, 0x08,
+ 0xAB, 0x10, 0x6C, 0x4F, 0x09, 0xCB, 0x7E, 0xE0,
+ 0x78, 0x68, 0xCC, 0x13, 0x6F, 0xFF, 0x33, 0x57,
+ 0xF6, 0x24, 0xA2, 0x1B, 0xED, 0x52, 0x63, 0xBA,
+ 0x3A, 0x7A, 0x27, 0x48, 0x3E, 0xBF, 0x66, 0x71,
+ 0xDB, 0xEF, 0x7A, 0xBB, 0x30, 0xEB, 0xEE, 0x08,
+ 0x4E, 0x58, 0xA0, 0xB0, 0x77, 0xAD, 0x42, 0xA5,
+ 0xA0, 0x98, 0x9D, 0x1E, 0xE7, 0x1B, 0x1B, 0x9B,
+ 0xC0, 0x45, 0x5F, 0xB0, 0xD2, 0xC3, 0x02, 0x29,
+ 0x00, 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F,
+ 0xB7, 0xE1, 0x3C, 0x78, 0x5E, 0xD2, 0x01, 0xE0,
+ 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12,
+ 0xA3, 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58,
+ 0xE9, 0x86, 0x91, 0x55, 0x5B, 0x44, 0xC5, 0x93,
+ 0x11, 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP384r1_oid_der[] = {
+ 0x30, 0x82, 0x01, 0x40, 0x02, 0x01, 0x01, 0x30,
+ 0x3C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x01, 0x01, 0x02, 0x31, 0x00, 0x8C, 0xB9, 0x1E,
+ 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F,
+ 0x7E, 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71,
+ 0x09, 0xED, 0x54, 0x56, 0xB4, 0x12, 0xB1, 0xDA,
+ 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7,
+ 0x29, 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00,
+ 0x13, 0x31, 0x07, 0xEC, 0x53, 0x30, 0x64, 0x04,
+ 0x30, 0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15,
+ 0x0C, 0x3C, 0x72, 0x08, 0x0A, 0xCE, 0x05, 0xAF,
+ 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27,
+ 0x87, 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9,
+ 0x0F, 0x8A, 0xA5, 0x81, 0x4A, 0x50, 0x3A, 0xD4,
+ 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28,
+ 0x26, 0x04, 0x30, 0x04, 0xA8, 0xC7, 0xDD, 0x22,
+ 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54, 0x16,
+ 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07,
+ 0xDC, 0xD2, 0xA6, 0x2E, 0x88, 0x0E, 0xA5, 0x3E,
+ 0xEB, 0x62, 0xD5, 0x7C, 0xB4, 0x39, 0x02, 0x95,
+ 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA,
+ 0x50, 0x4C, 0x11, 0x04, 0x61, 0x04, 0x1D, 0x1C,
+ 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6,
+ 0x3A, 0x81, 0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47,
+ 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3, 0xDB, 0x7F,
+ 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26,
+ 0xE0, 0x34, 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87,
+ 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E, 0x8A, 0xBE,
+ 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1,
+ 0xEB, 0x8E, 0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7,
+ 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64, 0xE1, 0x9C,
+ 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46,
+ 0x46, 0x21, 0x77, 0x91, 0x81, 0x11, 0x42, 0x82,
+ 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15, 0x02, 0x31,
+ 0x00, 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D,
+ 0x28, 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41,
+ 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56,
+ 0xB3, 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25,
+ 0xA7, 0xCF, 0x3A, 0xB6, 0xAF, 0x6B, 0x7F, 0xC3,
+ 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65,
+ 0x65, 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP384t1_oid_der[] = {
+ 0x30, 0x82, 0x01, 0x40, 0x02, 0x01, 0x01, 0x30,
+ 0x3C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x01, 0x01, 0x02, 0x31, 0x00, 0x8C, 0xB9, 0x1E,
+ 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F,
+ 0x7E, 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71,
+ 0x09, 0xED, 0x54, 0x56, 0xB4, 0x12, 0xB1, 0xDA,
+ 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7,
+ 0x29, 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00,
+ 0x13, 0x31, 0x07, 0xEC, 0x53, 0x30, 0x64, 0x04,
+ 0x30, 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D,
+ 0x28, 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41,
+ 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56,
+ 0xB4, 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11,
+ 0x23, 0xAC, 0xD3, 0xA7, 0x29, 0x90, 0x1D, 0x1A,
+ 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC,
+ 0x50, 0x04, 0x30, 0x7F, 0x51, 0x9E, 0xAD, 0xA7,
+ 0xBD, 0xA8, 0x1B, 0xD8, 0x26, 0xDB, 0xA6, 0x47,
+ 0x91, 0x0F, 0x8C, 0x4B, 0x93, 0x46, 0xED, 0x8C,
+ 0xCD, 0xC6, 0x4E, 0x4B, 0x1A, 0xBD, 0x11, 0x75,
+ 0x6D, 0xCE, 0x1D, 0x20, 0x74, 0xAA, 0x26, 0x3B,
+ 0x88, 0x80, 0x5C, 0xED, 0x70, 0x35, 0x5A, 0x33,
+ 0xB4, 0x71, 0xEE, 0x04, 0x61, 0x04, 0x18, 0xDE,
+ 0x98, 0xB0, 0x2D, 0xB9, 0xA3, 0x06, 0xF2, 0xAF,
+ 0xCD, 0x72, 0x35, 0xF7, 0x2A, 0x81, 0x9B, 0x80,
+ 0xAB, 0x12, 0xEB, 0xD6, 0x53, 0x17, 0x24, 0x76,
+ 0xFE, 0xCD, 0x46, 0x2A, 0xAB, 0xFF, 0xC4, 0xFF,
+ 0x19, 0x1B, 0x94, 0x6A, 0x5F, 0x54, 0xD8, 0xD0,
+ 0xAA, 0x2F, 0x41, 0x88, 0x08, 0xCC, 0x25, 0xAB,
+ 0x05, 0x69, 0x62, 0xD3, 0x06, 0x51, 0xA1, 0x14,
+ 0xAF, 0xD2, 0x75, 0x5A, 0xD3, 0x36, 0x74, 0x7F,
+ 0x93, 0x47, 0x5B, 0x7A, 0x1F, 0xCA, 0x3B, 0x88,
+ 0xF2, 0xB6, 0xA2, 0x08, 0xCC, 0xFE, 0x46, 0x94,
+ 0x08, 0x58, 0x4D, 0xC2, 0xB2, 0x91, 0x26, 0x75,
+ 0xBF, 0x5B, 0x9E, 0x58, 0x29, 0x28, 0x02, 0x31,
+ 0x00, 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D,
+ 0x28, 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41,
+ 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56,
+ 0xB3, 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25,
+ 0xA7, 0xCF, 0x3A, 0xB6, 0xAF, 0x6B, 0x7F, 0xC3,
+ 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65,
+ 0x65, 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP512r1_oid_der[] = {
+ 0x30, 0x82, 0x01, 0xA2, 0x02, 0x01, 0x01, 0x30,
+ 0x4C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x01, 0x01, 0x02, 0x41, 0x00, 0xAA, 0xDD, 0x9D,
+ 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6,
+ 0xAE, 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D,
+ 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, 0xD6, 0x63, 0x9C,
+ 0xCA, 0x70, 0x33, 0x08, 0x71, 0x7D, 0x4D, 0x9B,
+ 0x00, 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1,
+ 0x2A, 0xE6, 0xA3, 0x80, 0xE6, 0x28, 0x81, 0xFF,
+ 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60,
+ 0x56, 0x58, 0x3A, 0x48, 0xF3, 0x30, 0x81, 0x84,
+ 0x04, 0x40, 0x78, 0x30, 0xA3, 0x31, 0x8B, 0x60,
+ 0x3B, 0x89, 0xE2, 0x32, 0x71, 0x45, 0xAC, 0x23,
+ 0x4C, 0xC5, 0x94, 0xCB, 0xDD, 0x8D, 0x3D, 0xF9,
+ 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98,
+ 0x63, 0xBC, 0x2D, 0xED, 0x5D, 0x5A, 0xA8, 0x25,
+ 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A,
+ 0xC8, 0xB5, 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2,
+ 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC,
+ 0x94, 0xCA, 0x04, 0x40, 0x3D, 0xF9, 0x16, 0x10,
+ 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC,
+ 0x2D, 0xED, 0x5D, 0x5A, 0xA8, 0x25, 0x3A, 0xA1,
+ 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5,
+ 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9,
+ 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA,
+ 0xDC, 0x08, 0x3E, 0x67, 0x98, 0x40, 0x50, 0xB7,
+ 0x5E, 0xBA, 0xE5, 0xDD, 0x28, 0x09, 0xBD, 0x63,
+ 0x80, 0x16, 0xF7, 0x23, 0x04, 0x81, 0x81, 0x04,
+ 0x81, 0xAE, 0xE4, 0xBD, 0xD8, 0x2E, 0xD9, 0x64,
+ 0x5A, 0x21, 0x32, 0x2E, 0x9C, 0x4C, 0x6A, 0x93,
+ 0x85, 0xED, 0x9F, 0x70, 0xB5, 0xD9, 0x16, 0xC1,
+ 0xB4, 0x3B, 0x62, 0xEE, 0xF4, 0xD0, 0x09, 0x8E,
+ 0xFF, 0x3B, 0x1F, 0x78, 0xE2, 0xD0, 0xD4, 0x8D,
+ 0x50, 0xD1, 0x68, 0x7B, 0x93, 0xB9, 0x7D, 0x5F,
+ 0x7C, 0x6D, 0x50, 0x47, 0x40, 0x6A, 0x5E, 0x68,
+ 0x8B, 0x35, 0x22, 0x09, 0xBC, 0xB9, 0xF8, 0x22,
+ 0x7D, 0xDE, 0x38, 0x5D, 0x56, 0x63, 0x32, 0xEC,
+ 0xC0, 0xEA, 0xBF, 0xA9, 0xCF, 0x78, 0x22, 0xFD,
+ 0xF2, 0x09, 0xF7, 0x00, 0x24, 0xA5, 0x7B, 0x1A,
+ 0xA0, 0x00, 0xC5, 0x5B, 0x88, 0x1F, 0x81, 0x11,
+ 0xB2, 0xDC, 0xDE, 0x49, 0x4A, 0x5F, 0x48, 0x5E,
+ 0x5B, 0xCA, 0x4B, 0xD8, 0x8A, 0x27, 0x63, 0xAE,
+ 0xD1, 0xCA, 0x2B, 0x2F, 0xA8, 0xF0, 0x54, 0x06,
+ 0x78, 0xCD, 0x1E, 0x0F, 0x3A, 0xD8, 0x08, 0x92,
+ 0x02, 0x41, 0x00, 0xAA, 0xDD, 0x9D, 0xB8, 0xDB,
+ 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, 0x33,
+ 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3,
+ 0xC9, 0xD2, 0x0E, 0xD6, 0x63, 0x9C, 0xCA, 0x70,
+ 0x33, 0x08, 0x70, 0x55, 0x3E, 0x5C, 0x41, 0x4C,
+ 0xA9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7F,
+ 0xAC, 0x10, 0x47, 0x1D, 0xB1, 0xD3, 0x81, 0x08,
+ 0x5D, 0xDA, 0xDD, 0xB5, 0x87, 0x96, 0x82, 0x9C,
+ 0xA9, 0x00, 0x69, 0x02, 0x01, 0x01,
+};
+static const uint8_t brainpoolP512t1_oid_der[] = {
+ 0x30, 0x82, 0x01, 0xA2, 0x02, 0x01, 0x01, 0x30,
+ 0x4C, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x01, 0x01, 0x02, 0x41, 0x00, 0xAA, 0xDD, 0x9D,
+ 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6,
+ 0xAE, 0x33, 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D,
+ 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, 0xD6, 0x63, 0x9C,
+ 0xCA, 0x70, 0x33, 0x08, 0x71, 0x7D, 0x4D, 0x9B,
+ 0x00, 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1,
+ 0x2A, 0xE6, 0xA3, 0x80, 0xE6, 0x28, 0x81, 0xFF,
+ 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60,
+ 0x56, 0x58, 0x3A, 0x48, 0xF3, 0x30, 0x81, 0x84,
+ 0x04, 0x40, 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9,
+ 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, 0x33, 0xC9,
+ 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9,
+ 0xD2, 0x0E, 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33,
+ 0x08, 0x71, 0x7D, 0x4D, 0x9B, 0x00, 0x9B, 0xC6,
+ 0x68, 0x42, 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3,
+ 0x80, 0xE6, 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82,
+ 0xC6, 0x85, 0x28, 0xAA, 0x60, 0x56, 0x58, 0x3A,
+ 0x48, 0xF0, 0x04, 0x40, 0x7C, 0xBB, 0xBC, 0xF9,
+ 0x44, 0x1C, 0xFA, 0xB7, 0x6E, 0x18, 0x90, 0xE4,
+ 0x68, 0x84, 0xEA, 0xE3, 0x21, 0xF7, 0x0C, 0x0B,
+ 0xCB, 0x49, 0x81, 0x52, 0x78, 0x97, 0x50, 0x4B,
+ 0xEC, 0x3E, 0x36, 0xA6, 0x2B, 0xCD, 0xFA, 0x23,
+ 0x04, 0x97, 0x65, 0x40, 0xF6, 0x45, 0x00, 0x85,
+ 0xF2, 0xDA, 0xE1, 0x45, 0xC2, 0x25, 0x53, 0xB4,
+ 0x65, 0x76, 0x36, 0x89, 0x18, 0x0E, 0xA2, 0x57,
+ 0x18, 0x67, 0x42, 0x3E, 0x04, 0x81, 0x81, 0x04,
+ 0x64, 0x0E, 0xCE, 0x5C, 0x12, 0x78, 0x87, 0x17,
+ 0xB9, 0xC1, 0xBA, 0x06, 0xCB, 0xC2, 0xA6, 0xFE,
+ 0xBA, 0x85, 0x84, 0x24, 0x58, 0xC5, 0x6D, 0xDE,
+ 0x9D, 0xB1, 0x75, 0x8D, 0x39, 0xC0, 0x31, 0x3D,
+ 0x82, 0xBA, 0x51, 0x73, 0x5C, 0xDB, 0x3E, 0xA4,
+ 0x99, 0xAA, 0x77, 0xA7, 0xD6, 0x94, 0x3A, 0x64,
+ 0xF7, 0xA3, 0xF2, 0x5F, 0xE2, 0x6F, 0x06, 0xB5,
+ 0x1B, 0xAA, 0x26, 0x96, 0xFA, 0x90, 0x35, 0xDA,
+ 0x5B, 0x53, 0x4B, 0xD5, 0x95, 0xF5, 0xAF, 0x0F,
+ 0xA2, 0xC8, 0x92, 0x37, 0x6C, 0x84, 0xAC, 0xE1,
+ 0xBB, 0x4E, 0x30, 0x19, 0xB7, 0x16, 0x34, 0xC0,
+ 0x11, 0x31, 0x15, 0x9C, 0xAE, 0x03, 0xCE, 0xE9,
+ 0xD9, 0x93, 0x21, 0x84, 0xBE, 0xEF, 0x21, 0x6B,
+ 0xD7, 0x1D, 0xF2, 0xDA, 0xDF, 0x86, 0xA6, 0x27,
+ 0x30, 0x6E, 0xCF, 0xF9, 0x6D, 0xBB, 0x8B, 0xAC,
+ 0xE1, 0x98, 0xB6, 0x1E, 0x00, 0xF8, 0xB3, 0x32,
+ 0x02, 0x41, 0x00, 0xAA, 0xDD, 0x9D, 0xB8, 0xDB,
+ 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, 0x33,
+ 0xC9, 0xFC, 0x07, 0xCB, 0x30, 0x8D, 0xB3, 0xB3,
+ 0xC9, 0xD2, 0x0E, 0xD6, 0x63, 0x9C, 0xCA, 0x70,
+ 0x33, 0x08, 0x70, 0x55, 0x3E, 0x5C, 0x41, 0x4C,
+ 0xA9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7F,
+ 0xAC, 0x10, 0x47, 0x1D, 0xB1, 0xD3, 0x81, 0x08,
+ 0x5D, 0xDA, 0xDD, 0xB5, 0x87, 0x96, 0x82, 0x9C,
+ 0xA9, 0x00, 0x69, 0x02, 0x01, 0x01,
+};
+
+struct supported_ecc_curve {
+ const uint8_t *oid_der;
+ size_t oid_size;
+ const uint8_t *name_der;
+ size_t name_size;
+ size_t key_size;
+ uint32_t tee_id;
+ const char *label;
+ size_t label_size;
+};
+
+#define ECC_CURVE(_tee_id, _key_size, _label) \
+ { \
+ .tee_id = _tee_id, \
+ .key_size = _key_size, \
+ .oid_der = _label ## _oid_der, \
+ .oid_size = sizeof(_label ## _oid_der), \
+ .name_der = _label ## _name_der, \
+ .name_size = sizeof(_label ## _name_der), \
+ .label = #_label, \
+ .label_size = sizeof(#_label) - 1, \
+ }
+
+/* These are introduced with GPD TEE Core Internal API v1.2 */
+#ifndef TEE_ECC_CURVE_BSI_P160r1
+#define TEE_ECC_CURVE_BSI_P160r1 0x00000101 /* 160 bits */
+#define TEE_ECC_CURVE_BSI_P192r1 0x00000102 /* 192 bits */
+#define TEE_ECC_CURVE_BSI_P224r1 0x00000103 /* 224 bits */
+#define TEE_ECC_CURVE_BSI_P256r1 0x00000104 /* 256 bits */
+#define TEE_ECC_CURVE_BSI_P320r1 0x00000105 /* 320 bits */
+#define TEE_ECC_CURVE_BSI_P384r1 0x00000106 /* 384 bits */
+#define TEE_ECC_CURVE_BSI_P512r1 0x00000107 /* 512 bits */
+#define TEE_ECC_CURVE_BSI_P160t1 0x00000201 /* 160 bits */
+#define TEE_ECC_CURVE_BSI_P192t1 0x00000202 /* 192 bits */
+#define TEE_ECC_CURVE_BSI_P224t1 0x00000203 /* 224 bits */
+#define TEE_ECC_CURVE_BSI_P256t1 0x00000204 /* 256 bits */
+#define TEE_ECC_CURVE_BSI_P320t1 0x00000205 /* 320 bits */
+#define TEE_ECC_CURVE_BSI_P384t1 0x00000206 /* 384 bits */
+#define TEE_ECC_CURVE_BSI_P512t1 0x00000207 /* 512 bits */
+#define TEE_ECC_CURVE_25519 0x00000300 /* 256 bits */
+#define TEE_ECC_CURVE_SM2 0x00000400 /* 256 bits */
+#endif
+
+static const struct supported_ecc_curve ec_curve_param[] = {
+ ECC_CURVE(TEE_ECC_CURVE_NIST_P192, 192, prime192v1),
+ ECC_CURVE(TEE_ECC_CURVE_NIST_P224, 224, secp224r1),
+ ECC_CURVE(TEE_ECC_CURVE_NIST_P256, 256, prime256v1),
+ ECC_CURVE(TEE_ECC_CURVE_NIST_P384, 384, secp384r1),
+ ECC_CURVE(TEE_ECC_CURVE_NIST_P521, 521, secp521r1),
+ /* Note: this will be for GPD TEE Core Internal API v1.2 */
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P160r1, 160, brainpoolP160r1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P160t1, 160, brainpoolP160t1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P192r1, 192, brainpoolP192r1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P192t1, 192, brainpoolP192t1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P224r1, 224, brainpoolP224r1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P224t1, 224, brainpoolP224t1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P256r1, 256, brainpoolP256r1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P256t1, 256, brainpoolP256t1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P320r1, 320, brainpoolP320r1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P320t1, 320, brainpoolP320t1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P384r1, 384, brainpoolP384r1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P384t1, 384, brainpoolP384t1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P512r1, 512, brainpoolP512r1),
+ ECC_CURVE(TEE_ECC_CURVE_BSI_P512t1, 512, brainpoolP512t1),
+};
+
+static const struct supported_ecc_curve *get_curve(void *attr, size_t size)
+{
+ size_t idx = 0;
+
+ /* Weak: not a real DER parser: try by params then by named curve */
+ for (idx = 0; idx < ARRAY_SIZE(ec_curve_param); idx++) {
+ const struct supported_ecc_curve *curve = &ec_curve_param[idx];
+
+ if (size == curve->oid_size &&
+ !TEE_MemCompare(attr, curve->oid_der, curve->oid_size))
+ return curve;
+
+ if (size == curve->name_size &&
+ !TEE_MemCompare(attr, curve->name_der, curve->name_size))
+ return curve;
+ }
+
+ return NULL;
+}
+
+size_t ec_params2tee_keysize(void *ec_params, size_t size)
+{
+ const struct supported_ecc_curve *curve = get_curve(ec_params, size);
+
+ if (!curve)
+ return 0;
+
+ return curve->key_size;
+}
+
+/*
+ * This function intentionally panics if the curve is not found.
+ * Use ec_params2tee_keysize() to check the curve is supported by
+ * the internal core API.
+ */
+uint32_t ec_params2tee_curve(void *ec_params, size_t size)
+{
+ const struct supported_ecc_curve *curve = get_curve(ec_params, size);
+
+ assert(curve);
+
+ return curve->tee_id;
+}
+
+uint32_t load_tee_ec_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count,
+ struct sks_object *obj)
+{
+ TEE_Attribute *attrs = NULL;
+ size_t count = 0;
+ uint32_t rv = SKS_ERROR;
+
+ assert(get_type(obj->attributes) == SKS_CKK_EC);
+
+ switch (get_class(obj->attributes)) {
+ case SKS_CKO_PUBLIC_KEY:
+ attrs = TEE_Malloc(3 * sizeof(TEE_Attribute),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!attrs)
+ return SKS_MEMORY;
+
+ if (sks2tee_load_attr(&attrs[count], TEE_ATTR_ECC_CURVE,
+ obj, SKS_CKA_EC_PARAMS))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_ECC_PUBLIC_VALUE_X,
+ obj, SKS_CKA_EC_POINT))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_ECC_PUBLIC_VALUE_Y,
+ obj, SKS_CKA_EC_POINT))
+ count++;
+
+ if (count == 3)
+ rv = SKS_OK;
+
+ break;
+
+ case SKS_CKO_PRIVATE_KEY:
+ attrs = TEE_Malloc(4 * sizeof(TEE_Attribute),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!attrs)
+ return SKS_MEMORY;
+
+ if (sks2tee_load_attr(&attrs[count], TEE_ATTR_ECC_CURVE,
+ obj, SKS_CKA_EC_PARAMS))
+ count++;
+
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_ECC_PRIVATE_VALUE,
+ obj, SKS_CKA_VALUE))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_ECC_PUBLIC_VALUE_X,
+ obj, SKS_CKA_EC_POINT))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_ECC_PUBLIC_VALUE_Y,
+ obj, SKS_CKA_EC_POINT))
+ count++;
+
+ if (count == 4)
+ rv = SKS_OK;
+
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ if (rv == SKS_OK) {
+ *tee_attrs = attrs;
+ *tee_count = count;
+ }
+
+ return rv;
+}
+
+uint32_t sks2tee_algo_ecdh(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ struct serialargs args;
+ uint32_t rv = 0;
+ uint32_t kdf = 0;
+
+ TEE_MemFill(&args, 0, sizeof(args));
+
+ serialargs_init(&args, proc_params->data, proc_params->size);
+
+ rv = serialargs_get(&args, &kdf, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ if (kdf != SKS_CKD_NULL) {
+ EMSG("Currently no support for hashed shared data");
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ switch (get_object_key_bit_size(obj)) {
+ case 192:
+ *tee_id = TEE_ALG_ECDH_P192;
+ break;
+ case 224:
+ *tee_id = TEE_ALG_ECDH_P224;
+ break;
+ case 256:
+ *tee_id = TEE_ALG_ECDH_P256;
+ break;
+ case 384:
+ *tee_id = TEE_ALG_ECDH_P384;
+ break;
+ case 521:
+ *tee_id = TEE_ALG_ECDH_P521;
+ break;
+ default:
+ TEE_Panic(0);
+ break;
+ }
+
+ return SKS_OK;
+}
+
+uint32_t sks2tee_ecdh_param_pub(struct sks_attribute_head *proc_params,
+ void **pub_data, size_t *pub_size)
+{
+ struct serialargs args;
+ uint32_t rv = 0;
+ uint32_t temp = 0;
+
+ TEE_MemFill(&args, 0, sizeof(args));
+
+ serialargs_init(&args, proc_params->data, proc_params->size);
+
+ /* Skip KDF */
+ rv = serialargs_get(&args, &temp, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ /* Shared data size, shall be 0 */
+ rv = serialargs_get(&args, &temp, sizeof(uint32_t));
+ if (rv || temp)
+ return rv;
+
+ /* Public data size and content */
+ rv = serialargs_get(&args, &temp, sizeof(uint32_t));
+ if (rv || !temp)
+ return rv;
+
+ *pub_size = temp;
+
+ return serialargs_get_ptr(&args, pub_data, temp);
+}
+
+uint32_t sks2tee_algo_ecdsa(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ switch (proc_params->id) {
+ case SKS_CKM_ECDSA:
+ case SKS_CKM_ECDSA_SHA1:
+ case SKS_CKM_ECDSA_SHA224:
+ case SKS_CKM_ECDSA_SHA256:
+ case SKS_CKM_ECDSA_SHA384:
+ case SKS_CKM_ECDSA_SHA512:
+ break;
+ default:
+ return SKS_ERROR;
+ }
+
+ switch (get_object_key_bit_size(obj)) {
+ case 192:
+ *tee_id = TEE_ALG_ECDSA_P192;
+ break;
+ case 224:
+ *tee_id = TEE_ALG_ECDSA_P224;
+ break;
+ case 256:
+ *tee_id = TEE_ALG_ECDSA_P256;
+ break;
+ case 384:
+ *tee_id = TEE_ALG_ECDSA_P384;
+ break;
+ case 521:
+ *tee_id = TEE_ALG_ECDSA_P521;
+ break;
+ default:
+ TEE_Panic(0);
+ break;
+ }
+
+ return SKS_OK;
+}
+
+static uint32_t tee2sks_ec_attributes(struct sks_attrs_head **pub_head,
+ struct sks_attrs_head **priv_head,
+ TEE_ObjectHandle tee_obj, uint32_t tee_size)
+{
+ void *x_ptr = NULL;
+ void *y_ptr = NULL;
+ uint8_t *ecpoint = NULL;
+ size_t x_size = 0;
+ size_t y_size = 0;
+ size_t psize = 0;
+ size_t qsize = 0;
+ size_t dersize = 0;
+ size_t poffset = 0;
+ uint32_t rv = 0;
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_VALUE,
+ tee_obj, TEE_ATTR_ECC_PRIVATE_VALUE);
+ if (rv)
+ goto bail;
+
+ rv = alloc_get_tee_attribute_data(tee_obj, TEE_ATTR_ECC_PUBLIC_VALUE_X,
+ &x_ptr, &x_size);
+ if (rv)
+ goto bail;
+
+ rv = alloc_get_tee_attribute_data(tee_obj, TEE_ATTR_ECC_PUBLIC_VALUE_Y,
+ &y_ptr, &y_size);
+ if (rv)
+ goto x_cleanup;
+
+ psize = (tee_size + 7) / 8;
+ if (x_size > psize || y_size > psize) {
+ rv = SKS_BAD_PARAM;
+ goto p_cleanup;
+ }
+
+ qsize = 1 + 2 * psize;
+ /* TODO: Support DER long definitive form, needed for 64 key size */
+ if (qsize < 0x80) {
+ dersize = qsize + 2;
+ } else {
+ EMSG("DER long definitive form not yet supported");
+ rv = SKS_CKR_MECHANISM_INVALID;
+ goto p_cleanup;
+ }
+
+ ecpoint = TEE_Malloc(dersize, TEE_MALLOC_FILL_ZERO);
+ if (!ecpoint) {
+ rv = SKS_MEMORY;
+ goto p_cleanup;
+ }
+
+ /* DER encoding */
+ ecpoint[0] = 0x04;
+ ecpoint[1] = qsize & 0x7f;
+ /* Only UNCOMPRESSED ECPOINT is currently supported */
+ ecpoint[2] = 0x04;
+
+ poffset = 0;
+ if (x_size < psize)
+ poffset = psize - x_size;
+ TEE_MemMove(ecpoint + 3 + poffset, x_ptr, x_size);
+
+ poffset = 0;
+ if (y_size < psize)
+ poffset = psize - y_size;
+ TEE_MemMove(ecpoint + 3 + psize + poffset, y_ptr, y_size);
+
+ /*
+ * Add EC_POINT on both private and public key objects as
+ * TEE_PopulateTransientObject requires public x/y values
+ * for TEE_TYPE_ECDSA_KEYPAIR.
+ */
+ rv = add_attribute(priv_head, SKS_CKA_EC_POINT, ecpoint, dersize);
+ if (rv)
+ goto priv_cleanup;
+
+ rv = add_attribute(pub_head, SKS_CKA_EC_POINT, ecpoint, dersize);
+
+priv_cleanup:
+ TEE_Free(ecpoint);
+p_cleanup:
+ TEE_Free(y_ptr);
+x_cleanup:
+ TEE_Free(x_ptr);
+bail:
+ return rv;
+}
+
+uint32_t generate_ec_keys(struct sks_attribute_head *proc_params,
+ struct sks_attrs_head **pub_head,
+ struct sks_attrs_head **priv_head)
+{
+ uint32_t rv = 0;
+ void *a_ptr = NULL;
+ uint32_t a_size = 0;
+ uint32_t tee_size = 0;
+ uint32_t tee_curve = 0;
+ TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL;
+ TEE_Attribute tee_key_attr[1];
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ TEE_MemFill(tee_key_attr, 0, sizeof(tee_key_attr));
+
+ if (!proc_params || !*pub_head || !*priv_head)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+
+ if (!get_attribute_ptr(*pub_head, SKS_CKA_EC_POINT, NULL, NULL) ||
+ !get_attribute_ptr(*priv_head, SKS_CKA_VALUE, NULL, NULL) ||
+ !get_attribute_ptr(*priv_head, SKS_CKA_EC_POINT, NULL, NULL)) {
+ EMSG("Unexpected attribute(s) found");
+ trace_attributes("public-key", *pub_head);
+ trace_attributes("privat-key", *priv_head);
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ if (get_attribute_ptr(*pub_head, SKS_CKA_EC_PARAMS, &a_ptr, &a_size)) {
+ EMSG("Not EC_PARAMS attribute found");
+ return SKS_CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+
+ tee_size = ec_params2tee_keysize(a_ptr, a_size);
+ if (!tee_size)
+ return SKS_CKR_ATTRIBUTE_TYPE_INVALID;
+
+ tee_curve = ec_params2tee_curve(a_ptr, a_size);
+
+ TEE_InitValueAttribute(&tee_key_attr[0], TEE_ATTR_ECC_CURVE,
+ tee_curve, 0);
+
+ /* Create an ECDSA TEE key: will match PKCS11 ECDSA and ECDH */
+ res = TEE_AllocateTransientObject(TEE_TYPE_ECDSA_KEYPAIR,
+ 521/*tee_size*/, &tee_obj);
+ if (res) {
+ EMSG("TEE service failed, %" PRIx32, res);
+ return tee2sks_error(res);
+ }
+
+ res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE);
+ if (res) {
+ rv = tee2sks_error(res);
+ goto bail;
+ }
+
+ res = TEE_GenerateKey(tee_obj, tee_size, &tee_key_attr[0], 1);
+ if (res) {
+ rv = tee2sks_error(res);
+ goto bail;
+ }
+
+ /*
+ * Private key needs the same EC_PARAMS as used by the public key.
+ * Since it is also common for userspace to provide an empty private
+ * EC_PARAMS, make sure to remove before adding the correct one.
+ */
+ remove_attribute(priv_head, SKS_CKA_EC_PARAMS);
+ rv = add_attribute(priv_head, SKS_CKA_EC_PARAMS, a_ptr, a_size);
+ if (rv)
+ goto bail;
+
+ rv = tee2sks_ec_attributes(pub_head, priv_head, tee_obj, tee_size);
+
+bail:
+ if (tee_obj != TEE_HANDLE_NULL)
+ TEE_FreeTransientObject(tee_obj);
+
+ return rv;
+}
+
+static int sks2uecc_curve_id(int curve_id)
+{
+ int uECC_curve_id = -1;
+ switch (curve_id)
+ {
+ case TEE_ECC_CURVE_NIST_P192:
+ uECC_curve_id = UECC_CURVE_ID_SECP192R1;
+ break;
+ case TEE_ECC_CURVE_NIST_P224:
+ uECC_curve_id = UECC_CURVE_ID_SECP224R1;
+ break;
+ case TEE_ECC_CURVE_NIST_P256:
+ uECC_curve_id = UECC_CURVE_ID_SECP256R1;
+ break;
+ case TEE_ECC_CURVE_NIST_P384:
+ uECC_curve_id = UECC_CURVE_ID_SECP384R1;
+ break;
+ case TEE_ECC_CURVE_NIST_P521:
+ default:
+ EMSG("[%s][%d] not support curve id!", __FUNCTION__, __LINE__);
+ uECC_curve_id = UECC_CURVE_ID_UNSUPPORT;
+ break;
+ }
+ return uECC_curve_id;
+}
+
+uint32_t generate_hsm_ec_keys(struct sks_attribute_head *proc_params,
+ struct sks_attrs_head **pub_head,
+ struct sks_attrs_head **priv_head)
+{
+ uint32_t rv = 0;
+ void *a_ptr = NULL;
+ uint32_t a_size = 0;
+ uint32_t tee_size = 0;
+ uint32_t tee_curve = 0;
+ TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL;
+ TEE_Attribute tee_key_attr[1];
+ TEE_Result res = TEE_ERROR_GENERIC;
+ int keyid = 0;
+ int key_size = 0;
+ int uECC_curve_id = -1;
+
+ TEE_MemFill(tee_key_attr, 0, sizeof(tee_key_attr));
+
+ if (!proc_params || !*pub_head || !*priv_head)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+
+ if (!get_attribute_ptr(*pub_head, SKS_CKA_EC_POINT, NULL, NULL) ||
+ !get_attribute_ptr(*priv_head, SKS_CKA_VALUE, NULL, NULL) ||
+ !get_attribute_ptr(*priv_head, SKS_CKA_EC_POINT, NULL, NULL)) {
+ EMSG("Unexpected attribute(s) found");
+ trace_attributes("public-key", *pub_head);
+ trace_attributes("privat-key", *priv_head);
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ if (get_attribute_ptr(*pub_head, SKS_CKA_EC_PARAMS, &a_ptr, &a_size)) {
+ EMSG("Not EC_PARAMS attribute found");
+ return SKS_CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+
+ tee_size = ec_params2tee_keysize(a_ptr, a_size);
+ if (!tee_size)
+ return SKS_CKR_ATTRIBUTE_TYPE_INVALID;
+
+ tee_curve = ec_params2tee_curve(a_ptr, a_size);
+
+ key_size = tee_size >> 3;
+
+ uECC_curve_id = sks2uecc_curve_id(tee_curve);
+ if (uECC_curve_id == UECC_CURVE_ID_UNSUPPORT)
+ {
+ rv = SKS_CKR_ARGUMENTS_BAD;
+ goto bail;
+ }
+
+ rv = mtk_generate_ecc_key_pair(tee_size, uECC_curve_id, &keyid);
+ if (rv)
+ goto bail;
+
+ /*
+ * Private key needs the same EC_PARAMS as used by the public key.
+ * Since it is also common for userspace to provide an empty private
+ * EC_PARAMS, make sure to remove before adding the correct one.
+ */
+ remove_attribute(priv_head, SKS_CKA_EC_PARAMS);
+ rv = add_attribute(priv_head, SKS_CKA_EC_PARAMS, a_ptr, a_size);
+ if (rv)
+ goto bail;
+
+ rv = add_attribute(pub_head, SKS_CKA_HSM_KEY_ID, &keyid, sizeof(keyid));
+ if (rv)
+ goto bail;
+
+ rv = add_attribute(pub_head, SKS_CKA_HSM_KEY_LEN, &key_size, sizeof(key_size));
+ if (rv )
+ goto bail;
+
+ rv = add_attribute(priv_head, SKS_CKA_HSM_KEY_ID, &keyid, sizeof(keyid));
+ if (rv)
+ goto bail;
+
+ rv = add_attribute(priv_head, SKS_CKA_HSM_KEY_LEN, &key_size, sizeof(key_size));
+ if (rv )
+ goto bail;
+
+bail:
+ return rv;
+}
+
+uint32_t import_hsm_ecc_keypair(struct sks_attrs_head **pub,
+ struct sks_attrs_head **priv,
+ uint8_t *keyblob,
+ int *blobsize)
+{
+ uint32_t rv = 0;
+ uint8_t *pubkeybuf = NULL;
+ uint32_t pubkeylength;
+ uint8_t *privkeybuf = NULL;
+ uint32_t privkeylength;
+ void *data = NULL;
+ uint32_t data_size;
+ void *a_ptr = NULL;
+ uint32_t a_size = 0;
+ uint32_t tee_size = 0;
+ uint32_t tee_curve = 0;
+ int key_size = 0;
+ int keyid = 0;
+ int uECC_curve_id = -1;
+ ecc_keypair_datastruct ecckeypair;
+
+ TEE_MemFill(&ecckeypair, 0, sizeof(ecckeypair));
+
+ if (!*pub || !*priv || !keyblob || !blobsize)
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+
+ rv = get_attribute_ptr(*priv, SKS_CKA_VALUE, &privkeybuf, &privkeylength);
+ if (rv) {
+ EMSG("[%s][%d] rv : %d\n", __FUNCTION__, __LINE__, rv);
+ return SKS_CKR_GENERAL_ERROR;
+ }
+
+ rv = get_attribute_ptr(*pub, SKS_CKA_VALUE, &pubkeybuf, &pubkeylength);
+ if (rv) {
+ EMSG("[%s][%d] rv : %d\n", __FUNCTION__, __LINE__, rv);
+ return SKS_CKR_GENERAL_ERROR;
+ }
+
+ if (get_attribute_ptr(*pub, SKS_CKA_EC_PARAMS, &a_ptr, &a_size)) {
+ EMSG("Not EC_PARAMS attribute found");
+ return SKS_CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+
+ tee_size = ec_params2tee_keysize(a_ptr, a_size);
+ if (!tee_size)
+ return SKS_CKR_ATTRIBUTE_TYPE_INVALID;
+
+ tee_curve = ec_params2tee_curve(a_ptr, a_size);
+
+ key_size = tee_size >> 3;
+
+ uECC_curve_id = sks2uecc_curve_id(tee_curve);
+ if (uECC_curve_id == UECC_CURVE_ID_UNSUPPORT)
+ {
+ rv = SKS_CKR_ARGUMENTS_BAD;
+ goto bail;
+ }
+
+ ecckeypair.curve_id = uECC_curve_id;
+ TEE_MemMove(ecckeypair.public, pubkeybuf, pubkeylength);
+ TEE_MemMove(ecckeypair.private, privkeybuf, privkeylength);
+
+ rv = mtk_import_key((uint8_t *)&ecckeypair, sizeof(ecckeypair), &keyid, keyblob, blobsize, KEY_ALGO_ID_ECC);
+ if (rv)
+ goto bail;
+
+ rv = add_attribute(pub, SKS_CKA_HSM_KEY_ID, &keyid, sizeof(keyid));
+ if (rv)
+ return SKS_CKR_GENERAL_ERROR;
+
+ rv = add_attribute(pub, SKS_CKA_HSM_KEY_LEN, &key_size, sizeof(key_size));
+ if (rv )
+ return SKS_CKR_GENERAL_ERROR;
+
+ rv = add_attribute(priv, SKS_CKA_HSM_KEY_ID, &keyid, sizeof(keyid));
+ if (rv)
+ return SKS_CKR_GENERAL_ERROR;
+
+ rv = add_attribute(priv, SKS_CKA_HSM_KEY_LEN, &key_size, sizeof(key_size));
+ if (rv )
+ return SKS_CKR_GENERAL_ERROR;
+bail:
+ return rv;
+}
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_hsm.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_hsm.c
new file mode 100644
index 0000000..6bfcf24
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_hsm.c
@@ -0,0 +1,1690 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include "processing_mtk_hsm.h"
+#include "hsm_mbox_if.h"
+#include "mtk_crypto.h"
+#include "hsm_job.h"
+#include "sks_hsm_debug.h"
+
+#define GET_BE32(a) ((((uint32_t) (a)[0]) << 24) | \
+ (((uint32_t) (a)[1]) << 16) | \
+ (((uint32_t) (a)[2]) << 8) | \
+ ((uint32_t) (a)[3]))
+
+#define PUT_BE32(a, val) { \
+ (a)[0] = (uint8_t) ((((uint32_t) (val)) >> 24) & 0xff); \
+ (a)[1] = (uint8_t) ((((uint32_t) (val)) >> 16) & 0xff); \
+ (a)[2] = (uint8_t) ((((uint32_t) (val)) >> 8) & 0xff); \
+ (a)[3] = (uint8_t) (((uint32_t) (val)) & 0xff); \
+}
+
+#define PUT_BE64(a, val) { \
+ (a)[0] = (uint8_t) (((uint64_t) (val)) >> 56 & 0xff); \
+ (a)[1] = (uint8_t) (((uint64_t) (val)) >> 48 & 0xff); \
+ (a)[2] = (uint8_t) (((uint64_t) (val)) >> 40 & 0xff); \
+ (a)[3] = (uint8_t) (((uint64_t) (val)) >> 32 & 0xff); \
+ (a)[4] = (uint8_t) (((uint64_t) (val)) >> 24 & 0xff); \
+ (a)[5] = (uint8_t) (((uint64_t) (val)) >> 16 & 0xff); \
+ (a)[6] = (uint8_t) (((uint64_t) (val)) >> 8 & 0xff); \
+ (a)[7] = (uint8_t) (((uint64_t) (val)) & 0xff); \
+}
+
+#define LOOKBIT(x) (1UL << (x))
+
+extern TEE_Result Send_job(job_struct *pjob);
+extern TEE_Result dump_hsm_log(void);
+
+void __SHOW_VAL(char *c, uint8_t *ptr, uint32_t len);
+void __SHOW_VAL(char *c, uint8_t *ptr, uint32_t len)
+{
+#if HSM_TA_DEBUG
+
+ uint8_t line[8] = {0};
+ SKS_HSM_DEBUG(" --- %s ( %d ) bytes ---\r\n", c, len);
+ int j = 0;
+ for (j = 0; j < len; j++)
+ {
+ line[j % 8] = *(ptr + j);
+ if ((j % 8) == 7)
+ SKS_HSM_DEBUG(" %02X %02X %02X %02X - %02X %02X %02X %02X \r\n"
+ , line[0], line[1], line[2], line[3]
+ , line[4], line[5], line[6], line[7]);
+ }
+ if ((j % 8) != 0)
+ {
+ switch (j % 8)
+ {
+ case 1: SKS_HSM_DEBUG(" %02X -- -- -- - -- -- -- -- \r\n", line[0]); break;
+ case 2: SKS_HSM_DEBUG(" %02X %02X -- -- - -- -- -- -- \r\n", line[0], line[1]); break;
+ case 3: SKS_HSM_DEBUG(" %02X %02X %02X -- - -- -- -- -- \r\n", line[0], line[1], line[2]); break;
+ case 4: SKS_HSM_DEBUG(" %02X %02X %02X %02X - -- -- -- -- \r\n", line[0], line[1], line[2], line[3]); break;
+ case 5: SKS_HSM_DEBUG(" %02X %02X %02X %02X - %02X -- -- -- \r\n", line[0], line[1], line[2], line[3], line[4]); break;
+ case 6: SKS_HSM_DEBUG(" %02X %02X %02X %02X - %02X %02X -- -- \r\n", line[0], line[1], line[2], line[3], line[4], line[5]); break;
+ case 7: SKS_HSM_DEBUG(" %02X %02X %02X %02X - %02X %02X %02X -- \r\n", line[0], line[1], line[2], line[3], line[4], line[5], line[6]); break;
+ }
+ }
+ SKS_HSM_DEBUG(" --------------------\r\n");
+
+#endif
+}
+
+static void inc32(uint8_t *block, uint32_t i)
+{
+ uint32_t val = 0;
+ uint32_t org_val = 0;
+
+ val = GET_BE32(block + 12);
+ org_val = val;
+ val += i;
+ PUT_BE32(block + 12, val);
+
+ if (org_val > val) // Overflow
+ {
+ for (int i = 11; i >= 0; i--)
+ {
+ block[i]++;
+ if (block[i] != 0)
+ break;
+ }
+ }
+}
+
+static void xor_block(uint8_t *dst, const uint8_t *src)
+{
+ uint32_t *d = (uint32_t *) dst;
+ uint32_t *s = (uint32_t *) src;
+ *d++ ^= *s++;
+ *d++ ^= *s++;
+ *d++ ^= *s++;
+ *d++ ^= *s++;
+}
+
+static void shift_right_block(uint8_t *v)
+{
+ uint32_t val = 0;
+
+ val = GET_BE32(v + 12);
+ val >>= 1;
+ if (v[11] & 0x01)
+ val |= 0x80000000;
+ PUT_BE32(v + 12, val);
+
+ val = GET_BE32(v + 8);
+ val >>= 1;
+ if (v[7] & 0x01)
+ val |= 0x80000000;
+ PUT_BE32(v + 8, val);
+
+ val = GET_BE32(v + 4);
+ val >>= 1;
+ if (v[3] & 0x01)
+ val |= 0x80000000;
+ PUT_BE32(v + 4, val);
+
+ val = GET_BE32(v);
+ val >>= 1;
+ PUT_BE32(v, val);
+}
+
+
+/* Multiplication in GF(2^128) */
+static void gf_mult(const uint8_t *x, const uint8_t *y, uint8_t *z)
+{
+ uint8_t v[16] = {0};
+ int i = 0;
+ int j = 0;
+
+ memset(z, 0, 16); /* Z_0 = 0^128 */
+ memcpy(v, y, 16); /* V_0 = Y */
+
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 8; j++) {
+ if (x[i] & LOOKBIT(7 - j)) {
+ /* Z_(i + 1) = Z_i XOR V_i */
+ xor_block(z, v);
+ } else {
+ /* Z_(i + 1) = Z_i */
+ }
+
+ if (v[15] & 0x01) {
+ /* V_(i + 1) = (V_i >> 1) XOR R */
+ shift_right_block(v);
+ /* R = 11100001 || 0^120 */
+ v[0] ^= 0xe1;
+ } else {
+ /* V_(i + 1) = V_i >> 1 */
+ shift_right_block(v);
+ }
+ }
+ }
+}
+
+
+static void ghash_start(uint8_t *y)
+{
+ /* Y_0 = 0^128 */
+ memset(y, 0, 16);
+}
+
+
+static void ghash(const uint8_t *h, const uint8_t *x, size_t xlen, uint8_t *y)
+{
+ size_t m = 0;
+ size_t i = 0;
+ const uint8_t *xpos = x;
+ uint8_t tmp[16] = {0};
+
+ m = xlen / 16;
+
+ for (i = 0; i < m; i++) {
+ /* Y_i = (Y^(i-1) XOR X_i) dot H */
+ xor_block(y, xpos);
+ xpos += 16;
+
+ /* dot operation:
+ * multiplication operation for binary Galois (finite) field of
+ * 2^128 elements */
+ gf_mult(y, h, tmp);
+ memcpy(y, tmp, 16);
+ }
+
+ if (x + xlen > xpos) {
+ /* Add zero padded last block */
+ size_t last = x + xlen - xpos;
+ memcpy(tmp, xpos, last);
+ memset(tmp + last, 0, sizeof(tmp) - last);
+
+ /* Y_i = (Y^(i-1) XOR X_i) dot H */
+ xor_block(y, tmp);
+
+ /* dot operation:
+ * multiplication operation for binary Galois (finite) field of
+ * 2^128 elements */
+ gf_mult(y, h, tmp);
+ memcpy(y, tmp, 16);
+ }
+
+ /* Return Y_m */
+}
+
+
+static void aes_gcm_calculate_j0(const uint8_t *H, const uint8_t *iv, size_t iv_len, uint8_t *J0)
+{
+ uint8_t len_buf[16] = {0};
+
+ if (iv_len == 12)
+ {
+ /* calculate block J_0 = IV || 0^31 || 1 */
+ memcpy(J0, iv, iv_len);
+ memset(J0 + iv_len, 0, 16 - iv_len);
+ J0[15] = 0x01;
+ }
+ else
+ {
+ /*
+ * s = 128 * ceil(len(IV)/128) - len(IV)
+ * J_0 = GHASH_H(IV || 0^(s+64) || [len(IV)]_64)
+ */
+ ghash_start(J0);
+ ghash(H, iv, iv_len, J0);
+ PUT_BE64(len_buf, 0);
+ PUT_BE64(len_buf + 8, iv_len * 8);
+ ghash(H, len_buf, sizeof(len_buf), J0);
+ }
+}
+
+
+static void aes_gcm_ghash(const uint8_t *H, const uint8_t *aad, size_t aad_len,
+ const uint8_t *crypt, size_t crypt_len, uint8_t *S)
+{
+ uint8_t len_buf[16] = {0};
+
+ /*
+ * u = 128 * ceil[len(C)/128] - len(C)
+ * v = 128 * ceil[len(A)/128] - len(A)
+ * S = GHASH_H(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64)
+ * (i.e., zero padded to block size A || C and lengths of each in bits)
+ */
+ ghash_start(S);
+ ghash(H, aad, aad_len, S);
+ ghash(H, crypt, crypt_len, S);
+ PUT_BE64(len_buf, aad_len * 8);
+ PUT_BE64(len_buf + 8, crypt_len * 8);
+ ghash(H, len_buf, sizeof(len_buf), S);
+}
+
+static uint32_t get_symmetric_key_from_attribute(struct sks_object *key, MTK_HSM_State *state)
+{
+ int key_id = 0;
+ int key_id_size = sizeof(key_id);
+ int key_len = 0;
+ int key_len_size = sizeof(key_len);
+ uint32_t rv = 0;
+
+ if ((key == NULL) || (state == NULL))
+ return SKS_CKR_ARGUMENTS_BAD;
+
+ rv = get_attribute(key->attributes, SKS_CKA_HSM_KEY_ID, &key_id, &key_id_size);
+ if (rv != 0)
+ return rv;
+ rv = get_attribute(key->attributes, SKS_CKA_HSM_KEY_LEN, &key_len, &key_len_size);
+ if (rv != 0)
+ return rv;
+
+ state->key1_id = key_id;
+ state->key1_len = key_len;
+
+ SKS_HSM_DEBUG(" ==> state->key1_len: %d\n", state->key1_len);
+ return SKS_OK;
+}
+
+uint32_t mtk_AES_ECB_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key)
+{
+ MTK_HSM_State *_ptr = NULL;
+ uint32_t rv = 0;
+
+ if ((session == NULL) || (proc_params == NULL) || (key == NULL))
+ return SKS_BAD_PARAM;
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ // Get key
+ rv = get_symmetric_key_from_attribute(key, _ptr);
+ if(rv != SKS_OK)
+ return rv;
+
+ session->processing->mtk_hsm_handle = _ptr;
+
+
+ return SKS_OK;
+}
+
+uint32_t mtk_AES_CBC_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key)
+{
+ MTK_HSM_State *_ptr = NULL;
+ uint8_t *IV = NULL;
+ uint32_t rv = 0;
+
+ if ((session == NULL) || (proc_params == NULL))
+ return SKS_BAD_PARAM;
+
+ IV = proc_params->data;
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ memcpy(_ptr->CBC_IV, IV, 16);
+
+ // Get key
+ rv = get_symmetric_key_from_attribute(key, _ptr);
+ if(rv != SKS_OK)
+ return rv;
+
+ session->processing->mtk_hsm_handle = _ptr;
+
+ return SKS_OK;
+}
+
+uint32_t mtk_AES_CTR_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key)
+{
+ MTK_HSM_State *_ptr = NULL;
+ uint8_t *CTR = NULL;
+ struct serialargs args;
+ uint32_t rv = 0;
+ /* CTR parameters */
+ uint32_t incr_counter = 0;
+
+ if ((session == NULL) || (proc_params == NULL))
+ return SKS_BAD_PARAM;
+
+ TEE_MemFill(&args, 0, sizeof(args));
+
+ if (!proc_params)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&args, proc_params->data, proc_params->size);
+
+ rv = serialargs_get(&args, &incr_counter, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get_ptr(&args, &CTR, 16);
+ if (rv)
+ goto bail;
+
+ __SHOW_VAL("CTR", CTR, 16);
+
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ memcpy(_ptr->CTR, CTR, 16);
+
+ // Get key
+ rv = get_symmetric_key_from_attribute(key, _ptr);
+ if(rv != SKS_OK)
+ return rv;
+
+ session->processing->mtk_hsm_handle = _ptr;
+
+bail:
+ return SKS_OK;
+
+}
+
+uint32_t mtk_AES_GCM_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key)
+{
+ MTK_HSM_State *_ptr = NULL;
+ uint8_t *pIv = NULL;
+ uint32_t ulIvLen = 0;
+ uint8_t *pAAD = NULL;
+ uint32_t ulAADLen = 0;
+ uint8_t ulTagBits = 0;
+
+ struct serialargs args;
+ uint32_t rv = 0;
+ /* GCM parameters */
+ uint32_t incr_counter = 0;
+
+ static const org_0[16] = {0};
+ uint8_t H[16] = {0};
+ job_struct _job = {0};
+ uint8_t J0[16] = {0};
+ uint8_t S[16] = {0};
+
+ if ((session == NULL) || (proc_params == NULL))
+ return SKS_BAD_PARAM;
+
+ TEE_MemFill(&args, 0, sizeof(args));
+
+ if (!proc_params)
+ return SKS_BAD_PARAM;
+
+ serialargs_init(&args, proc_params->data, proc_params->size);
+
+ rv = serialargs_get(&args, &ulIvLen, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get_ptr(&args, &pIv, ulIvLen);
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get(&args, &ulAADLen, sizeof(uint32_t));
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get_ptr(&args, &pAAD, ulAADLen);
+ if (rv)
+ goto bail;
+
+ rv = serialargs_get(&args, &ulTagBits, sizeof(uint8_t));
+ if (rv)
+ goto bail;
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ // Get key
+ rv = get_symmetric_key_from_attribute(key, _ptr);
+ if(rv != SKS_OK)
+ return rv;
+
+ /* H = ECB(0^128) */
+ SKS_HSM_DEBUG("-> H = ECB(0^128)\r\n");
+
+ _job.inputPtr = org_0;
+ _job.inputLength = 16;
+ _job.outputPtr = H;
+ _job.outputLength = 16;
+
+ _job.service = CRYPTO_ENCRYPT;
+ _job.family = CRYPTO_ALGOFAM_AES;
+ _job.mode = CRYPTO_ALGOMODE_ECB;
+ _job.operation_mode = CRYPTO_OPERATIONMODE_START;
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len * 8;
+
+ Send_job(&_job);
+
+ /* calculate_j0 */
+ SKS_HSM_DEBUG("-> Calculate j0 \r\n");
+ aes_gcm_calculate_j0(H, pIv, ulIvLen, J0);
+// __SHOW_VAL("J0", J0, 16);
+
+ /* calculate S of add data*/
+ ghash(H, pAAD, ulAADLen, S);
+
+ memcpy(_ptr->H, H, 16);
+ memcpy(_ptr->S, S, 16);
+ memcpy(_ptr->J0, J0, 16);
+ inc32(J0, 1);
+ memcpy(_ptr->CTR, J0, 16);
+ _ptr->add_len = ulAADLen;
+ _ptr->total_len = 0;
+
+ session->processing->mtk_hsm_handle = _ptr;
+
+bail:
+ return SKS_OK;
+
+}
+
+uint32_t mtk_HMAC_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key)
+{
+ MTK_HSM_State *_ptr = NULL;
+ uint32_t rv = 0;
+
+ if ((session == NULL) || (proc_params == NULL))
+ return SKS_BAD_PARAM;
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ memset(_ptr->SHA_IV, 0, SHA_MAX_OUTPUT_SIZE);
+ memset(_ptr->SHA_buf, 0, SHA_MAX_BLOCK_SIZE);
+ _ptr->SHA_remain_len = 0;
+ _ptr->isFirstUpdate = true;
+
+ // Get key
+ rv = get_symmetric_key_from_attribute(key, _ptr);
+ if(rv != SKS_OK)
+ return rv;
+
+ session->processing->mtk_hsm_handle = _ptr;
+
+ return SKS_OK;
+}
+
+uint32_t mtk_AES_CMAC_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key)
+{
+ MTK_HSM_State *_ptr = NULL;
+ uint32_t rv = 0;
+
+ if ((session == NULL) || (proc_params == NULL))
+ return SKS_BAD_PARAM;
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ memset(_ptr->CMAC_Buf, 0, 16);
+ _ptr->isFirstUpdate = true;
+
+ // Get key
+ rv = get_symmetric_key_from_attribute(key, _ptr);
+ if(rv != SKS_OK)
+ return rv;
+
+ session->processing->mtk_hsm_handle = _ptr;
+
+ return SKS_OK;
+}
+
+uint32_t mtk_SHA_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params)
+{
+ MTK_HSM_State *_ptr = NULL;
+
+ if ((session == NULL) || (proc_params == NULL))
+ return SKS_BAD_PARAM;
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ memset(_ptr->SHA_IV, 0, SHA_MAX_OUTPUT_SIZE);
+ memset(_ptr->SHA_buf, 0, SHA_MAX_BLOCK_SIZE);
+ _ptr->SHA_remain_len = 0;
+ _ptr->isFirstUpdate = true;
+
+ session->processing->mtk_hsm_handle = _ptr;
+
+ return SKS_OK;
+}
+
+uint32_t mtk_ECDSA_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key)
+{
+ MTK_HSM_State *_ptr = NULL;
+ int key_id = 0;
+ int key_id_size = sizeof(key_id);
+ int key_len = 0;
+ int key_len_size = sizeof(key_len);
+ uint32_t rv = 0;
+
+ if ((session == NULL) || (proc_params == NULL))
+ return SKS_BAD_PARAM;
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ // Get key
+ rv = get_attribute(key->attributes, SKS_CKA_HSM_KEY_ID, &key_id, &key_id_size);
+ rv = get_attribute(key->attributes, SKS_CKA_HSM_KEY_LEN, &key_len, &key_len_size);
+
+ session->processing->mtk_hsm_handle = _ptr;
+ session->processing->mtk_hsm_handle->key1_id = key_id;
+ session->processing->mtk_hsm_handle->key1_len = key_len;
+
+ return SKS_OK;
+}
+
+uint32_t mtk_ECDSA_SHA_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key)
+{
+ MTK_HSM_State *_ptr = NULL;
+ int key_id = 0;
+ int key_id_size = sizeof(key_id);
+ int key_len = 0;
+ int key_len_size = sizeof(key_len);
+ uint32_t rv = 0;
+
+ if ((session == NULL) || (proc_params == NULL))
+ return SKS_BAD_PARAM;
+
+ _ptr = TEE_Malloc(sizeof(MTK_HSM_State), TEE_MALLOC_FILL_ZERO);
+ if (!_ptr)
+ return SKS_MEMORY;
+
+ memset(_ptr->SHA_IV, 0, SHA_MAX_OUTPUT_SIZE);
+ memset(_ptr->SHA_buf, 0, SHA_MAX_BLOCK_SIZE);
+ _ptr->SHA_remain_len = 0;
+ _ptr->isFirstUpdate = true;
+
+ // Get key
+ rv = get_attribute(key->attributes, SKS_CKA_HSM_KEY_ID, &key_id, &key_id_size);
+ rv = get_attribute(key->attributes, SKS_CKA_HSM_KEY_LEN, &key_len, &key_len_size);
+
+ session->processing->mtk_hsm_handle = _ptr;
+ session->processing->mtk_hsm_handle->key1_id = key_id;
+ session->processing->mtk_hsm_handle->key1_len = key_len;
+
+ return SKS_OK;
+}
+
+enum Crypto_OperationModeType _Step_to_OPmode(enum processing_step step, uint8_t isFirstUpdate)
+{
+ switch (step)
+ {
+ case SKS_FUNC_STEP_ONESHOT:
+ return CRYPTO_OPERATIONMODE_SINGLECALL;
+
+ case SKS_FUNC_STEP_UPDATE:
+ if (isFirstUpdate == true)
+ return CRYPTO_OPERATIONMODE_START;
+ else
+ return CRYPTO_OPERATIONMODE_UPDATE;
+
+ case SKS_FUNC_STEP_FINAL:
+ return CRYPTO_OPERATIONMODE_FINISH;
+
+ default:
+ return CRYPTO_OPERATIONMODE_INVALID;
+ }
+}
+
+uint32_t mtk_AES_ECB_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ job_struct _job = {0};
+
+ if (step == SKS_FUNC_STEP_FINAL)
+ return SKS_OK;
+
+ if ((session == NULL) || (out == NULL))
+ return SKS_BAD_PARAM;
+
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+
+ _job.outputPtr = out ? (uint8_t *)out->memref.buffer : NULL;
+ _job.outputLength = out ? out->memref.size : 0;
+
+ if (function == SKS_FUNCTION_ENCRYPT)
+ _job.service = CRYPTO_ENCRYPT;
+ else // SKS_FUNCTION_DECRYPT
+ _job.service = CRYPTO_DECRYPT;
+
+ _job.family = CRYPTO_ALGOFAM_AES;
+ _job.mode = CRYPTO_ALGOMODE_ECB;
+ _job.operation_mode = CRYPTO_OPERATIONMODE_START;
+
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len * 8;
+
+
+ SKS_HSM_DEBUG(" ==> _job.inputLength: %d\n", _job.inputLength);
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+
+ Send_job(&_job);
+
+ return SKS_OK;
+}
+
+uint32_t mtk_AES_CBC_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ uint8_t next_IV[16] = {0}; // Used by decryption
+ job_struct _job = {0};
+ uint8_t *in_buf = NULL;
+ uint8_t *out_buf = NULL;
+
+ if (step == SKS_FUNC_STEP_FINAL)
+ return SKS_OK;
+
+ if ((session == NULL) || (out == NULL))
+ return SKS_BAD_PARAM;
+
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+ _job.secondaryInputPtr = (uint8_t *)_ptr->CBC_IV;
+ _job.secondaryInputLength = 16;
+
+ _job.outputPtr = out ? (uint8_t *)out->memref.buffer : NULL;
+ _job.outputLength = out ? out->memref.size : 0;
+ if (function == SKS_FUNCTION_ENCRYPT)
+ _job.service = CRYPTO_ENCRYPT;
+ else // SKS_FUNCTION_DECRYPT
+ _job.service = CRYPTO_DECRYPT;
+
+ _job.family = CRYPTO_ALGOFAM_AES;
+ _job.mode = CRYPTO_ALGOMODE_CBC;
+ _job.operation_mode = CRYPTO_OPERATIONMODE_START;
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len * 8;
+
+ SKS_HSM_DEBUG(" ==> _job.inputLength: %d\n", _job.inputLength);
+ SKS_HSM_DEBUG(" ==> _job.secondaryInputLength: %d\n", _job.secondaryInputLength);
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+
+ Send_job(&_job);
+
+ in_buf = (uint8_t *)_job.inputPtr;
+ out_buf = (uint8_t *)_job.outputPtr;
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ // Update IV[]
+ for (int i = 16; i >= 1; i--)
+ {
+ if (function == SKS_FUNCTION_ENCRYPT)
+ _ptr->CBC_IV[16 - i] = out_buf[_job.outputLength - i];
+ else
+ _ptr->CBC_IV[16 - i] = in_buf[_job.outputLength - i];
+ }
+ }
+
+ return SKS_OK;
+}
+
+uint32_t mtk_AES_CTR_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ job_struct _job = {0};
+
+ if (step == SKS_FUNC_STEP_FINAL)
+ return SKS_OK;
+
+ if ((session == NULL) || (in == NULL) || (out == NULL))
+ return SKS_BAD_PARAM;
+
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+ _job.secondaryInputPtr = (uint8_t *)_ptr->CTR;
+ _job.secondaryInputLength = 16;
+
+ _job.outputPtr = out ? (uint8_t *)out->memref.buffer : NULL;
+ _job.outputLength = out ? out->memref.size : 0;
+ if (function == SKS_FUNCTION_ENCRYPT)
+ _job.service = CRYPTO_ENCRYPT;
+ else // SKS_FUNCTION_DECRYPT
+ _job.service = CRYPTO_DECRYPT;
+
+ _job.family = CRYPTO_ALGOFAM_AES;
+ _job.mode = CRYPTO_ALGOMODE_CTR;
+ _job.operation_mode = CRYPTO_OPERATIONMODE_START;
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len * 8;
+
+
+ SKS_HSM_DEBUG(" ==> _job.inputLength: %d\n", _job.inputLength);
+ SKS_HSM_DEBUG(" ==> _job.secondaryInputLength: %d\n", _job.secondaryInputLength);
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+
+ Send_job(&_job);
+
+ // Update CTR ! _ptr->CTR[] += (_job.inputLength / 16);
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ // Update CTR !!!!
+ inc32(_ptr->CTR, (_job.inputLength / 16));
+ }
+
+ return SKS_OK;
+}
+
+uint32_t mtk_AES_GCM_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ uint8_t tmp_S[64] = {0};
+ uint8_t len_buf[16] = {0};
+ job_struct _job = {0};
+
+ SKS_HSM_DEBUG(" mtk_AES_GCM_step!! function: %d, step: %d \n", function, step);
+
+ memcpy(tmp_S, _ptr->S, 16);
+
+ if (step != SKS_FUNC_STEP_FINAL)
+ {
+ _ptr->total_len += in->memref.size;
+
+ if (function == SKS_FUNCTION_DECRYPT) // Hash before decrypt
+ {
+ ghash(_ptr->H, in->memref.buffer, in->memref.size, tmp_S);
+// __SHOW_VAL("Ghash Decrypt input", out->memref.buffer, in->memref.size);
+// __SHOW_VAL("Decrypt S", tmp_S, 16);
+ }
+
+ mtk_AES_CTR_step(session, in, out, function, step);
+
+ if (function == SKS_FUNCTION_ENCRYPT) // Hash after encrypt
+ {
+ ghash(_ptr->H, out->memref.buffer, in->memref.size, tmp_S);
+// __SHOW_VAL("Ghash Encrypt input", out->memref.buffer, in->memref.size);
+// __SHOW_VAL("Encrypt S", tmp_S, 16);
+ }
+ }
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ memcpy(_ptr->S, tmp_S, 16);
+ }
+ else // (step == SKS_FUNC_STEP_FINAL) or (step == SKS_FUNC_STEP_ONESHOT)
+ {
+ PUT_BE64(len_buf, (_ptr->add_len) * 8);
+ PUT_BE64(len_buf + 8, _ptr->total_len * 8);
+ ghash(_ptr->H, len_buf, sizeof(len_buf), tmp_S);
+
+ /* T = MSB_t(GCTR_K(J_0, S)) */
+ _job.inputPtr = tmp_S;
+ _job.inputLength = 16;
+ _job.secondaryInputPtr = _ptr->J0;
+ _job.secondaryInputLength = 16;
+ _job.outputPtr = len_buf;
+ _job.outputLength = 16;
+
+ _job.service = CRYPTO_ENCRYPT;
+ _job.family = CRYPTO_ALGOFAM_AES;
+ _job.mode = CRYPTO_ALGOMODE_CTR;
+ _job.operation_mode = CRYPTO_OPERATIONMODE_START;
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len * 8;
+
+ Send_job(&_job);
+
+ __SHOW_VAL("Fianl tag", len_buf, 16);
+
+ if (step == SKS_FUNC_STEP_ONESHOT)
+ memcpy(&out->memref.buffer[out->memref.size - 16], len_buf, 16);
+ else
+ memcpy(out->memref.buffer, len_buf, 16);
+
+ }
+
+ return SKS_OK;
+}
+
+uint32_t mtk_AES_CMAC_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ job_struct _job = {0};
+ uint8_t veri_buf[64] = {0};
+ uint8_t _buf[16] = {0};
+ uint8_t *verify_buf = NULL;
+ uint8_t *out_buf = NULL;
+
+ if ((session == NULL))
+ return SKS_BAD_PARAM;
+
+ if (step == SKS_FUNC_STEP_ONESHOT)
+ {
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+ }
+ else if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+
+ if (_ptr->isFirstUpdate == true)
+ {
+ memcpy(_ptr->CMAC_Buf, &((uint8_t *)_job.inputPtr)[_job.inputLength - 16], 16);
+ _job.inputLength -= 16;
+
+ if (_job.inputLength == 0)
+ return SKS_OK;
+ }
+ else
+ {
+ memcpy(_buf, &((uint8_t *)_job.inputPtr)[_job.inputLength - 16], 16);
+
+ if (_job.inputLength > 16)
+ {
+ for (int i = _job.inputLength; i >= 16; i-- )
+ ((uint8_t *)_job.inputPtr)[i] = ((uint8_t *)_job.inputPtr)[i - 16];
+ }
+
+ memcpy((uint8_t *)_job.inputPtr, _ptr->CMAC_Buf, 16);
+ memcpy(_ptr->CMAC_Buf, _buf, 16);
+ }
+ }
+ else // (step == SKS_FUNC_STEP_FINAL)
+ {
+ _job.inputPtr = _ptr->CMAC_Buf;
+ _job.inputLength = 16;
+ }
+
+
+ _job.secondaryInputPtr = (uint8_t *)_ptr->CBC_IV;
+ _job.secondaryInputLength = 16;
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ _job.outputPtr = veri_buf;
+ }
+ else
+ {
+ if (function == SKS_FUNCTION_VERIFY)
+ _job.outputPtr = veri_buf;
+ else
+ _job.outputPtr = inout ? (uint8_t *)inout->memref.buffer : NULL;
+ }
+ _job.outputLength = 16;
+
+ _job.service = CRYPTO_MACGENERATE; // No matter the function is sign or verify, HSM do the same thing.
+ _job.family = CRYPTO_ALGOFAM_AES;
+ _job.mode = CRYPTO_ALGOMODE_CMAC;
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len * 8;
+ SKS_HSM_DEBUG(" ==> _job.keyLength: %d\n", _job.keyLength);
+
+
+ _job.operation_mode = _Step_to_OPmode(step, _ptr->isFirstUpdate);
+ SKS_HSM_DEBUG(" step: %d --> op_mode: %d \n", step, _job.operation_mode);
+
+ SKS_HSM_DEBUG(" ==> _job.inputLength: %d\n", _job.inputLength);
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+
+ Send_job(&_job);
+
+ if (step == SKS_FUNC_STEP_ONESHOT)
+ verify_buf = inout ? (uint8_t *)inout->memref.buffer : NULL;
+ else
+ verify_buf = in ? (uint8_t *)in->memref.buffer : NULL;
+
+ out_buf = (uint8_t *)_job.outputPtr;
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ // Update IV[]
+ memcpy(_ptr->CBC_IV, out_buf, 16);
+// __SHOW_VAL("CMAC Updated IV[]", _ptr->CBC_IV, 16);
+ }
+ else
+ {
+ if (function == SKS_FUNCTION_VERIFY)
+ {
+ if (memcmp(verify_buf, out_buf, _job.outputLength) != 0)
+ {
+ SKS_HSM_ERROR(" CMAC%d verify ERROR!! \n", _job.keyLength);
+ return SKS_ERROR;
+ }
+ }
+ }
+
+ if (_ptr->isFirstUpdate == true)
+ _ptr->isFirstUpdate = false;
+
+ return SKS_OK;
+}
+
+static uint32_t _merge_remain_data(TEE_Param *in, TEE_Param *new_in, MTK_HSM_State *mtk_ptr, uint32_t _block_size)
+{
+ uint8_t *in_buf = (uint8_t *)in->memref.buffer;
+ uint32_t in_size = in->memref.size;
+
+ uint32_t rlen = mtk_ptr->SHA_remain_len;
+ uint32_t merged_len = in_size + rlen;
+
+ if (merged_len < _block_size)
+ {
+ memcpy(&mtk_ptr->SHA_buf[rlen], in_buf, in_size);
+ mtk_ptr->SHA_remain_len = merged_len;
+
+ SKS_HSM_DEBUG(" ==> No copy, new rlen: %d \n", mtk_ptr->SHA_remain_len);
+ return SKS_OK;
+ }
+
+ if (rlen != 0)
+ {
+ new_in->memref.buffer = TEE_Malloc(merged_len, TEE_MALLOC_FILL_ZERO);
+ if (!new_in->memref.buffer)
+ {
+ SKS_HSM_ERROR(" %s [%d] Memory allocate fail!! \n", __FUNCTION__, __LINE__);
+ return SKS_MEMORY;
+ }
+
+ memcpy(new_in->memref.buffer, mtk_ptr->SHA_buf, rlen);
+ memcpy((&new_in->memref.buffer[rlen]), in_buf, in_size);
+ }
+
+ rlen = merged_len % _block_size;
+ in_size = merged_len - rlen;
+
+ if (new_in->memref.buffer != NULL)
+ memcpy(mtk_ptr->SHA_buf, &new_in->memref.buffer[in_size], rlen);
+ else
+ memcpy(mtk_ptr->SHA_buf, &in_buf[in_size], rlen);
+
+ new_in->memref.size = in_size;
+ mtk_ptr->SHA_remain_len = rlen;
+ SKS_HSM_DEBUG(" ==> new in_size: %d \n", new_in->memref.size);
+ SKS_HSM_DEBUG(" ==> new rlen: %d \n", mtk_ptr->SHA_remain_len);
+
+ __SHOW_VAL("Remain data", mtk_ptr->SHA_buf, mtk_ptr->SHA_remain_len);
+
+ return SKS_OK;
+
+}
+
+#define SHA_MAX_OUTPUT_SIZE (64)
+uint32_t mtk_SHA_step(uint32_t mecha_type,
+ struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+
+ job_struct _job = {0};
+ uint8_t _block_size = 0;
+ uint8_t tmp_SHA_block[SHA_MAX_OUTPUT_SIZE] = {0};
+
+ TEE_Param new_in_body = {0};
+ uint8_t *out_buf = NULL;
+
+ switch (mecha_type)
+ {
+ case SKS_CKM_MTK_HSM_SHA1:
+ _job.family = CRYPTO_ALGOFAM_SHA1;
+ _block_size = 64;
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA224:
+ _job.family = CRYPTO_ALGOFAM_SHA2_224;
+ _block_size = 64;
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA256:
+ _job.family = CRYPTO_ALGOFAM_SHA2_256;
+ _block_size = 64;
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA384:
+ _job.family = CRYPTO_ALGOFAM_SHA2_384;
+ _block_size = 128;
+ break;
+
+ case SKS_CKM_MTK_HSM_SHA512:
+ _job.family = CRYPTO_ALGOFAM_SHA2_512;
+ _block_size = 128;
+ break;
+
+ default:
+ return SKS_BAD_PARAM;
+ break;
+ }
+
+ // Process the data left last time that is not block size alignment.
+ if (step == SKS_FUNC_STEP_ONESHOT)
+ {
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+ }
+ else if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ if (_merge_remain_data(in, &new_in_body, _ptr, _block_size) != SKS_OK)
+ return SKS_MEMORY;
+
+ if (new_in_body.memref.size == 0)
+ {
+ return SKS_OK;
+ }
+
+ if (new_in_body.memref.buffer == NULL)
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ else
+ _job.inputPtr = new_in_body.memref.buffer;
+
+ _job.inputLength = new_in_body.memref.size;
+ }
+ else
+ {
+ if (_ptr->SHA_remain_len != 0)
+ {
+ _job.inputPtr = _ptr->SHA_buf;
+ _job.inputLength = _ptr->SHA_remain_len;
+ }
+ else
+ {
+ _job.inputPtr = NULL;
+ _job.inputLength = 0;
+ }
+ }
+
+ _job.secondaryInputPtr = (uint8_t *)_ptr->SHA_IV;
+ _job.secondaryInputLength = _block_size / 2;
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ _job.outputPtr = tmp_SHA_block;
+ _job.outputLength = _block_size / 2;
+ }
+ else
+ {
+ _job.outputPtr = out ? (uint8_t *)out->memref.buffer : NULL;
+ _job.outputLength = out ? out->memref.size : 0;
+ }
+
+ _job.service = CRYPTO_HASH;
+ _job.mode = CRYPTO_ALGOMODE_NOT_SET;
+
+ _job.cryptoKeyId = 0xFF;
+ _job.keyLength = 0;
+
+ _job.operation_mode = _Step_to_OPmode(step, _ptr->isFirstUpdate);
+
+ SKS_HSM_DEBUG(" ==> _job.secondaryInputLength: %d\n", _job.secondaryInputLength);
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+
+ Send_job(&_job);
+
+ out_buf = (uint8_t *)_job.outputPtr;
+
+ __SHOW_VAL("out_buf", out_buf, 32);
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ memcpy(_ptr->SHA_IV, out_buf, _job.outputLength); // Update SHA_IV[]
+
+ if (_ptr->isFirstUpdate == true)
+ _ptr->isFirstUpdate = false;
+
+ if (new_in_body.memref.buffer != NULL)
+ TEE_Free(new_in_body.memref.buffer);
+
+ return SKS_OK;
+}
+
+uint32_t mtk_SHA256_HMAC_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ uint8_t *verify_buf = NULL;
+ uint8_t *out_buf = NULL;
+ job_struct _job = {0};
+ uint8_t _block_size = 64;
+ uint8_t veri_buf[64] = {0};
+
+ TEE_Param new_in_body = {0};
+
+ if ((session == NULL))
+ return SKS_BAD_PARAM;
+
+ // Process the data left last time that is not block size alignment.
+ if (step == SKS_FUNC_STEP_ONESHOT)
+ {
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+ }
+ else if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ if (_merge_remain_data(in, &new_in_body, _ptr, _block_size) != SKS_OK)
+ return SKS_MEMORY;
+
+ if (new_in_body.memref.size == 0)
+ {
+ return SKS_OK;
+ }
+
+ if (new_in_body.memref.buffer == NULL)
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ else
+ _job.inputPtr = new_in_body.memref.buffer;
+
+ _job.inputLength = new_in_body.memref.size;
+ }
+ else
+ {
+ if (_ptr->SHA_remain_len != 0)
+ {
+ _job.inputPtr = _ptr->SHA_buf;
+ _job.inputLength = _ptr->SHA_remain_len;
+ }
+ else
+ {
+ _job.inputPtr = NULL;
+ _job.inputLength = 0;
+ }
+ }
+
+ _job.secondaryInputPtr = (uint8_t *)_ptr->SHA_IV;
+ _job.secondaryInputLength = 32;
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ _job.outputPtr = veri_buf;
+ _job.outputLength = _block_size / 2;
+ }
+ else
+ {
+ if (function == SKS_FUNCTION_VERIFY)
+ _job.outputPtr = veri_buf;
+ else
+ _job.outputPtr = inout ? (uint8_t *)inout->memref.buffer : NULL;
+
+ _job.outputLength = 32;
+ }
+
+ _job.service = CRYPTO_MACGENERATE; // No matter the function is sign or verify, HSM do the same thing.
+ _job.family = CRYPTO_ALGOFAM_SHA2_256;
+ _job.mode = CRYPTO_ALGOMODE_HMAC;
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len * 8;
+
+ _job.operation_mode = _Step_to_OPmode(step, _ptr->isFirstUpdate);
+
+ SKS_HSM_DEBUG(" ==> _job.inputLength: %d\n", _job.inputLength);
+ SKS_HSM_DEBUG(" ==> _job.secondaryInputLength: %d\n", _job.secondaryInputLength);
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+
+ Send_job(&_job);
+
+ if (step == SKS_FUNC_STEP_ONESHOT)
+ verify_buf = inout ? (uint8_t *)inout->memref.buffer : NULL;
+ else
+ verify_buf = in ? (uint8_t *)in->memref.buffer : NULL;
+
+ out_buf = (uint8_t *)_job.outputPtr;
+
+ __SHOW_VAL("out_buf", out_buf, 32);
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ // Update SHA_IV[]
+ memcpy(_ptr->SHA_IV, out_buf, 32);
+ }
+ else
+ {
+ if (function == SKS_FUNCTION_VERIFY)
+ {
+ __SHOW_VAL("Verification out_buf", verify_buf, _job.outputLength);
+ if (memcmp(verify_buf, out_buf, _job.outputLength) != 0)
+ {
+ SKS_HSM_ERROR(" HMAC256 verify ERROR!! \n");
+ return SKS_ERROR;
+ }
+ }
+ }
+
+ if (_ptr->isFirstUpdate == true)
+ _ptr->isFirstUpdate = false;
+
+ if (new_in_body.memref.buffer != NULL)
+ TEE_Free(new_in_body.memref.buffer);
+
+ return SKS_OK;
+}
+
+uint32_t mtk_SHA384_HMAC_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ job_struct _job = {0};
+ uint8_t _block_size = 128;
+ uint8_t veri_buf[64] = {0};
+
+ TEE_Param new_in_body = {0};
+ uint8_t *verify_buf = NULL;
+ uint8_t *out_buf = NULL;
+
+ if ((session == NULL))
+ return SKS_BAD_PARAM;
+
+ // Process the data left last time that is not block size alignment.
+ if (step == SKS_FUNC_STEP_ONESHOT)
+ {
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+ }
+ else if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ if (_merge_remain_data(in, &new_in_body, _ptr, _block_size) != SKS_OK)
+ return SKS_MEMORY;
+
+ if (new_in_body.memref.size == 0)
+ {
+ return SKS_OK;
+ }
+
+ if (new_in_body.memref.buffer == NULL)
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ else
+ _job.inputPtr = new_in_body.memref.buffer;
+
+ _job.inputLength = new_in_body.memref.size;
+ }
+ else
+ {
+ if (_ptr->SHA_remain_len != 0)
+ {
+ _job.inputPtr = _ptr->SHA_buf;
+ _job.inputLength = _ptr->SHA_remain_len;
+ }
+ else
+ {
+ _job.inputPtr = NULL;
+ _job.inputLength = 0;
+ }
+ }
+
+ _job.secondaryInputPtr = (uint8_t *)_ptr->SHA_IV;
+ _job.secondaryInputLength = 64; // A specific length of HMAC-384
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ _job.outputPtr = veri_buf;
+ _job.outputLength = _block_size / 2;
+ }
+ else
+ {
+ if (function == SKS_FUNCTION_VERIFY)
+ _job.outputPtr = veri_buf;
+ else
+ _job.outputPtr = inout ? (uint8_t *)inout->memref.buffer : NULL;
+
+ _job.outputLength = 48;
+ }
+
+ _job.service = CRYPTO_MACGENERATE; // No matter the function is sign or verify, HSM do the same thing.
+ _job.family = CRYPTO_ALGOFAM_SHA2_384;
+ _job.mode = CRYPTO_ALGOMODE_HMAC;
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len * 8;
+
+ _job.operation_mode = _Step_to_OPmode(step, _ptr->isFirstUpdate);
+
+ SKS_HSM_DEBUG(" ==> _job.inputLength: %d\n", _job.inputLength);
+ SKS_HSM_DEBUG(" ==> _job.secondaryInputLength: %d\n", _job.secondaryInputLength);
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+
+ Send_job(&_job);
+
+ if (step == SKS_FUNC_STEP_ONESHOT)
+ verify_buf = inout ? (uint8_t *)inout->memref.buffer : NULL;
+ else
+ verify_buf = in ? (uint8_t *)in->memref.buffer : NULL;
+
+ out_buf = (uint8_t *)_job.outputPtr;
+
+ __SHOW_VAL("out_buf", out_buf, _job.outputLength);
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ {
+ // Update SHA_IV[]
+ memcpy(_ptr->SHA_IV, out_buf, _job.outputLength);
+ }
+ else
+ {
+ if (function == SKS_FUNCTION_VERIFY)
+ {
+ __SHOW_VAL("Verification out_buf", verify_buf, _job.outputLength);
+ if (memcmp(verify_buf, out_buf, _job.outputLength) != 0)
+ {
+ SKS_HSM_ERROR(" HMAC384 verify ERROR!! \n");
+ return SKS_ERROR;
+ }
+ }
+ }
+
+ if (_ptr->isFirstUpdate == true)
+ _ptr->isFirstUpdate = false;
+
+ if (new_in_body.memref.buffer != NULL)
+ TEE_Free(new_in_body.memref.buffer);
+
+ return SKS_OK;
+}
+
+uint32_t mtk_ECDSA_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ job_struct _job = {0};
+ uint8_t r[64] = {0};
+ uint8_t s[64] = {0};
+ uint8_t *out_buf = NULL;
+ uint8_t rs_len = 0;
+
+ if ((session == NULL) || (in == NULL))
+ return SKS_BAD_PARAM;
+
+ _job.inputPtr = in ? (uint8_t *)in->memref.buffer : NULL;
+ _job.inputLength = in ? in->memref.size : 0;
+
+ if (function == SKS_FUNCTION_SIGN)
+ {
+ _job.outputPtr = r;
+ _job.outputLength = inout ? (inout->memref.size / 2): 0;
+ _job.secondaryOutputPtr = s;
+ _job.secondaryOutputLength = inout ? (inout->memref.size / 2): 0;
+ }
+ else // (function == SKS_FUNCTION_VERIFY)
+ {
+ uint8_t rs_len = inout ? (inout->memref.size / 2): 0;
+ uint8_t *in_buf2 = inout ? (uint8_t *)inout->memref.buffer : NULL;
+ memcpy(r, in_buf2, rs_len);
+ memcpy(s, &in_buf2[rs_len], rs_len);
+
+ _job.secondaryInputPtr = r;
+ _job.secondaryInputLength = rs_len;
+ _job.tertiaryInputPtr = s;
+ _job.tertiaryInputLength = rs_len;
+ }
+
+ if (function == SKS_FUNCTION_SIGN)
+ _job.service = CRYPTO_SIGNATUREGENERATE;
+ else
+ _job.service = CRYPTO_SIGNATUREVERIFY;
+
+ _job.family = CRYPTO_ALGOFAM_ECCNIST;
+ _job.mode = CRYPTO_ALGOMODE_NOT_SET;
+
+ _job.cryptoKeyId = _ptr->key1_id;
+ _job.keyLength = _ptr->key1_len* 8;
+
+ _job.operation_mode = _Step_to_OPmode(step, _ptr->isFirstUpdate);
+
+ SKS_HSM_DEBUG(" ==> _job.inputLength: %d\n", _job.inputLength);
+ if (function == SKS_FUNCTION_SIGN)
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+ else
+ SKS_HSM_DEBUG(" ==> _job.secondaryInputLength: %d\n", _job.secondaryInputLength);
+
+
+ Send_job(&_job);
+
+ out_buf = inout ? (uint8_t *)inout->memref.buffer : NULL;
+ rs_len = _job.outputLength;
+
+ __SHOW_VAL("r", r, rs_len);
+ __SHOW_VAL("s", s, rs_len);
+
+ if (function == SKS_FUNCTION_SIGN)
+ {
+ // Merge 2 output buffer into 1
+ memcpy(out_buf, r, rs_len);
+ memcpy(&out_buf[rs_len], s, rs_len);
+ }
+
+ return SKS_OK;
+}
+
+uint32_t mtk_ECDSA_SHA_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step)
+{
+ MTK_HSM_State *_ptr = session->processing->mtk_hsm_handle;
+ uint32_t mecha_type = session->processing->mecha_type;
+ uint32_t digesting_mecha_type = 0;
+ uint8_t digestedOutBuf[512] = {0};
+ uint32_t digestedDataLen = 0;
+ TEE_Param digestedOut = {0};
+
+ if ((session == NULL) || (in == NULL))
+ return SKS_BAD_PARAM;
+
+ // ASSERT SHA one-shot only
+
+ if (step != SKS_FUNC_STEP_ONESHOT)
+ {
+ SKS_HSM_ERROR(" ASSERT SHA one-shot only!! \n");
+ return SKS_BAD_PARAM;
+ }
+
+ switch (mecha_type)
+ {
+ case SKS_CKM_MTK_HSM_ECDSA_SHA224:
+ digesting_mecha_type = SKS_CKM_MTK_HSM_SHA224;
+ digestedOut.memref.size = 28;
+ break;
+
+ case SKS_CKM_MTK_HSM_ECDSA_SHA256:
+ digesting_mecha_type = SKS_CKM_MTK_HSM_SHA256;
+ digestedOut.memref.size = 32;
+ break;
+
+ case SKS_CKM_MTK_HSM_ECDSA_SHA384:
+ digesting_mecha_type = SKS_CKM_MTK_HSM_SHA384;
+ digestedOut.memref.size = 48;
+ break;
+ case SKS_CKM_MTK_HSM_ECDSA_SHA512:
+ digesting_mecha_type = SKS_CKM_MTK_HSM_SHA512;
+ digestedOut.memref.size = 64;
+ break;
+ default:
+ case SKS_CKM_MTK_HSM_ECDSA_SHA1:
+ digesting_mecha_type = SKS_CKM_MTK_HSM_SHA1;
+ digestedOut.memref.size = 20;
+ break;
+ }
+ digestedOut.memref.buffer = digestedOutBuf;
+
+ mtk_SHA_step(digesting_mecha_type, session, in, &digestedOut, function, step);
+ mtk_ECDSA_step(session, &digestedOut, inout, function, step);
+
+ return SKS_OK;
+}
+
+uint32_t mtk_generate_random(TEE_Param *out)
+{
+ job_struct _job = {0};
+
+ if (out == NULL)
+ return SKS_BAD_PARAM;
+
+ _job.outputPtr = (uint8_t *)out->memref.buffer;
+ _job.outputLength = out->memref.size;
+
+ _job.service = CRYPTO_RANDOMGENERATE;
+ _job.family = CRYPTO_ALGOFAM_RNG;
+ _job.mode = CRYPTO_ALGOMODE_NOT_SET;
+
+ SKS_HSM_DEBUG(" ==> _job.outputLength: %d\n", _job.outputLength);
+
+ Send_job(&_job);
+
+ __SHOW_VAL("TRNG val", _job.outputPtr, _job.outputLength);
+
+ return SKS_OK;
+}
+
+uint32_t mtk_dump_hsm_log(void)
+{
+ dump_hsm_log();
+
+ return 0;
+}
+
+TEE_Result Send_job(job_struct *pjob)
+{
+ TEE_TASessionHandle cryp_session;
+ TEE_Result res = TEE_SUCCESS;
+ uint32_t origin = 0;
+ TEE_Param params[4];
+ TEE_UUID uuid = PTA_MBOX_UUID;
+ int hsm_ret = -1;
+
+ uint32_t types = TEE_PARAM_TYPES( TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT);
+
+ TEE_MemFill(params, 0, sizeof(TEE_Param) * 4);
+ params[0].value.a = (uint32_t)pjob;
+ params[0].value.b = (uint32_t)sizeof(job_struct);
+ params[1].value.a = (uint32_t)&hsm_ret;
+
+ res = TEE_OpenTASession(&uuid, 0, types, params, &cryp_session,
+ &origin);
+
+ if (res != TEE_SUCCESS) {
+ SKS_HSM_ERROR("rpc - TEE_OpenTASession returned 0x%x\n",
+ (unsigned int)res);
+ return res;
+ }
+
+ res = TEE_InvokeTACommand(cryp_session, 0, PTA_CMD_HSM_SEND_JOB, types, params, &origin);
+ if (res != TEE_SUCCESS) {
+ SKS_HSM_ERROR("rpc_call_cryp - TEE_InvokeTACommand returned 0x%x\n",
+ (unsigned int)res);
+ }
+
+ TEE_CloseTASession(cryp_session);
+
+ return res;
+
+}
+
+TEE_Result dump_hsm_log(void)
+{
+ TEE_TASessionHandle cryp_session;
+ TEE_Result res = TEE_SUCCESS;
+ uint32_t origin = 0;
+ TEE_Param params[4];
+ TEE_UUID uuid = PTA_MBOX_UUID;
+ int hsm_ret = -1;
+
+ uint32_t types = TEE_PARAM_TYPES( TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT);
+
+ TEE_MemFill(params, 0, sizeof(TEE_Param) * 4);
+
+ res = TEE_OpenTASession(&uuid, 0, types, params, &cryp_session,
+ &origin);
+
+ if (res != TEE_SUCCESS) {
+ SKS_HSM_ERROR("rpc - TEE_OpenTASession returned 0x%x\n",
+ (unsigned int)res);
+ return res;
+ }
+
+ res = TEE_InvokeTACommand(cryp_session, 0, PTA_CMD_HSM_DUMP_LOG, types, params, &origin);
+ if (res != TEE_SUCCESS) {
+ SKS_HSM_ERROR("rpc_call_cryp - TEE_InvokeTACommand returned 0x%x\n",
+ (unsigned int)res);
+ }
+
+ TEE_CloseTASession(cryp_session);
+
+ return res;
+
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_hsm.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_hsm.h
new file mode 100644
index 0000000..f27b4be
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_hsm.h
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __PROCESSING_MTK_HSM_H
+#define __PROCESSING_MTK_HSM_H
+
+#include <assert.h>
+#include <sks_internal_abi.h>
+#include <sks_ta.h>
+#include <string.h>
+#include <tee_api_defines.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <util.h>
+
+#include "attributes.h"
+#include "object.h"
+#include "pkcs11_token.h"
+#include "pkcs11_attributes.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+
+#define PTA_MBOX_UUID {0x12345678, 0x1234, 0x5678, {0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89}}
+
+extern uint32_t mtk_AES_ECB_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+extern uint32_t mtk_AES_CBC_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+extern uint32_t mtk_AES_CTR_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+extern uint32_t mtk_AES_GCM_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+extern uint32_t mtk_AES_CMAC_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+extern uint32_t mtk_HMAC_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+extern uint32_t mtk_ECDSA_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+extern uint32_t mtk_SHA_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params);
+extern uint32_t mtk_ECDSA_SHA_init(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *key);
+extern uint32_t mtk_SHA_step(uint32_t mecha_type,
+ struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step);
+
+extern uint32_t mtk_AES_ECB_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step);
+extern uint32_t mtk_AES_CBC_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step);
+extern uint32_t mtk_AES_CTR_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step);
+extern uint32_t mtk_AES_GCM_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step);
+extern uint32_t mtk_AES_CMAC_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *out,
+ enum processing_func function,
+ enum processing_step step);
+extern uint32_t mtk_SHA256_HMAC_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step);
+extern uint32_t mtk_SHA384_HMAC_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step);
+extern uint32_t mtk_ECDSA_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step);
+extern uint32_t mtk_ECDSA_SHA_step(struct pkcs11_session *session,
+ TEE_Param *in, TEE_Param *inout,
+ enum processing_func function,
+ enum processing_step step);
+
+extern uint32_t mtk_generate_random(TEE_Param *out);
+
+extern uint32_t mtk_dump_hsm_log(void);
+
+#endif // __PROCESSING_MTK_HSM_H
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_key.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_key.c
new file mode 100644
index 0000000..3136a1d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_key.c
@@ -0,0 +1,902 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#include <assert.h>
+#include <sks_internal_abi.h>
+#include <sks_ta.h>
+#include <string.h>
+#include <tee_api_defines.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <util.h>
+#include <tee_api.h>
+
+#include "attributes.h"
+#include "object.h"
+#include "pkcs11_token.h"
+#include "pkcs11_attributes.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+#include "mtk_key.h"
+#include "sks_hsm_debug.h"
+
+#define KEY_TABLE_STRING "key_table"
+#define KEY_TABLE_SIZE_STRING "key_tbl_size"
+
+#define ALIGN_TO_16(x) (((x+15)>>4)<<4)
+
+static int pta_gen_sym_key(int size, int *pkey_id);
+static int pta_get_key_blob(uint8_t *dst, int size, int key_id, int algo_id, int *pblobsize);
+static int pta_get_key_table(uint8_t *dst, int size, int *ptablesize);
+static int pta_gen_key_pair(int size, int uECC_curve_id, int *pkey_id);
+static int pta_rebuild_key_table(uint8_t *buffer, int tablesize);
+static int pta_rebuild_key_blob(uint8_t *buffer, int blob_size, int key_id);
+static int pta_import_key(uint8_t *pkeybuffer, uint32_t size, int *pkeyid, int algo_id);
+static int pta_export_key(uint8_t *pblob, uint32_t blobsize, uint8_t *ppubkey, uint32_t *ppubkeylength);
+static int pta_delete_key(int key_id);
+
+static int _create_file(uint8_t *pPOName, uint32_t namelen)
+{
+ TEE_ObjectHandle ohKey = TEE_HANDLE_NULL;
+ TEE_ObjectHandle hPersistObj = TEE_HANDLE_NULL;
+ TEE_Result nResult = TEE_SUCCESS;
+
+
+ nResult = TEE_CreatePersistentObject(
+ TEE_STORAGE_PRIVATE,
+ pPOName, namelen,
+ (TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META),
+ ohKey,
+ TEE_HANDLE_NULL, 0,
+ &hPersistObj);
+
+ if (nResult != 0)
+ {
+ if (nResult != TEE_ERROR_ITEM_NOT_FOUND)
+ SKS_HSM_ERROR("TEE_CreatePersistentObject error, nResult 0x%x!!!\n", nResult);
+ return nResult;
+ }
+
+ TEE_CloseObject(hPersistObj);
+
+ return nResult;
+}
+
+static int _delete_file(uint8_t *pPOName, uint32_t namelen)
+{
+ TEE_ObjectHandle hPersistObj = TEE_HANDLE_NULL;
+ TEE_Result nResult = TEE_SUCCESS;
+
+ nResult = TEE_OpenPersistentObject(
+ TEE_STORAGE_PRIVATE,
+ pPOName, namelen,
+ TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META,
+ &hPersistObj);
+
+ if (nResult != 0)
+ {
+ if (nResult != TEE_ERROR_ITEM_NOT_FOUND)
+ SKS_HSM_ERROR("TEE_OpenPersistentObject error, nResult 0x%x!!!\n", nResult);
+ return nResult;
+ }
+
+ TEE_CloseAndDeletePersistentObject(hPersistObj);
+
+ return TEE_SUCCESS;
+
+}
+
+static int _write_file(uint8_t *pPOName, uint32_t namelen, uint8_t *Content, uint32_t size)
+{
+ TEE_ObjectHandle hPersistObj = TEE_HANDLE_NULL;
+ TEE_Result nResult = TEE_SUCCESS;
+
+ nResult = TEE_OpenPersistentObject(
+ TEE_STORAGE_PRIVATE,
+ pPOName, namelen,
+ TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META,
+ &hPersistObj);
+
+ if (nResult != 0)
+ {
+ if (nResult != TEE_ERROR_ITEM_NOT_FOUND)
+ SKS_HSM_ERROR("TEE_OpenPersistentObject error, nResult 0x%x!!!\n", nResult);
+ return nResult;
+ }
+
+ nResult = TEE_WriteObjectData(
+ hPersistObj,
+ (void*)Content,
+ size);
+
+ if (nResult != 0)
+ {
+ SKS_HSM_ERROR("TEE_WriteObjectData error, nResult 0x%x!!!\n", nResult);
+ return nResult;
+ }
+
+ TEE_CloseObject(hPersistObj);
+
+ return nResult;
+}
+static int _read_file(uint8_t *pPOName, uint32_t namelen, uint8_t *Content, uint32_t size)
+{
+ TEE_ObjectHandle hPersistObj = TEE_HANDLE_NULL;
+ TEE_Result nResult = TEE_SUCCESS;
+ uint32_t count = 0;
+ uint32_t rsize = size;
+
+ nResult = TEE_OpenPersistentObject(
+ TEE_STORAGE_PRIVATE,
+ pPOName, namelen,
+ TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META,
+ &hPersistObj);
+
+ if (nResult != 0)
+ {
+ if (nResult != TEE_ERROR_ITEM_NOT_FOUND)
+ SKS_HSM_ERROR("TEE_CreatePersistentObject error, nResult 0x%x!!!\n", nResult);
+ return nResult;
+ }
+
+ nResult = TEE_ReadObjectData(hPersistObj, Content, rsize, &count);
+ if ((rsize != count) || (nResult != 0))
+ {
+ SKS_HSM_ERROR("error rsize 0x%x, count 0x%x!!!\n", rsize, count);
+ SKS_HSM_ERROR("nResult 0x%x!!!\n", nResult);
+ TEE_CloseObject(hPersistObj);
+ return -1;
+ }
+ TEE_CloseObject(hPersistObj);
+
+ return nResult;
+}
+
+char *itoa_32(int n, char *str, int radix)
+{
+ char digit[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ char *p = str;
+ char *head = str;
+ unsigned int val;
+
+ if (str == NULL) {
+ return NULL;
+ }
+
+ if (n == 0) {
+ *p++ = '0';
+ *p = 0;
+ return str;
+ }
+
+ if (radix == 10 && n < 0)
+ val = (-n);
+ else
+ val = n;
+
+ while (val) {
+ *p++ = digit[val % radix];
+ val /= radix;
+ }
+
+ if (radix == 10 && n < 0)
+ *p++ = '-';
+ *p = 0;
+ for (--p; head < p ; ++head, --p)
+ {
+ char temp = *head;
+ *head = *p;
+ *p = temp;
+ }
+ return str;
+}
+
+static void _make_blob_filename(uint8_t *dst, int key_id)
+{
+ int8_t *prefix = "blob_";
+ int8_t strkeyid[64] = {0};
+
+ if (dst == NULL) {
+ return;
+ }
+ itoa_32(key_id, strkeyid, 16);
+
+ memcpy(dst, prefix, strlen(prefix));
+ memcpy(dst + strlen((char *)prefix), strkeyid, strlen(strkeyid));
+}
+
+static void _write_key_blob_to_storage(uint8_t *buffer, uint32_t blobsize, int key_id)
+{
+ int8_t *prefix = "blob_";
+ int8_t pPOName[128] = {0};
+ uint32_t namelen = 0;
+
+ if (buffer == NULL) {
+ return;
+ }
+ _make_blob_filename(pPOName, key_id);
+
+ namelen = strlen((char *)pPOName);
+
+ _create_file(pPOName, namelen);
+ _write_file(pPOName, namelen, buffer, blobsize);
+}
+
+
+static void _remove_key_blob_from_storage(key_id)
+{
+ int8_t *prefix = "blob_";
+ int8_t pPOName[128] = {0};
+ uint32_t namelen = 0;
+
+ _make_blob_filename(pPOName, key_id);
+
+ namelen = strlen((char *)pPOName);
+ _delete_file(pPOName, namelen);
+
+}
+
+static void _write_key_table_to_storage(uint8_t *buffer, uint32_t tablesize)
+{
+ int8_t pTableName[] = KEY_TABLE_STRING;
+ int8_t pTableSizeName[] = KEY_TABLE_SIZE_STRING;
+ uint32_t namelen = 0;
+
+ if (buffer == NULL) {
+ return;
+ }
+ namelen = strlen((char *)pTableName);
+ _create_file(pTableName, namelen);
+ _write_file(pTableName, namelen, buffer, tablesize);
+
+ namelen = strlen((char *)pTableSizeName);
+ _create_file(pTableSizeName, namelen);
+ _write_file(pTableSizeName, namelen, &tablesize, sizeof(uint32_t));
+}
+
+static void _read_key_table_size(uint32_t *ptablesize)
+{
+ int8_t pTableSizeName[128] = KEY_TABLE_SIZE_STRING;
+ uint8_t Content[4] = {0};
+ uint32_t dstsize = sizeof(Content);
+ uint32_t namelen = 0;
+
+ if (ptablesize == NULL) {
+ return;
+ }
+ namelen = strlen((char *)pTableSizeName);
+ _read_file(pTableSizeName, namelen, Content, dstsize);
+
+ *ptablesize = *((uint32_t *)Content);
+}
+
+static void _read_key_table(uint8_t *buffer, uint32_t tablesize)
+{
+ int8_t pTableName[128] = KEY_TABLE_STRING;
+ uint32_t namelen = 0;
+
+ namelen = strlen((char *)pTableName);
+ _read_file(pTableName, namelen, buffer, tablesize);
+}
+
+static void _read_key_blob(uint8_t *buffer, uint32_t buffersize, int key_id)
+{
+ int8_t pBlobName[128] = {0};
+ uint32_t namelen = 0;
+
+ _make_blob_filename(pBlobName, key_id);
+
+ namelen = strlen((char *)pBlobName);
+ _read_file(pBlobName, namelen, buffer, buffersize);
+}
+
+static int _get_key_info_in_table(key_table *ptbl, int idx, uint32_t *pkeyid, uint32_t *pkeysize)
+{
+ if (ptbl == NULL) {
+ return -1;
+ }
+ *pkeyid = ptbl->slot[idx].id;
+ *pkeysize = ptbl->slot[idx].key_w.size;
+ return 0;
+}
+
+static inline void _estimate_blob_size(uint32_t key_size, uint32_t *pblobsize)
+{
+ *pblobsize = ALIGN_TO_16(key_size) + BLOB_MAC_SIZE + BLOB_HEADER_SIZE;
+}
+
+static inline int _check_symmetric_key_size_valid(uint32_t size)
+{
+ return (size == 16) || (size == 24) || (size == 32) || (size == 48);
+}
+
+int mtk_delete_key(struct sks_object *object)
+{
+ uint8_t buffer[sizeof(key_table)] = {0};
+ int tablesize = 0;
+ uint32_t rv = 0;
+ int key_id = 0;
+ int key_id_size = sizeof(key_id);
+
+ if (object == NULL)
+ return SKS_CKR_ARGUMENTS_BAD;
+
+ rv = get_attribute(object->attributes, SKS_CKA_HSM_KEY_ID, &key_id, &key_id_size);
+ if (rv != 0) /* not mtk key object */
+ return SKS_CKR_ARGUMENTS_BAD;
+ if (pta_delete_key(key_id) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ _remove_key_blob_from_storage(key_id);
+
+ if (pta_get_key_table(buffer, sizeof(buffer), &tablesize) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ _write_key_table_to_storage(buffer, tablesize);
+
+ return TEE_SUCCESS;
+}
+
+int mtk_generate_symmetric_key(int size, int *pkeyid)
+{
+ int key_id = 0;
+ uint8_t buffer[sizeof(key_table)] = {0};
+ int blobsize = 0;
+ int tablesize = 0;
+
+ int _rv = _check_symmetric_key_size_valid(size);
+ SKS_HSM_DEBUG(" %s [%d] size: %d, rv: %d \n", __FUNCTION__, __LINE__, size, _rv);
+ if (!_check_symmetric_key_size_valid(size))
+ return TEE_ERROR_GENERIC;
+
+ if (pkeyid == NULL)
+ return TEE_ERROR_GENERIC;
+
+ if (pta_gen_sym_key(size, &key_id) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ if (pta_get_key_blob(buffer, sizeof(buffer), key_id, KEY_ALGO_ID_AES, &blobsize) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ _write_key_blob_to_storage(buffer, blobsize, key_id);
+
+ if (pta_get_key_table(buffer, sizeof(buffer), &tablesize) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ _write_key_table_to_storage(buffer, tablesize);
+
+ *pkeyid = key_id;
+
+ return TEE_SUCCESS;
+}
+
+int mtk_generate_ecc_key_pair(int size, int curve_id, int *pkeyid)
+{
+ int key_id = 0;
+ uint8_t buffer[sizeof(key_table)] = {0};
+ int blobsize = 0;
+ int tablesize = 0;
+ int uECC_curve_id = curve_id;
+
+ if (pkeyid == NULL)
+ return TEE_ERROR_GENERIC;
+
+ if (pta_gen_key_pair(size, uECC_curve_id, &key_id) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ if (pta_get_key_blob(buffer, sizeof(buffer), key_id, KEY_ALGO_ID_ECC, &blobsize) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ _write_key_blob_to_storage(buffer, blobsize, key_id);
+
+ if (pta_get_key_table(buffer, sizeof(buffer), &tablesize) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ _write_key_table_to_storage(buffer, tablesize);
+
+ *pkeyid = key_id;
+
+ return TEE_SUCCESS;
+}
+
+
+int mtk_rebuild_key_table(void)
+{
+ uint8_t *table_buffer = NULL;
+ uint8_t *blob_buffer = NULL;
+ int table = 0;
+ uint32_t tablesize = 0, blob_size = 0, key_size = 0, key_id = 0;
+ uint32_t maxblobsize = MAX_BLOB_SIZE;
+ key_table *ptable = NULL;
+
+ _read_key_table_size(&tablesize);
+
+ if (tablesize <= 0) {
+ SKS_HSM_ERROR("[%s][%d] invalid table size : %d\n", __FUNCTION__, __LINE__, tablesize);
+ goto fail;
+ }
+
+ table_buffer = TEE_Malloc(tablesize, TEE_MALLOC_FILL_ZERO);
+ if (table_buffer == NULL) {
+ SKS_HSM_ERROR("[%s][%d] allocate memory fail\n", __FUNCTION__, __LINE__);
+ goto fail;
+ }
+
+ blob_buffer = TEE_Malloc(maxblobsize, TEE_MALLOC_FILL_ZERO);
+ if (blob_buffer == NULL) {
+ SKS_HSM_ERROR("[%s][%d] allocate memory fail\n", __FUNCTION__, __LINE__);
+ goto fail;
+ }
+
+ _read_key_table(table_buffer, tablesize);
+ ptable = (key_table *)table_buffer;
+ SKS_HSM_INFO("[%s][%d] ptable->nkeys : %d\n", __FUNCTION__, __LINE__, ptable->nkeys);
+
+ /* clean garbage slot address info in table*/
+ for (int i = 0; i < ptable->nkeys; ++i) {
+ ptable->slot[i].key_w.addr32 = 0;
+ }
+
+ if (pta_rebuild_key_table(table_buffer, tablesize) != 0) {
+ SKS_HSM_ERROR("[%s][%d] rebuild key table fail!\n", __FUNCTION__, __LINE__);
+ goto fail;
+ }
+
+ /* Rebuild the key blob for each key_id in the key table*/
+ for (int i = 0; i < ptable->nkeys; ++i) {
+ memset(blob_buffer, 0, maxblobsize);
+ blob_size = key_id = key_size = 0;
+
+ _get_key_info_in_table(ptable, i, &key_id, &key_size);
+ if (key_size == 0 || key_id == 0)
+ continue;
+
+ _estimate_blob_size(key_size, &blob_size);
+ _read_key_blob(blob_buffer, blob_size, key_id);
+ pta_rebuild_key_blob(blob_buffer, blob_size, key_id);
+ }
+
+
+ if (table_buffer != NULL)
+ TEE_Free(table_buffer);
+ if (blob_buffer != NULL)
+ TEE_Free(blob_buffer);
+
+ return 0;
+
+fail:
+ if (table_buffer != NULL)
+ TEE_Free(table_buffer);
+ if (blob_buffer != NULL)
+ TEE_Free(blob_buffer);
+
+ return -1;
+}
+
+int mtk_import_key(uint8_t *pkey, uint32_t size,
+ int *pkeyid, int *pblob,
+ int *inblobsize, int algo_id)
+{
+ uint8_t buffer[sizeof(key_table)] = {0};
+ int blobsize = 0;
+ int key_id = 0;
+ int tablesize = 0;
+ int rv = 0;
+ ecc_keypair_datastruct *pecckey = NULL;
+
+ if ((pkey == NULL) || (pkeyid == NULL) || (inblobsize == NULL)) {
+ SKS_HSM_ERROR("[%s][%d] bad argument\n", __FUNCTION__, __LINE__);
+ goto fail;
+ }
+
+ switch (algo_id)
+ {
+ case KEY_ALGO_ID_ECC:
+ pecckey = (ecc_keypair_datastruct *)pkey;
+ if (pecckey->curve_id == UECC_CURVE_ID_UNSUPPORT) {
+ SKS_HSM_ERROR("[%s][%d] not support curve\n", __FUNCTION__, __LINE__);
+ goto fail;
+ }
+ break;
+ case KEY_ALGO_ID_AES:
+ if (!_check_symmetric_key_size_valid(size)) {
+ SKS_HSM_ERROR("[%s][%d] not symmetric key size (%d)\n", __FUNCTION__, __LINE__, size);
+ goto fail;
+ }
+ break;
+ default:
+ SKS_HSM_ERROR("[%s][%d] not algorithm type\n", __FUNCTION__, __LINE__);
+ break;
+ }
+
+ rv = pta_import_key(pkey, size, &key_id, algo_id);
+ if (rv != TEE_SUCCESS) {
+ SKS_HSM_ERROR("[%s][%d] import key fail (%d)\n", __FUNCTION__, __LINE__, rv);
+ goto fail;
+ }
+
+ rv = pta_get_key_blob(buffer, sizeof(buffer), key_id, algo_id, &blobsize);
+ if (rv != TEE_SUCCESS) {
+ SKS_HSM_ERROR("[%s][%d] get blob fail (%d)\n", __FUNCTION__, __LINE__, rv);
+ goto fail;
+ }
+
+ if (blobsize > *inblobsize) {
+ SKS_HSM_ERROR("[%s][%d] in buf too small (%d > %d)\n", __FUNCTION__, __LINE__, blobsize, inblobsize);
+ goto fail;
+ }
+ _write_key_blob_to_storage(buffer, blobsize, key_id);
+ memcpy(pblob, buffer, blobsize);
+ *inblobsize = blobsize;
+
+ rv = pta_get_key_table(buffer, sizeof(buffer), &tablesize);
+ if (rv != TEE_SUCCESS) {
+ SKS_HSM_ERROR("[%s][%d] get table fail (%d)\n", __FUNCTION__, __LINE__, rv);
+ goto fail;
+ }
+
+ _write_key_table_to_storage(buffer, tablesize);
+
+ *pkeyid = key_id;
+
+ return TEE_SUCCESS;
+fail:
+ return TEE_ERROR_GENERIC;
+}
+
+int mtk_export_key(uint8_t *pblob, uint32_t blobsize, uint8_t *ppubkey, uint32_t *ppubkeylength)
+{
+ int rv = 0;
+ if ((pblob == NULL) || (ppubkey == NULL) || (ppubkeylength == NULL)) {
+ SKS_HSM_ERROR("[%s][%d] bad argument\n", __FUNCTION__, __LINE__);
+ goto fail;
+ }
+
+ rv = pta_export_key(pblob, blobsize, ppubkey, ppubkeylength);
+ if (rv != TEE_SUCCESS) {
+ SKS_HSM_ERROR("[%s][%d] export key fail (%d)\n", __FUNCTION__, __LINE__, rv);
+ goto fail;
+ }
+
+ return TEE_SUCCESS;
+fail:
+ return TEE_ERROR_GENERIC;
+
+}
+
+static void _fill_pta_params(TEE_Param *params,
+ uint32_t a0, uint32_t b0,
+ uint32_t a1, uint32_t b1,
+ uint32_t a2, uint32_t b2,
+ uint32_t a3, uint32_t b3)
+{
+ TEE_MemFill(params, 0, sizeof(TEE_Param) * 4);
+
+ params[0].value.a = a0;
+ params[0].value.b = b0;
+
+ params[1].value.a = a1;
+ params[1].value.b = b1;
+
+ params[2].value.a = a2;
+ params[2].value.b = b2;
+
+ params[3].value.a = a3;
+ params[3].value.b = b3;
+}
+
+static int _transmit_to_pta(TEE_Param *params, uint32_t cmd_id)
+{
+ TEE_TASessionHandle pta_session;
+ uint32_t origin;
+ TEE_UUID uuid = PTA_MBOX_UUID;
+ TEE_Result res = TEE_SUCCESS;
+
+ uint32_t types = TEE_PARAM_TYPES( TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT
+ , TEE_PARAM_TYPE_VALUE_INPUT);
+
+ res = TEE_OpenTASession(&uuid, 0, types, params, &pta_session,
+ &origin);
+
+ if (res != TEE_SUCCESS) {
+ SKS_HSM_ERROR("rpc_sha256 - TEE_OpenTASession returned 0x%x\n",
+ (unsigned int)res);
+ return res;
+ }
+
+
+ res = TEE_InvokeTACommand(pta_session, 0, cmd_id, types, params, &origin);
+ if (res != TEE_SUCCESS) {
+ SKS_HSM_ERROR("rpc_call_cryp - TEE_InvokeTACommand returned 0x%x\n",
+ (unsigned int)res);
+ }
+
+ TEE_CloseTASession(pta_session);
+ return res;
+}
+
+static int pta_gen_key_pair(int size, int uECC_curve_id, int *pkey_id) // TODO: ADD CURVE ID
+{
+ TEE_Result res = TEE_SUCCESS;
+ TEE_Param params[4] = {0};
+
+ int hsm_ret = -1;
+ int key_id = -2;
+ int key_size = size;
+
+ if (pkey_id == NULL) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)size,
+ (uint32_t)uECC_curve_id, (uint32_t)&key_id,
+ NULL, NULL,
+ NULL, NULL);
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_GEN_KEY_PAIR);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ *pkey_id = key_id;
+
+ return hsm_ret;
+}
+
+static int pta_gen_sym_key(int size, int *pkey_id)
+{
+ TEE_Result res = TEE_SUCCESS;
+ TEE_Param params[4] = {0};
+
+ int hsm_ret = -1;
+ int key_id = -2;
+ int key_size = size;
+
+ if (pkey_id == NULL) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)&key_id,
+ (uint32_t)key_size , NULL,
+ NULL, NULL,
+ NULL, NULL);
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_GEN_SYMM_KEY);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ *pkey_id = key_id;
+
+ return hsm_ret;
+}
+
+static int pta_delete_key(int key_id)
+{
+ TEE_Result res = TEE_SUCCESS;
+ TEE_Param params[4] = {0};
+
+ int hsm_ret = -1;
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)key_id,
+ NULL , NULL,
+ NULL, NULL,
+ NULL, NULL);
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_DELETE_KEY);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ return hsm_ret;
+}
+
+static int pta_export_key(uint8_t *pblob, uint32_t blobsize, uint8_t *ppubkey, uint32_t *ppubkeylength)
+{
+ TEE_Result res;
+ TEE_Param params[4];
+
+ int hsm_ret = -1;
+
+ if ((pblob == NULL) || (ppubkey == NULL) || (ppubkeylength == NULL)) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)pblob,
+ (uint32_t)blobsize , (uint32_t)ppubkey,
+ (uint32_t)ppubkeylength, NULL,
+ NULL, NULL);
+
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_EXPORT_KEY);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ return hsm_ret;
+}
+
+static int pta_import_key(uint8_t *pkeybuffer, uint32_t size, int *pkeyid, int algo_id)
+{
+ TEE_Result res = TEE_SUCCESS;
+ TEE_Param params[4];
+
+ int hsm_ret = -1;
+ int key_id = 0;
+
+ if ((pkeybuffer == NULL) || (pkeyid == NULL)) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)pkeybuffer,
+ (uint32_t)size , (uint32_t)&key_id,
+ (uint32_t)algo_id, NULL,
+ NULL, NULL);
+
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_IMPORT_KEY);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ *pkeyid = key_id;
+
+ return hsm_ret;
+}
+
+static int pta_get_key_blob(uint8_t *dst, int size, int key_id, int algo_id, int *pblobsize)
+{
+ TEE_Result res = TEE_SUCCESS;
+ TEE_Param params[4];
+
+ int hsm_ret = -1;
+ uint32_t blobsize;
+
+ if (dst == NULL) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)key_id,
+ (uint32_t)dst , (uint32_t)size,
+ (uint32_t)algo_id, (uint32_t)&blobsize,
+ NULL, NULL);
+
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_GET_KEY_BLOB);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ *pblobsize = blobsize;
+
+ return hsm_ret;
+}
+
+static int pta_get_key_table(uint8_t *dst, int size, int *ptablesize)
+{
+ TEE_Result res = TEE_SUCCESS;
+ TEE_Param params[4];
+
+ int hsm_ret = -1;
+ uint32_t tablesize;
+
+ if (dst == NULL) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)dst,
+ (uint32_t)size , (uint32_t)&tablesize,
+ NULL, NULL,
+ NULL, NULL);
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_GET_KEY_TABLE);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ *ptablesize = tablesize;
+
+ return hsm_ret;
+}
+
+
+static int pta_rebuild_key_table(uint8_t *buffer, int tablesize)
+{
+ TEE_Result res = TEE_SUCCESS;
+ TEE_Param params[4] = {0};
+ int hsm_ret = -1;
+
+ if (buffer == NULL) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)buffer,
+ (uint32_t)tablesize , NULL,
+ NULL, NULL,
+ NULL, NULL);
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_REBUILD_KEY_TABLE);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ return hsm_ret;
+}
+
+static int pta_rebuild_key_blob(uint8_t *buffer, int blob_size, int key_id)
+{
+ TEE_Result res = TEE_SUCCESS;
+ TEE_Param params[4] = {0};
+ int hsm_ret = -1;
+
+ if (buffer == NULL) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ _fill_pta_params(params,
+ (uint32_t)&hsm_ret, (uint32_t)buffer,
+ (uint32_t)blob_size , (uint32_t)key_id,
+ NULL, NULL,
+ NULL, NULL);
+
+ res = _transmit_to_pta(params, PTA_CMD_HSM_REBUILD_KEY_BLOB);
+
+ if (res != TEE_SUCCESS) {
+ return TEE_ERROR_GENERIC;
+ }
+
+ return hsm_ret;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_key.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_key.h
new file mode 100644
index 0000000..751f5ed
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_mtk_key.h
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __PROCESSING_MTK_KEY_H
+#define __PROCESSING_MTK_KEY_H
+
+#include "object.h"
+#include "mtk_key.h"
+
+/*
+ * MTK HSM related APIs
+ */
+int mtk_generate_symmetric_key(int size, int *pkeyid);
+int mtk_generate_ecc_key_pair(int size, int curve_id, int *pkeyid);
+int mtk_rebuild_key_table(void);
+int mtk_import_key(uint8_t *pkey, uint32_t size,
+ int *pkeyid, int *pblob,
+ int *inblobsize, int algo_id);
+int mtk_export_key(uint8_t *pblob, uint32_t blobsize,
+ uint8_t *ppubkey, uint32_t *ppubkeylength);
+
+int mtk_delete_key(struct sks_object *object);
+
+
+#endif // __PROCESSING_MTK_KEY_H
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_rsa.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_rsa.c
new file mode 100644
index 0000000..eea201d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_rsa.c
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <assert.h>
+#include <compiler.h>
+#include <tee_api_defines.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include "attributes.h"
+#include "pkcs11_token.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+uint32_t sks2tee_proc_params_rsa_pss(struct active_processing *processing,
+ struct sks_attribute_head *proc_params)
+{
+ struct serialargs args;
+ uint32_t rv;
+ uint32_t data32;
+ uint32_t salt_len;
+
+ serialargs_init(&args, proc_params->data, proc_params->size);
+
+ rv = serialargs_get(&args, &data32, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &data32, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &salt_len, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ processing->extra_ctx = TEE_Malloc(sizeof(uint32_t),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!processing->extra_ctx)
+ return SKS_MEMORY;
+
+ *(uint32_t *)processing->extra_ctx = salt_len;
+
+ return SKS_OK;
+}
+
+void tee_release_rsa_pss_operation(struct active_processing *processing)
+{
+ TEE_Free(processing->extra_ctx);
+ processing->extra_ctx = NULL;
+}
+
+uint32_t sks2tee_algo_rsa_pss(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params)
+{
+ struct serialargs args;
+ uint32_t rv;
+ uint32_t hash;
+ uint32_t mgf;
+ uint32_t salt_len;
+
+ serialargs_init(&args, proc_params->data, proc_params->size);
+
+ rv = serialargs_get(&args, &hash, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &mgf, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &salt_len, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ switch (*tee_id) {
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
+ if (hash != SKS_CKM_SHA_1 || mgf != SKS_CKG_MGF1_SHA1)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ break;
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
+ if (hash != SKS_CKM_SHA224 || mgf != SKS_CKG_MGF1_SHA224)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ break;
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
+ if (hash != SKS_CKM_SHA256 || mgf != SKS_CKG_MGF1_SHA256)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ break;
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
+ if (hash != SKS_CKM_SHA384 || mgf != SKS_CKG_MGF1_SHA384)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ break;
+ case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
+ if (hash != SKS_CKM_SHA512 || mgf != SKS_CKG_MGF1_SHA512)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ break;
+ default:
+ return SKS_ERROR;
+ }
+
+ return SKS_OK;
+}
+
+// Currently unused
+uint32_t tee_init_rsa_aes_key_wrap_operation(struct active_processing *proc,
+ void *proc_params,
+ size_t params_size)
+{
+ struct serialargs args;
+ uint32_t rv;
+ uint32_t aes_bit_size;
+ uint32_t hash;
+ uint32_t mgf;
+ uint32_t source_type;
+ void *source_data;
+ uint32_t source_size;
+
+ serialargs_init(&args, proc_params, params_size);
+
+ rv = serialargs_get(&args, &aes_bit_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &hash, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &mgf, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &source_type, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &source_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get_ptr(&args, &source_data, source_size);
+ if (rv)
+ return rv;
+
+ // TODO
+ (void)proc;
+ return SKS_ERROR;
+}
+
+uint32_t sks2tee_algo_rsa_oaep(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params)
+{
+ struct serialargs args;
+ uint32_t rv;
+ uint32_t hash;
+ uint32_t mgf;
+ uint32_t source_type;
+ void *source_data;
+ uint32_t source_size;
+
+ serialargs_init(&args, proc_params->data, proc_params->size);
+
+ rv = serialargs_get(&args, &hash, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &mgf, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &source_type, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &source_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get_ptr(&args, &source_data, source_size);
+ if (rv)
+ return rv;
+
+ switch (proc_params->id) {
+ case SKS_CKM_RSA_PKCS_OAEP:
+ switch (hash) {
+ case SKS_CKM_SHA_1:
+ if (mgf != SKS_CKG_MGF1_SHA1 || source_size)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1;
+ break;
+ case SKS_CKM_SHA224:
+ if (mgf != SKS_CKG_MGF1_SHA224 || source_size)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224;
+ break;
+ case SKS_CKM_SHA256:
+ if (mgf != SKS_CKG_MGF1_SHA256 || source_size)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256;
+ break;
+ case SKS_CKM_SHA384:
+ if (mgf != SKS_CKG_MGF1_SHA384 || source_size)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384;
+ break;
+ case SKS_CKM_SHA512:
+ if (mgf != SKS_CKG_MGF1_SHA512 || source_size)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+ *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512;
+ break;
+ default:
+ EMSG("Unexpected %s (0x%" PRIx32 ")",
+ sks2str_proc(hash), hash);
+ return SKS_ERROR;
+ }
+ break;
+ default:
+ EMSG("Unexpected %s (0x%" PRIx32 ")",
+ sks2str_proc(proc_params->id), proc_params->id);
+ return SKS_ERROR;
+ }
+
+ return SKS_OK;
+}
+
+// Unused yet...
+uint32_t tee_init_rsa_oaep_operation(struct active_processing *processing,
+ void *proc_params, size_t params_size);
+
+uint32_t tee_init_rsa_oaep_operation(struct active_processing *processing,
+ void *proc_params, size_t params_size)
+{
+ struct serialargs args;
+ uint32_t rv;
+ uint32_t hash;
+ uint32_t mgf;
+ uint32_t source_type;
+ void *source_data;
+ uint32_t source_size;
+
+ serialargs_init(&args, proc_params, params_size);
+
+ rv = serialargs_get(&args, &hash, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &mgf, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &source_type, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get(&args, &source_size, sizeof(uint32_t));
+ if (rv)
+ return rv;
+
+ rv = serialargs_get_ptr(&args, &source_data, source_size);
+ if (rv)
+ return rv;
+
+ // TODO
+ (void)processing;
+ return SKS_ERROR;
+}
+
+uint32_t load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count,
+ struct sks_object *obj)
+{
+ TEE_Attribute *attrs = NULL;
+ size_t count = 0;
+ uint32_t rv = SKS_ERROR;
+
+ assert(get_type(obj->attributes) == SKS_CKK_RSA);
+
+ switch (get_class(obj->attributes)) {
+ case SKS_CKO_PUBLIC_KEY:
+ attrs = TEE_Malloc(3 * sizeof(TEE_Attribute),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!attrs)
+ return SKS_MEMORY;
+
+ if (sks2tee_load_attr(&attrs[count], TEE_ATTR_RSA_MODULUS,
+ obj, SKS_CKA_MODULUS))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_RSA_PUBLIC_EXPONENT,
+ obj, SKS_CKA_PUBLIC_EXPONENT))
+ count++;
+
+ if (count == 2)
+ rv = SKS_OK;
+
+ break;
+
+ case SKS_CKO_PRIVATE_KEY:
+ attrs = TEE_Malloc(8 * sizeof(TEE_Attribute),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!attrs)
+ return SKS_MEMORY;
+
+ if (sks2tee_load_attr(&attrs[count], TEE_ATTR_RSA_MODULUS,
+ obj, SKS_CKA_MODULUS))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_RSA_PUBLIC_EXPONENT,
+ obj, SKS_CKA_PUBLIC_EXPONENT))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_RSA_PRIVATE_EXPONENT,
+ obj, SKS_CKA_PRIVATE_EXPONENT))
+ count++;
+
+ if (count != 3)
+ break;
+
+ if (get_attribute(obj->attributes, SKS_CKA_PRIME_1,
+ NULL, NULL)) {
+ rv = SKS_OK;
+ break;
+ }
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_RSA_PRIME1,
+ obj, SKS_CKA_PRIME_1))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_RSA_PRIME2,
+ obj, SKS_CKA_PRIME_2))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_RSA_EXPONENT1,
+ obj, SKS_CKA_EXPONENT_1))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_RSA_EXPONENT2,
+ obj, SKS_CKA_EXPONENT_2))
+ count++;
+
+ if (sks2tee_load_attr(&attrs[count],
+ TEE_ATTR_RSA_COEFFICIENT,
+ obj, SKS_CKA_COEFFICIENT))
+ count++;
+
+ if (count == 8)
+ rv = SKS_OK;
+
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ if (rv == SKS_OK) {
+ *tee_attrs = attrs;
+ *tee_count = count;
+ }
+
+ return rv;
+}
+
+static uint32_t tee2sks_rsa_attributes(struct sks_attrs_head **pub_head,
+ struct sks_attrs_head **priv_head,
+ TEE_ObjectHandle tee_obj)
+{
+ uint32_t rv;
+
+ rv = tee2sks_add_attribute(pub_head, SKS_CKA_MODULUS,
+ tee_obj, TEE_ATTR_RSA_MODULUS);
+ if (rv)
+ goto bail;
+
+ if (get_attribute_ptr(*pub_head, SKS_CKA_PUBLIC_EXPONENT, NULL, NULL)) {
+ rv = tee2sks_add_attribute(pub_head,
+ SKS_CKA_PUBLIC_EXPONENT,
+ tee_obj,
+ TEE_ATTR_RSA_PUBLIC_EXPONENT);
+ if (rv)
+ goto bail;
+ }
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_MODULUS,
+ tee_obj, TEE_ATTR_RSA_MODULUS);
+ if (rv)
+ goto bail;
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_PUBLIC_EXPONENT,
+ tee_obj, TEE_ATTR_RSA_PUBLIC_EXPONENT);
+ if (rv)
+ goto bail;
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_PRIVATE_EXPONENT,
+ tee_obj, TEE_ATTR_RSA_PRIVATE_EXPONENT);
+ if (rv)
+ goto bail;
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_PRIME_1,
+ tee_obj, TEE_ATTR_RSA_PRIME1);
+ if (rv)
+ goto bail;
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_PRIME_2,
+ tee_obj, TEE_ATTR_RSA_PRIME2);
+ if (rv)
+ goto bail;
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_EXPONENT_1,
+ tee_obj, TEE_ATTR_RSA_EXPONENT1);
+ if (rv)
+ goto bail;
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_EXPONENT_2,
+ tee_obj, TEE_ATTR_RSA_EXPONENT2);
+ if (rv)
+ goto bail;
+
+ rv = tee2sks_add_attribute(priv_head, SKS_CKA_COEFFICIENT,
+ tee_obj, TEE_ATTR_RSA_COEFFICIENT);
+bail:
+ return rv;
+}
+
+uint32_t generate_rsa_keys(struct sks_attribute_head *proc_params,
+ struct sks_attrs_head **pub_head,
+ struct sks_attrs_head **priv_head)
+{
+ uint32_t rv;
+ void *a_ptr;
+ uint32_t a_size;
+ TEE_ObjectHandle tee_obj;
+ TEE_Result res;
+ uint32_t tee_size;
+ TEE_Attribute tee_attrs[1];
+ uint32_t tee_count = 0;
+
+ if (!proc_params || !*pub_head || !*priv_head) {
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ if (get_attribute_ptr(*pub_head, SKS_CKA_MODULUS_BITS,
+ &a_ptr, &a_size)) {
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ if (a_size != sizeof(uint32_t)) {
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ TEE_MemMove(&tee_size, a_ptr, sizeof(uint32_t));
+
+ rv = get_attribute_ptr(*pub_head, SKS_CKA_PUBLIC_EXPONENT,
+ &a_ptr, &a_size);
+ if (rv == SKS_OK) {
+ TEE_InitRefAttribute(&tee_attrs[tee_count],
+ TEE_ATTR_RSA_PUBLIC_EXPONENT,
+ a_ptr, a_size);
+
+ tee_count++;
+ }
+
+ if (!get_attribute(*pub_head, SKS_CKA_MODULUS, NULL, NULL) ||
+ !get_attribute(*priv_head, SKS_CKA_MODULUS, NULL, NULL) ||
+ !get_attribute(*priv_head, SKS_CKA_PUBLIC_EXPONENT, NULL, NULL) ||
+ !get_attribute(*priv_head, SKS_CKA_PRIVATE_EXPONENT, NULL, NULL) ||
+ !get_attribute(*priv_head, SKS_CKA_PRIME_1, NULL, NULL) ||
+ !get_attribute(*priv_head, SKS_CKA_PRIME_2, NULL, NULL) ||
+ !get_attribute(*priv_head, SKS_CKA_EXPONENT_1, NULL, NULL) ||
+ !get_attribute(*priv_head, SKS_CKA_EXPONENT_2, NULL, NULL) ||
+ !get_attribute(*priv_head, SKS_CKA_COEFFICIENT, NULL, NULL)) {
+ EMSG("Unexpected attribute(s) found");
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ /* Create an ECDSA TEE key: will match PKCS11 ECDSA and ECDH */
+ res = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR,
+ tee_size, &tee_obj);
+ if (res) {
+ DMSG("TEE_AllocateTransientObject failed 0x%" PRIx32, res);
+ return tee2sks_error(res);
+ }
+
+ res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE);
+ if (res) {
+ DMSG("TEE_RestrictObjectUsage1 failed 0x%" PRIx32, res);
+ rv = tee2sks_error(res);
+ goto bail;
+ }
+
+ res = TEE_GenerateKey(tee_obj, tee_size, &tee_attrs[0], tee_count);
+ if (res) {
+ DMSG("TEE_GenerateKey failed 0x%" PRIx32, res);
+ rv = tee2sks_error(res);
+ goto bail;
+ }
+
+ rv = tee2sks_rsa_attributes(pub_head, priv_head, tee_obj);
+
+bail:
+ if (tee_obj != TEE_HANDLE_NULL)
+ TEE_FreeTransientObject(tee_obj);
+
+ return rv;
+}
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_symm.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_symm.c
new file mode 100644
index 0000000..71314a3
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/processing_symm.c
@@ -0,0 +1,627 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <assert.h>
+#include <sks_internal_abi.h>
+#include <sks_ta.h>
+#include <string.h>
+#include <tee_api_defines.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <util.h>
+
+#include "attributes.h"
+#include "object.h"
+#include "pkcs11_token.h"
+#include "pkcs11_attributes.h"
+#include "processing.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+bool processing_is_tee_symm(uint32_t proc_id)
+{
+ switch (proc_id) {
+ /* Authentication */
+ case SKS_CKM_AES_CMAC_GENERAL:
+ case SKS_CKM_AES_CMAC:
+ case SKS_CKM_MD5_HMAC:
+ case SKS_CKM_SHA_1_HMAC:
+ case SKS_CKM_SHA224_HMAC:
+ case SKS_CKM_SHA256_HMAC:
+ case SKS_CKM_SHA384_HMAC:
+ case SKS_CKM_SHA512_HMAC:
+ case SKS_CKM_AES_XCBC_MAC:
+ /* Cipherering */
+ case SKS_CKM_AES_ECB:
+ case SKS_CKM_AES_CBC:
+ case SKS_CKM_AES_CBC_PAD:
+ case SKS_CKM_AES_CTS:
+ case SKS_CKM_AES_CTR:
+ case SKS_CKM_AES_CCM:
+ case SKS_CKM_AES_GCM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static uint32_t sks2tee_algorithm(uint32_t *tee_id,
+ struct sks_attribute_head *proc_params)
+{
+ static const uint32_t sks2tee_algo[][2] = {
+ /* AES flavors */
+ { SKS_CKM_AES_ECB, TEE_ALG_AES_ECB_NOPAD },
+ { SKS_CKM_AES_CBC, TEE_ALG_AES_CBC_NOPAD },
+ { SKS_CKM_AES_CBC_PAD, TEE_ALG_AES_CBC_NOPAD }, // TODO
+ { SKS_CKM_AES_CTR, TEE_ALG_AES_CTR },
+ { SKS_CKM_AES_CTS, TEE_ALG_AES_CTS },
+ { SKS_CKM_AES_CCM, TEE_ALG_AES_CCM },
+ { SKS_CKM_AES_GCM, TEE_ALG_AES_GCM },
+ { SKS_CKM_AES_CMAC, TEE_ALG_AES_CMAC },
+ { SKS_CKM_AES_CMAC_GENERAL, TEE_ALG_AES_CMAC },
+ { SKS_CKM_AES_XCBC_MAC, TEE_ALG_AES_CBC_MAC_NOPAD },
+ /* HMAC flavors */
+ { SKS_CKM_MD5_HMAC, TEE_ALG_HMAC_MD5 },
+ { SKS_CKM_SHA_1_HMAC, TEE_ALG_HMAC_SHA1 },
+ { SKS_CKM_SHA224_HMAC, TEE_ALG_HMAC_SHA224 },
+ { SKS_CKM_SHA256_HMAC, TEE_ALG_HMAC_SHA256 },
+ { SKS_CKM_SHA384_HMAC, TEE_ALG_HMAC_SHA384 },
+ { SKS_CKM_SHA512_HMAC, TEE_ALG_HMAC_SHA512 },
+ };
+ size_t end = sizeof(sks2tee_algo) / (2 * sizeof(uint32_t));
+ size_t n = 0;
+
+ for (n = 0; n < end; n++) {
+ if (proc_params->id == sks2tee_algo[n][0]) {
+ *tee_id = sks2tee_algo[n][1];
+ break;
+ }
+ }
+
+ if (n == end)
+ return SKS_NOT_IMPLEMENTED;
+
+ return SKS_OK;
+}
+
+static uint32_t sks2tee_key_type(uint32_t *tee_type,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ static const uint32_t sks2tee_key_type[][2] = {
+ { SKS_CKK_AES, TEE_TYPE_AES },
+ { SKS_CKK_GENERIC_SECRET, TEE_TYPE_GENERIC_SECRET },
+ { SKS_CKK_MD5_HMAC, TEE_TYPE_HMAC_MD5 },
+ { SKS_CKK_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 },
+ { SKS_CKK_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 },
+ { SKS_CKK_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 },
+ { SKS_CKK_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 },
+ { SKS_CKK_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 },
+ };
+ static const uint32_t sks_mech2tee_type[][2] = {
+ { SKS_CKM_MD5_HMAC, TEE_TYPE_HMAC_MD5 },
+ { SKS_CKM_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 },
+ { SKS_CKM_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 },
+ { SKS_CKM_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 },
+ { SKS_CKM_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 },
+ { SKS_CKM_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 },
+ };
+ size_t last = 0;
+ size_t n = 0;
+ uint32_t type = 0;
+ uint32_t key_type = 0;
+
+ assert(get_class(obj->attributes) == SKS_CKO_SECRET_KEY);
+
+ key_type = get_type(obj->attributes);
+ last = sizeof(sks2tee_key_type) / (2 * sizeof(uint32_t));
+ for (n = 0; n < last; n++) {
+ if (sks2tee_key_type[n][0] == key_type) {
+ type = sks2tee_key_type[n][1];
+ break;
+ }
+ }
+ if (n == last)
+ return SKS_NOT_FOUND;
+
+ /*
+ * HMAC secret corresponds to the generic secret key type
+ * or the mechanism specific key type. If generic, find the
+ * corresponding TEE_TYPE based on the mechanism used.
+ */
+ if (type == TEE_TYPE_GENERIC_SECRET) {
+ last = sizeof(sks_mech2tee_type) /
+ (2 * sizeof(uint32_t));
+ for (n = 0; n < last; n++) {
+ if (sks_mech2tee_type[n][0] == proc_params->id) {
+ type = sks_mech2tee_type[n][1];
+ break;
+ }
+ }
+ }
+
+ *tee_type = type;
+
+ return SKS_OK;
+}
+
+static uint32_t allocate_tee_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ uint32_t size = (uint32_t)get_object_key_bit_size(obj);
+ uint32_t algo = 0;
+ uint32_t mode = 0;
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ assert(session->processing->tee_op_handle == TEE_HANDLE_NULL);
+
+ if (sks2tee_algorithm(&algo, proc_params))
+ return SKS_FAILED;
+
+ /* Sign/Verify with AES or generic key relate to TEE MAC operation */
+ switch (proc_params->id) {
+ case SKS_CKM_AES_CMAC_GENERAL:
+ case SKS_CKM_AES_CMAC:
+ case SKS_CKM_MD5_HMAC:
+ case SKS_CKM_SHA_1_HMAC:
+ case SKS_CKM_SHA224_HMAC:
+ case SKS_CKM_SHA256_HMAC:
+ case SKS_CKM_SHA384_HMAC:
+ case SKS_CKM_SHA512_HMAC:
+ case SKS_CKM_AES_XCBC_MAC:
+ mode = TEE_MODE_MAC;
+ break;
+ default:
+ sks2tee_mode(&mode, function);
+ break;
+ }
+
+ res = TEE_AllocateOperation(&session->processing->tee_op_handle,
+ algo, mode, size);
+ switch (res) {
+ case TEE_ERROR_NOT_SUPPORTED:
+ return SKS_CKR_MECHANISM_INVALID;
+ case TEE_SUCCESS:
+ break;
+ default:
+ EMSG("TEE_AllocateOp. failed %" PRIx32 " %" PRIx32 " %" PRIx32,
+ algo, mode, size);
+ }
+
+ return tee2sks_error(res);
+}
+
+static uint32_t load_tee_key(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ TEE_Attribute tee_attr;
+ size_t object_size = 0;
+ uint32_t key_type = 0;
+ uint32_t rv = 0;
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ TEE_MemFill(&tee_attr, 0, sizeof(tee_attr));
+
+ if (obj->key_handle != TEE_HANDLE_NULL) {
+ /* Key was already loaded and fits current need */
+ goto key_ready;
+ }
+
+ if (!sks2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE,
+ obj, SKS_CKA_VALUE)) {
+ EMSG("No secret found");
+ return SKS_FAILED;
+ }
+
+ rv = sks2tee_key_type(&key_type, proc_params, obj);
+ if (rv)
+ return rv;
+
+ object_size = get_object_key_bit_size(obj);
+ if (!object_size)
+ return SKS_ERROR;
+
+ res = TEE_AllocateTransientObject(key_type, object_size,
+ &obj->key_handle);
+ if (res) {
+ DMSG("TEE_AllocateTransientObject failed, %" PRIx32, res);
+ return tee2sks_error(res);
+ }
+
+ res = TEE_PopulateTransientObject(obj->key_handle, &tee_attr, 1);
+ if (res) {
+ DMSG("TEE_PopulateTransientObject failed, %" PRIx32, res);
+ goto error;
+ }
+
+key_ready:
+ res = TEE_SetOperationKey(session->processing->tee_op_handle,
+ obj->key_handle);
+ if (res) {
+ DMSG("TEE_SetOperationKey failed, %" PRIx32, res);
+ goto error;
+ }
+
+ return tee2sks_error(res);
+
+error:
+ TEE_FreeTransientObject(obj->key_handle);
+ obj->key_handle = TEE_HANDLE_NULL;
+
+ return tee2sks_error(res);
+}
+
+static uint32_t init_tee_operation(struct pkcs11_session *session,
+ struct sks_attribute_head *proc_params)
+{
+ uint32_t rv = SKS_ERROR;
+
+ switch (proc_params->id) {
+ case SKS_CKM_AES_CMAC_GENERAL:
+ case SKS_CKM_AES_CMAC:
+ case SKS_CKM_MD5_HMAC:
+ case SKS_CKM_SHA_1_HMAC:
+ case SKS_CKM_SHA224_HMAC:
+ case SKS_CKM_SHA256_HMAC:
+ case SKS_CKM_SHA384_HMAC:
+ case SKS_CKM_SHA512_HMAC:
+ case SKS_CKM_AES_XCBC_MAC:
+ if (proc_params->size)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+
+ TEE_MACInit(session->processing->tee_op_handle, NULL, 0);
+ rv = SKS_OK;
+ break;
+ case SKS_CKM_AES_ECB:
+ if (proc_params->size)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+
+ TEE_CipherInit(session->processing->tee_op_handle, NULL, 0);
+ rv = SKS_OK;
+ break;
+ case SKS_CKM_AES_CBC:
+ case SKS_CKM_AES_CBC_PAD:
+ case SKS_CKM_AES_CTS:
+ if (proc_params->size != 16)
+ return SKS_CKR_MECHANISM_PARAM_INVALID;
+
+ TEE_CipherInit(session->processing->tee_op_handle,
+ proc_params->data, 16);
+ rv = SKS_OK;
+ break;
+ case SKS_CKM_AES_CTR:
+ rv = tee_init_ctr_operation(session->processing,
+ proc_params->data,
+ proc_params->size);
+ break;
+ case SKS_CKM_AES_CCM:
+ rv = tee_init_ccm_operation(session->processing,
+ proc_params->data,
+ proc_params->size);
+ break;
+ case SKS_CKM_AES_GCM:
+ rv = tee_init_gcm_operation(session->processing,
+ proc_params->data,
+ proc_params->size);
+ break;
+ default:
+ TEE_Panic(proc_params->id);
+ break;
+ }
+
+ return rv;
+}
+
+uint32_t init_symm_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ struct sks_attribute_head *proc_params,
+ struct sks_object *obj)
+{
+ uint32_t rv = 0;
+
+ assert(processing_is_tee_symm(proc_params->id));
+
+ rv = allocate_tee_operation(session, function, proc_params, obj);
+ if (rv)
+ return rv;
+
+ rv = load_tee_key(session, proc_params, obj);
+ if (rv)
+ return rv;
+
+ return init_tee_operation(session, proc_params);
+}
+
+/*
+ * step_sym_cipher - processing symmetric (and related) cipher operation step
+ *
+ * @session - current session
+ * @function
+ * @step - step ID in the processing (oneshot, update,final)
+ * @in - input data reference #1
+ * @io2 - input or output data reference #2, depending on function/step.
+ */
+uint32_t step_symm_operation(struct pkcs11_session *session,
+ enum processing_func function,
+ enum processing_step step,
+ TEE_Param *in, TEE_Param *io2)
+{
+ uint32_t rv = SKS_ERROR;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ void *in_buf = in ? in->memref.buffer : NULL;
+ size_t in_size = in ? in->memref.size : 0;
+ void *out_buf = io2 ? io2->memref.buffer : NULL;
+ uint32_t out_size = io2 ? io2->memref.size : 0;
+ uint32_t out_size2 = out_size;
+ void *in2_buf = io2 ? io2->memref.buffer : NULL;
+ uint32_t in2_size = io2 ? io2->memref.size : 0;
+ bool output_data = false;
+ struct active_processing *proc = session->processing;
+
+ switch (step) {
+ case SKS_FUNC_STEP_ONESHOT:
+ case SKS_FUNC_STEP_UPDATE:
+ case SKS_FUNC_STEP_FINAL:
+ break;
+ default:
+ return SKS_ERROR;
+ }
+
+ /* Validate input buffer size */
+ switch (proc->mecha_type) {
+ case SKS_CKM_AES_ECB:
+ case SKS_CKM_AES_CBC:
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ if ((in_size % 16) != 0)
+ return SKS_CKR_DATA_LEN_RANGE;
+ break;
+ case SKS_FUNCTION_DECRYPT:
+ if ((in_size % 16) != 0)
+ return SKS_CKR_ENCRYPTED_DATA_LEN_RANGE;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SKS_CKM_AES_CBC_PAD:
+ switch (function) {
+ case SKS_FUNCTION_DECRYPT:
+ if ((in_size % 16) != 0)
+ return SKS_CKR_ENCRYPTED_DATA_LEN_RANGE;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SKS_CKM_AES_CTS:
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ if (in_size < 16)
+ return SKS_CKR_DATA_LEN_RANGE;
+ break;
+ case SKS_FUNCTION_DECRYPT:
+ if (in_size < 16)
+ return SKS_CKR_ENCRYPTED_DATA_LEN_RANGE;
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ /*
+ * Feed active operation with with data
+ * (SKS_FUNC_STEP_UPDATE/_ONESHOT)
+ */
+ switch (proc->mecha_type) {
+ case SKS_CKM_AES_CMAC_GENERAL:
+ case SKS_CKM_AES_CMAC:
+ case SKS_CKM_MD5_HMAC:
+ case SKS_CKM_SHA_1_HMAC:
+ case SKS_CKM_SHA224_HMAC:
+ case SKS_CKM_SHA256_HMAC:
+ case SKS_CKM_SHA384_HMAC:
+ case SKS_CKM_SHA512_HMAC:
+ case SKS_CKM_AES_XCBC_MAC:
+ if (step == SKS_FUNC_STEP_FINAL)
+ break;
+
+ if (!in) {
+ DMSG("No input data");
+ return SKS_BAD_PARAM;
+ }
+
+ switch (function) {
+ case SKS_FUNCTION_SIGN:
+ case SKS_FUNCTION_VERIFY:
+ TEE_MACUpdate(proc->tee_op_handle, in_buf, in_size);
+ rv = SKS_OK;
+ break;
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+
+ case SKS_CKM_AES_ECB:
+ case SKS_CKM_AES_CBC:
+ case SKS_CKM_AES_CBC_PAD:
+ case SKS_CKM_AES_CTS:
+ case SKS_CKM_AES_CTR:
+ if (step == SKS_FUNC_STEP_FINAL ||
+ step == SKS_FUNC_STEP_ONESHOT)
+ break;
+
+ if (!in) {
+ DMSG("No input data");
+ return SKS_BAD_PARAM;
+ }
+
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ case SKS_FUNCTION_DECRYPT:
+ res = TEE_CipherUpdate(proc->tee_op_handle,
+ in_buf, in_size,
+ out_buf, &out_size);
+ output_data = true;
+ rv = tee2sks_error(res);
+ break;
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+
+ case SKS_CKM_AES_CCM:
+ case SKS_CKM_AES_GCM:
+ if (step == SKS_FUNC_STEP_FINAL)
+ break;
+
+ if (!in) {
+ DMSG("No input data");
+ return SKS_BAD_PARAM;
+ }
+
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ res = TEE_AEUpdate(proc->tee_op_handle,
+ in_buf, in_size, out_buf, &out_size);
+ output_data = true;
+ rv = tee2sks_error(res);
+
+ if (step == SKS_FUNC_STEP_ONESHOT &&
+ (rv == SKS_OK || rv == SKS_SHORT_BUFFER)) {
+ out_buf = (char *)out_buf + out_size;
+ out_size2 -= out_size;
+ }
+ break;
+ case SKS_FUNCTION_DECRYPT:
+ rv = tee_ae_decrypt_update(proc, in_buf, in_size);
+ out_size = 0;
+ output_data = true;
+ break;
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+ default:
+ TEE_Panic(proc->mecha_type);
+ break;
+ }
+
+ if (step == SKS_FUNC_STEP_UPDATE)
+ goto bail;
+
+ /*
+ * Finalize (SKS_FUNC_STEP_ONESHOT/_FINAL) operation
+ */
+ switch (session->processing->mecha_type) {
+ case SKS_CKM_AES_CMAC_GENERAL:
+ case SKS_CKM_AES_CMAC:
+ case SKS_CKM_MD5_HMAC:
+ case SKS_CKM_SHA_1_HMAC:
+ case SKS_CKM_SHA224_HMAC:
+ case SKS_CKM_SHA256_HMAC:
+ case SKS_CKM_SHA384_HMAC:
+ case SKS_CKM_SHA512_HMAC:
+ case SKS_CKM_AES_XCBC_MAC:
+ switch (function) {
+ case SKS_FUNCTION_SIGN:
+ res = TEE_MACComputeFinal(proc->tee_op_handle,
+ NULL, 0, out_buf, &out_size);
+ output_data = true;
+ rv = tee2sks_error(res);
+ break;
+ case SKS_FUNCTION_VERIFY:
+ res = TEE_MACCompareFinal(proc->tee_op_handle,
+ NULL, 0, in2_buf, in2_size);
+ rv = tee2sks_error(res);
+ break;
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+
+ case SKS_CKM_AES_ECB:
+ case SKS_CKM_AES_CBC:
+ case SKS_CKM_AES_CBC_PAD:
+ case SKS_CKM_AES_CTS:
+ case SKS_CKM_AES_CTR:
+ if (step == SKS_FUNC_STEP_ONESHOT && !in) {
+ DMSG("No input data");
+ return SKS_BAD_PARAM;
+ }
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ case SKS_FUNCTION_DECRYPT:
+ res = TEE_CipherDoFinal(proc->tee_op_handle,
+ in_buf, in_size,
+ out_buf, &out_size);
+ output_data = true;
+ rv = tee2sks_error(res);
+ break;
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+
+ case SKS_CKM_AES_CCM:
+ case SKS_CKM_AES_GCM:
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ rv = tee_ae_encrypt_final(proc, out_buf, &out_size2);
+ output_data = true;
+
+ /*
+ * FIXME: on failure & ONESHOT, restore operation state
+ * before TEE_AEUpdate() was called
+ */
+ if (step == SKS_FUNC_STEP_ONESHOT) {
+ out_size += out_size2;
+ } else {
+ out_size = out_size2;
+ }
+ break;
+ case SKS_FUNCTION_DECRYPT:
+ rv = tee_ae_decrypt_final(proc, out_buf, &out_size);
+ output_data = true;
+ break;
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+ default:
+ TEE_Panic(proc->mecha_type);
+ break;
+ }
+
+bail:
+ if (output_data && (rv == SKS_OK || rv == SKS_SHORT_BUFFER)) {
+ if (io2)
+ io2->memref.size = out_size;
+ else
+ rv = SKS_BAD_PARAM;
+ }
+
+ return rv;
+}
+
+uint32_t do_symm_derivation(struct pkcs11_session *session __unused,
+ struct sks_attribute_head *proc_params __unused,
+ struct sks_object *parent_key __unused,
+ struct sks_attrs_head **head __unused)
+{
+ EMSG("Symm key derivation not yet supported");
+ return SKS_ERROR;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sanitize_object.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sanitize_object.c
new file mode 100644
index 0000000..d7b7449
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sanitize_object.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sks_internal_abi.h>
+#include <sks_ta.h>
+#include <stdlib.h>
+#include <string.h>
+#include <util.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <trace.h>
+
+#include "attributes.h"
+#include "sanitize_object.h"
+#include "serializer.h"
+#include "sks_helpers.h"
+
+/*
+ * Functions to generate a serialized object.
+ * References are pointers to struct serializer.
+ */
+#define SKS_ID(sks) case sks:
+
+bool sanitize_consistent_class_and_type(struct sks_attrs_head *attrs)
+{
+ uint32_t class = get_class(attrs);
+ uint32_t type = get_type(attrs);
+
+ switch (class) {
+ case SKS_CKO_DATA:
+ return true;
+ case SKS_CKO_SECRET_KEY:
+ return key_type_is_symm_key(type);
+ case SKS_CKO_MECHANISM:
+ return mechanism_is_valid(type);
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ return key_type_is_asymm_key(type);
+ case SKS_CKO_CERTIFICATE:
+ return certificate_is_valid(type);
+ case SKS_CKO_OTP_KEY:
+ case SKS_CKO_DOMAIN_PARAMETERS:
+ case SKS_CKO_HW_FEATURE:
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+/* Sanitize class/type in a client attribute list */
+static uint32_t sanitize_class_and_type(struct sks_attrs_head **dst,
+ void *src)
+{
+ struct sks_object_head head;
+ char *cur = NULL;
+ char *end = NULL;
+ size_t len = 0;
+ uint32_t class_found = 0;
+ uint32_t type_found = 0;
+ struct sks_attribute_head cli_ref;
+ uint32_t rc = SKS_OK;
+ size_t src_size = 0;
+
+ TEE_MemMove(&head, src, sizeof(head));
+ TEE_MemFill(&cli_ref, 0, sizeof(cli_ref));
+
+ src_size = sizeof(struct sks_object_head) + head.attrs_size;
+
+ class_found = SKS_UNDEFINED_ID;
+ type_found = SKS_UNDEFINED_ID;
+
+ cur = (char *)src + sizeof(struct sks_object_head);
+ end = cur + head.attrs_size;
+
+ for (; cur < end; cur += len) {
+ /* Structure aligned copy of client reference in the object */
+ TEE_MemMove(&cli_ref, cur, sizeof(cli_ref));
+ len = sizeof(cli_ref) + cli_ref.size;
+
+ if (sks_attr_is_class(cli_ref.id)) {
+ uint32_t class;
+
+ if (cli_ref.size != sks_attr_is_class(cli_ref.id)) {
+ rc = SKS_CKR_TEMPLATE_INCONSISTENT;
+ goto bail;
+ }
+
+ TEE_MemMove(&class, cur + sizeof(cli_ref), cli_ref.size);
+
+ if (class_found != SKS_UNDEFINED_ID &&
+ class_found != class) {
+ EMSG("Conflicting class value");
+ rc = SKS_CKR_TEMPLATE_INCONSISTENT;
+ goto bail;
+ }
+
+ class_found = class;
+ continue;
+ }
+
+ /* The attribute is a type-in-class */
+ if (sks_attr_is_type(cli_ref.id)) {
+ uint32_t type = 0;
+
+ if (cli_ref.size != sks_attr_is_type(cli_ref.id)) {
+ rc = SKS_CKR_TEMPLATE_INCONSISTENT;
+ goto bail;
+ }
+
+ TEE_MemMove(&type, cur + sizeof(cli_ref), cli_ref.size);
+
+ if (type_found != SKS_UNDEFINED_ID &&
+ type_found != type) {
+ EMSG("Conflicting type-in-class value");
+ rc = SKS_CKR_TEMPLATE_INCONSISTENT;
+ goto bail;
+ }
+
+ type_found = type;
+ }
+ }
+
+ /* Sanity */
+ if (cur != end) {
+ EMSG("Unexpected alignment issue");
+ rc = SKS_FAILED;
+ goto bail;
+ }
+
+ if (class_found != SKS_UNDEFINED_ID) {
+ rc = add_attribute(dst, SKS_CKA_CLASS,
+ &class_found, sizeof(uint32_t));
+ if (rc)
+ goto bail;
+ }
+
+ if (type_found != SKS_UNDEFINED_ID) {
+ rc = add_attribute(dst, SKS_CKA_KEY_TYPE,
+ &type_found, sizeof(uint32_t));
+ }
+
+bail:
+ if (rc)
+ trace_attributes_from_api_head("bad-template", src, src_size);
+
+ return rc;
+}
+
+static uint32_t sanitize_boolprop(struct sks_attrs_head **dst,
+ struct sks_attribute_head *cli_ref,
+ char *cur, uint32_t *boolprop_base,
+ uint32_t *sanity)
+{
+ int shift = 0;
+ uint32_t mask = 0;
+ uint32_t value = 0;
+ uint32_t *boolprop_ptr = NULL;
+ uint32_t *sanity_ptr = NULL;
+
+ /* Get the boolean property shift position and value */
+ shift = sks_attr2boolprop_shift(cli_ref->id);
+ if (shift < 0)
+ return SKS_NOT_FOUND;
+
+ if (shift >= SKS_MAX_BOOLPROP_SHIFT)
+ return SKS_FAILED;
+
+ mask = 1 << (shift % 32);
+ if ((*(uint8_t *)(cur + sizeof(*cli_ref))) == SKS_TRUE)
+ value = mask;
+ else
+ value = 0;
+
+ /* Locate the current config value for the boolean property */
+ boolprop_ptr = boolprop_base + (shift / 32);
+ sanity_ptr = sanity + (shift / 32);
+
+ /* Error if already set to a different boolean value */
+ if (*sanity_ptr & mask && value != (*boolprop_ptr & mask))
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+
+ if (value)
+ *boolprop_ptr |= mask;
+ else
+ *boolprop_ptr &= ~mask;
+
+ /* Store the attribute inside the serialized data */
+ if (!(*sanity_ptr & mask)) {
+ uint32_t rc = 0;
+ uint8_t sks_bool = !!value;
+
+ rc = add_attribute(dst, SKS_BOOLPROPS_BASE + shift,
+ &sks_bool, sizeof(uint8_t));
+ if (rc)
+ return rc;
+ }
+
+ *sanity_ptr |= mask;
+
+ return SKS_OK;
+}
+
+static uint32_t sanitize_boolprops(struct sks_attrs_head **dst, void *src)
+{
+ struct sks_object_head head;
+ char *cur = NULL;
+ char *end = NULL;
+ size_t len = 0;
+ struct sks_attribute_head cli_ref;
+ uint32_t sanity[SKS_MAX_BOOLPROP_ARRAY] = { 0 };
+ uint32_t boolprops[SKS_MAX_BOOLPROP_ARRAY] = { 0 };
+ uint32_t rc = 0;
+
+ TEE_MemMove(&head, src, sizeof(head));
+ TEE_MemFill(&cli_ref, 0, sizeof(cli_ref));
+
+ cur = (char *)src + sizeof(struct sks_object_head);
+ end = cur + head.attrs_size;
+
+ for (; cur < end; cur += len) {
+ /* Structure aligned copy of the cli_ref in the object */
+ TEE_MemMove(&cli_ref, cur, sizeof(cli_ref));
+ len = sizeof(cli_ref) + cli_ref.size;
+
+ rc = sanitize_boolprop(dst, &cli_ref, cur, boolprops, sanity);
+ if (rc != SKS_OK && rc != SKS_NOT_FOUND)
+ return rc;
+ }
+
+ return SKS_OK;
+}
+
+/* Counterpart of serialize_indirect_attribute() */
+static uint32_t sanitize_indirect_attr(struct sks_attrs_head **dst,
+ struct sks_attribute_head *cli_ref,
+ char *cur)
+{
+ struct sks_attrs_head *obj2 = NULL;
+ uint32_t rc = 0;
+ uint32_t class = get_class(*dst);
+
+ if (class == SKS_UNDEFINED_ID)
+ return SKS_NOT_FOUND;
+
+ /*
+ * Serialized attributes: current applicable only the key templates which
+ * are tables of attributes.
+ */
+ switch (cli_ref->id) {
+ case SKS_CKA_WRAP_TEMPLATE:
+ case SKS_CKA_UNWRAP_TEMPLATE:
+ case SKS_CKA_DERIVE_TEMPLATE:
+ break;
+ default:
+ return SKS_NOT_FOUND;
+ }
+ /* Such attributes are expected only for keys (and vendor defined) */
+ if (sks_attr_class_is_key(class))
+ return SKS_CKR_TEMPLATE_INCONSISTENT;
+
+ rc = init_attributes_head(&obj2);
+ if (rc != SKS_OK)
+ return rc;
+
+ /* Build a new serial object while sanitizing the attributes list */
+ rc = sanitize_client_object(&obj2, cur + sizeof(*cli_ref),
+ cli_ref->size);
+ if (rc)
+ return rc;
+
+ return add_attribute(dst, cli_ref->id, obj2,
+ sizeof(struct sks_attrs_head) + obj2->attrs_size);
+}
+
+uint32_t sanitize_client_object(struct sks_attrs_head **dst,
+ void *src, size_t size)
+{
+ struct sks_object_head head;
+ uint32_t rc = 0;
+ char *cur = NULL;
+ char *end = NULL;
+ size_t next = 0;
+
+ TEE_MemFill(&head, 0, sizeof(head));
+
+ if (size < sizeof(struct sks_object_head))
+ return SKS_BAD_PARAM;
+
+ TEE_MemMove(&head, src, sizeof(struct sks_object_head));
+
+ if (size < (sizeof(struct sks_object_head) + head.attrs_size))
+ return SKS_BAD_PARAM;
+
+ rc = init_attributes_head(dst);
+ if (rc != SKS_OK)
+ goto bail;
+
+ rc = sanitize_class_and_type(dst, src);
+ if (rc)
+ goto bail;
+
+ rc = sanitize_boolprops(dst, src);
+ if (rc)
+ goto bail;
+
+ cur = (char *)src + sizeof(struct sks_object_head);
+ end = cur + head.attrs_size;
+
+ for (; cur < end; cur += next) {
+ struct sks_attribute_head cli_ref;
+
+ if (cur + sizeof(cli_ref) > end)
+ return SKS_BAD_PARAM;
+
+ TEE_MemMove(&cli_ref, cur, sizeof(cli_ref));
+ next = sizeof(cli_ref) + cli_ref.size;
+
+ if (sks_attr_is_class(cli_ref.id) ||
+ sks_attr_is_type(cli_ref.id) ||
+ sks_attr2boolprop_shift(cli_ref.id) >= 0)
+ continue;
+
+ rc = sanitize_indirect_attr(dst, &cli_ref, cur);
+ if (rc == SKS_OK)
+ continue;
+ if (rc != SKS_NOT_FOUND)
+ goto bail;
+
+ if (!valid_sks_attribute_id(cli_ref.id, cli_ref.size)) {
+ EMSG("Invalid attribute id 0x%" PRIx32, cli_ref.id);
+ rc = SKS_CKR_TEMPLATE_INCONSISTENT;
+ goto bail;
+ }
+
+ rc = add_attribute(dst, cli_ref.id, cur + sizeof(cli_ref),
+ cli_ref.size);
+ if (rc)
+ goto bail;
+ }
+
+ /* sanity */
+ if (cur != end) {
+ EMSG("Unexpected alignment issue");
+ rc = SKS_FAILED;
+ goto bail;
+ }
+
+bail:
+ return rc;
+}
+
+/*
+ * Debug: dump object attribute array to output trace
+ */
+
+static uint32_t __trace_attributes(char *prefix, void *src, void *end)
+{
+ size_t next = 0;
+ char *prefix2 = NULL;
+ size_t prefix_len = strlen(prefix);
+ char *cur = src;
+ uint32_t rc = 0;
+
+ /* append 4 spaces to the prefix plus terminal '\0' */
+ prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO);
+ if (!prefix2)
+ return SKS_MEMORY;
+
+ TEE_MemMove(prefix2, prefix, prefix_len + 1);
+ TEE_MemFill(prefix2 + prefix_len, ' ', 4);
+ *(prefix2 + prefix_len + 4) = '\0';
+
+ for (; cur < (char *)end; cur += next) {
+ struct sks_ref sks_ref;
+ uint8_t data[4] = { 0 };
+ uint32_t data_u32 = 0;
+
+ TEE_MemMove(&sks_ref, cur, sizeof(sks_ref));
+ TEE_MemMove(&data[0], cur + sizeof(sks_ref),
+ MIN(sks_ref.size, sizeof(data)));
+ TEE_MemMove(&data_u32, cur + sizeof(sks_ref), sizeof(data_u32));
+
+ next = sizeof(sks_ref) + sks_ref.size;
+
+ IMSG_RAW("%s Attr %s / %s (0x%04" PRIx32 " %" PRIu32 "-byte)",
+ prefix, sks2str_attr(sks_ref.id),
+ sks2str_attr_value(sks_ref.id, sks_ref.size,
+ cur + sizeof(sks_ref)),
+ sks_ref.id, sks_ref.size);
+
+ switch (sks_ref.size) {
+ case 0:
+ break;
+ case 1:
+ DMSG_RAW("%s Attr byte value: %02x", prefix, data[0]);
+ break;
+ case 2:
+ DMSG_RAW("%s Attr byte value: %02x %02x",
+ prefix, data[0], data[1]);
+ break;
+ case 3:
+ DMSG_RAW("%s Attr byte value: %02x %02x %02x",
+ prefix, data[0], data[1], data[2]);
+ break;
+ case 4:
+ DMSG_RAW("%s Attr byte value: %02x %02x %02x %02x",
+ prefix, data[0], data[1], data[2], data[3]);
+ break;
+ default:
+ DMSG_RAW("%s Attr byte value: %02x %02x %02x %02x ...",
+ prefix, data[0], data[1], data[2], data[3]);
+ break;
+ }
+
+ switch (sks_ref.id) {
+ case SKS_CKA_WRAP_TEMPLATE:
+ case SKS_CKA_UNWRAP_TEMPLATE:
+ case SKS_CKA_DERIVE_TEMPLATE:
+ rc = trace_attributes_from_api_head(prefix2,
+ cur + sizeof(sks_ref),
+ (char *)end - cur);
+ if (rc)
+ return rc;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Sanity */
+ if (cur != (char *)end) {
+ EMSG("Warning: unexpected alignment issue");
+ }
+
+ TEE_Free(prefix2);
+ return SKS_OK;
+}
+
+uint32_t trace_attributes_from_api_head(const char *prefix,
+ void *ref, size_t size)
+{
+ struct sks_object_head head;
+ char *pre = NULL;
+ size_t offset = 0;
+ uint32_t rc = 0;
+
+ TEE_MemMove(&head, ref, sizeof(head));
+
+ if (size > sizeof(head) + head.attrs_size) {
+ EMSG("template overflows client buffer (%zu/%zu)",
+ size, sizeof(head) + head.attrs_size);
+ return SKS_FAILED;
+ }
+
+
+ pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO);
+ if (!pre)
+ return SKS_MEMORY;
+ if (prefix)
+ TEE_MemMove(pre, prefix, strlen(prefix));
+
+ IMSG_RAW("%s,--- (serial object) Attributes list --------", pre);
+ IMSG_RAW("%s| %" PRIx32 " item(s) - %" PRIu32 " bytes",
+ pre, head.attrs_count, head.attrs_size);
+
+ offset = sizeof(head);
+ pre[prefix ? strlen(prefix) : 0] = '|';
+ rc = __trace_attributes(pre, (char *)ref + offset,
+ (char *)ref + offset + head.attrs_size);
+ if (rc)
+ goto bail;
+
+ IMSG_RAW("%s`-----------------------", prefix ? prefix : "");
+
+bail:
+ TEE_Free(pre);
+ return rc;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sanitize_object.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sanitize_object.h
new file mode 100644
index 0000000..86013d2
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sanitize_object.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __SERIAL_SANITIZE_H
+#define __SERIAL_SANITIZE_H
+
+#include "serializer.h"
+
+/*
+ * sanitize_consistent_class_and_type - Check object type matches object class
+ *
+ * @attrs - object attributes
+ * Return true if class/type matches, else return false
+ */
+bool sanitize_consistent_class_and_type(struct sks_attrs_head *attrs);
+
+/**
+ * sanitize_client_object - Setup a serializer from a serialized object
+ *
+ * @dst - output structure tracking the generated serial object
+ * @head - pointer to the formatted serialized object (its head)
+ * @size - byte size of the serialized binary blob
+ *
+ * This function copies an attribute list from a client API attribute head
+ * into a SKS internal attribute structure. It generates a serialized attribute
+ * list with a consistent format and identified attribute IDs.
+ *
+ * ref points to a blob starting with a sks head.
+ * ref may pointer to an unaligned address.
+ * This function allocates, fill and returns a serialized attribute list
+ * into a serializer container.
+ */
+uint32_t sanitize_client_object(struct sks_attrs_head **dst,
+ void *head, size_t size);
+
+/* Debug: dump attribute content as debug traces */
+uint32_t trace_attributes_from_api_head(const char *prefix,
+ void *ref, size_t size);
+
+#endif /*__SERIAL_SANITIZE_H*/
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/serializer.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/serializer.c
new file mode 100644
index 0000000..09b129f
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/serializer.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <sks_internal_abi.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string_ext.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <trace.h>
+
+#include "serializer.h"
+#include "sks_helpers.h"
+
+/*
+ * Util routines for serializes unformatted arguments in a client memref
+ */
+void serialargs_init(struct serialargs *args, void *in, size_t size)
+{
+ args->start = in;
+ args->next = in;
+ args->size = size;
+}
+
+uint32_t serialargs_get(struct serialargs *args, void *out, size_t size)
+{
+ if (args->next + size > args->start + args->size) {
+ EMSG("arg too short: full %zd, remain %zd, expect %zd",
+ args->size, args->size - (args->next - args->start), size);
+ return SKS_BAD_PARAM;
+ }
+
+ TEE_MemMove(out, args->next, size);
+
+ args->next += size;
+
+ return SKS_OK;
+}
+
+uint32_t serialargs_alloc_and_get(struct serialargs *args,
+ void **out, size_t size)
+{
+ void *ptr = NULL;
+
+ if (!size) {
+ *out = NULL;
+ return SKS_OK;
+ }
+
+ if (args->next + size > args->start + args->size) {
+ EMSG("arg too short: full %zd, remain %zd, expect %zd",
+ args->size, args->size - (args->next - args->start), size);
+ return SKS_BAD_PARAM;
+ }
+
+ ptr = TEE_Malloc(size, TEE_MALLOC_FILL_ZERO);
+ if (!ptr)
+ return SKS_MEMORY;
+
+ TEE_MemMove(ptr, args->next, size);
+
+ args->next += size;
+ *out = ptr;
+
+ return SKS_OK;
+}
+
+uint32_t serialargs_get_ptr(struct serialargs *args, void **out, size_t size)
+{
+ void *ptr = args->next;
+
+ if (!size) {
+ *out = NULL;
+ return SKS_OK;
+ }
+
+ if (args->next + size > args->start + args->size) {
+ EMSG("arg too short: full %zd, remain %zd, expect %zd",
+ args->size, args->size - (args->next - args->start), size);
+ return SKS_BAD_PARAM;
+ }
+
+ args->next += size;
+ *out = ptr;
+
+ return SKS_OK;
+}
+
+uint32_t serialargs_alloc_get_one_attribute(struct serialargs *args __unused,
+ struct sks_attribute_head **out __unused)
+{
+ struct sks_attribute_head head;
+ size_t out_size = sizeof(head);
+ void *pref = NULL;
+
+ TEE_MemFill(&head, 0, sizeof(head));
+
+ if (args->next + out_size > args->start + args->size) {
+ EMSG("arg too short: full %zd, remain %zd, expect at least %zd",
+ args->size, args->size - (args->next - args->start),
+ out_size);
+ return SKS_BAD_PARAM;
+ }
+
+ TEE_MemMove(&head, args->next, out_size);
+
+ if (head.size > (SIZE_MAX - out_size)) {
+ EMSG("arg size too big");
+ return SKS_BAD_PARAM;
+ }
+
+ out_size += head.size;
+ if (args->next + out_size > args->start + args->size) {
+ EMSG("arg too short: full %zd, remain %zd, expect %zd",
+ args->size, args->size - (args->next - args->start),
+ out_size);
+ return SKS_BAD_PARAM;
+ }
+
+ pref = TEE_Malloc(out_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!pref)
+ return SKS_MEMORY;
+
+ TEE_MemMove(pref, args->next, out_size);
+ args->next += out_size;
+
+ *out = pref;
+
+ return SKS_OK;
+}
+
+uint32_t serialargs_alloc_get_attributes(struct serialargs *args __unused,
+ struct sks_object_head **out __unused)
+{
+ struct sks_object_head attr;
+ struct sks_object_head *pattr = NULL;
+ size_t attr_size = sizeof(attr);
+
+ TEE_MemFill(&attr, 0, sizeof(attr));
+
+ if (args->next + attr_size > args->start + args->size) {
+ EMSG("arg too short: full %zd, remain %zd, expect at least %zd",
+ args->size, args->size - (args->next - args->start),
+ attr_size);
+ return SKS_BAD_PARAM;
+ }
+
+ TEE_MemMove(&attr, args->next, attr_size);
+
+ if (attr.attrs_size > (SIZE_MAX - attr_size)) {
+ EMSG("arg size too big");
+ return SKS_BAD_PARAM;
+ }
+
+ attr_size += attr.attrs_size;
+ if (args->next + attr_size > args->start + args->size) {
+ EMSG("arg too short: full %zd, remain %zd, expect %zd",
+ args->size, args->size - (args->next - args->start),
+ attr_size);
+ return SKS_BAD_PARAM;
+ }
+
+ pattr = TEE_Malloc(attr_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!pattr)
+ return SKS_MEMORY;
+
+ TEE_MemMove(pattr, args->next, attr_size);
+ args->next += attr_size;
+
+ *out = pattr;
+
+ return SKS_OK;
+}
+
+/*
+ * serialize - serialize input data in buffer
+ *
+ * Serialize data in provided buffer.
+ * Insure 64byte alignment of appended data in the buffer.
+ */
+uint32_t serialize(char **bstart, size_t *blen, void *data, size_t len)
+{
+ char *buf = NULL;
+ size_t nlen = *blen + len;
+
+ buf = TEE_Realloc(*bstart, nlen);
+ if (!buf)
+ return SKS_MEMORY;
+
+ TEE_MemMove(buf + *blen, data, len);
+
+ *blen = nlen;
+ *bstart = buf;
+
+ return SKS_OK;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/serializer.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/serializer.h
new file mode 100644
index 0000000..05b7c47
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/serializer.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#ifndef __SERIALIZER_H__
+#define __SERIALIZER_H__
+
+#include <sks_internal_abi.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <tee_internal_api.h>
+
+/*
+ * Util routines for serializes unformated arguments in a client memref
+ */
+struct serialargs {
+ char *start;
+ char *next;
+ size_t size;
+};
+
+void serialargs_init(struct serialargs *args, void *in, size_t size);
+
+uint32_t serialargs_get(struct serialargs *args, void *out, size_t sz);
+
+uint32_t serialargs_get_ptr(struct serialargs *args, void **out, size_t size);
+
+uint32_t serialargs_alloc_get_one_attribute(struct serialargs *args,
+ struct sks_attribute_head **out);
+
+uint32_t serialargs_alloc_get_attributes(struct serialargs *args,
+ struct sks_object_head **out);
+
+uint32_t serialargs_alloc_and_get(struct serialargs *args,
+ void **out, size_t size);
+
+#define SKS_MAX_BOOLPROP_SHIFT 64
+#define SKS_MAX_BOOLPROP_ARRAY (SKS_MAX_BOOLPROP_SHIFT / sizeof(uint32_t))
+
+/**
+ * serialize - Append data into a serialized buffer
+ */
+uint32_t serialize(char **bstart, size_t *blen, void *data, size_t len);
+
+#endif /*__SERIALIZER_H*/
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_helpers.c b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_helpers.c
new file mode 100644
index 0000000..c33397a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_helpers.c
@@ -0,0 +1,895 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#include <assert.h>
+#include <sks_internal_abi.h>
+#include <sks_ta.h>
+#include <string.h>
+#include <util.h>
+#include <tee_internal_api.h>
+
+#include "attributes.h"
+#include "object.h"
+#include "pkcs11_attributes.h"
+#include "processing.h"
+#include "sks_helpers.h"
+
+static const char __maybe_unused unknown[] = "<unknown-identifier>";
+
+struct attr_size {
+ uint32_t id;
+ uint32_t size;
+#if CFG_TEE_TA_LOG_LEVEL > 0
+ const char *string;
+#endif
+};
+
+#if CFG_TEE_TA_LOG_LEVEL > 0
+#define SKS_ID_SZ(_id, _size) { .id = _id, .size = _size, .string = #_id }
+#else
+#define SKS_ID_SZ(_id, _size) { .id = _id, .size = _size }
+#endif
+
+static const struct attr_size attr_ids[] = {
+ SKS_ID_SZ(SKS_CKA_CLASS, 4),
+ SKS_ID_SZ(SKS_CKA_KEY_TYPE, 4),
+ SKS_ID_SZ(SKS_CKA_VALUE, 0),
+ SKS_ID_SZ(SKS_CKA_VALUE_LEN, 4),
+ SKS_ID_SZ(SKS_CKA_LABEL, 0),
+ SKS_ID_SZ(SKS_CKA_WRAP_TEMPLATE, 0),
+ SKS_ID_SZ(SKS_CKA_UNWRAP_TEMPLATE, 0),
+ SKS_ID_SZ(SKS_CKA_DERIVE_TEMPLATE, 0),
+ SKS_ID_SZ(SKS_CKA_START_DATE, 4),
+ SKS_ID_SZ(SKS_CKA_END_DATE, 4),
+ SKS_ID_SZ(SKS_CKA_OBJECT_ID, 0),
+ SKS_ID_SZ(SKS_CKA_APPLICATION, 0),
+ SKS_ID_SZ(SKS_CKA_MECHANISM_TYPE, 4),
+ SKS_ID_SZ(SKS_CKA_ID, 0),
+ SKS_ID_SZ(SKS_CKA_ALLOWED_MECHANISMS, 0),
+ SKS_ID_SZ(SKS_CKA_EC_POINT, 0),
+ SKS_ID_SZ(SKS_CKA_EC_PARAMS, 0),
+ SKS_ID_SZ(SKS_CKA_MODULUS, 0),
+ SKS_ID_SZ(SKS_CKA_MODULUS_BITS, 4),
+ SKS_ID_SZ(SKS_CKA_PUBLIC_EXPONENT, 0),
+ SKS_ID_SZ(SKS_CKA_PRIVATE_EXPONENT, 0),
+ SKS_ID_SZ(SKS_CKA_PRIME_1, 0),
+ SKS_ID_SZ(SKS_CKA_PRIME_2, 0),
+ SKS_ID_SZ(SKS_CKA_EXPONENT_1, 0),
+ SKS_ID_SZ(SKS_CKA_EXPONENT_2, 0),
+ SKS_ID_SZ(SKS_CKA_COEFFICIENT, 0),
+ SKS_ID_SZ(SKS_CKA_SUBJECT, 0),
+ SKS_ID_SZ(SKS_CKA_PUBLIC_KEY_INFO, 0),
+ SKS_ID_SZ(SKS_CKA_CERTIFICATE_TYPE, 4),
+ SKS_ID_SZ(SKS_CKA_CERTIFICATE_CATEGORY, 4),
+ SKS_ID_SZ(SKS_CKA_ISSUER, 0),
+ SKS_ID_SZ(SKS_CKA_SERIAL_NUMBER, 0),
+ SKS_ID_SZ(SKS_CKA_URL, 0),
+ SKS_ID_SZ(SKS_CKA_HASH_OF_SUBJECT_PUBLIC_KEY, 0),
+ SKS_ID_SZ(SKS_CKA_HASH_OF_ISSUER_PUBLIC_KEY, 0),
+ SKS_ID_SZ(SKS_CKA_NAME_HASH_ALGORITHM, 4),
+ SKS_ID_SZ(SKS_CKA_KEY_GEN_MECHANISM, 4),
+ /* Below are boolean attributes */
+ SKS_ID_SZ(SKS_CKA_TOKEN, 1),
+ SKS_ID_SZ(SKS_CKA_PRIVATE, 1),
+ SKS_ID_SZ(SKS_CKA_TRUSTED, 1),
+ SKS_ID_SZ(SKS_CKA_SENSITIVE, 1),
+ SKS_ID_SZ(SKS_CKA_ENCRYPT, 1),
+ SKS_ID_SZ(SKS_CKA_DECRYPT, 1),
+ SKS_ID_SZ(SKS_CKA_WRAP, 1),
+ SKS_ID_SZ(SKS_CKA_UNWRAP, 1),
+ SKS_ID_SZ(SKS_CKA_SIGN, 1),
+ SKS_ID_SZ(SKS_CKA_SIGN_RECOVER, 1),
+ SKS_ID_SZ(SKS_CKA_VERIFY, 1),
+ SKS_ID_SZ(SKS_CKA_VERIFY_RECOVER, 1),
+ SKS_ID_SZ(SKS_CKA_DERIVE, 1),
+ SKS_ID_SZ(SKS_CKA_EXTRACTABLE, 1),
+ SKS_ID_SZ(SKS_CKA_LOCAL, 1),
+ SKS_ID_SZ(SKS_CKA_NEVER_EXTRACTABLE, 1),
+ SKS_ID_SZ(SKS_CKA_ALWAYS_SENSITIVE, 1),
+ SKS_ID_SZ(SKS_CKA_MODIFIABLE, 1),
+ SKS_ID_SZ(SKS_CKA_COPYABLE, 1),
+ SKS_ID_SZ(SKS_CKA_DESTROYABLE, 1),
+ SKS_ID_SZ(SKS_CKA_ALWAYS_AUTHENTICATE, 1),
+ SKS_ID_SZ(SKS_CKA_WRAP_WITH_TRUSTED, 1),
+ /* Specific SKS attribute IDs */
+ SKS_ID_SZ(SKS_UNDEFINED_ID, 0),
+};
+
+struct processing_id {
+ uint32_t id;
+ bool supported;
+#if CFG_TEE_TA_LOG_LEVEL > 0
+ const char *string;
+#endif
+};
+
+#if CFG_TEE_TA_LOG_LEVEL > 0
+#define SKS_PROCESSING_ID(_id) \
+ { .id = _id, .supported = true, .string = #_id }
+#define SKS_UNSUPPORTED_PROCESSING_ID(_id) \
+ { .id = _id, .supported = false, .string = #_id }
+#else
+#define SKS_PROCESSING_ID(_id) \
+ { .id = _id, .supported = true }
+#define SKS_UNSUPPORTED_PROCESSING_ID(_id) \
+ { .id = _id, .supported = false }
+
+#endif
+
+static const struct processing_id __maybe_unused processing_ids[] = {
+ SKS_PROCESSING_ID(SKS_CKM_AES_ECB),
+ SKS_PROCESSING_ID(SKS_CKM_AES_CBC),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_AES_CBC_PAD),
+ SKS_PROCESSING_ID(SKS_CKM_AES_CTR),
+ SKS_PROCESSING_ID(SKS_CKM_AES_GCM),
+ SKS_PROCESSING_ID(SKS_CKM_AES_CCM),
+ SKS_PROCESSING_ID(SKS_CKM_AES_CTS),
+ SKS_PROCESSING_ID(SKS_CKM_AES_GMAC),
+ SKS_PROCESSING_ID(SKS_CKM_AES_CMAC),
+ SKS_PROCESSING_ID(SKS_CKM_AES_CMAC_GENERAL),
+ SKS_PROCESSING_ID(SKS_CKM_AES_ECB_ENCRYPT_DATA),
+ SKS_PROCESSING_ID(SKS_CKM_AES_CBC_ENCRYPT_DATA),
+ SKS_PROCESSING_ID(SKS_CKM_AES_KEY_GEN),
+ SKS_PROCESSING_ID(SKS_CKM_GENERIC_SECRET_KEY_GEN),
+ SKS_PROCESSING_ID(SKS_CKM_MD5_HMAC),
+ SKS_PROCESSING_ID(SKS_CKM_SHA_1_HMAC),
+ SKS_PROCESSING_ID(SKS_CKM_SHA224_HMAC),
+ SKS_PROCESSING_ID(SKS_CKM_SHA256_HMAC),
+ SKS_PROCESSING_ID(SKS_CKM_SHA384_HMAC),
+ SKS_PROCESSING_ID(SKS_CKM_SHA512_HMAC),
+ SKS_PROCESSING_ID(SKS_CKM_AES_XCBC_MAC),
+ SKS_PROCESSING_ID(SKS_CKM_EC_KEY_PAIR_GEN),
+ SKS_PROCESSING_ID(SKS_CKM_ECDSA),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECDSA_SHA1),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECDSA_SHA224),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECDSA_SHA256),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECDSA_SHA384),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECDSA_SHA512),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECDH1_DERIVE),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECDH1_COFACTOR_DERIVE),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECMQV_DERIVE),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_ECDH_AES_KEY_WRAP),
+ SKS_PROCESSING_ID(SKS_CKM_RSA_PKCS_KEY_PAIR_GEN),
+ SKS_PROCESSING_ID(SKS_CKM_RSA_PKCS),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_RSA_9796),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_RSA_X_509),
+ SKS_PROCESSING_ID(SKS_CKM_SHA1_RSA_PKCS),
+ SKS_PROCESSING_ID(SKS_CKM_RSA_PKCS_OAEP),
+ SKS_PROCESSING_ID(SKS_CKM_SHA1_RSA_PKCS_PSS),
+ SKS_PROCESSING_ID(SKS_CKM_SHA256_RSA_PKCS),
+ SKS_PROCESSING_ID(SKS_CKM_SHA384_RSA_PKCS),
+ SKS_PROCESSING_ID(SKS_CKM_SHA512_RSA_PKCS),
+ SKS_PROCESSING_ID(SKS_CKM_SHA256_RSA_PKCS_PSS),
+ SKS_PROCESSING_ID(SKS_CKM_SHA384_RSA_PKCS_PSS),
+ SKS_PROCESSING_ID(SKS_CKM_SHA512_RSA_PKCS_PSS),
+ SKS_PROCESSING_ID(SKS_CKM_SHA224_RSA_PKCS),
+ SKS_PROCESSING_ID(SKS_CKM_SHA224_RSA_PKCS_PSS),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_RSA_AES_KEY_WRAP),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_MD5),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_SHA_1),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_SHA224),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_SHA256),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_SHA384),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_CKM_SHA512),
+ SKS_UNSUPPORTED_PROCESSING_ID(SKS_UNDEFINED_ID)
+};
+
+struct string_id {
+ uint32_t id;
+#if CFG_TEE_TA_LOG_LEVEL > 0
+ const char *string;
+#endif
+};
+
+#if CFG_TEE_TA_LOG_LEVEL > 0
+#define SKS_ID(_id) { .id = _id, .string = #_id }
+#else
+#define SKS_ID(_id) { .id = _id }
+#endif
+
+static const struct string_id __maybe_unused string_cmd[] = {
+ SKS_ID(SKS_CMD_PING),
+ SKS_ID(SKS_CMD_CK_SLOT_LIST),
+ SKS_ID(SKS_CMD_CK_SLOT_INFO),
+ SKS_ID(SKS_CMD_CK_TOKEN_INFO),
+ SKS_ID(SKS_CMD_CK_MECHANISM_IDS),
+ SKS_ID(SKS_CMD_CK_MECHANISM_INFO),
+ SKS_ID(SKS_CMD_CK_INIT_TOKEN),
+ SKS_ID(SKS_CMD_CK_INIT_PIN),
+ SKS_ID(SKS_CMD_CK_SET_PIN),
+ SKS_ID(SKS_CMD_CK_OPEN_RO_SESSION),
+ SKS_ID(SKS_CMD_CK_OPEN_RW_SESSION),
+ SKS_ID(SKS_CMD_CK_CLOSE_SESSION),
+ SKS_ID(SKS_CMD_CK_SESSION_INFO),
+ SKS_ID(SKS_CMD_CK_CLOSE_ALL_SESSIONS),
+ SKS_ID(SKS_CMD_IMPORT_OBJECT),
+ SKS_ID(SKS_CMD_DESTROY_OBJECT),
+ SKS_ID(SKS_CMD_ENCRYPT_INIT),
+ SKS_ID(SKS_CMD_DECRYPT_INIT),
+ SKS_ID(SKS_CMD_ENCRYPT_UPDATE),
+ SKS_ID(SKS_CMD_DECRYPT_UPDATE),
+ SKS_ID(SKS_CMD_ENCRYPT_FINAL),
+ SKS_ID(SKS_CMD_DECRYPT_FINAL),
+ SKS_ID(SKS_CMD_GENERATE_SYMM_KEY),
+ SKS_ID(SKS_CMD_SIGN_INIT),
+ SKS_ID(SKS_CMD_VERIFY_INIT),
+ SKS_ID(SKS_CMD_SIGN_UPDATE),
+ SKS_ID(SKS_CMD_VERIFY_UPDATE),
+ SKS_ID(SKS_CMD_SIGN_FINAL),
+ SKS_ID(SKS_CMD_VERIFY_FINAL),
+ SKS_ID(SKS_CMD_FIND_OBJECTS_INIT),
+ SKS_ID(SKS_CMD_FIND_OBJECTS),
+ SKS_ID(SKS_CMD_FIND_OBJECTS_FINAL),
+ SKS_ID(SKS_CMD_GET_OBJECT_SIZE),
+ SKS_ID(SKS_CMD_GET_ATTRIBUTE_VALUE),
+ SKS_ID(SKS_CMD_SET_ATTRIBUTE_VALUE),
+ SKS_ID(SKS_CMD_DERIVE_KEY),
+ SKS_ID(SKS_CMD_INIT_PIN),
+ SKS_ID(SKS_CMD_SET_PIN),
+ SKS_ID(SKS_CMD_LOGIN),
+ SKS_ID(SKS_CMD_LOGOUT),
+ SKS_ID(SKS_CMD_GENERATE_KEY_PAIR),
+ SKS_ID(SKS_CMD_ENCRYPT_ONESHOT),
+ SKS_ID(SKS_CMD_DECRYPT_ONESHOT),
+ SKS_ID(SKS_CMD_SIGN_ONESHOT),
+ SKS_ID(SKS_CMD_VERIFY_ONESHOT),
+};
+
+static const struct string_id __maybe_unused string_rc[] = {
+ SKS_ID(SKS_CKR_OK),
+ SKS_ID(SKS_CKR_GENERAL_ERROR),
+ SKS_ID(SKS_CKR_DEVICE_MEMORY),
+ SKS_ID(SKS_CKR_ARGUMENTS_BAD),
+ SKS_ID(SKS_CKR_BUFFER_TOO_SMALL),
+ SKS_ID(SKS_CKR_FUNCTION_FAILED),
+ SKS_ID(SKS_CKR_SIGNATURE_INVALID),
+ SKS_ID(SKS_CKR_ATTRIBUTE_TYPE_INVALID),
+ SKS_ID(SKS_CKR_ATTRIBUTE_VALUE_INVALID),
+ SKS_ID(SKS_CKR_OBJECT_HANDLE_INVALID),
+ SKS_ID(SKS_CKR_KEY_HANDLE_INVALID),
+ SKS_ID(SKS_CKR_MECHANISM_INVALID),
+ SKS_ID(SKS_CKR_SESSION_HANDLE_INVALID),
+ SKS_ID(SKS_CKR_SLOT_ID_INVALID),
+ SKS_ID(SKS_CKR_MECHANISM_PARAM_INVALID),
+ SKS_ID(SKS_CKR_TEMPLATE_INCONSISTENT),
+ SKS_ID(SKS_CKR_TEMPLATE_INCOMPLETE),
+ SKS_ID(SKS_CKR_PIN_INCORRECT),
+ SKS_ID(SKS_CKR_PIN_LOCKED),
+ SKS_ID(SKS_CKR_PIN_EXPIRED),
+ SKS_ID(SKS_CKR_PIN_INVALID),
+ SKS_ID(SKS_CKR_PIN_LEN_RANGE),
+ SKS_ID(SKS_CKR_SESSION_EXISTS),
+ SKS_ID(SKS_CKR_SESSION_READ_ONLY),
+ SKS_ID(SKS_CKR_SESSION_READ_WRITE_SO_EXISTS),
+ SKS_ID(SKS_CKR_OPERATION_ACTIVE),
+ SKS_ID(SKS_CKR_KEY_TYPE_INCONSISTENT),
+ SKS_ID(SKS_CKR_KEY_FUNCTION_NOT_PERMITTED),
+ SKS_ID(SKS_CKR_OPERATION_NOT_INITIALIZED),
+ SKS_ID(SKS_CKR_TOKEN_WRITE_PROTECTED),
+ SKS_ID(SKS_CKR_TOKEN_NOT_PRESENT),
+ SKS_ID(SKS_CKR_TOKEN_NOT_RECOGNIZED),
+ SKS_ID(SKS_CKR_ACTION_PROHIBITED),
+ SKS_ID(SKS_CKR_ATTRIBUTE_READ_ONLY),
+ SKS_ID(SKS_CKR_PIN_TOO_WEAK),
+ SKS_ID(SKS_CKR_CURVE_NOT_SUPPORTED),
+ SKS_ID(SKS_CKR_DOMAIN_PARAMS_INVALID),
+ SKS_ID(SKS_CKR_USER_ALREADY_LOGGED_IN),
+ SKS_ID(SKS_CKR_USER_ANOTHER_ALREADY_LOGGED_IN),
+ SKS_ID(SKS_CKR_USER_NOT_LOGGED_IN),
+ SKS_ID(SKS_CKR_USER_PIN_NOT_INITIALIZED),
+ SKS_ID(SKS_CKR_USER_TOO_MANY_TYPES),
+ SKS_ID(SKS_CKR_USER_TYPE_INVALID),
+ SKS_ID(SKS_CKR_SESSION_READ_ONLY_EXISTS),
+ SKS_ID(SKS_CKR_KEY_SIZE_RANGE),
+ SKS_ID(SKS_CKR_ATTRIBUTE_SENSITIVE),
+ SKS_ID(SKS_CKR_SIGNATURE_LEN_RANGE),
+ SKS_ID(SKS_CKR_DATA_LEN_RANGE),
+ SKS_ID(SKS_CKR_ENCRYPTED_DATA_LEN_RANGE),
+ SKS_ID(SKS_NOT_FOUND),
+ SKS_ID(SKS_NOT_IMPLEMENTED),
+};
+
+static const struct string_id __maybe_unused string_slot_flags[] = {
+ SKS_ID(SKS_CKFS_TOKEN_PRESENT),
+ SKS_ID(SKS_CKFS_REMOVABLE_DEVICE),
+ SKS_ID(SKS_CKFS_HW_SLOT),
+};
+
+static const struct string_id __maybe_unused string_token_flags[] = {
+ SKS_ID(SKS_CKFT_RNG),
+ SKS_ID(SKS_CKFT_WRITE_PROTECTED),
+ SKS_ID(SKS_CKFT_LOGIN_REQUIRED),
+ SKS_ID(SKS_CKFT_USER_PIN_INITIALIZED),
+ SKS_ID(SKS_CKFT_RESTORE_KEY_NOT_NEEDED),
+ SKS_ID(SKS_CKFT_CLOCK_ON_TOKEN),
+ SKS_ID(SKS_CKFT_PROTECTED_AUTHENTICATION_PATH),
+ SKS_ID(SKS_CKFT_DUAL_CRYPTO_OPERATIONS),
+ SKS_ID(SKS_CKFT_TOKEN_INITIALIZED),
+ SKS_ID(SKS_CKFT_USER_PIN_COUNT_LOW),
+ SKS_ID(SKS_CKFT_USER_PIN_FINAL_TRY),
+ SKS_ID(SKS_CKFT_USER_PIN_LOCKED),
+ SKS_ID(SKS_CKFT_USER_PIN_TO_BE_CHANGED),
+ SKS_ID(SKS_CKFT_SO_PIN_COUNT_LOW),
+ SKS_ID(SKS_CKFT_SO_PIN_FINAL_TRY),
+ SKS_ID(SKS_CKFT_SO_PIN_LOCKED),
+ SKS_ID(SKS_CKFT_SO_PIN_TO_BE_CHANGED),
+ SKS_ID(SKS_CKFT_ERROR_STATE),
+};
+
+static const struct string_id __maybe_unused string_class[] = {
+ SKS_ID(SKS_CKO_SECRET_KEY),
+ SKS_ID(SKS_CKO_PUBLIC_KEY),
+ SKS_ID(SKS_CKO_PRIVATE_KEY),
+ SKS_ID(SKS_CKO_OTP_KEY),
+ SKS_ID(SKS_CKO_CERTIFICATE),
+ SKS_ID(SKS_CKO_DATA),
+ SKS_ID(SKS_CKO_DOMAIN_PARAMETERS),
+ SKS_ID(SKS_CKO_HW_FEATURE),
+ SKS_ID(SKS_CKO_MECHANISM),
+ SKS_ID(SKS_UNDEFINED_ID)
+};
+
+static const struct string_id __maybe_unused string_key_type[] = {
+ SKS_ID(SKS_CKK_AES),
+ SKS_ID(SKS_CKK_GENERIC_SECRET),
+ SKS_ID(SKS_CKK_MD5_HMAC),
+ SKS_ID(SKS_CKK_SHA_1_HMAC),
+ SKS_ID(SKS_CKK_SHA224_HMAC),
+ SKS_ID(SKS_CKK_SHA256_HMAC),
+ SKS_ID(SKS_CKK_SHA384_HMAC),
+ SKS_ID(SKS_CKK_SHA512_HMAC),
+ SKS_ID(SKS_CKK_EC),
+ SKS_ID(SKS_CKK_RSA),
+ SKS_ID(SKS_UNDEFINED_ID)
+};
+
+static const struct string_id __maybe_unused string_certificate_type[] = {
+ SKS_ID(SKS_CKC_X_509),
+ SKS_ID(SKS_CKC_X_509_ATTR_CER),
+ SKS_ID(SKS_CKC_WTLS),
+ SKS_ID(SKS_UNDEFINED_ID)
+};
+
+/* Processing IDs not exported in the TA API */
+static const struct string_id __maybe_unused string_internal_processing[] = {
+ SKS_ID(SKS_PROCESSING_IMPORT),
+ SKS_ID(SKS_PROCESSING_COPY),
+};
+
+static const struct string_id __maybe_unused string_proc_flags[] = {
+ SKS_ID(SKS_CKFM_HW),
+ SKS_ID(SKS_CKFM_ENCRYPT),
+ SKS_ID(SKS_CKFM_DECRYPT),
+ SKS_ID(SKS_CKFM_DIGEST),
+ SKS_ID(SKS_CKFM_SIGN),
+ SKS_ID(SKS_CKFM_SIGN_RECOVER),
+ SKS_ID(SKS_CKFM_VERIFY),
+ SKS_ID(SKS_CKFM_VERIFY_RECOVER),
+ SKS_ID(SKS_CKFM_GENERATE),
+ SKS_ID(SKS_CKFM_GENERATE_PAIR),
+ SKS_ID(SKS_CKFM_WRAP),
+ SKS_ID(SKS_CKFM_UNWRAP),
+ SKS_ID(SKS_CKFM_DERIVE),
+ SKS_ID(SKS_CKFM_EC_F_P),
+ SKS_ID(SKS_CKFM_EC_F_2M),
+ SKS_ID(SKS_CKFM_EC_ECPARAMETERS),
+ SKS_ID(SKS_CKFM_EC_NAMEDCURVE),
+ SKS_ID(SKS_CKFM_EC_UNCOMPRESS),
+ SKS_ID(SKS_CKFM_EC_COMPRESS),
+};
+
+static const struct string_id __maybe_unused string_functions[] = {
+ SKS_ID(SKS_FUNCTION_ENCRYPT),
+ SKS_ID(SKS_FUNCTION_DECRYPT),
+ SKS_ID(SKS_FUNCTION_SIGN),
+ SKS_ID(SKS_FUNCTION_VERIFY),
+ SKS_ID(SKS_FUNCTION_DERIVE),
+};
+
+/*
+ * Helper functions to analyse SKS identifiers
+ */
+
+size_t sks_attr_is_class(uint32_t attribute_id)
+{
+ if (attribute_id == SKS_CKA_CLASS)
+ return sizeof(uint32_t);
+ else
+ return 0;
+}
+
+size_t sks_attr_is_type(uint32_t attribute_id)
+{
+ switch (attribute_id) {
+ case SKS_CKA_CERTIFICATE_TYPE:
+ case SKS_CKA_KEY_TYPE:
+ case SKS_CKA_MECHANISM_TYPE:
+ case SKS_CKA_KEY_GEN_MECHANISM:
+ return sizeof(uint32_t);
+ default:
+ return 0;
+ }
+}
+
+bool sks_class_has_type(uint32_t class)
+{
+ switch (class) {
+ case SKS_CKO_CERTIFICATE:
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_MECHANISM:
+ case SKS_CKO_HW_FEATURE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+bool sks_attr_class_is_key(uint32_t class)
+{
+ switch (class) {
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Returns shift position or -1 on error */
+int sks_attr2boolprop_shift(uint32_t attr)
+{
+ COMPILE_TIME_ASSERT(SKS_BOOLPROPS_BASE == 0);
+
+ if (attr > SKS_BOOLPROPS_LAST)
+ return -1;
+
+ return attr;
+}
+
+/*
+ * Conversion between SKS and GPD TEE return codes
+ */
+
+TEE_Result sks2tee_error(uint32_t rv)
+{
+ switch (rv) {
+ case SKS_CKR_OK:
+ return TEE_SUCCESS;
+
+ case SKS_CKR_ARGUMENTS_BAD:
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ case SKS_CKR_DEVICE_MEMORY:
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ case SKS_CKR_BUFFER_TOO_SMALL:
+ return TEE_ERROR_SHORT_BUFFER;
+
+ default:
+ return TEE_ERROR_GENERIC;
+ }
+}
+
+TEE_Result sks2tee_noerr(uint32_t rc)
+{
+ switch (rc) {
+ case SKS_CKR_ARGUMENTS_BAD:
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ case SKS_CKR_DEVICE_MEMORY:
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ case SKS_CKR_BUFFER_TOO_SMALL:
+ return TEE_ERROR_SHORT_BUFFER;
+
+ case SKS_CKR_GENERAL_ERROR:
+ return TEE_ERROR_GENERIC;
+
+ default:
+ return TEE_SUCCESS;
+ }
+}
+
+uint32_t tee2sks_error(TEE_Result res)
+{
+ switch (res) {
+ case TEE_SUCCESS:
+ return SKS_CKR_OK;
+
+ case TEE_ERROR_BAD_PARAMETERS:
+ return SKS_CKR_ARGUMENTS_BAD;
+
+ case TEE_ERROR_OUT_OF_MEMORY:
+ return SKS_CKR_DEVICE_MEMORY;
+
+ case TEE_ERROR_SHORT_BUFFER:
+ return SKS_CKR_BUFFER_TOO_SMALL;
+
+ case TEE_ERROR_MAC_INVALID:
+ return SKS_CKR_SIGNATURE_INVALID;
+
+ case TEE_ERROR_SIGNATURE_INVALID:
+ return SKS_CKR_SIGNATURE_INVALID;
+
+ default:
+ return SKS_CKR_GENERAL_ERROR;
+ }
+}
+
+bool valid_sks_attribute_id(uint32_t id, uint32_t size)
+{
+ size_t n = 0;
+
+ for (n = 0; n < ARRAY_SIZE(attr_ids); n++) {
+ if (id != attr_ids[n].id)
+ continue;
+
+ /* Check size matches if provided */
+ return !attr_ids[n].size || size == attr_ids[n].size;
+ }
+
+ return false;
+}
+
+bool key_type_is_symm_key(uint32_t id)
+{
+ switch (id) {
+ case SKS_CKK_AES:
+ case SKS_CKK_GENERIC_SECRET:
+ case SKS_CKK_MD5_HMAC:
+ case SKS_CKK_SHA_1_HMAC:
+ case SKS_CKK_SHA224_HMAC:
+ case SKS_CKK_SHA256_HMAC:
+ case SKS_CKK_SHA384_HMAC:
+ case SKS_CKK_SHA512_HMAC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool key_type_is_asymm_key(uint32_t id)
+{
+ switch (id) {
+ case SKS_CKK_EC:
+ case SKS_CKK_RSA:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool certificate_is_valid(uint32_t id)
+{
+ switch (id) {
+ case SKS_CKC_X_509:
+ case SKS_CKC_X_509_ATTR_CER:
+ case SKS_CKC_WTLS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool mechanism_is_valid(uint32_t id)
+{
+ size_t n = 0;
+
+ for (n = 0; n < ARRAY_SIZE(processing_ids); n++)
+ if (id == processing_ids[n].id)
+ return true;
+
+ return false;
+}
+
+bool mechanism_is_supported(uint32_t id)
+{
+ size_t n = 0;
+
+ for (n = 0; n < ARRAY_SIZE(processing_ids); n++) {
+ if (processing_ids[n].id == id)
+ return processing_ids[n].supported;
+ }
+
+ return false;
+}
+
+size_t get_supported_mechanisms(uint32_t *array, size_t array_count)
+{
+ size_t n = 0;
+ size_t m = 0;
+ size_t count = 0;
+
+ for (n = 0; n < ARRAY_SIZE(processing_ids); n++) {
+ if (processing_ids[n].supported)
+ count++;
+ }
+
+ if (array_count == 0)
+ return count;
+
+ if (array_count < count) {
+ EMSG("Expect well sized array");
+ return 0;
+ }
+
+ if (!array) {
+ EMSG("array is NULL");
+ TEE_Panic(0);
+ }
+
+ for (n = 0, m = 0; n < ARRAY_SIZE(processing_ids); n++) {
+ if (processing_ids[n].supported) {
+ array[m] = processing_ids[n].id;
+ m++;
+ }
+ }
+
+ assert(m == count);
+
+ return m;
+}
+
+/* Initialize a TEE attribute for a target SKS attribute in an object */
+bool sks2tee_load_attr(TEE_Attribute *tee_ref, uint32_t tee_id,
+ struct sks_object *obj, uint32_t sks_id)
+{
+ void *a_ptr = NULL;
+ uint32_t a_size = 0;
+ uint32_t data32 = 0;
+
+ switch (tee_id) {
+ case TEE_ATTR_ECC_PUBLIC_VALUE_X:
+ case TEE_ATTR_ECC_PUBLIC_VALUE_Y:
+ case TEE_ATTR_ECC_CURVE:
+ if (get_attribute_ptr(obj->attributes, SKS_CKA_EC_PARAMS,
+ &a_ptr, &a_size)) {
+ EMSG("Missing EC_PARAMS attribute");
+ return false;
+ }
+
+ if (tee_id == TEE_ATTR_ECC_CURVE) {
+ data32 = ec_params2tee_curve(a_ptr, a_size);
+ TEE_InitValueAttribute(tee_ref, TEE_ATTR_ECC_CURVE,
+ data32, 0);
+ return true;
+ }
+
+ data32 = (ec_params2tee_keysize(a_ptr, a_size) + 7) / 8;
+
+ if (get_attribute_ptr(obj->attributes, SKS_CKA_EC_POINT,
+ &a_ptr, &a_size)) {
+ /*
+ * Public X/Y is required for both TEE keypair and
+ * public key, so abort if EC_POINT is not provided
+ * during object import.
+ */
+ EMSG("Missing EC_POINT attribute");
+ return false;
+ }
+
+ /* TODO: Support DER long definitive form */
+ if (a_size >= 0x80) {
+ EMSG("DER long definitive form not yet supported");
+ return false;
+ }
+ if (((char *)a_ptr)[2] != 0x04) {
+ EMSG("Unsupported EC_POINT form");
+ return false;
+ }
+ if (a_size != 2 + 2 * data32 + 1) {
+ EMSG("Invalid EC_POINT attribute");
+ return false;
+ }
+
+ if (tee_id == TEE_ATTR_ECC_PUBLIC_VALUE_X)
+ TEE_InitRefAttribute(tee_ref, tee_id,
+ (uint8_t *)a_ptr + 3, data32);
+ else
+ TEE_InitRefAttribute(tee_ref, tee_id,
+ (uint8_t *)a_ptr + 3 + data32, data32);
+
+ return true;
+
+ default:
+ break;
+ }
+
+ if (get_attribute_ptr(obj->attributes, sks_id, &a_ptr, &a_size))
+ return false;
+
+ TEE_InitRefAttribute(tee_ref, tee_id, a_ptr, a_size);
+
+ return true;
+}
+
+/* Easy conversion between SKS function of TEE crypto mode */
+void sks2tee_mode(uint32_t *tee_id, uint32_t function)
+{
+ switch (function) {
+ case SKS_FUNCTION_ENCRYPT:
+ *tee_id = TEE_MODE_ENCRYPT;
+ break;
+ case SKS_FUNCTION_DECRYPT:
+ *tee_id = TEE_MODE_DECRYPT;
+ break;
+ case SKS_FUNCTION_SIGN:
+ *tee_id = TEE_MODE_SIGN;
+ break;
+ case SKS_FUNCTION_VERIFY:
+ *tee_id = TEE_MODE_VERIFY;
+ break;
+ case SKS_FUNCTION_DERIVE:
+ *tee_id = TEE_MODE_DERIVE;
+ break;
+ default:
+ TEE_Panic(function);
+ }
+}
+
+#if CFG_TEE_TA_LOG_LEVEL > 0
+/*
+ * Convert a SKS ID into its label string
+ */
+const char *sks2str_attr(uint32_t id)
+{
+ size_t n = 0;
+
+ for (n = 0; n < ARRAY_SIZE(attr_ids); n++) {
+ if (id != attr_ids[n].id)
+ continue;
+
+ /* Skip SKS_ prefix */
+ return (char *)attr_ids[n].string + strlen("SKS_CKA_");
+ }
+
+ return unknown;
+}
+
+static const char *sks2str_mechanism_type(uint32_t id)
+{
+ size_t n = 0;
+
+ for (n = 0; n < ARRAY_SIZE(processing_ids); n++) {
+ if (id != processing_ids[n].id)
+ continue;
+
+ /* Skip SKS_ prefix */
+ return (char *)processing_ids[n].string + strlen("SKS_CKM_");
+ }
+
+ return unknown;
+}
+
+static const char *id2str(uint32_t id, const struct string_id *table,
+ size_t count, const char *prefix)
+{
+ size_t n = 0;
+ const char *str = NULL;
+
+ for (n = 0; n < count; n++) {
+ if (id != table[n].id)
+ continue;
+
+ str = table[n].string;
+
+ /* Skip prefix provided matches found */
+ if (prefix && !TEE_MemCompare(str, prefix, strlen(prefix)))
+ str += strlen(prefix);
+
+ return str;
+ }
+
+ return unknown;
+}
+
+#define ID2STR(id, table, prefix) \
+ id2str(id, table, ARRAY_SIZE(table), prefix)
+
+const char *sks2str_class(uint32_t id)
+{
+ return ID2STR(id, string_class, "SKS_CKO_");
+}
+
+const char *sks2str_type(uint32_t id, uint32_t class)
+{
+ switch (class) {
+ case SKS_CKO_SECRET_KEY:
+ case SKS_CKO_PUBLIC_KEY:
+ case SKS_CKO_PRIVATE_KEY:
+ return sks2str_key_type(id);
+ default:
+ return unknown;
+ }
+}
+const char *sks2str_key_type(uint32_t id)
+{
+ return ID2STR(id, string_key_type, "SKS_CKK_");
+}
+
+const char *sks2str_certificate_type(uint32_t id)
+{
+ return ID2STR(id, string_certificate_type, "SKS_CKC_");
+}
+
+const char *sks2str_boolprop(uint32_t id)
+{
+ if (id < 64)
+ return sks2str_attr(id);
+
+ return unknown;
+}
+
+const char *sks2str_proc(uint32_t id)
+{
+ const char *str = ID2STR(id, string_internal_processing,
+ "SKS_PROCESSING_");
+
+ if (str != unknown)
+ return str;
+
+ return sks2str_mechanism_type(id);
+}
+
+const char *sks2str_proc_flag(uint32_t id)
+{
+ return ID2STR(id, string_proc_flags, "SKS_CKFM_");
+}
+
+const char *sks2str_rc(uint32_t id)
+{
+ return ID2STR(id, string_rc, "SKS_CKR_");
+}
+
+const char *sks2str_skscmd(uint32_t id)
+{
+ return ID2STR(id, string_cmd, NULL);
+}
+
+const char *sks2str_slot_flag(uint32_t id)
+{
+ return ID2STR(id, string_slot_flags, "SKS_CKFS_");
+}
+
+const char *sks2str_token_flag(uint32_t id)
+{
+ return ID2STR(id, string_token_flags, "SKS_CKFT_");
+}
+
+const char *sks2str_attr_value(uint32_t id, size_t size, void *value)
+{
+ static const char str_true[] = "TRUE";
+ static const char str_false[] = "FALSE";
+ static const char str_unkwon[] = "*";
+ uint32_t type = 0;
+
+ if (sks_attr2boolprop_shift(id) >= 0)
+ return !!*(uint8_t *)value ? str_true : str_false;
+
+ if (size < sizeof(uint32_t))
+ return str_unkwon;
+
+ TEE_MemMove(&type, value, sizeof(uint32_t));
+
+ if (sks_attr_is_class(id))
+ return sks2str_class(type);
+
+ if (id == SKS_CKA_KEY_TYPE)
+ return sks2str_key_type(type);
+
+ if (id == SKS_CKA_MECHANISM_TYPE)
+ return sks2str_mechanism_type(type);
+
+ return str_unkwon;
+}
+
+const char *sks2str_function(uint32_t id)
+{
+ return ID2STR(id, string_functions, "SKS_FUNCTION_");
+}
+#endif /*CFG_TEE_TA_LOG_LEVEL*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_helpers.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_helpers.h
new file mode 100644
index 0000000..c394a7a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_helpers.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#ifndef __SKS_HELPERS_H
+#define __SKS_HELPERS_H
+
+#include <sks_ta.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <tee_internal_api.h>
+
+/* Short aliases for return code */
+#define SKS_OK SKS_CKR_OK
+#define SKS_ERROR SKS_CKR_GENERAL_ERROR
+#define SKS_MEMORY SKS_CKR_DEVICE_MEMORY
+#define SKS_BAD_PARAM SKS_CKR_ARGUMENTS_BAD
+#define SKS_SHORT_BUFFER SKS_CKR_BUFFER_TOO_SMALL
+#define SKS_FAILED SKS_CKR_FUNCTION_FAILED
+
+struct sks_object;
+
+/*
+ * Helper functions to analyse CK fields
+ */
+bool valid_sks_attribute_id(uint32_t id, uint32_t size);
+
+size_t sks_attr_is_class(uint32_t attribute_id);
+size_t sks_attr_is_type(uint32_t attribute_id);
+bool sks_class_has_boolprop(uint32_t class);
+bool sks_class_has_type(uint32_t class);
+bool sks_attr_class_is_key(uint32_t class);
+int sks_attr2boolprop_shift(uint32_t attr);
+
+bool key_type_is_symm_key(uint32_t id);
+bool key_type_is_asymm_key(uint32_t id);
+bool certificate_is_valid(uint32_t id);
+bool mechanism_is_valid(uint32_t id);
+size_t get_supported_mechanisms(uint32_t *array, size_t array_count);
+bool mechanism_is_supported(uint32_t id);
+
+void sks2tee_mode(uint32_t *tee_id, uint32_t function);
+bool sks2tee_load_attr(TEE_Attribute *tee_ref, uint32_t tee_id,
+ struct sks_object *obj, uint32_t sks_id);
+
+/*
+ * Convert SKS return code into a GPD TEE result ID when matching.
+ * If not, return a TEE success (_noerr) or generic error (_error).
+ */
+TEE_Result sks2tee_noerr(uint32_t rv);
+TEE_Result sks2tee_error(uint32_t rv);
+uint32_t tee2sks_error(TEE_Result res);
+
+/* Id-to-string conversions when CFG_TEE_TA_LOG_LEVEL > 0 */
+const char *sks2str_attr(uint32_t id);
+const char *sks2str_class(uint32_t id);
+const char *sks2str_type(uint32_t id, uint32_t class);
+const char *sks2str_key_type(uint32_t id);
+const char *sks2str_certificate_type(uint32_t id);
+const char *sks2str_boolprop(uint32_t id);
+const char *sks2str_proc(uint32_t id);
+const char *sks2str_proc_flag(uint32_t id);
+const char *sks2str_slot_flag(uint32_t id);
+const char *sks2str_token_flag(uint32_t id);
+const char *sks2str_rc(uint32_t id);
+const char *sks2str_skscmd(uint32_t id);
+const char *sks2str_attr_value(uint32_t id, size_t size, void *value);
+const char *sks2str_function(uint32_t id);
+
+#endif /*__CK_HELPERS_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_hsm_debug.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_hsm_debug.h
new file mode 100644
index 0000000..5c5d0df
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sks_hsm_debug.h
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef __SKS_HSM_DEBUG_H__
+#define __SKS_HSM_DEBUG_H__
+
+/****************************************
+ * # 0: none
+ * # 1: error
+ * # 2: error + warning
+ * # 3: error + warning + debug
+ * # 4: error + warning + debug + flow
+ ****************************************/
+#define SKS_HSM_LOG_LEVEL 3
+
+#define SKS_HSM_ERROR_LOG_LEVEL 1
+#define SKS_HSM_INFO_LOG_LEVEL 2
+#define SKS_HSM_DEBUG_LOG_LEVEL 3
+#define SKS_HSM_FLOW_LOG_LEVEL 4
+
+#if (SKS_HSM_FLOW_LOG_LEVEL <= SKS_HSM_LOG_LEVEL)
+#define SKS_HSM_FLOW(x...) FMSG(x)
+#else
+#define SKS_HSM_FLOW(x...)
+#endif
+
+#if (SKS_HSM_DEBUG_LOG_LEVEL <= SKS_HSM_LOG_LEVEL)
+#define SKS_HSM_DEBUG(x...) DMSG(x)
+#else
+#define SKS_HSM_DEBUG(x...)
+#endif
+
+#if (SKS_HSM_INFO_LOG_LEVEL <= SKS_HSM_LOG_LEVEL)
+#define SKS_HSM_INFO(x...) IMSG(x)
+#else
+#define SKS_HSM_INFO(x...)
+#endif
+
+#if (SKS_HSM_ERROR_LOG_LEVEL <= SKS_HSM_LOG_LEVEL)
+#define SKS_HSM_ERROR(x...) EMSG(x)
+#else
+#define SKS_HSM_ERROR(x...)
+#endif
+
+
+#endif /*__SKS_HSM_DEBUG_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sub.mk
new file mode 100644
index 0000000..f5a3d15
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/sub.mk
@@ -0,0 +1,18 @@
+srcs-y += entry.c
+srcs-y += sks_helpers.c
+srcs-y += handle.c
+srcs-y += pkcs11_token.c
+srcs-y += persistent_token.c
+srcs-y += serializer.c
+srcs-y += sanitize_object.c
+srcs-y += object.c
+srcs-y += processing.c
+srcs-y += processing_aes.c
+srcs-y += pkcs11_attributes.c
+srcs-y += attributes.c
+srcs-y += processing_symm.c
+srcs-y += processing_ec.c
+srcs-y += processing_rsa.c
+srcs-y += processing_asymm.c
+srcs-y += processing_mtk_hsm.c
+srcs-y += processing_mtk_key.c
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/user_ta_header_defines.h b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/user_ta_header_defines.h
new file mode 100644
index 0000000..1d33a3e
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/src/user_ta_header_defines.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2017-2018, Linaro Limited
+ */
+
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+#include <sks_ta.h>
+
+#define TA_UUID TA_SKS_UUID
+
+#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \
+ TA_FLAG_MULTI_SESSION | \
+ TA_FLAG_EXEC_DDR | \
+ TA_FLAG_INSTANCE_KEEP_ALIVE)
+
+#define TA_STACK_SIZE (2 * 1024)
+#define TA_DATA_SIZE (16 * 1024)
+
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
+ "Secure key services trusted application" }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0000 } }
+
+#endif /*USER_TA_HEADER_DEFINES_H*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/sub.mk
new file mode 100644
index 0000000..b927f9b
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/sub.mk
@@ -0,0 +1,6 @@
+global-incdirs-y += include
+global-incdirs-y += src
+subdirs-y += src
+
+CFG_SKS_TA_TOKEN_COUNT ?= 3
+CPPFLAGS += -DCFG_SKS_TA_TOKEN_COUNT=$(CFG_SKS_TA_TOKEN_COUNT)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/ta.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/ta.mk
new file mode 100644
index 0000000..19c6061
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/ta.mk
@@ -0,0 +1,3 @@
+LOCAL_PATH := $(call my-dir)
+local_module := fd02c9da-306c-48c7-a49c-bbd827ae86ee.ta
+include $(BUILD_OPTEE_MK)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/user_ta.mk b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/user_ta.mk
new file mode 100644
index 0000000..f3ada68
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/optee_services/secure_key_services/ta/user_ta.mk
@@ -0,0 +1 @@
+user-ta-uuid := fd02c9da-306c-48c7-a49c-bbd827ae86ee
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/gpt.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/gpt.c
new file mode 100644
index 0000000..aba6236
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/gpt.c
@@ -0,0 +1,196 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#include <kernel/pseudo_ta.h>
+#include <kernel/thread.h>
+#include <kernel/interrupt.h>
+#include <kernel/misc.h>
+#include <mm/core_memprot.h>
+#include <kernel/tee_time.h>
+#include <io.h>
+#include "gpt.h"
+// #include <initcall.h>
+
+register_phys_mem(MEM_AREA_IO_NSEC, GPT_BASE, GPT_SIZE);
+vaddr_t gpt_base;
+extern bool itr_set_polarity(unsigned int irq, unsigned int polarity);
+
+void dump_gpt(void){
+ DMSG("-------------gpt dump start---------------------");
+ DMSG("GPT_IRQEN:%x at %p", read32(gpt_base+GPT_IRQEN),gpt_base+GPT_IRQEN);
+ DMSG("GPT_IRQSTA:%x at %p", read32(gpt_base+GPT_IRQSTA),gpt_base+GPT_IRQSTA);
+ DMSG("GPT_IRQACK:%x at %p", read32(gpt_base+GPT_IRQACK),gpt_base+GPT_IRQACK);
+ int i=0;
+ for (i=0;i<6;i++){
+ DMSG("GPT(%d) GPT_CON:%x at %p", i, read32(gpt_base+GPT_CON(i)), gpt_base+GPT_CON(i));
+ DMSG("GPT(%d) GPT_CLK:%x at %p", i, read32(gpt_base+GPT_CLK(i)), gpt_base+GPT_CLK(i));
+ DMSG("GPT(%d) GPT_COUNT:%x at %p", i, read32(gpt_base+GPT_COUNT(i)), gpt_base+GPT_COUNT(i));
+ DMSG("GPT(%d) GPT_COMPARE:%x at %p", i, read32(gpt_base+GPT_COMPARE(i)), gpt_base+GPT_COMPARE(i));
+ }
+ DMSG("-------------gpt dump end---------------------");
+}
+void gpt_irqen(uint8_t gpt_num)
+{
+ uint32_t value = read32(gpt_base+GPT_IRQEN);
+ value |= (1<<(gpt_num));
+ write32(value, gpt_base+GPT_IRQEN);
+ DMSG("write %x to %p", value, gpt_base+GPT_IRQEN);
+}
+
+void gpt_irqdisableall(void)
+{
+ write32(0, gpt_base+GPT_IRQEN);
+ DMSG("write %x to %p", 0, gpt_base+GPT_IRQEN);
+}
+
+void gpt_irqackall(void)
+{
+ write32(0x3F, gpt_base+GPT_IRQACK);
+ DMSG("write %x to %p", 0x3F, gpt_base+GPT_IRQEN);
+}
+
+void gpt_reset(uint8_t gpt_num)
+{
+ write32(0x2, gpt_base+GPT_CON(gpt_num));
+ write32(0, gpt_base+GPT_CLK(gpt_num));
+ write32(0, gpt_base+GPT_COMPARE(gpt_num));
+}
+
+uint8_t gpt_irqsta_all()
+{
+ return read32(gpt_base+GPT_IRQSTA);
+}
+
+uint8_t gpt_irqsta(uint8_t gpt_num)
+{
+ return (read32(gpt_base+GPT_IRQSTA) & (1<<gpt_num));
+}
+
+void gpt_ackirq(uint8_t gpt_num)
+{
+ write32((0x1<<gpt_num), gpt_base+GPT_IRQACK);
+}
+
+void gpt_enable(uint8_t gpt_num, uint8_t mode)
+{
+ //clear
+ write32(0x2, gpt_base+GPT_CON(gpt_num));
+ uint32_t value = (mode & 0x30) | 0x1;
+ DMSG("write %x to %p", value, gpt_base+GPT_CON(gpt_num));
+ write32(value, gpt_base+GPT_CON(gpt_num));
+}
+
+void gpt_set_compare(uint8_t gpt_num, uint32_t value)
+{
+ DMSG("write %x to %p", value, gpt_base+GPT_COMPARE(gpt_num));
+ write32(value, gpt_base+GPT_COMPARE(gpt_num));
+}
+
+static enum itr_return gpt_itr_cb(struct itr_handler *h)
+{
+ uint8_t data = *((uint8_t*)(h->data));
+ EMSG("cpu %zu: got gpt interrupt for gpt :%d.", get_core_pos(), data);
+ //dump_gpt();
+ gpt_ackirq(data);
+ //dump_gpt();
+ return ITRR_HANDLED;
+}
+
+uint8_t gpt_itr_data = 0;
+static struct itr_handler gpt_itr = {
+ .it = IT_GPT_NUMBER,
+ .flags = ITRF_TRIGGER_LEVEL,
+ .handler = gpt_itr_cb,
+ .data = &gpt_itr_data,
+};
+KEEP_PAGER(gpt_itr);
+
+static TEE_Result init_gpt_itr(uint8_t gpt_num)
+{
+ *((uint8_t*)(gpt_itr.data)) = gpt_num;
+ itr_add(&gpt_itr);
+ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!Attention!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ // This is for mtk mt2712 platform specificlly.
+ // If the irq is low level trigger, need to invert the trigger polarity.
+ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!Attention!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ itr_set_polarity(IT_GPT_NUMBER, (gpt_itr.flags & ITRF_TRIGGER_LEVEL)==ITRF_TRIGGER_LEVEL);
+ itr_enable(IT_GPT_NUMBER);
+ return TEE_SUCCESS;
+}
+
+void gpt_init(uint8_t gpt_num, uint32_t time)
+{
+ gpt_base = (vaddr_t)phys_to_virt_io(GPT_BASE);
+ IMSG("gpt_base: %p\n", gpt_base);
+ //dump_gpt();
+ // Clear the status of gpt as they may used in NWD.
+ gpt_irqdisableall();
+ gpt_irqackall();
+ gpt_reset(0);
+ gpt_reset(1);
+ gpt_set_compare(gpt_num, time*13000000);
+ init_gpt_itr(gpt_num);
+ gpt_irqen(gpt_num);
+ gpt_enable(gpt_num, 0/*mode*/);
+ //dump_gpt();
+}
+
+static TEE_Result invoke_command(void *pSessionContext __unused,
+ uint32_t nCommandID, uint32_t nParamTypes,
+ TEE_Param pParams[TEE_NUM_PARAMS])
+{
+ IMSG("GPT nCommandID(%x)\n", nCommandID);
+ switch (nCommandID) {
+ case PTA_CMD_GPT_INIT:
+ if (TEE_PARAM_TYPE_GET(nParamTypes, 0) !=
+ TEE_PARAM_TYPE_VALUE_INPUT)
+ return TEE_ERROR_BAD_PARAMETERS;
+ uint32_t gpt_num = pParams[0].value.a;
+ uint32_t time_value = pParams[0].value.b;
+ IMSG("input value gpt num:%d, time:%d s\n", gpt_num, time_value);
+ gpt_init(gpt_num, time_value);
+ return TEE_SUCCESS;
+
+ default:
+ break;
+ }
+
+ return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+pseudo_ta_register(.uuid = PTA_GPT_TEST_PTA_UUID, .name = "gpt",
+ .flags = PTA_DEFAULT_FLAGS,
+ .invoke_command_entry_point = invoke_command);
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/gpt.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/gpt.h
new file mode 100644
index 0000000..a5f7668
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/gpt.h
@@ -0,0 +1,60 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#ifndef __GPT_H__
+#define __GPT_H__
+
+#include <sm/optee_smc.h>
+
+#define PTA_GPT_TEST_PTA_UUID { 0x472567ad, 0xa180, 0x402c, \
+ { 0x50, 0x95, 0x7b, 0x4e, 0xd3, 0xe0, 0x5e, 0x83 } }
+
+#define GPT_BASE 0x10008000
+#define GPT_SIZE 0xA0
+#define GPT_IRQEN (0x0)
+#define GPT_IRQSTA (0x4)
+#define GPT_IRQACK (0x8)
+
+#define GPT_N(n) ((n+1)<<4)
+#define GPT_CON(n) (GPT_N(n)+(0x0))
+#define GPT_CLK(n) (GPT_N(n)+(0x4))
+#define GPT_COUNT(n) (GPT_N(n)+(0x8))
+#define GPT_COMPARE(n) (GPT_N(n)+(0xC))
+
+
+#define IT_GPT_NUMBER 184
+
+#define PTA_CMD_GPT_INIT 0
+#endif /* __GPT_H__ */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/pta.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/pta.mk
new file mode 100644
index 0000000..e82d4fa
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/pta.mk
@@ -0,0 +1,5 @@
+libdir := $(call my-dir)
+libname := gpt
+
+include $(BUILD_OPTEE_OS_LIB)
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/sub.mk
new file mode 100644
index 0000000..6bdb8bd
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/gpt/sub.mk
@@ -0,0 +1,4 @@
+srcs-y := \
+ gpt.c \
+
+$(call add-pta-src, gpt.c)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/address.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/address.h
new file mode 100644
index 0000000..e72b758
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/address.h
@@ -0,0 +1,47 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef _ADDRESS_H_
+#define _ADDRESS_H_
+
+typedef struct addr_t
+{
+ void *pa; // physical address in AP view
+ void *va; // virtual address
+ void *ha; // physical address in HSM view
+} addr_t;
+
+#endif /* end of include guard: _ADDRESS_H_ */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy.c
new file mode 100644
index 0000000..1206eae
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy.c
@@ -0,0 +1,354 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <mm/core_memprot.h>
+#include <tee/cache.h>
+#include "buddy.h"
+#include "buddy_config.h"
+#include "share_memmap.h"
+
+#if BUDDY_MEMPOOL_SIZE > BUDDY_MEMPOOL_BUF_LEN
+#error "[buddy system] not enough memory..."
+#endif
+
+#define max(a, b) (((a)>(b))?(a):(b))
+#define min(a, b) (((a)<(b))?(a):(b))
+
+typedef uint16_t node_len_t ;
+
+struct buddy {
+ uint32_t size;
+ node_len_t longest[];
+};
+
+static struct buddy *__instance = NULL;
+// static uint8_t buddy_table[sizeof(struct buddy) + 2 * BUDDY_TOTAL_BLOCKS * sizeof(node_len_t)];
+static uint8_t *memory_pool = NULL;
+static vaddr_t v_memory_pool;
+
+static inline int left_child(int index)
+{
+ /* index * 2 + 1 */
+ return ((index << 1) + 1);
+}
+
+static inline int right_child(int index)
+{
+ /* index * 2 + 2 */
+ return ((index << 1) + 2);
+}
+
+static inline int parent(int index)
+{
+ /* (index+1)/2 - 1 */
+ return (((index + 1) >> 1) - 1);
+}
+
+static inline bool is_power_of_2(int index)
+{
+ return !(index & (index - 1));
+}
+
+static inline unsigned next_power_of_2(unsigned size)
+{
+ /* depend on the fact that size < 2^32 */
+ size -= 1;
+ size |= (size >> 1);
+ size |= (size >> 2);
+ size |= (size >> 4);
+ size |= (size >> 8);
+ size |= (size >> 16);
+ return size + 1;
+}
+
+static inline uint8_t *get_va_in_mempool(int idx)
+{
+ return (v_memory_pool + (idx << BUDDY_BLOCK_SIZE_ORDER));
+}
+
+static inline uint8_t *get_pa_in_mempool(int idx)
+{
+ return (memory_pool + (idx << BUDDY_BLOCK_SIZE_ORDER));
+}
+
+static inline int map_pa_2_idx_in_mempool(uint8_t * ptr)
+{
+ return (((int)ptr - (int)memory_pool) >> BUDDY_BLOCK_SIZE_ORDER);
+}
+
+void buddy_init(void)
+{
+ if (__instance != NULL) {
+ return;
+ }
+
+ struct buddy *self = NULL;
+ node_len_t node_size;
+ unsigned num_of_fragments = BUDDY_TOTAL_BLOCKS;
+ int i;
+ int table_size = sizeof(struct buddy) + 2 * BUDDY_TOTAL_BLOCKS * sizeof(node_len_t);
+
+ /* alloacte an array to represent a complete binary tree */
+ self = (struct buddy *) malloc(table_size);
+ memset(self, 0, table_size);
+
+ self->size = num_of_fragments;
+ node_size = num_of_fragments * 2;
+
+ /* initialize *longest* array for buddy structure */
+ int iter_end = num_of_fragments * 2 - 1;
+ for (i = 0; i < iter_end; i++) {
+ if (is_power_of_2(i + 1)) {
+ node_size >>= 1;
+ }
+ self->longest[i] = node_size;
+ }
+
+ core_mmu_add_mapping(MEM_AREA_RAM_SEC, TEE_BUDDY_MEMPOOL_BUF_BASE, TEE_BUDDY_MEMPOOL_BUF_LEN);
+ v_memory_pool = (vaddr_t)phys_to_virt(TEE_BUDDY_MEMPOOL_BUF_BASE, MEM_AREA_RAM_SEC);
+
+ if (cache_operation(TEE_CACHEINVALIDATE, v_memory_pool, TEE_BUDDY_MEMPOOL_BUF_LEN) != TEE_SUCCESS) {
+ EMSG("[\x1b[31m%s\033[0m][%d] cache invalidate fail\n", __FUNCTION__, __LINE__);
+ return;
+ }
+
+ memory_pool = (uint8_t *)TEE_BUDDY_MEMPOOL_BUF_BASE;
+ __instance = (void*)self;
+
+
+}
+
+void buddy_deinit(void)
+{
+ memory_pool = NULL;
+ __instance = NULL;
+}
+
+/* choose the child with smaller longest value which is still larger
+ * than *size* */
+unsigned choose_better_child(struct buddy *self, unsigned index, size_t size)
+{
+ struct compound {
+ size_t size;
+ unsigned index;
+ } children[2];
+
+ children[0].index = left_child(index);
+ children[0].size = self->longest[children[0].index];
+ children[1].index = right_child(index);
+ children[1].size = self->longest[children[1].index];
+
+ int min_idx = (children[0].size <= children[1].size) ? 0 : 1;
+
+ if (size > children[min_idx].size) {
+ min_idx = 1 - min_idx;
+ }
+
+ return children[min_idx].index;
+}
+
+/** allocate *size* from a buddy system *self*
+ * @return the offset from the beginning of memory to be managed */
+int buddy_alloc_blk(size_t size)
+{
+ struct buddy *self = __instance;
+
+ if (self == NULL || self->size < size || size <= 0) {
+ return -1;
+ }
+
+ size = next_power_of_2(size);
+
+ unsigned index = 0;
+ if (self->longest[index] < size) {
+ return -1;
+ }
+
+ /* search recursively for the child */
+ unsigned node_size = 0;
+ for (node_size = self->size; node_size != size; node_size >>= 1) {
+ /* choose the child with smaller longest value which is still larger
+ * than *size* */
+ /* TODO */
+ index = choose_better_child(self, index, size);
+ }
+
+ /* update the *longest* value back */
+ self->longest[index] = 0;
+ int offset = (index + 1) * node_size - self->size;
+
+ while (index) {
+ index = parent(index);
+ self->longest[index] =
+ max(self->longest[left_child(index)],
+ self->longest[right_child(index)]);
+ }
+
+ return offset;
+}
+
+void buddy_free_blk(int offset)
+{
+ struct buddy *self = __instance;
+
+ if (self == NULL || offset < 0 || offset > self->size) {
+ return;
+ }
+
+ node_len_t node_size;
+ unsigned index;
+
+ /* get the corresponding index from offset */
+ node_size = 1;
+ index = offset + self->size - 1;
+
+ for (; self->longest[index] != 0; index = parent(index)) {
+ node_size <<= 1; /* node_size *= 2; */
+
+ if (index == 0) {
+ break;
+ }
+ }
+
+ self->longest[index] = node_size;
+
+ while (index) {
+ index = parent(index);
+ node_size <<= 1;
+
+ node_len_t left_longest = self->longest[left_child(index)];
+ node_len_t right_longest = self->longest[right_child(index)];
+
+ if (left_longest + right_longest == node_size) {
+ self->longest[index] = node_size;
+ } else {
+ self->longest[index] = max(left_longest, right_longest);
+ }
+ }
+}
+
+void buddy_dump(void)
+{
+ struct buddy *self = __instance;
+
+ int len = self->size << 1;
+ int max_col = self->size << 1;
+ int level = 0;
+ int i, j;
+
+ char cs[] = {'/', '\\'};
+ int idx = 0;
+ char c;
+
+ for (i = 0, max_col = len, level = 0; i < len - 1; i++) {
+ if (is_power_of_2(i + 1)) {
+ max_col >>= 1;
+ level ++;
+ idx = 0;
+ // LOGE("\n%d(%3d): ", level, max_col);
+ }
+
+ // LOGE("%*d", max_col, self->longest[i]);
+ }
+
+ for (i = 0, max_col = len, level = 0; i < len - 1; i++) {
+ if (is_power_of_2(i + 1)) {
+ max_col >>= 1;
+ level ++;
+ idx = 0;
+ // LOGE("\n%d(%3d): ", level, max_col);
+ }
+
+ if (self->longest[i] > 0) {
+ c = '-';
+ } else {
+ c = cs[idx];
+ idx ^= 0x1;
+ }
+
+ for (j = 0; j < max_col; j++) {
+ // LOGE("%c", c);
+ }
+ }
+ // LOGE("\n");
+}
+
+int buddy_size(int offset)
+{
+ struct buddy *self = __instance;
+ unsigned node_size = 1;
+ unsigned index = offset + self->size - 1;
+
+ for (; self->longest[index]; index = parent(index)) {
+ node_size >>= 1;
+ }
+
+ return node_size;
+}
+
+int buddy_malloc(uint32_t size, addr_t *addr)
+{
+ int idx = -1;
+ int blks = 0;
+
+ blks = (size >> BUDDY_BLOCK_SIZE_ORDER) + 1;
+ idx = buddy_alloc_blk(blks);
+ if (idx < 0) {
+ // LOGE("[\x1b[34m%s\033[0m][%d] allocate fail\r\n", __FUNCTION__, __LINE__);
+ return BUDDY_FAIL;
+ }
+
+ addr->pa = get_pa_in_mempool(idx);
+ addr->va = get_va_in_mempool(idx);
+
+ return BUDDY_OK;
+}
+
+
+void buddy_free(addr_t *addr)
+{
+ int idx = -1;
+
+ idx = map_pa_2_idx_in_mempool(addr->pa);
+
+ buddy_free_blk(idx);
+}
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy.h
new file mode 100644
index 0000000..cf8c49b
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy.h
@@ -0,0 +1,50 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef BUDDY_H
+#define BUDDY_H
+
+#include <stdint.h>
+#include "address.h"
+
+#define BUDDY_OK (0)
+#define BUDDY_FAIL (-1)
+
+void buddy_init(void);
+int buddy_malloc(uint32_t size, addr_t *addr);
+void buddy_free(addr_t *addr);
+
+#endif /* end of include guard: BUDDY_H */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy_config.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy_config.h
new file mode 100644
index 0000000..49f77f2
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/buddy_config.h
@@ -0,0 +1,44 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef _BUDDY_CONFIG_H_
+
+#define BUDDY_TOTAL_BLOCKS (128)
+#define BUDDY_BLOCK_SIZE_ORDER (6)
+#define BUDDY_BLOCK_SIZE (1<<BUDDY_BLOCK_SIZE_ORDER) //64
+#define BUDDY_MEMPOOL_SIZE (BUDDY_BLOCK_SIZE*BUDDY_TOTAL_BLOCKS)
+
+#endif /* end of include guard: _BUDDY_CONFIG_H_ */
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_dump.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_dump.c
new file mode 100644
index 0000000..9c43efe
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_dump.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * Copyright (C) 2020 MediaTek Inc. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <io.h>
+#include <kernel/delay.h>
+#include <tee/cache.h>
+#include <optee_msg.h>
+#include <mm/core_memprot.h>
+#include "hsm_dump.h"
+#include "share_memmap.h"
+
+#define OPTEE_BUFFER_SHIFT (24) // specific for optee
+#define HSM_LOG_FMT_BUF_LEN 256UL
+
+#define HSM_LOG_BUF_LEN (LOG_BUF_LEN - sizeof(struct hsm_log)) /* 16KB - size of log buffer var*/
+#define HSM_LOG_BUF_BASE (JOB_PHYSICAL_BUF_BASE - HSM_LOG_BUF_LEN)
+#define HSM_LOG_BUF_VAR_LEN (sizeof(struct hsm_log)) /* size of log buffer var */
+#define HSM_LOG_BUF_VAR_BASE (HSM_LOG_BUF_BASE - HSM_LOG_BUF_VAR_LEN)
+
+struct hsm_log {
+ uint64_t log_next_seq;
+ uint64_t log_next_idx;
+ uint64_t log_first_seq;
+ uint64_t log_first_idx;
+} __attribute__ ((packed));
+
+struct log_header {
+ uint32_t next_idx;
+ uint32_t text_len;
+ uint32_t log_len;
+ int32_t loglevel;
+};
+
+uint8_t *gvBuffAddr = NULL;
+uint8_t *gvBuffVarAddr = NULL;
+
+static inline uint8_t *log_text(const struct log_header *msg)
+{
+ return (uint8_t *)msg + sizeof(struct log_header);
+}
+
+static void flush_to_console(uint8_t *msg, uint32_t len)
+{
+ uint32_t i = 0;
+ unsigned char str[256];
+ memset(str, 0, sizeof(str));
+ if (len > 255)
+ {
+ IMSG("ingore messge!!!");
+ }
+
+ for (i = 0; i < len; i++)
+ {
+ str[i] = *((char *)msg + i);
+ // IMSG("[%s][%d]\r\n", __FUNCTION__, __LINE__);
+ }
+ str[i] = '\0';
+ IMSG("%s", str);
+ mdelay(1);
+}
+
+static int clean_and_invalidate_log_buffer(void)
+{
+ if (gvBuffAddr == NULL || gvBuffVarAddr == NULL)
+ {
+ EMSG("== BUFFER NULL!! ==\n");
+ return -1;
+ }
+ if (cache_operation(TEE_CACHECLEAN, gvBuffAddr, HSM_LOG_BUF_LEN) != TEE_SUCCESS)
+ {
+ EMSG("== CACHE FAIL!! ==\n");
+ return -1;
+ }
+ if (cache_operation(TEE_CACHEINVALIDATE, gvBuffAddr, HSM_LOG_BUF_LEN) != TEE_SUCCESS)
+ {
+ EMSG("== CACHE INVALIDATE FAIL!! ==\n");
+ return -1;
+ }
+ if (cache_operation(TEE_CACHECLEAN, gvBuffVarAddr, HSM_LOG_BUF_VAR_LEN) != TEE_SUCCESS)
+ {
+ EMSG("== CACHE FAIL!! ==\n");
+ return -1;
+ }
+ if (cache_operation(TEE_CACHEINVALIDATE, gvBuffVarAddr, HSM_LOG_BUF_VAR_LEN) != TEE_SUCCESS)
+ {
+ EMSG("== CACHE INVALIDATE FAIL!! ==\n");
+ return -1;
+ }
+ return 0;
+}
+
+int hsm_dump_init(void)
+{
+ core_mmu_add_mapping(MEM_AREA_RAM_SEC, HSM_LOG_BUF_BASE, HSM_LOG_BUF_LEN);
+ gvBuffAddr = (vaddr_t)phys_to_virt(HSM_LOG_BUF_BASE, MEM_AREA_RAM_SEC);
+
+ if (gvBuffAddr == NULL)
+ {
+ EMSG("[%s][%d] memory map fail.\r\n", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ core_mmu_add_mapping(MEM_AREA_RAM_SEC, HSM_LOG_BUF_VAR_BASE, HSM_LOG_BUF_VAR_LEN);
+ gvBuffVarAddr = (vaddr_t)phys_to_virt(HSM_LOG_BUF_VAR_BASE, MEM_AREA_RAM_SEC);
+
+ if (gvBuffVarAddr == NULL)
+ {
+ EMSG("[%s][%d] memory map fail.\r\n", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int hsm_dump_log(void)
+{
+ struct hsm_log *Buff_log_Var_Addr;
+ uint32_t local_idx;
+ uint64_t local_first_seq;
+ struct log_header *msg;
+ volatile uint64_t *log_first_idx;
+ volatile uint64_t *log_first_seq;
+ volatile uint64_t *log_next_seq;
+
+ if(clean_and_invalidate_log_buffer() != 0)
+ {
+ EMSG("[%s][%d] clean & invalidate fail.\r\n", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ msg = (struct log_header *)gvBuffAddr;
+ Buff_log_Var_Addr = (struct hsm_log *)gvBuffVarAddr;
+
+ log_first_idx = (uint32_t *) & (Buff_log_Var_Addr->log_first_idx);
+ log_first_seq = &(Buff_log_Var_Addr->log_first_seq);
+ log_next_seq = &(Buff_log_Var_Addr->log_next_seq);
+
+ local_idx = *log_first_idx;
+ local_first_seq = *log_first_seq;
+ while (local_first_seq < *log_next_seq) {
+ msg = (struct log_header *)(gvBuffAddr + local_idx);
+
+ /* The log entry may be overwritten by the new log entry and
+ * the header becomes invalid due to slow UART TX speed.
+ * IF the header meets following conditions, we assume that
+ * the log entry is courrupted.
+ * 1. The text length is greater then LOG_FMT_BUF_LEN.
+ * 2. The text buffer address is out of range.
+ */
+
+ if ((msg->log_len > HSM_LOG_FMT_BUF_LEN) ||
+ (log_text(msg) > (gvBuffAddr + HSM_LOG_BUF_LEN)) ||
+ (log_text(msg) < gvBuffAddr)) {
+ IMSG("[%s][%d]\r\n", __FUNCTION__, __LINE__);
+ break;
+ }
+
+ flush_to_console((uint8_t *)log_text(msg), msg->text_len);
+ local_idx = msg->next_idx;
+ local_first_seq++;
+ }
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_dump.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_dump.h
new file mode 100644
index 0000000..ddf1753
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_dump.h
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * Copyright (C) 2020 MediaTek Inc. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __HSM_DUMP_H__
+#define __HSM_DUMP_H__
+
+extern int hsm_dump_init(void);
+extern int hsm_dump_log(void);
+
+#endif //__HSM_DUMP_H__
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_if_impl.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_if_impl.c
new file mode 100644
index 0000000..365b9e0
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_if_impl.c
@@ -0,0 +1,773 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#include <kernel/misc.h>
+#include <io.h>
+#include <stdio.h>
+#include <string.h>
+#include <tee/cache.h>
+#include <kernel/delay.h>
+#include "system_event.h"
+#include "mbox_serv.h"
+#include "km_ipc.h"
+#include "address.h"
+#include "sync_obj.h"
+#include "buddy.h"
+#include "hsm_job.h"
+#include "mtk_crypto.h"
+#include "share_memmap.h"
+#include "hsm_pta_debug.h"
+
+#define HSM_IN_BUF_OFFSET (0)
+#define HSM_IN_BUF_LEN (0x2000) // IN BUF 1 --> 8KB
+
+#define HSM_IN_BUF2_OFFSET (HSM_IN_BUF_LEN)
+#define HSM_IN_BUF2_LEN (0x400) // IN BUF 2 --> 1KB
+
+#define HSM_IN_BUF3_OFFSET (HSM_IN_BUF2_OFFSET + HSM_IN_BUF2_LEN)
+#define HSM_IN_BUF3_LEN (0x400) // IN BUF 3 --> 1KB
+
+#define HSM_OUT_BUF_OFFSET (HSM_IN_BUF3_OFFSET + HSM_IN_BUF3_LEN)
+#define HSM_OUT_BUF_LEN (0x2000) // OUT BUF 1 --> 8KB
+
+#define HSM_OUT_BUF2_OFFSET (HSM_OUT_BUF_OFFSET + HSM_OUT_BUF_LEN)
+#define HSM_OUT_BUF2_LEN (0x400) // OUT BUF 2 --> 1KB
+
+#define HSM_OUT_JOB_OFFSET (HSM_OUT_BUF2_OFFSET + HSM_OUT_BUF2_LEN)
+#define HSM_OUT_JOB_LEN (0x80) // JOB BUF --> 128B
+
+#define HSM_OUT_RET_OFFSET (HSM_OUT_JOB_OFFSET + HSM_OUT_JOB_LEN)
+#define HSM_OUT_RET_LEN (0x10) // RET BUF --> 16B
+
+vaddr_t mbox_io_buf_base;
+
+static uint32_t algo_2_eventid(uint32_t algo_type)
+{
+ uint32_t event_id = 0xffffffff;
+
+ switch (algo_type)
+ {
+ case CRYPTO_ALGOFAM_SHA1:
+ case CRYPTO_ALGOFAM_SHA2_224:
+ case CRYPTO_ALGOFAM_SHA2_256:
+ case CRYPTO_ALGOFAM_SHA2_384:
+ case CRYPTO_ALGOFAM_SHA2_512:
+ case CRYPTO_ALGOFAM_AES:
+ event_id = SYS_EVENT_CRY_AES_SHA;
+ break;
+ case CRYPTO_ALGOFAM_ECCNIST:
+ event_id = SYS_EVENT_CRY_ECC;
+ break;
+ case CRYPTO_ALGOFAM_RNG:
+ case CRYPTO_ALGOFAM_SECURECOUNTER:
+ event_id = SYS_EVENT_CRY_TRNG;
+ break;
+ case CRYPTO_ALGOFAM_NOT_SET:
+ default:
+ break;
+ }
+
+ return event_id;
+}
+
+static inline void _set_mbox_tx_header(struct sys_event *tx, int cpu_serial, int event_id)
+{
+ if (tx == NULL) {
+ HSM_PTA_ERROR("[%s][%d] invalid input ptr\n", __FUNCTION__, __LINE__);
+ return;
+ }
+ memset(tx, 0, sizeof(struct sys_event));
+ tx->cpu_serial = CPU_SERIAL_HSM;
+ tx->event_id = SYS_EVENT_KEY_MANAGEMENT;
+}
+
+
+int hsm_export_key(uint8_t *pblob, uint32_t blobsize, uint8_t *ppubkey, uint32_t *ppubkeylength) {
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ sync_handle sync = {0};
+ addr_t in_share_buffer = {0};
+ addr_t out_share_buffer = {0};
+ addr_t keylength = {0};
+ int hsm_ret = -1;
+
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(blobsize, &in_share_buffer) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(*ppubkeylength, &out_share_buffer) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(sizeof(uint32_t), &keylength) != 0 ) {
+ goto fail;
+ }
+ memput_and_cclean(&in_share_buffer, pblob, blobsize);
+ memput_and_cclean(&keylength, ppubkeylength, sizeof(uint32_t));
+
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_EXPORT_KEY;
+ tx.data.data[1] = get_hsm_address(&in_share_buffer);
+ tx.data.data[2] = blobsize;
+ tx.data.data[3] = get_hsm_address(&out_share_buffer);
+ tx.data.data[4] = get_hsm_address(&keylength);
+ tx.data.data[14] = get_hsm_address(&sync);
+
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+ release_sync_handle(&sync);
+
+ cclean_and_memcopy(ppubkeylength, &keylength, sizeof(int));
+ cclean_and_memcopy(ppubkey, &out_share_buffer, *ppubkeylength);
+
+ physical_free(&in_share_buffer);
+ physical_free(&out_share_buffer);
+ physical_free(&keylength);
+
+ return hsm_ret;
+fail:
+ release_sync_handle(&sync);
+ physical_free(&in_share_buffer);
+ physical_free(&out_share_buffer);
+ physical_free(&keylength);
+
+ return hsm_ret;
+
+}
+
+int hsm_import_key(uint8_t *keybuffer, int size, int *pkey_id, int algo_id) {
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ sync_handle sync = {0};
+ addr_t keyid = {0};
+ addr_t share_buffer = {0};
+ int hsm_ret = -1;
+
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(sizeof(int), &keyid) != 0) {
+ goto fail;
+ }
+ if (physical_malloc(size, &share_buffer) != 0 ) {
+ goto fail;
+ }
+ memput_and_cclean(&share_buffer, keybuffer, size);
+
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_IMPORT_KEY;
+ tx.data.data[1] = get_hsm_address(&share_buffer);
+ tx.data.data[2] = size;
+ tx.data.data[3] = get_hsm_address(&keyid);
+ tx.data.data[4] = algo_id;
+ tx.data.data[14] = get_hsm_address(&sync);
+
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+ release_sync_handle(&sync);
+
+ cclean_and_memcopy(pkey_id, &keyid, sizeof(int));
+
+ physical_free(&keyid);
+ physical_free(&share_buffer);
+
+ return hsm_ret;
+fail:
+ release_sync_handle(&sync);
+ physical_free(&keyid);
+ physical_free(&share_buffer);
+
+ return hsm_ret;
+}
+
+int hsm_delete_key(int key_id) {
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ sync_handle sync = {0};
+ int hsm_ret = -1;
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_DELETE_KEY;
+ tx.data.data[1] = key_id;
+ tx.data.data[14] = get_hsm_address(&sync);
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+
+ release_sync_handle(&sync);
+ return hsm_ret;
+fail:
+ release_sync_handle(&sync);
+ return hsm_ret;
+}
+
+int hsm_gen_key_pair(int size, int uECC_curve_id, int *pkey_id) {
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ sync_handle sync = {0};
+ addr_t keyid = {0};
+ int hsm_ret = -1;
+
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(sizeof(int), &keyid) != 0) {
+ goto fail;
+ }
+
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_KEY_PAIR_GENERATION;
+ tx.data.data[1] = size;
+ tx.data.data[2] = uECC_curve_id;
+ tx.data.data[3] = get_hsm_address(&keyid);
+ tx.data.data[14] = get_hsm_address(&sync);
+
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+ release_sync_handle(&sync);
+
+ cclean_and_memcopy(pkey_id, &keyid, sizeof(int));
+
+ physical_free(&keyid);
+ return hsm_ret;
+fail:
+ release_sync_handle(&sync);
+ physical_free(&keyid);
+
+ return hsm_ret;
+}
+
+int hsm_gen_symm_key(int size, int *pkeyid) {
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ sync_handle sync = {0};
+ addr_t keyid = {0};
+ int hsm_ret = -1;
+
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(sizeof(int), &keyid) != 0) {
+ goto fail;
+ }
+
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_SYMM_KEY_GENERATION;
+ tx.data.data[1] = size;
+ tx.data.data[2] = get_hsm_address(&keyid);
+ tx.data.data[14] = get_hsm_address(&sync);
+
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+ release_sync_handle(&sync);
+
+ cclean_and_memcopy(pkeyid, &keyid, sizeof(int));
+
+ physical_free(&keyid);
+ return hsm_ret;
+fail:
+ HSM_PTA_ERROR("[%s][%d] mbox if fail ret : %d\n", __FUNCTION__, __LINE__, hsm_ret);
+ release_sync_handle(&sync);
+ physical_free(&keyid);
+
+ return hsm_ret;
+}
+
+
+int hsm_get_key_blob(uint8_t *dst, int size, int key_id, int algo_id, int *pblobsize) {
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ sync_handle sync = {0};
+ addr_t buffer = {0};
+ addr_t blob_size = {0};
+ int bsize = 0;
+ int hsm_ret = -1;
+
+ if (dst == NULL || pblobsize == NULL) {
+ goto fail;
+ }
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(size, &buffer) != 0) {
+ goto fail;
+ }
+ if (physical_malloc(sizeof(int), &blob_size) != 0) {
+ goto fail;
+ }
+
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_GET_KEY_BLOB;
+ tx.data.data[1] = get_hsm_address(&buffer);
+ tx.data.data[2] = size;
+ tx.data.data[3] = key_id;
+ tx.data.data[4] = algo_id;
+ tx.data.data[5] = get_hsm_address(&blob_size);
+ tx.data.data[14] = get_hsm_address(&sync);
+
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+ release_sync_handle(&sync);
+
+ cclean_and_memcopy(&bsize, &blob_size, sizeof(int));
+
+ if (size < bsize) {
+ goto fail;
+ }
+ *pblobsize = bsize;
+
+ cclean_and_memcopy(dst, &buffer, bsize);
+
+ physical_free(&buffer);
+ physical_free(&blob_size);
+
+ return hsm_ret;
+
+fail:
+ HSM_PTA_ERROR("[%s][%d] mbox if fail ret : %d\n", __FUNCTION__, __LINE__, hsm_ret);
+ release_sync_handle(&sync);
+ physical_free(&buffer);
+ physical_free(&blob_size);
+
+ return hsm_ret;
+
+}
+
+int hsm_get_key_table(uint8_t *dst, int size, int *ptablesize) {
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ int hsm_ret = -1;
+ sync_handle sync = {0};
+ addr_t buffer = {0};
+ addr_t table_size = {0};
+ int tblsize = 0;
+
+ if (dst == NULL || ptablesize == NULL) {
+ goto fail;
+ }
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(size, &buffer) != 0) {
+ goto fail;
+ }
+ if (physical_malloc(sizeof(int), &table_size) != 0) {
+ goto fail;
+ }
+
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_GET_KEY_TABLE;
+ tx.data.data[1] = get_hsm_address(&buffer);
+ tx.data.data[2] = size;
+ tx.data.data[3] = get_hsm_address(&table_size);
+ tx.data.data[14] = get_hsm_address(&sync);
+
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+ release_sync_handle(&sync);
+
+ cclean_and_memcopy(&tblsize, &table_size, sizeof(int));
+
+ if (size < tblsize) {
+ goto fail;
+ }
+ *ptablesize = tblsize;
+
+ cclean_and_memcopy(dst, &buffer, tblsize);
+
+ physical_free(&buffer);
+ physical_free(&table_size);
+
+ return hsm_ret;
+
+fail:
+ HSM_PTA_ERROR("[%s][%d] mbox if fail ret : %d\n", __FUNCTION__, __LINE__, hsm_ret);
+ release_sync_handle(&sync);
+ physical_free(&buffer);
+ physical_free(&table_size);
+
+ return hsm_ret;
+}
+
+int hsm_rebuild_key_table(uint8_t *buffer, int table_size) {
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ int hsm_ret = -1;
+ sync_handle sync = {0};
+ addr_t share_buffer = {0};
+ int tblsize = 0;
+
+ if (buffer == NULL) {
+ goto fail;
+ }
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(table_size, &share_buffer) != 0 ) {
+ goto fail;
+ }
+ memput_and_cclean(&share_buffer, buffer, table_size);
+
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_REBUILD_KEY_TABLE;
+ tx.data.data[1] = get_hsm_address(&share_buffer);
+ tx.data.data[2] = table_size;
+ tx.data.data[14] = get_hsm_address(&sync);
+
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+ release_sync_handle(&sync);
+ physical_free(&share_buffer);
+
+ return hsm_ret;
+
+fail:
+ HSM_PTA_ERROR("[%s][%d] mbox if fail ret : %d\n", __FUNCTION__, __LINE__, hsm_ret);
+ release_sync_handle(&sync);
+ physical_free(&share_buffer);
+
+ return hsm_ret;
+}
+
+int hsm_rebuild_key_blob(uint8_t *buffer, int blob_size, int key_id)
+{
+ struct sys_event tx;
+ uint8_t mbox_ret = -1;
+ int hsm_ret = -1;
+ sync_handle sync = {0};
+ addr_t share_buffer = {0};
+ int tblsize = 0;
+
+ if (buffer == NULL) {
+ goto fail;
+ }
+ if (allocate_sync_handle(&sync) != 0 ) {
+ goto fail;
+ }
+ if (physical_malloc(blob_size, &share_buffer) != 0 ) {
+ goto fail;
+ }
+ memput_and_cclean(&share_buffer, buffer, blob_size);
+
+ _set_mbox_tx_header(&tx, CPU_SERIAL_HSM, SYS_EVENT_KEY_MANAGEMENT);
+
+ tx.data.data[0] = KM_MBOX_CMD_REBUILD_KEY_BLOB;
+ tx.data.data[1] = get_hsm_address(&share_buffer);
+ tx.data.data[2] = blob_size;
+ tx.data.data[3] = key_id;
+ tx.data.data[14] = get_hsm_address(&sync);
+
+ mbox_ret = mbox_serv_tx(&tx);
+ if (mbox_ret != MBOX_SERV_OK) {
+ goto fail;
+ }
+ wait_remote_sync_done(&sync);
+ hsm_ret = get_hsm_return_value(&sync);
+ if (hsm_ret != 0) {
+ goto fail;
+ }
+ release_sync_handle(&sync);
+ physical_free(&share_buffer);
+
+ return hsm_ret;
+
+fail:
+ HSM_PTA_ERROR("[%s][%d] mbox if fail ret : %d\n", __FUNCTION__, __LINE__, hsm_ret);
+ release_sync_handle(&sync);
+ physical_free(&share_buffer);
+
+ return hsm_ret;
+}
+
+int hsm_send_job(job_struct *pjob)
+{
+ uint32_t in_len, in_len2, in_len3;
+ uint8_t *in_buf = NULL;
+ uint8_t *in_buf3 = NULL;
+ uint32_t out_len = 0, out_len2 = 0;
+ uint8_t *out_buf = NULL;
+ uint8_t *out_buf2 = NULL;
+ uint8_t *IV = NULL;
+ job_struct job2hsm;
+ uint32_t hsmaddr_job = 0;
+ int ret = -1;
+ struct sys_event tx = {0};
+
+ HSM_PTA_DEBUG("[\x1b[31m%s\033[0m][%d]\n", __FUNCTION__, __LINE__);
+ memcpy(&job2hsm, pjob, sizeof(job_struct));
+
+ tx.event_id = algo_2_eventid(job2hsm.family);
+
+ // In buffer #1
+ HSM_PTA_DEBUG("\x1b[1;32m inputLength: %d \033[0m \n", job2hsm.inputLength);
+ in_len = job2hsm.inputLength;
+ if (in_len != 0)
+ {
+ in_buf = (uint8_t *)job2hsm.inputPtr;
+ memcpy(mbox_io_buf_base + HSM_IN_BUF_OFFSET, in_buf, in_len);
+ ret = hsm_addr_remap((uint32_t)HSM_ALL_IO_BUF_BASE + HSM_IN_BUF_OFFSET, &hsmaddr_job);
+ if (ret != 0)
+ {
+ HSM_PTA_ERROR("[\x1b[31m%s\033[0m] remap error : %d\n", __func__, ret);
+ return -1;
+ }
+ job2hsm.inputPtr = hsmaddr_job;
+ }
+
+ // In buffer #2
+ HSM_PTA_DEBUG("\x1b[1;32m secondaryInputLength: %d \033[0m \n", job2hsm.secondaryInputLength);
+ in_len2 = job2hsm.secondaryInputLength;
+ if (in_len2 != 0)
+ {
+ IV = (uint8_t *)job2hsm.secondaryInputPtr;
+ memcpy(mbox_io_buf_base + HSM_IN_BUF2_OFFSET, IV, in_len2);
+ ret = hsm_addr_remap((uint32_t)HSM_ALL_IO_BUF_BASE + HSM_IN_BUF2_OFFSET, &hsmaddr_job);
+ if (ret != 0)
+ {
+ HSM_PTA_ERROR("[\x1b[31m%s\033[0m] remap error : %d\n", __func__, ret);
+ return -1;
+ }
+ job2hsm.secondaryInputPtr = hsmaddr_job;
+ }
+
+ // In buffer #3
+ HSM_PTA_DEBUG("\x1b[1;32m tertiaryInputLength: %d \033[0m \n", job2hsm.tertiaryInputLength);
+ in_len3 = job2hsm.tertiaryInputLength;
+ if (in_len3 != 0)
+ {
+ in_buf3 = (uint8_t *)job2hsm.tertiaryInputPtr;
+ memcpy(mbox_io_buf_base + HSM_IN_BUF3_OFFSET, in_buf3, in_len2);
+ ret = hsm_addr_remap((uint32_t)HSM_ALL_IO_BUF_BASE + HSM_IN_BUF3_OFFSET, &hsmaddr_job);
+ if (ret != 0)
+ {
+ HSM_PTA_ERROR("[\x1b[31m%s\033[0m] remap error : %d\n", __func__, ret);
+ return -1;
+ }
+ job2hsm.tertiaryInputPtr = hsmaddr_job;
+ }
+
+ // Out buffer #1
+ HSM_PTA_DEBUG("\x1b[1;32m OutputLength: %d \033[0m \n", job2hsm.outputLength);
+ out_len = job2hsm.outputLength;
+ out_buf = (uint8_t *)job2hsm.outputPtr;
+ if (out_len != 0)
+ {
+ ret = hsm_addr_remap((uint32_t)HSM_ALL_IO_BUF_BASE + HSM_OUT_BUF_OFFSET, &hsmaddr_job);
+ if (ret != 0)
+ {
+ HSM_PTA_ERROR("[\x1b[31m%s\033[0m] remap error : %d\n", __func__, ret);
+ return -1;
+ }
+ job2hsm.outputPtr = hsmaddr_job;
+ }
+
+ // Out buffer #2
+ HSM_PTA_DEBUG("\x1b[1;32m secondaryOutputLength: %d \033[0m \n", job2hsm.secondaryOutputLength);
+ out_len2 = job2hsm.secondaryOutputLength;
+ out_buf2 = (uint8_t *)job2hsm.secondaryOutputPtr;
+ if (out_len2 != 0)
+ {
+ ret = hsm_addr_remap((uint32_t)HSM_ALL_IO_BUF_BASE + HSM_OUT_BUF2_OFFSET, &hsmaddr_job);
+ if (ret != 0)
+ {
+ HSM_PTA_ERROR("[\x1b[31m%s\033[0m] remap error : %d\n", __func__, ret);
+ return -1;
+ }
+ job2hsm.secondaryOutputPtr = hsmaddr_job;
+ }
+
+ // Return value pointer
+ ret = hsm_addr_remap((uint32_t)HSM_ALL_IO_BUF_BASE + HSM_OUT_RET_OFFSET, &hsmaddr_job);
+ if (ret != 0)
+ {
+ HSM_PTA_ERROR("[\x1b[31m%s\033[0m] remap error : %d\n", __func__, ret);
+ return -1;
+ }
+ job2hsm.retValPtr = hsmaddr_job;
+
+
+ HSM_PTA_DEBUG(" job2hsm.event_id : 0x%x\r\n", (uint32_t)job2hsm.event_id);
+ HSM_PTA_DEBUG(" job2hsm.priority : 0x%x\r\n", (uint32_t)job2hsm.priority);
+ HSM_PTA_DEBUG(" job2hsm.job_id : 0x%x\r\n", (uint32_t)job2hsm.job_id);
+ HSM_PTA_DEBUG(" job2hsm.service : 0x%x\r\n", (uint32_t)job2hsm.service);
+ HSM_PTA_DEBUG(" job2hsm.family : 0x%x\r\n", (uint32_t)job2hsm.family);
+ HSM_PTA_DEBUG(" job2hsm.operation_mode : 0x%x\r\n", (uint32_t)job2hsm.operation_mode);
+ HSM_PTA_DEBUG(" job2hsm.mode : 0x%x\r\n", (uint32_t)job2hsm.mode);
+ HSM_PTA_DEBUG(" job2hsm.cryptoKeyId : 0x%x\r\n", (uint32_t)job2hsm.cryptoKeyId);
+ HSM_PTA_DEBUG(" job2hsm.keyLength : 0x%x\r\n", (uint32_t)job2hsm.keyLength);
+
+ // Job buffer
+ memcpy(mbox_io_buf_base + HSM_OUT_JOB_OFFSET, &job2hsm, sizeof(job_struct));
+ if (cache_operation(TEE_CACHECLEAN, mbox_io_buf_base, HSM_OUT_RET_OFFSET) != TEE_SUCCESS)
+ {
+ HSM_PTA_ERROR("\x1b[31m == CACHE FAIL!! == \033[0m\n");
+ return -1;
+ }
+ if (cache_operation(TEE_CACHEINVALIDATE, mbox_io_buf_base, (HSM_OUT_RET_OFFSET + HSM_OUT_RET_LEN)) != TEE_SUCCESS)
+ {
+ HSM_PTA_ERROR("\x1b[31m == CACHE INVALIDATE FAIL!! == \033[0m\n");
+ return -1;
+ }
+
+
+ ret = hsm_addr_remap((uint32_t)HSM_ALL_IO_BUF_BASE + HSM_OUT_JOB_OFFSET, &hsmaddr_job);
+ if (ret != 0)
+ {
+ HSM_PTA_ERROR("[\x1b[31m%s\033[0m] remap error : %d\n", __func__, ret);
+ return -1;
+ }
+ tx.data.data[0] = hsmaddr_job;
+
+
+ // Give return value a initial value
+ write8(MBOX_SERV_FEEDBACK_INIT_VAL, mbox_io_buf_base + HSM_OUT_RET_OFFSET);
+
+ // Send job with physical address to HSM, and wait for job done.
+ ret = mbox_serv_tx(&tx);
+
+ // Waiting for HSM done the job
+ uint8_t hsm_feedback_result = MBOX_SERV_FEEDBACK_INIT_VAL;
+ while (1)
+ {
+ // Invalidating cache
+ if (cache_operation(TEE_CACHECLEAN, mbox_io_buf_base, (HSM_OUT_RET_OFFSET + HSM_OUT_RET_LEN)) != TEE_SUCCESS)
+ {
+ HSM_PTA_ERROR("\x1b[31m == CACHE CLEAN FAIL!! == \033[0m\n");
+ return -1;
+ }
+ if (cache_operation(TEE_CACHEINVALIDATE, mbox_io_buf_base, (HSM_OUT_RET_OFFSET + HSM_OUT_RET_LEN)) != TEE_SUCCESS)
+ {
+ HSM_PTA_ERROR("\x1b[31m == CACHE INVALIDATE FAIL!! == \033[0m\n");
+ return -1;
+ }
+
+ hsm_feedback_result = read8(mbox_io_buf_base + HSM_OUT_RET_OFFSET);
+ // HSM_PTA_ERROR("hsm_feedback_result %d \033[0m\n", hsm_feedback_result);
+ if (hsm_feedback_result != MBOX_SERV_FEEDBACK_INIT_VAL)
+ {
+ HSM_PTA_DEBUG("\x1b[33m Got HSM feedback: 0x%x \033[0m\n", hsm_feedback_result);
+ break;
+ }
+ mdelay(1);
+ }
+
+ if (hsm_feedback_result == MBOX_SERV_FEEDBACK_VERIFY_FAIL) {
+ HSM_PTA_ERROR("\x1b[31m == Verification FAIL!! == \033[0m\n");
+ return TEE_ERROR_SIGNATURE_INVALID;
+ }
+
+
+ if (out_len != 0) {
+ memcpy(out_buf, mbox_io_buf_base + HSM_OUT_BUF_OFFSET, out_len);
+ }
+
+ if (out_len2 != 0) {
+ memcpy(out_buf2, mbox_io_buf_base + HSM_OUT_BUF2_OFFSET, out_len2);
+ }
+
+ return 0;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_if_impl.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_if_impl.h
new file mode 100644
index 0000000..b85081a
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_if_impl.h
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef __HSM_IF_IMPL_H__
+#define __HSM_IF_IMPL_H__
+
+#include "hsm_job.h"
+
+extern int hsm_gen_key_pair(int size, int uECC_curve_id, int *pkey_id);
+extern int hsm_gen_symm_key(int size, int *pkeyid);
+extern int hsm_get_key_blob(uint8_t *dst, int size, int key_id, int algo_id, int *pblobsize);
+extern int hsm_get_key_table(uint8_t *dst, int size, int *ptablesize);
+extern int hsm_rebuild_key_table(uint8_t *buffer, int table_size);
+extern int hsm_rebuild_key_blob(uint8_t *buffer, int blob_size, int key_id);
+extern int hsm_import_key(uint8_t *keybuffer, int size, int *pkey_id, int algo_id);
+extern int hsm_export_key(uint8_t *pblob, uint32_t blobsize, uint8_t *ppubkey, uint32_t *ppubkeylength);
+extern int hsm_send_job(job_struct *pjob);
+extern int hsm_delete_key(int key_id);
+
+#endif /*__HSM_IF_IMPL_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_mbox_if.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_mbox_if.c
new file mode 100644
index 0000000..6ddaa77
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_mbox_if.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <io.h>
+#include <kernel/pseudo_ta.h>
+#include <tee_api_defines.h>
+#include <kernel/thread.h>
+#include <kernel/interrupt.h>
+#include <kernel/misc.h>
+#include <mm/core_memprot.h>
+#include <kernel/tee_time.h>
+
+// For memcpy
+#include <string.h>
+
+// For cache clean and invalidate
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+#include <tee/cache.h>
+
+#include "hsm_mbox_if.h"
+#include "hsm_if_impl.h"
+#include "hsm_pta_debug.h"
+#include "system_event.h"
+#include "mbox_serv.h"
+#include "mtk_crypto.h"
+
+#include "buddy.h"
+#include "share_memmap.h"
+#include "sync_obj.h"
+#include "hsm_dump.h"
+
+extern vaddr_t mbox_io_buf_base;
+
+static void _pta_hsm_gen_key_pair_handler(TEE_Param *pParams)
+{
+ int *phsmret, *pkeyid;
+ int size;
+ int uECC_curve_id;
+
+ phsmret = (int*)pParams[0].value.a;
+ size = (int)pParams[0].value.b;
+ uECC_curve_id = (int)pParams[1].value.a;
+ pkeyid = (int*)pParams[1].value.b;
+
+ *phsmret = hsm_gen_key_pair(size, uECC_curve_id, pkeyid);
+
+ return;
+}
+
+static void _pta_hsm_gen_symm_key_handler(TEE_Param *pParams)
+{
+ int *phsmret, *pkeyid;
+ int key_size;
+
+ phsmret = (int*)pParams[0].value.a;
+ pkeyid = (int*)pParams[0].value.b;
+ key_size = (int)pParams[1].value.a;
+
+ *phsmret = hsm_gen_symm_key(key_size, pkeyid);
+
+ return;
+}
+
+static void _pta_hsm_get_key_blob_handler(TEE_Param *pParams)
+{
+ int *phsmret, *pblobsize;
+ int buf_size, key_id, algo_id;
+ uint8_t *buffer;
+
+ phsmret = (int*) pParams[0].value.a;
+ key_id = (int) pParams[0].value.b;
+ buffer = (uint8_t *) pParams[1].value.a;
+ buf_size = (int) pParams[1].value.b;
+ algo_id = (int) pParams[2].value.a;
+ pblobsize = (int*) pParams[2].value.b;
+
+ *phsmret = hsm_get_key_blob(buffer, buf_size, key_id, algo_id, pblobsize);
+
+ return;
+}
+
+static void _pta_hsm_get_key_table_handler(TEE_Param *pParams)
+{
+ int *phsmret, *ptablesize;
+ int buf_size;
+ uint8_t *buffer;
+
+ phsmret = (int*)pParams[0].value.a;
+ buffer = (uint8_t *)pParams[0].value.b;
+ buf_size = (int)pParams[1].value.a;
+ ptablesize = (int*)pParams[1].value.b;
+
+ *phsmret = hsm_get_key_table(buffer, buf_size, ptablesize);
+
+ return;
+}
+
+static void _pta_hsm_rebuild_key_table_handler(TEE_Param *pParams)
+{
+ int *phsmret;
+ int table_size;
+ uint8_t *buffer;
+
+ phsmret = (int*)pParams[0].value.a;
+ buffer = (uint8_t *)pParams[0].value.b;
+ table_size = (int)pParams[1].value.a;
+
+ *phsmret = hsm_rebuild_key_table(buffer, table_size);
+
+ return;
+}
+
+static void _pta_hsm_rebuild_key_blob_handler(TEE_Param *pParams)
+{
+ int *phsmret;
+ int blob_size;
+ int key_id;
+ uint8_t *buffer;
+
+ phsmret = (int*)pParams[0].value.a;
+ buffer = (uint8_t *)pParams[0].value.b;
+ blob_size = (int)pParams[1].value.a;
+ key_id = (int)pParams[1].value.b;
+
+ *phsmret = hsm_rebuild_key_blob(buffer, blob_size, key_id);
+
+ return;
+}
+
+
+static void _pta_hsm_import_key(TEE_Param *pParams)
+{
+ int *phsmret;
+ uint8_t *keybuffer;
+ int size;
+ int *pkeyid;
+ int algo_id;
+
+ phsmret = (int*)pParams[0].value.a;
+ keybuffer = (uint8_t *)pParams[0].value.b;
+ size = (int)pParams[1].value.a;
+ pkeyid = (int*)pParams[1].value.b;
+ algo_id = (int*)pParams[2].value.a;
+
+ *phsmret = hsm_import_key(keybuffer, size, pkeyid, algo_id);
+
+ return;
+}
+
+static void _pta_hsm_export_key(TEE_Param *pParams)
+{
+ int *phsmret;
+ uint8_t *pblob;
+ uint32_t blobsize;
+ uint8_t *ppubkey;
+ uint32_t *ppubkeylength;
+
+ phsmret = (int*)pParams[0].value.a;
+ pblob = (uint8_t *)pParams[0].value.b;
+ blobsize = (int)pParams[1].value.a;
+ ppubkey = (uint8_t *)pParams[1].value.b;
+ ppubkeylength = (int*)pParams[2].value.a;
+
+ *phsmret = hsm_export_key(pblob, blobsize, ppubkey, ppubkeylength);
+
+ return;
+}
+
+static void _pta_hsm_send_job_handler(TEE_Param *pParams)
+{
+ int *phsmret;
+ job_struct *pjob;
+ uint32_t in_size;
+
+ pjob = (job_struct *)(pParams[0].value.a);
+ in_size = pParams[0].value.b;
+ phsmret = (int*)pParams[1].value.a;
+
+ *phsmret = hsm_send_job(pjob);
+}
+
+static void _pta_hsm_delete_key(TEE_Param *pParams)
+{
+ int *phsmret;
+ uint32_t keyid;
+
+ phsmret = (int*)pParams[0].value.a;
+ keyid = (uint32_t)pParams[0].value.b;
+
+ *phsmret = hsm_delete_key(keyid);
+
+ return;
+}
+
+TEE_Result TA_CreateEntryPoint(void)
+{
+ static int inited = 0;
+
+ if (inited)
+ return TEE_SUCCESS;
+
+ /* Allocate some resources, init something, ... */
+ mbox_serv_init();
+ hsm_dump_init();
+ buddy_init();
+
+ core_mmu_add_mapping(MEM_AREA_RAM_SEC, HSM_ALL_IO_BUF_BASE, HSM_ALL_IO_BUF_LEN);
+ mbox_io_buf_base = (vaddr_t)phys_to_virt(HSM_ALL_IO_BUF_BASE, MEM_AREA_RAM_SEC);
+
+ inited = 1;
+
+ /* Return with a status */
+ return TEE_SUCCESS;
+}
+
+void TA_DestroyEntryPoint(void)
+{
+ /* Release resources if required before TA destruction */
+}
+
+/* Static Function */
+static TEE_Result invoke_command(void *pSessionContext __unused,
+ uint32_t nCommandID, uint32_t nParamTypes,
+ TEE_Param pParams[TEE_NUM_PARAMS])
+{
+ if(pParams == NULL){
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ HSM_PTA_DEBUG("\x1b[1;31m MBOX receives nCommandID(%x) \033[0m\n", nCommandID);
+
+ switch (nCommandID)
+ {
+ case PTA_CMD_HSM_SEND_JOB:
+ _pta_hsm_send_job_handler(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_GEN_KEY_PAIR:
+ _pta_hsm_gen_key_pair_handler(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_GEN_SYMM_KEY:
+ _pta_hsm_gen_symm_key_handler(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_GET_KEY_BLOB:
+ _pta_hsm_get_key_blob_handler(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_GET_KEY_TABLE:
+ _pta_hsm_get_key_table_handler(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_REBUILD_KEY_TABLE:
+ _pta_hsm_rebuild_key_table_handler(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_REBUILD_KEY_BLOB:
+ _pta_hsm_rebuild_key_blob_handler(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_IMPORT_KEY:
+ _pta_hsm_import_key(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_EXPORT_KEY:
+ _pta_hsm_export_key(pParams);
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_DUMP_LOG:
+ hsm_dump_log();
+ return TEE_SUCCESS;
+
+ case PTA_CMD_HSM_DELETE_KEY:
+ _pta_hsm_delete_key(pParams);
+ return TEE_SUCCESS;
+
+ default:
+ break;
+ }
+
+ return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+pseudo_ta_register(.uuid = PTA_MBOX_UUID, .name = "mbox",
+ .flags = PTA_DEFAULT_FLAGS,
+ .invoke_command_entry_point = invoke_command,
+ .create_entry_point = TA_CreateEntryPoint,
+ .destroy_entry_point = TA_DestroyEntryPoint);
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_pta_debug.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_pta_debug.h
new file mode 100644
index 0000000..596f453
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/hsm_pta_debug.h
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef __HSM_PTA_DEBUG_H__
+#define __HSM_PTA_DEBUG_H__
+
+/****************************************
+ * # 0: none
+ * # 1: error
+ * # 2: error + warning
+ * # 3: error + warning + debug
+ * # 4: error + warning + debug + flow
+ ****************************************/
+#define HSM_PTA_LOG_LEVEL 3
+
+#define HSM_PTA_ERROR_LOG_LEVEL 1
+#define HSM_PTA_INFO_LOG_LEVEL 2
+#define HSM_PTA_DEBUG_LOG_LEVEL 3
+#define HSM_PTA_FLOW_LOG_LEVEL 4
+
+#if (HSM_PTA_FLOW_LOG_LEVEL <= HSM_PTA_LOG_LEVEL)
+#define HSM_PTA_FLOW(x...) FMSG(x)
+#else
+#define HSM_PTA_FLOW(x...)
+#endif
+
+#if (HSM_PTA_DEBUG_LOG_LEVEL <= HSM_PTA_LOG_LEVEL)
+#define HSM_PTA_DEBUG(x...) DMSG(x)
+#else
+#define HSM_PTA_DEBUG(x...)
+#endif
+
+#if (HSM_PTA_INFO_LOG_LEVEL <= HSM_PTA_LOG_LEVEL)
+#define HSM_PTA_INFO(x...) IMSG(x)
+#else
+#define HSM_PTA_INFO(x...)
+#endif
+
+#if (HSM_PTA_ERROR_LOG_LEVEL <= HSM_PTA_LOG_LEVEL)
+#define HSM_PTA_ERROR(x...) EMSG(x)
+#else
+#define HSM_PTA_ERROR(x...)
+#endif
+
+
+#endif /*__HSM_PTA_DEBUG_H__*/
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/km_ipc.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/km_ipc.h
new file mode 100644
index 0000000..864597b
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/km_ipc.h
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef __KEY_IPC_H__
+#define __KEY_IPC_H__
+
+typedef enum KM_MBOX_CMD
+{
+ KM_MBOX_CMD_START = 0,
+ /* TEE <-> HSM*/
+ KM_MBOX_CMD_TRIGGER_REMOTE_TO_RECV,
+ KM_MBOX_CMD_TRIGGER_HSM_TO_READ_ELEMENT,
+ /* TEE <- HSM*/
+ KM_MBOX_CMD_STORE_KEY_ELEMET,
+ KM_MBOX_CMD_GET_ELEMET_CBK,
+ KM_MBOX_CMD_READ_KE_TABLE_ELEMENTS,
+ KM_MBOX_CMD_HSM_BUILDUP_TABLE_DONE,
+ /* TEE -> HSM*/
+ KM_MBOX_CMD_SET_ELEMENT,
+ KM_MBOX_CMD_GET_ELEMENT,
+ KM_MBOX_CMD_STORE_KEY_ELEMET_DONE,
+ KM_MBOX_CMD_TRIGGER_REBUILD_KE_TABLE,
+ KM_MBOX_CMD_READ_KE_TABLE_ELEMENTS_DONE,
+ /* OPTEE USED */
+ KM_MBOX_CMD_KEY_PAIR_GENERATION,
+ KM_MBOX_CMD_SYMM_KEY_GENERATION,
+ KM_MBOX_CMD_GET_KEY_BLOB,
+ KM_MBOX_CMD_GET_KEY_TABLE,
+ KM_MBOX_CMD_REBUILD_KEY_TABLE,
+ KM_MBOX_CMD_REBUILD_KEY_BLOB,
+ KM_MBOX_CMD_IMPORT_KEY,
+ KM_MBOX_CMD_EXPORT_KEY,
+ KM_MBOX_CMD_DELETE_KEY,
+ KM_MBOX_CMD_END,
+} km_mbox_cmd;
+
+#endif //__KEY_IPC_H__
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_common.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_common.h
new file mode 100644
index 0000000..9770d89
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_common.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __MBOX_COMMON_H__
+#define __MBOX_COMMON_H__
+
+#include <stdint.h>
+// #include <drStd.h>
+// #include <DrApi/DrApi.h>
+// #include <DrApi/DrApiLogging.h>
+// #include <DrApi/DrApiThread.h>
+#include "drCommon.h"
+
+#include "tee_common.h"
+#include "mbox_hw.h"
+#include "mbox_sw.h"
+#include "reg_op.h"
+#include "processor.h"
+#include "system_event.h"
+
+#define MBOX_DEBUG 0
+
+#if MBOX_DEBUG
+#define TEE_MBOX_DEBUG(string, args...) \
+ if(1) { \
+ drDbgPrintf("[MBOX]"string, ##args); \
+ }
+#else
+#define TEE_MBOX_DEBUG(string, args...)
+#endif
+
+#define TEE_MBOX_ERR(string, args...) \
+ if(1) { \
+ drDbgPrintf("[MBOX]"string, ##args); \
+ }
+
+#endif // __MBOX_COMMON_H__
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_drv.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_drv.c
new file mode 100644
index 0000000..c62756b
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_drv.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <kernel/interrupt.h>
+#include <mm/core_memprot.h>
+
+#include "reg_op.h"
+#include "mbox_hw.h"
+#include "mbox_sw.h"
+#include "mbox_drv.h"
+
+// extern void mtk_mbox_irq_start_thread(int irq);
+// extern void mtk_mbox_irq_stop_thread(int irq);
+
+
+struct mbox_info {
+ const uint32_t base;
+ struct mbox_reg *vbase;
+ uint32_t irq;
+ uint32_t err_irq_num;
+};
+
+struct erm_info {
+ const uint32_t base;
+ struct erm_reg *vbase;
+ uint32_t irq;
+};
+
+
+register_phys_mem(MEM_AREA_IO_SEC, HSM_MBOX_BASE, MBOX_REGISTER_RANGE);
+register_phys_mem(MEM_AREA_IO_SEC, HSM_ERMST_BASE, ERMST_REGISTER_RANGE);
+
+/* MBOX base mapping */
+static struct mbox_info mbox[CPU_SERIAL_CNT] = {
+ {(const uint32_t)HSM_MBOX_BASE, (struct mbox_reg*)NULL, IVALID_IRQ_ID, INVALID_MBOX_E_IRQ},
+ {(const uint32_t)HSM_MBOX_BASE, (struct mbox_reg*)NULL, IVALID_IRQ_ID, INVALID_MBOX_E_IRQ},
+};
+
+static struct erm_info erm = {
+ .base = HSM_ERMST_BASE,
+ .vbase = NULL,
+ .irq = ERM_IRQ_ID,
+};
+
+/* pointer to self */
+static const struct mbox_info *p_mbox;
+
+/* callback function */
+static void (*mbox_user_isr)(uint8_t msg_id);
+
+static uint8_t ca53_itr_msg_id = -1;
+
+
+void mbox_reset(void)
+{
+ uint8_t i = 0;
+ write32(&p_mbox->vbase->msg_irq_en, 0UL);
+ write32(&p_mbox->vbase->region_irq_en, 0UL);
+
+ for (i = MBOX_MSG_ID_MIN; i <= MBOX_MSG_ID_MAX; i++) {
+ write32(&p_mbox->vbase->msg[i], 0UL);
+ }
+
+ write32(&p_mbox->vbase->msg_pending, 0xFFFFFFFFUL);
+}
+
+/* MBOX_REQ_MSG_PENDING */
+static inline uint32_t mbox_get_msg_bit_offset(uint8_t msg_id)
+{
+ return BIT(31UL - (uint32_t)(msg_id));
+}
+
+/* MBOX_NS_DOMAIN_CFG */
+static inline uint32_t mbox_get_domain_offset(enum mbox_regions region)
+{
+ return (28UL - ((uint32_t)(region) * 4UL));
+}
+
+static inline uint32_t mbox_get_sec_offset(enum mbox_regions region)
+{
+ return (31UL - ((uint32_t)(region) * 4UL));
+}
+
+static inline uint32_t mbox_get_boundary_offset(uint8_t boundary)
+{
+ return (24UL - ((uint32_t)(boundary) * 8UL));
+}
+
+static inline int8_t mbox_is_pending(uint8_t msg_id, uint32_t pending)
+{
+ int8_t result = MBOX_FAIL;
+
+ if ((pending & mbox_get_msg_bit_offset(msg_id)) > 0UL) {
+ result = MBOX_SUCC;
+ }
+
+ return result;
+}
+
+static void __mbox_register_interrupt(void)
+{
+ uint32_t irq = erm.irq;
+
+ // mtk_mbox_irq_start_thread(irq);
+}
+
+static void __mbox_unregister_interrupt(void)
+{
+ uint32_t irq = erm.irq;
+
+ // mtk_mbox_irq_stop_thread(irq);
+}
+
+static enum itr_return mbox_isr(struct itr_handler *h)
+{
+ EMSG("[%s: %d]\n", __func__, __LINE__);
+ uint32_t pending = read32(&erm.vbase->pending);
+
+ /*
+ * clear pending.
+ * Please clear it before callback to avoid racing condition in the
+ * MBOX service.
+ */
+ write32(&erm.vbase->pending, pending);
+
+ if ((mbox_user_isr != NULL) && ((pending & BIT(ERM_LBIST_BIT) ) != 0UL)) {
+ mbox_user_isr(ca53_itr_msg_id);
+ mbox_irq_done();
+ }
+ return ITRR_HANDLED;
+}
+KEEP_PAGER(mbox_isr);
+
+uint8_t mbox_itr_data = 0;
+static struct itr_handler mbox_itr = {
+ .it = ERM_IRQ_ID,
+ .flags = ITRF_TRIGGER_LEVEL,
+ .handler = mbox_isr,
+ .data = &mbox_itr_data,
+};
+KEEP_PAGER(mbox_itr);
+
+extern bool itr_set_polarity(unsigned int irq, unsigned int polarity);
+static int init_mbox_itr(void)
+{
+ *((uint8_t*)(mbox_itr.data)) = 321;
+ itr_add(&mbox_itr);
+ itr_enable(ERM_IRQ_ID);
+ return 0;
+}
+
+void mbox_init(enum CPU_SERIAL cpu_serial,
+ void (*p_mbox_msg_isr)(uint8_t msg_id))
+{
+ // uint8_t *RegBase_virtual;
+
+ /* point to self */
+ p_mbox = &mbox[cpu_serial];
+
+ for (int i = 0; i < CPU_SERIAL_CNT; ++i)
+ {
+ if (mbox[i].base != (const uint32_t)NULL)
+ {
+ mbox[i].vbase = (vaddr_t)phys_to_virt_io(mbox[i].base);
+ IMSG("[%s] mbox[i].vbase : 0x%x\n", __FUNCTION__, mbox[i].vbase);
+ }
+ }
+ erm.vbase = (vaddr_t)phys_to_virt_io(erm.base);
+ IMSG("[%s] erm.vbase : 0x%x\n", __FUNCTION__, erm.vbase);
+ // mbox_reset();
+
+ /* store callback */
+ mbox_user_isr = p_mbox_msg_isr;
+
+ // init_mbox_itr();
+
+}
+
+void mbox_deinit(void)
+{
+
+}
+
+void mbox_irq_done(void)
+{
+ uint32_t pending = read32(&erm.vbase->pending);
+ write32(&erm.vbase->pending, pending);
+
+ clrbits_le32(&erm.vbase->irq_set, BIT(ERM_LBIST_BIT));
+}
+
+void mbox_msg_tx(enum CPU_SERIAL send_to, uint8_t msg_id, uint32_t msg)
+{
+ if (msg_id <= MBOX_MSG_ID_MAX) {
+ write32(&mbox[send_to].vbase->msg[msg_id], msg);
+ }
+}
+
+void mbox_msg_rx(enum CPU_SERIAL send_to, uint8_t msg_id, uint32_t *pmsg)
+{
+ if ((msg_id <= MBOX_MSG_ID_MAX) && (pmsg != NULL)) {
+ *pmsg = read32(&mbox[send_to].vbase->msg[msg_id]);
+ }
+}
+
+void mbox_set_ca53_intr_msg_id(uint8_t msg_id)
+{
+ ca53_itr_msg_id = msg_id;
+}
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_drv.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_drv.h
new file mode 100644
index 0000000..4f516e7
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_drv.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __MBOX_DRV_H__
+#define __MBOX_DRV_H__
+
+#include <stdint.h>
+#include "processor.h"
+
+#define MBOX_SUCC 0
+#define MBOX_FAIL -1
+
+#define MBOX_MSG_ID_MIN 0U
+#define MBOX_MSG_ID_MAX 31U
+#define MBOX_INVALID 0xFFU
+
+#define MBOX_REGION_SIZE_MIN 0U
+#define MBOX_REGION_SIZE_MAX 32U
+
+enum mbox_regions {
+ MBOX_REGION_0,
+ MBOX_REGION_1,
+ MBOX_REGION_2,
+ MBOX_REGION_3,
+ MBOX_REGION_RX,
+ MBOX_DOMAIN_CNT,
+ MBOX_REGION_INVALID = -1,
+};
+
+/* Give boundary of r0,r1,r2, then the rest space is for r3 */
+#define MBOX_BOUNDARY_01 0U
+#define MBOX_BOUNDARY_12 1U
+#define MBOX_BOUNDARY_CNT 2U
+
+#define ISR(x) void x(void)
+
+// extern void mbox_init(void);
+extern void mbox_deinit(void);
+// extern void mbox_write(int idx, int val);
+// extern void mbox_read(int idx, uint32_t *pmsg);
+extern void mbox_irq_done(void);
+
+extern void mbox_init(enum CPU_SERIAL cpu_serial, void (*p_mbox_msg_isr)(uint8_t msg_id));
+
+extern void mbox_msg_tx(enum CPU_SERIAL send_to, uint8_t msg_id, uint32_t msg);
+extern void mbox_msg_rx(enum CPU_SERIAL send_to, uint8_t msg_id, uint32_t *pmsg);
+
+extern void mbox_set_ca53_intr_msg_id(uint8_t msg_id);
+
+#endif //__MBOX_DRV_H__
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_hw.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_hw.h
new file mode 100644
index 0000000..073b6ba
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_hw.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __MBOX_HW_H__
+#define __MBOX_HW_H__
+
+// #include "reg_base.h"
+
+#define IO_PHYS 0x10000000
+
+#define HSM_MBOX_BASE (IO_PHYS + 0x00651000)
+#define HSM_ERMST_BASE (IO_PHYS + 0x00650000)
+
+#define MBOX_REGISTER_RANGE 0x180
+#define ERMST_REGISTER_RANGE 0x28
+
+#define IVALID_IRQ_ID 0
+#define ERM_IRQ_ID 196//91
+
+#define ERM_LBIST_BIT 2
+
+#define CA53_INTR_MSG_ID 15
+
+#define INVALID_MBOX_E_IRQ (-1)
+
+#endif //__MBOX_HW_H__
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_serv.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_serv.c
new file mode 100644
index 0000000..cecac1d
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_serv.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <kernel/interrupt.h>
+#include <mm/core_memprot.h>
+
+#include "mbox_drv.h"
+#include "mbox_serv.h"
+#include "system_event.h"
+#include "processor.h"
+
+#define MBOX_SERV_MAGIC_NUM 0x5AA52731UL
+#define MBOX_SERV_MAGIC_ERROR 0xCCE2911BUL
+
+#define MBOX_SERV_TX_DELAY_MS 1UL
+#define MBOX_SERV_TX_DELAY_CNT 1UL
+#define MBOX_SERV_TX_DELAY (MBOX_SERV_TX_DELAY_MS / MBOX_SERV_TX_DELAY_CNT)
+
+struct mbox_domain {
+ uint8_t domain;
+ uint8_t security;
+};
+
+struct mbox_serv_table {
+ enum mbox_regions region;
+ enum CPU_SERIAL cpu_serial;
+};
+
+static const struct mbox_serv_table mbox_serv_tb[][MBOX_SERV_ENTRY_CNT] = {
+ /* CA53 */
+ {
+ {MBOX_REGION_0, CPU_SERIAL_HSM},
+ {MBOX_REGION_1, CPU_SERIAL_CA53},
+ },
+
+ /* HSM */
+ {
+ {MBOX_REGION_0, CPU_SERIAL_HSM},
+ {MBOX_REGION_1, CPU_SERIAL_CA53},
+ },
+};
+
+static enum CPU_SERIAL mbox_serv_serial;
+static const struct mbox_serv_table *p_mbox_serv;
+static struct mbox_serv_registry mbox_serv_registry_tb[SYS_EVENT_CNT];
+static int8_t mbox_serv_mutex[MBOX_DOMAIN_CNT];
+
+static inline void mbox_serv_ack(uint8_t msg_id)
+{
+ /* clear macgic number. Let sender knows that we received the msg */
+ mbox_msg_tx(mbox_serv_serial, msg_id, MBOX_SERV_MAGIC_NUM);
+}
+
+static inline void mbox_serv_ack_error(uint8_t msg_id)
+{
+ /* clear macgic number. Let sender knows that there is something wrong in isr */
+ mbox_msg_tx(mbox_serv_serial, msg_id, MBOX_SERV_MAGIC_ERROR);
+}
+
+static int8_t wait_remote_ack(enum CPU_SERIAL dest, uint8_t msg_id)
+{
+ uint32_t data = 0;
+ int8_t result = MBOX_SERV_ERR_FAIL;
+
+ /* wait remote set MBOX_SERV_MAGIC_NUM or MBOX_SERV_MAGIC_ERROR to mail box*/
+ while(1)
+ {
+ mbox_msg_rx(dest, msg_id, &data);
+ if (data == MBOX_SERV_MAGIC_NUM)
+ {
+ result = MBOX_SERV_OK;
+ break;
+ }
+ else if (data == MBOX_SERV_MAGIC_ERROR)
+ {
+ result = MBOX_SERV_ERR_REMOTE_FAIL;
+ // mbox_msg_rx(dest, msg_id + 1, &data);
+ mbox_msg_tx(dest, msg_id, MBOX_SERV_MAGIC_NUM);
+ mbox_msg_rx(dest, msg_id + 1, &data);
+ result = (int8_t)data;
+ break;
+ }
+ // drApiThreadSleep(1/*ms*/); //TODO
+ }
+
+ return result;
+}
+
+static int8_t mbox_serv_get_res(enum mbox_regions region)
+{
+ uint8_t i;
+ int8_t result = MBOX_SERV_ERR_BUSY;
+
+ for (i = 0; i < MBOX_SERV_TX_DELAY_CNT; i++) {
+ // SuspendAllInterrupts();
+ if (mbox_serv_mutex[(uint8_t)region] == false) {
+ mbox_serv_mutex[(uint8_t)region] = true;
+ // ResumeAllInterrupts();
+ result = 0;
+ break;
+ }
+ // ResumeAllInterrupts();
+
+ // drApiThreadSleep(MBOX_SERV_TX_DELAY); //TODO
+ }
+ return result;
+}
+
+static void mbox_serv_release_res(enum mbox_regions region)
+{
+ mbox_serv_mutex[(uint8_t)region] = false;
+}
+
+static int8_t mbox_serv_is_ack(enum CPU_SERIAL dest, uint8_t msg_id)
+{
+ int8_t result = false;
+ uint8_t i;
+ uint32_t data = 0;
+
+
+ for (i = 0; i < MBOX_SERV_TX_DELAY_CNT; i++) {
+ /* Get target header to check that it received the msg or not */
+ mbox_msg_rx(dest, msg_id, &data);
+
+ /* Data is cleared after msg is taken */
+ if (data == MBOX_SERV_MAGIC_NUM) {
+ result = true;
+ break;
+ }
+
+ // drApiThreadSleep(MBOX_SERV_TX_DELAY); //TODO
+ }
+
+ return result;
+}
+
+static inline uint8_t mbox_serv_convert_msg_id(uint8_t idx)
+{
+ return idx * MBOX_ENTRY_SIZE;
+}
+
+static int8_t mbox_serv_search_msg_id(enum CPU_SERIAL src,
+ enum CPU_SERIAL dest,
+ enum mbox_regions *region,
+ uint8_t *msg_id)
+{
+ uint8_t i;
+ int8_t result = MBOX_SERV_ERR_FAIL;
+
+ for (i = 0; i < MBOX_SERV_ENTRY_CNT; i++) {
+ if (mbox_serv_tb[dest][i].cpu_serial == src) {
+ *msg_id = mbox_serv_convert_msg_id(i);
+ *region = mbox_serv_tb[dest][i].region;
+ result = 0;
+ break;
+ }
+ }
+
+ return result;
+}
+
+static inline int8_t mbox_serv_q_is_empty(const struct mbox_serv_queue *q)
+{
+ int8_t result = false;
+
+ if (q->in_idx == q->out_idx) {
+ result = true;
+ }
+
+ return result;
+}
+
+static inline int8_t mbox_serv_q_is_full(const struct mbox_serv_queue *q)
+{
+ uint8_t idx;
+ int8_t result = false;
+
+ idx = (q->in_idx + 1U) % MBOX_SERV_QUEUE_SIZE;
+
+ if (idx == q->out_idx) {
+ result = true;
+ }
+
+ return result;
+}
+
+static inline void mbox_serv_enqueue(struct mbox_serv_queue *const q)
+{
+ if (q != NULL) {
+ q->in_idx = (q->in_idx + 1U) % MBOX_SERV_QUEUE_SIZE;
+ }
+}
+
+void mbox_serv_dequeue(struct mbox_serv_queue *const q)
+{
+ if (q != NULL) {
+ q->out_idx = (q->out_idx + 1U) % MBOX_SERV_QUEUE_SIZE;
+ }
+}
+
+void mbox_serv_isr(uint8_t msg_id)
+{
+ /* receive msg and put to rx queue */
+ uint8_t i;
+ uint8_t idx;
+ uint8_t event_id;
+ uint8_t offset;
+ uint32_t header;
+ const struct mbox_serv_registry *p_registry;
+ struct sys_event *p_event;
+ int8_t result = MBOX_SERV_OK;
+
+ /*
+ * Interrupt at lastest message queue.
+ * Get the first message queue on each entry
+ */
+ offset = msg_id - MBOX_DATA_SIZE;
+
+ /* decode msg */
+ mbox_msg_rx(mbox_serv_serial, offset, &header);
+ event_id = (uint8_t)(header & MBOX_SERV_EVENT_ID_MASK);
+ idx = offset / MBOX_ENTRY_SIZE;
+
+ /* if event id is not in the range or can't find callback, ignore it */
+ if ((event_id < (uint8_t)SYS_EVENT_CNT) &&
+ (idx < MBOX_SERV_ENTRY_CNT)) {
+ p_registry = &mbox_serv_registry_tb[event_id];
+
+ if (p_registry->q != NULL) {
+ /* if qeueu full, ignore the msg */
+ if (mbox_serv_q_is_full(p_registry->q) == false) {
+ p_event = &p_registry->q->event[p_registry->q->in_idx];
+
+ /* put to user event */
+ p_event->event_id = event_id;
+ p_event->cpu_serial = p_mbox_serv[idx].cpu_serial;
+
+ for (i = 0; i < MBOX_DATA_SIZE; i++) {
+ mbox_msg_rx(mbox_serv_serial,
+ offset + 1U + i,
+ &p_event->data.data[i]);
+ }
+
+ /* update queue status */
+ mbox_serv_enqueue(p_registry->q);
+
+ if (p_registry->cbk.status == MBOX_SERV_CBK_STATUS_ENABLE)
+ p_registry->cbk.fpCallback();
+
+ } else {
+ // TEE_MBOX_ERR("[\x1b[31m%s, %d\033[0m] MBOX_SERV_ERR_Q_FULL\n", __func__, __LINE__); //TODO
+ result = MBOX_SERV_ERR_Q_FULL;
+ }
+ } else {
+ // TEE_MBOX_ERR("[\x1b[31m%s, %d\033[0m] MBOX_SERV_ERR_NO_REGISTRY\n", __func__, __LINE__); //TODO
+ result = MBOX_SERV_ERR_NO_REGISTRY;
+ }
+ } else {
+ // TEE_MBOX_ERR("[\x1b[31m%s, %d\033[0m] MBOX_SERV_ERR_INVALID_ID\n", __func__, __LINE__); //TODO
+ result = MBOX_SERV_ERR_INVALID_ID;
+ }
+ /* clear header as ACK. Let this region free */
+ mbox_serv_ack(offset);
+
+ // workaround, TEMP USED
+ // if ((result == MBOX_SERV_OK) && (p_registry->cbk.status == MBOX_SERV_CBK_STATUS_ENABLE))
+ // {
+ // p_registry->cbk.fpCallback();
+ // }
+
+ (void)result;
+}
+void mbox_serv_init(void)
+{
+ uint8_t msg_id = -1;
+ int i;
+ enum mbox_regions region = MBOX_REGION_INVALID;
+
+ /* init table pointer */
+ mbox_serv_serial = CPU_SERIAL_CA53;
+ p_mbox_serv = mbox_serv_tb[mbox_serv_serial];
+
+ /* init event */
+ (void)memset(&mbox_serv_registry_tb, 0, sizeof(mbox_serv_registry_tb));
+
+ /* init mutex*/
+ (void)memset(&mbox_serv_mutex, 0, sizeof(mbox_serv_mutex));
+
+ /* init mbox driver and set callback function */
+ mbox_init(mbox_serv_serial, mbox_serv_isr);
+
+ for (i = 0; i < MBOX_SERV_ENTRY_CNT; i++) {
+ /* enable latest message interrupt on each entry */
+ // mbox_irq_enable(mbox_serv_convert_msg_id(i) + MBOX_DATA_SIZE);
+
+ /* set Magic to show initial done */
+ mbox_msg_tx(mbox_serv_serial,
+ mbox_serv_convert_msg_id(i),
+ MBOX_SERV_MAGIC_NUM);
+ }
+
+
+ mbox_serv_search_msg_id(CPU_SERIAL_HSM, CPU_SERIAL_CA53, ®ion, &msg_id);
+
+ mbox_set_ca53_intr_msg_id(mbox_serv_convert_msg_id(region) + MBOX_DATA_SIZE);
+}
+
+int8_t mbox_serv_register_event(uint8_t event_id,
+ const struct mbox_serv_registry *registry)
+{
+ int8_t result = MBOX_SERV_ERR_FAIL;
+
+ if ((event_id < (uint8_t)SYS_EVENT_CNT) && (registry != NULL)) {
+ mbox_serv_registry_tb[event_id] = *registry;
+ result = 0;
+ }
+
+ return result;
+}
+
+int8_t mbox_serv_tx(const struct sys_event *event)
+{
+ int8_t result;
+ uint8_t msg_id = -1;
+ uint8_t i;
+ enum CPU_SERIAL dest;
+ enum CPU_SERIAL src;
+ enum mbox_regions region = MBOX_REGION_INVALID;
+ uint32_t header;
+
+ dest = event->cpu_serial;
+ src = mbox_serv_serial;
+ result = mbox_serv_search_msg_id(src, dest, ®ion, &msg_id);
+
+
+ if ((result == 0) && (event->event_id < (uint8_t)SYS_EVENT_CNT)) {
+ if (mbox_serv_get_res(region) == 0) {
+ if (mbox_serv_is_ack(dest, msg_id) == true) {
+
+ header = ((event->priority & 0xFFFF) << 16) | event->event_id;
+ /* Put header first */
+ mbox_msg_tx(dest,
+ msg_id,
+ header);
+ /*
+ * Finally write the data to the latest message
+ * queue. We use latest msg q to trigger target
+ * MCU interrupt.
+ */
+ for (i = 0; i < MBOX_DATA_SIZE; i++) {
+ mbox_msg_tx(dest,
+ msg_id + i + 1U,
+ event->data.data[i]);
+ }
+
+ result = wait_remote_ack(dest, msg_id);
+
+ } else {
+ result = MBOX_SERV_ERR_BUSY;
+ }
+
+ mbox_serv_release_res(region);
+ } else {
+ result = MBOX_SERV_ERR_NO_RES;
+ }
+ } else {
+ result = MBOX_SERV_ERR_INVALID_ID;
+ }
+
+ return result;
+}
+
+
+struct sys_event *mbox_serv_rx(struct mbox_serv_queue *const q)
+{
+ struct sys_event *event = NULL;
+
+ if (q != NULL) {
+ if (mbox_serv_q_is_empty(q) == false) {
+ event = &q->event[q->out_idx];
+ }
+ }
+
+ return event;
+}
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_serv.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_serv.h
new file mode 100644
index 0000000..cb81cf5
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_serv.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _MBOX_SERV_H_
+#define _MBOX_SERV_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "system_event.h"
+
+#define MBOX_SERV_EVENT_ID_MASK 0xffUL
+
+#define MBOX_SERV_ENTRY_CNT 2U
+#define MBOX_SERV_QUEUE_SIZE 8U
+
+#define MBOX_SERV_JOB_IN_ACTIVE (1)
+#define MBOX_SERV_OK (0)
+#define MBOX_SERV_ERR_FAIL (-1)
+#define MBOX_SERV_ERR_BUSY (-2)
+#define MBOX_SERV_ERR_Q_FULL (-3)
+#define MBOX_SERV_ERR_NO_REGISTRY (-4)
+#define MBOX_SERV_ERR_INVALID_ID (-5)
+#define MBOX_SERV_ERR_NO_RES (-6)
+#define MBOX_SERV_ERR_REMOTE_FAIL (-7)
+#define MBOX_SERV_ERR_NO_JOB_CANCELED (-8)
+
+#define MBOX_SERV_CBK_STATUS_IDLE (0)
+#define MBOX_SERV_CBK_STATUS_ENABLE (1)
+#define MBOX_SERV_CBK_STATUS_DISABLE (2)
+
+#define MBOX_SERV_FEEDBACK_INIT_VAL (0x33)
+#define MBOX_SERV_FEEDBACK_MAGIC_NUM (0xAD)
+#define MBOX_SERV_FEEDBACK_VERIFY_FAIL (0xDC)
+
+struct mbox_callback
+{
+ uint32_t status;
+ void (*fpCallback)(void);
+};
+
+struct mbox_serv_queue {
+ uint8_t in_idx;
+ uint8_t out_idx;
+ struct sys_event event[MBOX_SERV_QUEUE_SIZE];
+};
+
+struct mbox_serv_registry {
+ uint32_t task_id;
+ uint32_t rx_mask;
+ struct mbox_callback cbk;
+ struct mbox_serv_queue *q;
+};
+
+void mbox_serv_init(void);
+int8_t mbox_serv_register_event(uint8_t event_id,
+ const struct mbox_serv_registry *registry);
+int8_t mbox_serv_tx(const struct sys_event *event);
+struct sys_event* mbox_serv_rx(struct mbox_serv_queue * const q);
+// void mbox_serv_set_region(int8_t lock_enable);
+void mbox_serv_dequeue(struct mbox_serv_queue *const q);
+
+#endif //_MBOX_SERV_H_
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_sw.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_sw.h
new file mode 100644
index 0000000..8365e7e
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/mbox_sw.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __MBOX_SW_H__
+#define __MBOX_SW_H__
+
+struct mbox_reg {
+ uint32_t msg_pending; //0x00
+ uint32_t msg_irq_en; //0x04
+ uint32_t ns_domain_cfg; //0x08
+ uint32_t reserved0; //0x0c
+ uint32_t region_size; //0x10
+ uint32_t region_err; //0x14
+ uint32_t region_irq_en; //0x18
+ uint32_t reserved1[57]; //0x20
+ uint32_t msg[32]; //0x100~0x180
+};
+
+struct erm_reg {
+ uint32_t pending; //0x00
+ uint32_t irq_en; //0x04
+ uint32_t irq_set; //0x08
+ uint32_t reserved0; //0x0c
+ uint32_t gdma_sram_tsel; //0x10
+ uint32_t mcu_sram_tsel; //0x14
+ uint32_t mcu_dcls_mask_h; //0x18
+ uint32_t mcu_dcls_mask_l; //0x1c
+ uint32_t eco1; //0x20
+ uint32_t eco2; //0x24
+};
+
+#endif //__MBOX_SW_H__
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/pta.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/pta.mk
new file mode 100644
index 0000000..f7716f7
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/pta.mk
@@ -0,0 +1,5 @@
+libdir := $(call my-dir)
+libname := hsm_mbox_if
+
+include $(BUILD_OPTEE_OS_LIB)
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/reg_op.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/reg_op.h
new file mode 100644
index 0000000..f8f9953
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/reg_op.h
@@ -0,0 +1,96 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2018. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef _REG_OP_H_
+#define _REG_OP_H_
+
+#include <stdint.h>
+
+#define BIT(x) ((0x1ul) << ((uint32_t)(x)))
+
+#ifndef read8
+#define read8(addr) (*(volatile uint8_t*)(addr))
+#endif
+#ifndef write8
+#define write8(addr, val) ((*(volatile uint8_t*)(addr)) = (val))
+#endif
+
+#ifndef read16
+#define read16(addr) (*(volatile uint16_t*)(addr))
+#endif
+#ifndef write16
+#define write16(addr, val) ((*(volatile uint16_t*)(addr)) = (val))
+#endif
+
+#ifndef read32
+#define read32(addr) (*(volatile uint32_t*)(addr))
+#endif
+#ifndef write32
+#define write32(addr, val) ((*(volatile uint32_t*)(addr)) = (val))
+#endif
+
+
+
+
+#define setbits_le8(addr, set) \
+ write8((addr), (read8((addr)) | (uint8_t)(set)))
+
+#define clrbits_le8(addr, clear) \
+ write8((addr), (read8((addr)) & ~(uint8_t)(clear)))
+
+#define clrsetbits_le8(addr, clear, set) \
+ write8((addr), ((read8((addr)) & ~((uint8_t)(clear))) | (uint8_t)(set)))
+
+#define setbits_le16(addr, set) \
+ write16((addr), (read16((addr)) | (uint16_t)(set)))
+
+#define clrbits_le16(addr, clear) \
+ write16((addr), (read16((addr)) & ~(uint16_t)(clear)))
+
+#define clrsetbits_le16(addr, clear, set) \
+ write16((addr), ((read16((addr)) & ~((uint16_t)(clear))) | (uint16_t)(set)))
+
+#define setbits_le32(addr, set) \
+ write32((addr), (read32((addr)) | (uint32_t)(set)))
+
+#define clrbits_le32(addr, clear) \
+ write32((addr), (read32((addr)) & ~(uint32_t)(clear)))
+
+#define clrsetbits_le32(addr, clear, set) \
+ write32((addr), ((read32((addr)) & ~((uint32_t)(clear))) | (uint32_t)(set)))
+
+#endif /* _REG_OP_H */
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/share_memmap.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/share_memmap.h
new file mode 100644
index 0000000..4e94f39
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/share_memmap.h
@@ -0,0 +1,60 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef __SHARE_MEMMAP_H__
+#define __SHARE_MEMMAP_H__
+
+#define HSM_BUF_END (0x44270000)
+
+#define JOB_PHYSICAL_BUF_LEN 0x2800 /*10KB*/
+#define JOB_PHYSICAL_BUF_BASE (HSM_BUF_END - JOB_PHYSICAL_BUF_LEN)
+
+#define LOG_BUF_LEN 0x4000 /*16KB*/
+#define LOG_BUF_BASE (JOB_PHYSICAL_BUF_BASE - LOG_BUF_LEN)
+
+#define KEY_IPC_PHYSICAL_BUF_LEN 0x2800 /*10KB*/
+#define KEY_IPC_PHYSICAL_BUF_BASE (LOG_BUF_BASE - KEY_IPC_PHYSICAL_BUF_LEN)
+
+#define BUDDY_MEMPOOL_BUF_LEN 0x10000 /*64KB*/
+#define BUDDY_MEMPOOL_BUF_BASE (KEY_IPC_PHYSICAL_BUF_BASE - BUDDY_MEMPOOL_BUF_LEN)
+
+#define TEE_BUDDY_MEMPOOL_BUF_LEN 0x10000 /*64KB*/
+#define TEE_BUDDY_MEMPOOL_BUF_BASE (BUDDY_MEMPOOL_BUF_BASE - TEE_BUDDY_MEMPOOL_BUF_LEN)
+
+#define HSM_ALL_IO_BUF_LEN 0x4000 /*16KB*/
+#define HSM_ALL_IO_BUF_BASE (TEE_BUDDY_MEMPOOL_BUF_BASE - HSM_ALL_IO_BUF_LEN)
+
+#endif //__SHARE_MEMMAP_H__
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sub.mk
new file mode 100644
index 0000000..2197b24
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sub.mk
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: BSD-2-Clause
+srcs-y := \
+ hsm_mbox_if.c \
+ hsm_if_impl.c \
+ mbox_drv.c \
+ mbox_serv.c \
+ buddy.c \
+ sync_obj.c \
+ hsm_dump.c
+
+incdirs-lib-y = \
+ include/ \
+ ../../../../optee_services/secure_key_services/ta/include/
+
+$(call add-pta-src, hsm_mbox_if.c)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sync_obj.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sync_obj.c
new file mode 100644
index 0000000..5d73d1b
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sync_obj.c
@@ -0,0 +1,204 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <kernel/delay.h>
+#include <tee/cache.h>
+#include "buddy.h"
+#include "address.h"
+#include "sync_obj.h"
+
+/* map physical address from CA53 to HSM */
+int hsm_addr_remap(uint32_t phyaddr, uint32_t *p_remaped)
+{
+ uint32_t hbit = (phyaddr & 0xf0000000) >> 28;
+ int ret = 0;
+
+ switch (hbit)
+ {
+ case 0x0:
+ *p_remaped = phyaddr | 0x90000000;
+ break;
+ case 0x1:
+ *p_remaped = phyaddr | 0xf0000000;
+ break;
+ case 0x2:
+ case 0x3:
+ ret = -1;
+ break;
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ case 0xa:
+ case 0xb:
+ *p_remaped = phyaddr - 0x30000000;
+ break;
+ case 0xc:
+ case 0xd:
+ case 0xe:
+ case 0xf:
+ *p_remaped = phyaddr - 0x20000000;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+int allocate_sync_handle(sync_handle *handle)
+{
+ uint32_t *phsm;
+ addr_t *p = handle;
+ int ret = buddy_malloc(sizeof(sync_object), p);
+ if (ret != BUDDY_OK) {
+ EMSG("[\x1b[31m%s\033[0m][%d] buddy_malloc fail \n", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ memset(p->va, 0, sizeof(sync_object));
+ hsm_addr_remap(p->pa, &phsm);
+ p->ha = phsm;
+
+ // IMSG("[\x1b[31m%s\033[0m][%d] p->pa : 0x%x\n", __FUNCTION__, __LINE__, p->pa);
+ // IMSG("[\x1b[31m%s\033[0m][%d] p->va : 0x%x\n", __FUNCTION__, __LINE__, p->va);
+ // IMSG("[\x1b[31m%s\033[0m][%d] p->ha : 0x%x\n", __FUNCTION__, __LINE__, p->ha);
+
+ return 0;
+}
+
+int release_sync_handle(sync_handle *handle)
+{
+ buddy_free(handle);
+}
+
+void wait_remote_sync_done(sync_handle *handle)
+{
+ sync_object *psyncobj;
+ addr_t *p = handle;
+
+ psyncobj = (sync_object *)p->va;
+
+ while (1) {
+ if (cache_operation(TEE_CACHECLEAN, psyncobj, sizeof(sync_object)) != TEE_SUCCESS)
+ EMSG("\x1b[31m == CACHE FAIL!! == \033[0m\n");
+
+ if (psyncobj->done == 1)
+ break;
+
+ mdelay(1);
+ }
+}
+
+void *get_hsm_address(sync_handle *p)
+{
+ return p->ha;
+}
+
+int get_hsm_return_value(sync_handle *p)
+{
+ sync_object *psyncobj;
+
+ psyncobj = (sync_object *)p->va;
+ if (cache_operation(TEE_CACHECLEAN, psyncobj, sizeof(sync_object)) != TEE_SUCCESS)
+ EMSG("\x1b[31m == CACHE FAIL!! == \033[0m\n");
+
+ return psyncobj->status;
+}
+
+void cclean_and_memcopy(void *dest, addr_t *src, size_t n)
+{
+ uint8_t *vsrc;
+ vsrc = (uint8_t *)src->va;
+ if (cache_operation(TEE_CACHECLEAN, vsrc, n) != TEE_SUCCESS)
+ EMSG("\x1b[31m == CACHE FAIL!! == \033[0m\n");
+
+ memcpy(dest, vsrc, n);
+}
+
+void memput_and_cclean(addr_t *dest, void *src, size_t n)
+{
+ uint8_t *vdst;
+ vdst = (uint8_t *)dest->va;
+
+ memcpy(vdst, src, n);
+
+ if (cache_operation(TEE_CACHECLEAN, vdst, n) != TEE_SUCCESS)
+ EMSG("\x1b[31m == CACHE FAIL!! == \033[0m\n");
+}
+
+
+int physical_malloc(uint32_t size, addr_t *addr)
+{
+ addr_t tmp = {0};
+
+ if (addr == NULL) {
+ goto fail;
+ }
+
+ if (buddy_malloc(size, &tmp) != BUDDY_OK) {
+ goto fail;
+ }
+
+ if (hsm_addr_remap(tmp.pa, &tmp.ha) != 0) {
+ goto fail;
+ }
+
+ok:
+ memcpy(addr, &tmp, sizeof(addr_t));
+ return 0;
+fail:
+ if (tmp.va != NULL) {
+ buddy_free(&tmp);
+ }
+ return -1;
+}
+
+
+void physical_free(addr_t *addr)
+{
+ if (addr == NULL) {
+ return;
+ }
+ buddy_free(addr);
+}
\ No newline at end of file
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sync_obj.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sync_obj.h
new file mode 100644
index 0000000..1e2bfbf
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/mbox/sync_obj.h
@@ -0,0 +1,68 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+#ifndef _SYNC_OBJ_H_
+#define _SYNC_OBJ_H_
+
+#include "address.h"
+
+typedef struct sync_object_t
+{
+ uint32_t done;
+ uint32_t status;
+} sync_object;
+
+typedef addr_t sync_handle;
+
+/*
+ * sync obj APIs
+ */
+int allocate_sync_handle(sync_handle *handle);
+int release_sync_handle(sync_handle *handle);
+void wait_remote_sync_done(sync_handle *handle);
+void *get_hsm_address(sync_handle *p);
+int get_hsm_return_value(sync_handle *p);
+
+/*
+ * memory opreation APIs
+ */
+int hsm_addr_remap(uint32_t phyaddr, uint32_t *p_remaped);
+void cclean_and_memcopy(void *dest, addr_t *src, size_t n);
+void memput_and_cclean(addr_t *dest, void *src, size_t n);
+int physical_malloc(uint32_t size, addr_t *addr);
+void physical_free(addr_t *addr);
+
+#endif /* end of include guard: _SYNC_OBJ_H_ */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/pta.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/pta.mk
new file mode 100644
index 0000000..d45f9bf
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/app/pta.mk
@@ -0,0 +1 @@
+include $(call all-pta-mk-under, $(call my-dir))
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/common/pta.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/pta.mk
new file mode 100644
index 0000000..d45f9bf
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/common/pta.mk
@@ -0,0 +1 @@
+include $(call all-pta-mk-under, $(call my-dir))
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta.mk
new file mode 100644
index 0000000..d45f9bf
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta.mk
@@ -0,0 +1 @@
+include $(call all-pta-mk-under, $(call my-dir))
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/include/pta_dapc.h b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/include/pta_dapc.h
new file mode 100644
index 0000000..c2b188c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/include/pta_dapc.h
@@ -0,0 +1,46 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+#ifndef __TEE_PTA_TTDAPC_H__
+#define __TEE_PTA_TTDAPC_H__
+
+#define PTA_DAPC_UUID {0x2603779b, 0xb2a6, 0x4f7e, {0x87, 0x83, 0x62, 0xab, 0x11, 0xb3, 0x83, 0xfd}}
+
+/* Command For DAPC TA */
+#define PTA_CMD_DAPC_TEST 0
+#define PTA_CMD_DAPC_MASTER_TEST 1
+#define PTA_CMD_DAPC_SLAVE_APC_TEST 2
+
+#endif /* __TEE_PTA_TTDAPC_H__ */
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/pta.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/pta.mk
new file mode 100644
index 0000000..5fb69ba
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/pta.mk
@@ -0,0 +1,5 @@
+libdir := $(call my-dir)
+libname := pta_dapc
+
+include $(BUILD_OPTEE_OS_LIB)
+
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/pta_dapc.c b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/pta_dapc.c
new file mode 100644
index 0000000..a0d6685
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/pta_dapc.c
@@ -0,0 +1,103 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2020. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#include <pta_dapc.h>
+#include <dapc_public.h>
+//#include <initcall.h>
+#include <io.h>
+#include <kernel/pseudo_ta.h>
+//#include <kernel/interrupt.h>
+//#include <mm/core_memprot.h>
+//#include <mm/core_mmu.h>
+#include <tee_api_defines.h>
+
+/* Static Function */
+static TEE_Result invoke_command(void *pSessionContext __unused,
+ uint32_t nCommandID, uint32_t nParamTypes,
+ TEE_Param pParams[TEE_NUM_PARAMS])
+{
+ uint32_t p1, p2, p3;
+ int ret;
+
+ EMSG("DEVAPC nCommandID(%x)\n", nCommandID);
+
+ switch (nCommandID) {
+ case PTA_CMD_DAPC_TEST:
+ EMSG("DEVAPC test command\n");
+
+ if (TEE_PARAM_TYPE_GET(nParamTypes, 0) != TEE_PARAM_TYPE_VALUE_INOUT)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ p1 = pParams[0].value.a;
+ p2 = pParams[0].value.b;
+ EMSG("input value p1: %u, p2: %u\n", p1, p2);
+
+ return TEE_SUCCESS;
+
+ case PTA_CMD_DAPC_MASTER_TEST:
+ EMSG("DEVAPC try to set master transaction...\n");
+
+ p1 = pParams[0].value.a;
+ p2 = pParams[1].value.a;
+ EMSG("input value p1: %u, p2: %u\n", p1, p2);
+
+ set_master_transaction(p1 ,p2);
+ dump_devapc();
+
+ return TEE_SUCCESS;
+
+ case PTA_CMD_DAPC_SLAVE_APC_TEST:
+ EMSG("DEVAPC try to set module apc...\n");
+
+ p1 = pParams[0].value.a;
+ p2 = pParams[1].value.a;
+ p3 = pParams[2].value.a;
+ EMSG("input value p1: %u, p2: %u, p3: %u\n", p1, p2, p3);
+
+ set_module_apc(p1, p2, p3);
+ dump_devapc();
+
+ return TEE_SUCCESS;
+ default:
+ break;
+ }
+
+ return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+pseudo_ta_register(.uuid = PTA_DAPC_UUID, .name = "pta_dapc",
+ .flags = PTA_DEFAULT_FLAGS,
+ .invoke_command_entry_point = invoke_command);
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/sub.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/sub.mk
new file mode 100644
index 0000000..713c26c
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/mt2712/pta_dapc/sub.mk
@@ -0,0 +1,11 @@
+srcs-y := \
+ pta_dapc.c
+
+incdirs-lib-y = \
+ include/ \
+ ../../../mt2712/dapc/include
+
+libdirs += $(call my-dir)/../../../mt2712/dapc
+libnames += dapc
+
+$(call add-pta-src, pta_dapc.c)
diff --git a/src/bsp/trustzone/optee/source/mt2xxx/pta/pta.mk b/src/bsp/trustzone/optee/source/mt2xxx/pta/pta.mk
new file mode 100644
index 0000000..fe62cda
--- /dev/null
+++ b/src/bsp/trustzone/optee/source/mt2xxx/pta/pta.mk
@@ -0,0 +1,45 @@
+define my-dir
+$(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
+endef
+
+define all-pta-mk-under
+$(wildcard $1/*/pta.mk)
+endef
+
+define _add-prebuilt-libname
+libdirs += $(call my-dir)
+libnames += $1
+endef
+
+define add-prebuilt-libname
+$(eval $(call _add-prebuilt-libname, $1))
+endef
+
+define add-pta-src
+$(eval LDADD := $(LDADD) $(out-dir)/../..$(subst ..,,$(libdir)/$(strip $(subst .c,.o,$1))))
+endef
+
+# $1: libname
+# $2: object file in libname
+define _add-libname-pta-obj
+my-path := $(call my-dir)
+$(out-dir)$$(subst ..,,$$(my-path))/$$(strip $2): $(call my-dir)/lib$$(strip $1).a
+ echo $$@
+ $(q)mkdir -p $$(dir $$@)
+ $(q)cd $$(dir $$@); $(AR$(sm)) x $$(abspath $$<) $2
+
+libdeps += $(out-dir)$$(subst ..,,$$(my-path))/$$(strip $2)
+LDADD := $(LDADD) $(out-dir)$$(subst ..,,$$(my-path))/$$(strip $2)
+endef
+
+define add-libname-pta-obj
+$(eval $(call _add-libname-pta-obj,$1,$2))
+endef
+
+base-prefix = core-lib/
+BUILD_OPTEE_OS_LIB := mk/lib.mk
+
+#include $(call all-pta-mk-under, $(call my-dir))
+include $(call my-dir)/common/pta.mk
+-include $(call my-dir)/$(PLATFORM_FLAVOR)/pta.mk
+