Key unwrapping implementation in TZ backend 45/290445/11
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 22 Mar 2023 08:48:31 +0000 (09:48 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 31 Mar 2023 12:11:52 +0000 (12:11 +0000)
Change-Id: I1ada1788c7f436b9cdd22cc7734eb3ab0159c544

src/manager/crypto/tz-backend/internals.cpp
src/manager/crypto/tz-backend/internals.h
src/manager/crypto/tz-backend/obj.cpp
src/manager/crypto/tz-backend/obj.h
src/manager/crypto/tz-backend/tz-context.cpp
src/manager/crypto/tz-backend/tz-context.h

index 5b8ad1e..cec70b8 100644 (file)
@@ -151,6 +151,8 @@ namespace Crypto {
 namespace TZ {
 namespace Internals {
 
+namespace {
+
 tz_algo_type getGenSKeyType(AlgoType type)
 {
        switch (type)
@@ -189,6 +191,44 @@ tz_hash_type getHashType(HashAlgorithm hash)
        }
 }
 
+void decompose(const CryptoAlgorithm &alg,
+                          AlgoType &algo,
+                          uint32_t &ctrLenOrTagSizeBits,
+                          RawBuffer &iv,
+                          RawBuffer &aad)
+{
+       algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+       switch (algo) {
+               case AlgoType::AES_CTR:
+                       iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
+                       ctrLenOrTagSizeBits = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
+                       // counter length is in bits
+                       if (ctrLenOrTagSizeBits != Params::DEFAULT_AES_IV_LEN * 8) {
+                               LogError("CTR length invalid: " << std::to_string(ctrLenOrTagSizeBits));
+                               ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
+                       }
+                       break;
+               case AlgoType::AES_CBC:
+                       iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
+                       break;
+               case AlgoType::AES_CFB:
+                       iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
+                       break;
+               case AlgoType::AES_GCM:
+                       iv = unpack<RawBuffer>(alg, ParamName::ED_IV);
+                       alg.getParam(ParamName::ED_TAG_LEN, ctrLenOrTagSizeBits);
+                       alg.getParam(ParamName::ED_AAD, aad);
+                       break;
+               case AlgoType::RSA_OAEP:
+                       break;
+               default:
+                       ThrowErr(Exc::Crypto::InputParam, "Invalid decryption algorithm");
+                       break;
+       }
+}
+
+} // namespace
+
 RawBuffer generateIV()
 {
        RawBuffer result;
@@ -324,6 +364,38 @@ void importData(const Data &data,
                                                                                hash);
 }
 
+void importWrappedKey(const RawBuffer &wrappingKey,
+                                         const Pwd &wrappingKeyPwd,
+                                         const CryptoAlgorithm &alg,
+                                         const Data &encryptedKey,
+                                         const Password &encryptedKeyPassword,
+                                         const RawBuffer &encryptedKeyIV,
+                                         RawBuffer &encryptedKeyTag,
+                                         const RawBuffer &encryptedKeyId)
+{
+       RawBuffer encryptedKeyPwdBuf(encryptedKeyPassword.begin(), encryptedKeyPassword.end());
+
+       AlgoType algo;
+       uint32_t ctrLenOrTagSizeBits = 0;
+       RawBuffer iv;
+       RawBuffer aad;
+       decompose(alg, algo, ctrLenOrTagSizeBits, iv, aad);
+
+       // TODO it is awful!
+       TrustZoneContext::Instance().importWrappedKey(wrappingKey,
+                                                                                                 wrappingKeyPwd,
+                                                                                                 getAlgType(algo),
+                                                                                                 iv,
+                                                                                                 ctrLenOrTagSizeBits,
+                                                                                                 aad,
+                                                                                                 toTzDataType(encryptedKey.type),
+                                                                                                 encryptedKey.data,
+                                                                                                 encryptedKeyPwdBuf,
+                                                                                                 encryptedKeyIV,
+                                                                                                 encryptedKeyTag,
+                                                                                                 encryptedKeyId);
+}
+
 RawBuffer getData(const RawBuffer &dataId,
                                  const Pwd &pwd)
 {
index bdfcc03..77b8c36 100644 (file)
@@ -62,6 +62,15 @@ void importData(const Data &key,
                                         RawBuffer &tag,
                                         const RawBuffer &hash);
 
+void importWrappedKey(const RawBuffer &wrappingKey,
+                                         const Pwd &wrappingKeyPwd,
+                                         const CryptoAlgorithm &alg,
+                                         const Data &encryptedKey,
+                                         const Password &encryptedKeyPassword,
+                                         const RawBuffer &encryptedKeyIV,
+                                         RawBuffer &encryptedKeyTag,
+                                         const RawBuffer &encryptedKeyId);
+
 RawBuffer getData(const RawBuffer &dataId,
                                  const Pwd &pwd);
 
index 86ac7a6..717c012 100644 (file)
@@ -68,6 +68,35 @@ Token BData::derive(const CryptoAlgorithm &alg, const Password &pass, const RawB
        return Token(backendId(), DataType(KeyType::KEY_AES), Store::pack(hash, pass, iv, tag));
 }
 
+Token Key::unwrap(const CryptoAlgorithm &params,
+                                 const Data &encryptedKey,
+                                 const Password &pass,
+                                 const RawBuffer &hash)
+{
+
+       if (!encryptedKey.type.isKey() || encryptedKey.type.isEllipticCurve())
+               ThrowErr(Exc::Crypto::DataTypeNotSupported, "Invalid data provided for import");
+
+       RawBuffer passIV;
+       RawBuffer tag;
+
+       if (!pass.empty()) {
+               // IV is needed for data encryption with pwd
+               passIV = Internals::generateIV();
+       }
+
+       Internals::importWrappedKey(getBinary(),
+                                                               getPassword(),
+                                                               params,
+                                                               encryptedKey,
+                                                               pass,
+                                                               passIV,
+                                                               tag,
+                                                               hash);
+
+       return Token(backendId(), encryptedKey.type, Store::pack(hash, pass, passIV, tag));
+}
+
 RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
 {
     return Internals::symmetricEncrypt(getBinary(), getPassword(), alg, data);
@@ -134,6 +163,13 @@ int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message,
        return Internals::verify(getBinary(), getPassword(), algWithType, message, sign);
 }
 
+Token Cert::unwrap(const CryptoAlgorithm &,
+                                  const Data &,
+                                  const Password &,
+                                  const RawBuffer &)
+{
+       ThrowErr(Exc::Crypto::OperationNotSupported);
+}
 
 } // namespace TZ
 } // namespace Crypto
index 77b3be8..96e4efc 100644 (file)
@@ -21,6 +21,7 @@
 #pragma once
 
 #include <generic-backend/gobj.h>
+#include <generic-backend/gstore.h>
 #include <data-type.h>
 
 namespace CKM {
@@ -90,6 +91,11 @@ public:
                return m_password;
        }
 
+       Token unwrap(const CryptoAlgorithm &params,
+                                const Data &encryptedKey,
+                                const Password &pass,
+                                const RawBuffer &hash) override;
+
 protected:
        int m_scheme;
        Pwd m_password;
@@ -122,6 +128,11 @@ class Cert : public AKey {
 public:
        Cert(CryptoBackend backendId, int scheme, RawBuffer buffer, Pwd pwd, DataType dataType) :
                AKey(backendId, scheme, std::move(buffer), std::move(pwd), dataType) {}
+
+       Token unwrap(const CryptoAlgorithm &,
+                                const Data &,
+                                const Password &,
+                                const RawBuffer &) override;
 };
 
 } // namespace TZ
index a058e1b..a998bc9 100644 (file)
@@ -599,6 +599,57 @@ void TrustZoneContext::importData(
        LogDebug("Imported object ID is (hex): " << rawToHexString(hash));
 }
 
+void TrustZoneContext::importWrappedKey(const RawBuffer &wrappingKey,
+                                                                               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(wrappingKey,
+                                                         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));
+}
+
 void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize)
 {
        // command ID = CMD_GET_DATA_SIZE
index 2a1cff3..71ef9c9 100644 (file)
@@ -89,6 +89,19 @@ public:
                                        RawBuffer &pwdTag,
                                        const RawBuffer &hash);
 
+       void importWrappedKey(const RawBuffer &wrappingKey,
+                                                 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 &encryptedKeyHash);
+
        void executeCrypt(tz_command cmd,
                                        tz_algo_type algo,
                                        const RawBuffer &keyId,