Key derivation implementation: client & server 52/288052/11
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 1 Feb 2023 16:00:34 +0000 (17:00 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 17 Mar 2023 09:20:00 +0000 (10:20 +0100)
Client and server part (no implementation in backend)

Change-Id: I38d9be59b2c07ed59b61374f461383b58e4c98d0

14 files changed:
src/include/ckm/ckm-manager.h
src/include/ckm/ckm-type.h
src/manager/client-capi/ckmc-manager.cpp
src/manager/client/client-manager-impl.cpp
src/manager/client/client-manager-impl.h
src/manager/client/client-manager.cpp
src/manager/common/protocols.cpp
src/manager/common/protocols.h
src/manager/crypto/generic-backend/gobj.h
src/manager/crypto/sw-backend/obj.cpp
src/manager/crypto/sw-backend/obj.h
src/manager/service/ckm-logic.cpp
src/manager/service/ckm-logic.h
src/manager/service/ckm-service.cpp

index 68f613c..8a94b54 100644 (file)
@@ -170,6 +170,12 @@ public:
                                const RawBuffer &encrypted,
                                RawBuffer &decrypted);
 
+       int deriveKey(const CryptoAlgorithm &algo,
+                                 const Alias &secretAlias,
+                                 const Password &secretPassword,
+                                 const Alias &newKeyAlias,
+                                 const Policy &newKeyPolicy);
+
        static ManagerShPtr create();
 
 private:
index 43a7de7..2bc7610 100644 (file)
@@ -127,6 +127,25 @@ enum Permission : int {
                                          // keep in sync with ckmc_permission_e !
 };
 
+enum class KdfPrf : int {
+       HMAC_SHA256 = 1,
+       HMAC_SHA384,
+       HMAC_SHA512
+       // keep in sync with ckmc_kdf_prf_e !
+};
+
+enum class KbkdfMode : int {
+       COUNTER = 1,
+       // keep in sync with ckmc_kbkdf_mode_e !
+};
+
+enum class KbkdfCounterLocation : int {
+       BEFORE_FIXED = 1,
+       AFTER_FIXED,
+       MIDDLE_FIXED
+       // keep in sync with ckmc_kbkdf_counter_location_e !
+};
+
 // algorithm parameters
 enum class ParamName : int {
        ALGO_TYPE = 1,      // If there's no such param, the service will try to deduce the algorithm
@@ -147,9 +166,21 @@ enum class ParamName : int {
        SV_HASH_ALGO = 301, // hash algorithm (HashAlgorithm)
        SV_RSA_PADDING,     // RSA padding (RSAPaddingAlgorithm)
 
+       KDF_PRF = 401,          // KdfPrf
+       KDF_LEN,
+       KBKDF_MODE,             // KbkdfMode
+       KBKDF_LABEL,
+       KBKDF_CONTEXT,
+       KBKDF_FIXED_INPUT,
+       KBKDF_COUNTER_LOCATION, // KbkdfCounterLocation
+       KBKDF_RLEN,
+       KBKDF_LLEN,
+       KBKDF_NO_SEPARATOR,
+       ECDH_PUBKEY,
+
        // special values marking valid values range
        FIRST = ALGO_TYPE,
-       LAST = SV_RSA_PADDING
+       LAST = ECDH_PUBKEY
 };
 
 // algorithm types (ALGO_TYPE param)
@@ -159,6 +190,10 @@ enum class AlgoType : int {
        AES_GCM,
        AES_CFB,
        RSA_OAEP,
+       KBKDF,
+       ECDH,
+       // keep in sync with ckmc_algo_type_e !
+
        RSA_SV,
        DSA_SV,
        ECDSA_SV,
index febac67..ba72405 100644 (file)
@@ -187,18 +187,12 @@ int _cryptoOperation(cryptoFn operation,
        const CKM::CryptoAlgorithm *ca = reinterpret_cast<const CKM::CryptoAlgorithm *>
                                                                         (params);
 
-       // password
-       CKM::Password pass;
-
-       if (password)
-               pass = password;
-
        // buffers
        CKM::RawBuffer inBuffer(in.data, in.data + in.size);
        CKM::RawBuffer outBuffer;
 
        auto mgr = CKM::Manager::create();
-       int ret = ((*mgr).*operation)(*ca, key_alias, pass, inBuffer, outBuffer);
+       int ret = ((*mgr).*operation)(*ca, key_alias, _tostring(password), inBuffer, outBuffer);
 
        if (ret != CKM_API_SUCCESS)
                return to_ckmc_error(ret);
@@ -995,3 +989,29 @@ int ckmc_decrypt_data(ckmc_param_list_h params,
 
        EXCEPTION_GUARD_END
 }
+
+KEY_MANAGER_CAPI
+int ckmc_key_derive(const ckmc_param_list_h params,
+                                       const char *secret_alias,
+                                       const char *secret_password,
+                                       const char *new_key_alias,
+                                       ckmc_policy_s new_key_policy)
+{
+       if (secret_alias == nullptr || new_key_alias == nullptr || params == nullptr)
+               return CKMC_ERROR_INVALID_PARAMETER;
+
+       EXCEPTION_GUARD_START_CAPI
+
+       // params
+       const CKM::CryptoAlgorithm *ca = reinterpret_cast<const CKM::CryptoAlgorithm *>
+                                                                        (params);
+
+       auto mgr = CKM::Manager::create();
+       return to_ckmc_error(mgr->deriveKey(*ca,
+                                                                               CKM::Alias(secret_alias),
+                                                                               _tostring(secret_password),
+                                                                               CKM::Alias(new_key_alias),
+                                                                               _toCkmPolicy(new_key_policy)));
+
+       EXCEPTION_GUARD_END
+}
index a4905dc..08d4157 100644 (file)
@@ -739,4 +739,24 @@ int Manager::Impl::decrypt(const CryptoAlgorithm &algo,
                                 decrypted);
 }
 
+int Manager::Impl::deriveKey(const CryptoAlgorithm &algo,
+                                                        const Alias &secretAlias,
+                                                        const Password &secretPassword,
+                                                        const Alias &newKeyAlias,
+                                                        const Policy &newKeyPolicy)
+{
+       EXCEPTION_GUARD_START_CPPAPI
+
+       AliasSupport secret(secretAlias);
+       AliasSupport newKey(newKeyAlias);
+       CryptoAlgorithmSerializable cas(algo);
+
+       return Request(*this, LogicCommand::DERIVE, m_storageConnection,
+                       cas, secret.getName(), secret.getOwner(), secretPassword,
+                       newKey.getName(), newKey.getOwner(), PolicySerializable(newKeyPolicy)
+               ).maybeDeserialize();
+
+       EXCEPTION_GUARD_END
+}
+
 } // namespace CKM
index 133ac08..6371bfe 100644 (file)
@@ -135,6 +135,13 @@ public:
                                const RawBuffer &encrypted,
                                RawBuffer &decrypted);
 
+       int deriveKey(const CryptoAlgorithm &algo,
+                                 const Alias &secretAlias,
+                                 const Password &secretPassword,
+                                 const Alias &newKeyAlias,
+                                 const Policy &newKeyPolicy);
+
+
 private:
        int saveBinaryData(
                const Alias &alias,
index 7155ea9..45cc796 100644 (file)
@@ -285,6 +285,15 @@ int Manager::decrypt(
        return m_impl->decrypt(algo, keyAlias, password, encrypted, decrypted);
 }
 
+int Manager::deriveKey(const CryptoAlgorithm &algo,
+                                          const Alias &secretAlias,
+                                          const Password &secretPassword,
+                                          const Alias &newKeyAlias,
+                                          const Policy &newKeyPolicy)
+{
+       return m_impl->deriveKey(algo, secretAlias, secretPassword, newKeyAlias, newKeyPolicy);
+}
+
 ManagerShPtr Manager::create()
 {
        try {
index a429daf..6a762a7 100644 (file)
@@ -195,6 +195,10 @@ CryptoAlgorithmSerializable::CryptoAlgorithmSerializable(IStream &stream)
                case ParamName::ED_IV:
                case ParamName::ED_AAD:
                case ParamName::ED_LABEL:
+               case ParamName::KBKDF_LABEL:
+               case ParamName::KBKDF_CONTEXT:
+               case ParamName::KBKDF_FIXED_INPUT:
+               case ParamName::ECDH_PUBKEY:
                        Deserializer<RawBuffer>::Deserialize(stream, buffer);
                        setParam(name, buffer);
                        break;
@@ -206,6 +210,13 @@ CryptoAlgorithmSerializable::CryptoAlgorithmSerializable(IStream &stream)
                case ParamName::GEN_EC:
                case ParamName::SV_HASH_ALGO:
                case ParamName::SV_RSA_PADDING:
+               case ParamName::KDF_LEN:
+               case ParamName::KDF_PRF:
+               case ParamName::KBKDF_MODE:
+               case ParamName::KBKDF_RLEN:
+               case ParamName::KBKDF_LLEN:
+               case ParamName::KBKDF_COUNTER_LOCATION:
+               case ParamName::KBKDF_NO_SEPARATOR:
                        Deserializer<uint64_t>::Deserialize(stream, integer);
                        setParam(name, integer);
                        break;
index 9e03f18..8796e5b 100644 (file)
@@ -66,7 +66,8 @@ enum class LogicCommand : int {
        SET_PERMISSION,
        SAVE_PKCS12,
        GET_PKCS12,
-       GET_PROTECTION_STATUS
+       GET_PROTECTION_STATUS,
+       DERIVE
 };
 
 enum class EncryptionCommand : int {
index b7a43c4..4763878 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <generic-backend/exception.h>
 #include <crypto-backend.h>
+#include <token.h>
 
 namespace CKM {
 namespace Crypto {
@@ -62,6 +63,11 @@ public:
                ThrowErr(Exc::Crypto::OperationNotSupported);
        }
 
+       virtual Token derive(const CryptoAlgorithm &, const Password &, const RawBuffer &)
+       {
+               ThrowErr(Exc::Crypto::OperationNotSupported);
+       }
+
        virtual ~GObj()
        {
        }
index c14998f..7961458 100644 (file)
@@ -57,6 +57,11 @@ AlgoType key2algo(DataType type)
 
 } // namespace anonymous
 
+Token BData::derive(const CryptoAlgorithm &, const Password &, const RawBuffer &)
+{
+       return Token();
+}
+
 RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
 {
        return Internals::symmetricEncrypt(getBinary(), alg, data);
@@ -119,6 +124,11 @@ RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
        return Internals::asymmetricDecrypt(getEvpShPtr(), alg, data);
 }
 
+Token AKey::derive(const CryptoAlgorithm &, const Password &, const RawBuffer &)
+{
+       return Token();
+}
+
 EvpShPtr AKey::getEvpShPtr()
 {
        if (m_evp)
index a00a478..ffb8231 100644 (file)
@@ -43,6 +43,7 @@ public:
        {
                return m_raw;
        }
+       Token derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) override;
 
 protected:
        RawBuffer m_raw;
@@ -69,6 +70,7 @@ public:
                   const RawBuffer &sign) override;
        RawBuffer encrypt(const CryptoAlgorithm &, const RawBuffer &) override;
        RawBuffer decrypt(const CryptoAlgorithm &, const RawBuffer &) override;
+       Token derive(const CryptoAlgorithm &, const Password &, const RawBuffer &) override;
 
 protected:
        virtual EvpShPtr getEvpShPtr();
index 99418ef..bb07985 100644 (file)
@@ -1514,5 +1514,44 @@ RawBuffer CKMLogic::setPermission(
        }));
 }
 
+RawBuffer CKMLogic::deriveKey(
+       const Credentials &cred,
+       const int msgID,
+       const CryptoAlgorithm &params,
+       const Name &secretName,
+       const ClientId &secretOwner,
+       const Password &secretPassword,
+       const Name &newKeyName,
+       const ClientId &newKeyOwner,
+       const Policy &newKeyPolicy)
+{
+       return SerializeMessage(msgID, tryRet([&] {
+               // Get key/secret for internal service use. It won't be exported to the client
+               Crypto::GObjUPtr obj;
+               int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
+                                                                        secretName, secretOwner, secretPassword, obj);
+               if (retCode != CKM_API_SUCCESS) {
+                       if (retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
+                               return retCode;
+
+                       retCode = readDataHelper(false, cred, DataType::BINARY_DATA,
+                                                                        secretName, secretOwner, secretPassword, obj);
+                       if (retCode != CKM_API_SUCCESS)
+                               return retCode;
+               }
+
+               auto [dbOp, digest, ret] = beginSaveAndGetHash(cred, newKeyName, newKeyOwner);
+               if (ret != CKM_API_SUCCESS)
+                       return ret;
+
+               // derive
+               Token derived = obj->derive(params, newKeyPolicy.password, digest);
+
+               dbOp.finalize(std::move(derived), newKeyPolicy);
+
+               return CKM_API_SUCCESS;
+       }));
+}
+
 } // namespace CKM
 
index 4e77ad6..58d0700 100644 (file)
@@ -191,6 +191,17 @@ public:
                const ClientId &accessor,
                const PermissionMask permissionMask);
 
+       RawBuffer deriveKey(
+               const Credentials &cred,
+               const int msgID,
+               const CryptoAlgorithm &params,
+               const Name &secretName,
+               const ClientId &secretOwner,
+               const Password &secretPassword,
+               const Name &newKeyName,
+               const ClientId &newKeyOwner,
+               const Policy &newKeyPolicy);
+
        int setPermissionHelper(
                const Credentials &cred,
                const Name &name,
index d7e5d00..27c90ad 100644 (file)
@@ -431,6 +431,33 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer)
                                   permissionMask);
        }
 
+       case LogicCommand::DERIVE: {
+               CryptoAlgorithmSerializable keyDerivationAlgorithm;
+               Name secretName;
+               ClientId secretExplicitOwner;
+               Password secretPassword;
+               Name newKeyName;
+               ClientId newKeyExplicitOwner;
+               PolicySerializable newKeyPolicy;
+               buffer.Deserialize(keyDerivationAlgorithm,
+                                                  secretName,
+                                                  secretExplicitOwner,
+                                                  secretPassword,
+                                                  newKeyName,
+                                                  newKeyExplicitOwner,
+                                                  newKeyPolicy);
+               return m_logic->deriveKey(
+                       cred,
+                       msgId,
+                       keyDerivationAlgorithm,
+                       secretName,
+                       cred.effectiveOwner(secretExplicitOwner),
+                       secretPassword,
+                       newKeyName,
+                       cred.effectiveOwner(newKeyExplicitOwner),
+                       newKeyPolicy);
+       }
+
        default:
                Throw(Exception::BrokenProtocol);
        }