From 98a04c21a7d86a80d7997d75ad2f4e8fd59343f5 Mon Sep 17 00:00:00 2001 From: Amey Avinash Raghatate Date: Fri, 22 Aug 2025 12:58:58 +0530 Subject: [PATCH 1/3] ecdh: new example demonstrating ECDH shared secret derivation - Introduced a new example utilizing the TEE_ALG_ECDH_DERIVE_SHARED_SECRET algorithm. - This example demonstrates how to establish a shared secret using Elliptic Curve Diffie-Hellman (ECDH). - Provides a reference for secure key exchange and cryptographic operations with ECDH in OP-TEE. Signed-off-by: Amey Avinash Raghatate --- ecdh/Android.mk | 17 +++ ecdh/CMakeLists.txt | 13 ++ ecdh/Makefile | 15 ++ ecdh/host/Makefile | 28 ++++ ecdh/host/main.c | 88 ++++++++++++ ecdh/ta/Android.mk | 3 + ecdh/ta/Makefile | 13 ++ ecdh/ta/ecdh_ta.c | 232 +++++++++++++++++++++++++++++++ ecdh/ta/include/ecdh_ta.h | 26 ++++ ecdh/ta/sub.mk | 2 + ecdh/ta/user_ta_header_defines.h | 27 ++++ 11 files changed, 464 insertions(+) create mode 100644 ecdh/Android.mk create mode 100644 ecdh/CMakeLists.txt create mode 100644 ecdh/Makefile create mode 100644 ecdh/host/Makefile create mode 100644 ecdh/host/main.c create mode 100644 ecdh/ta/Android.mk create mode 100644 ecdh/ta/Makefile create mode 100644 ecdh/ta/ecdh_ta.c create mode 100644 ecdh/ta/include/ecdh_ta.h create mode 100644 ecdh/ta/sub.mk create mode 100644 ecdh/ta/user_ta_header_defines.h diff --git a/ecdh/Android.mk b/ecdh/Android.mk new file mode 100644 index 0000000..c096f53 --- /dev/null +++ b/ecdh/Android.mk @@ -0,0 +1,17 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_CFLAGS += -DANDROID_BUILD +LOCAL_CFLAGS += -Wall + +LOCAL_SRC_FILES += host/main.c + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ta/include + +LOCAL_SHARED_LIBRARIES := libteec +LOCAL_MODULE := optee_example_ecdh +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_TAGS := optional +include $(BUILD_EXECUTABLE) + +include $(LOCAL_PATH)/ta/Android.mk diff --git a/ecdh/CMakeLists.txt b/ecdh/CMakeLists.txt new file mode 100644 index 0000000..17a2013 --- /dev/null +++ b/ecdh/CMakeLists.txt @@ -0,0 +1,13 @@ +project (optee_example_ecdh 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/ecdh/Makefile b/ecdh/Makefile new file mode 100644 index 0000000..dfa4f8b --- /dev/null +++ b/ecdh/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 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 diff --git a/ecdh/host/Makefile b/ecdh/host/Makefile new file mode 100644 index 0000000..f5861bd --- /dev/null +++ b/ecdh/host/Makefile @@ -0,0 +1,28 @@ +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 + +OBJS = main.o + +CFLAGS += -Wall -I../ta/include -I./include +CFLAGS += -I$(TEEC_EXPORT)/include +LDADD += -lteec -L$(TEEC_EXPORT)/lib + +BINARY = optee_example_ecdh + +.PHONY: all +all: $(BINARY) + +$(BINARY): $(OBJS) + $(CC) $(LDFLAGS) -o $@ $< $(LDADD) + +.PHONY: clean +clean: + rm -f $(OBJS) $(BINARY) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/ecdh/host/main.c b/ecdh/host/main.c new file mode 100644 index 0000000..a2f1800 --- /dev/null +++ b/ecdh/host/main.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Advanced Micro Devices, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include + +static void hexdump(const void *p, size_t len) +{ + const unsigned char *b = (const unsigned char *)p; + + for (size_t i = 0; i < len; i++) { + printf("%02x", b[i]); + if ((i + 1) % 32 == 0) + printf("\n"); + } + if (len % 32) + printf("\n"); +} + +int main(void) +{ + TEEC_Result res; + TEEC_Context ctx; + TEEC_Session sess; + TEEC_Operation op; + TEEC_UUID uuid = TA_ECDH_UUID; + uint32_t err_origin; + + 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 0x%x origin 0x%x", + res, err_origin); + + uint32_t curve = TA_ECC_CURVE_NIST_P384; + + uint8_t secret[ECDH_BUF_BYTES]; + + memset(&op, 0, sizeof(op)); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, + TEEC_NONE, + TEEC_NONE, + TEEC_MEMREF_TEMP_OUTPUT); + + op.params[0].value.a = curve; /* IN: curve id */ + op.params[0].value.b = 0; /* OUT: secret len */ + op.params[3].tmpref.buffer = secret; /* OUT buffer for secret */ + op.params[3].tmpref.size = sizeof(secret); + + res = TEEC_InvokeCommand(&sess, TA_ECDH_CMD_DERIVE_SELFTEST, + &op, &err_origin); + if (res == TEEC_ERROR_SHORT_BUFFER) { + /* Resize and try once more with the exact size TA asked for */ + size_t need = op.params[0].value.b; + + if (need > sizeof(secret)) + errx(1, "Required secret buffer too big: %zu", need); + + op.params[3].tmpref.size = need; + res = TEEC_InvokeCommand(&sess, TA_ECDH_CMD_DERIVE_SELFTEST, + &op, &err_origin); + } + + if (res != TEEC_SUCCESS) + errx(1, "Invoke TA_ECDH_CMD_DERIVE_SELFTEST failed 0x%x origin 0x%x", + res, err_origin); + + size_t secret_len = op.params[0].value.b; + + printf("ECDH shared secret (%zu bytes) on curve id %u:\n", + secret_len, curve); + hexdump(secret, secret_len); + + TEEC_CloseSession(&sess); + TEEC_FinalizeContext(&ctx); + return 0; +} diff --git a/ecdh/ta/Android.mk b/ecdh/ta/Android.mk new file mode 100644 index 0000000..7904968 --- /dev/null +++ b/ecdh/ta/Android.mk @@ -0,0 +1,3 @@ +LOCAL_PATH := $(call my-dir) +local_module := 50c82425-94da-4072-a3e0-58ef063767c0.ta +include $(BUILD_OPTEE_MK) diff --git a/ecdh/ta/Makefile b/ecdh/ta/Makefile new file mode 100644 index 0000000..d576fa1 --- /dev/null +++ b/ecdh/ta/Makefile @@ -0,0 +1,13 @@ +CFG_TEE_TA_LOG_LEVEL ?= 4 +CFG_TA_OPTEE_CORE_API_COMPAT_1_1=y + +# The UUID for the Trusted Application +BINARY=50c82425-94da-4072-a3e0-58ef063767c0 + +-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/ecdh/ta/ecdh_ta.c b/ecdh/ta/ecdh_ta.c new file mode 100644 index 0000000..d1892d4 --- /dev/null +++ b/ecdh/ta/ecdh_ta.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2025, Advanced Micro Devices, Inc. All rights reserved. + */ + +#include +#include + +#include + +#define CHECK(res, msg) \ + do { if ((res) != TEE_SUCCESS) { EMSG(msg); TEE_Panic((res)); } } while (0) + +static uint32_t curve_bits(uint32_t curve_id) +{ + switch (curve_id) { + case TEE_ECC_CURVE_NIST_P192: + return 192; + case TEE_ECC_CURVE_NIST_P224: + return 224; + case TEE_ECC_CURVE_NIST_P256: + return 256; + case TEE_ECC_CURVE_NIST_P384: + return 384; + default: + return 0; + } +} + +static uint32_t select_curve(uint32_t curve_id) +{ + switch (curve_id) { + case TA_ECC_CURVE_NIST_P192: + return TEE_ECC_CURVE_NIST_P192; + case TA_ECC_CURVE_NIST_P224: + return TEE_ECC_CURVE_NIST_P224; + case TA_ECC_CURVE_NIST_P256: + return TEE_ECC_CURVE_NIST_P256; + case TA_ECC_CURVE_NIST_P384: + return TEE_ECC_CURVE_NIST_P384; + default: + return 0; + } + +} + +static TEE_Result gen_ec_keypair(TEE_ObjectHandle *key, uint32_t curve) +{ + TEE_Result res; + uint32_t bits = curve_bits(curve); + TEE_Attribute attrs[1]; + + if (!bits) + return TEE_ERROR_BAD_PARAMETERS; + + res = TEE_AllocateTransientObject(TEE_TYPE_ECDH_KEYPAIR, bits, key); + if (res) + return res; + + TEE_InitValueAttribute(&attrs[0], TEE_ATTR_ECC_CURVE, curve, 0); + res = TEE_GenerateKey(*key, bits, attrs, 1); + return res; +} + +static TEE_Result get_pub_xy(TEE_ObjectHandle key, + uint8_t *x, uint32_t *x_len, + uint8_t *y, uint32_t *y_len) +{ + TEE_Result res; + + res = TEE_GetObjectBufferAttribute(key, TEE_ATTR_ECC_PUBLIC_VALUE_X, + x, x_len); + if (res) + return res; + res = TEE_GetObjectBufferAttribute(key, TEE_ATTR_ECC_PUBLIC_VALUE_Y, + y, y_len); + return res; +} + +static TEE_Result derive_secret(TEE_ObjectHandle my_key, + const uint8_t *peer_x, uint32_t peer_x_len, + const uint8_t *peer_y, uint32_t peer_y_len, + uint8_t *secret, uint32_t *secret_len, + uint32_t curve) +{ + TEE_Result res; + uint32_t bits = curve_bits(curve); + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle derived = TEE_HANDLE_NULL; + TEE_Attribute params[2]; + + if (!bits) + return TEE_ERROR_BAD_PARAMETERS; + + /* Allocate operation for ECDH derive */ + res = TEE_AllocateOperation(&op, TEE_ALG_ECDH_DERIVE_SHARED_SECRET, + TEE_MODE_DERIVE, bits); + if (res) + return res; + + res = TEE_SetOperationKey(op, my_key); + if (res) + goto out; + + /* Provide peer public coordinates as derivation parameters */ + TEE_InitRefAttribute(¶ms[0], TEE_ATTR_ECC_PUBLIC_VALUE_X, + (void *)peer_x, peer_x_len); + TEE_InitRefAttribute(¶ms[1], TEE_ATTR_ECC_PUBLIC_VALUE_Y, + (void *)peer_y, peer_y_len); + + /* Derived secret goes into a GENERIC_SECRET transient object */ + res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET, bits, &derived); + if (res) + goto out; + + TEE_DeriveKey(op, params, 2, derived); + + /* Fetch the raw shared secret bytes */ + res = TEE_GetObjectBufferAttribute(derived, TEE_ATTR_SECRET_VALUE, + secret, secret_len); + +out: + if (derived != TEE_HANDLE_NULL) + TEE_FreeTransientObject(derived); + if (op != TEE_HANDLE_NULL) + TEE_FreeOperation(op); + return res; +} + +static TEE_Result cmd_ecdh_selftest(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res; + const uint32_t exp_pt = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, /* curve id in,secret len out */ + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT); /* shared secret out */ + + if (param_types != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + uint32_t curve_ta = params[0].value.a; + uint32_t curve = select_curve(curve_ta); + uint32_t bits = curve_bits(curve); + + DMSG("curve = %u", curve); + DMSG("bits = %u", bits); + + if (!bits) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_ObjectHandle keyA = TEE_HANDLE_NULL, keyB = TEE_HANDLE_NULL; + + res = gen_ec_keypair(&keyA, curve); + CHECK(res, "gen key A"); + + res = gen_ec_keypair(&keyB, curve); + CHECK(res, "gen key B"); + + /* Export A.pub and B.pub */ + uint8_t Ax[ECDH_BUF_BYTES] = {0}, Ay[ECDH_BUF_BYTES] = {0}; + uint8_t Bx[ECDH_BUF_BYTES] = {0}, By[ECDH_BUF_BYTES] = {0}; + uint32_t Ax_len = ECDH_BUF_BYTES, Ay_len = ECDH_BUF_BYTES; + uint32_t Bx_len = ECDH_BUF_BYTES, By_len = ECDH_BUF_BYTES; + + res = get_pub_xy(keyA, Ax, &Ax_len, Ay, &Ay_len); + CHECK(res, "get A pub"); + + res = get_pub_xy(keyB, Bx, &Bx_len, By, &By_len); + CHECK(res, "get B pub"); + + /* Derive from A with B.pub and from B with A.pub */ + uint8_t Sa[ECDH_BUF_BYTES] = {0}, Sb[ECDH_BUF_BYTES] = {0}; + uint32_t Sa_len = ECDH_BUF_BYTES, Sb_len = ECDH_BUF_BYTES; + + res = derive_secret(keyA, Bx, Bx_len, By, By_len, Sa, &Sa_len, curve); + CHECK(res, "derive A"); + + res = derive_secret(keyB, Ax, Ax_len, Ay, Ay_len, Sb, &Sb_len, curve); + CHECK(res, "derive B"); + + /* They must be identical in length and value */ + if (Sa_len != Sb_len || TEE_MemCompare(Sa, Sb, Sa_len) != 0) { + res = TEE_ERROR_GENERIC; + goto out; + } + + /* Copy to output */ + if (params[3].memref.size < Sa_len) { + /* Tell host needed size */ + params[0].value.b = Sa_len; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + TEE_MemMove(params[3].memref.buffer, Sa, Sa_len); + params[0].value.b = Sa_len; + params[3].memref.size = Sa_len; + res = TEE_SUCCESS; + +out: + if (keyA != TEE_HANDLE_NULL) + TEE_FreeTransientObject(keyA); + if (keyB != TEE_HANDLE_NULL) + TEE_FreeTransientObject(keyB); + return res; +} + +/* TA entry points */ + +TEE_Result TA_CreateEntryPoint(void) { return TEE_SUCCESS; } +void TA_DestroyEntryPoint(void) {} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t pt, TEE_Param params[4], void **ctx) +{ + (void)pt; (void)params; (void)ctx; + return TEE_SUCCESS; +} +void TA_CloseSessionEntryPoint(void *ctx) { (void)ctx; } + +TEE_Result TA_InvokeCommandEntryPoint(void *ctx, uint32_t cmd_id, + uint32_t param_types, TEE_Param params[4]) +{ + (void)ctx; + + switch (cmd_id) { + case TA_ECDH_CMD_DERIVE_SELFTEST: + return cmd_ecdh_selftest(param_types, params); + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/ecdh/ta/include/ecdh_ta.h b/ecdh/ta/include/ecdh_ta.h new file mode 100644 index 0000000..f6e5757 --- /dev/null +++ b/ecdh/ta/include/ecdh_ta.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Advanced Micro Devices, Inc. All rights reserved. + */ + +#ifndef __ECDH_TA_H__ +#define __ECDH_TA_H__ + +/* UUID of the ECDH example trusted application */ + +#define TA_ECDH_UUID \ + { 0x50c82425, 0x94da, 0x4072, \ + { 0xa3, 0xe0, 0x58, 0xef, 0x06, 0x37, 0x67, 0xc0 } } + +#define TA_ECDH_CMD_DERIVE_SELFTEST 0 + +#define TA_ECC_CURVE_NIST_P192 0 +#define TA_ECC_CURVE_NIST_P224 1 +#define TA_ECC_CURVE_NIST_P256 2 +#define TA_ECC_CURVE_NIST_P384 3 + +#define ECDH_MAX_BITS 521 +#define ECDH_MAX_BYTES ((ECDH_MAX_BITS + 7) / 8) +#define ECDH_BUF_BYTES (ECDH_MAX_BYTES + 14) + +#endif diff --git a/ecdh/ta/sub.mk b/ecdh/ta/sub.mk new file mode 100644 index 0000000..ae33971 --- /dev/null +++ b/ecdh/ta/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ecdh_ta.c diff --git a/ecdh/ta/user_ta_header_defines.h b/ecdh/ta/user_ta_header_defines.h new file mode 100644 index 0000000..4d4a5fb --- /dev/null +++ b/ecdh/ta/user_ta_header_defines.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2025, Advanced Micro Devices, Inc. All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_ECDH_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) + +/* The gpd.ta.version property */ +#define TA_VERSION "1.0" + +/* The gpd.ta.description property */ +#define TA_DESCRIPTION "Example of TA using an ECDH sequence" + +#endif /*USER_TA_HEADER_DEFINES_H*/ From 46318074c956d89b967356b3ce62e92288abb667 Mon Sep 17 00:00:00 2001 From: Amey Avinash Raghatate Date: Fri, 19 Sep 2025 14:44:46 +0530 Subject: [PATCH 2/3] [REVIEW] update ecdh TA as per the review comments Update ecdh TA as per the review comments. Signed-off-by: Amey Avinash Raghatate --- ecdh/host/main.c | 31 +++-------- ecdh/ta/ecdh_ta.c | 94 ++++++++++++++++++-------------- ecdh/ta/include/ecdh_ta.h | 10 ++-- ecdh/ta/user_ta_header_defines.h | 2 +- 4 files changed, 68 insertions(+), 69 deletions(-) diff --git a/ecdh/host/main.c b/ecdh/host/main.c index a2f1800..50da0dc 100644 --- a/ecdh/host/main.c +++ b/ecdh/host/main.c @@ -26,12 +26,15 @@ static void hexdump(const void *p, size_t len) int main(void) { - TEEC_Result res; - TEEC_Context ctx; - TEEC_Session sess; - TEEC_Operation op; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Context ctx = {0}; + TEEC_Session sess = {0}; + TEEC_Operation op = {0}; TEEC_UUID uuid = TA_ECDH_UUID; - uint32_t err_origin; + uint32_t err_origin = 0; + size_t secret_len = 0; + uint32_t curve = TA_ECDH_ECC_CURVE_NIST_P384; + uint8_t secret[ECDH_BUF_BYTES]; res = TEEC_InitializeContext(NULL, &ctx); if (res != TEEC_SUCCESS) @@ -43,10 +46,6 @@ int main(void) errx(1, "TEEC_OpenSession failed 0x%x origin 0x%x", res, err_origin); - uint32_t curve = TA_ECC_CURVE_NIST_P384; - - uint8_t secret[ECDH_BUF_BYTES]; - memset(&op, 0, sizeof(op)); op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, @@ -60,23 +59,11 @@ int main(void) res = TEEC_InvokeCommand(&sess, TA_ECDH_CMD_DERIVE_SELFTEST, &op, &err_origin); - if (res == TEEC_ERROR_SHORT_BUFFER) { - /* Resize and try once more with the exact size TA asked for */ - size_t need = op.params[0].value.b; - - if (need > sizeof(secret)) - errx(1, "Required secret buffer too big: %zu", need); - - op.params[3].tmpref.size = need; - res = TEEC_InvokeCommand(&sess, TA_ECDH_CMD_DERIVE_SELFTEST, - &op, &err_origin); - } - if (res != TEEC_SUCCESS) errx(1, "Invoke TA_ECDH_CMD_DERIVE_SELFTEST failed 0x%x origin 0x%x", res, err_origin); - size_t secret_len = op.params[0].value.b; + secret_len = op.params[0].value.b; printf("ECDH shared secret (%zu bytes) on curve id %u:\n", secret_len, curve); diff --git a/ecdh/ta/ecdh_ta.c b/ecdh/ta/ecdh_ta.c index d1892d4..3fd4ab6 100644 --- a/ecdh/ta/ecdh_ta.c +++ b/ecdh/ta/ecdh_ta.c @@ -30,23 +30,23 @@ static uint32_t curve_bits(uint32_t curve_id) static uint32_t select_curve(uint32_t curve_id) { switch (curve_id) { - case TA_ECC_CURVE_NIST_P192: + case TA_ECDH_ECC_CURVE_NIST_P192: return TEE_ECC_CURVE_NIST_P192; - case TA_ECC_CURVE_NIST_P224: + case TA_ECDH_ECC_CURVE_NIST_P224: return TEE_ECC_CURVE_NIST_P224; - case TA_ECC_CURVE_NIST_P256: + case TA_ECDH_ECC_CURVE_NIST_P256: return TEE_ECC_CURVE_NIST_P256; - case TA_ECC_CURVE_NIST_P384: + case TA_ECDH_ECC_CURVE_NIST_P384: return TEE_ECC_CURVE_NIST_P384; default: - return 0; + return TEE_CRYPTO_ELEMENT_NONE; } } static TEE_Result gen_ec_keypair(TEE_ObjectHandle *key, uint32_t curve) { - TEE_Result res; + TEE_Result res = TEE_ERROR_GENERIC; uint32_t bits = curve_bits(curve); TEE_Attribute attrs[1]; @@ -58,15 +58,14 @@ static TEE_Result gen_ec_keypair(TEE_ObjectHandle *key, uint32_t curve) return res; TEE_InitValueAttribute(&attrs[0], TEE_ATTR_ECC_CURVE, curve, 0); - res = TEE_GenerateKey(*key, bits, attrs, 1); - return res; + return TEE_GenerateKey(*key, bits, attrs, 1); } static TEE_Result get_pub_xy(TEE_ObjectHandle key, uint8_t *x, uint32_t *x_len, uint8_t *y, uint32_t *y_len) { - TEE_Result res; + TEE_Result res = TEE_ERROR_GENERIC; res = TEE_GetObjectBufferAttribute(key, TEE_ATTR_ECC_PUBLIC_VALUE_X, x, x_len); @@ -78,12 +77,12 @@ static TEE_Result get_pub_xy(TEE_ObjectHandle key, } static TEE_Result derive_secret(TEE_ObjectHandle my_key, - const uint8_t *peer_x, uint32_t peer_x_len, - const uint8_t *peer_y, uint32_t peer_y_len, + uint8_t *peer_x, uint32_t peer_x_len, + uint8_t *peer_y, uint32_t peer_y_len, uint8_t *secret, uint32_t *secret_len, uint32_t curve) { - TEE_Result res; + TEE_Result res = TEE_ERROR_GENERIC; uint32_t bits = curve_bits(curve); TEE_OperationHandle op = TEE_HANDLE_NULL; TEE_ObjectHandle derived = TEE_HANDLE_NULL; @@ -104,9 +103,9 @@ static TEE_Result derive_secret(TEE_ObjectHandle my_key, /* Provide peer public coordinates as derivation parameters */ TEE_InitRefAttribute(¶ms[0], TEE_ATTR_ECC_PUBLIC_VALUE_X, - (void *)peer_x, peer_x_len); + peer_x, peer_x_len); TEE_InitRefAttribute(¶ms[1], TEE_ATTR_ECC_PUBLIC_VALUE_Y, - (void *)peer_y, peer_y_len); + peer_y, peer_y_len); /* Derived secret goes into a GENERIC_SECRET transient object */ res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET, bits, &derived); @@ -142,41 +141,44 @@ static TEE_Result cmd_ecdh_selftest(uint32_t param_types, TEE_Param params[4]) uint32_t curve_ta = params[0].value.a; uint32_t curve = select_curve(curve_ta); uint32_t bits = curve_bits(curve); + uint8_t Ax[ECDH_BUF_BYTES] = {0}; + uint8_t Ay[ECDH_BUF_BYTES] = {0}; + uint8_t Bx[ECDH_BUF_BYTES] = {0}; + uint8_t By[ECDH_BUF_BYTES] = {0}; + uint32_t Ax_len = ECDH_BUF_BYTES; + uint32_t Ay_len = ECDH_BUF_BYTES; + uint32_t Bx_len = ECDH_BUF_BYTES; + uint32_t By_len = ECDH_BUF_BYTES; + uint8_t Sa[ECDH_BUF_BYTES] = {0}; + uint8_t Sb[ECDH_BUF_BYTES] = {0}; + uint32_t Sa_len = ECDH_BUF_BYTES; + uint32_t Sb_len = ECDH_BUF_BYTES; DMSG("curve = %u", curve); DMSG("bits = %u", bits); - if (!bits) + if (!bits || curve == TEE_CRYPTO_ELEMENT_NONE) return TEE_ERROR_BAD_PARAMETERS; - TEE_ObjectHandle keyA = TEE_HANDLE_NULL, keyB = TEE_HANDLE_NULL; + TEE_ObjectHandle key_a = TEE_HANDLE_NULL; + TEE_ObjectHandle key_b = TEE_HANDLE_NULL; - res = gen_ec_keypair(&keyA, curve); + res = gen_ec_keypair(&key_a, curve); CHECK(res, "gen key A"); - res = gen_ec_keypair(&keyB, curve); + res = gen_ec_keypair(&key_b, curve); CHECK(res, "gen key B"); - /* Export A.pub and B.pub */ - uint8_t Ax[ECDH_BUF_BYTES] = {0}, Ay[ECDH_BUF_BYTES] = {0}; - uint8_t Bx[ECDH_BUF_BYTES] = {0}, By[ECDH_BUF_BYTES] = {0}; - uint32_t Ax_len = ECDH_BUF_BYTES, Ay_len = ECDH_BUF_BYTES; - uint32_t Bx_len = ECDH_BUF_BYTES, By_len = ECDH_BUF_BYTES; - - res = get_pub_xy(keyA, Ax, &Ax_len, Ay, &Ay_len); + res = get_pub_xy(key_a, Ax, &Ax_len, Ay, &Ay_len); CHECK(res, "get A pub"); - res = get_pub_xy(keyB, Bx, &Bx_len, By, &By_len); + res = get_pub_xy(key_b, Bx, &Bx_len, By, &By_len); CHECK(res, "get B pub"); - /* Derive from A with B.pub and from B with A.pub */ - uint8_t Sa[ECDH_BUF_BYTES] = {0}, Sb[ECDH_BUF_BYTES] = {0}; - uint32_t Sa_len = ECDH_BUF_BYTES, Sb_len = ECDH_BUF_BYTES; - - res = derive_secret(keyA, Bx, Bx_len, By, By_len, Sa, &Sa_len, curve); + res = derive_secret(key_a, Bx, Bx_len, By, By_len, Sa, &Sa_len, curve); CHECK(res, "derive A"); - res = derive_secret(keyB, Ax, Ax_len, Ay, Ay_len, Sb, &Sb_len, curve); + res = derive_secret(key_b, Ax, Ax_len, Ay, Ay_len, Sb, &Sb_len, curve); CHECK(res, "derive B"); /* They must be identical in length and value */ @@ -199,24 +201,34 @@ static TEE_Result cmd_ecdh_selftest(uint32_t param_types, TEE_Param params[4]) res = TEE_SUCCESS; out: - if (keyA != TEE_HANDLE_NULL) - TEE_FreeTransientObject(keyA); - if (keyB != TEE_HANDLE_NULL) - TEE_FreeTransientObject(keyB); + if (key_a != TEE_HANDLE_NULL) + TEE_FreeTransientObject(key_a); + if (key_b != TEE_HANDLE_NULL) + TEE_FreeTransientObject(key_b); return res; } /* TA entry points */ -TEE_Result TA_CreateEntryPoint(void) { return TEE_SUCCESS; } -void TA_DestroyEntryPoint(void) {} +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} -TEE_Result TA_OpenSessionEntryPoint(uint32_t pt, TEE_Param params[4], void **ctx) +TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused, + TEE_Param params[4] __unused, + void **ctx __unused) { - (void)pt; (void)params; (void)ctx; return TEE_SUCCESS; } -void TA_CloseSessionEntryPoint(void *ctx) { (void)ctx; } + +void TA_CloseSessionEntryPoint(void *ctx __unused) +{ +} TEE_Result TA_InvokeCommandEntryPoint(void *ctx, uint32_t cmd_id, uint32_t param_types, TEE_Param params[4]) diff --git a/ecdh/ta/include/ecdh_ta.h b/ecdh/ta/include/ecdh_ta.h index f6e5757..22da253 100644 --- a/ecdh/ta/include/ecdh_ta.h +++ b/ecdh/ta/include/ecdh_ta.h @@ -12,12 +12,12 @@ { 0x50c82425, 0x94da, 0x4072, \ { 0xa3, 0xe0, 0x58, 0xef, 0x06, 0x37, 0x67, 0xc0 } } -#define TA_ECDH_CMD_DERIVE_SELFTEST 0 +#define TA_ECDH_CMD_DERIVE_SELFTEST 0 -#define TA_ECC_CURVE_NIST_P192 0 -#define TA_ECC_CURVE_NIST_P224 1 -#define TA_ECC_CURVE_NIST_P256 2 -#define TA_ECC_CURVE_NIST_P384 3 +#define TA_ECDH_ECC_CURVE_NIST_P192 0 +#define TA_ECDH_ECC_CURVE_NIST_P224 1 +#define TA_ECDH_ECC_CURVE_NIST_P256 2 +#define TA_ECDH_ECC_CURVE_NIST_P384 3 #define ECDH_MAX_BITS 521 #define ECDH_MAX_BYTES ((ECDH_MAX_BITS + 7) / 8) diff --git a/ecdh/ta/user_ta_header_defines.h b/ecdh/ta/user_ta_header_defines.h index 4d4a5fb..5d31fe7 100644 --- a/ecdh/ta/user_ta_header_defines.h +++ b/ecdh/ta/user_ta_header_defines.h @@ -10,7 +10,7 @@ #define TA_UUID TA_ECDH_UUID -#define TA_FLAGS TA_FLAG_EXEC_DDR +#define TA_FLAGS 0 /* Provisioned stack size */ #define TA_STACK_SIZE (2 * 1024) From eabef55e2ffd49077ac1dda5b3ccdb043225512f Mon Sep 17 00:00:00 2001 From: Amey Avinash Raghatate Date: Thu, 25 Sep 2025 10:44:32 +0530 Subject: [PATCH 3/3] [REVIEW] update ecdh TA as per the review comments Update ecdh TA as per the review comments Signed-off-by: Amey Avinash Raghatate --- ecdh/ta/ecdh_ta.c | 83 ++++++++++++++++++--------------------- ecdh/ta/include/ecdh_ta.h | 11 ++++++ 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/ecdh/ta/ecdh_ta.c b/ecdh/ta/ecdh_ta.c index 3fd4ab6..b8a1bab 100644 --- a/ecdh/ta/ecdh_ta.c +++ b/ecdh/ta/ecdh_ta.c @@ -48,7 +48,7 @@ static TEE_Result gen_ec_keypair(TEE_ObjectHandle *key, uint32_t curve) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t bits = curve_bits(curve); - TEE_Attribute attrs[1]; + TEE_Attribute attrs[1] = { }; if (!bits) return TEE_ERROR_BAD_PARAMETERS; @@ -86,7 +86,7 @@ static TEE_Result derive_secret(TEE_ObjectHandle my_key, uint32_t bits = curve_bits(curve); TEE_OperationHandle op = TEE_HANDLE_NULL; TEE_ObjectHandle derived = TEE_HANDLE_NULL; - TEE_Attribute params[2]; + TEE_Attribute params[2] = { }; if (!bits) return TEE_ERROR_BAD_PARAMETERS; @@ -119,49 +119,46 @@ static TEE_Result derive_secret(TEE_ObjectHandle my_key, secret, secret_len); out: - if (derived != TEE_HANDLE_NULL) - TEE_FreeTransientObject(derived); - if (op != TEE_HANDLE_NULL) - TEE_FreeOperation(op); + TEE_FreeTransientObject(derived); + TEE_FreeOperation(op); return res; } static TEE_Result cmd_ecdh_selftest(uint32_t param_types, TEE_Param params[4]) { - TEE_Result res; + TEE_Result res = TEE_ERROR_GENERIC; const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, /* curve id in,secret len out */ TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT); /* shared secret out */ - if (param_types != exp_pt) - return TEE_ERROR_BAD_PARAMETERS; - uint32_t curve_ta = params[0].value.a; uint32_t curve = select_curve(curve_ta); uint32_t bits = curve_bits(curve); - uint8_t Ax[ECDH_BUF_BYTES] = {0}; - uint8_t Ay[ECDH_BUF_BYTES] = {0}; - uint8_t Bx[ECDH_BUF_BYTES] = {0}; - uint8_t By[ECDH_BUF_BYTES] = {0}; - uint32_t Ax_len = ECDH_BUF_BYTES; - uint32_t Ay_len = ECDH_BUF_BYTES; - uint32_t Bx_len = ECDH_BUF_BYTES; - uint32_t By_len = ECDH_BUF_BYTES; - uint8_t Sa[ECDH_BUF_BYTES] = {0}; - uint8_t Sb[ECDH_BUF_BYTES] = {0}; - uint32_t Sa_len = ECDH_BUF_BYTES; - uint32_t Sb_len = ECDH_BUF_BYTES; - - DMSG("curve = %u", curve); - DMSG("bits = %u", bits); + uint8_t a_x[ECDH_BUF_BYTES] = {0}; + uint8_t a_y[ECDH_BUF_BYTES] = {0}; + uint8_t b_x[ECDH_BUF_BYTES] = {0}; + uint8_t b_y[ECDH_BUF_BYTES] = {0}; + uint32_t a_x_len = ECDH_BUF_BYTES; + uint32_t a_y_len = ECDH_BUF_BYTES; + uint32_t b_x_len = ECDH_BUF_BYTES; + uint32_t b_y_len = ECDH_BUF_BYTES; + uint8_t s_a[ECDH_BUF_BYTES] = {0}; + uint8_t s_b[ECDH_BUF_BYTES] = {0}; + uint32_t s_a_len = ECDH_BUF_BYTES; + uint32_t s_b_len = ECDH_BUF_BYTES; + TEE_ObjectHandle key_a = TEE_HANDLE_NULL; + TEE_ObjectHandle key_b = TEE_HANDLE_NULL; - if (!bits || curve == TEE_CRYPTO_ELEMENT_NONE) + if (param_types != exp_pt) return TEE_ERROR_BAD_PARAMETERS; - TEE_ObjectHandle key_a = TEE_HANDLE_NULL; - TEE_ObjectHandle key_b = TEE_HANDLE_NULL; + DMSG("curve = %"PRIu32, curve); + DMSG("bits = %"PRIu32, bits); + + if (!bits || curve == TEE_CRYPTO_ELEMENT_NONE) + return TEE_ERROR_BAD_PARAMETERS; res = gen_ec_keypair(&key_a, curve); CHECK(res, "gen key A"); @@ -169,42 +166,40 @@ static TEE_Result cmd_ecdh_selftest(uint32_t param_types, TEE_Param params[4]) res = gen_ec_keypair(&key_b, curve); CHECK(res, "gen key B"); - res = get_pub_xy(key_a, Ax, &Ax_len, Ay, &Ay_len); + res = get_pub_xy(key_a, a_x, &a_x_len, a_y, &a_y_len); CHECK(res, "get A pub"); - res = get_pub_xy(key_b, Bx, &Bx_len, By, &By_len); + res = get_pub_xy(key_b, b_x, &b_x_len, b_y, &b_y_len); CHECK(res, "get B pub"); - res = derive_secret(key_a, Bx, Bx_len, By, By_len, Sa, &Sa_len, curve); + res = derive_secret(key_a, b_x, b_x_len, b_y, b_y_len, s_a, &s_a_len, curve); CHECK(res, "derive A"); - res = derive_secret(key_b, Ax, Ax_len, Ay, Ay_len, Sb, &Sb_len, curve); + res = derive_secret(key_b, a_x, a_x_len, a_y, a_y_len, s_b, &s_b_len, curve); CHECK(res, "derive B"); /* They must be identical in length and value */ - if (Sa_len != Sb_len || TEE_MemCompare(Sa, Sb, Sa_len) != 0) { + if (s_a_len != s_b_len || TEE_MemCompare(s_a, s_b, s_a_len) != 0) { res = TEE_ERROR_GENERIC; goto out; } /* Copy to output */ - if (params[3].memref.size < Sa_len) { + if (params[3].memref.size < s_a_len) { /* Tell host needed size */ - params[0].value.b = Sa_len; + params[0].value.b = s_a_len; res = TEE_ERROR_SHORT_BUFFER; goto out; } - TEE_MemMove(params[3].memref.buffer, Sa, Sa_len); - params[0].value.b = Sa_len; - params[3].memref.size = Sa_len; + TEE_MemMove(params[3].memref.buffer, s_a, s_a_len); + params[0].value.b = s_a_len; + params[3].memref.size = s_a_len; res = TEE_SUCCESS; out: - if (key_a != TEE_HANDLE_NULL) - TEE_FreeTransientObject(key_a); - if (key_b != TEE_HANDLE_NULL) - TEE_FreeTransientObject(key_b); + TEE_FreeTransientObject(key_a); + TEE_FreeTransientObject(key_b); return res; } @@ -230,11 +225,9 @@ void TA_CloseSessionEntryPoint(void *ctx __unused) { } -TEE_Result TA_InvokeCommandEntryPoint(void *ctx, uint32_t cmd_id, +TEE_Result TA_InvokeCommandEntryPoint(void *ctx __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[4]) { - (void)ctx; - switch (cmd_id) { case TA_ECDH_CMD_DERIVE_SELFTEST: return cmd_ecdh_selftest(param_types, params); diff --git a/ecdh/ta/include/ecdh_ta.h b/ecdh/ta/include/ecdh_ta.h index 22da253..f41e7ae 100644 --- a/ecdh/ta/include/ecdh_ta.h +++ b/ecdh/ta/include/ecdh_ta.h @@ -13,6 +13,17 @@ { 0xa3, 0xe0, 0x58, 0xef, 0x06, 0x37, 0x67, 0xc0 } } #define TA_ECDH_CMD_DERIVE_SELFTEST 0 +/* + * TA_ECDH_CMD_DERIVE_SELFTEST - Test EC keys generation and ECDH derivation + * + * in params[0].value.a EC curve ID (one of TA_ECDH_ECC_CURVE_*) + * out params[3].memref Generated shared secret key from ECDH + * + * Return TEE_SUCCESS upon success. + * Return TEE_ERROR_SHORT_BUFFER is output buffer is too short in which case + * size is provided output in param[3]memref.size) + * Return another compliant TEE_Result error code in case of failure. + */ #define TA_ECDH_ECC_CURVE_NIST_P192 0 #define TA_ECDH_ECC_CURVE_NIST_P224 1