From 25942910ab57b32f73d9c56d8c6cf07c7cf98c49 Mon Sep 17 00:00:00 2001 From: hemanth-silabs <50145824+hemanth-silabs@users.noreply.github.com> Date: Wed, 26 Apr 2023 10:18:53 +0530 Subject: [PATCH] [crypto] allow key reference usage for ECDSA (#8961) Add new class to handle ECDSA using key refs. Update SRP to use key refs. --- include/openthread/instance.h | 2 +- include/openthread/platform/crypto.h | 98 ++++++++++++++++++++++-- src/core/common/instance.cpp | 12 +++ src/core/crypto/crypto_platform.cpp | 47 ++++++++++++ src/core/crypto/ecdsa.hpp | 110 +++++++++++++++++++++++++++ src/core/crypto/storage.cpp | 13 +++- src/core/crypto/storage.hpp | 26 +++++-- src/core/mac/mac.hpp | 6 ++ src/core/mac/mac_types.cpp | 2 +- src/core/mac/mac_types.hpp | 2 +- src/core/mac/sub_mac.hpp | 11 +++ src/core/net/srp_client.cpp | 42 ++++++++++ src/core/net/srp_client.hpp | 54 ++++++++----- src/core/thread/key_manager.cpp | 13 +++- src/core/thread/key_manager.hpp | 24 ++++-- tests/unit/test_platform.cpp | 37 +++++++++ 16 files changed, 451 insertions(+), 48 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 852246802..16e26126c 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (310) +#define OPENTHREAD_API_VERSION (311) /** * @addtogroup api-instance diff --git a/include/openthread/platform/crypto.h b/include/openthread/platform/crypto.h index 69253bb0d..0bccc38b8 100644 --- a/include/openthread/platform/crypto.h +++ b/include/openthread/platform/crypto.h @@ -60,9 +60,10 @@ extern "C" { */ typedef enum { - OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data. - OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES. - OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC. + OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data. + OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES. + OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC. + OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA. } otCryptoKeyType; /** @@ -74,6 +75,7 @@ typedef enum OT_CRYPTO_KEY_ALG_VENDOR, ///< Key Algorithm: Vendor Defined. OT_CRYPTO_KEY_ALG_AES_ECB, ///< Key Algorithm: AES ECB. OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256. + OT_CRYPTO_KEY_ALG_ECDSA, ///< Key Algorithm: ECDSA. } otCryptoKeyAlgorithm; /** @@ -82,11 +84,12 @@ typedef enum */ enum { - OT_CRYPTO_KEY_USAGE_NONE = 0, ///< Key Usage: Key Usage is empty. - OT_CRYPTO_KEY_USAGE_EXPORT = 1 << 0, ///< Key Usage: Key can be exported. - OT_CRYPTO_KEY_USAGE_ENCRYPT = 1 << 1, ///< Key Usage: Encryption (vendor defined). - OT_CRYPTO_KEY_USAGE_DECRYPT = 1 << 2, ///< Key Usage: AES ECB. - OT_CRYPTO_KEY_USAGE_SIGN_HASH = 1 << 3, ///< Key Usage: HMAC SHA-256. + OT_CRYPTO_KEY_USAGE_NONE = 0, ///< Key Usage: Key Usage is empty. + OT_CRYPTO_KEY_USAGE_EXPORT = 1 << 0, ///< Key Usage: Key can be exported. + OT_CRYPTO_KEY_USAGE_ENCRYPT = 1 << 1, ///< Key Usage: Encryption (vendor defined). + OT_CRYPTO_KEY_USAGE_DECRYPT = 1 << 2, ///< Key Usage: AES ECB. + OT_CRYPTO_KEY_USAGE_SIGN_HASH = 1 << 3, ///< Key Usage: Sign Hash. + OT_CRYPTO_KEY_USAGE_VERIFY_HASH = 1 << 4, ///< Key Usage: Verify Hash. }; /** @@ -650,6 +653,85 @@ otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey, const otPlatCryptoSha256Hash *aHash, const otPlatCryptoEcdsaSignature *aSignature); +/** + * Calculate the ECDSA signature for a hashed message using the Key reference passed. + * + * This method uses the deterministic digital signature generation procedure from RFC 6979. + * + * @param[in] aKeyRef Key Reference to the slot where the key-pair is stored. + * @param[in] aHash A pointer to a SHA-256 hash structure where the hash value for signature calculation + * is stored. + * @param[out] aSignature A pointer to an ECDSA signature structure to output the calculated signature. + * + * @retval OT_ERROR_NONE The signature was calculated successfully, @p aSignature was updated. + * @retval OT_ERROR_PARSE The key-pair DER format could not be parsed (invalid format). + * @retval OT_ERROR_NO_BUFS Failed to allocate buffer for signature calculation. + * @retval OT_ERROR_INVALID_ARGS The @p aContext is NULL. + * + * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled. + * + */ +otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef, + const otPlatCryptoSha256Hash *aHash, + otPlatCryptoEcdsaSignature *aSignature); + +/** + * Get the associated public key from the key reference passed. + * + * The public key is stored differently depending on the crypto backend library being used + * (OPENTHREAD_CONFIG_CRYPTO_LIB). + * + * This API must make sure to return the public key as a byte sequence representation of an + * uncompressed curve point (RFC 6605 - sec 4) + * + * @param[in] aKeyRef Key Reference to the slot where the key-pair is stored. + * @param[out] aPublicKey A pointer to an ECDSA public key structure to store the public key. + * + * @retval OT_ERROR_NONE Public key was retrieved successfully, and @p aBuffer is updated. + * @retval OT_ERROR_PARSE The key-pair DER format could not be parsed (invalid format). + * @retval OT_ERROR_INVALID_ARGS The @p aContext is NULL. + * + * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled. + * + */ +otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey); + +/** + * Generate and import a new ECDSA key-pair at reference passed. + * + * @param[in] aKeyRef Key Reference to the slot where the key-pair is stored. + * + * @retval OT_ERROR_NONE A new key-pair was generated successfully. + * @retval OT_ERROR_NO_BUFS Failed to allocate buffer for key generation. + * @retval OT_ERROR_NOT_CAPABLE Feature not supported. + * @retval OT_ERROR_FAILED Failed to generate key-pair. + * + * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled. + * + */ +otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef); + +/** + * Use the keyref to verify the ECDSA signature of a hashed message. + * + * @param[in] aKeyRef Key Reference to the slot where the key-pair is stored. + * @param[in] aHash A pointer to a SHA-256 hash structure where the hash value for signature verification + * is stored. + * @param[in] aSignature A pointer to an ECDSA signature structure where the signature value to be verified is + * stored. + * + * @retval OT_ERROR_NONE The signature was verified successfully. + * @retval OT_ERROR_SECURITY The signature is invalid. + * @retval OT_ERROR_INVALID_ARGS The key or hash is invalid. + * @retval OT_ERROR_NO_BUFS Failed to allocate buffer for signature verification. + * + * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled. + * + */ +otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef, + const otPlatCryptoSha256Hash *aHash, + const otPlatCryptoEcdsaSignature *aSignature); + /** * Perform PKCS#5 PBKDF2 using CMAC (AES-CMAC-PRF-128). * diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp index 294fc4a71..94b905076 100644 --- a/src/core/common/instance.cpp +++ b/src/core/common/instance.cpp @@ -345,6 +345,10 @@ void Instance::Finalize(void) IgnoreError(otIp6SetEnabled(this, false)); IgnoreError(otLinkSetEnabled(this, false)); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Get().DestroyTemporaryKeys(); +#endif + Get().Deinit(); #endif @@ -369,6 +373,10 @@ exit: void Instance::FactoryReset(void) { Get().Wipe(); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Get().DestroyTemporaryKeys(); + Get().DestroyPersistentKeys(); +#endif otPlatReset(this); } @@ -378,6 +386,10 @@ Error Instance::ErasePersistentInfo(void) VerifyOrExit(Get().IsDisabled(), error = kErrorInvalidState); Get().Wipe(); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Get().DestroyTemporaryKeys(); + Get().DestroyPersistentKeys(); +#endif exit: return error; diff --git a/src/core/crypto/crypto_platform.cpp b/src/core/crypto/crypto_platform.cpp index bfb33ec0d..a8da82e95 100644 --- a/src/core/crypto/crypto_platform.cpp +++ b/src/core/crypto/crypto_platform.cpp @@ -662,6 +662,53 @@ exit: #endif // #if !OPENTHREAD_RADIO +#elif OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA + +#if !OPENTHREAD_RADIO +#if OPENTHREAD_CONFIG_ECDSA_ENABLE + +OT_TOOL_WEAK otError otPlatCryptoEcdsaGenerateKey(otPlatCryptoEcdsaKeyPair *aKeyPair) +{ + OT_UNUSED_VARIABLE(aKeyPair); + + return OT_ERROR_NOT_CAPABLE; +} + +OT_TOOL_WEAK otError otPlatCryptoEcdsaGetPublicKey(const otPlatCryptoEcdsaKeyPair *aKeyPair, + otPlatCryptoEcdsaPublicKey *aPublicKey) +{ + OT_UNUSED_VARIABLE(aKeyPair); + OT_UNUSED_VARIABLE(aPublicKey); + + return OT_ERROR_NOT_CAPABLE; +} + +OT_TOOL_WEAK otError otPlatCryptoEcdsaSign(const otPlatCryptoEcdsaKeyPair *aKeyPair, + const otPlatCryptoSha256Hash *aHash, + otPlatCryptoEcdsaSignature *aSignature) +{ + OT_UNUSED_VARIABLE(aKeyPair); + OT_UNUSED_VARIABLE(aHash); + OT_UNUSED_VARIABLE(aSignature); + + return OT_ERROR_NOT_CAPABLE; +} + +OT_TOOL_WEAK otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey, + const otPlatCryptoSha256Hash *aHash, + const otPlatCryptoEcdsaSignature *aSignature) + +{ + OT_UNUSED_VARIABLE(aPublicKey); + OT_UNUSED_VARIABLE(aHash); + OT_UNUSED_VARIABLE(aSignature); + + return OT_ERROR_NOT_CAPABLE; +} +#endif // #if OPENTHREAD_CONFIG_ECDSA_ENABLE + +#endif // #if !OPENTHREAD_RADIO + #endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/core/crypto/ecdsa.hpp b/src/core/crypto/ecdsa.hpp index e75708349..41a693d7d 100644 --- a/src/core/crypto/ecdsa.hpp +++ b/src/core/crypto/ecdsa.hpp @@ -46,6 +46,7 @@ #include "common/error.hpp" #include "crypto/sha256.hpp" +#include "crypto/storage.hpp" namespace ot { namespace Crypto { @@ -77,6 +78,9 @@ public: class PublicKey; class KeyPair; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + class KeyPairAsRef; +#endif /** * This class represents an ECDSA signature. @@ -90,6 +94,9 @@ public: { friend class KeyPair; friend class PublicKey; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + friend class KeyPairAsRef; +#endif public: static constexpr uint8_t kSize = OT_CRYPTO_ECDSA_SIGNATURE_SIZE; ///< Signature size in bytes. @@ -204,6 +211,105 @@ public: } }; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + /** + * This class represents a key pair (public and private keys) as a PSA KeyRef. + * + */ + class KeyPairAsRef + { + public: + /** + * This constructor initializes a `KeyPairAsRef`. + * + * @param[in] aKeyRef PSA key reference to use while using the keypair. + */ + explicit KeyPairAsRef(otCryptoKeyRef aKeyRef = 0) { mKeyRef = aKeyRef; } + + /** + * This method generates a new keypair and imports it into PSA ITS. + * + * @retval kErrorNone A new key pair was generated successfully. + * @retval kErrorNoBufs Failed to allocate buffer for key generation. + * @retval kErrorNotCapable Feature not supported. + * @retval kErrorFailed Failed to generate key. + * + */ + Error Generate(void) const { return otPlatCryptoEcdsaGenerateAndImportKey(mKeyRef); } + + /** + * This method imports a new keypair into PSA ITS. + * + * @param[in] aKeyPair KeyPair to be imported in DER format. + * + * @retval kErrorNone A key pair was imported successfully. + * @retval kErrorNotCapable Feature not supported. + * @retval kErrorFailed Failed to import the key. + * + */ + Error ImportKeyPair(const KeyPair &aKeyPair) + { + return Crypto::Storage::ImportKey(mKeyRef, Storage::kKeyTypeEcdsa, Storage::kKeyAlgorithmEcdsa, + (Storage::kUsageSignHash | Storage::kUsageVerifyHash), + Storage::kTypePersistent, aKeyPair.GetDerBytes(), + aKeyPair.GetDerLength()); + } + + /** + * This method gets the associated public key from the keypair referenced by mKeyRef. + * + * @param[out] aPublicKey A reference to a `PublicKey` to output the value. + * + * @retval kErrorNone Public key was retrieved successfully, and @p aPublicKey is updated. + * @retval kErrorFailed There was a error exporting the public key from PSA. + * + */ + Error GetPublicKey(PublicKey &aPublicKey) const + { + return otPlatCryptoEcdsaExportPublicKey(mKeyRef, &aPublicKey); + } + + /** + * This method calculates the ECDSA signature for a hashed message using the private key from keypair + * referenced by mKeyRef. + * + * This method uses the deterministic digital signature generation procedure from RFC 6979. + * + * @param[in] aHash The SHA-256 hash value of the message to use for signature calculation. + * @param[out] aSignature A reference to a `Signature` to output the calculated signature value. + * + * @retval kErrorNone The signature was calculated successfully and @p aSignature was updated. + * @retval kErrorParse The key-pair DER format could not be parsed (invalid format). + * @retval kErrorInvalidArgs The @p aHash is invalid. + * @retval kErrorNoBufs Failed to allocate buffer for signature calculation. + * + */ + Error Sign(const Sha256::Hash &aHash, Signature &aSignature) const + { + return otPlatCryptoEcdsaSignUsingKeyRef(mKeyRef, &aHash, &aSignature); + } + + /** + * This method gets the Key reference for the keypair stored in the PSA. + * + * @returns The PSA key ref. + * + */ + otCryptoKeyRef GetKeyRef(void) const { return mKeyRef; } + + /** + * This method sets the Key reference. + * + * @param[in] aKeyRef PSA key reference to use while using the keypair. + * + */ + void SetKeyRef(otCryptoKeyRef aKeyRef) { mKeyRef = aKeyRef; } + + private: + otCryptoKeyRef mKeyRef; + }; +#endif + /** * This class represents a public key. * @@ -214,6 +320,9 @@ public: class PublicKey : public otPlatCryptoEcdsaPublicKey, public Equatable { friend class KeyPair; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + friend class KeyPairAsRef; +#endif public: static constexpr uint8_t kSize = OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE; ///< Size of the public key in bytes. @@ -242,6 +351,7 @@ public: { return otPlatCryptoEcdsaVerify(this, &aHash, &aSignature); } + } OT_TOOL_PACKED_END; }; diff --git a/src/core/crypto/storage.cpp b/src/core/crypto/storage.cpp index b9301fc35..726daa930 100644 --- a/src/core/crypto/storage.cpp +++ b/src/core/crypto/storage.cpp @@ -41,7 +41,7 @@ namespace Crypto { #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE Error Key::ExtractKey(uint8_t *aKeyBuffer, uint16_t &aKeyLength) const { - Error error; + Error error = kErrorNone; size_t readKeyLength; OT_ASSERT(IsKeyRef()); @@ -55,6 +55,17 @@ Error Key::ExtractKey(uint8_t *aKeyBuffer, uint16_t &aKeyLength) const exit: return error; } + +void Storage::DestroyPersistentKeys(void) +{ + DestroyKey(kNetworkKeyRef); + DestroyKey(kPskcRef); + DestroyKey(kActiveDatasetNetworkKeyRef); + DestroyKey(kActiveDatasetPskcRef); + DestroyKey(kPendingDatasetNetworkKeyRef); + DestroyKey(kPendingDatasetPskcRef); + DestroyKey(kEcdsaRef); +} #endif LiteralKey::LiteralKey(const Key &aKey) diff --git a/src/core/crypto/storage.hpp b/src/core/crypto/storage.hpp index e7189e09f..8193943fb 100644 --- a/src/core/crypto/storage.hpp +++ b/src/core/crypto/storage.hpp @@ -57,9 +57,10 @@ namespace Storage { */ enum KeyType : uint8_t { - kKeyTypeRaw = OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data. - kKeyTypeAes = OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES. - kKeyTypeHmac = OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC. + kKeyTypeRaw = OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data. + kKeyTypeAes = OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES. + kKeyTypeHmac = OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC. + kKeyTypeEcdsa = OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA. }; /** @@ -71,13 +72,15 @@ enum KeyAlgorithm : uint8_t kKeyAlgorithmVendor = OT_CRYPTO_KEY_ALG_VENDOR, ///< Key Algorithm: Vendor Defined. kKeyAlgorithmAesEcb = OT_CRYPTO_KEY_ALG_AES_ECB, ///< Key Algorithm: AES ECB. kKeyAlgorithmHmacSha256 = OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256. + kKeyAlgorithmEcdsa = OT_CRYPTO_KEY_ALG_ECDSA, ///< Key Algorithm: ECDSA. }; -constexpr uint8_t kUsageNone = OT_CRYPTO_KEY_USAGE_NONE; ///< Key Usage: Key Usage is empty. -constexpr uint8_t kUsageExport = OT_CRYPTO_KEY_USAGE_EXPORT; ///< Key Usage: Key can be exported. -constexpr uint8_t kUsageEncrypt = OT_CRYPTO_KEY_USAGE_ENCRYPT; ///< Key Usage: Encrypt (vendor defined). -constexpr uint8_t kUsageDecrypt = OT_CRYPTO_KEY_USAGE_DECRYPT; ///< Key Usage: AES ECB. -constexpr uint8_t kUsageSignHash = OT_CRYPTO_KEY_USAGE_SIGN_HASH; ///< Key Usage: HMAC SHA-256. +constexpr uint8_t kUsageNone = OT_CRYPTO_KEY_USAGE_NONE; ///< Key Usage: Key Usage is empty. +constexpr uint8_t kUsageExport = OT_CRYPTO_KEY_USAGE_EXPORT; ///< Key Usage: Key can be exported. +constexpr uint8_t kUsageEncrypt = OT_CRYPTO_KEY_USAGE_ENCRYPT; ///< Key Usage: Encrypt (vendor defined). +constexpr uint8_t kUsageDecrypt = OT_CRYPTO_KEY_USAGE_DECRYPT; ///< Key Usage: AES ECB. +constexpr uint8_t kUsageSignHash = OT_CRYPTO_KEY_USAGE_SIGN_HASH; ///< Key Usage: Sign Hash. +constexpr uint8_t kUsageVerifyHash = OT_CRYPTO_KEY_USAGE_VERIFY_HASH; ///< Key Usage: Verify Hash. /** * This enumeration defines the key storage types. @@ -102,6 +105,7 @@ constexpr KeyRef kActiveDatasetNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OF constexpr KeyRef kActiveDatasetPskcRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 4; constexpr KeyRef kPendingDatasetNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 5; constexpr KeyRef kPendingDatasetPskcRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 6; +constexpr KeyRef kEcdsaRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 7; /** * Determine if a given `KeyRef` is valid or not. @@ -186,6 +190,12 @@ inline void DestroyKey(KeyRef aKeyRef) */ inline bool HasKey(KeyRef aKeyRef) { return otPlatCryptoHasKey(aKeyRef); } +/** + * Delete all the persistent keys stored in PSA ITS. + * + */ +void DestroyPersistentKeys(void); + } // namespace Storage #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index dc0fd7b58..d30b223a4 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -587,6 +587,12 @@ public: */ bool IsEnabled(void) const { return mEnabled; } + /** + * This method clears the Mode2Key stored in PSA ITS. + * + */ + void ClearMode2Key(void) { mMode2KeyMaterial.Clear(); } + #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE /** * This method gets the CSL channel. diff --git a/src/core/mac/mac_types.cpp b/src/core/mac/mac_types.cpp index 83fab4ba9..7ed4b1b31 100644 --- a/src/core/mac/mac_types.cpp +++ b/src/core/mac/mac_types.cpp @@ -299,7 +299,7 @@ void KeyMaterial::SetFrom(const Key &aKey, bool aIsExportable) #endif } -void KeyMaterial::ExtractKey(Key &aKey) +void KeyMaterial::ExtractKey(Key &aKey) const { #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE aKey.Clear(); diff --git a/src/core/mac/mac_types.hpp b/src/core/mac/mac_types.hpp index 9ee73986c..6a73244d2 100644 --- a/src/core/mac/mac_types.hpp +++ b/src/core/mac/mac_types.hpp @@ -540,7 +540,7 @@ public: * @param[out] aKey A reference to the output the key. * */ - void ExtractKey(Key &aKey); + void ExtractKey(Key &aKey) const; /** * This method converts `KeyMaterial` to a `Crypto::Key`. diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp index a148b7405..e56321058 100644 --- a/src/core/mac/sub_mac.hpp +++ b/src/core/mac/sub_mac.hpp @@ -477,6 +477,17 @@ public: */ const KeyMaterial &GetNextMacKey(void) const { return mNextKey; } + /** + * This method clears the stored MAC keys. + * + */ + void ClearMacKeys(void) + { + mPrevKey.Clear(); + mCurrKey.Clear(); + mNextKey.Clear(); + } + /** * This method returns the current MAC frame counter value. * diff --git a/src/core/net/srp_client.cpp b/src/core/net/srp_client.cpp index 6335bdc4a..4a6bee3ab 100644 --- a/src/core/net/srp_client.cpp +++ b/src/core/net/srp_client.cpp @@ -835,7 +835,12 @@ Error Client::PrepareUpdateMessage(Message &aMessage) info.Clear(); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + info.mKeyRef.SetKeyRef(kSrpEcdsaKeyRef); + SuccessOrExit(error = ReadOrGenerateKey(info.mKeyRef)); +#else SuccessOrExit(error = ReadOrGenerateKey(info.mKeyPair)); +#endif // Generate random Message ID and ensure it is different from last one do @@ -885,6 +890,34 @@ exit: return error; } +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +Error Client::ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPairAsRef &aKeyRef) +{ + Error error = kErrorNone; + Crypto::Ecdsa::P256::KeyPair keyPair; + + VerifyOrExit(!Crypto::Storage::HasKey(aKeyRef.GetKeyRef())); + error = Get().Read(keyPair); + + if (error == kErrorNone) + { + Crypto::Ecdsa::P256::PublicKey publicKey; + + if (keyPair.GetPublicKey(publicKey) == kErrorNone) + { + SuccessOrExit(error = aKeyRef.ImportKeyPair(keyPair)); + IgnoreError(Get().Delete()); + ExitNow(); + } + IgnoreError(Get().Delete()); + } + + error = aKeyRef.Generate(); + +exit: + return error; +} +#else Error Client::ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair) { Error error; @@ -907,6 +940,7 @@ Error Client::ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair) exit: return error; } +#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE Error Client::AppendServiceInstructions(Message &aMessage, Info &aInfo) { @@ -1281,7 +1315,11 @@ Error Client::AppendKeyRecord(Message &aMessage, Info &aInfo) const key.SetAlgorithm(Dns::KeyRecord::kAlgorithmEcdsaP256Sha256); key.SetLength(sizeof(Dns::KeyRecord) - sizeof(Dns::ResourceRecord) + sizeof(Crypto::Ecdsa::P256::PublicKey)); SuccessOrExit(error = aMessage.Append(key)); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrExit(error = aInfo.mKeyRef.GetPublicKey(publicKey)); +#else SuccessOrExit(error = aInfo.mKeyPair.GetPublicKey(publicKey)); +#endif SuccessOrExit(error = aMessage.Append(publicKey)); aInfo.mRecordCount++; @@ -1418,7 +1456,11 @@ Error Client::AppendSignature(Message &aMessage, Info &aInfo) sha256.Update(aMessage, 0, offset); sha256.Finish(hash); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrExit(error = aInfo.mKeyRef.Sign(hash, signature)); +#else SuccessOrExit(error = aInfo.mKeyPair.Sign(hash, signature)); +#endif // Move back in message and append SIG RR now with compressed host // name (as signer's name) along with the calculated signature. diff --git a/src/core/net/srp_client.hpp b/src/core/net/srp_client.hpp index 0b846cb56..992940cfd 100644 --- a/src/core/net/srp_client.hpp +++ b/src/core/net/srp_client.hpp @@ -794,6 +794,10 @@ private: // Number of fast data polls after SRP Update tx (11x 188ms = ~2 seconds) static constexpr uint8_t kFastPollsAfterUpdateTx = 11; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + static constexpr uint32_t kSrpEcdsaKeyRef = Crypto::Storage::kEcdsaRef; +#endif + #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE static constexpr uint8_t kMaxTimeoutFailuresToSwitchServer = OPENTHREAD_CONFIG_SRP_CLIENT_MAX_TIMEOUT_FAILURES_TO_SWITCH_SERVER; @@ -981,29 +985,37 @@ private: { static constexpr uint16_t kUnknownOffset = 0; // Unknown offset value (used when offset is not yet set). - uint16_t mDomainNameOffset; // Offset of domain name serialization - uint16_t mHostNameOffset; // Offset of host name serialization. - uint16_t mRecordCount; // Number of resource records in Update section. - Crypto::Ecdsa::P256::KeyPair mKeyPair; // The ECDSA key pair. + uint16_t mDomainNameOffset; // Offset of domain name serialization + uint16_t mHostNameOffset; // Offset of host name serialization. + uint16_t mRecordCount; // Number of resource records in Update section. +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Ecdsa::P256::KeyPairAsRef mKeyRef; // The ECDSA key ref for key-pair. +#else + Crypto::Ecdsa::P256::KeyPair mKeyPair; // The ECDSA key pair. +#endif }; - Error Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester); - void Stop(Requester aRequester, StopMode aMode); - void Resume(void); - void Pause(void); - void HandleNotifierEvents(Events aEvents); - void HandleRoleChanged(void); - Error UpdateHostInfoStateOnAddressChange(void); - void UpdateServiceStateToRemove(Service &aService); - State GetState(void) const { return mState; } - void SetState(State aState); - void ChangeHostAndServiceStates(const ItemState *aNewStates, ServiceStateChangeMode aMode); - void InvokeCallback(Error aError) const; - void InvokeCallback(Error aError, const HostInfo &aHostInfo, const Service *aRemovedServices) const; - void HandleHostInfoOrServiceChange(void); - void SendUpdate(void); - Error PrepareUpdateMessage(Message &aMessage); - Error ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair); + Error Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester); + void Stop(Requester aRequester, StopMode aMode); + void Resume(void); + void Pause(void); + void HandleNotifierEvents(Events aEvents); + void HandleRoleChanged(void); + Error UpdateHostInfoStateOnAddressChange(void); + void UpdateServiceStateToRemove(Service &aService); + State GetState(void) const { return mState; } + void SetState(State aState); + void ChangeHostAndServiceStates(const ItemState *aNewStates, ServiceStateChangeMode aMode); + void InvokeCallback(Error aError) const; + void InvokeCallback(Error aError, const HostInfo &aHostInfo, const Service *aRemovedServices) const; + void HandleHostInfoOrServiceChange(void); + void SendUpdate(void); + Error PrepareUpdateMessage(Message &aMessage); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Error ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPairAsRef &aKeyRef); +#else + Error ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair); +#endif Error AppendServiceInstructions(Message &aMessage, Info &aInfo); bool CanAppendService(const Service &aService); Error AppendServiceInstruction(Service &aService, Message &aMessage, Info &aInfo); diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp index 642688952..ddcbf74ef 100644 --- a/src/core/thread/key_manager.cpp +++ b/src/core/thread/key_manager.cpp @@ -284,7 +284,7 @@ exit: return; } -void KeyManager::ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys) +void KeyManager::ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys) const { Crypto::HmacSha256 hmac; uint8_t keySequenceBytes[sizeof(uint32_t)]; @@ -306,7 +306,7 @@ void KeyManager::ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys) } #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE -void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) +void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const { Crypto::HkdfSha256 hkdf; uint8_t salt[sizeof(uint32_t) + sizeof(kHkdfExtractSaltString)]; @@ -634,6 +634,15 @@ exit: return; } +void KeyManager::DestroyTemporaryKeys(void) +{ + mMleKey.Clear(); + mKek.Clear(); + Get().ClearMacKeys(); + Get().ClearMode2Key(); +} + +void KeyManager::DestroyPersistentKeys(void) { Crypto::Storage::DestroyPersistentKeys(); } #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE } // namespace ot diff --git a/src/core/thread/key_manager.hpp b/src/core/thread/key_manager.hpp index 4182aa918..7428301c9 100644 --- a/src/core/thread/key_manager.hpp +++ b/src/core/thread/key_manager.hpp @@ -254,7 +254,7 @@ public: * @returns A key reference to the Thread Network Key. * */ - NetworkKeyRef GetNetworkKeyRef(void) { return mNetworkKeyRef; } + NetworkKeyRef GetNetworkKeyRef(void) const { return mNetworkKeyRef; } /** * This method sets the Thread Network Key using Key Reference. @@ -299,7 +299,7 @@ public: * @returns A key reference to the PSKc. * */ - const PskcRef &GetPskcRef(void) { return mPskcRef; } + const PskcRef &GetPskcRef(void) const { return mPskcRef; } /** * This method sets the PSKc as a Key reference. @@ -545,11 +545,25 @@ public: * * This is called to indicate the @p aMacFrameCounter value is now used. * - * @param[in] aMacFrameCounter The 15.4 link MAC frame counter value. + * @param[in] aMacFrameCounter The 15.4 link MAC frame counter value. * */ void MacFrameCounterUsed(uint32_t aMacFrameCounter); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + /** + * This method destroys all the volatile mac keys stored in PSA ITS. + * + */ + void DestroyTemporaryKeys(void); + + /** + * This method destroys all the persistent keys stored in PSA ITS. + * + */ + void DestroyPersistentKeys(void); +#endif + private: static constexpr uint32_t kDefaultKeySwitchGuardTime = 624; static constexpr uint32_t kOneHourIntervalInMsec = 3600u * 1000u; @@ -571,10 +585,10 @@ private: const Mac::Key &GetMacKey(void) const { return mKeys.mMacKey; } }; - void ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys); + void ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys) const; #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE - void ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey); + void ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const; #endif void StartKeyRotationTimer(void); diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp index e2ef71986..54f51a14f 100644 --- a/tests/unit/test_platform.cpp +++ b/tests/unit/test_platform.cpp @@ -409,6 +409,43 @@ bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef) #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef) +{ + OT_UNUSED_VARIABLE(aKeyRef); + + return OT_ERROR_NONE; +} + +otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey) +{ + OT_UNUSED_VARIABLE(aKeyRef); + OT_UNUSED_VARIABLE(aPublicKey); + + return OT_ERROR_NONE; +} + +otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef, + const otPlatCryptoSha256Hash *aHash, + otPlatCryptoEcdsaSignature *aSignature) +{ + OT_UNUSED_VARIABLE(aKeyRef); + OT_UNUSED_VARIABLE(aHash); + OT_UNUSED_VARIABLE(aSignature); + + return OT_ERROR_NONE; +} + +otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef, + const otPlatCryptoSha256Hash *aHash, + const otPlatCryptoEcdsaSignature *aSignature) +{ + OT_UNUSED_VARIABLE(aKeyRef); + OT_UNUSED_VARIABLE(aHash); + OT_UNUSED_VARIABLE(aSignature); + + return OT_ERROR_NONE; +} + otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold) { OT_UNUSED_VARIABLE(aInstance);