Fix secret pwd passing in TZ backend KBKDF
[platform/core/security/key-manager.git] / src / manager / crypto / tz-backend / tz-context.cpp
index b2e55db..ad09c65 100644 (file)
@@ -50,6 +50,9 @@ 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;
 
@@ -66,9 +69,65 @@ static std::string rawToHexString(const RawBuffer &raw)
 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_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));
+}
+
+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...);
+}
+
+template <typename ...Args>
+TZSerializer makeSerializer(const Args&... args)
+{
+       TZSerializer ser;
+       push<Args...>(ser, args...);
+       return ser;
+}
+
 } // anonymous namespace
 
 TrustZoneContext::TrustZoneContext()
@@ -89,6 +148,31 @@ 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
@@ -97,12 +181,8 @@ void TrustZoneContext::generateIV(RawBuffer& 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);
@@ -111,129 +191,95 @@ 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
-       TZSerializer sOut;
-       sOut.Push(new TZSerializableBinary(KM_KEY_ID_SIZE));
-
-       TrustZoneMemory outMemory(m_Context, sOut.GetSize(), 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 = outMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = outMemory.Get()->size;
-       Execute(CMD_GENERATE_KEY, &op);
 
-       sOut.Deserialize(outMemory);
-       sOut.Pull(keyId);
+       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
        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);
 
        TZSerializer sOut;
-       sOut.Push(new TZSerializableBinary(KM_KEY_ID_SIZE));
        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 = outMemory.Get();
-       op.params[2].memref.offset = 0;
-       op.params[2].memref.size = outMemory.Get()->size;
+
        Execute(CMD_GENERATE_KEY_PWD, &op);
 
        sOut.Deserialize(outMemory);
-       sOut.Pull(keyId);
        sOut.Pull(pwdTag);
+
+       if (pwdTag.size() != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
+               ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
+       }
 }
 
 void TrustZoneContext::GenerateAKey(tz_command commandId,
                                     TZSerializer &sIn,
-                                    uint32_t keySizeBits,
+                                    uint32_t genParam, // key size in bits or EC type
                                     const RawBuffer &pubPwd,
                                     const RawBuffer &pubPwdIv,
                                     const RawBuffer &privPwd,
                                     const RawBuffer &privPwdIv,
-                                    RawBuffer &pubKeyId,
                                     RawBuffer &pubKeyTag,
-                                    RawBuffer &privKeyId,
-                                    RawBuffer &privKeyTag)
+                                    RawBuffer &privKeyTag,
+                                    const RawBuffer &hashPriv,
+                                                                       const RawBuffer &hashPub)
 {
        uint32_t pubTagSize = 0;
        uint32_t privTagSize = 0;
-
        uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1;
-       sIn.Push(new TZSerializableFlag(pubPwdExists));
        if (pubPwdExists) {
-               sIn.Push(new TZSerializablePwdData(pubPwd, pubPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
-               pubTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3;
+               pubTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
        }
        uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
-       sIn.Push(new TZSerializableFlag(privPwdExists));
        if (privPwdExists) {
-               sIn.Push(new TZSerializablePwdData(privPwd, privPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
-               privTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3;
+               privTagSize = Params::DEFAULT_AES_GCM_TAG_LEN_BYTES;
        }
 
+       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(KM_KEY_ID_SIZE));
-       if (pubTagSize) {
-               sOut.Push(new TZSerializableBinary(pubTagSize));
-       }
-       sOut.Push(new TZSerializableBinary(KM_KEY_ID_SIZE));
-       if (privTagSize) {
-               sOut.Push(new TZSerializableBinary(privTagSize));
-       }
+       sOut.Push(new TZSerializableBinary(pubTagSize));
+       sOut.Push(new TZSerializableBinary(privTagSize));
 
        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[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 = 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);
+       op.params[0].value.b = genParam;
+
        Execute(commandId, &op);
 
        sOut.Deserialize(outMemory);
-
-       sOut.Pull(pubKeyId);
-
        if (pubPwdExists) {
                sOut.Pull(pubKeyTag);
        }
 
-       sOut.Pull(privKeyId);
-
        if (privPwdExists) {
                sOut.Pull(privKeyTag);
        }
@@ -244,10 +290,10 @@ void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
                                                                        const RawBuffer &pubPwdIv,
                                                                        const RawBuffer &privPwd,
                                                                        const RawBuffer &privPwdIv,
-                                                                       RawBuffer &pubKeyId,
                                                                        RawBuffer &pubKeyTag,
-                                                                       RawBuffer &privKeyId,
-                                                                       RawBuffer &privKeyTag)
+                                                                       RawBuffer &privKeyTag,
+                                                                       const RawBuffer &hashPriv,
+                                                                       const RawBuffer &hashPub)
 {
        // command ID = CMD_GENERATE_RSA_KEYPAIR
        TZSerializer sIn;
@@ -259,10 +305,10 @@ void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
                     pubPwdIv,
                     privPwd,
                     privPwdIv,
-                    pubKeyId,
                     pubKeyTag,
-                    privKeyId,
-                    privKeyTag);
+                    privKeyTag,
+                    hashPriv,
+                    hashPub);
 }
 
 void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
@@ -273,16 +319,13 @@ void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
                                                                        const RawBuffer &pubPwdIv,
                                                                        const RawBuffer &privPwd,
                                                                        const RawBuffer &privPwdIv,
-                                                                       RawBuffer &pubKeyId,
                                                                        RawBuffer &pubKeyTag,
-                                                                       RawBuffer &privKeyId,
-                                                                       RawBuffer &privKeyTag)
+                                                                       RawBuffer &privKeyTag,
+                                                                       const RawBuffer &hashPriv,
+                                                                       const RawBuffer &hashPub)
 {
        // command ID = CMD_GENERATE_DSA_KEYPAIR
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(prime));
-       sIn.Push(new TZSerializableBinary(subprime));
-       sIn.Push(new TZSerializableBinary(base));
+       auto sIn = makeSerializer(prime, subprime, base);
 
        GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
                     sIn,
@@ -291,10 +334,36 @@ void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
                     pubPwdIv,
                     privPwd,
                     privPwdIv,
-                    pubKeyId,
                     pubKeyTag,
-                    privKeyId,
-                    privKeyTag);
+                    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,
@@ -312,17 +381,10 @@ void TrustZoneContext::executeCrypt(tz_command cmd,
        }
 
        TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(data));
-       int32_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(),
-                                                                          pwd.getTag().size() * 8,
-                                                                          pwd.getTag()));
-       if (algo != ALGO_RSA)
-               sIn.Push(new TZSerializableBinary(iv));
-       sIn.Push(new TZSerializableBinary(keyId));
+       if (algo == ALGO_RSA)
+               sIn = makeSerializer(data, pwd, keyId);
+       else
+               sIn = makeSerializer(data, pwd, iv, keyId);
 
        TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
        sIn.Serialize(inMemory);
@@ -342,16 +404,8 @@ void TrustZoneContext::executeCrypt(tz_command cmd,
        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);
 
@@ -373,20 +427,7 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
                ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
        }
 
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(data));
-       int32_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(),
-                                                                          pwd.getTag().size() * 8,
-                                                                          pwd.getTag()));
-       sIn.Push(new TZSerializableBinary(iv));
-       sIn.Push(new TZSerializableBinary(keyId));
-       sIn.Push(new TZSerializableBinary(aad));
-       sIn.Push(new TZSerializableFlag(tagSizeBits));
-
+       auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits);
        TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
        sIn.Serialize(inMemory);
 
@@ -398,16 +439,8 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
        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);
 
@@ -430,21 +463,7 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
                ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
        }
 
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(data));
-       int32_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(),
-                                                                          pwd.getTag().size() * 8,
-                                                                          pwd.getTag()));
-       sIn.Push(new TZSerializableBinary(iv));
-       sIn.Push(new TZSerializableBinary(keyId));
-       sIn.Push(new TZSerializableBinary(aad));
-       sIn.Push(new TZSerializableFlag(tagSizeBits));
-       sIn.Push(new TZSerializableBinary(tag));
-
+       auto sIn = makeSerializer(data, pwd, iv, keyId, aad, tagSizeBits, tag);
        TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
        sIn.Serialize(inMemory);
 
@@ -452,16 +471,8 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
        sOut.Push(new TZSerializableBinary(data.size()));
        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_DECRYPT, &op);
 
@@ -469,6 +480,91 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
        sOut.Pull(out);
 }
 
+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");
+       }
+
+       auto sIn = makeSerializer(pwd, iv, keyId, aad, tagSizeBits);
+       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_AES_GCM;
+       op.params[0].value.b = encrypt;
+
+       Execute(CMD_CIPHER_INIT, &op);
+
+       return op.params[0].value.b;
+}
+
+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);
+}
+
+RawBuffer TrustZoneContext::updateGcmCipher(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(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,
@@ -482,16 +578,7 @@ void TrustZoneContext::executeSign(tz_algo_type algo,
                        + std::to_string(keyId.size()) + ")");
        }
 
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(message));
-       int32_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(),
-                                                                          pwd.getTag().size() * 8,
-                                                                          pwd.getTag()));
-       sIn.Push(new TZSerializableBinary(keyId));
+       auto sIn = makeSerializer(message, pwd, keyId);
        TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
        sIn.Serialize(inMemory);
 
@@ -499,17 +586,10 @@ void TrustZoneContext::executeSign(tz_algo_type algo,
        sOut.Push(new TZSerializableBinary(MAX_KEY_SIZE.at(algo), 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[0].value.b = hash;
-       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_SIGN, &op);
 
        sOut.Deserialize(outMemory);
@@ -529,28 +609,14 @@ int TrustZoneContext::executeVerify(tz_algo_type algo,
                        + std::to_string(keyId.size()) + ")");
        }
 
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(message));
-       sIn.Push(new TZSerializableBinary(signature));
-       int32_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(),
-                                                                          pwd.getTag().size() * 8,
-                                                                          pwd.getTag()));
-       sIn.Push(new TZSerializableBinary(keyId));
+       auto sIn = makeSerializer(message, signature, pwd, keyId);
        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 = hash;
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
+
        Execute(CMD_VERIFY, &op);
 
        int opRet = op.params[0].value.a;
@@ -573,17 +639,12 @@ void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
                ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
        }
 
-       TZSerializer sIn;
-       sIn.Push(new TZSerializableBinary(keyId));
+       auto sIn = makeSerializer(keyId);
        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);
-       op.params[1].memref.parent = inMemory.Get();
-       op.params[1].memref.offset = 0;
-       op.params[1].memref.size = inMemory.Get()->size;
+       TEEC_Operation op = makeOp(TEEC_VALUE_OUTPUT, inMemory);
+
        Execute(CMD_DESTROY_KEY, &op);
 }
 
@@ -594,54 +655,135 @@ 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
-       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));
+       LogDebug("TrustZoneContext::importData data size = [" << data.size() << "]");
+
+       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)
@@ -649,19 +791,12 @@ void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
        // command ID = CMD_GET_DATA_SIZE
        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;
 }
@@ -673,39 +808,21 @@ void TrustZoneContext::getData(const RawBuffer &dataId,
        // command ID = CMD_GET_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);
 
@@ -718,22 +835,117 @@ void TrustZoneContext::destroyData(const RawBuffer &dataId)
 {
        //      command ID = CMD_DESTROY_DATA
        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;