--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#include <cstring>
+#include <functional>
+#include <stdexcept>
+#include <string>
+
+#include <hal/hal-common-interface.h>
+#include <hal/hal-security-keys-interface.h>
+#include <hal/hal-security-keys-types.h>
+#include <km_ta_defines.h>
+#include <tee_client_api.h>
+
+#include "crypto-params.h"
+#include "log.h"
+#include "tz-memory.h"
+#include "tz-serializer.h"
+
+#define EXPORT __attribute__ ((visibility("default")))
+
+namespace {
+
+// Identifier of our key-manager TA
+const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
+
+tz_algo_type to_tz_algo_type(hal_security_keys_algo_type_e type)
+{
+ switch (type) {
+ case HAL_SECURITY_KEYS_ALGO_TYPE_AES_CTR: return ALGO_AES_CTR;
+ case HAL_SECURITY_KEYS_ALGO_TYPE_AES_CBC: return ALGO_AES_CBC;
+ case HAL_SECURITY_KEYS_ALGO_TYPE_AES_GCM: return ALGO_AES_GCM;
+ case HAL_SECURITY_KEYS_ALGO_TYPE_AES_CFB: return ALGO_AES_CFB;
+ case HAL_SECURITY_KEYS_ALGO_TYPE_RSA_OAEP: return ALGO_RSA;
+ case HAL_SECURITY_KEYS_ALGO_TYPE_RSA: return ALGO_RSA_SV;
+ case HAL_SECURITY_KEYS_ALGO_TYPE_DSA: return ALGO_DSA_SV;
+ case HAL_SECURITY_KEYS_ALGO_TYPE_ECDSA: return ALGO_ECDSA_SV;
+ default:
+ throw std::invalid_argument("Requested algorithm is not supported");
+ }
+}
+
+tz_ec to_tz_ec_type(hal_security_keys_ec_type_e ec)
+{
+ switch (ec) {
+ case HAL_SECURITY_KEYS_EC_TYPE_PRIME192V1: return EC_NIST_P192;
+ case HAL_SECURITY_KEYS_EC_TYPE_PRIME256V1: return EC_NIST_P256;
+ case HAL_SECURITY_KEYS_EC_TYPE_SECP384R1: return EC_NIST_P384;
+ default:
+ throw std::invalid_argument("EC not supported by tz-backend");
+ }
+}
+
+tz_kem to_tz_kem_type(hal_security_keys_kem_type_e kem)
+{
+ switch (kem) {
+ case HAL_SECURITY_KEYS_ML_KEM_768: return ML_KEM_768;
+ case HAL_SECURITY_KEYS_ML_KEM_1024: return ML_KEM_1024;
+ default:
+ throw std::invalid_argument("KEM not supported by tz-backend");
+ }
+}
+
+tz_data_type to_tz_data_type(hal_security_keys_data_type_e type)
+{
+ switch (type) {
+ case HAL_SECURITY_KEYS_DATA_TYPE_BINARY_DATA: return TYPE_GENERIC_SECRET;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_AES: return TYPE_SKEY;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_RSA_PUBLIC: return TYPE_AKEY_PUBLIC_RSA;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_RSA_PRIVATE: return TYPE_AKEY_PRIVATE_RSA;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_DSA_PUBLIC: return TYPE_AKEY_PUBLIC_DSA;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_DSA_PRIVATE: return TYPE_AKEY_PRIVATE_DSA;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_ECDSA_PUBLIC: return TYPE_AKEY_PUBLIC_EC;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_ECDSA_PRIVATE: return TYPE_AKEY_PRIVATE_EC;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_KEM_PUBLIC: return TYPE_AKEY_PUBLIC_KEM;
+ case HAL_SECURITY_KEYS_DATA_TYPE_KEY_KEM_PRIVATE: return TYPE_AKEY_PRIVATE_KEM;
+ default:
+ throw std::invalid_argument("Data type not supported by tz-backend");
+ }
+}
+
+tz_hash_type to_tz_hash_type(hal_security_keys_hash_algorithm_e hash)
+{
+ switch (hash) {
+ case HAL_SECURITY_KEYS_HASH_ALGORITHM_SHA1: return HASH_SHA1;
+ case HAL_SECURITY_KEYS_HASH_ALGORITHM_SHA256: return HASH_SHA256;
+ case HAL_SECURITY_KEYS_HASH_ALGORITHM_SHA384: return HASH_SHA384;
+ case HAL_SECURITY_KEYS_HASH_ALGORITHM_SHA512: return HASH_SHA512;
+ default:
+ throw std::invalid_argument("Requested hash algorithm is not supported");
+ }
+}
+
+tz_prf to_tz_prf(hal_security_keys_kdf_prf_type_e prf)
+{
+ switch (prf) {
+ case HAL_SECURITY_KEYS_PRF_TYPE_HMAC_SHA256: return PRF_HMAC_SHA256;
+ case HAL_SECURITY_KEYS_PRF_TYPE_HMAC_SHA384: return PRF_HMAC_SHA384;
+ case HAL_SECURITY_KEYS_PRF_TYPE_HMAC_SHA512: return PRF_HMAC_SHA512;
+ default:
+ throw std::invalid_argument("PRF not supported by tz-backend");
+ }
+}
+
+tz_kbkdf_mode to_tz_kbkdf_mode(hal_security_keys_kbkdf_mode_e mode)
+{
+ switch (mode) {
+ case HAL_SECURITY_KEYS_KBKDF_MODE_COUNTER: return KBKDF_MODE_COUNTER;
+ default:
+ throw std::invalid_argument("KBKDF mode not supported by tz-backend");
+ }
+}
+
+tz_kbkdf_ctr_loc to_tz_kbkdf_ctr_loc(hal_security_keys_kbkdf_counter_location_e loc)
+{
+ switch (loc) {
+ case HAL_SECURITY_KEYS_KBKDF_COUNTER_LOCATION_BEFORE_FIXED: return KBKDF_LOC_BEFORE_FIXED;
+ case HAL_SECURITY_KEYS_KBKDF_COUNTER_LOCATION_AFTER_FIXED: return KBKDF_LOC_AFTER_FIXED;
+ case HAL_SECURITY_KEYS_KBKDF_COUNTER_LOCATION_MIDDLE_FIXED: return KBKDF_LOC_MIDDLE_FIXED;
+ default:
+ throw std::invalid_argument("KBKDF counter location not supported by tz-backend");
+ }
+}
+
+//Maximum size for given key type in bytes according to key-manager-ta implementation.
+//Note that they are greater than TEE Internal Core API v1.1.2.50 (Table 5-9) values.
+size_t get_tz_max_key_size(tz_algo_type type)
+{
+ switch (type) {
+ case ALGO_RSA:
+ case ALGO_RSA_SV:
+ case ALGO_DSA_SV:
+ return 4096 / 8;
+ case ALGO_ECDSA_SV:
+ return 1024 / 8; // 384*2 + additional space for DER encoding
+ default:
+ throw std::invalid_argument("Algorithm not supported by tz-backend");
+ }
+}
+
+template <class T, bool uppercase = false>
+T hex_dump(const hal_security_keys_data_s &raw)
+{
+ T dump;
+
+ if (!raw.buffer)
+ return dump;
+
+ dump.reserve(2 * raw.length);
+ constexpr char digit[2][16] = {{
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'
+ }, {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+ }};
+
+ for (size_t i = 0; i < raw.length; ++i) {
+ dump.push_back(digit[uppercase][raw.buffer[i] / 16]);
+ dump.push_back(digit[uppercase][raw.buffer[i] % 16]);
+ }
+
+ return dump;
+}
+
+static std::string raw_to_hex_string(const hal_security_keys_data_s &raw)
+{
+ return hex_dump<std::string>(raw);
+}
+
+int try_catch(const std::function<int()> &func)
+{
+ try {
+ return func();
+ } catch (const std::invalid_argument &e) {
+ LOGE("Invalid parameter: " << e.what());
+ return HAL_SECURITY_KEYS_ERROR_INVALID_PARAMETER;
+ } catch (const std::bad_alloc &e) {
+ LOGE("Memory allocation exception: " << e.what());
+ return HAL_SECURITY_KEYS_ERROR_OUT_OF_MEMORY;
+ } catch (const std::exception &e) {
+ LOGE("Exception occurred: " << e.what());
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ } catch (...) {
+ LOGE("Unknown exception occurred.");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+}
+
+#define EXCEPTION_GUARD_START return try_catch([&]()->int {
+#define EXCEPTION_GUARD_END });
+
+#define CHECK_RET(func) do { int ret = (func); if (ret) return ret; } while (0)
+
+template <typename T>
+void push(TZSerializer& ser, const T& value)
+{
+ ser.Push(new TZSerializableFlag(static_cast<uint32_t>(value)));
+}
+
+template<>
+void push<hal_security_keys_data_s>(TZSerializer& ser, const hal_security_keys_data_s& value)
+{
+ ser.Push(new TZSerializableBinary(value));
+}
+
+template<>
+void push<hal_security_keys_password_iv_s>(TZSerializer& ser, const hal_security_keys_password_iv_s& value)
+{
+ int32_t with_pwd = !value.password.buffer ? 0 : 1;
+ ser.Push(new TZSerializableFlag(with_pwd));
+ if (with_pwd)
+ ser.Push(new TZSerializablePwdData(value.password, value.iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
+}
+
+template<>
+void push<hal_security_keys_password_iv_tag_s>(TZSerializer& ser, const hal_security_keys_password_iv_tag_s& value)
+{
+ int32_t with_pwd = !value.password.buffer ? 0 : 1;
+ ser.Push(new TZSerializableFlag(with_pwd));
+ if (with_pwd)
+ ser.Push(new TZSerializablePwdData(value.password,
+ value.iv,
+ value.tag.length * 8,
+ value.tag));
+}
+
+template <typename T, typename ...Args>
+void push(TZSerializer& ser, const T& first, const Args&... args)
+{
+ push<T>(ser, first);
+ push<Args...>(ser, args...);
+}
+
+template <typename ...Args>
+TZSerializer makeSerializer(const Args&... args)
+{
+ TZSerializer ser;
+ push<Args...>(ser, args...);
+ return ser;
+}
+
+TEEC_Operation make_op(uint32_t value, TrustZoneMemory& mem1)
+{
+ TEEC_Operation op;
+
+ op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE);
+
+ op.params[1].memref.parent = mem1.Get();
+ op.params[1].memref.offset = 0;
+ op.params[1].memref.size = mem1.Get()->size;
+ return op;
+}
+
+TEEC_Operation make_op(uint32_t value, TrustZoneMemory& mem1, TrustZoneMemory& mem2)
+{
+ TEEC_Operation op = make_op(value, mem1);
+
+ op.paramTypes = TEEC_PARAM_TYPES(value, TEEC_MEMREF_WHOLE, TEEC_MEMREF_WHOLE, TEEC_NONE);
+
+ op.params[2].memref.parent = mem2.Get();
+ op.params[2].memref.offset = 0;
+ op.params[2].memref.size = mem2.Get()->size;
+
+ return op;
+}
+
+int execute(tz_command command_id, TEEC_Operation* op, TEEC_Session tz_session)
+{
+ uint32_t ret = 0;
+ LOGD("Executing TZ operation " << command_id);
+
+ TEEC_Result result = TEEC_InvokeCommand(&tz_session, static_cast<unsigned int>(command_id), op, &ret);
+ if (result != TEEC_SUCCESS) {
+ switch (result) {
+ case TEEC_ERROR_TARGET_DEAD:
+ LOGE("TA panicked while executing command " << static_cast<unsigned int>(command_id));
+ return HAL_SECURITY_KEYS_ERROR_TARGET_DEAD;
+ case TEEC_ERROR_BAD_PARAMETERS:
+ LOGE("Incorrect parameters provided to TA");
+ return HAL_SECURITY_KEYS_ERROR_INVALID_PARAMETER;
+ default:
+ LOGE("TA failed to invoke command " <<
+ static_cast<unsigned int>(command_id) << " with error: " << std::hex <<
+ static_cast<unsigned int>(result) << " with origin: " << std::hex << ret);
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+ }
+
+ int ta_ret = op->params[0].value.a;
+ switch (ta_ret) {
+ case KM_TA_SUCCESS:
+ case KM_TA_ERROR_SIGNATURE:
+ return HAL_SECURITY_KEYS_ERROR_NONE;
+ case KM_TA_ERROR_AUTH_FAILED:
+ LOGE("Crypto operation authentication failed");
+ return HAL_SECURITY_KEYS_ERROR_AUTHENTICATION_FAILED;
+ default:
+ LOGE("Unknown TA error during operation: " << ta_ret);
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+}
+
+} // anonymous namespace
+
+int security_keys_context_initialize(hal_security_keys_context_s* context)
+{
+ EXCEPTION_GUARD_START
+ LOGD("security_keys_context_initialize");
+
+ if (!context)
+ return HAL_SECURITY_KEYS_ERROR_INVALID_PARAMETER;
+
+ TEEC_Context* tz_context = new TEEC_Context;
+ TEEC_Session* tz_session = new TEEC_Session;
+ if (!tz_context || !tz_session)
+ return HAL_SECURITY_KEYS_ERROR_OUT_OF_MEMORY;
+
+ TEEC_Operation op;
+ TEEC_Result result;
+ uint32_t ret;
+
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+
+ result = TEEC_InitializeContext(nullptr, tz_context);
+ if (result != TEEC_SUCCESS) {
+ LOGE("Failed to initialize context: " << result);
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+ context->ctx = (void *)tz_context;
+
+ result = TEEC_OpenSession(tz_context, tz_session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &ret);
+ if (result != TEEC_SUCCESS) {
+ LOGE("Failed to open session to Key Manager TA: " << result);
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+ context->session = (void *)tz_session;
+
+ LOGD("Initialized context");
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_context_free(hal_security_keys_context_s* context)
+{
+ EXCEPTION_GUARD_START
+ LOGD("security_keys_context_free");
+
+ if (!context)
+ return 0;
+
+ if (context->session) {
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context->session);
+ TEEC_CloseSession(tz_session);
+ delete static_cast<TEEC_Session*>(context->session);
+ context->session = nullptr;
+ }
+
+ if (context->ctx) {
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context->ctx);
+ TEEC_FinalizeContext(tz_context);
+ delete static_cast<TEEC_Context*>(context->ctx);
+ context->ctx = nullptr;
+ }
+
+ LOGD("Destroyed context");
+
+ return 0;
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_create_iv(const hal_security_keys_context_s context,
+ hal_security_keys_data_s* iv)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_GENERATE_IV
+ LOGD("security_keys_create_iv");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ TrustZoneMemory iv_memory(*tz_context, Params::DEFAULT_AES_IV_LEN, TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, iv_memory);
+
+ CHECK_RET(execute(CMD_GENERATE_IV, &op, *tz_session));
+
+ iv->buffer = (unsigned char*)malloc(iv_memory.Get()->size);
+ if (!(iv->buffer)) {
+ LOGE("Failed to allocate memory for IV");
+ return HAL_SECURITY_KEYS_ERROR_OUT_OF_MEMORY;
+ }
+
+ memcpy(iv->buffer, iv_memory.Get()->buffer, iv_memory.Get()->size);
+ iv->length = iv_memory.Get()->size;
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_create_key_aes(const hal_security_keys_context_s context,
+ const size_t key_size_bits,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_s key_pwd,
+ hal_security_keys_data_s* key_tag)
+{
+ EXCEPTION_GUARD_START
+ LOGD("security_keys_create_key_aes");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ bool with_pwd = !key_pwd.password.buffer ? 0 : 1;
+ if (with_pwd) {
+ // command ID = CMD_GENERATE_KEY_PWD
+ TZSerializer s_in;
+ s_in.Push(new TZSerializablePwdData(key_pwd.password, key_pwd.iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
+ s_in.Push(new TZSerializableBinary(key_id));
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = ALGO_AES_GEN;
+ op.params[0].value.b = key_size_bits;
+
+ CHECK_RET(execute(CMD_GENERATE_KEY_PWD, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(key_tag);
+
+ if (key_tag->length != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
+ LOGE("Deserialized incorrect key tag");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ return 0;
+ } else {
+ // command ID = CMD_GENERATE_KEY
+ TZSerializer s_in;
+ s_in.Push(new TZSerializableBinary(key_id));
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ op.params[0].value.a = ALGO_AES_GEN;
+ op.params[0].value.b = key_size_bits;
+
+ return execute(CMD_GENERATE_KEY, &op, *tz_session);
+ }
+
+ EXCEPTION_GUARD_END
+}
+
+int create_asym_key_pair(const hal_security_keys_context_s context,
+ tz_command command_id,
+ TZSerializer &s_in,
+ uint32_t gen_param, // key size in bits or type
+ const hal_security_keys_data_s priv_key_id,
+ const hal_security_keys_password_iv_s priv_key_pwd,
+ const hal_security_keys_data_s pub_key_id,
+ const hal_security_keys_password_iv_s pub_key_pwd,
+ hal_security_keys_data_s* priv_key_tag,
+ hal_security_keys_data_s* pub_key_tag)
+{
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ bool with_pub_pwd = !pub_key_pwd.password.buffer ? 0 : 1;
+ TZSerializer s_out;
+ if (with_pub_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+
+ bool with_priv_pwd = !priv_key_pwd.password.buffer ? 0 : 1;
+ if (with_priv_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+
+ push(s_in, pub_key_pwd, priv_key_pwd, priv_key_id, pub_key_id);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op;
+ if (s_out.GetSize() == 0)
+ op = make_op(TEEC_VALUE_INOUT, in_memory);
+ else
+ op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+
+ op.params[0].value.b = gen_param;
+
+ CHECK_RET(execute(command_id, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ if (with_pub_pwd)
+ s_out.Pull(pub_key_tag);
+
+ if (with_priv_pwd)
+ s_out.Pull(priv_key_tag);
+
+ return 0;
+}
+
+int security_keys_create_key_pair_rsa(const hal_security_keys_context_s context,
+ const size_t key_size_bits,
+ const hal_security_keys_data_s priv_key_id,
+ const hal_security_keys_password_iv_s priv_key_pwd,
+ const hal_security_keys_data_s pub_key_id,
+ const hal_security_keys_password_iv_s pub_key_pwd,
+ hal_security_keys_data_s* priv_key_tag,
+ hal_security_keys_data_s* pub_key_tag)
+
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_GENERATE_RSA_KEYPAIR
+ LOGD("security_keys_create_key_pair_rsa");
+
+ TZSerializer s_in;
+ return create_asym_key_pair(context, CMD_GENERATE_RSA_KEYPAIR,
+ s_in, key_size_bits,
+ priv_key_id, priv_key_pwd,
+ pub_key_id, pub_key_pwd,
+ priv_key_tag, pub_key_tag);
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_create_key_pair_dsa(const hal_security_keys_context_s context,
+ const size_t key_size_bits,
+ const hal_security_keys_data_s prime,
+ const hal_security_keys_data_s subprime,
+ const hal_security_keys_data_s base,
+ const hal_security_keys_data_s priv_key_id,
+ const hal_security_keys_password_iv_s priv_key_pwd,
+ const hal_security_keys_data_s pub_key_id,
+ const hal_security_keys_password_iv_s pub_key_pwd,
+ hal_security_keys_data_s* priv_key_tag,
+ hal_security_keys_data_s* pub_key_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_GENERATE_DSA_KEYPAIR
+ LOGD("security_keys_create_key_pair_dsa");
+
+ auto s_in = makeSerializer(prime, subprime, base);
+ return create_asym_key_pair(context, CMD_GENERATE_DSA_KEYPAIR,
+ s_in, key_size_bits,
+ priv_key_id, priv_key_pwd,
+ pub_key_id, pub_key_pwd,
+ priv_key_tag, pub_key_tag);
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_create_key_pair_ecdsa(const hal_security_keys_context_s context,
+ const hal_security_keys_ec_type_e ec_type,
+ const hal_security_keys_data_s priv_key_id,
+ const hal_security_keys_password_iv_s priv_key_pwd,
+ const hal_security_keys_data_s pub_key_id,
+ const hal_security_keys_password_iv_s pub_key_pwd,
+ hal_security_keys_data_s* priv_key_tag,
+ hal_security_keys_data_s* pub_key_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_GENERATE_EC_KEYPAIR
+ LOGD("security_keys_create_key_pair_ecdsa");
+
+ auto tz_ec_type = to_tz_ec_type(ec_type);
+
+ TZSerializer s_in;
+ return create_asym_key_pair(context, CMD_GENERATE_EC_KEYPAIR,
+ s_in, tz_ec_type,
+ priv_key_id, priv_key_pwd,
+ pub_key_id, pub_key_pwd,
+ priv_key_tag, pub_key_tag);
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_create_key_pair_kem(const hal_security_keys_context_s context,
+ const hal_security_keys_kem_type_e kem_type,
+ const hal_security_keys_data_s priv_key_id,
+ const hal_security_keys_password_iv_s priv_key_pwd,
+ const hal_security_keys_data_s pub_key_id,
+ const hal_security_keys_password_iv_s pub_key_pwd,
+ hal_security_keys_data_s* priv_key_tag,
+ hal_security_keys_data_s* pub_key_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_GENERATE_KEM_KEYPAIR
+ LOGD("security_keys_create_key_pair_kem");
+
+ auto tz_kem_type = to_tz_kem_type(kem_type);
+
+ TZSerializer s_in;
+ return create_asym_key_pair(context, CMD_GENERATE_KEM_KEYPAIR,
+ s_in, tz_kem_type,
+ priv_key_id, priv_key_pwd,
+ pub_key_id, pub_key_pwd,
+ priv_key_tag, pub_key_tag);
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_import_wrapped_key(const hal_security_keys_context_s context,
+ const hal_security_keys_algo_type_e algo,
+ const hal_security_keys_hash_algorithm_e hash,
+ const hal_security_keys_data_s iv,
+ const hal_security_keys_data_s aad,
+ const size_t ctr_len_or_tag_size_bits,
+ const hal_security_keys_data_s wrapping_key_id,
+ const hal_security_keys_password_iv_tag_s wrapping_key_pwd,
+ const hal_security_keys_data_s wrapped_key,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_s key_pwd,
+ const hal_security_keys_data_type_e key_type,
+ hal_security_keys_data_s* key_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_IMPORT_WRAPPED_KEY
+ LOGD("security_keys_import_wrapped_key wrapped_key size = [" << wrapped_key.length << "]");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_algo_type = to_tz_algo_type(algo);
+ auto tz_hash_type = to_tz_hash_type(hash);
+ auto tz_key_type = to_tz_data_type(key_type);
+
+ TZSerializer s_in;
+ if (tz_algo_type == ALGO_RSA) {
+ s_in = makeSerializer(wrapping_key_id, wrapping_key_pwd,
+ tz_algo_type, tz_hash_type, tz_key_type,
+ wrapped_key, key_pwd, key_id);
+ } else {
+ s_in = makeSerializer(wrapping_key_id, wrapping_key_pwd,
+ tz_algo_type, iv, ctr_len_or_tag_size_bits,
+ aad, tz_key_type, wrapped_key, key_pwd, key_id);
+ }
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ bool with_pwd = !key_pwd.password.buffer ? 0 : 1;
+ if (with_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ if (with_pwd)
+ op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+
+ CHECK_RET(execute(CMD_IMPORT_WRAPPED_KEY, &op, *tz_session));
+
+ if (with_pwd) {
+ s_out.Deserialize(out_memory);
+ s_out.Pull(key_tag);
+ }
+
+ LOGD("Imported object ID is (hex): " << raw_to_hex_string(key_id));
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+void get_data_size(const hal_security_keys_context_s context,
+ const hal_security_keys_data_s data_id,
+ const hal_security_keys_password_iv_tag_s pwd,
+ const tz_data_type type,
+ uint32_t &data_size)
+{
+ // command ID = CMD_GET_DATA_SIZE
+ LOGD("get_data_size");
+ LOGD("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << raw_to_hex_string(data_id));
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(data_id, pwd, type);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_OUTPUT, in_memory);
+
+ execute(CMD_GET_DATA_SIZE, &op, *tz_session);
+ data_size = op.params[0].value.b;
+}
+
+int security_keys_export_wrapped_key(const hal_security_keys_context_s context,
+ const hal_security_keys_algo_type_e algo,
+ const hal_security_keys_hash_algorithm_e hash,
+ const hal_security_keys_data_s iv,
+ const hal_security_keys_data_s aad,
+ const size_t ctr_len_or_tag_size_bits,
+ const hal_security_keys_data_s wrapping_key_id,
+ const hal_security_keys_password_iv_tag_s wrapping_key_pwd,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_tag_s key_pwd,
+ const hal_security_keys_data_type_e key_type,
+ hal_security_keys_data_s* wrapped_key)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_EXPORT_WRAPPED_KEY
+ LOGD("security_keys_export_wrapped_key");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_algo_type = to_tz_algo_type(algo);
+ auto tz_hash_type = to_tz_hash_type(hash);
+ auto tz_key_type = to_tz_data_type(key_type);
+
+ TZSerializer s_in;
+ if (tz_algo_type == ALGO_RSA) {
+ s_in = makeSerializer(wrapping_key_id, wrapping_key_pwd,
+ tz_algo_type, tz_hash_type,
+ key_id, key_pwd, tz_key_type);
+ } else {
+ s_in = makeSerializer(wrapping_key_id, wrapping_key_pwd,
+ tz_algo_type, iv, ctr_len_or_tag_size_bits,
+ aad, key_id, key_pwd, tz_key_type);
+ }
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ uint32_t data_size = 0;
+ get_data_size(context, key_id, key_pwd, tz_key_type, data_size);
+ LOGD("get_data_size = [" << data_size << "]");
+
+ uint32_t enc_overhead = KM_ENCRYPTION_OVERHEAD;
+ if (tz_algo_type == ALGO_RSA)
+ enc_overhead = KM_RSA_BLOCK_SIZE;
+
+ // encrypted data may be longer
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(data_size + enc_overhead, false));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+ s_out.Serialize(out_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+
+ CHECK_RET(execute(CMD_EXPORT_WRAPPED_KEY, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(wrapped_key);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_encapsulate_key(const hal_security_keys_context_s context,
+ const hal_security_keys_kem_type_e kem_type,
+ const hal_security_keys_data_s pub_key_id,
+ const hal_security_keys_password_iv_tag_s pub_key_pwd,
+ const hal_security_keys_data_s shared_secret_id,
+ const hal_security_keys_password_iv_s shared_secret_pwd,
+ hal_security_keys_data_s* ciphertext,
+ hal_security_keys_data_s* shared_secret_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_ENCAPSULATE_KEY
+ LOGD("security_keys_encapsulate_key");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_kem_type = to_tz_kem_type(kem_type);
+
+ TZSerializer s_in = makeSerializer(pub_key_id, pub_key_pwd,
+ shared_secret_pwd, shared_secret_id);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ uint32_t out_memory_size = 0;
+ switch (tz_kem_type) {
+ case ML_KEM_768:
+ out_memory_size = 1088;
+ break;
+ case ML_KEM_1024:
+ out_memory_size = 1568;
+ break;
+ default:
+ return HAL_SECURITY_KEYS_ERROR_INVALID_PARAMETER;
+ }
+ s_out.Push(new TZSerializableBinary(out_memory_size, false));
+
+ bool with_pwd = !shared_secret_pwd.password.buffer ? 0 : 1;
+ if (with_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = tz_kem_type;
+
+ CHECK_RET(execute(CMD_ENCAPSULATE_KEY, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(ciphertext);
+ if (with_pwd)
+ s_out.Pull(shared_secret_tag);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_decapsulate_key(const hal_security_keys_context_s context,
+ const hal_security_keys_kem_type_e kem_type,
+ const hal_security_keys_data_s priv_key_id,
+ const hal_security_keys_password_iv_tag_s priv_key_pwd,
+ const hal_security_keys_data_s shared_secret_id,
+ const hal_security_keys_password_iv_s shared_secret_pwd,
+ const hal_security_keys_data_s ciphertext,
+ hal_security_keys_data_s* shared_secret_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_DECAPSULATE_KEY
+ LOGD("security_keys_decapsulate_key");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_kem_type = to_tz_kem_type(kem_type);
+
+ TZSerializer s_in = makeSerializer(priv_key_id, priv_key_pwd,
+ shared_secret_pwd, shared_secret_id, ciphertext);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ bool with_pwd = !shared_secret_pwd.password.buffer ? 0 : 1;
+ if (with_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ if (with_pwd)
+ op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+
+ op.params[0].value.a = tz_kem_type;
+
+ CHECK_RET(execute(CMD_DECAPSULATE_KEY, &op, *tz_session));
+
+ if (with_pwd) {
+ s_out.Deserialize(out_memory);
+ s_out.Pull(shared_secret_tag);
+ }
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_destroy_key(const hal_security_keys_context_s context,
+ const hal_security_keys_data_s key_id)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_DESTROY_KEY
+ LOGD("security_keys_destroy_key");
+
+ if (key_id.length != KM_KEY_ID_SIZE) {
+ LOGE("TZ Backend received incorrect key buffer");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(key_id);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_OUTPUT, in_memory);
+
+ return execute(CMD_DESTROY_KEY, &op, *tz_session);
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_import_data(const hal_security_keys_context_s context,
+ const hal_security_keys_data_s data_id,
+ const hal_security_keys_password_iv_s data_pwd,
+ const hal_security_keys_data_type_e data_type,
+ const hal_security_keys_data_s data,
+ const hal_security_keys_data_s data_encryption_iv,
+ const hal_security_keys_data_s data_encryption_tag,
+ hal_security_keys_data_s* data_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_IMPORT_DATA
+ LOGD("security_keys_import_data data size = [" << data.length << "]");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_data_type = to_tz_data_type(data_type);
+
+ uint32_t data_size_bits = data.length * 8;
+ auto s_in = makeSerializer(tz_data_type, data, data_size_bits, data_encryption_iv, data_encryption_tag,
+ data_pwd, data_id);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ bool with_pwd = !data_pwd.password.buffer ? 0 : 1;
+ if (with_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ if (with_pwd)
+ op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+
+ CHECK_RET(execute(CMD_IMPORT_DATA, &op, *tz_session));
+
+ if (with_pwd) {
+ s_out.Deserialize(out_memory);
+ s_out.Pull(data_tag);
+ }
+
+ LOGD("Imported object ID is (hex): " << raw_to_hex_string(data_id));
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_export_data(const hal_security_keys_context_s context,
+ const hal_security_keys_data_s data_id,
+ const hal_security_keys_password_iv_tag_s data_pwd,
+ const hal_security_keys_data_type_e data_type,
+ hal_security_keys_data_s* data)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_GET_DATA
+ LOGD("security_keys_export_data");
+ LOGD("Object ID (passed to CMD_GET_DATA) is (hex): " << raw_to_hex_string(data_id));
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_data_type = to_tz_data_type(data_type);
+
+ auto s_in = makeSerializer(data_id, data_pwd, tz_data_type);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ uint32_t data_size = 0;
+ get_data_size(context, data_id, data_pwd, tz_data_type, data_size);
+ LOGD("get_data_size = [" << data_size << "]");
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(data_size));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+ s_out.Serialize(out_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+
+ CHECK_RET(execute(CMD_GET_DATA, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(data);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_wrap_concatenated_data(const hal_security_keys_context_s context,
+ const hal_security_keys_algo_type_e algo,
+ const hal_security_keys_hash_algorithm_e hash,
+ const hal_security_keys_data_s wrapping_key_id,
+ const hal_security_keys_password_iv_tag_s wrapping_key_pwd,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_tag_s key_pwd,
+ const hal_security_keys_data_s data,
+ hal_security_keys_data_s* wrapped_key)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_WRAP_CONCATENATED_DATA
+ LOGD("security_keys_wrap_concatenated_data");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_algo_type = to_tz_algo_type(algo);
+ auto tz_hash_type = to_tz_hash_type(hash);
+
+ if (tz_algo_type != ALGO_RSA) {
+ LOGE("Only RSA is supported in security_keys_wrap_concatenated_data");
+ return HAL_SECURITY_KEYS_ERROR_INVALID_PARAMETER;
+ }
+
+ TZSerializer s_in = makeSerializer(wrapping_key_id, wrapping_key_pwd,
+ tz_algo_type, tz_hash_type,
+ key_id, key_pwd, data);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ uint32_t out_memory_size = KM_RSA_BLOCK_SIZE;
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(out_memory_size, false));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+ s_out.Serialize(out_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ CHECK_RET(execute(CMD_WRAP_CONCATENATED_DATA, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(wrapped_key);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_unwrap_concatenated_data(const hal_security_keys_context_s context,
+ const hal_security_keys_algo_type_e algo,
+ const hal_security_keys_hash_algorithm_e hash,
+ const hal_security_keys_data_s wrapping_key_id,
+ const hal_security_keys_password_iv_tag_s wrapping_key_pwd,
+ const hal_security_keys_data_s wrapped_key,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_s key_pwd,
+ const hal_security_keys_data_type_e key_type,
+ const size_t key_size_bits,
+ hal_security_keys_data_s* data,
+ hal_security_keys_data_s* key_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_UNWRAP_CONCATENATED_DATA
+ LOGD("security_keys_unwrap_concatenated_data");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_algo_type = to_tz_algo_type(algo);
+ auto tz_hash_type = to_tz_hash_type(hash);
+ auto tz_key_type = to_tz_data_type(key_type);
+
+ if (tz_algo_type != ALGO_RSA) {
+ LOGE("Only RSA is supported in security_keys_unwrap_concatenated_data");
+ return HAL_SECURITY_KEYS_ERROR_INVALID_PARAMETER;
+ }
+
+ TZSerializer s_in = makeSerializer(wrapping_key_id, wrapping_key_pwd,
+ tz_algo_type, tz_hash_type, tz_key_type,
+ wrapped_key, key_pwd, key_id, key_size_bits);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ uint32_t out_memory_size = KM_RSA_BLOCK_SIZE;
+ bool with_pwd = !key_pwd.password.buffer ? 0 : 1;
+ if (with_pwd)
+ out_memory_size += Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
+
+ s_out.Push(new TZSerializableBinary(out_memory_size, false));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+ s_out.Serialize(out_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ CHECK_RET(execute(CMD_UNWRAP_CONCATENATED_DATA, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(data);
+ if (with_pwd)
+ s_out.Pull(key_tag);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_encrypt_data_auth(const hal_security_keys_context_s context,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_tag_s key_pwd,
+ const hal_security_keys_data_s data,
+ const hal_security_keys_data_s iv,
+ const hal_security_keys_data_s aad,
+ const size_t tag_size_bits,
+ hal_security_keys_data_s* tag,
+ hal_security_keys_data_s* out)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_ENCRYPT
+ LOGD("security_keys_encrypt_data_auth");
+
+ if (key_id.length != KM_KEY_ID_SIZE) {
+ LOGE("TZ Backend received incorrect key buffer");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(data, key_pwd, iv, key_id, aad, tag_size_bits);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ uint32_t out_memory_size = static_cast<uint32_t>(data.length + Params::CIPHER_EXTRA_PADDING_SIZE);
+ uint32_t tag_size_bytes = (tag_size_bits + 7) / 8;
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(out_memory_size, false));
+ s_out.Push(new TZSerializableBinary(tag_size_bytes));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = ALGO_AES_GCM;
+
+ CHECK_RET(execute(CMD_ENCRYPT, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(out);
+ s_out.Pull(tag);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_decrypt_data_auth(const hal_security_keys_context_s context,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_tag_s key_pwd,
+ const hal_security_keys_data_s data,
+ const hal_security_keys_data_s iv,
+ const hal_security_keys_data_s aad,
+ const size_t tag_size_bits,
+ const hal_security_keys_data_s tag,
+ hal_security_keys_data_s* out)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_DECRYPT
+ LOGD("security_keys_decrypt_data_auth");
+
+ if (key_id.length != KM_KEY_ID_SIZE) {
+ LOGE("TZ Backend received incorrect key buffer");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(data, key_pwd, iv, key_id, aad, tag_size_bits, tag);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(data.length));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = ALGO_AES_GCM;
+
+ CHECK_RET(execute(CMD_DECRYPT, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(out);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_encrypt_data(const hal_security_keys_context_s context,
+ const hal_security_keys_algo_type_e algo,
+ const hal_security_keys_hash_algorithm_e hash,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_tag_s key_pwd,
+ const hal_security_keys_data_s data,
+ const hal_security_keys_data_s iv,
+ hal_security_keys_data_s* out)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_ENCRYPT
+ LOGD("security_keys_encrypt_data");
+
+ if (key_id.length != KM_KEY_ID_SIZE) {
+ LOGE("TZ Backend received incorrect key buffer (size = " <<
+ std::to_string(key_id.length) << ")");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_algo_type = to_tz_algo_type(algo);
+ auto tz_hash_type = to_tz_hash_type(hash);
+
+ TZSerializer s_in;
+ if (tz_algo_type == ALGO_RSA)
+ s_in = makeSerializer(data, key_pwd, tz_hash_type, key_id);
+ else
+ s_in = makeSerializer(data, key_pwd, iv, key_id);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ uint32_t out_memory_size;
+ if (tz_algo_type == ALGO_RSA)
+ out_memory_size = get_tz_max_key_size(ALGO_RSA);
+ else
+ out_memory_size = static_cast<uint32_t>(data.length + Params::CIPHER_EXTRA_PADDING_SIZE);
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(out_memory_size, false));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = tz_algo_type;
+
+ CHECK_RET(execute(CMD_ENCRYPT, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(out);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_decrypt_data(const hal_security_keys_context_s context,
+ const hal_security_keys_algo_type_e algo,
+ const hal_security_keys_hash_algorithm_e hash,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_tag_s key_pwd,
+ const hal_security_keys_data_s data,
+ const hal_security_keys_data_s iv,
+ hal_security_keys_data_s* out)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_DECRYPT
+ LOGD("security_keys_decrypt_data");
+
+ if (key_id.length != KM_KEY_ID_SIZE) {
+ LOGE("TZ Backend received incorrect key buffer (size = " <<
+ std::to_string(key_id.length) << ")");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_algo_type = to_tz_algo_type(algo);
+ auto tz_hash_type = to_tz_hash_type(hash);
+
+ TZSerializer s_in;
+ if (tz_algo_type == ALGO_RSA)
+ s_in = makeSerializer(data, key_pwd, tz_hash_type, key_id);
+ else
+ s_in = makeSerializer(data, key_pwd, iv, key_id);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ // decrypt operation does not require padding
+ uint32_t out_memory_size = data.length;
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(out_memory_size, false));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = tz_algo_type;
+
+ CHECK_RET(execute(CMD_DECRYPT, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(out);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_destroy_data(const hal_security_keys_context_s context,
+ const hal_security_keys_data_s data_id)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_DESTROY_DATA
+ LOGD("security_keys_destroy_data");
+ LOGD("Object ID (passed to CMD_DESTROY_DATA) is (hex): " << raw_to_hex_string(data_id));
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(data_id);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_OUTPUT, in_memory);
+
+ return execute(CMD_DESTROY_DATA, &op, *tz_session);
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_cipher_initialize(const hal_security_keys_context_s context,
+ const bool encrypt,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_tag_s key_pwd,
+ const hal_security_keys_data_s iv,
+ const hal_security_keys_data_s aad,
+ const size_t tag_size_bits,
+ hal_security_keys_cipher_context_t* cipher_context)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_CIPHER_INIT
+ LOGD("security_keys_cipher_initialize");
+
+ if (key_id.length != KM_KEY_ID_SIZE) {
+ LOGE("TZ Backend received incorrect key buffer");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(key_pwd, iv, key_id, aad, tag_size_bits);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ op.params[0].value.a = ALGO_AES_GCM;
+ op.params[0].value.b = encrypt ? CIPHER_ENCRYPT : CIPHER_DECRYPT;
+
+ CHECK_RET(execute(CMD_CIPHER_INIT, &op, *tz_session));
+
+ *cipher_context = op.params[0].value.b;
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_cipher_add_aad(const hal_security_keys_context_s context,
+ const hal_security_keys_cipher_context_t cipher_context,
+ const hal_security_keys_data_s aad)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_CIPHER_INIT_AAD
+ LOGD("security_keys_cipher_add_aad");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(aad);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ op.params[0].value.a = cipher_context;
+
+ return execute(CMD_CIPHER_INIT_AAD, &op, *tz_session);
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_cipher_update(const hal_security_keys_context_s context,
+ const hal_security_keys_cipher_context_t cipher_context,
+ const hal_security_keys_data_s data,
+ hal_security_keys_data_s* out)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_CIPHER_UPDATE
+ LOGD("security_keys_cipher_update");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(data);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(data.length));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = cipher_context;
+
+ CHECK_RET(execute(CMD_CIPHER_UPDATE, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(out);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_cipher_finalize(const hal_security_keys_context_s context,
+ const hal_security_keys_cipher_context_t cipher_context,
+ const hal_security_keys_data_s data,
+ hal_security_keys_data_s* out)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_CIPHER_FINALIZE
+ LOGD("security_keys_cipher_finalize");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto s_in = makeSerializer(data);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES, false));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = cipher_context;
+
+ CHECK_RET(execute(CMD_CIPHER_FINALIZE, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(out);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_cipher_free(const hal_security_keys_context_s context,
+ const hal_security_keys_cipher_context_t cipher_context)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_CIPHER_CLEANUP
+ LOGD("security_keys_cipher_free");
+
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ TEEC_Operation op;
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+ op.params[0].value.a = cipher_context;
+
+ return execute(CMD_CIPHER_CLEANUP, &op, *tz_session);
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_create_signature(const hal_security_keys_context_s context,
+ const hal_security_keys_algo_type_e algo,
+ const hal_security_keys_hash_algorithm_e hash,
+ const hal_security_keys_data_s priv_key_id,
+ const hal_security_keys_password_iv_tag_s priv_key_pwd,
+ const hal_security_keys_data_s message,
+ hal_security_keys_data_s* signature)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_SIGN
+ LOGD("security_keys_create_signature");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_algo_type = to_tz_algo_type(algo);
+ auto tz_hash_type = to_tz_hash_type(hash);
+ auto tz_max_key_size = get_tz_max_key_size(tz_algo_type);
+
+ if (priv_key_id.length != KM_KEY_ID_SIZE) {
+ LOGE("TZ Backend received incorrect key buffer (size = " <<
+ std::to_string(priv_key_id.length) << ")");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ auto s_in = makeSerializer(message, priv_key_pwd, priv_key_id);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ s_out.Push(new TZSerializableBinary(tz_max_key_size, false));
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = tz_algo_type;
+ op.params[0].value.b = tz_hash_type;
+
+ CHECK_RET(execute(CMD_SIGN, &op, *tz_session));
+
+ s_out.Deserialize(out_memory);
+ s_out.Pull(signature);
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_verify_signature(const hal_security_keys_context_s context,
+ const hal_security_keys_algo_type_e algo,
+ const hal_security_keys_hash_algorithm_e hash,
+ const hal_security_keys_data_s pub_key_id,
+ const hal_security_keys_password_iv_tag_s pub_key_pwd,
+ const hal_security_keys_data_s message,
+ const hal_security_keys_data_s signature)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_VERIFY
+ LOGD("security_keys_verify_signature");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_algo_type = to_tz_algo_type(algo);
+ auto tz_hash_type = to_tz_hash_type(hash);
+
+ if (pub_key_id.length != KM_KEY_ID_SIZE) {
+ LOGE("TZ Backend received incorrect key buffer (size = " <<
+ std::to_string(pub_key_id.length) << ")");
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ auto s_in = makeSerializer(message, signature, pub_key_pwd, pub_key_id);
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ op.params[0].value.a = tz_algo_type;
+ op.params[0].value.b = tz_hash_type;
+
+ CHECK_RET(execute(CMD_VERIFY, &op, *tz_session));
+
+ int ret = op.params[0].value.a;
+ switch (ret) {
+ case KM_TA_SUCCESS:
+ return HAL_SECURITY_KEYS_ERROR_NONE;
+ case KM_TA_ERROR_SIGNATURE:
+ LOGW("Signature verification failed");
+ return HAL_SECURITY_KEYS_ERROR_VERIFICATION_FAILED;
+ default:
+ LOGE("Unknown TA error during operation: " << ret);
+ return HAL_SECURITY_KEYS_ERROR_INTERNAL_ERROR;
+ }
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_derive_ecdh(const hal_security_keys_context_s context,
+ const hal_security_keys_ec_type_e ec_type,
+ const hal_security_keys_data_s pub_key_x,
+ const hal_security_keys_data_s pub_key_y,
+ const hal_security_keys_data_s priv_key_id,
+ const hal_security_keys_password_iv_tag_s priv_key_pwd,
+ const hal_security_keys_data_s secret_id,
+ const hal_security_keys_password_iv_s secret_pwd,
+ hal_security_keys_data_s* secret_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_DERIVE
+ LOGD("security_keys_derive_ecdh");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_ec_type = to_tz_ec_type(ec_type);
+
+ auto s_in = makeSerializer(priv_key_id, priv_key_pwd, tz_ec_type,
+ pub_key_x, pub_key_y, secret_pwd, secret_id);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ bool with_pwd = !secret_pwd.password.buffer ? 0 : 1;
+ if (with_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ if (with_pwd)
+ op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = ALGO_ECDH_DRV;
+
+ CHECK_RET(execute(CMD_DERIVE, &op, *tz_session));
+
+ if (with_pwd) {
+ s_out.Deserialize(out_memory);
+ s_out.Pull(secret_tag);
+ }
+
+ LOGD("Derived object ID is (hex): " << raw_to_hex_string(secret_id));
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_derive_kbkdf(const hal_security_keys_context_s context,
+ const hal_security_keys_kbkdf_params_s params,
+ const hal_security_keys_data_s secret_id,
+ const hal_security_keys_password_iv_tag_s secret_pwd,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_s key_pwd,
+ hal_security_keys_data_s* key_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_DERIVE
+ LOGD("security_keys_derive_kbkdf");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_prf = to_tz_prf(params.prf);
+ auto tz_mode = to_tz_kbkdf_mode(params.mode);
+ auto tz_location = to_tz_kbkdf_ctr_loc(params.location);
+
+ auto s_in = makeSerializer(secret_id, secret_pwd,
+ params.length, params.label, params.context, params.fixed,
+ tz_prf, tz_mode, tz_location,
+ params.rlen, params.llen, params.no_separator,
+ key_pwd, key_id);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ bool with_pwd = !key_pwd.password.buffer ? 0 : 1;
+ if (with_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ if (with_pwd)
+ op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = ALGO_KBKDF_DRV;
+
+ CHECK_RET(execute(CMD_DERIVE, &op, *tz_session));
+
+ if (with_pwd) {
+ s_out.Deserialize(out_memory);
+ s_out.Pull(key_tag);
+ }
+
+ LOGD("Derived object ID is (hex): " << raw_to_hex_string(key_id));
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_derive_hybrid_kbkdf(const hal_security_keys_context_s context,
+ const hal_security_keys_kbkdf_params_s params,
+ const hal_security_keys_data_s first_secret_id,
+ const hal_security_keys_password_iv_tag_s first_secret_pwd,
+ const hal_security_keys_data_s second_secret_id,
+ const hal_security_keys_password_iv_tag_s second_secret_pwd,
+ const hal_security_keys_data_s key_id,
+ const hal_security_keys_password_iv_s key_pwd,
+ hal_security_keys_data_s* key_tag)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_DERIVE_HYBRID
+ LOGD("security_keys_derive_hybrid_kbkdf");
+
+ TEEC_Context* tz_context = static_cast<TEEC_Context*>(context.ctx);
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ auto tz_prf = to_tz_prf(params.prf);
+ auto tz_mode = to_tz_kbkdf_mode(params.mode);
+ auto tz_location = to_tz_kbkdf_ctr_loc(params.location);
+
+ auto s_in = makeSerializer(first_secret_id, first_secret_pwd,
+ second_secret_id, second_secret_pwd,
+ params.length, params.label, params.context, params.fixed,
+ tz_prf, tz_mode, tz_location,
+ params.rlen, params.llen, params.no_separator,
+ key_pwd, key_id);
+
+ TrustZoneMemory in_memory(*tz_context, s_in.GetSize(), TEEC_MEM_INPUT);
+ s_in.Serialize(in_memory);
+
+ TZSerializer s_out;
+ bool with_pwd = !key_pwd.password.buffer ? 0 : 1;
+ if (with_pwd)
+ s_out.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+
+ TrustZoneMemory out_memory(*tz_context, s_out.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op = make_op(TEEC_VALUE_INOUT, in_memory);
+ if (with_pwd)
+ op = make_op(TEEC_VALUE_INOUT, in_memory, out_memory);
+ op.params[0].value.a = ALGO_KBKDF_DRV;
+
+ CHECK_RET(execute(CMD_DERIVE_HYBRID, &op, *tz_session));
+
+ if (with_pwd) {
+ s_out.Deserialize(out_memory);
+ s_out.Pull(key_tag);
+ }
+
+ LOGD("Derived object ID is (hex): " << raw_to_hex_string(key_id));
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+int security_keys_get_max_chunk_size(const hal_security_keys_context_s context,
+ size_t* chunk_size)
+{
+ EXCEPTION_GUARD_START
+
+ // command ID = CMD_GET_MAX_CHUNK_SIZE
+ LOGD("security_keys_get_max_chunk_size");
+
+ TEEC_Session* tz_session = static_cast<TEEC_Session*>(context.session);
+
+ TEEC_Operation op;
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+
+ CHECK_RET(execute(CMD_GET_MAX_CHUNK_SIZE, &op, *tz_session));
+
+ *chunk_size = op.params[0].value.b;
+
+ return 0;
+
+ EXCEPTION_GUARD_END
+}
+
+static int security_keys_backend_init(void **data)
+{
+ hal_backend_security_keys_funcs *security_keys_funcs;
+
+ if (!data)
+ return HAL_SECURITY_KEYS_ERROR_INVALID_PARAMETER;
+
+ security_keys_funcs = *(hal_backend_security_keys_funcs **)data;
+ if (!security_keys_funcs)
+ return HAL_SECURITY_KEYS_ERROR_INVALID_PARAMETER;
+
+ security_keys_funcs->context_initialize = security_keys_context_initialize;
+ security_keys_funcs->context_free = security_keys_context_free;
+ security_keys_funcs->create_iv = security_keys_create_iv;
+ security_keys_funcs->create_key_aes = security_keys_create_key_aes;
+ security_keys_funcs->create_key_pair_rsa = security_keys_create_key_pair_rsa;
+ security_keys_funcs->create_key_pair_dsa = security_keys_create_key_pair_dsa;
+ security_keys_funcs->create_key_pair_ecdsa = security_keys_create_key_pair_ecdsa;
+ security_keys_funcs->create_key_pair_kem = security_keys_create_key_pair_kem;
+ security_keys_funcs->import_wrapped_key = security_keys_import_wrapped_key;
+ security_keys_funcs->export_wrapped_key = security_keys_export_wrapped_key;
+ security_keys_funcs->encapsulate_key = security_keys_encapsulate_key;
+ security_keys_funcs->decapsulate_key = security_keys_decapsulate_key;
+ security_keys_funcs->destroy_key = security_keys_destroy_key;
+ security_keys_funcs->import_data = security_keys_import_data;
+ security_keys_funcs->export_data = security_keys_export_data;
+ security_keys_funcs->wrap_concatenated_data = security_keys_wrap_concatenated_data;
+ security_keys_funcs->unwrap_concatenated_data = security_keys_unwrap_concatenated_data;
+ security_keys_funcs->encrypt_data_auth = security_keys_encrypt_data_auth;
+ security_keys_funcs->decrypt_data_auth = security_keys_decrypt_data_auth;
+ security_keys_funcs->encrypt_data = security_keys_encrypt_data;
+ security_keys_funcs->decrypt_data = security_keys_decrypt_data;
+ security_keys_funcs->destroy_data = security_keys_destroy_data;
+ security_keys_funcs->cipher_initialize = security_keys_cipher_initialize;
+ security_keys_funcs->cipher_add_aad = security_keys_cipher_add_aad;
+ security_keys_funcs->cipher_update = security_keys_cipher_update;
+ security_keys_funcs->cipher_finalize = security_keys_cipher_finalize;
+ security_keys_funcs->cipher_free = security_keys_cipher_free;
+ security_keys_funcs->create_signature = security_keys_create_signature;
+ security_keys_funcs->verify_signature = security_keys_verify_signature;
+ security_keys_funcs->derive_ecdh = security_keys_derive_ecdh;
+ security_keys_funcs->derive_kbkdf = security_keys_derive_kbkdf;
+ security_keys_funcs->derive_hybrid_kbkdf = security_keys_derive_hybrid_kbkdf;
+ security_keys_funcs->get_max_chunk_size = security_keys_get_max_chunk_size;
+
+ return 0;
+}
+
+static int security_keys_backend_exit(void *data)
+{
+ (void) data;
+ return 0;
+}
+
+EXPORT hal_backend hal_backend_security_keys_data = {
+ .name = "backend_security_keys",
+ .vendor = "Samsung",
+ .init = security_keys_backend_init,
+ .exit = security_keys_backend_exit,
+ .major_version = 1,
+ .minor_version = 0,
+};