Fix secret pwd passing in TZ backend KBKDF
[platform/core/security/key-manager.git] / src / manager / crypto / tz-backend / tz-context.cpp
index f9b2f2b..ad09c65 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2017-2021 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.
  * @version    1.0
  */
 
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
 #include <tz-backend/tz-context.h>
 #include <tz-backend/tz-memory.h>
-#include <tz-backend/tz-serializer.h>
 #include <generic-backend/exception.h>
 #include <generic-backend/crypto-params.h>
 #include <generic-backend/encryption-params.h>
@@ -32,6 +33,8 @@
 
 #include <cstdint>
 #include <cstring>
+#include <cassert>
+#include <unordered_map>
 
 namespace CKM {
 namespace Crypto {
@@ -47,22 +50,82 @@ namespace {
 // whatever TA will return us.
 const uint32_t CIPHER_EXTRA_PADDING_SIZE = 16;
 
+// Maximum size of GCM tag in bytes.
+const size_t MAX_GCM_TAG_SIZE = 16;
+
 // Identifier of our TA
 const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
 
 //raw to hex string conversion to print persistent storage data ID
 static std::string rawToHexString(const RawBuffer &raw)
 {
-        std::string dump;
+       return hexDump<std::string>(raw);
+}
+
+/*
+ * 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.
+ */
+const std::unordered_map<tz_algo_type, size_t> MAX_KEY_SIZE = {
+       { ALGO_RSA, 4096 / 8 },
+       { ALGO_RSA_SV, 4096 / 8 },
+       { ALGO_DSA_SV, 4096 / 8 },
+       { ALGO_ECDSA_SV, 1024 / 8 } // 384*2 + additional space for DERR encoding
+};
+
+struct EncPwd {
+       const RawBuffer &password;
+       const RawBuffer &iv;
+};
+
+template <typename T>
+void push(TZSerializer& ser, const T& value)
+{
+       ser.Push(new TZSerializableFlag(static_cast<uint32_t>(value)));
+}
+
+template<>
+void push<RawBuffer>(TZSerializer& ser, const RawBuffer& value)
+{
+       ser.Push(new TZSerializableBinary(value));
+}
 
-        for (auto &e : raw) {
-                char buf[3];
-                snprintf(buf, sizeof(buf), "%02x", (e & 0xff));
-                dump.push_back(buf[0]);
-                dump.push_back(buf[1]);
-        }
+template<>
+void push<Pwd>(TZSerializer& ser, const Pwd& value)
+{
+       int32_t pwd_flag = value.getPassword().empty() ? 0 : 1;
+       ser.Push(new TZSerializableFlag(pwd_flag));
+       if (pwd_flag)
+               ser.Push(new TZSerializablePwdData(value.getPassword(),
+                                                                                  value.getIV(),
+                                                                                  value.getTag().size() * 8,
+                                                                                  value.getTag()));
+}
+
+template<>
+void push<EncPwd>(TZSerializer& ser, const EncPwd& value)
+{
+       int32_t pwd_flag = value.password.empty() ? 0 : 1;
+       ser.Push(new TZSerializableFlag(pwd_flag));
+       if (pwd_flag)
+               ser.Push(new TZSerializablePwdData(value.password,
+                                                                                  value.iv,
+                                                                                  Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
+}
+
+template <typename T, typename ...Args>
+void push(TZSerializer& ser, const T& first, const Args&... args)
+{
+       push<T>(ser, first);
+       push<Args...>(ser, args...);
+}
 
-        return dump;
+template <typename ...Args>
+TZSerializer makeSerializer(const Args&... args)
+{
+       TZSerializer ser;
+       push<Args...>(ser, args...);
+       return ser;
 }
 
 } // anonymous namespace
@@ -85,28 +148,41 @@ TrustZoneContext& TrustZoneContext::Instance()
        return instance;
 }
 
+TEEC_Operation makeOp(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 makeOp(uint32_t value, TrustZoneMemory& mem1, TrustZoneMemory& mem2)
+{
+       TEEC_Operation op = makeOp(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;
+}
+
 void TrustZoneContext::generateIV(RawBuffer& iv)
 {
        // command ID = CMD_GENERATE_IV
-       //
-       // TEEC_Operation layout:
-       // params:
-       //   [1].memref.buffer - output
-       //   [1].memref.size - output size
-       // output:
-       //   [0].value.a - return code
-
        // IV generation is a simple call - no need to serialize data
        // just provide the output buffer with size equal to iv.
        uint32_t ivSize = Params::DEFAULT_AES_IV_LEN;
        TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_NONE, TEEC_NONE);
-       op.params[1].memref.parent = ivMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = ivMemory.Get()->size;
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, ivMemory);
+
        Execute(CMD_GENERATE_IV, &op);
 
        iv.resize(ivSize);
@@ -115,254 +191,229 @@ void TrustZoneContext::generateIV(RawBuffer& iv)
 
 void TrustZoneContext::generateSKey(tz_algo_type algo,
                                                                        uint32_t keySizeBits,
-                                                                       RawBuffer &keyId)
+                                                                       const RawBuffer &hash)
 {
        // command ID = CMD_GENERATE_KEY
-       //
-       // TEEC_Operation layout:
-       // params:
-       //   [0].value.a - key type
-       //   [0].value.b - key bit size
-       // output:
-       //   [0].value.a - return code
-       //   [1].memref - serialized key reference
-
-       KM_BufferSizeDesc bufSize;
-
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.out_size = KM_KEY_ID_SIZE;
-       uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
+       auto sIn = makeSerializer(hash);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_NONE, TEEC_NONE);
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
        op.params[0].value.a = algo;
        op.params[0].value.b = keySizeBits;
-       op.params[1].memref.parent = keyMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = keyMemorySize;
-       Execute(CMD_GENERATE_KEY, &op);
 
-       KM_SymmetricInput* output = nullptr;
-       int ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
-       }
-
-       KM_OutData* outData = nullptr;
-       ret = KM_ParamsDeserializeOutData(output, &outData);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
-       }
-
-       if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
-               ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
-       }
-
-       keyId.resize(KM_KEY_ID_SIZE);
-       memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
+       Execute(CMD_GENERATE_KEY, &op);
 }
 
 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
                                                                        const RawBuffer &pwd,
                                                                        const RawBuffer &iv,
                                                                        const uint32_t keySizeBits,
-                                                                       RawBuffer &keyId,
-                                                                       RawBuffer &pwdTag)
+                                                                       RawBuffer &pwdTag,
+                                                                       const RawBuffer &hash)
 {
        // command ID = CMD_GENERATE_KEY_PWD
-       //
-       // TEEC_Operation layout:
-       // params:
-       //   [0].value.a - key type
-       //   [0].value.b - key size in bits
-       //   [1].memref  - input (seralized pwd/iv for pbkdf2)
-       // output:
-       //   [0].value.a - return code
-       //   [2].memref - serialized key reference ID
-
-       KM_BufferSizeDesc bufSize;
-
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.with_pwd_data = true;
-       bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
-       bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
-       uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
-
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.out_size = KM_KEY_ID_SIZE;
-       bufSize.tag_size = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
-       uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
-
-       KM_SymmetricInput* input = nullptr;
-       int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
-       }
+       TZSerializer sIn;
+       sIn.Push(new TZSerializablePwdData(pwd, iv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
+       sIn.Push(new TZSerializableBinary(hash));
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
 
-       ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
-                                                                       nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
-                                                                       Params::DERIVED_KEY_ITERATIONS, bufSize.tag_size * 8);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
-       }
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_MEMREF_WHOLE, TEEC_NONE);
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
        op.params[0].value.a = algo;
        op.params[0].value.b = keySizeBits;
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
-       op.params[2].memref.parent = keyMemory.Get();
-       op.params[2].memref.offset = 0;
-       op.params[2].memref.size = keyMemory.Get()->size;
+
        Execute(CMD_GENERATE_KEY_PWD, &op);
 
-       KM_SymmetricInput* output = nullptr;
-       ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
-       }
+       sOut.Deserialize(outMemory);
+       sOut.Pull(pwdTag);
 
-       KM_OutData* outData = nullptr;
-       ret = KM_ParamsDeserializeOutData(output, &outData);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
+       if (pwdTag.size() != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
+               ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
        }
+}
 
-       KM_TagData* tagData = nullptr;
-       ret = KM_ParamsDeserializeTagData(output, &tagData);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key's tag");
+void TrustZoneContext::GenerateAKey(tz_command commandId,
+                                    TZSerializer &sIn,
+                                    uint32_t genParam, // key size in bits or EC type
+                                    const RawBuffer &pubPwd,
+                                    const RawBuffer &pubPwdIv,
+                                    const RawBuffer &privPwd,
+                                    const RawBuffer &privPwdIv,
+                                    RawBuffer &pubKeyTag,
+                                    RawBuffer &privKeyTag,
+                                    const RawBuffer &hashPriv,
+                                                                       const RawBuffer &hashPub)
+{
+       uint32_t pubTagSize = 0;
+       uint32_t privTagSize = 0;
+       uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1;
+       if (pubPwdExists) {
+               pubTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
+       }
+       uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
+       if (privPwdExists) {
+               privTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
        }
 
-       if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
-               ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
+       push(sIn, EncPwd{pubPwd, pubPwdIv}, EncPwd{privPwd, privPwdIv}, hashPriv, hashPub);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(pubTagSize));
+       sOut.Push(new TZSerializableBinary(privTagSize));
+
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+       op.params[0].value.b = genParam;
+
+       Execute(commandId, &op);
+
+       sOut.Deserialize(outMemory);
+       if (pubPwdExists) {
+               sOut.Pull(pubKeyTag);
        }
 
-       if (tagData == nullptr || tagData->data_size != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
-               ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
+       if (privPwdExists) {
+               sOut.Pull(privKeyTag);
        }
+}
+
+void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
+                                                                       const RawBuffer &pubPwd,
+                                                                       const RawBuffer &pubPwdIv,
+                                                                       const RawBuffer &privPwd,
+                                                                       const RawBuffer &privPwdIv,
+                                                                       RawBuffer &pubKeyTag,
+                                                                       RawBuffer &privKeyTag,
+                                                                       const RawBuffer &hashPriv,
+                                                                       const RawBuffer &hashPub)
+{
+       // command ID = CMD_GENERATE_RSA_KEYPAIR
+       TZSerializer sIn;
 
-       keyId.resize(KM_KEY_ID_SIZE);
-       memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
+       GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
+                    sIn,
+                    keySizeBits,
+                    pubPwd,
+                    pubPwdIv,
+                    privPwd,
+                    privPwdIv,
+                    pubKeyTag,
+                    privKeyTag,
+                    hashPriv,
+                    hashPub);
+}
 
-       pwdTag.resize(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
-       memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
+void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
+                                                                       const RawBuffer &prime,
+                                                                       const RawBuffer &subprime,
+                                                                       const RawBuffer &base,
+                                                                       const RawBuffer &pubPwd,
+                                                                       const RawBuffer &pubPwdIv,
+                                                                       const RawBuffer &privPwd,
+                                                                       const RawBuffer &privPwdIv,
+                                                                       RawBuffer &pubKeyTag,
+                                                                       RawBuffer &privKeyTag,
+                                                                       const RawBuffer &hashPriv,
+                                                                       const RawBuffer &hashPub)
+{
+       // command ID = CMD_GENERATE_DSA_KEYPAIR
+       auto sIn = makeSerializer(prime, subprime, base);
+
+       GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
+                    sIn,
+                    keySizeBits,
+                    pubPwd,
+                    pubPwdIv,
+                    privPwd,
+                    privPwdIv,
+                    pubKeyTag,
+                    privKeyTag,
+                    hashPriv,
+                    hashPub);
+}
+
+void TrustZoneContext::generateECKey(tz_ec ec,
+                                                                        const RawBuffer &pubPwd,
+                                                                        const RawBuffer &pubPwdIv,
+                                                                        const RawBuffer &privPwd,
+                                                                        const RawBuffer &privPwdIv,
+                                                                        RawBuffer &pubKeyTag,
+                                                                        RawBuffer &privKeyTag,
+                                                                        const RawBuffer &hashPriv,
+                                                                        const RawBuffer &hashPub)
+{
+       // command ID = CMD_GENERATE_EC_KEYPAIR
+       TZSerializer sIn;
+
+       GenerateAKey(CMD_GENERATE_EC_KEYPAIR,
+                    sIn,
+                    static_cast<uint32_t>(ec),
+                    pubPwd,
+                    pubPwdIv,
+                    privPwd,
+                    privPwdIv,
+                    pubKeyTag,
+                    privKeyTag,
+                    hashPriv,
+                    hashPub);
 }
 
 void TrustZoneContext::executeCrypt(tz_command cmd,
                                                                        tz_algo_type algo,
-                                                                       const RawBuffer &key,
+                                                                       const RawBuffer &keyId,
                                                                        const Pwd &pwd,
                                                                        const RawBuffer &iv,
                                                                        const RawBuffer &data,
                                                                        RawBuffer &out)
 {
        // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
-       //
-       // TEEC_Operation layout:
-       // params:
-       //   [0].value.a - keyid
-       //   [0].value.b - algo
-       //   [1].memref - input data (serialized key/input)
-       // returned:
-       //   [0].value.a - return code
-       //   [2].memref - serialized output buffer
-
-       if (key.size() != KM_KEY_ID_SIZE) {
+       if (keyId.size() != KM_KEY_ID_SIZE) {
                ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
-                       + std::to_string(key.size()) + ")");
+                       + std::to_string(keyId.size()) + ")");
        }
 
-       KM_BufferSizeDesc bufSize;
+       TZSerializer sIn;
+       if (algo == ALGO_RSA)
+               sIn = makeSerializer(data, pwd, keyId);
+       else
+               sIn = makeSerializer(data, pwd, iv, keyId);
 
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.input_size = static_cast<uint32_t>(data.size());
-       bufSize.with_pwd_data = true;
-       bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
-       bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
-       bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
-       bufSize.iv_size = static_cast<uint32_t>(iv.size());
-       bufSize.key_id_size = static_cast<uint32_t>(key.size());
-       uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
 
        // decrypt operation does not require padding
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.out_size = static_cast<uint32_t>((cmd == CMD_ENCRYPT) ?
-                                                       data.size() + CIPHER_EXTRA_PADDING_SIZE :
-                                                       data.size());
-       uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
-
-       KM_SymmetricInput* input = nullptr;
-       int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
-       }
-
-       ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
-       }
-
-       uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
-       ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
-                                                                       pwd.getIV().data(), pwd.getIV().size(),
-                                                                       pwd.getTag().data(), pwd.getTag().size(),
-                                                                       Params::DERIVED_KEY_LENGTH_BITS,
-                                                                       Params::DERIVED_KEY_ITERATIONS,
-                                                                       pwdTagSizeBits);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
-       }
-
-       ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
+       uint32_t outMemorySize = data.size();
+       if (cmd == CMD_ENCRYPT) {
+               if (algo == ALGO_RSA) {
+                       // We don't know the key length
+                       outMemorySize = MAX_KEY_SIZE.at(ALGO_RSA);
+               } else {
+                       outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
+               }
        }
 
-       ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
-       }
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(outMemorySize, false));
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_MEMREF_WHOLE, TEEC_NONE);
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
        op.params[0].value.a = algo;
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
-       op.params[2].memref.parent = outMemory.Get();
-       op.params[2].memref.offset = 0;
-       op.params[2].memref.size = outMemory.Get()->size;
-       Execute(cmd, &op);
-
-       KM_SymmetricInput* output = nullptr;
-       ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
-       }
 
-       KM_OutData* outData = nullptr;
-       ret = KM_ParamsDeserializeOutData(output, &outData);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
-       }
+       Execute(cmd, &op);
 
-       // data_size should contain how much memory we actually took for our cipher operation
-       out.resize(outData->data_size);
-       memcpy(out.data(), outData->data, outData->data_size);
+       sOut.Deserialize(outMemory);
+       sOut.Pull(out);
 }
 
-void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
+void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
                                                                                const Pwd &pwd,
                                                                                const RawBuffer &iv,
                                                                                int tagSizeBits,
@@ -372,271 +423,228 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
                                                                                RawBuffer &tag)
 {
        // command ID = CMD_ENCRYPT (from km_ta_defines.h)
-       //
-       // TEEC_Operation layout:
-       // params:
-       //   [0].value.a - keyid
-       //   [0].value.b - algo
-       //   [1].memref - input data (serialized key/input/iv/aad)
-       // returned:
-       //   [0].value.a - return code
-       //   [2].memref - output
-
-       if (key.size() != KM_KEY_ID_SIZE) {
+       if (keyId.size() != KM_KEY_ID_SIZE) {
                ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
        }
 
-       uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
-       KM_BufferSizeDesc bufSize;
-
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.input_size = static_cast<uint32_t>(data.size());
-       bufSize.with_pwd_data = true;
-       bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
-       bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
-       bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
-       bufSize.iv_size = static_cast<uint32_t>(iv.size());
-       bufSize.key_id_size = static_cast<uint32_t>(key.size());
-       bufSize.with_ae_data = true;
-       bufSize.aad_size = static_cast<uint32_t>(aad.size());
-       uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
-
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
-       bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
-       uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
-
-       KM_SymmetricInput* input = nullptr;
-       int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
-       }
-
-       ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
-       }
-
-       uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
-       ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
-                                                                       pwd.getIV().data(), pwd.getIV().size(),
-                                                                       pwd.getTag().data(), pwd.getTag().size(),
-                                                                       Params::DERIVED_KEY_LENGTH_BITS,
-                                                                       Params::DERIVED_KEY_ITERATIONS,
-                                                                       pwdTagSizeBits);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
-       }
-
-       ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
-       }
+       auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
 
-       ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
-       }
+       uint32_t outMemorySize = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
+       uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
 
-       ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
-       }
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(outMemorySize, false));
+       sOut.Push(new TZSerializableBinary(tagSizeBytes));
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_MEMREF_WHOLE, TEEC_NONE);
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
        op.params[0].value.a = ALGO_AES_GCM;
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
-       op.params[2].memref.parent = outMemory.Get();
-       op.params[2].memref.offset = 0;
-       op.params[2].memref.size = outMemory.Get()->size;
-       Execute(CMD_ENCRYPT, &op);
 
-       KM_SymmetricInput* output = nullptr;
-       ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
-       }
-
-       KM_OutData* outData = nullptr;
-       ret = KM_ParamsDeserializeOutData(output, &outData);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
-       }
-
-       KM_TagData* tagData = nullptr;
-       ret = KM_ParamsDeserializeTagData(output, &tagData);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
-       }
-
-       out.resize(outData->data_size);
-       memcpy(out.data(), outData->data, outData->data_size);
+       Execute(CMD_ENCRYPT, &op);
 
-       if (tagData->data_size) {
-               tag.resize(tagData->data_size);
-               memcpy(tag.data(), tagData->data, tagData->data_size);
-       }
+       sOut.Deserialize(outMemory);
+       sOut.Pull(out);
+       sOut.Pull(tag);
 }
 
-void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
+void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
                                                                                const Pwd &pwd,
                                                                                const RawBuffer &iv,
-                                                                               int tagSizeBits,
+                                                                               int  tagSizeBits,
                                                                                const RawBuffer &tag,
                                                                                const RawBuffer &aad,
                                                                                const RawBuffer &data,
                                                                                RawBuffer &out)
 {
        // command ID = CMD_DECRYPT (from km_ta_defines.h)
-       //
-       // TEEC_Operation layout:
-       // params:
-       //   [0].value.a - keyid
-       //   [0].value.b - algo
-       //   [1].memref - input data (serialized key/input/iv/tag/aad)
-       // returned:
-       //   [0].value.a - output size
-       //   [2].memref - output (decrypted data)
-
-       if (key.size() != KM_KEY_ID_SIZE) {
+       if (keyId.size() != KM_KEY_ID_SIZE) {
                ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
        }
 
-       KM_BufferSizeDesc bufSize;
-
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.input_size = static_cast<uint32_t>(data.size());
-       bufSize.with_pwd_data = true;
-       bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
-       bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
-       bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
-       bufSize.iv_size = static_cast<uint32_t>(iv.size());
-       bufSize.key_id_size = static_cast<uint32_t>(key.size());
-       bufSize.with_ae_data = true;
-       bufSize.aad_size = static_cast<uint32_t>(aad.size());
-       bufSize.tag_size = static_cast<uint32_t>(tag.size());
-       uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
-
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.out_size = static_cast<uint32_t>(data.size());
-       uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
-
-       KM_SymmetricInput* input = nullptr;
-       int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ crypto operations");
-       }
+       auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits, tag);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
 
-       ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto operation: ", ret);
-       }
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(data.size()));
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
 
-       uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
-       ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
-                                                                       pwd.getIV().data(), pwd.getIV().size(),
-                                                                       pwd.getTag().data(), pwd.getTag().size(),
-                                                                       Params::DERIVED_KEY_LENGTH_BITS,
-                                                                       Params::DERIVED_KEY_ITERATIONS,
-                                                                       pwdTagSizeBits);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto operation: ", ret);
-       }
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+       op.params[0].value.a = ALGO_AES_GCM;
 
-       ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
-       }
+       Execute(CMD_DECRYPT, &op);
 
-       ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
-       }
+       sOut.Deserialize(outMemory);
+       sOut.Pull(out);
+}
 
-       ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
+uint32_t TrustZoneContext::initGcmCipher(uint32_t encrypt,
+                                                                                const RawBuffer &keyId,
+                                                                                const Pwd &pwd,
+                                                                                const RawBuffer &iv,
+                                                                                int tagSizeBits,
+                                                                                const RawBuffer &aad)
+{
+       // command ID = CMD_CIPHER_INIT (from km_ta_defines.h)
+       if (keyId.size() != KM_KEY_ID_SIZE) {
+               ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
        }
 
-       ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto operation: ", ret);
-       }
+       auto sIn = makeSerializer(pwd, iv, keyId, aad, tagSizeBits);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_MEMREF_WHOLE, TEEC_NONE);
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
        op.params[0].value.a = ALGO_AES_GCM;
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
-       op.params[2].memref.parent = outMemory.Get();
-       op.params[2].memref.offset = 0;
-       op.params[2].memref.size = outMemory.Get()->size;
-       Execute(CMD_DECRYPT, &op);
+       op.params[0].value.b = encrypt;
 
-       KM_SymmetricInput* output = nullptr;
-       ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
-       }
+       Execute(CMD_CIPHER_INIT, &op);
 
-       KM_OutData* outData = nullptr;
-       ret = KM_ParamsDeserializeOutData(output, &outData);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
-       }
+       return op.params[0].value.b;
+}
 
-       out.resize(outData->data_size);
-       memcpy(out.data(), outData->data, outData->data_size);
+void TrustZoneContext::addGcmAAD(uint32_t opId,
+                                                                const RawBuffer &aad)
+{
+       // command ID = CMD_CIPHER_INIT_AAD (from km_ta_defines.h)
+       auto sIn = makeSerializer(aad);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
+       op.params[0].value.a = opId;
+
+       Execute(CMD_CIPHER_INIT_AAD, &op);
 }
 
-void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
+RawBuffer TrustZoneContext::updateGcmCipher(uint32_t opId,
+                                                                                       const RawBuffer &data)
 {
-       // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
-       //
-       // TEEC_Operation layout:
-       // input params:
-       //   [1].memref - input data (serialized key ID)
-       // output params:
-       //   [0].value.a - return code
+       auto sIn = makeSerializer(data);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(data.size()));
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+       op.params[0].value.a = opId;
+
+       Execute(CMD_CIPHER_UPDATE, &op);
+
+       sOut.Deserialize(outMemory);
+
+       RawBuffer out;
+       sOut.Pull(out);
+       return out;
+}
 
+RawBuffer TrustZoneContext::finalizeGcmCipher(uint32_t opId,
+                                                                                         const RawBuffer &data)
+{
+       auto sIn = makeSerializer(data);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(MAX_GCM_TAG_SIZE, false));
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+       op.params[0].value.a = opId;
+
+       Execute(CMD_CIPHER_FINALIZE, &op);
+
+       sOut.Deserialize(outMemory);
+
+       RawBuffer out;
+       sOut.Pull(out);
+       return out;
+}
+
+void TrustZoneContext::executeSign(tz_algo_type algo,
+                                                               tz_hash_type hash,
+                                                               const RawBuffer &keyId,
+                                                               const Pwd &pwd,
+                                                               const RawBuffer &message,
+                                                               RawBuffer &signature)
+{
+       // command ID = CMD_SIGN (from km_ta_defines.h)
        if (keyId.size() != KM_KEY_ID_SIZE) {
-               ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
+               ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
+                       + std::to_string(keyId.size()) + ")");
        }
 
-       KM_BufferSizeDesc bufSize;
+       auto sIn = makeSerializer(message, pwd, keyId);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), false));
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+       op.params[0].value.a = algo;
+       op.params[0].value.b = hash;
+
+       Execute(CMD_SIGN, &op);
 
-       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
-       bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
-       uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
-       TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+       sOut.Deserialize(outMemory);
+       sOut.Pull(signature);
+}
 
-       KM_SymmetricInput* input = nullptr;
-       int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization: ", ret);
+int TrustZoneContext::executeVerify(tz_algo_type algo,
+                                                                       tz_hash_type hash,
+                                                                       const RawBuffer &keyId,
+                                                                       const Pwd &pwd,
+                                                                       const RawBuffer &message,
+                                                                       const RawBuffer &signature)
+{
+       // command ID = CMD_VERIFY (from km_ta_defines.h)
+       if (keyId.size() != KM_KEY_ID_SIZE) {
+               ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
+                       + std::to_string(keyId.size()) + ")");
        }
 
-       ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
-       if (ret) {
-               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
+       auto sIn = makeSerializer(message, signature, pwd, keyId);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
+       op.params[0].value.a = algo;
+       op.params[0].value.b = hash;
+
+       Execute(CMD_VERIFY, &op);
+
+       int opRet = op.params[0].value.a;
+       switch (opRet) {
+       case KM_TA_SUCCESS:
+               return CKM_API_SUCCESS;
+       case KM_TA_ERROR_SIGNATURE:
+               LogWarning("Signature verification failed");
+               return CKM_API_ERROR_VERIFICATION_FAILED;
+       default:
+               assert(false); // This condition should be checked inside Execute() function
+               ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
        }
+}
+
+void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
+{
+       // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
+       if (keyId.size() != KM_KEY_ID_SIZE) {
+               ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
+       }
+
+       auto sIn = makeSerializer(keyId);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_NONE, TEEC_NONE);
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
        Execute(CMD_DESTROY_KEY, &op);
 }
 
@@ -647,96 +655,148 @@ void TrustZoneContext::importData(
                                const RawBuffer &pwd,
                                const RawBuffer &iv,
                                const uint32_t keySizeBits,
-                               const uint32_t pwdTagSizeBits,
-                               RawBuffer &dataId,
-                               RawBuffer &pwdTag)
+                               RawBuffer &pwdTag,
+                               const RawBuffer &hash)
 {
        // command ID = CMD_IMPORT_DATA
-       // input:
-       //    [1].memref  - reference to serialized buffer:
-       //        uint32_t dataType contains information about type stored as binary data
-       //        KM_BinaryData with binary data
-       //        uint32_t binary/key size in bits
-       //        KM_BinaryData IV for data decryption with built in key
-       //        KM_BinaryData TAG for data decryption with built in key
-       //        uint32_t boolean value - true if password is provided
-       //        KM_PwdData with password (optional)
-       // Output:
-       //    [0].value.a - return code
-       //    [2].memref  - reference to serialized buffer:
-       //        KM_BinaryData with data id
-       //        KM_BinaryData with tag id (optional, if password was provided)
+       LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
 
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableFlag(dataType));
-       sIn.Push(new TZSerializableBinary(data));
-       sIn.Push(new TZSerializableFlag(keySizeBits));
-       sIn.Push(new TZSerializableBinary(encData.iv));
-       sIn.Push(new TZSerializableBinary(encData.tag));
-
-       uint32_t pwd_flag = pwd.empty() ? 0 : 1;
-       sIn.Push(new TZSerializableFlag(pwd_flag));
-       if (pwd_flag)
-               sIn.Push(new TZSerializablePwdData(pwd, iv, pwdTagSizeBits));
+       auto sIn = makeSerializer(
+               dataType, data, keySizeBits, encData.iv, encData.tag, EncPwd{pwd, iv}, hash);
 
        TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
        sIn.Serialize(inMemory);
 
-
        TZSerializer sOut;
-       sOut.Push(new TZSerializableBinary(KM_DATA_ID_SIZE));
-       if (pwd_flag) {
-               sOut.Push(new TZSerializableBinary(pwdTagSizeBits / 8));
+       if (!pwd.empty()) {
+               sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
        }
 
        TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_MEMREF_WHOLE, TEEC_NONE);
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
-       op.params[2].memref.parent = outMemory.Get();
-       op.params[2].memref.offset = 0;
-       op.params[2].memref.size = outMemory.Get()->size;
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
+       if (!pwd.empty())
+               op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
 
        Execute(CMD_IMPORT_DATA, &op);
 
-       sOut.Deserialize(outMemory);
-       sOut.Pull(dataId);
-       if (pwd_flag) {
+       if (!pwd.empty()) {
+               sOut.Deserialize(outMemory);
                sOut.Pull(pwdTag);
        }
 
-       LogDebug("Imported object ID is (hex): " << rawToHexString(dataId));
+       LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
+}
+
+void TrustZoneContext::importWrappedKey(const RawBuffer &wrappingKeyId,
+                                                                               const Pwd &wrappingKeyPwd,
+                                                                               tz_algo_type algo,
+                                                                               const RawBuffer &iv,
+                                                                               const uint32_t ctrLenOrTagSizeBits,
+                                                                               const RawBuffer &aad,
+                                                                               const tz_data_type encryptedKeyType,
+                                                                               const RawBuffer &encryptedKey,
+                                                                               const RawBuffer &encryptedKeyPwdBuf,
+                                                                               const RawBuffer &encryptedKeyIV,
+                                                                               RawBuffer &encryptedKeyTag,
+                                                                               const RawBuffer &encryptedKeyId)
+{
+       // command ID = CMD_IMPORT_WRAPPED_KEY
+       LogDebug("TrustZoneContext::importWrappedKey encryptedKey size = [" << encryptedKey.size() << "]");
+
+       auto sIn = makeSerializer(wrappingKeyId,
+                                                         wrappingKeyPwd,
+                                                         algo,
+                                                         iv,
+                                                         ctrLenOrTagSizeBits,
+                                                         aad,
+                                                         encryptedKeyType,
+                                                         encryptedKey,
+                                                         EncPwd{encryptedKeyPwdBuf, encryptedKeyIV},
+                                                         encryptedKeyId);
+
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TZSerializer sOut;
+       if (!encryptedKeyPwdBuf.empty()) {
+               sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+       }
+
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
+       if (!encryptedKeyPwdBuf.empty())
+               op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+
+       Execute(CMD_IMPORT_WRAPPED_KEY, &op);
+
+       if (!encryptedKeyPwdBuf.empty()) {
+               sOut.Deserialize(outMemory);
+               sOut.Pull(encryptedKeyTag);
+       }
+
+       LogDebug("Imported object ID is (hex): " << rawToHexString(encryptedKeyId));
+}
+
+RawBuffer TrustZoneContext::exportWrappedKey(const RawBuffer &wrappingKeyId,
+                                                                                        const Pwd &wrappingKeyPwd,
+                                                                                        tz_algo_type algo,
+                                                                                        const RawBuffer &iv,
+                                                                                        const uint32_t ctrLenOrTagSizeBits,
+                                                                                        const RawBuffer &aad,
+                                                                                        const RawBuffer &keyToWrapId,
+                                                                                        const Pwd &keyToWrapPwd)
+{
+       // command ID = CMD_EXPORT_WRAPPED_KEY
+       LogDebug("TrustZoneContext::exportWrappedKey");
+
+       auto sIn = makeSerializer(wrappingKeyId,
+                                                         wrappingKeyPwd,
+                                                         algo,
+                                                         iv,
+                                                         ctrLenOrTagSizeBits,
+                                                         aad,
+                                                         keyToWrapId,
+                                                         keyToWrapPwd);
+
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       uint32_t data_size = 0;
+       GetDataSize(keyToWrapId, data_size);
+
+       LogDebug("GetData data_size = [" << data_size << "]");
+
+       // encrypted data may be longer
+       TZSerializer sOut;
+       sOut.Push(new TZSerializableBinary(data_size + KM_ENCRYPTION_OVERHEAD));
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+       sOut.Serialize(outMemory);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+
+       Execute(CMD_EXPORT_WRAPPED_KEY, &op);
+
+       sOut.Deserialize(outMemory);
+
+       RawBuffer wrappedKey;
+       sOut.Pull(wrappedKey);
+
+       return wrappedKey;
 }
 
 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
 {
        // command ID = CMD_GET_DATA_SIZE
-       // TA will decrypt data with password if provided
-       // Parameters:
-       //    [1].memref  - reference to serialized buffer:
-       //        KM_BinaryData with object ID
-       // Output:
-       //    [0].value.a - return code
-       //    [0].value.b - size of buffer to be passed from CA
        LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId));
 
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(dataId));
-
+       auto sIn = makeSerializer(dataId);
        TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
        sIn.Serialize(inMemory);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_NONE, TEEC_NONE);
+       TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
 
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
        Execute(CMD_GET_DATA_SIZE, &op);
        dataSize = op.params[0].value.b;
 }
@@ -746,51 +806,23 @@ void TrustZoneContext::getData(const RawBuffer &dataId,
                         RawBuffer &data)
 {
        // command ID = CMD_GET_DATA
-       // TA will decrypt data with password if provided
-       // Parameters:
-       //    [1].memref  - reference to serialized buffer:
-       //        KM_BinaryData with object ID
-       //        uint32_t boolean value - true if password is provided
-       //        KM_PwdData with password (optional)
-       // Output:
-       //    [0].value.a - return code
-       //    [2].memref  - reference to serialized buffer:
-       //        KM_BinaryData with binary data
        LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
 
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(dataId));
-
-       uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1;
-       sIn.Push(new TZSerializableFlag(pwd_flag));
-
-       if (pwd_flag) {
-               sIn.Push(new TZSerializablePwdData(pwd.getPassword(),
-                                                 pwd.getIV(),
-                                                 Params::DEFAULT_AES_GCM_TAG_LEN_BITS,
-                                                 pwd.getTag()));
-       }
-
+       auto sIn = makeSerializer(dataId, pwd);
        TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
        sIn.Serialize(inMemory);
 
        uint32_t data_size = 0;
        GetDataSize(dataId, data_size);
 
+       LogDebug("GetData data_size = [" << data_size << "]");
+
        TZSerializer sOut;
        sOut.Push(new TZSerializableBinary(data_size));
        TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
        sOut.Serialize(outMemory);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_MEMREF_WHOLE, TEEC_NONE);
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
-       op.params[2].memref.parent = outMemory.Get();
-       op.params[2].memref.offset = 0;
-       op.params[2].memref.size = outMemory.Get()->size;
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
 
        Execute(CMD_GET_DATA, &op);
 
@@ -802,29 +834,118 @@ void TrustZoneContext::getData(const RawBuffer &dataId,
 void TrustZoneContext::destroyData(const RawBuffer &dataId)
 {
        //      command ID = CMD_DESTROY_DATA
-       //  TEEC_Operation parameters layout:
-       //      input:
-       //     [1].memref  - reference to serialized buffer:
-       //         KM_BinaryData with object ID
-       //  output:
-       //     [0].value.a - return code
        LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId));
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(dataId));
-
+       auto sIn = makeSerializer(dataId);
        TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
        sIn.Serialize(inMemory);
 
-       TEEC_Operation op;
-       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
-                                                                       TEEC_NONE, TEEC_NONE);
+       TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
 
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
        Execute(CMD_DESTROY_DATA, &op);
 }
 
+TZSerializablePwdData* makeSerializablePwd(const Pwd &pwd)
+{
+       auto &tag = pwd.getTag();
+       return new TZSerializablePwdData(pwd.getPassword(), pwd.getIV(), tag.size() * 8, tag);
+}
+
+void TrustZoneContext::executeEcdh(const RawBuffer &prvKeyId,
+                                                                  const Pwd &prvKeyPwd,
+                                                                  const RawBuffer &pubX,
+                                                                  const RawBuffer &pubY,
+                                                                  const RawBuffer &secretPwdBuf,
+                                                                  const RawBuffer &secretPwdIV,
+                                                                  RawBuffer &secretTag,
+                                                                  const RawBuffer &secretHash)
+{
+       // command ID = CMD_DERIVE
+       LogDebug("TrustZoneContext::executeEcdh");
+
+       auto sIn = makeSerializer(
+               prvKeyId, prvKeyPwd, pubX, pubY, EncPwd{secretPwdBuf, secretPwdIV}, secretHash);
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TZSerializer sOut;
+       if (!secretPwdBuf.empty()) {
+               sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+       }
+
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
+       if (!secretPwdBuf.empty())
+               op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+       op.params[0].value.a = ALGO_ECDH_DRV;
+
+       Execute(CMD_DERIVE, &op);
+
+       if (!secretPwdBuf.empty()) {
+               sOut.Deserialize(outMemory);
+               sOut.Pull(secretTag);
+       }
+
+       LogDebug("Derived object ID is (hex): " << rawToHexString(secretHash));
+}
+
+void TrustZoneContext::executeKbkdf(const RawBuffer& secretId,
+                                                                       const Pwd& secretPwd,
+                                                                       const RawBuffer& label,
+                                                                       const RawBuffer& context,
+                                                                       const RawBuffer& fixed,
+                                                                       tz_prf prf,
+                                                                       tz_kbkdf_mode mode,
+                                                                       tz_kbkdf_ctr_loc location,
+                                                                       size_t rlen,
+                                                                       size_t llen,
+                                                                       bool noSeparator,
+                                                                       const RawBuffer &keyPwdBuf,
+                                                                       const RawBuffer &keyPwdIV,
+                                                                       RawBuffer &keyTag,
+                                                                       const RawBuffer &keyHash)
+{
+       // command ID = CMD_DERIVE
+       LogDebug("TrustZoneContext::executeKbkdf");
+
+       auto sIn = makeSerializer(secretId,
+                                                         secretPwd,
+                                                         label,
+                                                         context,
+                                                         fixed,
+                                                         prf,
+                                                         mode,
+                                                         location,
+                                                         rlen,
+                                                         llen,
+                                                         noSeparator,
+                                                         EncPwd{keyPwdBuf, keyPwdIV}, keyHash);
+
+       TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+       sIn.Serialize(inMemory);
+
+       TZSerializer sOut;
+       if (!keyPwdBuf.empty()) {
+               sOut.Push(new TZSerializableBinary(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES));
+       }
+
+       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+
+       TEEC_Operation op = makeOp(TEEC_VALUE_INOUT, inMemory);
+       if (!keyPwdBuf.empty())
+               op = makeOp(TEEC_VALUE_INOUT, inMemory, outMemory);
+       op.params[0].value.a = ALGO_KBKDF_DRV;
+
+       Execute(CMD_DERIVE, &op);
+
+       if (!keyPwdBuf.empty()) {
+               sOut.Deserialize(outMemory);
+               sOut.Pull(keyTag);
+       }
+
+       LogDebug("Derived object ID is (hex): " << rawToHexString(keyHash));
+}
+
 void TrustZoneContext::Initialize()
 {
        TEEC_Operation op;
@@ -888,14 +1009,15 @@ void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
        }
 
        int ta_ret = op->params[0].value.a;
-       if (ta_ret != KM_TA_SUCCESS) {
-               switch (ta_ret) {
-               case KM_TA_ERROR_AUTH_FAILED:
-                       // Authentication cipher failed - notify with proper exception
-                       ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
-               default:
-                       ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
-               }
+       switch (ta_ret) {
+       case KM_TA_SUCCESS:
+       case KM_TA_ERROR_SIGNATURE:
+               break;
+       case KM_TA_ERROR_AUTH_FAILED:
+               // Authentication cipher failed - notify with proper exception
+               ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
+       default:
+               ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
        }
 }