From: m.ksiezak Date: Thu, 16 Mar 2023 10:56:02 +0000 (+0100) Subject: Implementation of ckmc_export_wrapped_key X-Git-Tag: accepted/tizen/unified/20230406.165733~5^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dc375c06b749aba6c49413a8b51887d4f1c62dba;p=platform%2Fcore%2Fsecurity%2Fkey-manager.git Implementation of ckmc_export_wrapped_key Change-Id: I2769be74b1ad3d76537d31bc3f7ac4659946029f --- diff --git a/src/include/ckm/ckm-manager.h b/src/include/ckm/ckm-manager.h index defe6ce0..8ce5dea9 100644 --- a/src/include/ckm/ckm-manager.h +++ b/src/include/ckm/ckm-manager.h @@ -186,6 +186,14 @@ public: const KeyType keyType, const Policy &policy); + int exportWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &wrappedKeyAlias, + const Password &wrappedKeyPassword, + KeyType &keyType, + RawBuffer &wrappedKey); + private: std::unique_ptr m_impl; }; diff --git a/src/include/ckmc/ckmc-manager.h b/src/include/ckmc/ckmc-manager.h index 54c5ab5a..fd92c25f 100644 --- a/src/include/ckmc/ckmc-manager.h +++ b/src/include/ckmc/ckmc-manager.h @@ -1062,18 +1062,18 @@ int ckmc_import_wrapped_key(const ckmc_param_list_h params, * - #CKMC_ALGO_RSA_OAEP * @param[in] wrapping_key_alias The name of the wrapping key * @param[in] wrapping_key_password An optional password of the wrapping key - * @param[in] alias The name of the key to be wrapped and exported - * @param[in] password An optional password used to decrypt the key pointed by @a alias + * @param[in] wrapped_key_alias The name of the key to be wrapped and exported + * @param[in] wrapped_key_password An optional password used to decrypt the key pointed by @a wrapped_key_alias * @param[out] ppwrapped_key The wrapped key * * @return @c 0 on success, otherwise a negative error value * @retval #CKMC_ERROR_NONE Successful * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid (missing or invalid mandatory * algorithm parameter, GCM tag authentication failed, - * @a wrapping_key_alias = NULL, @a alias = NULL, - * @a wrapped_key = NULL, @a ppwrapped_key = NULL) + * @a wrapping_key_alias = NULL, @a wrapped_key_alias = NULL, + * @a ppwrapped_key = NULL) * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) - * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN @a wrapping_key_alias or @a alias does not exist + * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN @a wrapping_key_alias or @a wrapped_key_alias does not exist * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_AUTHENTICATION_FAILED Wrapping key decryption failed because * @a wrapping_key_password is incorrect @@ -1089,8 +1089,8 @@ int ckmc_import_wrapped_key(const ckmc_param_list_h params, int ckmc_export_wrapped_key(const ckmc_param_list_h params, const char *wrapping_key_alias, const char *wrapping_key_password, - const char *alias, - const char *password, + const char *wrapped_key_alias, + const char *wrapped_key_password, ckmc_key_s **ppwrapped_key); diff --git a/src/manager/client-capi/ckmc-manager.cpp b/src/manager/client-capi/ckmc-manager.cpp index 488f2871..e5fa0ec0 100644 --- a/src/manager/client-capi/ckmc-manager.cpp +++ b/src/manager/client-capi/ckmc-manager.cpp @@ -1049,3 +1049,49 @@ int ckmc_import_wrapped_key(const ckmc_param_list_h params, EXCEPTION_GUARD_END } + +KEY_MANAGER_CAPI +int ckmc_export_wrapped_key(const ckmc_param_list_h params, + const char *wrapping_key_alias, + const char *wrapping_key_password, + const char *wrapped_key_alias, + const char *wrapped_key_password, + ckmc_key_s **ppwrapped_key) +{ + EXCEPTION_GUARD_START_CAPI + + if (params == nullptr || + wrapping_key_alias == nullptr || + wrapped_key_alias == 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 wrappedKey; + CKM::KeyType keyType; + auto mgr = CKM::Manager::create(); + + ret = to_ckmc_error(mgr->exportWrappedKey(*ca, + CKM::Alias(wrapping_key_alias), + _tostring(wrapping_key_password), + CKM::Alias(wrapped_key_alias), + _tostring(wrapped_key_password), + keyType, + wrappedKey)); + + + + if (ret == CKMC_ERROR_NONE) { + ckmc_key_type_e ckmcKeyType = static_cast(keyType); + ret = ckmc_key_new(wrappedKey.data(), wrappedKey.size(), ckmcKeyType, nullptr, &wrapped_key); + if (ret == CKMC_ERROR_NONE) + *ppwrapped_key = wrapped_key; + } + + return ret; + EXCEPTION_GUARD_END +} diff --git a/src/manager/client/client-manager-impl.cpp b/src/manager/client/client-manager-impl.cpp index 5228f911..d2d85345 100644 --- a/src/manager/client/client-manager-impl.cpp +++ b/src/manager/client/client-manager-impl.cpp @@ -789,4 +789,47 @@ int Manager::Impl::importWrappedKey(const CryptoAlgorithm ¶ms, EXCEPTION_GUARD_END } +int Manager::Impl::exportWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &wrappedKeyAlias, + const Password &wrappedKeyPassword, + KeyType &keyType, + RawBuffer &wrappedKey) +{ + EXCEPTION_GUARD_START_CPPAPI + + AliasSupport wrapping_helper(wrappingKeyAlias); + AliasSupport wrapped_helper(wrappedKeyAlias); + DataType *dataTypeKey = nullptr; + + int retCode = Request(*this, + LogicCommand::EXPORT_WRAPPED_KEY, + m_storageConnection, + CryptoAlgorithmSerializable(params), + wrapping_helper.getName(), + wrapping_helper.getOwner(), + wrappingKeyPassword, + wrapped_helper.getName(), + wrapped_helper.getOwner(), + wrappedKeyPassword + ).maybeDeserialize(dataTypeKey, wrappedKey); + + if (retCode != CKM_API_SUCCESS) + return retCode; + + if (dataTypeKey->isSKey()) { + keyType = KeyType::KEY_AES; + } else if (dataTypeKey->isKeyPrivate()) { + keyType = KeyType::KEY_RSA_PRIVATE; + } else { + return CKM_API_ERROR_INVALID_FORMAT; + } + + return retCode; + + EXCEPTION_GUARD_END +} + + } // namespace CKM diff --git a/src/manager/client/client-manager-impl.h b/src/manager/client/client-manager-impl.h index 19dbcc59..91e57327 100644 --- a/src/manager/client/client-manager-impl.h +++ b/src/manager/client/client-manager-impl.h @@ -149,6 +149,14 @@ public: const KeyType keyType, const Policy &policy); + int exportWrappedKey(const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &wrappedKeyAlias, + const Password &wrappedKeyPassword, + KeyType &keyType, + RawBuffer &wrappedKey); + private: int saveBinaryData( const Alias &alias, diff --git a/src/manager/client/client-manager.cpp b/src/manager/client/client-manager.cpp index 2c4d1d87..8ef76bb9 100644 --- a/src/manager/client/client-manager.cpp +++ b/src/manager/client/client-manager.cpp @@ -324,5 +324,24 @@ ManagerShPtr Manager::create() } } -} // namespace CKM +int Manager::exportWrappedKey( + const CryptoAlgorithm ¶ms, + const Alias &wrappingKeyAlias, + const Password &wrappingKeyPassword, + const Alias &wrappedKeyAlias, + const Password &wrappedKeyPassword, + KeyType &keyType, + RawBuffer &wrappedKey) +{ + return m_impl->exportWrappedKey( + params, + wrappingKeyAlias, + wrappingKeyPassword, + wrappedKeyAlias, + wrappedKeyPassword, + keyType, + wrappedKey + ); +} +} // namespace CKM diff --git a/src/manager/common/protocols.h b/src/manager/common/protocols.h index 3670b9cd..3b1cad88 100644 --- a/src/manager/common/protocols.h +++ b/src/manager/common/protocols.h @@ -68,7 +68,8 @@ enum class LogicCommand : int { GET_PKCS12, GET_PROTECTION_STATUS, DERIVE, - IMPORT_WRAPPED_KEY + IMPORT_WRAPPED_KEY, + EXPORT_WRAPPED_KEY }; enum class EncryptionCommand : int { @@ -138,4 +139,3 @@ struct COMMON_API CryptoAlgorithmSerializable : public CryptoAlgorithm, }; } // namespace CKM - diff --git a/src/manager/crypto/generic-backend/gobj.h b/src/manager/crypto/generic-backend/gobj.h index 7e60dab1..8433e67b 100644 --- a/src/manager/crypto/generic-backend/gobj.h +++ b/src/manager/crypto/generic-backend/gobj.h @@ -84,6 +84,13 @@ public: ThrowErr(Exc::Crypto::OperationNotSupported); } + virtual RawBuffer wrap(const CryptoAlgorithm &, + const Token &, + const Password &) + { + ThrowErr(Exc::Crypto::OperationNotSupported); + } + virtual ~GObj() { } diff --git a/src/manager/crypto/sw-backend/obj.cpp b/src/manager/crypto/sw-backend/obj.cpp index 1f812e0a..a120cc62 100644 --- a/src/manager/crypto/sw-backend/obj.cpp +++ b/src/manager/crypto/sw-backend/obj.cpp @@ -94,6 +94,16 @@ Token Key::unwrap(const CryptoAlgorithm ¶ms, return Token(backendId(), encryptedKey.type, Store::pack(decrypted, pass)); } +RawBuffer Key::wrap(const CryptoAlgorithm ¶ms, + const Token &keyToWrap, + const Password &keyToWrapPass) +{ + + RawBuffer data = Store::unpack(keyToWrap.data, keyToWrapPass); + return encrypt(params, data); +} + + RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data) { return Internals::symmetricEncrypt(getBinary(), alg, data); @@ -223,6 +233,13 @@ Token Cert::unwrap(const CryptoAlgorithm &, const Data &, const Password &, cons ThrowErr(Exc::Crypto::OperationNotSupported); } +RawBuffer Cert::wrap(const CryptoAlgorithm &, + const Token &, + const Password &) +{ + 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 15ddb988..16b801a5 100644 --- a/src/manager/crypto/sw-backend/obj.h +++ b/src/manager/crypto/sw-backend/obj.h @@ -57,6 +57,11 @@ class Key : public BData { const Data &encryptedKey, const Password &pass, const RawBuffer &hash) override; + + RawBuffer wrap(const CryptoAlgorithm ¶ms, + const Token &keyToWrap, + const Password &keyToWrapPass) override; + }; class SKey : public Key { @@ -95,6 +100,10 @@ public: const Password &, const RawBuffer &) override; + RawBuffer wrap(const CryptoAlgorithm &, + const Token &, + const Password &) override; + protected: EvpShPtr getEvpShPtr() override; }; diff --git a/src/manager/crypto/sw-backend/store.cpp b/src/manager/crypto/sw-backend/store.cpp index 96a081be..7d610f77 100644 --- a/src/manager/crypto/sw-backend/store.cpp +++ b/src/manager/crypto/sw-backend/store.cpp @@ -72,50 +72,6 @@ RawBuffer passwordToKey(const Password &password, const RawBuffer &salt, return result; } -RawBuffer unpack(const RawBuffer &packed, const Password &pass) -{ - MessageBuffer buffer; - buffer.Push(RawBuffer(packed)); - int encryptionScheme = EncryptionScheme::NONE; - RawBuffer data; - buffer.Deserialize(encryptionScheme, data); - - if (encryptionScheme == EncryptionScheme::NONE) { - if (!pass.empty()) - ThrowErr(Exc::AuthenticationFailed, "Unexpected custom password."); - return data; - } - - MessageBuffer internalBuffer; - internalBuffer.Push(std::move(data)); - RawBuffer encrypted; - RawBuffer iv; - RawBuffer tag; - - // serialization exceptions will be catched as CKM::Exception and will cause - // CKM_API_ERROR_SERVER_ERROR - internalBuffer.Deserialize(encrypted, iv, tag); - - /* - * AES GCM will check data integrity and handle cases where: - * - wrong password is used - * - password is empty when it shouldn't be - */ - RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH); - - RawBuffer ret; - - try { - ret = Crypto::SW::Internals::decryptDataAesGcm(key, encrypted, iv, tag); - } catch (const Exc::Crypto::InputParam &e) { - ThrowErr(Exc::AuthenticationFailed, "Decryption with custom password failed, authentication failed"); - } catch (const Exc::Exception &e) { - ThrowErr(Exc::InternalError, "Decryption with custom password failed, internal error"); - } - - return ret; -} - std::string rawToHexString(const RawBuffer &raw) { return hexDump(raw); @@ -214,6 +170,50 @@ RawBuffer Store::pack(const RawBuffer &data, const Password &pass) return SerializeMessage(scheme, packed); } +RawBuffer Store::unpack(const RawBuffer &packed, const Password &pass) +{ + MessageBuffer buffer; + buffer.Push(RawBuffer(packed)); + int encryptionScheme = EncryptionScheme::NONE; + RawBuffer data; + buffer.Deserialize(encryptionScheme, data); + + if (encryptionScheme == EncryptionScheme::NONE) { + if (!pass.empty()) + ThrowErr(Exc::AuthenticationFailed, "Unexpected custom password."); + return data; + } + + MessageBuffer internalBuffer; + internalBuffer.Push(std::move(data)); + RawBuffer encrypted; + RawBuffer iv; + RawBuffer tag; + + // serialization exceptions will be catched as CKM::Exception and will cause + // CKM_API_ERROR_SERVER_ERROR + internalBuffer.Deserialize(encrypted, iv, tag); + + /* + * AES GCM will check data integrity and handle cases where: + * - wrong password is used + * - password is empty when it shouldn't be + */ + RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH); + + RawBuffer ret; + + try { + ret = Crypto::SW::Internals::decryptDataAesGcm(key, encrypted, iv, tag); + } catch (const Exc::Crypto::InputParam &e) { + ThrowErr(Exc::AuthenticationFailed, "Decryption with custom password failed, authentication failed"); + } catch (const Exc::Exception &e) { + ThrowErr(Exc::InternalError, "Decryption with custom password failed, internal error"); + } + + return ret; +} + } // namespace SW } // namespace Crypto } // namespace CKM diff --git a/src/manager/crypto/sw-backend/store.h b/src/manager/crypto/sw-backend/store.h index eba13653..fa61e9bf 100644 --- a/src/manager/crypto/sw-backend/store.h +++ b/src/manager/crypto/sw-backend/store.h @@ -45,6 +45,7 @@ public: void destroy(const Token &) override {} static RawBuffer pack(const RawBuffer &data, const Password &pass); + static RawBuffer unpack(const RawBuffer &packed, const Password &pass); }; } // namespace SW diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index bc888764..d931083d 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -1575,7 +1575,6 @@ RawBuffer CKMLogic::importWrappedKey( const CKM::DataType encryptedKeyType, const PolicySerializable &encryptedKeyPolicy) { - return SerializeMessage(msgId, tryRet([&] { Crypto::GObjUPtr wrappingKey; @@ -1599,4 +1598,39 @@ RawBuffer CKMLogic::importWrappedKey( })); } +RawBuffer CKMLogic::exportWrappedKey( + const Credentials &cred, + const int msgID, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &wrappedKeyName, + const ClientId &wrappedKeyOwner, + const Password &wrappedKeyPassword) +{ + Crypto::GObjUPtr wrappingKey; + DB::Row wrappedKeyRow; + DataType wrappedKeyType; + RawBuffer wrappedKey; + + auto retCode = tryRet([&] { + auto retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName, + wrappingKeyOwner, wrappingKeyPassword, wrappingKey); + if (retCode != CKM_API_SUCCESS) + return retCode; + + retCode = readRowHelper(false, cred, DataType::DB_KEY_FIRST, wrappedKeyName, + wrappedKeyOwner, wrappedKeyPassword, wrappedKeyRow, wrappedKeyType); + if (retCode != CKM_API_SUCCESS) + return retCode; + + wrappedKey = wrappingKey->wrap(params, wrappedKeyRow, wrappedKeyPassword); + + return retCode; + }); + + return SerializeMessage(msgID, retCode, wrappedKeyType, wrappedKey); +} + } // namespace CKM diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index ce990bb6..b87848b5 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -202,6 +202,17 @@ public: const ClientId &newKeyOwner, const Policy &newKeyPolicy); + RawBuffer exportWrappedKey( + const Credentials &cred, + const int msgID, + const CryptoAlgorithm ¶ms, + const Name &wrappingKeyName, + const ClientId &wrappingKeyOwner, + const Password &wrappingKeyPassword, + const Name &wrappedKeyName, + const ClientId &wrappedKeyOwner, + const Password &wrappedKeyPassword); + int setPermissionHelper( const Credentials &cred, const Name &name, @@ -408,4 +419,3 @@ protected: }; } // namespace CKM - diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 8d06e647..5c52e097 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -492,6 +492,35 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer) encryptedKeyPolicy); } + case LogicCommand::EXPORT_WRAPPED_KEY: { + CryptoAlgorithmSerializable params; + Name wrappingKeyName; + ClientId wrappingKeyOwner; + Password wrappingKeyPassword; + Name wrappedKeyName; + ClientId wrappedKeyOwner; + Password wrappedKeyPassword; + + buffer.Deserialize(params, + wrappingKeyName, + wrappingKeyOwner, + wrappingKeyPassword, + wrappedKeyName, + wrappedKeyOwner, + wrappedKeyPassword); + + return m_logic->exportWrappedKey( + cred, + msgId, + params, + wrappingKeyName, + cred.effectiveOwner(wrappingKeyOwner), + wrappingKeyPassword, + wrappedKeyName, + cred.effectiveOwner(wrappedKeyOwner), + wrappedKeyPassword); + } + default: Throw(Exception::BrokenProtocol); }