From: Dariusz Michaluk Date: Fri, 19 Apr 2024 13:24:49 +0000 (+0200) Subject: Concatenated wrapping sw-backend implementation X-Git-Tag: accepted/tizen/7.0/unified/20240610.163828~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=849c611a62a25d08aa88fe101c56e9e8947754a7;p=platform%2Fcore%2Fsecurity%2Fkey-manager.git Concatenated wrapping sw-backend implementation Change-Id: I28856286c05c2ec1919674b0e7cf8add90cc20e1 --- diff --git a/src/include/ckm/ckm-manager.h b/src/include/ckm/ckm-manager.h index b98b4c8d..fbf633c5 100644 --- a/src/include/ckm/ckm-manager.h +++ b/src/include/ckm/ckm-manager.h @@ -192,6 +192,23 @@ public: KeyType &keyType, RawBuffer &wrappedKey); + int wrapConcatenatedData(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const Password &password, + const RawBuffer &data, + RawBuffer &wrappedKey); + + int unwrapConcatenatedData(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const RawBuffer &wrappedKey, + const Alias &alias, + size_t size, + const Policy &policy, + RawBuffer &data); + int initializeCipher(const CryptoAlgorithm ¶ms, const Alias &keyAlias, const Password &keyPassword, diff --git a/src/manager/client-capi/ckmc-manager.cpp b/src/manager/client-capi/ckmc-manager.cpp index 3712becf..e0c3be2b 100644 --- a/src/manager/client-capi/ckmc-manager.cpp +++ b/src/manager/client-capi/ckmc-manager.cpp @@ -1268,15 +1268,43 @@ int ckmc_wrap_concatenated_data(const ckmc_param_list_h params, const ckmc_raw_buffer_s *data, ckmc_key_s **ppwrapped_key) { - (void) params; - (void) wrapping_key_alias; - (void) wrapping_key_password; - (void) alias; - (void) password; - (void) data; - (void) ppwrapped_key; + EXCEPTION_GUARD_START_CAPI - return CKMC_ERROR_NONE; + if (params == nullptr || wrapping_key_alias == nullptr || + alias == nullptr || data == nullptr || ppwrapped_key == nullptr) + return CKMC_ERROR_INVALID_PARAMETER; + + const CKM::CryptoAlgorithm *ca = reinterpret_cast + (params); + + int ret = 0; + ckmc_key_s *wrapped_key = nullptr; + CKM::RawBuffer wrapped_key_buffer; + CKM::KeyType key_type = CKM::KeyType::KEY_AES; + + auto mgr = CKM::Manager::create(); + + ret = to_ckmc_error( + mgr->wrapConcatenatedData(*ca, + CKM::Alias(wrapping_key_alias), + _tostring(wrapping_key_password), + CKM::Alias(alias), + _tostring(password), + CKM::RawBuffer(data->data, data->data + data->size), + wrapped_key_buffer)); + + if (ret == CKMC_ERROR_NONE) { + ret = ckmc_key_new(wrapped_key_buffer.data(), + wrapped_key_buffer.size(), + static_cast(key_type), + nullptr, + &wrapped_key); + if (ret == CKMC_ERROR_NONE) + *ppwrapped_key = wrapped_key; + } + + return ret; + EXCEPTION_GUARD_END } KEY_MANAGER_CAPI @@ -1289,14 +1317,46 @@ int ckmc_unwrap_concatenated_data(const ckmc_param_list_h params, const ckmc_policy_s policy, ckmc_raw_buffer_s **ppdata) { - (void) params; - (void) wrapping_key_alias; - (void) wrapping_key_password; - (void) wrapped_key; - (void) alias; - (void) size; - (void) policy; - (void) ppdata; + EXCEPTION_GUARD_START_CAPI - return CKMC_ERROR_NONE; + if (params == nullptr || wrapping_key_alias == nullptr || + wrapped_key == nullptr || + wrapped_key->raw_key == nullptr || + wrapped_key->key_size == 0 || + wrapped_key->key_size * 8 < size || + alias == nullptr || + ((size != 128) & (size != 192) & (size != 256)) || + ppdata == nullptr) + return CKMC_ERROR_INVALID_PARAMETER; + + const CKM::CryptoAlgorithm *ca = reinterpret_cast + (params); + + int ret = 0; + CKM::RawBuffer data_buffer; + + if (static_cast(wrapped_key->key_type) != CKM::KeyType::KEY_AES) + return CKMC_ERROR_INVALID_PARAMETER; + + auto mgr = CKM::Manager::create(); + + ret = to_ckmc_error( + mgr->unwrapConcatenatedData(*ca, + CKM::Alias(wrapping_key_alias), + _tostring(wrapping_key_password), + CKM::RawBuffer(wrapped_key->raw_key, + wrapped_key->raw_key + wrapped_key->key_size), + CKM::Alias(alias), + size, + _toCkmPolicy(policy), + data_buffer)); + + if (ret == CKMC_ERROR_NONE) { + ret = ckmc_buffer_new(data_buffer.data(), + data_buffer.size(), + ppdata); + } + + return ret; + EXCEPTION_GUARD_END } \ No newline at end of file diff --git a/src/manager/client/client-manager-impl.cpp b/src/manager/client/client-manager-impl.cpp index 961f31db..05993f6c 100644 --- a/src/manager/client/client-manager-impl.cpp +++ b/src/manager/client/client-manager-impl.cpp @@ -813,6 +813,76 @@ int Manager::Impl::exportWrappedKey(const CryptoAlgorithm ¶ms, EXCEPTION_GUARD_END } +int Manager::Impl::wrapConcatenatedData(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const Password &password, + const RawBuffer &data, + RawBuffer &wrappedKey) +{ + EXCEPTION_GUARD_START_CPPAPI + + AliasSupport wrappingAliasHelper(wrappingKeyAlias); + AliasSupport aliasHelper(alias); + DataType dataTypeKey; + + int retCode = Request(*this, + LogicCommand::WRAP_CONCATENATED_DATA, + m_storageConnection, + CryptoAlgorithmSerializable(params), + wrappingAliasHelper.getName(), + wrappingAliasHelper.getOwner(), + wrappingKeyPassword, + aliasHelper.getName(), + aliasHelper.getOwner(), + password, + data + ).maybeDeserialize(dataTypeKey, wrappedKey); + + if (retCode != CKM_API_SUCCESS) + return retCode; + + if (!dataTypeKey.isSymmetricKey()) { + return CKM_API_ERROR_INVALID_FORMAT; + } + + return retCode; + + EXCEPTION_GUARD_END +} + +int Manager::Impl::unwrapConcatenatedData(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const RawBuffer &wrappedKey, + const Alias &alias, + size_t size, + const Policy &policy, + RawBuffer &data) +{ + EXCEPTION_GUARD_START_CPPAPI + + AliasSupport wrappingAliasHelper(wrappingKeyAlias); + AliasSupport aliasHelper(alias); + + return Request(*this, + LogicCommand::UNWRAP_CONCATENATED_DATA, + m_storageConnection, + CryptoAlgorithmSerializable(params), + wrappingAliasHelper.getName(), + wrappingAliasHelper.getOwner(), + wrappingKeyPassword, + wrappedKey, + aliasHelper.getName(), + aliasHelper.getOwner(), + size, + PolicySerializable(policy) + ).maybeDeserialize(data); + + EXCEPTION_GUARD_END +} + int Manager::Impl::initializeCipher( const CryptoAlgorithm ¶ms, const Alias &keyAlias, diff --git a/src/manager/client/client-manager-impl.h b/src/manager/client/client-manager-impl.h index 6e9b3d03..d7fa94b7 100644 --- a/src/manager/client/client-manager-impl.h +++ b/src/manager/client/client-manager-impl.h @@ -157,6 +157,23 @@ public: KeyType &keyType, RawBuffer &wrappedKey); + int wrapConcatenatedData(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const Password &password, + const RawBuffer &data, + RawBuffer &wrappedKey); + + int unwrapConcatenatedData(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const RawBuffer &wrappedKey, + const Alias &alias, + size_t size, + const Policy &policy, + RawBuffer &data); + int initializeCipher(const CryptoAlgorithm ¶ms, const Alias &keyAlias, const Password &keyPassword, diff --git a/src/manager/client/client-manager.cpp b/src/manager/client/client-manager.cpp index c808eb96..eb8f42cd 100644 --- a/src/manager/client/client-manager.cpp +++ b/src/manager/client/client-manager.cpp @@ -334,6 +334,48 @@ int Manager::exportWrappedKey( ); } +int Manager::wrapConcatenatedData( + const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &alias, + const Password &password, + const RawBuffer &data, + RawBuffer &wrappedKey) +{ + return m_impl->wrapConcatenatedData( + params, + wrappingKeyAlias, + wrappingKeyPassword, + alias, + password, + data, + wrappedKey + ); +} + +int Manager::unwrapConcatenatedData( + const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const RawBuffer &wrappedKey, + const Alias &alias, + size_t size, + const Policy &policy, + RawBuffer &data) +{ + return m_impl->unwrapConcatenatedData( + params, + wrappingKeyAlias, + wrappingKeyPassword, + wrappedKey, + alias, + size, + policy, + data + ); +} + int Manager::initializeCipher( const CryptoAlgorithm ¶ms, const Alias &keyAlias, diff --git a/src/manager/common/protocols.h b/src/manager/common/protocols.h index 75c12cf9..bfbf53be 100644 --- a/src/manager/common/protocols.h +++ b/src/manager/common/protocols.h @@ -70,6 +70,8 @@ enum class LogicCommand : int { DERIVE, IMPORT_WRAPPED_KEY, EXPORT_WRAPPED_KEY, + WRAP_CONCATENATED_DATA, + UNWRAP_CONCATENATED_DATA, GET_BACKEND_INFO }; diff --git a/src/manager/crypto/generic-backend/gobj.h b/src/manager/crypto/generic-backend/gobj.h index f67a0bb8..30049805 100644 --- a/src/manager/crypto/generic-backend/gobj.h +++ b/src/manager/crypto/generic-backend/gobj.h @@ -92,6 +92,23 @@ public: ThrowErr(Exc::Crypto::OperationNotSupported); } + virtual RawBuffer wrapConcatenated(const CryptoAlgorithm &, + const Token &, + const Password &, + const RawBuffer &) + { + ThrowErr(Exc::Crypto::OperationNotSupported); + } + + virtual std::tuple unwrapConcatenated(const CryptoAlgorithm &, + const Data &, + const Password &, + size_t, + const RawBuffer &) + { + ThrowErr(Exc::Crypto::OperationNotSupported); + } + // onward = true for encryption/signing, false for decryption/verification virtual GCtxShPtr initContext(const CryptoAlgorithm &, bool /*onward*/) { diff --git a/src/manager/crypto/sw-backend/obj.cpp b/src/manager/crypto/sw-backend/obj.cpp index 9043f832..c95702f4 100644 --- a/src/manager/crypto/sw-backend/obj.cpp +++ b/src/manager/crypto/sw-backend/obj.cpp @@ -105,7 +105,6 @@ RawBuffer Key::wrap(const CryptoAlgorithm ¶ms, return encrypt(params, data); } - RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data) { return Internals::symmetricEncrypt(getBinary(), alg, data); @@ -219,6 +218,43 @@ GCtxShPtr AKey::initContext(const CryptoAlgorithm &, bool) ThrowErr(Exc::Crypto::OperationNotSupported); } +RawBuffer AKey::wrapConcatenated(const CryptoAlgorithm ¶ms, + const Token &keyToWrap, + const Password &keyToWrapPass, + const RawBuffer &data) +{ + RawBuffer key = Store::unpack(keyToWrap.data, keyToWrapPass); + + key.insert(key.end(), data.begin(), data.begin() + data.size()); + return encrypt(params, key); +} + +std::tuple AKey::unwrapConcatenated(const CryptoAlgorithm ¶ms, + const Data &wrappedKey, + const Password &pass, + size_t size, + const RawBuffer &) +{ + if (!wrappedKey.type.isSymmetricKey()) { + ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a symmetric key"); + } + + auto decrypted = decrypt(params, wrappedKey.data); + RawBuffer key; + key.reserve(size/8); + key.insert(key.end(), decrypted.begin(), decrypted.begin() + size/8); + RawBuffer data; + data.reserve(decrypted.size() - size/8); + data.insert(data.end(), decrypted.begin() + size/8, decrypted.end()); + + // validate the decrypted key + auto tmp = CKM::Key::createAES(key); + if (!tmp) + ThrowErr(Exc::Crypto::InputParam, "Wrapped data is not a valid AES key"); + + return std::make_tuple(Token(backendId(), wrappedKey.type, Store::pack(key, pass)), data); +} + EvpShPtr Cert::getEvpShPtr() { if (m_evp) @@ -253,6 +289,21 @@ RawBuffer Cert::wrap(const CryptoAlgorithm &, const Token &, const Password &) ThrowErr(Exc::Crypto::OperationNotSupported); } +RawBuffer Cert::wrapConcatenated(const CryptoAlgorithm &, + const Token &, const Password &, + const RawBuffer &) +{ + ThrowErr(Exc::Crypto::OperationNotSupported); +} + +std::tuple Cert::unwrapConcatenated(const CryptoAlgorithm &, + const Data &, const Password &, + size_t, + const RawBuffer &) +{ + ThrowErr(Exc::Crypto::OperationNotSupported); +} + } // namespace SW } // namespace Crypto } // namespace CKM diff --git a/src/manager/crypto/sw-backend/obj.h b/src/manager/crypto/sw-backend/obj.h index 697e4ff4..37cc1777 100644 --- a/src/manager/crypto/sw-backend/obj.h +++ b/src/manager/crypto/sw-backend/obj.h @@ -61,7 +61,6 @@ class Key : public BData { RawBuffer wrap(const CryptoAlgorithm ¶ms, const Token &keyToWrap, const Password &keyToWrapPass) override; - }; class SKey : public Key { @@ -86,6 +85,17 @@ public: Token derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) override; GCtxShPtr initContext(const CryptoAlgorithm &, bool) override; + RawBuffer wrapConcatenated(const CryptoAlgorithm ¶ms, + const Token &keyToWrap, + const Password &keyToWrapPass, + const RawBuffer &data) override; + + std::tuple unwrapConcatenated(const CryptoAlgorithm ¶ms, + const Data &wrappedKey, + const Password &pass, + size_t size, + const RawBuffer &data) override; + protected: virtual EvpShPtr getEvpShPtr(); @@ -106,6 +116,15 @@ public: const Token &, const Password &) override; + RawBuffer wrapConcatenated(const CryptoAlgorithm &, + const Token &, const Password &, + const RawBuffer &) override; + + std::tuple unwrapConcatenated(const CryptoAlgorithm &, + const Data &, const Password &, + size_t, + const RawBuffer &) override; + protected: EvpShPtr getEvpShPtr() override; }; diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 4bcb3c7c..a6b24707 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -1652,9 +1652,15 @@ RawBuffer CKMLogic::exportWrappedKey( retCode2 = readRowHelper(false, cred, DataType::DB_KEY_FIRST, keyName, keyOwner, keyPassword, wrappedKeyRow, wrappedKeyType); + if (retCode2 != CKM_API_SUCCESS) return retCode2; + if (wrappingKey->backendId() != wrappedKeyRow.backendId) { + LogError("Mismatched backends"); + return CKM_API_ERROR_INPUT_PARAM; + } + if (!wrappedKeyType.isSymmetricKey()) { LogError("Only symmetric key can be exported"); return CKM_API_ERROR_INPUT_PARAM; @@ -1668,6 +1674,113 @@ RawBuffer CKMLogic::exportWrappedKey( return SerializeMessage(msgID, retCode, wrappedKeyType, wrappedKey); } +RawBuffer CKMLogic::wrapConcatenatedData( + const Credentials &cred, + const int msgID, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &keyName, + const ClientId &keyOwner, + const Password &keyPassword, + const RawBuffer &data) +{ + Crypto::GObjUPtr wrappingKey; + DB::Row keyRow; + DataType keyType; + RawBuffer wrappedKey; + + auto retCode = tryRet([&] { + auto retCode2 = readDataHelper(false, cred, DataType::KEY_RSA_PUBLIC, wrappingKeyName, + wrappingKeyOwner, wrappingKeyPassword, wrappingKey); + if (retCode2 != CKM_API_SUCCESS) + return retCode2; + + retCode2 = readRowHelper(false, cred, DataType::DB_KEY_FIRST, keyName, + keyOwner, keyPassword, keyRow, keyType); + if (retCode2 != CKM_API_SUCCESS) + return retCode2; + + if (wrappingKey->backendId() != keyRow.backendId) { + LogError("Mismatched backends"); + return CKM_API_ERROR_INPUT_PARAM; + } + + if (!keyType.isSymmetricKey()) { + LogError("Only symmetric key can be exported"); + return CKM_API_ERROR_INPUT_PARAM; + } + + wrappedKey = wrappingKey->wrapConcatenated(params, keyRow, keyPassword, data); + + return retCode2; + }); + + return SerializeMessage(msgID, retCode, keyType, wrappedKey); +} + +RawBuffer CKMLogic::unwrapConcatenatedData( + const Credentials &cred, + const int msgID, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const RawBuffer &wrappedKey, + const Name &keyName, + const ClientId &keyOwner, + size_t size, + const PolicySerializable &policy) +{ + RawBuffer data; + + auto retCode = tryRet([&] { + Crypto::GObjUPtr wrappingKey; + + auto [dbOp, digest, retCode2] = beginSaveAndGetHash(cred, keyName, keyOwner); + if (retCode2 != CKM_API_SUCCESS) + return retCode2; + + DataType wrappingKeyType; + retCode2 = readDataHelper(false, + cred, + DataType::DB_KEY_FIRST, + wrappingKeyName, + wrappingKeyOwner, + wrappingKeyPassword, + wrappingKey, + wrappingKeyType); + if (retCode2 != CKM_API_SUCCESS) + return retCode2; + + if (wrappingKeyType != DataType::KEY_RSA_PRIVATE) { + LogError("Only a private RSA key can be used for decryption"); + return CKM_API_ERROR_INPUT_PARAM; + } + + if (!m_decider.checkStore(wrappingKey->backendId(), DataType::KEY_AES, policy, true)) { + LogDebug("Can't import the wrapped key to backend " << + static_cast(wrappingKey->backendId()) << " with given policy"); + return CKM_API_ERROR_INPUT_PARAM; + } + + std::tuple tokenWithData = + wrappingKey->unwrapConcatenated(params, + Crypto::Data(DataType::KEY_AES, wrappedKey), + policy.password, + size, + digest); + + dbOp.finalize(std::move(std::get<0>(tokenWithData)), policy); + data = std::get<1>(tokenWithData); + + return retCode2; + }); + + return SerializeMessage(msgID, retCode, data); +} + RawBuffer CKMLogic::getBackendInfo(const int msgID, BackendId backend) { BackendInfo info; diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index a8fc1b73..4188bb25 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -226,6 +226,31 @@ public: const ClientId &keyOwner, const Password &keyPassword); + RawBuffer wrapConcatenatedData( + const Credentials &cred, + const int msgID, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &keyName, + const ClientId &keyOwner, + const Password &keyPassword, + const RawBuffer &data); + + RawBuffer unwrapConcatenatedData( + const Credentials &cred, + const int msgID, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const RawBuffer &wrappedKey, + const Name &keyName, + const ClientId &keyOwner, + size_t size, + const PolicySerializable &policy); + RawBuffer getBackendInfo( const int msgID, BackendId backend); diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 18036355..be4ebfe1 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -517,6 +517,71 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer) keyPassword); } + case LogicCommand::WRAP_CONCATENATED_DATA: { + CryptoAlgorithmSerializable params; + Name wrappingKeyName; + ClientId wrappingKeyOwner; + Password wrappingKeyPassword; + Name keyName; + Password keyPassword; + RawBuffer data; + + buffer.Deserialize(params, + wrappingKeyName, + wrappingKeyOwner, + wrappingKeyPassword, + keyName, + explicitOwner, + keyPassword, + data); + + return m_logic->wrapConcatenatedData( + cred, + msgId, + params, + wrappingKeyName, + cred.effectiveOwner(wrappingKeyOwner), + wrappingKeyPassword, + keyName, + cred.effectiveOwner(explicitOwner), + keyPassword, + data); + } + + case LogicCommand::UNWRAP_CONCATENATED_DATA: { + CryptoAlgorithmSerializable params; + Name wrappingKeyName; + ClientId wrappingKeyOwner; + Password wrappingKeyPassword; + RawBuffer wrappedKey; + Name keyName; + size_t size; + PolicySerializable policy; + + buffer.Deserialize(params, + wrappingKeyName, + wrappingKeyOwner, + wrappingKeyPassword, + wrappedKey, + keyName, + explicitOwner, + size, + policy); + + return m_logic->unwrapConcatenatedData( + cred, + msgId, + params, + wrappingKeyName, + cred.effectiveOwner(wrappingKeyOwner), + wrappingKeyPassword, + wrappedKey, + keyName, + cred.effectiveOwner(explicitOwner), + size, + policy); + } + case LogicCommand::GET_BACKEND_INFO: { BackendId backend;