diff --git a/Android.mk b/Android.mk index 7fd5c1bf4..bad1ea5c1 100644 --- a/Android.mk +++ b/Android.mk @@ -237,12 +237,14 @@ LOCAL_SRC_FILES := \ src/core/common/uptime.cpp \ src/core/crypto/aes_ccm.cpp \ src/core/crypto/aes_ecb.cpp \ + src/core/crypto/crypto_platform.cpp \ src/core/crypto/ecdsa.cpp \ src/core/crypto/hkdf_sha256.cpp \ src/core/crypto/hmac_sha256.cpp \ src/core/crypto/mbedtls.cpp \ src/core/crypto/pbkdf2_cmac.cpp \ src/core/crypto/sha256.cpp \ + src/core/crypto/storage.cpp \ src/core/diags/factory_diags.cpp \ src/core/mac/channel_mask.cpp \ src/core/mac/data_poll_handler.cpp \ diff --git a/examples/platforms/simulation/CMakeLists.txt b/examples/platforms/simulation/CMakeLists.txt index 74c13d0df..869a1ae61 100644 --- a/examples/platforms/simulation/CMakeLists.txt +++ b/examples/platforms/simulation/CMakeLists.txt @@ -59,6 +59,7 @@ set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE) add_library(openthread-simulation alarm.c + crypto.c diag.c entropy.c flash.c diff --git a/examples/platforms/simulation/Makefile.am b/examples/platforms/simulation/Makefile.am index 6a7724630..cdcad7a6d 100644 --- a/examples/platforms/simulation/Makefile.am +++ b/examples/platforms/simulation/Makefile.am @@ -41,6 +41,7 @@ libopenthread_simulation_a_CPPFLAGS = \ PLATFORM_SOURCES = \ alarm.c \ + crypto.c \ diag.c \ entropy.c \ flash.c \ diff --git a/examples/platforms/simulation/crypto.c b/examples/platforms/simulation/crypto.c new file mode 100644 index 000000000..36cf89be6 --- /dev/null +++ b/examples/platforms/simulation/crypto.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-simulation.h" + +#include +#include + +#include +#include + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + +// crypto key storage stubs + +otError otPlatCryptoImportKey(otCryptoKeyRef * aKeyRef, + otCryptoKeyType aKeyType, + otCryptoKeyAlgorithm aKeyAlgorithm, + int aKeyUsage, + otCryptoKeyStorage aKeyPersistence, + const uint8_t * aKey, + size_t aKeyLen) +{ + OT_UNUSED_VARIABLE(aKeyRef); + OT_UNUSED_VARIABLE(aKeyType); + OT_UNUSED_VARIABLE(aKeyAlgorithm); + OT_UNUSED_VARIABLE(aKeyUsage); + OT_UNUSED_VARIABLE(aKeyPersistence); + OT_UNUSED_VARIABLE(aKey); + OT_UNUSED_VARIABLE(aKeyLen); + + return OT_ERROR_NOT_IMPLEMENTED; +} + +otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t *aKeyLen) +{ + OT_UNUSED_VARIABLE(aKeyRef); + OT_UNUSED_VARIABLE(aBuffer); + OT_UNUSED_VARIABLE(aBufferLen); + OT_UNUSED_VARIABLE(aKeyLen); + + return OT_ERROR_NOT_IMPLEMENTED; +} + +otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef) +{ + OT_UNUSED_VARIABLE(aKeyRef); + + return OT_ERROR_NOT_IMPLEMENTED; +} + +bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef) +{ + OT_UNUSED_VARIABLE(aKeyRef); + + return false; +} + +#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE diff --git a/examples/platforms/simulation/radio.c b/examples/platforms/simulation/radio.c index 4bf353ae8..2faaa2f5f 100644 --- a/examples/platforms/simulation/radio.c +++ b/examples/platforms/simulation/radio.c @@ -149,11 +149,12 @@ otRadioCaps gRadioCaps = OT_RADIO_CAPS_NONE; #endif -static uint32_t sMacFrameCounter; -static uint8_t sKeyId; -static struct otMacKey sPrevKey; -static struct otMacKey sCurrKey; -static struct otMacKey sNextKey; +static uint32_t sMacFrameCounter; +static uint8_t sKeyId; +static otMacKeyMaterial sPrevKey; +static otMacKeyMaterial sCurrKey; +static otMacKeyMaterial sNextKey; +static otRadioKeyType sKeyType; static void ReverseExtAddress(otExtAddress *aReversed, const otExtAddress *aOrigin) { @@ -605,8 +606,8 @@ static otError radioProcessTransmitSecurity(otRadioFrame *aFrame) { otError error = OT_ERROR_NONE; #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 - struct otMacKey *key = NULL; - uint8_t keyId; + otMacKeyMaterial *key = NULL; + uint8_t keyId; otEXPECT(otMacFrameIsSecurityEnabled(aFrame) && otMacFrameIsKeyIdMode1(aFrame) && !aFrame->mInfo.mTxInfo.mIsSecurityProcessed); @@ -1195,22 +1196,24 @@ uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance) } #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE -void otPlatRadioSetMacKey(otInstance * aInstance, - uint8_t aKeyIdMode, - uint8_t aKeyId, - const otMacKey *aPrevKey, - const otMacKey *aCurrKey, - const otMacKey *aNextKey) +void otPlatRadioSetMacKey(otInstance * aInstance, + uint8_t aKeyIdMode, + uint8_t aKeyId, + const otMacKeyMaterial *aPrevKey, + const otMacKeyMaterial *aCurrKey, + const otMacKeyMaterial *aNextKey, + otRadioKeyType aKeyType) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aKeyIdMode); otEXPECT(aPrevKey != NULL && aCurrKey != NULL && aNextKey != NULL); - sKeyId = aKeyId; - memcpy(sPrevKey.m8, aPrevKey->m8, OT_MAC_KEY_SIZE); - memcpy(sCurrKey.m8, aCurrKey->m8, OT_MAC_KEY_SIZE); - memcpy(sNextKey.m8, aNextKey->m8, OT_MAC_KEY_SIZE); + sKeyId = aKeyId; + sKeyType = aKeyType; + memcpy(&sPrevKey, aPrevKey, sizeof(otMacKeyMaterial)); + memcpy(&sCurrKey, aCurrKey, sizeof(otMacKeyMaterial)); + memcpy(&sNextKey, aNextKey, sizeof(otMacKeyMaterial)); exit: return; diff --git a/include/Makefile.am b/include/Makefile.am index 6feb4469e..2d7273a2d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -96,6 +96,7 @@ dist_openthread_HEADERS = $(openthread_headers) ot_platform_headers = \ openthread/platform/alarm-micro.h \ openthread/platform/alarm-milli.h \ + openthread/platform/crypto.h \ openthread/platform/debug_uart.h \ openthread/platform/diag.h \ openthread/platform/entropy.h \ diff --git a/include/openthread/BUILD.gn b/include/openthread/BUILD.gn index 6a365fd9c..089c941f4 100644 --- a/include/openthread/BUILD.gn +++ b/include/openthread/BUILD.gn @@ -99,6 +99,7 @@ source_set("openthread") { "ping_sender.h", "platform/alarm-micro.h", "platform/alarm-milli.h", + "platform/crypto.h", "platform/debug_uart.h", "platform/diag.h", "platform/entropy.h", diff --git a/include/openthread/crypto.h b/include/openthread/crypto.h index ecde22e7a..a1a3d36ae 100644 --- a/include/openthread/crypto.h +++ b/include/openthread/crypto.h @@ -39,6 +39,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -78,23 +79,17 @@ typedef struct otCryptoSha256Hash otCryptoSha256Hash; * This function performs HMAC computation. * * @param[in] aKey A pointer to the key. - * @param[in] aKeyLength The key length in bytes. * @param[in] aBuf A pointer to the input buffer. * @param[in] aBufLength The length of @p aBuf in bytes. * @param[out] aHash A pointer to a `otCryptoSha256Hash` structure to output the hash value. * */ -void otCryptoHmacSha256(const uint8_t * aKey, - uint16_t aKeyLength, - const uint8_t * aBuf, - uint16_t aBufLength, - otCryptoSha256Hash *aHash); +void otCryptoHmacSha256(const otCryptoKey *aKey, const uint8_t *aBuf, uint16_t aBufLength, otCryptoSha256Hash *aHash); /** * This method performs AES CCM computation. * * @param[in] aKey A pointer to the key. - * @param[in] aKeyLength Length of the key in bytes. * @param[in] aTagLength Length of tag in bytes. * @param[in] aNonce A pointer to the nonce. * @param[in] aNonceLength Length of nonce in bytes. @@ -110,18 +105,17 @@ void otCryptoHmacSha256(const uint8_t * aKey, * @param[out] aTag A pointer to the tag. * */ -void otCryptoAesCcm(const uint8_t *aKey, - uint16_t aKeyLength, - uint8_t aTagLength, - const void * aNonce, - uint8_t aNonceLength, - const void * aHeader, - uint32_t aHeaderLength, - void * aPlainText, - void * aCipherText, - uint32_t aLength, - bool aEncrypt, - void * aTag); +void otCryptoAesCcm(const otCryptoKey *aKey, + uint8_t aTagLength, + const void * aNonce, + uint8_t aNonceLength, + const void * aHeader, + uint32_t aHeaderLength, + void * aPlainText, + void * aCipherText, + uint32_t aLength, + bool aEncrypt, + void * aTag); /** * This method creates ECDSA sign. diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h index b2d20979e..6e899b1b2 100644 --- a/include/openthread/dataset.h +++ b/include/openthread/dataset.h @@ -37,6 +37,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -70,6 +71,12 @@ struct otNetworkKey */ typedef struct otNetworkKey otNetworkKey; +/** + * This datatype represents KeyRef to NetworkKey. + * + */ +typedef otCryptoKeyRef otNetworkKeyRef; ///< Reference to Key + #define OT_NETWORK_NAME_MAX_SIZE 16 ///< Maximum size of the Thread Network Name field (bytes) /** @@ -127,6 +134,12 @@ struct otPskc */ typedef struct otPskc otPskc; +/** + * This datatype represents KeyRef to PSKc. + * + */ +typedef otCryptoKeyRef otPskcRef; ///< Reference to Key + /** * This structure represent Security Policy. * diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 786e807b8..08fb6fcff 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 (159) +#define OPENTHREAD_API_VERSION (160) /** * @addtogroup api-instance diff --git a/include/openthread/platform/crypto.h b/include/openthread/platform/crypto.h new file mode 100644 index 000000000..eb2791ad6 --- /dev/null +++ b/include/openthread/platform/crypto.h @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief + * This file includes the platform abstraction for Crypto operations. + */ + +#ifndef OPENTHREAD_PLATFORM_CRYPTO_H_ +#define OPENTHREAD_PLATFORM_CRYPTO_H_ + +#include +#include + +#include + +#ifdef OT_PLAT_CRYPTO_ATTRIBUTES_TYPE_HEADER +#include OT_PLAT_CRYPTO_ATTRIBUTES_TYPE_HEADER +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup plat-crypto + * + * @brief + * This module includes the platform abstraction for Crypto. + * + * @{ + * + */ + +/** + * This enumeration defines the key types. + * + */ +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. +} otCryptoKeyType; + +/** + * This enumeration defines the key algorithms. + * + */ +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. +} otCryptoKeyAlgorithm; + +/** + * This enumeration defines the key usage flags. + * + */ +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. +}; + +/** + * This enumeration defines the key storage types. + * + */ +typedef enum +{ + OT_CRYPTO_KEY_STORAGE_VOLATILE, ///< Key Persistence: Key is volatile. + OT_CRYPTO_KEY_STORAGE_PERSISTENT, ///< Key Persistence: Key is persistent. +} otCryptoKeyStorage; + +/** + * This datatype represents the key reference. + * + */ +typedef uint32_t otCryptoKeyRef; + +/** + * @struct otCryptoKey + * + * This structure represents the Key Material required for Crypto operations. + * + */ +typedef struct otCryptoKey +{ + const uint8_t *mKey; ///< Pointer to the buffer containing key. NULL indicates to use `mKeyRef`. + uint16_t mKeyLength; ///< The key length in bytes (applicable when `mKey` is not NULL). + uint32_t mKeyRef; ///< The PSA key ref (requires `mKey` to be NULL). +} otCryptoKey; + +/** + * Initialize the Crypto module. + * + * @retval OT_ERROR_NONE Successfully initialized Crypto module. + * @retval OT_ERROR_FAILED Failed to initialize Crypto module. + * + */ +otError otPlatCryptoInit(void); + +/** + * Import a key into PSA ITS. + * + * @param[inout] aKeyRef Pointer to the key ref to be used for crypto operations. + * @param[in] aKeyType Key Type encoding for the key. + * @param[in] aKeyAlgorithm Key algorithm encoding for the key. + * @param[in] aKeyUsage Key Usage encoding for the key (combinations of `OT_CRYPTO_KEY_USAGE_*`). + * @param[in] aKeyPersistence Key Persistence for this key + * @param[in] aKey Actual key to be imported. + * @param[in] aKeyLen Length of the key to be imported. + * + * @retval OT_ERROR_NONE Successfully imported the key. + * @retval OT_ERROR_FAILED Failed to import the key. + * @retval OT_ERROR_INVALID_ARGS @p aKey was set to NULL. + * + * @note If OT_CRYPTO_KEY_STORAGE_PERSISTENT is passed for aKeyPersistence then @p aKeyRef is input and platform + * should use the given aKeyRef and MUST not change it. + * + * If OT_CRYPTO_KEY_STORAGE_VOLATILE is passed for aKeyPersistence then @p aKeyRef is output, the initial + * value does not matter and platform API MUST update it to return the new key ref. + * + * This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled. + * + */ +otError otPlatCryptoImportKey(otCryptoKeyRef * aKeyRef, + otCryptoKeyType aKeyType, + otCryptoKeyAlgorithm aKeyAlgorithm, + int aKeyUsage, + otCryptoKeyStorage aKeyPersistence, + const uint8_t * aKey, + size_t aKeyLen); + +/** + * Export a key stored in PSA ITS. + * + * @param[in] aKeyRef The key ref to be used for crypto operations. + * @param[out] aBuffer Pointer to the buffer where key needs to be exported. + * @param[in] aBufferLen Length of the buffer passed to store the exported key. + * @param[out] aKeyLen Pointer to return the length of the exported key. + * + * @retval OT_ERROR_NONE Successfully exported @p aKeyRef. + * @retval OT_ERROR_FAILED Failed to export @p aKeyRef. + * @retval OT_ERROR_INVALID_ARGS @p aBuffer was NULL + * + * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled. + * + */ +otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t *aKeyLen); + +/** + * Destroy a key stored in PSA ITS. + * + * @param[in] aKeyRef The key ref to be destroyed + * + * @retval OT_ERROR_NONE Successfully destroyed the key. + * @retval OT_ERROR_FAILED Failed to destroy the key. + * + * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled. + * + */ +otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef); + +/** + * Check if the key ref passed has an associated key in PSA ITS. + * + * @param[in] aKeyRef The Key Ref to check. + * + * @retval TRUE There is an associated key with @p aKeyRef. + * @retval FALSE There is no associated key with @p aKeyRef. + * + * @note This API is only used by OT core when `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled. + * + */ +bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef); + +/** + * Initialize the HMAC operation. + * + * @param[in] aContext Context for HMAC operation. + * @param[in] aContextSize Context size HMAC operation. + * + * @retval OT_ERROR_NONE Successfully initialized HMAC operation. + * @retval OT_ERROR_FAILED Failed to initialize HMAC operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext was NULL + * + * @note In case PSA is supported pointer to psa_mac_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_md_context_t will be provided. + * + */ +otError otPlatCryptoHmacSha256Init(void *aContext, size_t aContextSize); + +/** + * Uninitialize the HMAC operation. + * + * @param[in] aContext Context for HMAC operation. + * @param[in] aContextSize Context size HMAC operation. + * + * + * @retval OT_ERROR_NONE Successfully uninitialized HMAC operation. + * @retval OT_ERROR_FAILED Failed to uninitialized HMAC operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext was NULL + * + * @note In case PSA is supported pointer to psa_mac_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_md_context_t will be provided. + * + */ +otError otPlatCryptoHmacSha256Deinit(void *aContext, size_t aContextSize); + +/** + * Start HMAC operation. + * + * @param[in] aContext Context for HMAC operation. + * @param[in] aContextSize Context size HMAC operation. + * @param[in] aKey Key material to be used for for HMAC operation. + * + * @retval OT_ERROR_NONE Successfully started HMAC operation. + * @retval OT_ERROR_FAILED Failed to start HMAC operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext or @p aKey was NULL + * + * @note In case PSA is supported pointer to psa_mac_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_md_context_t will be provided. + * + */ +otError otPlatCryptoHmacSha256Start(void *aContext, size_t aContextSize, const otCryptoKey *aKey); + +/** + * Update the HMAC operation with new input. + * + * @param[in] aContext Context for HMAC operation. + * @param[in] aContextSize Context size HMAC operation. + * @param[in] aBuf A pointer to the input buffer. + * @param[in] aBufLength The length of @p aBuf in bytes. + * + * @retval OT_ERROR_NONE Successfully updated HMAC with new input operation. + * @retval OT_ERROR_FAILED Failed to update HMAC operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext or @p aBuf was NULL + * + * @note In case PSA is supported pointer to psa_mac_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_md_context_t will be provided. + * + */ +otError otPlatCryptoHmacSha256Update(void *aContext, size_t aContextSize, const void *aBuf, uint16_t aBufLength); + +/** + * Complete the HMAC operation. + * + * @param[in] aContext Context for HMAC operation. + * @param[in] aContextSize Context size HMAC operation. + * @param[out] aBuf A pointer to the output buffer. + * @param[in] aBufLength The length of @p aBuf in bytes. + * + * @retval OT_ERROR_NONE Successfully completed HMAC operation. + * @retval OT_ERROR_FAILED Failed to complete HMAC operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext or @p aBuf was NULL + * + * @note In case PSA is supported pointer to psa_mac_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_md_context_t will be provided. + * + */ +otError otPlatCryptoHmacSha256Finish(void *aContext, size_t aContextSize, uint8_t *aBuf, size_t aBufLength); + +/** + * Initialise the AES operation. + * + * @param[in] aContext Context for AES operation. + * @param[in] aContextSize Context size AES operation. + * + * @retval OT_ERROR_NONE Successfully Initialised AES operation. + * @retval OT_ERROR_FAILED Failed to Initialise AES operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext was NULL + * + * @note In case PSA is supported pointer to psa_key_id will be passed as input. + * In case of mbedTLS, pointer to mbedtls_aes_context_t will be provided. + * + */ +otError otPlatCryptoAesInit(void *aContext, size_t aContextSize); + +/** + * Set the key for AES operation. + * + * @param[in] aContext Context for AES operation. + * @param[in] aContextSize Context size AES operation. + * @param[out] aKey Key to use for AES operation. + * + * @retval OT_ERROR_NONE Successfully set the key for AES operation. + * @retval OT_ERROR_FAILED Failed to set the key for AES operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext or @p aKey was NULL + * + * @note In case PSA is supported pointer to psa_key_id will be passed as input. + * In case of mbedTLS, pointer to mbedtls_aes_context_t will be provided. + * + */ +otError otPlatCryptoAesSetKey(void *aContext, size_t aContextSize, const otCryptoKey *aKey); + +/** + * Encrypt the given data. + * + * @param[in] aContext Context for AES operation. + * @param[in] aContextSize Context size AES operation. + * @param[in] aInput Pointer to the input buffer. + * @param[in] aOutput Pointer to the output buffer. + * + * @retval OT_ERROR_NONE Successfully encrypted @p aInput. + * @retval OT_ERROR_FAILED Failed to encrypt @p aInput. + * @retval OT_ERROR_INVALID_ARGS @p aContext or @p aKey or @p aOutput were NULL + * + * @note In case PSA is supported pointer to psa_key_id will be passed as input. + * In case of mbedTLS, pointer to mbedtls_aes_context_t will be provided. + * + */ +otError otPlatCryptoAesEncrypt(void *aContext, size_t aContextSize, const uint8_t *aInput, uint8_t *aOutput); + +/** + * Free the AES context. + * + * @param[in] aContext Context for AES operation. + * @param[in] aContextSize Context size AES operation. + * + * @retval OT_ERROR_NONE Successfully freed AES context. + * @retval OT_ERROR_FAILED Failed to free AES context. + * @retval OT_ERROR_INVALID_ARGS @p aContext was NULL + * + * @note In case PSA is supported pointer to psa_key_id will be passed as input. + * In case of mbedTLS, pointer to mbedtls_aes_context_t will be provided. + * + */ +otError otPlatCryptoAesFree(void *aContext, size_t aContextSize); + +/** + * Perform HKDF Expand step. + * + * @param[in] aContext Operation context for HKDF operation. + * @param[in] aContextSize Context size HKDF operation. + * @param[in] aInfo Pointer to the Info sequence. + * @param[in] aInfoLength Length of the Info sequence. + * @param[out] aOutputKey Pointer to the output Key. + * @param[in] aOutputKeyLength Size of the output key buffer. + * + * @retval OT_ERROR_NONE HKDF Expand was successful. + * @retval OT_ERROR_FAILED HKDF Expand failed. + * + */ +otError otPlatCryptoHkdfExpand(void * aContext, + size_t aContextSize, + const uint8_t *aInfo, + uint16_t aInfoLength, + uint8_t * aOutputKey, + uint16_t aOutputKeyLength); + +/** + * Perform HKDF Extract step. + * + * @param[in] aContext Operation context for HKDF operation. + * @param[in] aContextSize Context size HKDF operation. + * @param[in] aSalt Pointer to the Salt for HKDF. + * @param[in] aInfoLength length of Salt. + * @param[in] aInputKey Pointer to the input key. + * + * @retval OT_ERROR_NONE HKDF Extract was successful. + * @retval OT_ERROR_FAILED HKDF Extract failed. + * + */ +otError otPlatCryptoHkdfExtract(void * aContext, + size_t aContextSize, + const uint8_t * aSalt, + uint16_t aSaltLength, + const otCryptoKey *aInputKey); + +/** + * Initialise the SHA-256 operation. + * + * @param[in] aContext Context for SHA-256 operation. + * @param[in] aContextSize Context size SHA-256 operation. + * + * @retval OT_ERROR_NONE Successfully initialised SHA-256 operation. + * @retval OT_ERROR_FAILED Failed to initialise SHA-256 operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext was NULL + * + * @note In case PSA is supported pointer to psa_hash_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_sha256_context will be provided. + */ +otError otPlatCryptoSha256Init(void *aContext, size_t aContextSize); + +/** + * UnInitialise the SHA-256 operation. + * + * @param[in] aContext Context for SHA-256 operation. + * @param[in] aContextSize Context size SHA-256 operation. + * + * @retval OT_ERROR_NONE Successfully un-initialised SHA-256 operation. + * @retval OT_ERROR_FAILED Failed to un-initialised SHA-256 operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext was NULL + * + * @note In case PSA is supported pointer to psa_hash_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_sha256_context will be provided. + */ +otError otPlatCryptoSha256Deinit(void *aContext, size_t aContextSize); + +/** + * Start SHA-256 operation. + * + * @param[in] aContext Context for SHA-256 operation. + * @param[in] aContextSize Context size SHA-256 operation. + * + * @retval OT_ERROR_NONE Successfully started SHA-256 operation. + * @retval OT_ERROR_FAILED Failed to start SHA-256 operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext was NULL + * + * @note In case PSA is supported pointer to psa_hash_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_sha256_context will be provided. + */ +otError otPlatCryptoSha256Start(void *aContext, size_t aContextSize); + +/** + * Update SHA-256 operation with new input. + * + * @param[in] aContext Context for SHA-256 operation. + * @param[in] aContextSize Context size SHA-256 operation. + * @param[in] aBuf A pointer to the input buffer. + * @param[in] aBufLength The length of @p aBuf in bytes. + * + * @retval OT_ERROR_NONE Successfully updated SHA-256 with new input operation. + * @retval OT_ERROR_FAILED Failed to update SHA-256 operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext or @p aBuf was NULL + * + * @note In case PSA is supported pointer to psa_hash_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_sha256_context will be provided. + */ +otError otPlatCryptoSha256Update(void *aContext, size_t aContextSize, const void *aBuf, uint16_t aBufLength); + +/** + * Finish SHA-256 operation. + * + * @param[in] aContext Context for SHA-256 operation. + * @param[in] aContextSize Context size SHA-256 operation. + * @param[in] aHash A pointer to the output buffer, where hash needs to be stored. + * @param[in] aHashSize The length of @p aHash in bytes. + * + * @retval OT_ERROR_NONE Successfully completed the SHA-256 operation. + * @retval OT_ERROR_FAILED Failed to complete SHA-256 operation. + * @retval OT_ERROR_INVALID_ARGS @p aContext or @p aHash was NULL + * + * @note In case PSA is supported pointer to psa_hash_operation_t will be passed as input. + * In case of mbedTLS, pointer to mbedtls_sha256_context will be provided. + */ +otError otPlatCryptoSha256Finish(void *aContext, size_t aContextSize, uint8_t *aHash, uint16_t aHashSize); + +/** + * @} + * + */ + +#ifdef __cplusplus +} // end of extern "C" +#endif +#endif // OPENTHREAD_PLATFORM_CRYPTO_H_ diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index 822d91184..30028cce4 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -40,6 +40,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -199,6 +200,44 @@ struct otMacKey */ typedef struct otMacKey otMacKey; +/** + * This type represents a MAC Key Ref used by PSA. + * + */ +typedef otCryptoKeyRef otMacKeyRef; + +/** + * @struct otMacKeyMaterial + * + * This structure represents a MAC Key. + * + */ +OT_TOOL_PACKED_BEGIN +struct otMacKeyMaterial +{ + union + { + otMacKeyRef mKeyRef; ///< Reference to the key stored. + otMacKey mKey; ///< Key stored as literal. + } mKeyMaterial; +} OT_TOOL_PACKED_END; + +/** + * This structure represents a MAC Key reference. + * + */ +typedef struct otMacKeyMaterial otMacKeyMaterial; + +/** + * This enumeration defines constants about key types. + * + */ +typedef enum +{ + OT_KEY_TYPE_LITERAL_KEY = 0, ///< Use Literal Keys. + OT_KEY_TYPE_KEY_REF = 1, ///< Use Reference to Key. +} otRadioKeyType; + /** * This structure represents the IEEE 802.15.4 Header IE (Information Element) related information of a radio frame. */ @@ -231,12 +270,12 @@ typedef struct otRadioFrame */ struct { - const otMacKey *mAesKey; ///< The key used for AES-CCM frame security. - otRadioIeInfo * mIeInfo; ///< The pointer to the Header IE(s) related information. - uint32_t mTxDelay; ///< The delay time for this transmission (based on `mTxDelayBaseTime`). - uint32_t mTxDelayBaseTime; ///< The base time for the transmission delay. - uint8_t mMaxCsmaBackoffs; ///< Maximum number of backoffs attempts before declaring CCA failure. - uint8_t mMaxFrameRetries; ///< Maximum number of retries allowed after a transmission failure. + const otMacKeyMaterial *mAesKey; ///< The key material used for AES-CCM frame security. + otRadioIeInfo * mIeInfo; ///< The pointer to the Header IE(s) related information. + uint32_t mTxDelay; ///< The delay time for this transmission (based on `mTxDelayBaseTime`). + uint32_t mTxDelayBaseTime; ///< The base time for the transmission delay. + uint8_t mMaxCsmaBackoffs; ///< Maximum number of backoffs attempts before declaring CCA failure. + uint8_t mMaxFrameRetries; ///< Maximum number of retries allowed after a transmission failure. /** * Indicates whether frame counter and CSL IEs are properly updated in the header. @@ -559,14 +598,16 @@ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable); * @param[in] aPrevKey A pointer to the previous MAC key. * @param[in] aCurrKey A pointer to the current MAC key. * @param[in] aNextKey A pointer to the next MAC key. + * @param[in] aKeyType Key Type used. * */ -void otPlatRadioSetMacKey(otInstance * aInstance, - uint8_t aKeyIdMode, - uint8_t aKeyId, - const otMacKey *aPrevKey, - const otMacKey *aCurrKey, - const otMacKey *aNextKey); +void otPlatRadioSetMacKey(otInstance * aInstance, + uint8_t aKeyIdMode, + uint8_t aKeyId, + const otMacKeyMaterial *aPrevKey, + const otMacKeyMaterial *aCurrKey, + const otMacKeyMaterial *aNextKey, + otRadioKeyType aKeyType); /** * This method sets the current MAC frame counter value. diff --git a/include/openthread/thread.h b/include/openthread/thread.h index 449f06b97..b2cff9c6f 100644 --- a/include/openthread/thread.h +++ b/include/openthread/thread.h @@ -382,14 +382,27 @@ otError otThreadSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig); /** * Get the Thread Network Key. * - * @param[in] aInstance A pointer to an OpenThread instance. - * - * @returns A pointer to a buffer containing the Thread Network Key. + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[out] aNetworkKey A pointer to an `otNetworkkey` to return the Thread Network Key. * * @sa otThreadSetNetworkKey * */ -const otNetworkKey *otThreadGetNetworkKey(otInstance *aInstance); +void otThreadGetNetworkKey(otInstance *aInstance, otNetworkKey *aNetworkKey); + +/** + * Get the `otNetworkKeyRef` for Thread Network Key. + * + * This function requires the build-time feature `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` to be enabled. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns Reference to the Thread Network Key stored in memory. + * + * @sa otThreadSetNetworkKeyRef + * + */ +otNetworkKeyRef otThreadGetNetworkKeyRef(otInstance *aInstance); /** * Set the Thread Network Key. @@ -402,7 +415,6 @@ const otNetworkKey *otThreadGetNetworkKey(otInstance *aInstance); * @param[in] aKey A pointer to a buffer containing the Thread Network Key. * * @retval OT_ERROR_NONE Successfully set the Thread Network Key. - * @retval OT_ERROR_INVALID_ARGS If aKeyLength is larger than 16. * @retval OT_ERROR_INVALID_STATE Thread protocols are enabled. * * @sa otThreadGetNetworkKey @@ -410,6 +422,26 @@ const otNetworkKey *otThreadGetNetworkKey(otInstance *aInstance); */ otError otThreadSetNetworkKey(otInstance *aInstance, const otNetworkKey *aKey); +/** + * Set the Thread Network Key as a `otNetworkKeyRef`. + * + * This function succeeds only when Thread protocols are disabled. A successful + * call to this function invalidates the Active and Pending Operational Datasets in + * non-volatile memory. + * + * This function requires the build-time feature `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` to be enabled. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aKeyRef Reference to the Thread Network Key. + * + * @retval OT_ERROR_NONE Successfully set the Thread Network Key. + * @retval OT_ERROR_INVALID_STATE Thread protocols are enabled. + * + * @sa otThreadGetNetworkKeyRef + * + */ +otError otThreadSetNetworkKeyRef(otInstance *aInstance, otNetworkKeyRef aKeyRef); + /** * This function returns a pointer to the Thread Routing Locator (RLOC) address. * diff --git a/include/openthread/thread_ftd.h b/include/openthread/thread_ftd.h index 90debad39..d705b8d6b 100644 --- a/include/openthread/thread_ftd.h +++ b/include/openthread/thread_ftd.h @@ -556,13 +556,26 @@ otError otThreadGetNextCacheEntry(otInstance *aInstance, otCacheEntryInfo *aEntr * Get the Thread PSKc * * @param[in] aInstance A pointer to an OpenThread instance. - * - * @returns A pointer to Thread PSKc + * @param[out] aPskc A pointer to an `otPskc` to return the retrieved Thread PSKc. * * @sa otThreadSetPskc * */ -const otPskc *otThreadGetPskc(otInstance *aInstance); +void otThreadGetPskc(otInstance *aInstance, otPskc *aPskc); + +/** + * Get Key Reference to Thread PSKc stored + * + * This function requires the build-time feature `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` to be enabled. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns Key Reference to PSKc + * + * @sa otThreadSetPskcRef + * + */ +otPskcRef otThreadGetPskcRef(otInstance *aInstance); /** * Set the Thread PSKc @@ -582,6 +595,26 @@ const otPskc *otThreadGetPskc(otInstance *aInstance); */ otError otThreadSetPskc(otInstance *aInstance, const otPskc *aPskc); +/** + * Set the Thread PSKc + * + * This function requires the build-time feature `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` to be enabled. + * + * This function will only succeed when Thread protocols are disabled. A successful + * call to this function will also invalidate the Active and Pending Operational Datasets in + * non-volatile memory. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aPskcRef Key Reference to the new Thread PSKc. + * + * @retval OT_ERROR_NONE Successfully set the Thread PSKc. + * @retval OT_ERROR_INVALID_STATE Thread protocols are enabled. + * + * @sa otThreadGetPskcRef + * + */ +otError otThreadSetPskcRef(otInstance *aInstance, otPskcRef aKeyRef); + /** * Get the assigned parent priority. * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 9485d2d2f..ed5566c79 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -2550,9 +2550,10 @@ otError Interpreter::ProcessPskc(Arg aArgs[]) if (aArgs[0].IsEmpty()) { - const otPskc *pskc = otThreadGetPskc(mInstance); + otPskc pskc; - OutputBytes(pskc->m8); + otThreadGetPskc(mInstance, &pskc); + OutputBytes(pskc.m8); OutputLine(""); } else @@ -2581,6 +2582,36 @@ otError Interpreter::ProcessPskc(Arg aArgs[]) exit: return error; } + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +otError Interpreter::ProcessPskcRef(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + + if (aArgs[0].IsEmpty()) + { + OutputLine("0x%04x", otThreadGetPskcRef(mInstance)); + } + else + { + otPskcRef pskcRef; + + if (aArgs[1].IsEmpty()) + { + SuccessOrExit(error = aArgs[0].ParseAsUint32(pskcRef)); + } + else + { + ExitNow(error = OT_ERROR_INVALID_ARGS); + } + + SuccessOrExit(error = otThreadSetPskcRef(mInstance, pskcRef)); + } + +exit: + return error; +} +#endif #endif // OPENTHREAD_FTD #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE @@ -2965,7 +2996,10 @@ otError Interpreter::ProcessNetworkKey(Arg aArgs[]) if (aArgs[0].IsEmpty()) { - OutputBytes(otThreadGetNetworkKey(mInstance)->m8); + otNetworkKey networkKey; + + otThreadGetNetworkKey(mInstance, &networkKey); + OutputBytes(networkKey.m8); OutputLine(""); } else @@ -2980,6 +3014,28 @@ exit: return error; } +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +otError Interpreter::ProcessNetworkKeyRef(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + + if (aArgs[0].IsEmpty()) + { + OutputLine("0x%04x", otThreadGetNetworkKeyRef(mInstance)); + } + else + { + otNetworkKeyRef keyRef; + + SuccessOrExit(error = aArgs[0].ParseAsUint32(keyRef)); + SuccessOrExit(error = otThreadSetNetworkKeyRef(mInstance, keyRef)); + } + +exit: + return error; +} +#endif + otError Interpreter::ProcessNetworkName(Arg aArgs[]) { otError error = OT_ERROR_NONE; diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index b422b21a6..416e6a4c0 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -594,6 +594,9 @@ private: otError ProcessNetworkIdTimeout(Arg aArgs[]); #endif otError ProcessNetworkKey(Arg aArgs[]); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + otError ProcessNetworkKeyRef(Arg aArgs[]); +#endif otError ProcessNetworkName(Arg aArgs[]); #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE otError ProcessNetworkTime(Arg aArgs[]); @@ -617,6 +620,9 @@ private: #if OPENTHREAD_FTD otError ProcessPreferRouterId(Arg aArgs[]); otError ProcessPskc(Arg aArgs[]); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + otError ProcessPskcRef(Arg aArgs[]); +#endif #endif otError ProcessRcp(Arg aArgs[]); otError ProcessRegion(Arg aArgs[]); @@ -880,6 +886,9 @@ private: {"networkidtimeout", &Interpreter::ProcessNetworkIdTimeout}, #endif {"networkkey", &Interpreter::ProcessNetworkKey}, +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + {"networkkeyref", &Interpreter::ProcessNetworkKeyRef}, +#endif {"networkname", &Interpreter::ProcessNetworkName}, #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE {"networktime", &Interpreter::ProcessNetworkTime}, @@ -903,6 +912,9 @@ private: {"promiscuous", &Interpreter::ProcessPromiscuous}, #if OPENTHREAD_FTD {"pskc", &Interpreter::ProcessPskc}, +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + {"pskcref", &Interpreter::ProcessPskcRef}, +#endif #endif {"rcp", &Interpreter::ProcessRcp}, {"region", &Interpreter::ProcessRegion}, diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index eea5ba36d..f859b3177 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -692,6 +692,8 @@ otError Dataset::ProcessPskc(Arg aArgs[]) if (aArgs[0].IsEmpty()) { + // sDataset holds the key as a literal string, we don't + // need to export it from PSA ITS. if (sDataset.mComponents.mIsPskcPresent) { mInterpreter.OutputBytes(sDataset.mPskc.m8); diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index a18656ca3..bbc571e34 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -425,6 +425,7 @@ openthread_core_files = [ "crypto/aes_ccm.hpp", "crypto/aes_ecb.cpp", "crypto/aes_ecb.hpp", + "crypto/crypto_platform.cpp", "crypto/ecdsa.cpp", "crypto/ecdsa.hpp", "crypto/hkdf_sha256.cpp", @@ -437,6 +438,8 @@ openthread_core_files = [ "crypto/pbkdf2_cmac.hpp", "crypto/sha256.cpp", "crypto/sha256.hpp", + "crypto/storage.cpp", + "crypto/storage.hpp", "diags/factory_diags.cpp", "diags/factory_diags.hpp", "mac/channel_mask.cpp", @@ -678,6 +681,8 @@ openthread_radio_sources = [ "common/uptime.cpp", "crypto/aes_ccm.cpp", "crypto/aes_ecb.cpp", + "crypto/crypto_platform.cpp", + "crypto/storage.cpp", "diags/factory_diags.cpp", "mac/link_raw.cpp", "mac/mac_frame.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c83b04854..e18408560 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -110,12 +110,14 @@ set(COMMON_SOURCES common/uptime.cpp crypto/aes_ccm.cpp crypto/aes_ecb.cpp + crypto/crypto_platform.cpp crypto/ecdsa.cpp crypto/hkdf_sha256.cpp crypto/hmac_sha256.cpp crypto/mbedtls.cpp crypto/pbkdf2_cmac.cpp crypto/sha256.cpp + crypto/storage.cpp diags/factory_diags.cpp mac/channel_mask.cpp mac/data_poll_handler.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 22d48dc2d..a517c4581 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -187,12 +187,14 @@ SOURCES_COMMON = \ common/uptime.cpp \ crypto/aes_ccm.cpp \ crypto/aes_ecb.cpp \ + crypto/crypto_platform.cpp \ crypto/ecdsa.cpp \ crypto/hkdf_sha256.cpp \ crypto/hmac_sha256.cpp \ crypto/mbedtls.cpp \ crypto/pbkdf2_cmac.cpp \ crypto/sha256.cpp \ + crypto/storage.cpp \ diags/factory_diags.cpp \ mac/channel_mask.cpp \ mac/data_poll_handler.cpp \ @@ -327,6 +329,8 @@ libopenthread_radio_a_SOURCES = \ common/uptime.cpp \ crypto/aes_ccm.cpp \ crypto/aes_ecb.cpp \ + crypto/crypto_platform.cpp \ + crypto/storage.cpp \ diags/factory_diags.cpp \ mac/link_raw.cpp \ mac/mac_frame.cpp \ @@ -464,6 +468,7 @@ HEADERS_COMMON = \ crypto/mbedtls.hpp \ crypto/pbkdf2_cmac.hpp \ crypto/sha256.hpp \ + crypto/storage.hpp \ diags/factory_diags.hpp \ mac/channel_mask.hpp \ mac/data_poll_handler.hpp \ diff --git a/src/core/api/crypto_api.cpp b/src/core/api/crypto_api.cpp index 73195dd61..691889dd4 100644 --- a/src/core/api/crypto_api.cpp +++ b/src/core/api/crypto_api.cpp @@ -45,40 +45,33 @@ using namespace ot::Crypto; -void otCryptoHmacSha256(const uint8_t * aKey, - uint16_t aKeyLength, - const uint8_t * aBuf, - uint16_t aBufLength, - otCryptoSha256Hash *aHash) +void otCryptoHmacSha256(const otCryptoKey *aKey, const uint8_t *aBuf, uint16_t aBufLength, otCryptoSha256Hash *aHash) { HmacSha256 hmac; OT_ASSERT((aKey != nullptr) && (aBuf != nullptr) && (aHash != nullptr)); - hmac.Start(aKey, aKeyLength); + hmac.Start(*static_cast(aKey)); hmac.Update(aBuf, aBufLength); hmac.Finish(*static_cast(aHash)); } -void otCryptoAesCcm(const uint8_t *aKey, - uint16_t aKeyLength, - uint8_t aTagLength, - const void * aNonce, - uint8_t aNonceLength, - const void * aHeader, - uint32_t aHeaderLength, - void * aPlainText, - void * aCipherText, - uint32_t aLength, - bool aEncrypt, - void * aTag) +void otCryptoAesCcm(const otCryptoKey *aKey, + uint8_t aTagLength, + const void * aNonce, + uint8_t aNonceLength, + const void * aHeader, + uint32_t aHeaderLength, + void * aPlainText, + void * aCipherText, + uint32_t aLength, + bool aEncrypt, + void * aTag) { AesCcm aesCcm; + OT_ASSERT((aNonce != nullptr) && (aPlainText != nullptr) && (aCipherText != nullptr) && (aTag != nullptr)); - OT_ASSERT((aKey != nullptr) && (aNonce != nullptr) && (aPlainText != nullptr) && (aCipherText != nullptr) && - (aTag != nullptr)); - - aesCcm.SetKey(aKey, aKeyLength); + aesCcm.SetKey(*static_cast(aKey)); aesCcm.Init(aHeaderLength, aLength, aTagLength, aNonce, aNonceLength); if (aHeaderLength != 0) diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp index 0a9018489..e42bc5d66 100644 --- a/src/core/api/thread_api.cpp +++ b/src/core/api/thread_api.cpp @@ -112,13 +112,22 @@ otError otThreadSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig) return instance.Get().SetDeviceMode(Mle::DeviceMode(aConfig)); } -const otNetworkKey *otThreadGetNetworkKey(otInstance *aInstance) +void otThreadGetNetworkKey(otInstance *aInstance, otNetworkKey *aNetworkKey) { Instance &instance = *static_cast(aInstance); - return &instance.Get().GetNetworkKey(); + instance.Get().GetNetworkKey(*static_cast(aNetworkKey)); } +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +otNetworkKeyRef otThreadGetNetworkKeyRef(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().GetNetworkKeyRef(); +} +#endif + otError otThreadSetNetworkKey(otInstance *aInstance, const otNetworkKey *aKey) { Error error = kErrorNone; @@ -128,7 +137,8 @@ otError otThreadSetNetworkKey(otInstance *aInstance, const otNetworkKey *aKey) VerifyOrExit(instance.Get().IsDisabled(), error = kErrorInvalidState); - error = instance.Get().SetNetworkKey(*static_cast(aKey)); + instance.Get().SetNetworkKey(*static_cast(aKey)); + instance.Get().Clear(); instance.Get().Clear(); @@ -136,6 +146,25 @@ exit: return error; } +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +otError otThreadSetNetworkKeyRef(otInstance *aInstance, otNetworkKeyRef aKeyRef) +{ + Error error = kErrorNone; + Instance &instance = *static_cast(aInstance); + + VerifyOrExit(aKeyRef != 0, error = kErrorInvalidArgs); + + VerifyOrExit(instance.Get().IsDisabled(), error = kErrorInvalidState); + + instance.Get().SetNetworkKeyRef(static_cast(aKeyRef)); + instance.Get().Clear(); + instance.Get().Clear(); + +exit: + return error; +} +#endif + const otIp6Address *otThreadGetRloc(otInstance *aInstance) { Instance &instance = *static_cast(aInstance); diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index 93ccfa02f..f2a5bbce5 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -343,13 +343,22 @@ void otThreadSetSteeringData(otInstance *aInstance, const otExtAddress *aExtAddr } #endif -const otPskc *otThreadGetPskc(otInstance *aInstance) +void otThreadGetPskc(otInstance *aInstance, otPskc *aPskc) { Instance &instance = *static_cast(aInstance); - return &instance.Get().GetPskc(); + instance.Get().GetPskc(*static_cast(aPskc)); } +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +otPskcRef otThreadGetPskcRef(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().GetPskcRef(); +} +#endif + otError otThreadSetPskc(otInstance *aInstance, const otPskc *aPskc) { Error error = kErrorNone; @@ -365,6 +374,24 @@ exit: return error; } +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +otError otThreadSetPskcRef(otInstance *aInstance, otPskcRef aKeyRef) +{ + Error error = kErrorNone; + Instance &instance = *static_cast(aInstance); + + VerifyOrExit(aKeyRef != 0, error = kErrorInvalidArgs); + VerifyOrExit(instance.Get().IsDisabled(), error = kErrorInvalidState); + + instance.Get().SetPskcRef(aKeyRef); + instance.Get().Clear(); + instance.Get().Clear(); + +exit: + return error; +} +#endif + int8_t otThreadGetParentPriority(otInstance *aInstance) { Instance &instance = *static_cast(aInstance); diff --git a/src/core/config/platform.h b/src/core/config/platform.h index e1c082e84..83581fee7 100644 --- a/src/core/config/platform.h +++ b/src/core/config/platform.h @@ -128,6 +128,26 @@ #define OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT 0 #endif +/** + * @def OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + * + * Default NVM offset while using key refs. Platforms can override this definition based on implementation + * + */ +#ifndef OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET +#define OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET 0x20000 +#endif + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + * + * Define to 1 if you want to enable key ref usage support as defined by platform. + * + */ +#ifndef OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +#define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 0 +#endif + #if OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT #if (!defined(OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE) || \ !defined(OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MIN) || \ diff --git a/src/core/crypto/aes_ccm.cpp b/src/core/crypto/aes_ccm.cpp index a46cba440..a3ed5e5f1 100644 --- a/src/core/crypto/aes_ccm.cpp +++ b/src/core/crypto/aes_ccm.cpp @@ -44,12 +44,18 @@ namespace Crypto { void AesCcm::SetKey(const uint8_t *aKey, uint16_t aKeyLength) { - mEcb.SetKey(aKey, CHAR_BIT * aKeyLength); + Key cryptoKey; + + cryptoKey.Set(aKey, aKeyLength); + SetKey(cryptoKey); } -void AesCcm::SetKey(const Mac::Key &aMacKey) +void AesCcm::SetKey(const Mac::KeyMaterial &aMacKey) { - SetKey(aMacKey.GetKey(), Mac::Key::kSize); + Key cryptoKey; + + aMacKey.ConvertToCryptoKey(cryptoKey); + SetKey(cryptoKey); } void AesCcm::Init(uint32_t aHeaderLength, diff --git a/src/core/crypto/aes_ccm.hpp b/src/core/crypto/aes_ccm.hpp index ec11f4db4..34e50f721 100644 --- a/src/core/crypto/aes_ccm.hpp +++ b/src/core/crypto/aes_ccm.hpp @@ -38,8 +38,10 @@ #include +#include #include "common/error.hpp" #include "crypto/aes_ecb.hpp" +#include "crypto/storage.hpp" #include "mac/mac_types.hpp" namespace ot { @@ -73,6 +75,14 @@ public: kDecrypt, // Decryption mode. }; + /** + * This method sets the key. + * + * @param[in] aKey Crypto Key used in AES operation + * + */ + void SetKey(const Key &aKey) { mEcb.SetKey(aKey); } + /** * This method sets the key. * @@ -85,10 +95,10 @@ public: /** * This method sets the key. * - * @param[in] aMacKey A MAC key. + * @param[in] aMacKey Key Material for AES operation. * */ - void SetKey(const Mac::Key &aMacKey); + void SetKey(const Mac::KeyMaterial &aMacKey); /** * This method initializes the AES CCM computation. diff --git a/src/core/crypto/aes_ecb.cpp b/src/core/crypto/aes_ecb.cpp index 77fea9030..da0368eff 100644 --- a/src/core/crypto/aes_ecb.cpp +++ b/src/core/crypto/aes_ecb.cpp @@ -32,28 +32,38 @@ */ #include "aes_ecb.hpp" +#include "common/debug.hpp" +#include "common/error.hpp" namespace ot { namespace Crypto { AesEcb::AesEcb(void) { - mbedtls_aes_init(&mContext); + Error err = otPlatCryptoAesInit(&mContext, sizeof(mContext)); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } -void AesEcb::SetKey(const uint8_t *aKey, uint16_t aKeyLength) +void AesEcb::SetKey(const Key &aKey) { - mbedtls_aes_setkey_enc(&mContext, aKey, aKeyLength); + Error err = otPlatCryptoAesSetKey(&mContext, sizeof(mContext), &aKey); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } void AesEcb::Encrypt(const uint8_t aInput[kBlockSize], uint8_t aOutput[kBlockSize]) { - mbedtls_aes_crypt_ecb(&mContext, MBEDTLS_AES_ENCRYPT, aInput, aOutput); + Error err = otPlatCryptoAesEncrypt(&mContext, sizeof(mContext), aInput, aOutput); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } AesEcb::~AesEcb(void) { - mbedtls_aes_free(&mContext); + Error err = otPlatCryptoAesFree(&mContext, sizeof(mContext)); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } } // namespace Crypto diff --git a/src/core/crypto/aes_ecb.hpp b/src/core/crypto/aes_ecb.hpp index baed30e7c..ccb3e355b 100644 --- a/src/core/crypto/aes_ecb.hpp +++ b/src/core/crypto/aes_ecb.hpp @@ -35,8 +35,10 @@ #define AES_ECB_HPP_ #include "openthread-core-config.h" - #include +#include + +#include "crypto/storage.hpp" namespace ot { namespace Crypto { @@ -72,11 +74,10 @@ public: /** * This method sets the key. * - * @param[in] aKey A pointer to the key. - * @param[in] aKeyLength The key length in bits. + * @param[in] aKey Crypto Key used for ECB operation * */ - void SetKey(const uint8_t *aKey, uint16_t aKeyLength); + void SetKey(const Key &aKey); /** * This method encrypts data. @@ -88,7 +89,13 @@ public: void Encrypt(const uint8_t aInput[kBlockSize], uint8_t aOutput[kBlockSize]); private: - mbedtls_aes_context mContext; + union AesEcbContext + { + uint32_t mKeyRef; + mbedtls_aes_context mContext; + }; + + AesEcbContext mContext; }; /** diff --git a/src/core/crypto/crypto_platform.cpp b/src/core/crypto/crypto_platform.cpp new file mode 100644 index 000000000..92d831f71 --- /dev/null +++ b/src/core/crypto/crypto_platform.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the Crypto platform callbacks into OpenThread and default/weak Crypto platform APIs. + */ + +#include "openthread-core-config.h" + +#include +#include + +#include +#include +#include + +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "common/instance.hpp" +#include "common/message.hpp" +#include "crypto/hmac_sha256.hpp" +#include "crypto/storage.hpp" + +using namespace ot; +using namespace Crypto; + +//--------------------------------------------------------------------------------------------------------------------- +// Default/weak implementation of crypto platform APIs + +OT_TOOL_WEAK otError otPlatCryptoInit(void) +{ + return kErrorNone; +} + +// AES Implementation +OT_TOOL_WEAK otError otPlatCryptoAesInit(void *aContext, size_t aContextSize) +{ + Error error = kErrorNone; + mbedtls_aes_context *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed); + mbedtls_aes_init(context); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoAesSetKey(void *aContext, size_t aContextSize, const otCryptoKey *aKey) +{ + Error error = kErrorNone; + mbedtls_aes_context *context = static_cast(aContext); + const LiteralKey key(*static_cast(aKey)); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed); + VerifyOrExit((mbedtls_aes_setkey_enc(context, key.GetBytes(), (key.GetLength() * CHAR_BIT)) == 0), + error = kErrorFailed); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoAesEncrypt(void * aContext, + size_t aContextSize, + const uint8_t *aInput, + uint8_t * aOutput) +{ + Error error = kErrorNone; + mbedtls_aes_context *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed); + VerifyOrExit((mbedtls_aes_crypt_ecb(context, MBEDTLS_AES_ENCRYPT, aInput, aOutput) == 0), error = kErrorFailed); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoAesFree(void *aContext, size_t aContextSize) +{ + Error error = kErrorNone; + mbedtls_aes_context *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed); + mbedtls_aes_free(context); + +exit: + return error; +} + +#if !OPENTHREAD_RADIO + +// HMAC implementations +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Init(void *aContext, size_t aContextSize) +{ + Error error = kErrorNone; + const mbedtls_md_info_t *mdInfo = nullptr; + mbedtls_md_context_t * context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed); + mbedtls_md_init(context); + mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + VerifyOrExit((mbedtls_md_setup(context, mdInfo, 1) == 0), error = kErrorFailed); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Deinit(void *aContext, size_t aContextSize) +{ + Error error = kErrorNone; + mbedtls_md_context_t *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed); + mbedtls_md_free(context); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Start(void *aContext, size_t aContextSize, const otCryptoKey *aKey) +{ + Error error = kErrorNone; + mbedtls_md_context_t *context = static_cast(aContext); + const LiteralKey key(*static_cast(aKey)); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed); + VerifyOrExit((mbedtls_md_hmac_starts(context, key.GetBytes(), key.GetLength()) == 0), error = kErrorFailed); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Update(void * aContext, + size_t aContextSize, + const void *aBuf, + uint16_t aBufLength) +{ + Error error = kErrorNone; + mbedtls_md_context_t *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed); + VerifyOrExit((mbedtls_md_hmac_update(context, reinterpret_cast(aBuf), aBufLength) == 0), + error = kErrorFailed); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Finish(void *aContext, size_t aContextSize, uint8_t *aBuf, size_t aBufLength) +{ + OT_UNUSED_VARIABLE(aBufLength); + + Error error = kErrorNone; + mbedtls_md_context_t *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed); + VerifyOrExit((mbedtls_md_hmac_finish(context, aBuf) == 0), error = kErrorFailed); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHkdfExpand(void * aContext, + size_t aContextSize, + const uint8_t *aInfo, + uint16_t aInfoLength, + uint8_t * aOutputKey, + uint16_t aOutputKeyLength) +{ + Error error = kErrorNone; + HmacSha256 hmac; + HmacSha256::Hash hash; + uint8_t iter = 0; + uint16_t copyLength; + HmacSha256::Hash *prk = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(HmacSha256::Hash), error = kErrorFailed); + + // The aOutputKey is calculated as follows [RFC5889]: + // + // N = ceil( aOutputKeyLength / HashSize) + // T = T(1) | T(2) | T(3) | ... | T(N) + // aOutputKey is first aOutputKeyLength of T + // + // Where: + // T(0) = empty string (zero length) + // T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + // T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + // T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) + // ... + + while (aOutputKeyLength > 0) + { + Key cryptoKey; + + cryptoKey.Set(prk->GetBytes(), sizeof(HmacSha256::Hash)); + hmac.Start(cryptoKey); + + if (iter != 0) + { + hmac.Update(hash); + } + + hmac.Update(aInfo, aInfoLength); + + iter++; + hmac.Update(iter); + hmac.Finish(hash); + + copyLength = (aOutputKeyLength > sizeof(hash)) ? sizeof(hash) : aOutputKeyLength; + + memcpy(aOutputKey, hash.GetBytes(), copyLength); + aOutputKey += copyLength; + aOutputKeyLength -= copyLength; + } + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHkdfExtract(void * aContext, + size_t aContextSize, + const uint8_t * aSalt, + uint16_t aSaltLength, + const otCryptoKey *aInputKey) +{ + Error error = kErrorNone; + HmacSha256 hmac; + Key cryptoKey; + HmacSha256::Hash *prk = static_cast(aContext); + const LiteralKey inputKey(*static_cast(aInputKey)); + + VerifyOrExit(aContextSize >= sizeof(HmacSha256::Hash), error = kErrorFailed); + + cryptoKey.Set(aSalt, aSaltLength); + + // PRK is calculated as HMAC-Hash(aSalt, aInputKey) + hmac.Start(cryptoKey); + hmac.Update(inputKey.GetBytes(), inputKey.GetLength()); + hmac.Finish(*prk); + +exit: + return error; +} + +// SHA256 platform implementations +OT_TOOL_WEAK otError otPlatCryptoSha256Init(void *aContext, size_t aContextSize) +{ + Error error = kErrorNone; + mbedtls_sha256_context *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed); + mbedtls_sha256_init(context); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Deinit(void *aContext, size_t aContextSize) +{ + Error error = kErrorNone; + mbedtls_sha256_context *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed); + mbedtls_sha256_free(context); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Start(void *aContext, size_t aContextSize) +{ + Error error = kErrorNone; + mbedtls_sha256_context *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed); + VerifyOrExit((mbedtls_sha256_starts_ret(context, 0) == 0), error = kErrorFailed); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Update(void * aContext, + size_t aContextSize, + const void *aBuf, + uint16_t aBufLength) +{ + Error error = kErrorNone; + mbedtls_sha256_context *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed); + VerifyOrExit((mbedtls_sha256_update_ret(context, reinterpret_cast(aBuf), aBufLength) == 0), + error = kErrorFailed); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Finish(void *aContext, size_t aContextSize, uint8_t *aHash, uint16_t aHashSize) +{ + OT_UNUSED_VARIABLE(aHashSize); + + Error error = kErrorNone; + mbedtls_sha256_context *context = static_cast(aContext); + + VerifyOrExit(aContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed); + VerifyOrExit((mbedtls_sha256_finish_ret(context, aHash) == 0), error = kErrorFailed); + +exit: + return error; +} + +#endif // #if !OPENTHREAD_RADIO diff --git a/src/core/crypto/hkdf_sha256.cpp b/src/core/crypto/hkdf_sha256.cpp index dad7b0faf..7f44e3cba 100644 --- a/src/core/crypto/hkdf_sha256.cpp +++ b/src/core/crypto/hkdf_sha256.cpp @@ -35,61 +35,24 @@ #include +#include "common/code_utils.hpp" +#include "common/debug.hpp" + namespace ot { namespace Crypto { -void HkdfSha256::Extract(const uint8_t *aSalt, uint16_t aSaltLength, const uint8_t *aInputKey, uint16_t aInputKeyLength) +void HkdfSha256::Extract(const uint8_t *aSalt, uint16_t aSaltLength, const Key &aInputKey) { - HmacSha256 hmac; - - // PRK is calculated as HMAC-Hash(aSalt, aInputKey) - - hmac.Start(aSalt, aSaltLength); - hmac.Update(aInputKey, aInputKeyLength); - hmac.Finish(mPrk); + Error err = otPlatCryptoHkdfExtract(&mContext, sizeof(mContext), aSalt, aSaltLength, &aInputKey); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } void HkdfSha256::Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOutputKey, uint16_t aOutputKeyLength) { - HmacSha256 hmac; - HmacSha256::Hash hash; - uint8_t iter = 0; - uint16_t copyLength; - - // The aOutputKey is calculated as follows [RFC5889]: - // - // N = ceil( aOutputKeyLength / HashSize) - // T = T(1) | T(2) | T(3) | ... | T(N) - // aOutputKey is first aOutputKeyLength of T - // - // Where: - // T(0) = empty string (zero length) - // T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) - // T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) - // T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) - // ... - - while (aOutputKeyLength > 0) - { - hmac.Start(mPrk.GetBytes(), sizeof(mPrk)); - - if (iter != 0) - { - hmac.Update(hash); - } - - hmac.Update(aInfo, aInfoLength); - - iter++; - hmac.Update(iter); - hmac.Finish(hash); - - copyLength = (aOutputKeyLength > sizeof(hash)) ? sizeof(hash) : aOutputKeyLength; - - memcpy(aOutputKey, hash.GetBytes(), copyLength); - aOutputKey += copyLength; - aOutputKeyLength -= copyLength; - } + Error err = otPlatCryptoHkdfExpand(&mContext, sizeof(mContext), aInfo, aInfoLength, aOutputKey, aOutputKeyLength); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } } // namespace Crypto diff --git a/src/core/crypto/hkdf_sha256.hpp b/src/core/crypto/hkdf_sha256.hpp index 648ba72f4..f99a30b53 100644 --- a/src/core/crypto/hkdf_sha256.hpp +++ b/src/core/crypto/hkdf_sha256.hpp @@ -37,6 +37,8 @@ #include "openthread-core-config.h" +#include + #include "crypto/hmac_sha256.hpp" namespace ot { @@ -63,11 +65,10 @@ public: * * @param[in] aSalt A pointer to buffer containing salt. * @param[in] aSaltLength The salt length (in bytes). - * @param[in] aInputKey A pointer to buffer containing the input key. - * @param[in] aInputKeyLength The input key length (in bytes). + * @param[in] aInputKey The input key. * */ - void Extract(const uint8_t *aSalt, uint16_t aSaltLength, const uint8_t *aInputKey, uint16_t aInputKeyLength); + void Extract(const uint8_t *aSalt, uint16_t aSaltLength, const Key &aInputKey); /** * This method performs the HKDF Expand step. @@ -84,7 +85,13 @@ public: void Expand(const uint8_t *aInfo, uint16_t aInfoLength, uint8_t *aOutputKey, uint16_t aOutputKeyLength); private: - HmacSha256::Hash mPrk; // Pseudo-Random Key (derived from Extract step). + union HkdfContext + { + HmacSha256::Hash mPrk; // Pseudo-Random Key (derived from Extract step). + psa_key_derivation_operation_t mOperation; + }; + + HkdfContext mContext; }; /** diff --git a/src/core/crypto/hmac_sha256.cpp b/src/core/crypto/hmac_sha256.cpp index add3e3aca..4279e5ebb 100644 --- a/src/core/crypto/hmac_sha256.cpp +++ b/src/core/crypto/hmac_sha256.cpp @@ -32,7 +32,7 @@ */ #include "hmac_sha256.hpp" - +#include "common/debug.hpp" #include "common/message.hpp" namespace ot { @@ -40,25 +40,37 @@ namespace Crypto { HmacSha256::HmacSha256(void) { - const mbedtls_md_info_t *mdInfo = nullptr; - mbedtls_md_init(&mContext); - mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - mbedtls_md_setup(&mContext, mdInfo, 1); + Error err = otPlatCryptoHmacSha256Init(&mContext, sizeof(mContext)); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } HmacSha256::~HmacSha256(void) { - mbedtls_md_free(&mContext); + Error err = otPlatCryptoHmacSha256Deinit(&mContext, sizeof(mContext)); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } -void HmacSha256::Start(const uint8_t *aKey, uint16_t aKeyLength) +void HmacSha256::Start(const Key &aKey) { - mbedtls_md_hmac_starts(&mContext, aKey, aKeyLength); + Error err = otPlatCryptoHmacSha256Start(&mContext, sizeof(mContext), &aKey); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } void HmacSha256::Update(const void *aBuf, uint16_t aBufLength) { - mbedtls_md_hmac_update(&mContext, reinterpret_cast(aBuf), aBufLength); + Error err = otPlatCryptoHmacSha256Update(&mContext, sizeof(mContext), aBuf, aBufLength); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); +} + +void HmacSha256::Finish(Hash &aHash) +{ + Error err = otPlatCryptoHmacSha256Finish(&mContext, sizeof(mContext), aHash.m8, Hash::kSize); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } void HmacSha256::Update(const Message &aMessage, uint16_t aOffset, uint16_t aLength) @@ -74,10 +86,5 @@ void HmacSha256::Update(const Message &aMessage, uint16_t aOffset, uint16_t aLen } } -void HmacSha256::Finish(Hash &aHash) -{ - mbedtls_md_hmac_finish(&mContext, aHash.m8); -} - } // namespace Crypto } // namespace ot diff --git a/src/core/crypto/hmac_sha256.hpp b/src/core/crypto/hmac_sha256.hpp index 5fcd2a04f..b5ff18ff6 100644 --- a/src/core/crypto/hmac_sha256.hpp +++ b/src/core/crypto/hmac_sha256.hpp @@ -39,8 +39,12 @@ #include #include +#include + +#include #include "crypto/sha256.hpp" +#include "crypto/storage.hpp" namespace ot { @@ -83,11 +87,10 @@ public: /** * This method sets the key and starts the HMAC computation. * - * @param[in] aKey A pointer to the key. - * @param[in] aKeyLength The key length in bytes. + * @param[in] aKey The key to use. * */ - void Start(const uint8_t *aKey, uint16_t aKeyLength); + void Start(const Key &aKey); /** * This method inputs bytes into the HMAC computation. @@ -131,7 +134,13 @@ public: void Finish(Hash &aHash); private: - mbedtls_md_context_t mContext; + union HmacContext + { + psa_mac_operation_t mOperation; + mbedtls_md_context_t mContext; + }; + + HmacContext mContext; }; /** diff --git a/src/core/crypto/sha256.cpp b/src/core/crypto/sha256.cpp index 9721d29d5..dce510183 100644 --- a/src/core/crypto/sha256.cpp +++ b/src/core/crypto/sha256.cpp @@ -33,6 +33,8 @@ #include "sha256.hpp" +#include "common/debug.hpp" +#include "common/error.hpp" #include "common/message.hpp" namespace ot { @@ -40,22 +42,30 @@ namespace Crypto { Sha256::Sha256(void) { - mbedtls_sha256_init(&mContext); + Error err = otPlatCryptoSha256Init(&mContext, sizeof(mContext)); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } Sha256::~Sha256(void) { - mbedtls_sha256_free(&mContext); + Error err = otPlatCryptoSha256Deinit(&mContext, sizeof(mContext)); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } void Sha256::Start(void) { - mbedtls_sha256_starts_ret(&mContext, 0); + Error err = otPlatCryptoSha256Start(&mContext, sizeof(mContext)); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } void Sha256::Update(const void *aBuf, uint16_t aBufLength) { - mbedtls_sha256_update_ret(&mContext, reinterpret_cast(aBuf), aBufLength); + Error err = otPlatCryptoSha256Update(&mContext, sizeof(mContext), aBuf, aBufLength); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } void Sha256::Update(const Message &aMessage, uint16_t aOffset, uint16_t aLength) @@ -73,8 +83,9 @@ void Sha256::Update(const Message &aMessage, uint16_t aOffset, uint16_t aLength) void Sha256::Finish(Hash &aHash) { - mbedtls_sha256_finish_ret(&mContext, aHash.m8); + Error err = otPlatCryptoSha256Finish(&mContext, sizeof(mContext), aHash.m8, Hash::kSize); + OT_ASSERT(err == kErrorNone); + OT_UNUSED_VARIABLE(err); } - } // namespace Crypto } // namespace ot diff --git a/src/core/crypto/sha256.hpp b/src/core/crypto/sha256.hpp index 024fa452d..18f85b8e9 100644 --- a/src/core/crypto/sha256.hpp +++ b/src/core/crypto/sha256.hpp @@ -39,8 +39,10 @@ #include #include +#include #include +#include #include "common/clearable.hpp" #include "common/equatable.hpp" @@ -144,7 +146,13 @@ public: void Finish(Hash &aHash); private: - mbedtls_sha256_context mContext; + union Sha256Context + { + psa_hash_operation_t mOperation; + mbedtls_sha256_context mContext; + }; + + Sha256Context mContext; }; /** diff --git a/src/core/crypto/storage.cpp b/src/core/crypto/storage.cpp new file mode 100644 index 000000000..4a45eb48d --- /dev/null +++ b/src/core/crypto/storage.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes implementation for Crypto Internal Trusted Storage (ITS) APIs. + */ + +#include "crypto/storage.hpp" + +#include "common/debug.hpp" + +namespace ot { +namespace Crypto { + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +Error Key::ExtractKey(uint8_t *aKeyBuffer, uint16_t &aKeyLength) const +{ + Error error; + size_t readKeyLength; + + OT_ASSERT(IsKeyRef()); + + error = Crypto::Storage::ExportKey(GetKeyRef(), aKeyBuffer, aKeyLength, readKeyLength); + + OT_ASSERT(error == kErrorNone); + VerifyOrExit(readKeyLength <= aKeyLength, error = kErrorNoBufs); + + aKeyLength = static_cast(readKeyLength); + +exit: + return error; +} +#endif + +LiteralKey::LiteralKey(const Key &aKey) + : mKey(aKey.GetBytes()) + , mLength(aKey.GetLength()) +{ +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + if (aKey.IsKeyRef()) + { + Error error; + + mKey = mBuffer; + mLength = sizeof(mBuffer); + error = aKey.ExtractKey(mBuffer, mLength); + + OT_ASSERT(error == kErrorNone); + OT_UNUSED_VARIABLE(error); + } +#endif +} + +} // namespace Crypto +} // namespace ot diff --git a/src/core/crypto/storage.hpp b/src/core/crypto/storage.hpp new file mode 100644 index 000000000..0b4c018f5 --- /dev/null +++ b/src/core/crypto/storage.hpp @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes definitions for Crypto Internal Trusted Storage (ITS) APIs. + */ + +#ifndef STORAGE_HPP_ +#define STORAGE_HPP_ + +#include "openthread-core-config.h" + +#include + +#include "common/clearable.hpp" +#include "common/code_utils.hpp" +#include "common/error.hpp" +#include "common/non_copyable.hpp" + +namespace ot { +namespace Crypto { + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + +namespace Storage { + +/** + * This enumeration defines the key types. + * + */ +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. +}; + +/** + * This enumeration defines the key algorithms. + * + */ +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. +}; + +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. + +/** + * This enumeration defines the key storage types. + * + */ +enum StorageType : uint8_t +{ + kTypeVolatile = OT_CRYPTO_KEY_STORAGE_VOLATILE, ///< Key is volatile. + kTypePersistent = OT_CRYPTO_KEY_STORAGE_PERSISTENT, ///< Key is persistent. +}; + +/** + * This datatype represents the key reference. + * + */ +typedef otCryptoKeyRef KeyRef; + +constexpr KeyRef kInvalidKeyRef = 0x80000000; ///< Invalid `KeyRef` value (PSA_KEY_ID_VENDOR_MAX + 1). + +/** + * This type represents the Key Attributes structure. + * + */ +typedef otCryptoKeyAttributes KeyAttributes; + +/** + * Determine if a given `KeyRef` is valid or not. + * + * @param[in] aKeyRef The `KeyRef` to check. + * + * @retval TRUE If @p aKeyRef is valid. + * @retval FALSE If @p aKeyRef is not valid. + * + */ +inline bool IsKeyRefValid(KeyRef aKeyRef) +{ + return (aKeyRef < kInvalidKeyRef); +} + +/** + * Import a key into PSA ITS. + * + * @param[inout] aKeyRef Reference to the key ref to be used for crypto operations. + * @param[in] aKeyType Key Type encoding for the key. + * @param[in] aKeyAlgorithm Key algorithm encoding for the key. + * @param[in] aKeyUsage Key Usage encoding for the key. + * @param[in] aStorageType Key storage type. + * @param[in] aKey Actual key to be imported. + * @param[in] aKeyLen Length of the key to be imported. + * + * @retval kErrorNone Successfully imported the key. + * @retval kErrorFailed Failed to import the key. + * @retval kErrorInvalidArgs @p aKey was set to nullptr. + * + */ +inline Error ImportKey(KeyRef & aKeyRef, + KeyType aKeyType, + KeyAlgorithm aKeyAlgorithm, + int aKeyUsage, + StorageType aStorageType, + const uint8_t *aKey, + size_t aKeyLen) +{ + return otPlatCryptoImportKey(&aKeyRef, static_cast(aKeyType), + static_cast(aKeyAlgorithm), aKeyUsage, + static_cast(aStorageType), aKey, aKeyLen); +} + +/** + * Export a key stored in PSA ITS. + * + * @param[in] aKeyRef The key ref to be used for crypto operations. + * @param[out] aBuffer Pointer to the buffer where key needs to be exported. + * @param[in] aBufferLen Length of the buffer passed to store the exported key. + * @param[out] aKeyLen Reference to variable to return the length of the exported key. + * + * @retval kErrorNone Successfully exported @p aKeyRef. + * @retval kErrorFailed Failed to export @p aKeyRef. + * @retval kErrorInvalidArgs @p aBuffer was nullptr. + * + */ +inline Error ExportKey(KeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t &aKeyLen) +{ + return otPlatCryptoExportKey(aKeyRef, aBuffer, aBufferLen, &aKeyLen); +} + +/** + * Destroy a key stored in PSA ITS. + * + * @param[in] aKeyRef The key ref to be removed. + * + */ +inline void DestroyKey(KeyRef aKeyRef) +{ + if (IsKeyRefValid(aKeyRef)) + { + IgnoreError(otPlatCryptoDestroyKey(aKeyRef)); + } +} + +/** + * Check if the keyRef passed has an associated key in PSA ITS. + * + * @param[in] aKeyRef The Key Ref for to check. + * + * @retval true Key Ref passed has a key associated in PSA. + * @retval false Key Ref passed is invalid and has no key associated in PSA. + * + */ +inline bool HasKey(KeyRef aKeyRef) +{ + return otPlatCryptoHasKey(aKeyRef); +} + +} // namespace Storage + +#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + +/** + * This class represents a crypto key. + * + * The `Key` can represent a literal key (i.e., a pointer to a byte array containing the key along with a key length) + * or a `KeyRef` (if `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled). + * + */ +class Key : public otCryptoKey, public Clearable +{ +public: + /** + * This method sets the `Key` as a literal key from a given byte array and length. + * + * @param[in] aKeyBytes A pointer to buffer containing the key. + * @param[in] aKeyLength The key length (number of bytes in @p akeyBytes). + * + */ + void Set(const uint8_t *aKeyBytes, uint16_t aKeyLength) + { + mKey = aKeyBytes; + mKeyLength = aKeyLength; + } + + /** + * This method gets the pointer to the bye array containing the key. + * + * If `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled and `IsKeyRef()` returns `true`, then this + * method returns `nullptr`. + * + * @returns The pointer to the byte array containing the key, or `nullptr` if the `Key` represents a `KeyRef` + * + */ + const uint8_t *GetBytes(void) const { return mKey; } + + /** + * This method gets the key length (number of bytes). + * + * If `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` is enabled and `IsKeyRef()` returns `true`, then this + * method returns zero. + * + * @returns The key length (number of bytes in the byte array from `GetBytes()`), or zero if `Key` represents a + * `keyRef`. + * + */ + uint16_t GetLength(void) const { return mKeyLength; } + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + /** + * This method indicates whether or not the key is represented as a `KeyRef`. + * + * @retval TRUE The `Key` represents a `KeyRef` + * @retval FALSE The `Key` represents a literal key. + * + */ + bool IsKeyRef(void) const { return (mKey == nullptr); } + + /** + * This method gets the `KeyRef`. + * + * This method MUST be used when `IsKeyRef()` returns `true`, otherwise its behavior is undefined. + * + * @returns The `KeyRef` associated with `Key`. + * + */ + Storage::KeyRef GetKeyRef(void) const { return mKeyRef; } + + /** + * This method sets the `Key` as a `KeyRef`. + * + * @param[in] aKeyRef The `KeyRef` to set from. + * + */ + void SetAsKeyRef(Storage::KeyRef aKeyRef) + { + mKey = nullptr; + mKeyLength = 0; + mKeyRef = aKeyRef; + } + + /** + * This method extracts and return the literal key when the key is represented as a `KeyRef` + * + * This method MUST be used when `IsKeyRef()` returns `true`. + * + * @param[out] aKeyBuffer Pointer to a byte array buffer to place the extracted key. + * @param[inout] aKeyLength On input, the size of @p aKeyBuffer. + * On exit, returns the key length (number of bytes written in @p aKeyBuffer). + * + * @retval kErrorNone Successfully extracted the key, @p aKeyBuffer and @p aKeyLength are updated. + * @retval kErrorNoBufs Key does not fit in @p aKeyBuffer (extracted key length is larger than @p aKeyLength). + * + */ + Error ExtractKey(uint8_t *aKeyBuffer, uint16_t &aKeyLength) const; +#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +}; + +/** + * This class represents a literal key derived from a `Key`. + * + */ +class LiteralKey : public Clearable, private NonCopyable +{ +public: + static constexpr uint16_t kMaxSize = 32; ///< Maximum size of the key. + + /** + * This constructor initializes the `LiteralKey` from a given `Key`. + * + * If the @p aKey is itself represents a literal key the same key buffer pointers are used. If the @p aKey is + * a `KeyRef` then the literal key is extracted. In this case, the extracted key MUST be smaller than `kMaxSize`. + * + * @param[in] aKey The key to convert from. + * + */ + explicit LiteralKey(const Key &aKey); + + /* + * This method gets the pointer to the byte array containing the literal key. + * + * @returns The pointer to the byte array containing the literal key. + * + */ + const uint8_t *GetBytes(void) const { return mKey; } + + /** + * This method gets the key length. + * + * @returns The key length (number of bytes in the byte array from `GetBytes()`). + * + */ + uint16_t GetLength(void) const { return mLength; } + +private: + const uint8_t *mKey; + uint16_t mLength; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + uint8_t mBuffer[kMaxSize]; +#endif +}; + +} // namespace Crypto +} // namespace ot + +#endif // STORAGE_HPP_ diff --git a/src/core/mac/link_raw.cpp b/src/core/mac/link_raw.cpp index 400842694..550c44f57 100644 --- a/src/core/mac/link_raw.cpp +++ b/src/core/mac/link_raw.cpp @@ -225,10 +225,18 @@ Error LinkRaw::SetMacKey(uint8_t aKeyIdMode, const Key &aCurrKey, const Key &aNextKey) { - Error error = kErrorNone; + Error error = kErrorNone; + KeyMaterial prevKey; + KeyMaterial currKey; + KeyMaterial nextKey; VerifyOrExit(IsEnabled(), error = kErrorInvalidState); - mSubMac.SetMacKey(aKeyIdMode, aKeyId, aPrevKey, aCurrKey, aNextKey); + + prevKey.SetFrom(aPrevKey); + currKey.SetFrom(aCurrKey); + nextKey.SetFrom(aNextKey); + + mSubMac.SetMacKey(aKeyIdMode, aKeyId, prevKey, currKey, nextKey); exit: return error; diff --git a/src/core/mac/link_raw.hpp b/src/core/mac/link_raw.hpp index 318acc8b8..2f1bbf02c 100644 --- a/src/core/mac/link_raw.hpp +++ b/src/core/mac/link_raw.hpp @@ -254,6 +254,7 @@ public: * @param[in] aNextKey The next MAC key. * * @retval kErrorNone If successful. + * @retval kErrorFailed Platform failed to import key. * @retval kErrorInvalidState If the raw link-layer isn't enabled. * */ diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 1299fd752..546e8db8e 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -56,9 +56,6 @@ namespace ot { namespace Mac { -const otMacKey Mac::sMode2Key = { - {0x78, 0x58, 0x16, 0x86, 0xfd, 0xb4, 0x58, 0x0f, 0xb0, 0x92, 0x54, 0x6a, 0xec, 0xbd, 0x15, 0x66}}; - const otExtAddress Mac::sMode2ExtAddress = { {0x35, 0x06, 0xfe, 0xb8, 0x23, 0xd4, 0x87, 0x12}, }; @@ -127,6 +124,9 @@ Mac::Mac(Instance &aInstance) { ExtAddress randomExtAddress; + static const otMacKey sMode2Key = { + {0x78, 0x58, 0x16, 0x86, 0xfd, 0xb4, 0x58, 0x0f, 0xb0, 0x92, 0x54, 0x6a, 0xec, 0xbd, 0x15, 0x66}}; + randomExtAddress.GenerateRandom(); mCcaSuccessRateTracker.Clear(); @@ -145,6 +145,8 @@ Mac::Mac(Instance &aInstance) SetPanId(mPanId); SetExtAddress(randomExtAddress); SetShortAddress(GetShortAddress()); + + mMode2KeyMaterial.SetFrom(static_cast(sMode2Key)); } Error Mac::ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext) @@ -999,7 +1001,8 @@ void Mac::ProcessTransmitSecurity(TxFrame &aFrame) case Frame::kKeyIdMode2: { const uint8_t keySource[] = {0xff, 0xff, 0xff, 0xff}; - aFrame.SetAesKey(static_cast(sMode2Key)); + aFrame.SetAesKey(static_cast(mMode2KeyMaterial)); + mKeyIdMode2FrameCounter++; aFrame.SetFrameCounter(mKeyIdMode2FrameCounter); aFrame.SetKeySource(keySource); @@ -1613,15 +1616,15 @@ void Mac::HandleTimer(void) Error Mac::ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor) { - KeyManager & keyManager = Get(); - Error error = kErrorSecurity; - uint8_t securityLevel; - uint8_t keyIdMode; - uint32_t frameCounter; - uint8_t keyid; - uint32_t keySequence = 0; - const Key * macKey; - const ExtAddress *extAddress; + KeyManager & keyManager = Get(); + Error error = kErrorSecurity; + uint8_t securityLevel; + uint8_t keyIdMode; + uint32_t frameCounter; + uint8_t keyid; + uint32_t keySequence = 0; + const KeyMaterial *macKey; + const ExtAddress * extAddress; VerifyOrExit(aFrame.GetSecurityEnabled(), error = kErrorNone); @@ -1697,7 +1700,7 @@ Error Mac::ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neig break; case Frame::kKeyIdMode2: - macKey = static_cast(&sMode2Key); + macKey = static_cast(&mMode2KeyMaterial); extAddress = static_cast(&sMode2ExtAddress); break; @@ -1749,17 +1752,17 @@ exit: #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 Error Mac::ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame) { - Error error = kErrorSecurity; - uint8_t securityLevel; - uint8_t txKeyId; - uint8_t ackKeyId; - uint8_t keyIdMode; - uint32_t frameCounter; - Address srcAddr; - Address dstAddr; - Neighbor * neighbor = nullptr; - KeyManager &keyManager = Get(); - const Key * macKey; + Error error = kErrorSecurity; + uint8_t securityLevel; + uint8_t txKeyId; + uint8_t ackKeyId; + uint8_t keyIdMode; + uint32_t frameCounter; + Address srcAddr; + Address dstAddr; + Neighbor * neighbor = nullptr; + KeyManager & keyManager = Get(); + const KeyMaterial *macKey; VerifyOrExit(aAckFrame.GetSecurityEnabled(), error = kErrorNone); VerifyOrExit(aAckFrame.IsVersion2015()); diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index 89a2642a5..7746909fa 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -842,7 +842,6 @@ private: #endif static const char *OperationToString(Operation aOperation); - static const otMacKey sMode2Key; static const otExtAddress sMode2ExtAddress; static const otExtendedPanId sExtendedPanidInit; static const char sNetworkNameInit[]; @@ -923,6 +922,8 @@ private: #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE Filter mFilter; #endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE + + KeyMaterial mMode2KeyMaterial; }; /** diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index c51e52336..adc50dff3 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -1329,7 +1329,7 @@ exit: } #endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 -Error RxFrame::ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const Key &aMacKey) +Error RxFrame::ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const KeyMaterial &aMacKey) { #if OPENTHREAD_RADIO OT_UNUSED_VARIABLE(aExtAddress); diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index a815c127d..fbe1314d0 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -1166,7 +1166,7 @@ public: * @retval kErrorSecurity Received frame MIC check failed. * */ - Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const Key &aMacKey); + Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const KeyMaterial &aMacKey); #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE /** @@ -1281,7 +1281,10 @@ public: * @returns The pointer to the key. * */ - const Mac::Key &GetAesKey(void) const { return *static_cast(mInfo.mTxInfo.mAesKey); } + const Mac::KeyMaterial &GetAesKey(void) const + { + return *static_cast(mInfo.mTxInfo.mAesKey); + } /** * This method sets the key used for frame encryption and authentication (AES CCM). @@ -1289,7 +1292,7 @@ public: * @param[in] aAesKey The pointer to the key. * */ - void SetAesKey(const Mac::Key &aAesKey) { mInfo.mTxInfo.mAesKey = &aAesKey; } + void SetAesKey(const Mac::KeyMaterial &aAesKey) { mInfo.mTxInfo.mAesKey = &aAesKey; } /** * This method copies the PSDU and all attributes (except for frame link type) from another frame. diff --git a/src/core/mac/mac_links.cpp b/src/core/mac/mac_links.cpp index dd2ce65cf..e988a1fba 100644 --- a/src/core/mac/mac_links.cpp +++ b/src/core/mac/mac_links.cpp @@ -172,11 +172,11 @@ void Links::Send(TxFrame &aFrame, RadioTypes aRadioTypes) #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO -const Key *Links::GetCurrentMacKey(const Frame &aFrame) const +const KeyMaterial *Links::GetCurrentMacKey(const Frame &aFrame) const { // Gets the security MAC key (for Key Mode 1) based on radio link type of `aFrame`. - const Key *key = nullptr; + const KeyMaterial *key = nullptr; #if OPENTHREAD_CONFIG_MULTI_RADIO RadioType radioType = aFrame.GetRadioType(); #endif @@ -205,12 +205,12 @@ exit: return key; } -const Key *Links::GetTemporaryMacKey(const Frame &aFrame, uint32_t aKeySequence) const +const KeyMaterial *Links::GetTemporaryMacKey(const Frame &aFrame, uint32_t aKeySequence) const { // Gets the security MAC key (for Key Mode 1) based on radio link // type of `aFrame` and given Key Sequence. - const Key *key = nullptr; + const KeyMaterial *key = nullptr; #if OPENTHREAD_CONFIG_MULTI_RADIO RadioType radioType = aFrame.GetRadioType(); #endif diff --git a/src/core/mac/mac_links.hpp b/src/core/mac/mac_links.hpp index 21b0694e3..b818632bd 100644 --- a/src/core/mac/mac_links.hpp +++ b/src/core/mac/mac_links.hpp @@ -633,7 +633,7 @@ public: * @returns A reference to the current MAC key. * */ - const Key *GetCurrentMacKey(const Frame &aFrame) const; + const KeyMaterial *GetCurrentMacKey(const Frame &aFrame) const; /** * This method returns a reference to the temporary MAC key (for Key Mode 1) for a given Frame based on a given @@ -645,7 +645,7 @@ public: * @returns A reference to the temporary MAC key. * */ - const Key *GetTemporaryMacKey(const Frame &aFrame, uint32_t aKeySequence) const; + const KeyMaterial *GetTemporaryMacKey(const Frame &aFrame, uint32_t aKeySequence) const; #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE /** diff --git a/src/core/mac/mac_types.cpp b/src/core/mac/mac_types.cpp index 8e70ad356..62d6780c5 100644 --- a/src/core/mac/mac_types.cpp +++ b/src/core/mac/mac_types.cpp @@ -334,5 +334,98 @@ void LinkFrameCounters::SetAll(uint32_t aCounter) #endif } +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +KeyMaterial &KeyMaterial::operator=(const KeyMaterial &aOther) +{ + VerifyOrExit(GetKeyRef() != aOther.GetKeyRef()); + DestroyKey(); + SetKeyRef(aOther.GetKeyRef()); + +exit: + return *this; +} +#endif + +void KeyMaterial::Clear(void) +{ +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + DestroyKey(); + SetKeyRef(kInvalidKeyRef); +#else + GetKey().Clear(); +#endif +} + +void KeyMaterial::SetFrom(const Key &aKey, bool aIsExportable) +{ +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + { + Error error; + KeyRef keyRef = 0; + + DestroyKey(); + + error = Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes, Crypto::Storage::kKeyAlgorithmAesEcb, + (aIsExportable ? Crypto::Storage::kUsageExport : 0) | + Crypto::Storage::kUsageEncrypt | Crypto::Storage::kUsageDecrypt, + Crypto::Storage::kTypeVolatile, aKey.GetBytes(), Key::kSize); + + OT_ASSERT(error == kErrorNone); + OT_UNUSED_VARIABLE(error); + + SetKeyRef(keyRef); + } +#else + SetKey(aKey); + OT_UNUSED_VARIABLE(aIsExportable); +#endif +} + +void KeyMaterial::ExtractKey(Key &aKey) +{ +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + aKey.Clear(); + + if (Crypto::Storage::IsKeyRefValid(GetKeyRef())) + { + Error error; + size_t keySize; + + error = Crypto::Storage::ExportKey(GetKeyRef(), aKey.m8, Key::kSize, keySize); + OT_ASSERT(error == kErrorNone); + OT_UNUSED_VARIABLE(error); + } +#else + aKey = GetKey(); +#endif +} + +void KeyMaterial::ConvertToCryptoKey(Crypto::Key &aCryptoKey) const +{ +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + aCryptoKey.SetAsKeyRef(GetKeyRef()); +#else + aCryptoKey.Set(GetKey().GetBytes(), Key::kSize); +#endif +} + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +void KeyMaterial::DestroyKey(void) +{ + Crypto::Storage::DestroyKey(GetKeyRef()); + SetKeyRef(kInvalidKeyRef); +} +#endif + +bool KeyMaterial::operator==(const KeyMaterial &aOther) const +{ + return +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + (GetKeyRef() == aOther.GetKeyRef()); +#else + (GetKey() == aOther.GetKey()); +#endif +} + } // namespace Mac } // namespace ot diff --git a/src/core/mac/mac_types.hpp b/src/core/mac/mac_types.hpp index 2db9c9a37..f04dfed17 100644 --- a/src/core/mac/mac_types.hpp +++ b/src/core/mac/mac_types.hpp @@ -45,6 +45,7 @@ #include "common/clearable.hpp" #include "common/equatable.hpp" #include "common/string.hpp" +#include "crypto/storage.hpp" namespace ot { namespace Mac { @@ -419,15 +420,137 @@ public: static constexpr uint16_t kSize = OT_MAC_KEY_SIZE; ///< Key size in bytes. /** - * This method gets a pointer to the buffer containing the key. + * This method gets a pointer to the bytes array containing the key * - * @returns A pointer to the buffer containing the key. + * @returns A pointer to the byte array containing the key. * */ - const uint8_t *GetKey(void) const { return m8; } + const uint8_t *GetBytes(void) const { return m8; } } OT_TOOL_PACKED_END; +/** + * This type represents a MAC Key Ref used by PSA. + * + */ +typedef otMacKeyRef KeyRef; + +/** + * This class represents a MAC Key Material. + * + */ +OT_TOOL_PACKED_BEGIN +class KeyMaterial : public otMacKeyMaterial, public Unequatable +{ +public: + /** + * This constructor initializes a `KeyMaterial`. + * + */ + KeyMaterial(void) + { + GetKey().Clear(); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SetKeyRef(kInvalidKeyRef); +#endif + } + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + /** + * This method overload `=` operator to assign the `KeyMaterial` from another one. + * + * If the `KeyMaterial` currently stores a valid and different `KeyRef`, the assignment of new value will ensure to + * delete the previous one before using the new `KeyRef` from @p aOther. + * + * @param[in] aOther aOther The other `KeyMaterial` instance to assign from. + * + * @returns A reference to the current `KeyMaterial` + * + */ + KeyMaterial &operator=(const KeyMaterial &aOther); +#endif + + /** + * This method clears the `KeyMaterial`. + * + * Under `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE`, if the `KeyMaterial` currently stores a valid previous + * `KeyRef`, the `Clear()` call will ensure to delete the previous `KeyRef` and set it to `kInvalidKeyRef`. + * + */ + void Clear(void); + +#if !OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + /** + * This method gets the literal `Key`. + * + * @returns The literal `Key` + * + */ + const Key &GetKey(void) const { return static_cast(mKeyMaterial.mKey); } + +#else + /** + * This method gets the stored `KeyRef` + * + * @returns The `KeyRef` + * + */ + KeyRef GetKeyRef(void) const { return mKeyMaterial.mKeyRef; } +#endif + + /** + * This method sets the `KeyMaterial` from a given Key. + * + * If the `KeyMaterial` currently stores a valid `KeyRef`, the `SetFrom()` call will ensure to delete the previous + * one before creating and using a new `KeyRef` associated with the new `Key`. + * + * @param[in] aKey A reference to the new key. + * @param[in] aIsExportable Boolean indicating if the key is exportable (this is only applicable under + * `OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE` config). + * + */ + void SetFrom(const Key &aKey, bool aIsExportable = false); + + /** + * This method extracts the literal key from `KeyMaterial` + * + * @param[out] aKey A reference to the output the key. + * + */ + void ExtractKey(Key &aKey); + + /** + * This method converts `KeyMaterial` to a `Crypto::Key`. + * + * @param[out] A reference to a `Crypto::Key` to populate. + * + */ + void ConvertToCryptoKey(Crypto::Key &aCryptoKey) const; + + /** + * This method overloads operator `==` to evaluate whether or not two `KeyMaterial` instances are equal. + * + * @param[in] aOther The other `KeyMaterial` instance to compare with. + * + * @retval TRUE If the two `KeyMaterial` instances are equal. + * @retval FALSE If the two `KeyMaterial` instances are not equal. + * + */ + bool operator==(const KeyMaterial &aOther) const; + + KeyMaterial(const KeyMaterial &) = delete; + +private: +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + static constexpr KeyRef kInvalidKeyRef = Crypto::Storage::kInvalidKeyRef; + + void DestroyKey(void); + void SetKeyRef(KeyRef aKeyRef) { mKeyMaterial.mKeyRef = aKeyRef; } +#endif + Key &GetKey(void) { return static_cast(mKeyMaterial.mKey); } + void SetKey(const Key &aKey) { mKeyMaterial.mKey = aKey; } +} OT_TOOL_PACKED_END; + /** * This structure represents an IEEE 802.15.4 Extended PAN Identifier. * diff --git a/src/core/mac/sub_mac.cpp b/src/core/mac/sub_mac.cpp index 0b5f89ad6..b05324961 100644 --- a/src/core/mac/sub_mac.cpp +++ b/src/core/mac/sub_mac.cpp @@ -78,9 +78,6 @@ SubMac::SubMac(Instance &aInstance) #endif { mExtAddress.Clear(); - mPrevKey.Clear(); - mCurrKey.Clear(); - mNextKey.Clear(); } otRadioCaps SubMac::GetCaps(void) const @@ -832,11 +829,11 @@ void SubMac::SetState(State aState) } } -void SubMac::SetMacKey(uint8_t aKeyIdMode, - uint8_t aKeyId, - const Key &aPrevKey, - const Key &aCurrKey, - const Key &aNextKey) +void SubMac::SetMacKey(uint8_t aKeyIdMode, + uint8_t aKeyId, + const KeyMaterial &aPrevKey, + const KeyMaterial &aCurrKey, + const KeyMaterial &aNextKey) { switch (aKeyIdMode) { diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp index cfe9be2cc..873708762 100644 --- a/src/core/mac/sub_mac.hpp +++ b/src/core/mac/sub_mac.hpp @@ -38,6 +38,8 @@ #include +#include + #include "common/locator.hpp" #include "common/non_copyable.hpp" #include "common/timer.hpp" @@ -492,7 +494,11 @@ public: * @param[in] aNextKey The next MAC key. * */ - void SetMacKey(uint8_t aKeyIdMode, uint8_t aKeyId, const Key &aPrevKey, const Key &aCurrKey, const Key &aNextKey); + void SetMacKey(uint8_t aKeyIdMode, + uint8_t aKeyId, + const KeyMaterial &aPrevKey, + const KeyMaterial &aCurrKey, + const KeyMaterial &aNextKey); /** * This method returns a reference to the current MAC key. @@ -500,7 +506,7 @@ public: * @returns A reference to the current MAC key. * */ - const Key &GetCurrentMacKey(void) const { return mCurrKey; } + const KeyMaterial &GetCurrentMacKey(void) const { return mCurrKey; } /** * This method returns a reference to the previous MAC key. @@ -508,7 +514,7 @@ public: * @returns A reference to the previous MAC key. * */ - const Key &GetPreviousMacKey(void) const { return mPrevKey; } + const KeyMaterial &GetPreviousMacKey(void) const { return mPrevKey; } /** * This method returns a reference to the next MAC key. @@ -516,7 +522,7 @@ public: * @returns A reference to the next MAC key. * */ - const Key &GetNextMacKey(void) const { return mNextKey; } + const KeyMaterial &GetNextMacKey(void) const { return mNextKey; } /** * This method returns the current MAC frame counter value. @@ -642,9 +648,9 @@ private: Callbacks mCallbacks; otLinkPcapCallback mPcapCallback; void * mPcapCallbackContext; - Key mPrevKey; - Key mCurrKey; - Key mNextKey; + KeyMaterial mPrevKey; + KeyMaterial mCurrKey; + KeyMaterial mNextKey; uint32_t mFrameCounter; uint8_t mKeyId; #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 61569ed10..3932edb34 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -583,11 +583,15 @@ void BorderAgent::Start(void) { Error error; Coap::CoapSecure &coaps = Get(); + Pskc pskc; VerifyOrExit(mState == kStateStopped, error = kErrorAlready); + Get().GetPskc(pskc); SuccessOrExit(error = coaps.Start(kBorderAgentUdpPort)); - SuccessOrExit(error = coaps.SetPsk(Get().GetPskc().m8, OT_PSKC_MAX_SIZE)); + SuccessOrExit(error = coaps.SetPsk(pskc.m8, Pskc::kSize)); + + pskc.Clear(); coaps.SetConnectedCallback(HandleConnected, this); coaps.AddResource(mActiveGet); diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index 87f3c8397..6032bff4f 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -1163,9 +1163,12 @@ Error Commissioner::SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo Coap::Message * message; uint16_t offset; Ip6::MessageInfo messageInfo; + Kek kek; VerifyOrExit((message = NewMeshCoPMessage(Get())) != nullptr, error = kErrorNoBufs); + Get().ExtractKek(kek); + message->InitAsNonConfirmablePost(); SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kRelayTx)); SuccessOrExit(error = message->SetPayloadMarker()); @@ -1176,7 +1179,7 @@ Error Commissioner::SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo if (aMessage.GetSubType() == Message::kSubTypeJoinerFinalizeResponse) { - SuccessOrExit(error = Tlv::Append(*message, Get().GetKek())); + SuccessOrExit(error = Tlv::Append(*message, kek)); } tlv.SetType(Tlv::kJoinerDtlsEncapsulation); diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index a75ab4e19..19a61d8a3 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -564,13 +564,16 @@ Error Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdate case Tlv::kNetworkKey: { const NetworkKeyTlv *key = static_cast(cur); + NetworkKey networkKey; - if (aIsNetworkKeyUpdated && (key->GetNetworkKey() != keyManager.GetNetworkKey())) + keyManager.GetNetworkKey(networkKey); + + if (aIsNetworkKeyUpdated && (key->GetNetworkKey() != networkKey)) { *aIsNetworkKeyUpdated = true; } - IgnoreError(keyManager.SetNetworkKey(key->GetNetworkKey())); + keyManager.SetNetworkKey(key->GetNetworkKey()); break; } diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index b5cdded43..bdc18d7e4 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -154,9 +154,12 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo // check network key if (Tlv::Find(aMessage, networkKey) == kErrorNone) { - hasNetworkKey = true; + NetworkKey localNetworkKey; - if (networkKey != Get().GetNetworkKey()) + hasNetworkKey = true; + Get().GetNetworkKey(localNetworkKey); + + if (networkKey != localNetworkKey) { doesAffectConnectivity = true; doesAffectNetworkKey = true; @@ -164,7 +167,7 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo } // check active timestamp rollback - if (type == Tlv::kPendingTimestamp && (!hasNetworkKey || (networkKey == Get().GetNetworkKey()))) + if (type == Tlv::kPendingTimestamp && (!hasNetworkKey || !doesAffectNetworkKey)) { // no change to network key, active timestamp must be ahead const Timestamp *localActiveTimestamp = Get().GetTimestamp(); @@ -353,7 +356,10 @@ Error ActiveDataset::GenerateLocal(void) if (dataset.GetTlv() == nullptr) { - IgnoreError(dataset.SetTlv(Tlv::kNetworkKey, Get().GetNetworkKey())); + NetworkKey networkKey; + + Get().GetNetworkKey(networkKey); + IgnoreError(dataset.SetTlv(Tlv::kNetworkKey, networkKey)); } if (dataset.GetTlv() == nullptr) @@ -370,18 +376,18 @@ Error ActiveDataset::GenerateLocal(void) if (dataset.GetTlv() == nullptr) { + Pskc pskc; + if (Get().IsPskcSet()) { - IgnoreError(dataset.SetTlv(Tlv::kPskc, Get().GetPskc())); + Get().GetPskc(pskc); } else { - // PSKc has not yet been configured, generate new PSKc at random - Pskc pskc; - SuccessOrExit(error = pskc.GenerateRandom()); - IgnoreError(dataset.SetTlv(Tlv::kPskc, pskc)); } + + IgnoreError(dataset.SetTlv(Tlv::kPskc, pskc)); } if (dataset.GetTlv() == nullptr) diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index 5d683cdbf..3f3ee0545 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -314,9 +314,9 @@ Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void) Error error; Coap::Message *message = nullptr; Dataset dataset; - NetworkNameTlv networkName; const Tlv * tlv; + NetworkKey networkKey; VerifyOrExit((message = NewMeshCoPMessage(Get())) != nullptr, error = kErrorNoBufs); @@ -325,7 +325,8 @@ Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void) SuccessOrExit(error = message->SetPayloadMarker()); message->SetSubType(Message::kSubTypeJoinerEntrust); - SuccessOrExit(error = Tlv::Append(*message, Get().GetNetworkKey())); + Get().GetNetworkKey(networkKey); + SuccessOrExit(error = Tlv::Append(*message, networkKey)); SuccessOrExit(error = Tlv::Append(*message, Get().GetMeshLocalPrefix())); SuccessOrExit(error = Tlv::Append(*message, Get().GetExtendedPanId())); diff --git a/src/core/radio.cmake b/src/core/radio.cmake index 79e501fd2..dfc619922 100644 --- a/src/core/radio.cmake +++ b/src/core/radio.cmake @@ -56,6 +56,9 @@ target_sources(openthread-radio PRIVATE common/uptime.cpp crypto/aes_ccm.cpp crypto/aes_ecb.cpp + crypto/crypto_platform.cpp + crypto/hmac_sha256.cpp + crypto/storage.cpp diags/factory_diags.cpp mac/link_raw.cpp mac/mac_frame.cpp diff --git a/src/core/radio/radio.hpp b/src/core/radio/radio.hpp index 3deea9bd4..25c7170ea 100644 --- a/src/core/radio/radio.hpp +++ b/src/core/radio/radio.hpp @@ -38,6 +38,7 @@ #include +#include #include "common/locator.hpp" #include "common/non_copyable.hpp" #include "mac/mac_frame.hpp" @@ -277,11 +278,11 @@ public: * @param[in] aNextKey The next MAC key. * */ - void SetMacKey(uint8_t aKeyIdMode, - uint8_t aKeyId, - const Mac::Key &aPrevKey, - const Mac::Key &aCurrKey, - const Mac::Key &aNextKey); + void SetMacKey(uint8_t aKeyIdMode, + uint8_t aKeyId, + const Mac::KeyMaterial &aPrevKey, + const Mac::KeyMaterial &aCurrKey, + const Mac::KeyMaterial &aNextKey); /** * This method sets the current MAC Frame Counter value. @@ -704,13 +705,21 @@ inline void Radio::SetPanId(Mac::PanId aPanId) otPlatRadioSetPanId(GetInstancePtr(), aPanId); } -inline void Radio::SetMacKey(uint8_t aKeyIdMode, - uint8_t aKeyId, - const Mac::Key &aPrevKey, - const Mac::Key &aCurrKey, - const Mac::Key &aNextKey) +inline void Radio::SetMacKey(uint8_t aKeyIdMode, + uint8_t aKeyId, + const Mac::KeyMaterial &aPrevKey, + const Mac::KeyMaterial &aCurrKey, + const Mac::KeyMaterial &aNextKey) { - otPlatRadioSetMacKey(GetInstancePtr(), aKeyIdMode, aKeyId, &aPrevKey, &aCurrKey, &aNextKey); + otRadioKeyType aKeyType; + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + aKeyType = OT_KEY_TYPE_KEY_REF; +#else + aKeyType = OT_KEY_TYPE_LITERAL_KEY; +#endif + + otPlatRadioSetMacKey(GetInstancePtr(), aKeyIdMode, aKeyId, &aPrevKey, &aCurrKey, &aNextKey, aKeyType); } inline Error Radio::GetTransmitPower(int8_t &aPower) @@ -876,7 +885,11 @@ inline void Radio::SetShortAddress(Mac::ShortAddress) { } -inline void Radio::SetMacKey(uint8_t, uint8_t, const Mac::Key &, const Mac::Key &, const Mac::Key &) +inline void Radio::SetMacKey(uint8_t, + uint8_t, + const Mac::KeyMaterial &, + const Mac::KeyMaterial &, + const Mac::KeyMaterial &) { } diff --git a/src/core/radio/radio_platform.cpp b/src/core/radio/radio_platform.cpp index f673b9124..7ff553bb1 100644 --- a/src/core/radio/radio_platform.cpp +++ b/src/core/radio/radio_platform.cpp @@ -202,12 +202,13 @@ OT_TOOL_WEAK otRadioState otPlatRadioGetState(otInstance *aInstance) return OT_RADIO_STATE_INVALID; } -OT_TOOL_WEAK void otPlatRadioSetMacKey(otInstance * aInstance, - uint8_t aKeyIdMode, - uint8_t aKeyId, - const otMacKey *aPrevKey, - const otMacKey *aCurrKey, - const otMacKey *aNextKey) +OT_TOOL_WEAK void otPlatRadioSetMacKey(otInstance * aInstance, + uint8_t aKeyIdMode, + uint8_t aKeyId, + const otMacKeyMaterial *aPrevKey, + const otMacKeyMaterial *aCurrKey, + const otMacKeyMaterial *aNextKey, + otRadioKeyType aKeyType) { OT_UNUSED_VARIABLE(aInstance); OT_UNUSED_VARIABLE(aKeyIdMode); @@ -215,6 +216,7 @@ OT_TOOL_WEAK void otPlatRadioSetMacKey(otInstance * aInstance, OT_UNUSED_VARIABLE(aPrevKey); OT_UNUSED_VARIABLE(aCurrKey); OT_UNUSED_VARIABLE(aNextKey); + OT_UNUSED_VARIABLE(aKeyType); } OT_TOOL_WEAK void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter) diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp index 67983a17f..6d9a7d850 100644 --- a/src/core/thread/key_manager.cpp +++ b/src/core/thread/key_manager.cpp @@ -39,6 +39,7 @@ #include "common/locator_getters.hpp" #include "common/timer.hpp" #include "crypto/hkdf_sha256.hpp" +#include "crypto/storage.hpp" #include "thread/mle_router.hpp" #include "thread/thread_netif.hpp" @@ -179,13 +180,24 @@ KeyManager::KeyManager(Instance &aInstance) , mKekFrameCounter(0) , mIsPskcSet(false) { - Error error = mNetworkKey.GenerateRandom(); + IgnoreError(otPlatCryptoInit()); - OT_ASSERT(error == kErrorNone); - OT_UNUSED_VARIABLE(error); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + { + NetworkKey networkKey; + + mNetworkKeyRef = Crypto::Storage::kInvalidKeyRef; + mPskcRef = Crypto::Storage::kInvalidKeyRef; + + IgnoreError(networkKey.GenerateRandom()); + StoreNetworkKey(networkKey, /* aOverWriteExisting */ false); + } +#else + IgnoreError(mNetworkKey.GenerateRandom()); + mPskc.Clear(); +#endif mMacFrameCounters.Reset(); - mPskc.Clear(); } void KeyManager::Start(void) @@ -199,24 +211,31 @@ void KeyManager::Stop(void) mKeyRotationTimer.Stop(); } -#if OPENTHREAD_MTD || OPENTHREAD_FTD void KeyManager::SetPskc(const Pskc &aPskc) { - IgnoreError(Get().Update(mPskc, aPskc, kEventPskcChanged)); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + if (Crypto::Storage::IsKeyRefValid(mPskcRef)) + { + Pskc pskc; + + GetPskc(pskc); + VerifyOrExit(aPskc != pskc, Get().SignalIfFirst(kEventPskcChanged)); + } + + StorePskc(aPskc); + Get().Signal(kEventPskcChanged); +#else + SuccessOrExit(Get().Update(mPskc, aPskc, kEventPskcChanged)); +#endif + +exit: mIsPskcSet = true; } -#endif // OPENTHREAD_MTD || OPENTHREAD_FTD -Error KeyManager::SetNetworkKey(const NetworkKey &aKey) +void KeyManager::ResetFrameCounters(void) { - Error error = kErrorNone; Router *parent; - SuccessOrExit(Get().Update(mNetworkKey, aKey, kEventNetworkKeyChanged)); - Get().Signal(kEventThreadKeySeqCounterChanged); - mKeySequence = 0; - UpdateKeyMaterial(); - // reset parent frame counters parent = &Get().GetParent(); parent->SetKeySequence(0); @@ -243,17 +262,48 @@ Error KeyManager::SetNetworkKey(const NetworkKey &aKey) child.SetMleFrameCounter(0); } #endif +} + +void KeyManager::SetNetworkKey(const NetworkKey &aNetworkKey) +{ +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + if (Crypto::Storage::IsKeyRefValid(mNetworkKeyRef)) + { + NetworkKey networkKey; + + GetNetworkKey(networkKey); + VerifyOrExit(networkKey != aNetworkKey, Get().SignalIfFirst(kEventNetworkKeyChanged)); + } + + StoreNetworkKey(aNetworkKey, /* aOverWriteExisting */ true); + Get().Signal(kEventNetworkKeyChanged); +#else + SuccessOrExit(Get().Update(mNetworkKey, aNetworkKey, kEventNetworkKeyChanged)); +#endif + + Get().Signal(kEventThreadKeySeqCounterChanged); + + mKeySequence = 0; + UpdateKeyMaterial(); + ResetFrameCounters(); exit: - return error; + return; } void KeyManager::ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys) { Crypto::HmacSha256 hmac; uint8_t keySequenceBytes[sizeof(uint32_t)]; + Crypto::Key cryptoKey; - hmac.Start(mNetworkKey.m8, sizeof(mNetworkKey.m8)); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + cryptoKey.SetAsKeyRef(mNetworkKeyRef); +#else + cryptoKey.Set(mNetworkKey.m8, NetworkKey::kSize); +#endif + + hmac.Start(cryptoKey); Encoding::BigEndian::WriteUint32(aKeySequence, keySequenceBytes); hmac.Update(keySequenceBytes); @@ -263,40 +313,59 @@ void KeyManager::ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys) } #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE -void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aTrelKey) +void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) { Crypto::HkdfSha256 hkdf; uint8_t salt[sizeof(uint32_t) + sizeof(kHkdfExtractSaltString)]; + Crypto::Key cryptoKey; + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + cryptoKey.SetAsKeyRef(mNetworkKeyRef); +#else + cryptoKey.Set(mNetworkKey.m8, NetworkKey::kSize); +#endif Encoding::BigEndian::WriteUint32(aKeySequence, salt); memcpy(salt + sizeof(uint32_t), kHkdfExtractSaltString, sizeof(kHkdfExtractSaltString)); - hkdf.Extract(salt, sizeof(salt), mNetworkKey.m8, sizeof(NetworkKey)); - hkdf.Expand(kTrelInfoString, sizeof(kTrelInfoString), aTrelKey.m8, sizeof(Mac::Key)); + hkdf.Extract(salt, sizeof(salt), cryptoKey); + hkdf.Expand(kTrelInfoString, sizeof(kTrelInfoString), aKey.m8, Mac::Key::kSize); } #endif void KeyManager::UpdateKeyMaterial(void) { - HashKeys cur; -#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE - HashKeys prev; - HashKeys next; -#endif + HashKeys hashKeys; - ComputeKeys(mKeySequence, cur); - mMleKey = cur.mKeys.mMleKey; + ComputeKeys(mKeySequence, hashKeys); + + mMleKey.SetFrom(hashKeys.GetMleKey()); #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE - ComputeKeys(mKeySequence - 1, prev); - ComputeKeys(mKeySequence + 1, next); + { + Mac::KeyMaterial curKey; + Mac::KeyMaterial prevKey; + Mac::KeyMaterial nextKey; - Get().SetMacKey(Mac::Frame::kKeyIdMode1, (mKeySequence & 0x7f) + 1, prev.mKeys.mMacKey, - cur.mKeys.mMacKey, next.mKeys.mMacKey); + curKey.SetFrom(hashKeys.GetMacKey()); + + ComputeKeys(mKeySequence - 1, hashKeys); + prevKey.SetFrom(hashKeys.GetMacKey()); + + ComputeKeys(mKeySequence + 1, hashKeys); + nextKey.SetFrom(hashKeys.GetMacKey()); + + Get().SetMacKey(Mac::Frame::kKeyIdMode1, (mKeySequence & 0x7f) + 1, prevKey, curKey, nextKey); + } #endif #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE - ComputeTrelKey(mKeySequence, mTrelKey); + { + Mac::Key key; + + ComputeTrelKey(mKeySequence, key); + mTrelKey.SetFrom(key); + } #endif } @@ -328,20 +397,23 @@ exit: return; } -const Mle::Key &KeyManager::GetTemporaryMleKey(uint32_t aKeySequence) +const Mle::KeyMaterial &KeyManager::GetTemporaryMleKey(uint32_t aKeySequence) { HashKeys hashKeys; ComputeKeys(aKeySequence, hashKeys); - mTemporaryMleKey = hashKeys.mKeys.mMleKey; + mTemporaryMleKey.SetFrom(hashKeys.GetMleKey()); return mTemporaryMleKey; } #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE -const Mac::Key &KeyManager::GetTemporaryTrelMacKey(uint32_t aKeySequence) +const Mac::KeyMaterial &KeyManager::GetTemporaryTrelMacKey(uint32_t aKeySequence) { - ComputeTrelKey(aKeySequence, mTemporaryTrelKey); + Mac::Key key; + + ComputeTrelKey(aKeySequence, key); + mTemporaryTrelKey.SetFrom(key); return mTemporaryTrelKey; } @@ -396,13 +468,7 @@ void KeyManager::IncrementMleFrameCounter(void) void KeyManager::SetKek(const Kek &aKek) { - mKek = aKek; - mKekFrameCounter = 0; -} - -void KeyManager::SetKek(const uint8_t *aKek) -{ - memcpy(mKek.m8, aKek, sizeof(mKek)); + mKek.SetFrom(aKek, /* aIsExportable */ true); mKekFrameCounter = 0; } @@ -443,4 +509,137 @@ void KeyManager::HandleKeyRotationTimer(void) } } +void KeyManager::GetNetworkKey(NetworkKey &aNetworkKey) const +{ +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + if (Crypto::Storage::IsKeyRefValid(mNetworkKeyRef)) + { + Error error = kErrorNone; + size_t keyLen; + + error = Crypto::Storage::ExportKey(mNetworkKeyRef, aNetworkKey.m8, NetworkKey::kSize, keyLen); + OT_ASSERT(error == kErrorNone); + OT_ASSERT(keyLen == NetworkKey::kSize); + OT_UNUSED_VARIABLE(error); + } + else + { + aNetworkKey.Clear(); + } +#else + aNetworkKey = mNetworkKey; +#endif +} + +void KeyManager::GetPskc(Pskc &aPskc) const +{ +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + if (Crypto::Storage::IsKeyRefValid(mPskcRef)) + { + Error error = kErrorNone; + size_t keyLen; + + error = Crypto::Storage::ExportKey(mPskcRef, aPskc.m8, Pskc::kSize, keyLen); + OT_ASSERT(error == kErrorNone); + OT_ASSERT(keyLen == Pskc::kSize); + OT_UNUSED_VARIABLE(error); + } + else + { + aPskc.Clear(); + } +#else + aPskc = mPskc; +#endif +} + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + +void KeyManager::StoreNetworkKey(const NetworkKey &aNetworkKey, bool aOverWriteExisting) +{ + Error error; + NetworkKeyRef keyRef; + + keyRef = kNetworkKeyPsaItsOffset; + + if (!aOverWriteExisting) + { + // Check if there is already a network key stored in ITS. If + // stored, and we are not overwriting the existing key, + // return without doing anything. + if (Crypto::Storage::HasKey(keyRef)) + { + ExitNow(); + } + } + + Crypto::Storage::DestroyKey(keyRef); + + error = Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeHmac, Crypto::Storage::kKeyAlgorithmHmacSha256, + Crypto::Storage::kUsageSignHash | Crypto::Storage::kUsageExport, + Crypto::Storage::kTypePersistent, aNetworkKey.m8, NetworkKey::kSize); + OT_ASSERT(error == kErrorNone); + +exit: + if (mNetworkKeyRef != keyRef) + { + Crypto::Storage::DestroyKey(mNetworkKeyRef); + } + + mNetworkKeyRef = keyRef; +} + +void KeyManager::StorePskc(const Pskc &aPskc) +{ + PskcRef keyRef = kPskcPsaItsOffset; + Error error = kErrorNone; + + Crypto::Storage::DestroyKey(keyRef); + + error = Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeRaw, Crypto::Storage::kKeyAlgorithmVendor, + Crypto::Storage::kUsageExport, Crypto::Storage::kTypePersistent, aPskc.m8, + Pskc::kSize); + OT_ASSERT(error == kErrorNone); + OT_UNUSED_VARIABLE(error); + + if (mPskcRef != keyRef) + { + Crypto::Storage::DestroyKey(mPskcRef); + } + + mPskcRef = keyRef; +} + +void KeyManager::SetPskcRef(PskcRef aKeyRef) +{ + VerifyOrExit(mPskcRef != aKeyRef, Get().SignalIfFirst(kEventPskcChanged)); + + Crypto::Storage::DestroyKey(mPskcRef); + + mPskcRef = aKeyRef; + Get().Signal(kEventPskcChanged); + +exit: + mIsPskcSet = true; +} + +void KeyManager::SetNetworkKeyRef(otNetworkKeyRef aKeyRef) +{ + VerifyOrExit(mNetworkKeyRef != aKeyRef, Get().SignalIfFirst(kEventNetworkKeyChanged)); + + Crypto::Storage::DestroyKey(mNetworkKeyRef); + + mNetworkKeyRef = aKeyRef; + Get().Signal(kEventNetworkKeyChanged); + Get().Signal(kEventThreadKeySeqCounterChanged); + mKeySequence = 0; + UpdateKeyMaterial(); + ResetFrameCounters(); + +exit: + return; +} + +#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 c096ea105..407eab023 100644 --- a/src/core/thread/key_manager.hpp +++ b/src/core/thread/key_manager.hpp @@ -40,6 +40,7 @@ #include +#include #include "common/clearable.hpp" #include "common/encoding.hpp" #include "common/equatable.hpp" @@ -133,9 +134,11 @@ private: * */ OT_TOOL_PACKED_BEGIN -class NetworkKey : public otNetworkKey, public Equatable +class NetworkKey : public otNetworkKey, public Equatable, public Clearable { public: + static constexpr uint8_t kSize = OT_NETWORK_KEY_SIZE; ///< Size of the Thread Network Key (in bytes). + #if !OPENTHREAD_RADIO /** * This method generates a cryptographically secure random sequence to populate the Thread Network Key. @@ -146,8 +149,17 @@ public: */ Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(m8)); } #endif + } OT_TOOL_PACKED_END; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +/** + * Provides a representation for Network Key reference. + * + */ +typedef otNetworkKeyRef NetworkKeyRef; +#endif + /** * This class represents a Thread Pre-Shared Key for the Commissioner (PSKc). * @@ -156,6 +168,8 @@ OT_TOOL_PACKED_BEGIN class Pskc : public otPskc, public Equatable, public Clearable { public: + static constexpr uint8_t kSize = OT_PSKC_MAX_SIZE; ///< Size (number of bytes) of the PSKc. + #if !OPENTHREAD_RADIO /** * This method generates a cryptographically secure random sequence to populate the Thread PSKc. @@ -163,11 +177,18 @@ public: * @retval kErrorNone Successfully generated a random Thread PSKc. * */ - Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(Pskc)); } + Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(m8)); } #endif - } OT_TOOL_PACKED_END; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +/** + * Provides a representation for Network Key reference. + * + */ +typedef otPskcRef PskcRef; +#endif + /** * * This class represents a Key Encryption Key (KEK). @@ -175,6 +196,13 @@ public: */ typedef Mac::Key Kek; +/** + * + * This class represents a Key Material for Key Encryption Key (KEK). + * + */ +typedef Mac::KeyMaterial KekKeyMaterial; + /** * This class defines Thread Key Manager. * @@ -182,6 +210,9 @@ typedef Mac::Key Kek; class KeyManager : public InstanceLocator, private NonCopyable { public: + static constexpr uint32_t kNetworkKeyPsaItsOffset = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 1; + static constexpr uint32_t kPskcPsaItsOffset = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 2; + /** * This constructor initializes the object. * @@ -203,25 +234,39 @@ public: void Stop(void); /** - * This method returns the Thread Network Key. + * This method gets the Thread Network Key. * - * @returns The Thread Network Key. + * @param[out] aNetworkKey A reference to a `NetworkKey` to output the Thread Network Key. * */ - const NetworkKey &GetNetworkKey(void) const { return mNetworkKey; } + void GetNetworkKey(NetworkKey &aNetworkKey) const; /** * This method sets the Thread Network Key. * - * @param[in] aKey A Thread Network Key. - * - * @retval kErrorNone Successfully set the Thread Network Key. - * @retval kErrorInvalidArgs The @p aKeyLength value was invalid. + * @param[in] aNetworkKey A Thread Network Key. * */ - Error SetNetworkKey(const NetworkKey &aKey); + void SetNetworkKey(const NetworkKey &aNetworkKey); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + /** + * This method returns a Key Ref to Thread Network Key. + * + * @returns A key reference to the Thread Network Key. + * + */ + NetworkKeyRef GetNetworkKeyRef(void) { return mNetworkKeyRef; } + + /** + * This method sets the Thread Network Key using Key Reference. + * + * @param[in] aKeyRef Reference to Thread Network Key. + * + */ + void SetNetworkKeyRef(NetworkKeyRef aKeyRef); +#endif -#if OPENTHREAD_FTD || OPENTHREAD_MTD /** * This method indicates whether the PSKc is configured. * @@ -234,12 +279,12 @@ public: bool IsPskcSet(void) const { return mIsPskcSet; } /** - * This method returns a pointer to the PSKc. + * This method gets the PKSc. * - * @returns A reference to the PSKc. + * @param[out] aPskc A reference to a `Pskc` to return the PSKc. * */ - const Pskc &GetPskc(void) const { return mPskc; } + void GetPskc(Pskc &aPskc) const; /** * This method sets the PSKc. @@ -248,6 +293,23 @@ public: * */ void SetPskc(const Pskc &aPskc); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + /** + * This method returns a Key Ref to PSKc. + * + * @returns A key reference to the PSKc. + * + */ + const PskcRef &GetPskcRef(void) { return mPskcRef; } + + /** + * This method sets the PSKc as a Key reference. + * + * @param[in] aPskc A reference to the PSKc. + * + */ + void SetPskcRef(PskcRef aKeyRef); #endif /** @@ -273,7 +335,7 @@ public: * @returns The current TREL MAC key. * */ - const Mac::Key &GetCurrentTrelMacKey(void) const { return mTrelKey; } + const Mac::KeyMaterial &GetCurrentTrelMacKey(void) const { return mTrelKey; } /** * This method returns a temporary MAC key for TREL radio link computed from the given key sequence. @@ -283,26 +345,26 @@ public: * @returns The temporary TREL MAC key. * */ - const Mac::Key &GetTemporaryTrelMacKey(uint32_t aKeySequence); + const Mac::KeyMaterial &GetTemporaryTrelMacKey(uint32_t aKeySequence); #endif /** - * This method returns the current MLE key. + * This method returns the current MLE key Material. * * @returns The current MLE key. * */ - const Mle::Key &GetCurrentMleKey(void) const { return mMleKey; } + const Mle::KeyMaterial &GetCurrentMleKey(void) const { return mMleKey; } /** - * This method returns a temporary MLE key computed from the given key sequence. + * This method returns a temporary MLE key Material computed from the given key sequence. * * @param[in] aKeySequence The key sequence value. * * @returns The temporary MLE key. * */ - const Mle::Key &GetTemporaryMleKey(uint32_t aKeySequence); + const Mle::KeyMaterial &GetTemporaryMleKey(uint32_t aKeySequence); #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE /** @@ -385,12 +447,20 @@ public: void IncrementMleFrameCounter(void); /** - * This method returns the KEK. + * This method returns the KEK as `KekKeyMaterail` * - * @returns A pointer to the KEK. + * @returns The KEK as `KekKeyMaterial`. * */ - const Kek &GetKek(void) const { return mKek; } + const KekKeyMaterial &GetKek(void) const { return mKek; } + + /** + * This method retrieves the KEK as literal `Kek` key. + * + * @param[out] aKek A reference to a `Kek` to output the retrieved KEK. + * + */ + void ExtractKek(Kek &aKek) { mKek.ExtractKey(aKek); } /** * This method sets the KEK. @@ -403,10 +473,10 @@ public: /** * This method sets the KEK. * - * @param[in] aKek A pointer to the KEK. + * @param[in] aKekBytes A pointer to the KEK bytes. * */ - void SetKek(const uint8_t *aKek); + void SetKek(const uint8_t *aKekBytes) { SetKek(*reinterpret_cast(aKekBytes)); } /** * This method returns the current KEK Frame Counter value. @@ -493,18 +563,28 @@ private: { Crypto::HmacSha256::Hash mHash; Keys mKeys; + + const Mle::Key &GetMleKey(void) const { return mKeys.mMleKey; } + const Mac::Key &GetMacKey(void) const { return mKeys.mMacKey; } }; void ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys); #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE - void ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aTrelKey); + void ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey); #endif void StartKeyRotationTimer(void); static void HandleKeyRotationTimer(Timer &aTimer); void HandleKeyRotationTimer(void); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + void StoreNetworkKey(const NetworkKey &aNetworkKey, bool aOverWriteExisting); + void StorePskc(const Pskc &aPskc); +#endif + + void ResetFrameCounters(void); + static const uint8_t kThreadString[]; #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE @@ -512,15 +592,19 @@ private: static const uint8_t kTrelInfoString[]; #endif +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + NetworkKeyRef mNetworkKeyRef; +#else NetworkKey mNetworkKey; +#endif - uint32_t mKeySequence; - Mle::Key mMleKey; - Mle::Key mTemporaryMleKey; + uint32_t mKeySequence; + Mle::KeyMaterial mMleKey; + Mle::KeyMaterial mTemporaryMleKey; #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE - Mac::Key mTrelKey; - Mac::Key mTemporaryTrelKey; + Mac::KeyMaterial mTrelKey; + Mac::KeyMaterial mTemporaryTrelKey; #endif Mac::LinkFrameCounters mMacFrameCounters; @@ -533,11 +617,14 @@ private: bool mKeySwitchGuardEnabled; TimerMilli mKeyRotationTimer; -#if OPENTHREAD_MTD || OPENTHREAD_FTD - Pskc mPskc; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + PskcRef mPskcRef; +#else + Pskc mPskc; #endif - Kek mKek; - uint32_t mKekFrameCounter; + + KekKeyMaterial mKek; + uint32_t mKekFrameCounter; SecurityPolicy mSecurityPolicy; bool mIsPskcSet : 1; diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index bc91f7e84..251ba1041 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -2675,21 +2675,21 @@ void Mle::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageI void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { - Error error = kErrorNone; - Header header; - uint32_t keySequence; - const Key * mleKey; - uint32_t frameCounter; - uint8_t messageTag[kMleSecurityTagSize]; - uint8_t nonce[Crypto::AesCcm::kNonceSize]; - Mac::ExtAddress extAddr; - Crypto::AesCcm aesCcm; - uint16_t mleOffset; - uint8_t buf[64]; - uint16_t length; - uint8_t tag[kMleSecurityTagSize]; - uint8_t command; - Neighbor * neighbor; + Error error = kErrorNone; + Header header; + uint32_t keySequence; + const KeyMaterial *mleKey; + uint32_t frameCounter; + uint8_t messageTag[kMleSecurityTagSize]; + uint8_t nonce[Crypto::AesCcm::kNonceSize]; + Mac::ExtAddress extAddr; + Crypto::AesCcm aesCcm; + uint16_t mleOffset; + uint8_t buf[64]; + uint16_t length; + uint8_t tag[kMleSecurityTagSize]; + uint8_t command; + Neighbor * neighbor; otLogDebgMle("Receive UDP message"); diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp index 94af11d82..942c96ff8 100644 --- a/src/core/thread/mle_types.hpp +++ b/src/core/thread/mle_types.hpp @@ -571,7 +571,13 @@ private: } OT_TOOL_PACKED_END; /** - * This class represents a MLE key. + * This class represents a MLE Key Material + * + */ +typedef Mac::KeyMaterial KeyMaterial; + +/** + * This class represents a MLE Key. * */ typedef Mac::Key Key; diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp index d9df4ae3d..0d35de7d4 100644 --- a/src/lib/spinel/radio_spinel.hpp +++ b/src/lib/spinel/radio_spinel.hpp @@ -628,20 +628,21 @@ public: * * @param[in] aKeyIdMode The key ID mode. * @param[in] aKeyId The key index. - * @param[in] aPrevKey The previous MAC key. - * @param[in] aCurrKey The current MAC key. - * @param[in] aNextKey The next MAC key. + * @param[in] aPrevKey Pointer to previous MAC key. + * @param[in] aCurrKey Pointer to current MAC key. + * @param[in] aNextKey Pointer to next MAC key. * * @retval OT_ERROR_NONE Succeeded. + * @retval OT_ERROR_INVALID_ARGS One of the keys passed is invalid.. * @retval OT_ERROR_BUSY Failed due to another operation is on going. * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver. * */ - otError SetMacKey(uint8_t aKeyIdMode, - uint8_t aKeyId, - const otMacKey &aPrevKey, - const otMacKey &aCurrKey, - const otMacKey &aNextKey); + otError SetMacKey(uint8_t aKeyIdMode, + uint8_t aKeyId, + const otMacKeyMaterial *aPrevKey, + const otMacKeyMaterial *aCurrKey, + const otMacKeyMaterial *aNextKey); /** * This method sets the current MAC Frame Counter value. diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp index 86c12a9fa..7a7f78d66 100644 --- a/src/lib/spinel/radio_spinel_impl.hpp +++ b/src/lib/spinel/radio_spinel_impl.hpp @@ -1134,26 +1134,41 @@ exit: } template -otError RadioSpinel::SetMacKey(uint8_t aKeyIdMode, - uint8_t aKeyId, - const otMacKey &aPrevKey, - const otMacKey &aCurrKey, - const otMacKey &aNextKey) +otError RadioSpinel::SetMacKey(uint8_t aKeyIdMode, + uint8_t aKeyId, + const otMacKeyMaterial *aPrevKey, + const otMacKeyMaterial *aCurrKey, + const otMacKeyMaterial *aNextKey) { otError error; + size_t aKeySize; + + VerifyOrExit((aPrevKey != nullptr) && (aCurrKey != nullptr) && (aNextKey != nullptr), error = kErrorInvalidArgs); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrExit(error = otPlatCryptoExportKey(aPrevKey->mKeyMaterial.mKeyRef, aPrevKey->mKeyMaterial.mKey.m8, + sizeof(aPrevKey->mKeyMaterial.mKey.m8), &aKeySize)); + SuccessOrExit(error = otPlatCryptoExportKey(aCurrKey->mKeyMaterial.mKeyRef, aCurrKey->mKeyMaterial.mKey.m8, + sizeof(aCurrKey->mKeyMaterial.mKey.m8), &aKeySize)); + SuccessOrExit(error = otPlatCryptoExportKey(aNextKey->mKeyMaterial.mKeyRef, aNextKey->mKeyMaterial.mKey.m8, + sizeof(aNextKey->mKeyMaterial.mKey.m8), &aKeySize)); +#else + OT_UNUSED_VARIABLE(aKeySize); +#endif SuccessOrExit(error = Set(SPINEL_PROP_RCP_MAC_KEY, SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_DATA_WLEN_S SPINEL_DATATYPE_DATA_WLEN_S SPINEL_DATATYPE_DATA_WLEN_S, - aKeyIdMode, aKeyId, aPrevKey.m8, sizeof(otMacKey), aCurrKey.m8, sizeof(otMacKey), - aNextKey.m8, sizeof(otMacKey))); + aKeyIdMode, aKeyId, aPrevKey->mKeyMaterial.mKey.m8, sizeof(otMacKey), + aCurrKey->mKeyMaterial.mKey.m8, sizeof(otMacKey), aNextKey->mKeyMaterial.mKey.m8, + sizeof(otMacKey))); #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 mKeyIdMode = aKeyIdMode; mKeyId = aKeyId; - memcpy(mPrevKey.m8, aPrevKey.m8, OT_MAC_KEY_SIZE); - memcpy(mCurrKey.m8, aCurrKey.m8, OT_MAC_KEY_SIZE); - memcpy(mNextKey.m8, aNextKey.m8, OT_MAC_KEY_SIZE); + memcpy(mPrevKey.m8, aPrevKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE); + memcpy(mCurrKey.m8, aCurrKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE); + memcpy(mNextKey.m8, aNextKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE); mMacKeySet = true; #endif diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp index a62ae8b28..a7fbdb0ba 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -502,7 +502,11 @@ exit: template <> otError NcpBase::HandlePropertyGet(void) { - return mEncoder.WriteData(otThreadGetPskc(mInstance)->m8, sizeof(spinel_net_pskc_t)); + Pskc pskc; + + otThreadGetPskc(mInstance, &pskc); + + return mEncoder.WriteData(pskc.m8, sizeof(spinel_net_pskc_t)); } template <> otError NcpBase::HandlePropertySet(void) diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 4f03ec659..b8fb54932 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -662,7 +662,11 @@ exit: template <> otError NcpBase::HandlePropertyGet(void) { - return mEncoder.WriteData(otThreadGetNetworkKey(mInstance)->m8, OT_NETWORK_KEY_SIZE); + otNetworkKey networkKey; + + otThreadGetNetworkKey(mInstance, &networkKey); + + return mEncoder.WriteData(networkKey.m8, OT_NETWORK_KEY_SIZE); } template <> otError NcpBase::HandlePropertySet(void) diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp index c616b1fbb..03b704b97 100644 --- a/src/posix/platform/radio.cpp +++ b/src/posix/platform/radio.cpp @@ -563,15 +563,17 @@ otRadioState otPlatRadioGetState(otInstance *aInstance) return sRadioSpinel.GetState(); } -void otPlatRadioSetMacKey(otInstance * aInstance, - uint8_t aKeyIdMode, - uint8_t aKeyId, - const otMacKey *aPrevKey, - const otMacKey *aCurrKey, - const otMacKey *aNextKey) +void otPlatRadioSetMacKey(otInstance * aInstance, + uint8_t aKeyIdMode, + uint8_t aKeyId, + const otMacKeyMaterial *aPrevKey, + const otMacKeyMaterial *aCurrKey, + const otMacKeyMaterial *aNextKey, + otRadioKeyType aKeyType) { - SuccessOrDie(sRadioSpinel.SetMacKey(aKeyIdMode, aKeyId, *aPrevKey, *aCurrKey, *aNextKey)); + SuccessOrDie(sRadioSpinel.SetMacKey(aKeyIdMode, aKeyId, aPrevKey, aCurrKey, aNextKey)); OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aKeyType); } void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter) diff --git a/tests/unit/test_hkdf_sha256.cpp b/tests/unit/test_hkdf_sha256.cpp index afbfce6c9..08cfb4baa 100644 --- a/tests/unit/test_hkdf_sha256.cpp +++ b/tests/unit/test_hkdf_sha256.cpp @@ -129,6 +129,7 @@ void TestHkdfSha256(void) { ot::Crypto::HkdfSha256 hkdf; uint8_t outKey[kMaxOuttKey]; + ot::Crypto::Key testInputKey; printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); DumpBuffer("\nInput Key", test->mInKey, test->mInKeyLength); @@ -137,8 +138,11 @@ void TestHkdfSha256(void) DumpBuffer("\nExpected Output Key", test->mOutKey, test->mOutKeyLength); memset(outKey, kFillByte, sizeof(outKey)); + memset(&testInputKey, 0x00, sizeof(testInputKey)); + testInputKey.mKey = test->mInKey; + testInputKey.mKeyLength = test->mInKeyLength; - hkdf.Extract(test->mSalt, test->mSaltLength, test->mInKey, test->mInKeyLength); + hkdf.Extract(test->mSalt, test->mSaltLength, testInputKey); hkdf.Expand(test->mInfo, test->mInfoLength, outKey, test->mOutKeyLength); DumpBuffer("\nCalculated Output Key", outKey, test->mOutKeyLength); diff --git a/tests/unit/test_hmac_sha256.cpp b/tests/unit/test_hmac_sha256.cpp index 382217903..7e229789f 100644 --- a/tests/unit/test_hmac_sha256.cpp +++ b/tests/unit/test_hmac_sha256.cpp @@ -140,8 +140,7 @@ void TestHmacSha256(void) { struct TestCase { - const void * mKey; - uint16_t mKeyLength; + otCryptoKey mKey; const void * mData; uint16_t mDataLength; otCryptoSha256Hash mHash; @@ -219,11 +218,11 @@ void TestHmacSha256(void) }}; static const TestCase kTestCases[] = { - {kKey1, sizeof(kKey1), kData1, sizeof(kData1) - 1, kHash1}, - {kKey2, sizeof(kKey2) - 1, kData2, sizeof(kData2) - 1, kHash2}, - {kKey3, sizeof(kKey3), kData3, sizeof(kData3), kHash3}, - {kKey4, sizeof(kKey4), kData4, sizeof(kData4), kHash4}, - {kKey5, sizeof(kKey5), kData5, sizeof(kData5) - 1, kHash5}, + {{&kKey1[0], sizeof(kKey1), 0}, kData1, sizeof(kData1) - 1, kHash1}, + {{reinterpret_cast(&kKey2[0]), sizeof(kKey2) - 1, 0}, kData2, sizeof(kData2) - 1, kHash2}, + {{&kKey3[0], sizeof(kKey3), 0}, kData3, sizeof(kData3), kHash3}, + {{&kKey4[0], sizeof(kKey4), 0}, kData4, sizeof(kData4), kHash4}, + {{&kKey5[0], sizeof(kKey5), 0}, kData5, sizeof(kData5) - 1, kHash5}, }; Instance * instance = testInitInstance(); @@ -244,7 +243,7 @@ void TestHmacSha256(void) Crypto::HmacSha256 hmac; Crypto::HmacSha256::Hash hash; - hmac.Start(reinterpret_cast(testCase.mKey), testCase.mKeyLength); + hmac.Start(static_cast(testCase.mKey)); hmac.Update(testCase.mData, testCase.mDataLength); hmac.Finish(hash); @@ -270,7 +269,7 @@ void TestHmacSha256(void) Crypto::HmacSha256 hmac; Crypto::HmacSha256::Hash hash; - hmac.Start(reinterpret_cast(testCase.mKey), testCase.mKeyLength); + hmac.Start(static_cast(testCase.mKey)); hmac.Update(*message, offsets[index++], testCase.mDataLength); hmac.Finish(hash); diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp index c8bc870dd..465ae588d 100644 --- a/tests/unit/test_platform.cpp +++ b/tests/unit/test_platform.cpp @@ -502,4 +502,52 @@ OT_TOOL_WEAK otError otPlatInfraIfSendIcmp6Nd(uint32_t, const otIp6Address *, co } #endif +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + +otError otPlatCryptoImportKey(otCryptoKeyRef * aKeyRef, + otCryptoKeyType aKeyType, + otCryptoKeyAlgorithm aKeyAlgorithm, + int aKeyUsage, + otCryptoKeyStorage aKeyPersistence, + const uint8_t * aKey, + size_t aKeyLen) +{ + OT_UNUSED_VARIABLE(aKeyRef); + OT_UNUSED_VARIABLE(aKeyType); + OT_UNUSED_VARIABLE(aKeyAlgorithm); + OT_UNUSED_VARIABLE(aKeyUsage); + OT_UNUSED_VARIABLE(aKeyPersistence); + OT_UNUSED_VARIABLE(aKey); + OT_UNUSED_VARIABLE(aKeyLen); + + return OT_ERROR_NONE; +} + +otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t *aKeyLen) +{ + OT_UNUSED_VARIABLE(aKeyRef); + OT_UNUSED_VARIABLE(aBuffer); + OT_UNUSED_VARIABLE(aBufferLen); + + *aKeyLen = 0; + + return OT_ERROR_NONE; +} + +otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef) +{ + OT_UNUSED_VARIABLE(aKeyRef); + + return OT_ERROR_NONE; +} + +bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef) +{ + OT_UNUSED_VARIABLE(aKeyRef); + + return false; +} + +#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + } // extern "C" diff --git a/tests/unit/test_pskc.cpp b/tests/unit/test_pskc.cpp index 68e3eb8f5..19dbed642 100644 --- a/tests/unit/test_pskc.cpp +++ b/tests/unit/test_pskc.cpp @@ -46,7 +46,7 @@ void TestMinimumPassphrase(void) otInstance * instance = testInitInstance(); SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast("OpenThread"), static_cast(xpanid), pskc)); - VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc)) == 0); + VerifyOrQuit(memcmp(pskc.m8, expectedPskc, OT_PSKC_MAX_SIZE) == 0); testFreeInstance(instance); } @@ -76,7 +76,7 @@ void TestMaximumPassphrase(void) otInstance *instance = testInitInstance(); SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast("OpenThread"), static_cast(xpanid), pskc)); - VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc)) == 0); + VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc.m8)) == 0); testFreeInstance(instance); } @@ -91,7 +91,7 @@ void TestExampleInSpec(void) otInstance *instance = testInitInstance(); SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast("Test Network"), static_cast(xpanid), pskc)); - VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc)) == 0); + VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc.m8)) == 0); testFreeInstance(instance); } diff --git a/third_party/mbedtls/CMakeLists.txt b/third_party/mbedtls/CMakeLists.txt index 9715bf4e3..07682ba5e 100644 --- a/third_party/mbedtls/CMakeLists.txt +++ b/third_party/mbedtls/CMakeLists.txt @@ -72,7 +72,10 @@ else() configure_file(mbedtls-config.h openthread-mbedtls-config.h COPYONLY) endif() -target_include_directories(ot-config INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) +target_include_directories(ot-config + INTERFACE + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/repo/include) target_compile_definitions(mbedtls PUBLIC