tz-backend: Implement asymmetric operations 10/200310/9
authorLukasz Kostyra <l.kostyra@samsung.com>
Wed, 20 Feb 2019 11:27:33 +0000 (12:27 +0100)
committerTomasz Swierczek <t.swierczek@samsung.com>
Mon, 20 May 2019 09:07:31 +0000 (11:07 +0200)
Change-Id: Ie98b4e72addb257c2a8de1de57097fe077fff380

src/manager/common/data-type.cpp
src/manager/common/data-type.h
src/manager/crypto/platform/decider.cpp
src/manager/crypto/tz-backend/internals.cpp
src/manager/crypto/tz-backend/internals.h
src/manager/crypto/tz-backend/store.cpp
src/manager/crypto/tz-backend/tz-context.cpp
src/manager/crypto/tz-backend/tz-context.h

index 0bcf74f..8de9e15 100644 (file)
@@ -181,6 +181,11 @@ bool DataType::isBinaryData() const
        return m_dataType == BINARY_DATA;
 }
 
+bool DataType::isEllipticCurve() const
+{
+       return (m_dataType == KEY_ECDSA_PRIVATE) || (m_dataType == KEY_ECDSA_PUBLIC);
+}
+
 bool DataType::isInRange(int data)
 {
        if (data < static_cast<int>(DB_FIRST))
index 30829e1..014869f 100644 (file)
@@ -84,6 +84,7 @@ public:
        bool isKeyPublic() const;
        bool isCertificate() const;
        bool isBinaryData() const;
+       bool isEllipticCurve() const;
 
        static bool isInRange(int data);
        static DataType getChainDatatype(unsigned int index);
index e14e9b6..4ffe83a 100644 (file)
@@ -76,20 +76,30 @@ CryptoBackend chooseCryptoBackend(const DataParams& params)
                // TODO tz-backend could support the master key, but it would require
                //      hardcoding a known key ID and querying TA whether the key is
                //      reachable
-               if (params[0].encrypted)
+               if (params[0].encrypted) {
                        return CryptoBackend::OpenSSL;
+               }
 
                // tz-backend allows only for data binary export
-               if (params[0].policy.extractable && !params[0].data.isBinaryData())
+               if (params[0].policy.extractable && !params[0].data.isBinaryData()) {
                        return CryptoBackend::OpenSSL;
+               }
 
                // Use TrustZone only with symmetric keys or unencrypted binary
                // data until asymmetric cryptography is implemented
-               if (!params[0].data.isSKey() && !params[0].data.isBinaryData())
+               if (!params[0].data.isSKey() && !params[0].data.isBinaryData()) {
                        return CryptoBackend::OpenSSL;
+               }
        } else if (params.size() == 2) {
-               LogDebug("2 keys - asymmetric encryption not yet supported, selecting OpenSSL");
-               return CryptoBackend::OpenSSL;
+               // extractable private key can only be handled by OpenSSL
+               if (params[0].policy.extractable) {
+                       return CryptoBackend::OpenSSL;
+               }
+
+               // ECDSA algorithm is unsupported by GP API 1.0
+               if (params[0].data.isEllipticCurve() || params[1].data.isEllipticCurve()) {
+                       return CryptoBackend::OpenSSL;
+               }
        }
 
        try {
index 71038e0..7b7b9be 100644 (file)
 #include <generic-backend/algo-validation.h>
 #include <generic-backend/crypto-params.h>
 #include <dpl/log/log.h>
+#include <openssl/evp.h>
+#include <openssl/dsa.h>
+#include <openssl/bio.h>
+#include <openssl/bn.h>
 
 #include <tz-backend/internals.h>
 #include <tz-backend/tz-context.h>
+#include <openssl-error-handler.h>
 #include <km_ta_defines.h>
 
+#include <functional>
+
+namespace {
+
+using DSAPtr = std::unique_ptr<DSA, std::function<void(DSA*)>>;
+
+CKM::RawBuffer extractBignumData(BIGNUM* bn)
+{
+       size_t size = static_cast<size_t>(BN_num_bytes(bn));
+
+       CKM::RawBuffer result(size);
+       int ret = BN_bn2bin(bn, result.data());
+       if (ret != static_cast<int>(size)) {
+               ThrowErr(CKM::Exc::Crypto::InternalError,
+                       "Error while converting bignums - expected "
+                       + std::to_string(size) + " bytes of data, got " + std::to_string(ret));
+       }
+
+       return result;
+}
+
+void generateDSAParams(const int sizeBits, CKM::RawBuffer &prime,
+                                       CKM::RawBuffer &subprime, CKM::RawBuffer &base)
+{
+       DSAPtr dsa(DSA_new(), DSA_free);
+       if (!dsa) {
+               ThrowErr(CKM::Exc::Crypto::InternalError,
+                       "Failed to create DSA context for parameter gen");
+       }
+
+       if (DSA_generate_parameters_ex(dsa.get(), sizeBits, NULL, 0, NULL, NULL, NULL) == 0) {
+               ThrowErr(CKM::Exc::Crypto::InternalError,
+                       "Failed to generate DSA params, err = " + std::to_string(ERR_get_error()));
+       }
+
+       // at this stage dsa->p, dsa->q & dsa->r should contain our params
+       // extract them into buffers
+       prime = extractBignumData(dsa->p);
+       subprime = extractBignumData(dsa->q);
+       base = extractBignumData(dsa->g);
+}
+
+} // namespace
 
 namespace CKM {
 namespace Crypto {
 namespace TZ {
 namespace Internals {
 
-tz_algo_type getGenKeyType(AlgoType type)
+tz_algo_type getGenSKeyType(AlgoType type)
 {
        switch (type)
        {
@@ -52,6 +100,10 @@ tz_algo_type getAlgType(AlgoType type)
        case AlgoType::AES_CTR: return ALGO_AES_CTR;
        case AlgoType::AES_CFB: return ALGO_AES_CFB;
        case AlgoType::AES_GCM: return ALGO_AES_GCM;
+       case AlgoType::RSA_OAEP: return ALGO_RSA;
+       case AlgoType::RSA_SV: return ALGO_RSA_SV;
+       case AlgoType::DSA_SV: return ALGO_DSA_SV;
+       case AlgoType::ECDSA_SV: return ALGO_ECDSA_SV;
        default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
        };
 }
@@ -65,11 +117,30 @@ tz_algo_type getAlgType(KeyType keyType)
        case KeyType::KEY_RSA_PUBLIC:
        case KeyType::KEY_RSA_PRIVATE:
                return ALGO_RSA_GEN;
+       case KeyType::KEY_DSA_PUBLIC:
+       case KeyType::KEY_DSA_PRIVATE:
+               return ALGO_DSA_GEN;
+       case KeyType::KEY_ECDSA_PUBLIC:
+       case KeyType::KEY_ECDSA_PRIVATE:
+               return ALGO_ECDSA_GEN;
        default:
                ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
        };
 }
 
+tz_hash_type getHashType(HashAlgorithm hash)
+{
+       switch (hash)
+       {
+       case HashAlgorithm::SHA1: return HASH_SHA1;
+       case HashAlgorithm::SHA256: return HASH_SHA256;
+       case HashAlgorithm::SHA384: return HASH_SHA384;
+       case HashAlgorithm::SHA512: return HASH_SHA512;
+       default:
+               ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
+       }
+}
+
 RawBuffer generateIV()
 {
        RawBuffer result;
@@ -94,23 +165,84 @@ Data generateSKey(const CryptoAlgorithm &alg,
                }
 
                RawBuffer pwdBuf(pwd.begin(), pwd.end());
-               TrustZoneContext::Instance().generateSKeyPwd(getGenKeyType(keyType),
+               TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
                                                                                                        pwdBuf, iv, keyBits,
                                                                                                        keyData.data, tag);
        } else {
-               TrustZoneContext::Instance().generateSKey(getGenKeyType(keyType), keyBits,
+               TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
                                                                                                keyData.data);
        }
 
        return keyData;
 }
 
-DataPair generateAKey(const CryptoAlgorithm &,
-                                       const Password &,
-                                       const RawBuffer &)
+DataPair generateAKey(const CryptoAlgorithm &alg,
+                                       const Password &pubPwd,
+                                       const Password &privPwd,
+                                       const RawBuffer &pubPwdIv,
+                                       const RawBuffer &privPwdIv,
+                                       RawBuffer &pubTag,
+                                       RawBuffer &privTag)
 {
-       ThrowErr(Exc::Crypto::OperationNotSupported,
-                               "AKeys are not yet implemented in TrustZone backend");
+       AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+       int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
+
+       Data pubKeyData;
+       Data privKeyData;
+
+       RawBuffer pubPwdBuf;
+       if (!pubPwd.empty())
+               pubPwdBuf.assign(pubPwd.begin(), pubPwd.end());
+
+       RawBuffer privPwdBuf;
+       if (!privPwd.empty())
+               privPwdBuf.assign(privPwd.begin(), privPwd.end());
+
+       switch (keyType) {
+       case AlgoType::RSA_GEN: {
+               pubKeyData.type = DataType(KeyType::KEY_RSA_PUBLIC);
+               privKeyData.type = DataType(KeyType::KEY_RSA_PRIVATE);
+
+               TrustZoneContext::Instance().generateRSAKey(keyBits,
+                                                                                                       pubPwdBuf,
+                                                                                                       pubPwdIv,
+                                                                                                       privPwdBuf,
+                                                                                                       privPwdIv,
+                                                                                                       pubKeyData.data,
+                                                                                                       pubTag,
+                                                                                                       privKeyData.data,
+                                                                                                       privTag);
+               break;
+       }
+       case AlgoType::DSA_GEN: {
+               pubKeyData.type = DataType(KeyType::KEY_DSA_PUBLIC);
+               privKeyData.type = DataType(KeyType::KEY_DSA_PRIVATE);
+
+               RawBuffer prime;
+               RawBuffer subprime;
+               RawBuffer base;
+               generateDSAParams(keyBits, prime, subprime, base);
+               TrustZoneContext::Instance().generateDSAKey(keyBits,
+                                                                                                       prime,
+                                                                                                       subprime,
+                                                                                                       base,
+                                                                                                       pubPwdBuf,
+                                                                                                       pubPwdIv,
+                                                                                                       privPwdBuf,
+                                                                                                       privPwdIv,
+                                                                                                       pubKeyData.data,
+                                                                                                       pubTag,
+                                                                                                       privKeyData.data,
+                                                                                                       privTag);
+               break;
+       }
+       default: {
+               ThrowErr(Exc::Crypto::InputParam,
+                       "Invalid algo type provided for generateAKey function");
+       }
+       }
+
+       return DataPair(pubKeyData, privKeyData);
 }
 
 void destroyKey(const RawBuffer &key)
@@ -131,6 +263,10 @@ RawBuffer importData(const Data &data,
                dataType = TYPE_SKEY;
        } else if (data.type.isBinaryData()) {
                dataType = TYPE_GENERIC_SECRET;
+       } else if (data.type.isKeyPrivate()) {
+               dataType = TYPE_AKEY_PRIVATE;
+       } else if (data.type.isKeyPublic()) {
+               dataType = TYPE_AKEY_PUBLIC;
        } else {
                ThrowErr(Exc::Crypto::DataTypeNotSupported,
                        "Data type could not be impoted by tz-backend");
@@ -334,41 +470,93 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
                                "Incorrect algorithm provided for symmetric crypto operation");
 }
 
-RawBuffer asymmetricEncrypt(const RawBuffer &,
-                                                       const Pwd &,
-                                                       const CryptoAlgorithm &,
-                                                       const RawBuffer &)
+RawBuffer asymmetricEncrypt(const RawBuffer &key,
+                                                       const Pwd &pwd,
+                                                       const CryptoAlgorithm &alg,
+                                                       const RawBuffer &data)
 {
+       AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+       RawBuffer result;
+
+       switch (algo)
+       {
+       case AlgoType::RSA_OAEP: {
+               TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
+                                                                                               getAlgType(algo),
+                                                                                               key,
+                                                                                               pwd,
+                                                                                               unpack<RawBuffer>(alg, ParamName::ED_IV),
+                                                                                               data,
+                                                                                               result);
+               return result;
+       }
+       default:
+               break;
+       }
+
        ThrowErr(Exc::Crypto::OperationNotSupported,
-                               "Asymmetric encryption is not yet supported on TrustZone backend");
+                               "Incorrect algorithm provided for asymmetric crypto operation");
 }
 
-RawBuffer asymmetricDecrypt(const RawBuffer &,
-                                                       const Pwd &,
-                                                       const CryptoAlgorithm &,
-                                                       const RawBuffer &)
+RawBuffer asymmetricDecrypt(const RawBuffer &key,
+                                                       const Pwd &pwd,
+                                                       const CryptoAlgorithm &alg,
+                                                       const RawBuffer &cipher)
 {
+       AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+       RawBuffer result;
+
+       switch (algo)
+       {
+       case AlgoType::RSA_OAEP: {
+               TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
+                                                                                               getAlgType(algo),
+                                                                                               key,
+                                                                                               pwd,
+                                                                                               unpack<RawBuffer>(alg, ParamName::ED_IV),
+                                                                                               cipher,
+                                                                                               result);
+               return result;
+       }
+       default:
+               break;
+       }
+
        ThrowErr(Exc::Crypto::OperationNotSupported,
-                               "Asymmetric encryption is not yet supported on TrustZone backend");
+                               "Incorrect algorithm provided for asymmetric crypto operation");
 }
 
-RawBuffer sign(const RawBuffer &,
-                       const Pwd &,
-                       const CryptoAlgorithm &,
-                       const RawBuffer &)
+RawBuffer sign(const RawBuffer &pkey,
+                       const Pwd &pwd,
+                       const CryptoAlgorithm &alg,
+                       const RawBuffer &message)
 {
-       ThrowErr(Exc::Crypto::OperationNotSupported,
-                               "Certificate signing is not yet supported on TrustZone backend");
+       AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+       HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
+       RawBuffer signature;
+       TrustZoneContext::Instance().executeSign(getAlgType(algo),
+                                                                                       getHashType(hash),
+                                                                                       pkey,
+                                                                                       pwd,
+                                                                                       message,
+                                                                                       signature);
+       return signature;
 }
 
-int verify(const RawBuffer &,
-               const Pwd &,
-               const CryptoAlgorithm &,
-               const RawBuffer &,
-               const RawBuffer &)
+int verify(const RawBuffer &pkey,
+               const Pwd &pwd,
+               const CryptoAlgorithm &alg,
+               const RawBuffer &message,
+               const RawBuffer &signature)
 {
-       ThrowErr(Exc::Crypto::OperationNotSupported,
-                               "Certificate signing is not yet supported on TrustZone backend");
+       AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+       HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
+       return TrustZoneContext::Instance().executeVerify(getAlgType(algo),
+                                                                                                       getHashType(hash),
+                                                                                                       pkey,
+                                                                                                       pwd,
+                                                                                                       message,
+                                                                                                       signature);
 }
 
 } // namespace Internals
index 1c76f8d..b66351c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2017 - 2019 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.
@@ -40,8 +40,12 @@ using KeyIdPair = std::pair<int, RawBuffer>;
 RawBuffer generateIV();
 
 DataPair generateAKey(const CryptoAlgorithm &alg,
-                                       const Password &pwd,
-                                       const RawBuffer &iv);
+                                       const Password &pubPwd,
+                                       const Password &privPwd,
+                                       const RawBuffer &pubPwdIv,
+                                       const RawBuffer &privPwdIv,
+                                       RawBuffer &pubTag,
+                                       RawBuffer &privTag);
 
 Data generateSKey(const CryptoAlgorithm &alg,
                                const Password &pwd,
index 9549693..978a155 100644 (file)
@@ -113,12 +113,15 @@ GObjUPtr Store::getObject(const Token &token, const Password &pass)
                ThrowErr(Exc::Crypto::AuthenticationFailed,
                                 "This token is not protected with password but passed one");
        }
-       // TODO AKeys
+
+       if (token.dataType.isKeyPrivate() || token.dataType.isKeyPublic())
+               return make_unique<AKey>(scheme, id, Pwd(pass, iv, tag), token.dataType);
 
        if (token.dataType.isSKey())
                return make_unique<SKey>(scheme, id, Pwd(pass, iv, tag), token.dataType);
 
-       // TODO certificate/chaincert
+       if (token.dataType.isCertificate() || token.dataType.isChainCert())
+               return make_unique<Cert>(scheme, id, Pwd(pass, iv, tag), token.dataType);
 
        if (token.dataType.isBinaryData()) {
                RawBuffer exported_data = Internals::getData(id, Pwd(pass, iv, tag));
@@ -129,11 +132,24 @@ GObjUPtr Store::getObject(const Token &token, const Password &pass)
                         "This type of data is not supported by trustzone backend: ", (int)token.dataType);
 }
 
-TokenPair Store::generateAKey(const CryptoAlgorithm &, const Password &,
-                                                         const Password &)
+TokenPair Store::generateAKey(const CryptoAlgorithm &alg, const Password &privPass,
+                                                         const Password &pubPass)
 {
-       ThrowErr(Exc::Crypto::OperationNotSupported,
-                        "AKey operations are not implemented on TrustZone backend!");
+       RawBuffer pubIv, privIv;
+       RawBuffer pubTag, privTag;
+       if (!pubPass.empty()) {
+               pubIv = Internals::generateIV();
+       }
+       if (!privPass.empty()) {
+               privIv = Internals::generateIV();
+       }
+
+       Internals::DataPair ret = Internals::generateAKey(alg, pubPass, privPass, pubIv, privIv, pubTag, privTag);
+
+       return std::make_pair<Token, Token>(
+               Token(m_backendId, ret.second.type, pack(ret.second.data, privPass, privIv, privTag)),
+               Token(m_backendId, ret.first.type, pack(ret.first.data, pubPass, pubIv, pubTag))
+       );
 }
 
 Token Store::generateSKey(const CryptoAlgorithm &alg, const Password &pass)
@@ -151,7 +167,7 @@ Token Store::generateSKey(const CryptoAlgorithm &alg, const Password &pass)
 
 Token Store::import(const Data &data, const Password &pass, const EncryptionParams &e)
 {
-       if (!data.type.isBinaryData() && !data.type.isSKey())
+       if (!data.type.isBinaryData() && !data.type.isKey())
                ThrowErr(Exc::Crypto::DataTypeNotSupported, "Invalid data provided for import");
 
        RawBuffer passIV;
index f9b2f2b..0b54bb4 100644 (file)
@@ -21,7 +21,6 @@
 
 #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>
 
 #include <cstdint>
 #include <cstring>
+#include <cassert>
+#include <iomanip>
+#include <sstream>
+#include <unordered_map>
 
 namespace CKM {
 namespace Crypto {
@@ -65,6 +68,41 @@ static std::string rawToHexString(const RawBuffer &raw)
         return dump;
 }
 
+/*
+ * 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 }
+};
+
+void DeserializeKeyID(TrustZoneMemory &mem, RawBuffer &id)
+{
+       LogDebug("Deserializing key ID");
+
+       KM_SymmetricInput* output = nullptr;
+       int ret = KM_ParamsDeserializationInit(mem.Get()->buffer, mem.Get()->size, &output);
+       if (ret) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to initialize key ID data deserialization: ", ret);
+       }
+
+       KM_OutData* outData = nullptr;
+       ret = KM_ParamsDeserializeOutData(output, &outData);
+       if (ret) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key ID data: ", ret);
+       }
+
+       if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
+               ThrowErr(Exc::Crypto::InternalError, "Deserialized invalid key ID");
+       }
+
+       // data_size should contain how much memory we actually took for our cipher operation
+       id.resize(outData->data_size);
+       memcpy(id.data(), outData->data, outData->data_size);
+}
+
 } // anonymous namespace
 
 TrustZoneContext::TrustZoneContext()
@@ -144,24 +182,7 @@ void TrustZoneContext::generateSKey(tz_algo_type algo,
        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);
+       DeserializeKeyID(keyMemory, keyId);
 }
 
 void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
@@ -223,6 +244,8 @@ void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
        op.params[2].memref.size = keyMemory.Get()->size;
        Execute(CMD_GENERATE_KEY_PWD, &op);
 
+       DeserializeKeyID(keyMemory, keyId);
+
        KM_SymmetricInput* output = nullptr;
        ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
        if (ret) {
@@ -256,9 +279,174 @@ void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
        memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
 }
 
+void TrustZoneContext::GenerateAKey(tz_command commandId,
+                                    TZSerializer &sIn,
+                                    uint32_t keySizeBits,
+                                    const RawBuffer &pubPwd,
+                                    const RawBuffer &pubPwdIv,
+                                    const RawBuffer &privPwd,
+                                    const RawBuffer &privPwdIv,
+                                    RawBuffer &pubKeyId,
+                                    RawBuffer &pubKeyTag,
+                                    RawBuffer &privKeyId,
+                                    RawBuffer &privKeyTag)
+{
+       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;
+       }
+       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;
+       }
+
+       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(pubTagSize));
+       sOut.Push(new TZSerializableBinary(KM_KEY_ID_SIZE));
+       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;
+       Execute(commandId, &op);
+
+       sOut.Deserialize(outMemory);
+
+       sOut.Pull(pubKeyId);
+       if (pubKeyId.size() != KM_KEY_ID_SIZE) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize public key ID");
+       }
+
+       if (pubPwdExists) {
+               sOut.Pull(pubKeyTag);
+       }
+
+       sOut.Pull(privKeyId);
+       if (privKeyId.size() != KM_KEY_ID_SIZE) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize private key ID");
+       }
+
+       if (privPwdExists) {
+               sOut.Pull(privKeyTag);
+       }
+}
+
+void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
+                                                                       const RawBuffer &pubPwd,
+                                                                       const RawBuffer &pubPwdIv,
+                                                                       const RawBuffer &privPwd,
+                                                                       const RawBuffer &privPwdIv,
+                                                                       RawBuffer &pubKeyId,
+                                                                       RawBuffer &pubKeyTag,
+                                                                       RawBuffer &privKeyId,
+                                                                       RawBuffer &privKeyTag)
+{
+       // command ID = CMD_GENERATE_RSA_KEYPAIR
+       //
+       // TEEC_Operation layout:
+       // params:
+       //   [0].value.b - key bit size
+       //   [1].memref - reference to serialized buffer:
+       //       flag marking the public key password presence,
+       //       public key password data if the flag above is not 0,
+       //       flag marking the private key password presence,
+       //       public key private data if the flag above is not 0,
+       // output:
+       //   [0].value.a - return code
+       //   [2].memref
+       //       Public key ID,
+       //       public key tag if password was present,
+       //       Private key ID,
+       //       private key tag if password was present,
+
+       TZSerializer sIn;
+
+       GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
+                    sIn,
+                    keySizeBits,
+                    pubPwd,
+                    pubPwdIv,
+                    privPwd,
+                    privPwdIv,
+                    pubKeyId,
+                    pubKeyTag,
+                    privKeyId,
+                    privKeyTag);
+}
+
+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 &pubKeyId,
+                                                                       RawBuffer &pubKeyTag,
+                                                                       RawBuffer &privKeyId,
+                                                                       RawBuffer &privKeyTag)
+{
+       // command ID = CMD_GENERATE_DSA_KEYPAIR
+       //
+       // TEEC_Operation layout:
+       // params:
+       //   [0].value.b - key bit size
+       //   [1].memref - reference to serialized buffer:
+       //       prime, subprime, base,
+       //       flag marking the public key password presence,
+       //       public key password data if the flag above is not 0,
+       //       flag marking the private key password presence,
+       //       public key private data if the flag above is not 0,
+       // output:
+       //   [0].value.a - return code
+       //   [2].memref
+       //       Public key ID,
+       //       public key tag if password was present,
+       //       Private key ID,
+       //       private key tag if password was present,
+
+       TZSerializer sIn;
+       sIn.Push(new TZSerializableBinary(prime));
+       sIn.Push(new TZSerializableBinary(subprime));
+       sIn.Push(new TZSerializableBinary(base));
+
+       GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
+                    sIn,
+                    keySizeBits,
+                    pubPwd,
+                    pubPwdIv,
+                    privPwd,
+                    privPwdIv,
+                    pubKeyId,
+                    pubKeyTag,
+                    privKeyId,
+                    privKeyTag);
+}
+
 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,
@@ -275,9 +463,9 @@ void TrustZoneContext::executeCrypt(tz_command cmd,
        //   [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;
@@ -289,15 +477,22 @@ void TrustZoneContext::executeCrypt(tz_command cmd,
        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.key_id_size = static_cast<uint32_t>(keyId.size());
        uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
        TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
 
-       // 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());
+
+       // decrypt operation does not require padding
+       bufSize.out_size = static_cast<uint32_t>(data.size());
+       if (cmd == CMD_ENCRYPT) {
+               if (algo == ALGO_RSA) {
+                       // We don't know the key length
+                       bufSize.out_size = MAX_KEY_SIZE.at(ALGO_RSA);
+               } else {
+                       bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
+               }
+       }
        uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
        TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
 
@@ -328,7 +523,7 @@ void TrustZoneContext::executeCrypt(tz_command cmd,
                ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
        }
 
-       ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+       ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
        if (ret) {
                ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
        }
@@ -362,7 +557,7 @@ void TrustZoneContext::executeCrypt(tz_command cmd,
        memcpy(out.data(), outData->data, outData->data_size);
 }
 
-void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
+void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
                                                                                const Pwd &pwd,
                                                                                const RawBuffer &iv,
                                                                                int tagSizeBits,
@@ -382,7 +577,7 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
        //   [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");
        }
 
@@ -396,7 +591,7 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
        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.key_id_size = static_cast<uint32_t>(keyId.size());
        bufSize.with_ae_data = true;
        bufSize.aad_size = static_cast<uint32_t>(aad.size());
        uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
@@ -435,7 +630,7 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
                ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
        }
 
-       ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+       ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
        if (ret) {
                ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
        }
@@ -484,7 +679,7 @@ void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
        }
 }
 
-void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
+void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
                                                                                const Pwd &pwd,
                                                                                const RawBuffer &iv,
                                                                                int tagSizeBits,
@@ -504,7 +699,7 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
        //   [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");
        }
 
@@ -517,7 +712,7 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
        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.key_id_size = static_cast<uint32_t>(keyId.size());
        bufSize.with_ae_data = true;
        bufSize.aad_size = static_cast<uint32_t>(aad.size());
        bufSize.tag_size = static_cast<uint32_t>(tag.size());
@@ -556,7 +751,7 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
                ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
        }
 
-       ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+       ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
        if (ret) {
                ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
        }
@@ -599,6 +794,197 @@ void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
        memcpy(out.data(), outData->data, outData->data_size);
 }
 
+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)
+       //
+       // TEEC_Operation layout:
+       // input params:
+       //   [0].value.a - algorithm type (tz_algo_type)
+       //   [0].value.b - hash type (tz_hash_type)
+       //   [1].memref  - reference to serialized buffer:
+       //       KM_ParamsSerializeInputData with data to sign
+       //       KM_ParamsSerializeKeyId with key id
+       // output params:
+       //   [0].value.a - return code
+       //   [2].memref  - reference to serialized buffer:
+       //       KM_ParamsSerializeOutData with signature data
+
+       if (keyId.size() != KM_KEY_ID_SIZE) {
+               ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
+                       + std::to_string(keyId.size()) + ")");
+       }
+
+       KM_BufferSizeDesc bufSize;
+
+       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+       bufSize.input_size = static_cast<uint32_t>(message.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.key_id_size = static_cast<uint32_t>(keyId.size());
+       uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
+       TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+
+       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+       bufSize.out_size = MAX_KEY_SIZE.at(algo);
+       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 sign operations");
+       }
+
+       ret = KM_ParamsSerializeInputData(input, message.data(), message.size());
+       if (ret) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ sign 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 sign operation: ", ret);
+       }
+
+       ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
+       if (ret) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ sign operation: ", ret);
+       }
+
+       TEEC_Operation op;
+       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
+                                                                       TEEC_MEMREF_WHOLE, TEEC_NONE);
+       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);
+
+       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);
+       }
+
+       signature.resize(outData->data_size);
+       memcpy(signature.data(), outData->data, outData->data_size);
+}
+
+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)
+       //
+       // TEEC_Operation layout:
+       // input params:
+       //   [0].value.a - algorithm type (tz_algo_type)
+       //   [0].value.b - hash type (tz_hash_type)
+       //   [1].memref  - reference to serialized buffer:
+       //       KM_ParamsSerializeInputData with verify data (signature hidden in Tag data)
+       //       KM_ParamsSerializeKeyId with key id
+       // output params:
+       //   [0].value.a - return code
+
+       if (keyId.size() != KM_KEY_ID_SIZE) {
+               ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
+                       + std::to_string(keyId.size()) + ")");
+       }
+
+       KM_BufferSizeDesc bufSize;
+
+       memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+       bufSize.input_size = static_cast<uint32_t>(message.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.key_id_size = static_cast<uint32_t>(keyId.size());
+       bufSize.tag_size = static_cast<uint32_t>(signature.size());
+       uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
+       TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+
+       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 sign operations");
+       }
+
+       ret = KM_ParamsSerializeInputData(input, message.data(), message.size());
+       if (ret) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ sign 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 sign operation: ", ret);
+       }
+
+       ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
+       if (ret) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ sign operation: ", ret);
+       }
+
+       ret = KM_ParamsSerializeTagData(input, signature.data(), signature.size());
+       if (ret) {
+               ThrowErr(Exc::Crypto::InternalError, "Failed to serialize signature data for TZ sign operation: ", ret);
+       }
+
+       TEEC_Operation op;
+       op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
+                                                                       TEEC_NONE, TEEC_NONE);
+       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;
+       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)
@@ -888,14 +1274,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);
        }
 }
 
index 123c21e..05c336e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2017 - 2019 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.
@@ -27,6 +27,7 @@
 #include <memory>
 #include <tz-backend/obj.h>
 #include <generic-backend/encryption-params.h>
+#include <tz-backend/tz-serializer.h>
 
 namespace CKM {
 namespace Crypto {
@@ -48,6 +49,28 @@ public:
                                                const uint32_t pwdKeySizeBits,
                                                RawBuffer &keyId,
                                                RawBuffer &pwdTag);
+       void generateRSAKey(uint32_t keySizeBits,
+                                       const RawBuffer &pubPwd,
+                                       const RawBuffer &pubPwdIv,
+                                       const RawBuffer &privPwd,
+                                       const RawBuffer &privPwdIv,
+                                       RawBuffer &pubKeyId,
+                                       RawBuffer &pubKeyTag,
+                                       RawBuffer &privKeyId,
+                                       RawBuffer &privKeyTag);
+       void 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 &pubKeyId,
+                                               RawBuffer &pubKeyTag,
+                                               RawBuffer &privKeyId,
+                                               RawBuffer &privKeyTag);
+
        void importData(uint32_t dataType,
                                        const RawBuffer &data,
                                        const Crypto::EncryptionParams &encData,
@@ -60,13 +83,13 @@ public:
 
        void 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);
 
-       void executeEncryptAE(const RawBuffer &key,
+       void executeEncryptAE(const RawBuffer &keyId,
                                                const Pwd &pwd,
                                                const RawBuffer &iv,
                                                int tagSizeBits,
@@ -74,7 +97,7 @@ public:
                                                const RawBuffer &data,
                                                RawBuffer &out,
                                                RawBuffer &tag);
-       void executeDecryptAE(const RawBuffer &key,
+       void executeDecryptAE(const RawBuffer &keyId,
                                                const Pwd &pwd,
                                                const RawBuffer &iv,
                                                int tagSizeBits,
@@ -83,6 +106,19 @@ public:
                                                const RawBuffer &data,
                                                RawBuffer &out);
 
+       void executeSign(tz_algo_type algo,
+                                       tz_hash_type hash,
+                                       const RawBuffer &keyId,
+                                       const Pwd &pwd,
+                                       const RawBuffer &message,
+                                       RawBuffer &signature);
+       int executeVerify(tz_algo_type algo,
+                                       tz_hash_type hash,
+                                       const RawBuffer &keyId,
+                                       const Pwd &pwd,
+                                       const RawBuffer &message,
+                                       const RawBuffer &signature);
+
        void executeDestroy(const RawBuffer &keyId);
 
        void getData(const RawBuffer &dataId,
@@ -105,6 +141,18 @@ private:
 
        void Execute(tz_command commandID, TEEC_Operation* op);
 
+       void GenerateAKey(tz_command commandID,
+                         TZSerializer &sIn,
+                         uint32_t keySizeBits,
+                         const RawBuffer &pubPwd,
+                         const RawBuffer &pubPwdIv,
+                         const RawBuffer &privPwd,
+                         const RawBuffer &privPwdIv,
+                         RawBuffer &pubKeyId,
+                         RawBuffer &pubKeyTag,
+                         RawBuffer &privKeyId,
+                         RawBuffer &privKeyTag);
+
        TEEC_Context m_Context;
        TEEC_Session m_Session;