From 96e1a148a1f562a5ff1af3dca0250c3a96d73a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Sun, 22 Sep 2024 01:26:59 +0200 Subject: [PATCH 01/12] [crypto] introduce default port for PSA API --- include/openthread/platform/crypto.h | 12 +- src/core/BUILD.gn | 6 +- src/core/CMakeLists.txt | 6 +- ...atform.cpp => crypto_platform_mbedtls.cpp} | 70 -- src/core/crypto/crypto_platform_psa.cpp | 762 ++++++++++++++++++ src/core/crypto/storage.hpp | 11 +- 6 files changed, 785 insertions(+), 82 deletions(-) rename src/core/crypto/{crypto_platform.cpp => crypto_platform_mbedtls.cpp} (91%) create mode 100644 src/core/crypto/crypto_platform_psa.cpp diff --git a/include/openthread/platform/crypto.h b/include/openthread/platform/crypto.h index c5997ee6f71..789990bf960 100644 --- a/include/openthread/platform/crypto.h +++ b/include/openthread/platform/crypto.h @@ -58,10 +58,11 @@ extern "C" { */ typedef enum { - OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data. - OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES. - OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC. - OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA. + OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data. + OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES. + OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC. + OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA. + OT_CRYPTO_KEY_TYPE_DERIVE, ///< Key Type: Derive. } otCryptoKeyType; /** @@ -73,6 +74,7 @@ typedef enum OT_CRYPTO_KEY_ALG_AES_ECB, ///< Key Algorithm: AES ECB. OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256. OT_CRYPTO_KEY_ALG_ECDSA, ///< Key Algorithm: ECDSA. + OT_CRYPTO_KEY_ALG_HKDF_SHA256, ///< Key Algorithm: HKDF SHA-256. } otCryptoKeyAlgorithm; /** @@ -86,6 +88,8 @@ enum OT_CRYPTO_KEY_USAGE_DECRYPT = 1 << 2, ///< Key Usage: AES ECB. OT_CRYPTO_KEY_USAGE_SIGN_HASH = 1 << 3, ///< Key Usage: Sign Hash. OT_CRYPTO_KEY_USAGE_VERIFY_HASH = 1 << 4, ///< Key Usage: Verify Hash. + OT_CRYPTO_KEY_USAGE_DERIVE = 1 << 5, ///< Key Usage: Derive. + }; /** diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 0913a1e704c..2257576ee41 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -464,7 +464,8 @@ openthread_core_files = [ "crypto/aes_ecb.cpp", "crypto/aes_ecb.hpp", "crypto/context_size.hpp", - "crypto/crypto_platform.cpp", + "crypto/crypto_platform_mbedtls.cpp", + "crypto/crypto_platform_psa.cpp", "crypto/ecdsa.hpp", "crypto/hkdf_sha256.cpp", "crypto/hkdf_sha256.hpp", @@ -768,7 +769,8 @@ openthread_radio_sources = [ "common/uptime.cpp", "crypto/aes_ccm.cpp", "crypto/aes_ecb.cpp", - "crypto/crypto_platform.cpp", + "crypto/crypto_platform_mbedtls.cpp", + "crypto/crypto_platform_psa.cpp", "crypto/storage.cpp", "diags/factory_diags.cpp", "instance/instance.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6550ae80dd7..cbb5b7869f9 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -125,7 +125,8 @@ set(COMMON_SOURCES common/uptime.cpp crypto/aes_ccm.cpp crypto/aes_ecb.cpp - crypto/crypto_platform.cpp + crypto/crypto_platform_mbedtls.cpp + crypto/crypto_platform_psa.cpp crypto/hkdf_sha256.cpp crypto/hmac_sha256.cpp crypto/mbedtls.cpp @@ -286,7 +287,8 @@ set(RADIO_COMMON_SOURCES common/uptime.cpp crypto/aes_ccm.cpp crypto/aes_ecb.cpp - crypto/crypto_platform.cpp + crypto/crypto_platform_mbedtls.cpp + crypto/crypto_platform_psa.cpp crypto/storage.cpp diags/factory_diags.cpp instance/instance.cpp diff --git a/src/core/crypto/crypto_platform.cpp b/src/core/crypto/crypto_platform_mbedtls.cpp similarity index 91% rename from src/core/crypto/crypto_platform.cpp rename to src/core/crypto/crypto_platform_mbedtls.cpp index edde102c38a..0b1ac457000 100644 --- a/src/core/crypto/crypto_platform.cpp +++ b/src/core/crypto/crypto_platform_mbedtls.cpp @@ -750,74 +750,4 @@ OT_TOOL_WEAK otError otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword, #endif // #if OPENTHREAD_FTD -#elif OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA - -#if OPENTHREAD_FTD || OPENTHREAD_MTD -#if OPENTHREAD_CONFIG_ECDSA_ENABLE - -OT_TOOL_WEAK otError otPlatCryptoEcdsaGenerateKey(otPlatCryptoEcdsaKeyPair *aKeyPair) -{ - OT_UNUSED_VARIABLE(aKeyPair); - - return OT_ERROR_NOT_CAPABLE; -} - -OT_TOOL_WEAK otError otPlatCryptoEcdsaGetPublicKey(const otPlatCryptoEcdsaKeyPair *aKeyPair, - otPlatCryptoEcdsaPublicKey *aPublicKey) -{ - OT_UNUSED_VARIABLE(aKeyPair); - OT_UNUSED_VARIABLE(aPublicKey); - - return OT_ERROR_NOT_CAPABLE; -} - -OT_TOOL_WEAK otError otPlatCryptoEcdsaSign(const otPlatCryptoEcdsaKeyPair *aKeyPair, - const otPlatCryptoSha256Hash *aHash, - otPlatCryptoEcdsaSignature *aSignature) -{ - OT_UNUSED_VARIABLE(aKeyPair); - OT_UNUSED_VARIABLE(aHash); - OT_UNUSED_VARIABLE(aSignature); - - return OT_ERROR_NOT_CAPABLE; -} - -OT_TOOL_WEAK otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey, - const otPlatCryptoSha256Hash *aHash, - const otPlatCryptoEcdsaSignature *aSignature) - -{ - OT_UNUSED_VARIABLE(aPublicKey); - OT_UNUSED_VARIABLE(aHash); - OT_UNUSED_VARIABLE(aSignature); - - return OT_ERROR_NOT_CAPABLE; -} -#endif // #if OPENTHREAD_CONFIG_ECDSA_ENABLE - -#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD - -#if OPENTHREAD_FTD - -OT_TOOL_WEAK otError otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword, - uint16_t aPasswordLen, - const uint8_t *aSalt, - uint16_t aSaltLen, - uint32_t aIterationCounter, - uint16_t aKeyLen, - uint8_t *aKey) -{ - OT_UNUSED_VARIABLE(aPassword); - OT_UNUSED_VARIABLE(aPasswordLen); - OT_UNUSED_VARIABLE(aSalt); - OT_UNUSED_VARIABLE(aSaltLen); - OT_UNUSED_VARIABLE(aIterationCounter); - OT_UNUSED_VARIABLE(aKeyLen); - OT_UNUSED_VARIABLE(aKey); - - return OT_ERROR_NOT_CAPABLE; -} - -#endif // #if OPENTHREAD_FTD - #endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS diff --git a/src/core/crypto/crypto_platform_psa.cpp b/src/core/crypto/crypto_platform_psa.cpp new file mode 100644 index 00000000000..5595372ec97 --- /dev/null +++ b/src/core/crypto/crypto_platform_psa.cpp @@ -0,0 +1,762 @@ +/* + * Copyright (c) 2025, 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 + * using ARM PSA API. + */ + +#include "openthread-core-config.h" + +#include + +#include +#include + +#include +#include +#include + +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "common/new.hpp" +#include "config/crypto.h" +#include "crypto/ecdsa.hpp" +#include "crypto/hmac_sha256.hpp" +#include "crypto/storage.hpp" +#include "instance/instance.hpp" + +using namespace ot; +using namespace Crypto; + +#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA + +//--------------------------------------------------------------------------------------------------------------------- +// Default/weak implementation of crypto platform APIs + +static otError psaToOtError(psa_status_t aStatus) +{ + switch (aStatus) + { + case PSA_SUCCESS: + return kErrorNone; + case PSA_ERROR_INVALID_ARGUMENT: + return kErrorInvalidArgs; + case PSA_ERROR_BUFFER_TOO_SMALL: + return kErrorNoBufs; + default: + return kErrorFailed; + } +} + +static psa_key_type_t toPsaKeyType(otCryptoKeyType aType) +{ + switch (aType) + { + case OT_CRYPTO_KEY_TYPE_RAW: + return PSA_KEY_TYPE_RAW_DATA; + case OT_CRYPTO_KEY_TYPE_AES: + return PSA_KEY_TYPE_AES; + case OT_CRYPTO_KEY_TYPE_HMAC: + return PSA_KEY_TYPE_HMAC; + case OT_CRYPTO_KEY_TYPE_ECDSA: + return PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1); + case OT_CRYPTO_KEY_TYPE_DERIVE: + return PSA_KEY_TYPE_DERIVE; + default: + return PSA_KEY_TYPE_NONE; + } +} + +static psa_algorithm_t toPsaAlgorithm(otCryptoKeyAlgorithm aAlgorithm) +{ + switch (aAlgorithm) + { + case OT_CRYPTO_KEY_ALG_AES_ECB: + return PSA_ALG_ECB_NO_PADDING; + case OT_CRYPTO_KEY_ALG_HMAC_SHA_256: + return PSA_ALG_HMAC(PSA_ALG_SHA_256); + case OT_CRYPTO_KEY_ALG_ECDSA: + return PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256); + case OT_CRYPTO_KEY_ALG_HKDF_SHA256: + return PSA_ALG_HKDF(PSA_ALG_SHA_256); + default: + return PSA_ALG_NONE; + } +} + +static psa_key_usage_t toPsaKeyUsage(int aUsage) +{ + psa_key_usage_t usage = 0; + + if (aUsage & OT_CRYPTO_KEY_USAGE_EXPORT) + { + usage |= PSA_KEY_USAGE_EXPORT; + } + + if (aUsage & OT_CRYPTO_KEY_USAGE_ENCRYPT) + { + usage |= PSA_KEY_USAGE_ENCRYPT; + } + + if (aUsage & OT_CRYPTO_KEY_USAGE_DECRYPT) + { + usage |= PSA_KEY_USAGE_DECRYPT; + } + + if (aUsage & OT_CRYPTO_KEY_USAGE_SIGN_HASH) + { + usage |= PSA_KEY_USAGE_SIGN_HASH; + } + + if (aUsage & OT_CRYPTO_KEY_USAGE_VERIFY_HASH) + { + usage |= PSA_KEY_USAGE_VERIFY_HASH; + } + + if (aUsage & OT_CRYPTO_KEY_USAGE_DERIVE) + { + usage |= PSA_KEY_USAGE_DERIVE; + } + + return usage; +} + +static bool checkKeyUsage(int aUsage) +{ + /* Check if only supported flags have been passed */ + int supportedFlags = OT_CRYPTO_KEY_USAGE_EXPORT | OT_CRYPTO_KEY_USAGE_ENCRYPT | OT_CRYPTO_KEY_USAGE_DECRYPT | + OT_CRYPTO_KEY_USAGE_SIGN_HASH | OT_CRYPTO_KEY_USAGE_VERIFY_HASH | OT_CRYPTO_KEY_USAGE_DERIVE; + + return (aUsage & ~supportedFlags) == 0; +} + +static bool checkContext(otCryptoContext *aContext, size_t aMinSize) +{ + /* Verify that the passed context is initialized and points to a big enough buffer */ + return aContext != nullptr && aContext->mContext != nullptr && aContext->mContextSize >= aMinSize; +} + +static otError extractPrivateKeyInfo(const uint8_t *aAsn1KeyPair, + size_t aAsn1KeyPairLen, + size_t *aKeyOffset, + size_t *aKeyLen) +{ + Error error = kErrorNone; + unsigned char *p = const_cast(aAsn1KeyPair); + const unsigned char *end = p + aAsn1KeyPairLen; + size_t len; + + // Parse the ASN.1 SEQUENCE headers + int ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + VerifyOrExit(ret == 0, error = kErrorInvalidArgs); + + // Parse the version (INTEGER) + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + VerifyOrExit(ret == 0, error = kErrorInvalidArgs); + + // Skip the version. + p += len; // Skip over the version + + // Parse the private key (OCTET STRING) + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + VerifyOrExit(ret == 0, error = kErrorInvalidArgs); + + // Check if the private key includes a padding byte (0x00) + if (*p == 0x00) + { + p++; + len--; // Skip the padding byte and reduce length by 1 + } + + *aKeyOffset = (p - aAsn1KeyPair); + *aKeyLen = len; + +exit: + return error; +} + +OT_TOOL_WEAK void otPlatCryptoInit(void) { psa_crypto_init(); } + +OT_TOOL_WEAK otError otPlatCryptoImportKey(otCryptoKeyRef *aKeyRef, + otCryptoKeyType aKeyType, + otCryptoKeyAlgorithm aKeyAlgorithm, + int aKeyUsage, + otCryptoKeyStorage aKeyPersistence, + const uint8_t *aKey, + size_t aKeyLen) +{ + Error error = kErrorNone; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = PSA_SUCCESS; + + VerifyOrExit(checkKeyUsage(aKeyUsage), error = kErrorInvalidArgs); + VerifyOrExit(aKeyRef != nullptr && aKey != nullptr, error = kErrorInvalidArgs); + + // PSA Crypto API expects the private key to be provided, not the full ASN1 buffer. + if (aKeyType == OT_CRYPTO_KEY_TYPE_ECDSA) + { + size_t pkOffset; + size_t pkLength; + + SuccessOrExit(error = extractPrivateKeyInfo(aKey, aKeyLen, &pkOffset, &pkLength)); + + // Overwrite the content of the key. + aKey += pkOffset; + aKeyLen = pkLength; + + psa_set_key_bits(&attributes, 256); + } + + psa_set_key_type(&attributes, toPsaKeyType(aKeyType)); + psa_set_key_algorithm(&attributes, toPsaAlgorithm(aKeyAlgorithm)); + psa_set_key_usage_flags(&attributes, toPsaKeyUsage(aKeyUsage)); + + switch (aKeyPersistence) + { + case OT_CRYPTO_KEY_STORAGE_PERSISTENT: + psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT); + psa_set_key_id(&attributes, *aKeyRef); + break; + case OT_CRYPTO_KEY_STORAGE_VOLATILE: + psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE); + break; + default: + OT_ASSERT(false); + } + + status = psa_import_key(&attributes, aKey, aKeyLen, aKeyRef); + +exit: + psa_reset_key_attributes(&attributes); + + if (error != kErrorNone) + { + return error; + } + + return psaToOtError(status); +} + +OT_TOOL_WEAK otError otPlatCryptoExportKey(otCryptoKeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t *aKeyLen) +{ + Error error = kErrorNone; + + VerifyOrExit(aBuffer != nullptr && aKeyLen != nullptr, error = kErrorInvalidArgs); + + error = psaToOtError(psa_export_key(aKeyRef, aBuffer, aBufferLen, aKeyLen)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoDestroyKey(otCryptoKeyRef aKeyRef) { return psaToOtError(psa_destroy_key(aKeyRef)); } + +OT_TOOL_WEAK bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + + status = psa_get_key_attributes(aKeyRef, &attributes); + psa_reset_key_attributes(&attributes); + + return status == PSA_SUCCESS; +} + +OT_TOOL_WEAK otError otPlatCryptoAesInit(otCryptoContext *aContext) +{ + Error error = kErrorNone; + psa_key_id_t *keyRef; + + VerifyOrExit(checkContext(aContext, sizeof(psa_key_id_t)), error = kErrorInvalidArgs); + + keyRef = static_cast(aContext->mContext); + *keyRef = PSA_KEY_ID_NULL; + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoAesSetKey(otCryptoContext *aContext, const otCryptoKey *aKey) +{ + Error error = kErrorNone; + psa_key_id_t *keyRef; + + VerifyOrExit(checkContext(aContext, sizeof(psa_key_id_t)), error = kErrorInvalidArgs); + VerifyOrExit(aKey != nullptr, error = kErrorInvalidArgs); + + keyRef = static_cast(aContext->mContext); + *keyRef = aKey->mKeyRef; + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoAesEncrypt(otCryptoContext *aContext, const uint8_t *aInput, uint8_t *aOutput) +{ + Error error = kErrorNone; + const size_t blockSize = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES); + psa_status_t status = PSA_SUCCESS; + psa_key_id_t *keyRef; + size_t cipherLen; + + VerifyOrExit(checkContext(aContext, sizeof(psa_key_id_t)), error = kErrorInvalidArgs); + VerifyOrExit(aInput != nullptr && aOutput != nullptr, error = kErrorInvalidArgs); + + keyRef = static_cast(aContext->mContext); + status = psa_cipher_encrypt(*keyRef, PSA_ALG_ECB_NO_PADDING, aInput, blockSize, aOutput, blockSize, &cipherLen); + + error = psaToOtError(status); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoAesFree(otCryptoContext *aContext) +{ + OT_UNUSED_VARIABLE(aContext); + + return kErrorNone; +} + +#if !OPENTHREAD_RADIO + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Init(otCryptoContext *aContext) +{ + Error error = kErrorNone; + psa_mac_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + // Initialize the structure using memset as documented alternative for psa_mac_operation_init(). + memset(operation, 0, sizeof(*operation)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Deinit(otCryptoContext *aContext) +{ + Error error = kErrorNone; + psa_mac_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_mac_abort(operation)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Start(otCryptoContext *aContext, const otCryptoKey *aKey) +{ + Error error = kErrorNone; + psa_mac_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs); + VerifyOrExit(aKey != nullptr, error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_mac_sign_setup(operation, aKey->mKeyRef, PSA_ALG_HMAC(PSA_ALG_SHA_256))); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength) +{ + Error error = kErrorNone; + psa_mac_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs); + VerifyOrExit(aBuf != nullptr, error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_mac_update(operation, static_cast(aBuf), aBufLength)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHmacSha256Finish(otCryptoContext *aContext, uint8_t *aBuf, size_t aBufLength) +{ + Error error = kErrorNone; + psa_mac_operation_t *operation; + size_t macLength; + + VerifyOrExit(checkContext(aContext, sizeof(psa_mac_operation_t)), error = kErrorInvalidArgs); + VerifyOrExit(aBuf != nullptr, error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_mac_sign_finish(operation, aBuf, aBufLength, &macLength)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHkdfInit(otCryptoContext *aContext) +{ + Error error = kErrorNone; + psa_key_derivation_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + *operation = PSA_KEY_DERIVATION_OPERATION_INIT; + + error = psaToOtError(psa_key_derivation_setup(operation, PSA_ALG_HKDF(PSA_ALG_SHA_256))); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHkdfExtract(otCryptoContext *aContext, + const uint8_t *aSalt, + uint16_t aSaltLength, + const otCryptoKey *aInputKey) +{ + Error error = kErrorNone; + psa_status_t status = PSA_SUCCESS; + psa_key_derivation_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs); + VerifyOrExit(aInputKey != nullptr, error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + status = psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_SALT, aSalt, aSaltLength); + SuccessOrExit(error = psaToOtError(status)); + + status = psa_key_derivation_input_key(operation, PSA_KEY_DERIVATION_INPUT_SECRET, aInputKey->mKeyRef); + SuccessOrExit(error = psaToOtError(status)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHkdfExpand(otCryptoContext *aContext, + const uint8_t *aInfo, + uint16_t aInfoLength, + uint8_t *aOutputKey, + uint16_t aOutputKeyLength) +{ + Error error = kErrorNone; + psa_status_t status = PSA_SUCCESS; + psa_key_derivation_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs); + VerifyOrExit(aOutputKey != nullptr, error = kErrorInvalidArgs); + VerifyOrExit(aOutputKeyLength != 0, error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + status = psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_INFO, aInfo, aInfoLength); + SuccessOrExit(error = psaToOtError(status)); + + status = psa_key_derivation_output_bytes(operation, aOutputKey, aOutputKeyLength); + SuccessOrExit(error = psaToOtError(status)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoHkdfDeinit(otCryptoContext *aContext) +{ + Error error = kErrorNone; + psa_key_derivation_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_key_derivation_operation_t)), error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_key_derivation_abort(operation)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Init(otCryptoContext *aContext) +{ + Error error = kErrorNone; + psa_hash_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + // Initialize the structure using memset as documented alternative for psa_hash_operation_init(). + memset(operation, 0, sizeof(*operation)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Deinit(otCryptoContext *aContext) +{ + Error error = kErrorNone; + psa_hash_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_hash_abort(operation)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Start(otCryptoContext *aContext) +{ + Error error = kErrorNone; + psa_hash_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_hash_setup(operation, PSA_ALG_SHA_256)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength) +{ + Error error = kErrorNone; + psa_hash_operation_t *operation; + + VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs); + VerifyOrExit(aBuf != nullptr, error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_hash_update(operation, static_cast(aBuf), aBufLength)); + +exit: + return error; +} + +OT_TOOL_WEAK otError otPlatCryptoSha256Finish(otCryptoContext *aContext, uint8_t *aHash, uint16_t aHashSize) +{ + Error error = kErrorNone; + psa_hash_operation_t *operation; + size_t hashSize; + + VerifyOrExit(checkContext(aContext, sizeof(psa_hash_operation_t)), error = kErrorInvalidArgs); + VerifyOrExit(aHash != nullptr, error = kErrorInvalidArgs); + + operation = static_cast(aContext->mContext); + + error = psaToOtError(psa_hash_finish(operation, aHash, aHashSize, &hashSize)); + +exit: + return error; +} + +OT_TOOL_WEAK void otPlatCryptoRandomInit(void) { psa_crypto_init(); } + +OT_TOOL_WEAK void otPlatCryptoRandomDeinit(void) +{ + // Intentionally empty +} + +OT_TOOL_WEAK otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize) +{ + return psaToOtError(psa_generate_random(aBuffer, aSize)); +} + +#if OPENTHREAD_CONFIG_ECDSA_ENABLE + +OT_TOOL_WEAK otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + psa_key_id_t keyId = static_cast(aKeyRef); + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT); + psa_set_key_id(&attributes, keyId); + psa_set_key_bits(&attributes, 256); + + status = psa_generate_key(&attributes, &keyId); + VerifyOrExit(status == PSA_SUCCESS); + +exit: + psa_reset_key_attributes(&attributes); + + return psaToOtError(status); +} + +OT_TOOL_WEAK otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey) +{ + psa_status_t status; + size_t exportedLen; + uint8_t buffer[1 + OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE]; + + status = psa_export_public_key(aKeyRef, buffer, sizeof(buffer), &exportedLen); + VerifyOrExit(status == PSA_SUCCESS); + + OT_ASSERT(exportedLen == sizeof(buffer)); + memcpy(aPublicKey->m8, buffer + 1, OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE); + +exit: + return psaToOtError(status); +} + +OT_TOOL_WEAK otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef, + const otPlatCryptoSha256Hash *aHash, + otPlatCryptoEcdsaSignature *aSignature) +{ + psa_status_t status; + size_t signatureLen; + + status = psa_sign_hash(aKeyRef, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8, OT_CRYPTO_SHA256_HASH_SIZE, + aSignature->m8, OT_CRYPTO_ECDSA_SIGNATURE_SIZE, &signatureLen); + VerifyOrExit(status == PSA_SUCCESS); + + OT_ASSERT(signatureLen == OT_CRYPTO_ECDSA_SIGNATURE_SIZE); + +exit: + return psaToOtError(status); +} + +OT_TOOL_WEAK otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey, + const otPlatCryptoSha256Hash *aHash, + const otPlatCryptoEcdsaSignature *aSignature) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t keyId; + psa_status_t status; + uint8_t buffer[1 + OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE]; + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&attributes, 256); + + /* + * `psa_import_key` expects a key format as specified by SEC1 §2.3.3 for the + * uncompressed representation of the ECPoint. + */ + buffer[0] = 0x04; + memcpy(buffer + 1, aPublicKey->m8, OT_CRYPTO_ECDSA_PUBLIC_KEY_SIZE); + + status = psa_import_key(&attributes, buffer, sizeof(buffer), &keyId); + VerifyOrExit(status == PSA_SUCCESS); + + status = psa_verify_hash(keyId, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8, OT_CRYPTO_SHA256_HASH_SIZE, + aSignature->m8, OT_CRYPTO_ECDSA_SIGNATURE_SIZE); + VerifyOrExit(status == PSA_SUCCESS); + +exit: + psa_reset_key_attributes(&attributes); + psa_destroy_key(keyId); + + return psaToOtError(status); +} + +OT_TOOL_WEAK otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef, + const otPlatCryptoSha256Hash *aHash, + const otPlatCryptoEcdsaSignature *aSignature) +{ + psa_status_t status; + + status = psa_verify_hash(aKeyRef, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), aHash->m8, + OT_CRYPTO_SHA256_HASH_SIZE, aSignature->m8, OT_CRYPTO_ECDSA_SIGNATURE_SIZE); + VerifyOrExit(status == PSA_SUCCESS); + +exit: + return psaToOtError(status); +} + +#endif // #if OPENTHREAD_CONFIG_ECDSA_ENABLE + +#endif // #if !OPENTHREAD_RADIO + +#if OPENTHREAD_FTD + +OT_TOOL_WEAK otError otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword, + uint16_t aPasswordLen, + const uint8_t *aSalt, + uint16_t aSaltLen, + uint32_t aIterationCounter, + uint16_t aKeyLen, + uint8_t *aKey) +{ + psa_status_t status = PSA_SUCCESS; + psa_key_id_t key_id = PSA_KEY_ID_NULL; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t algorithm = PSA_ALG_PBKDF2_AES_CMAC_PRF_128; + psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE); + psa_set_key_algorithm(&attributes, algorithm); + psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(aPasswordLen)); + + status = psa_import_key(&attributes, aPassword, aPasswordLen, &key_id); + VerifyOrExit(status == PSA_SUCCESS); + + status = psa_key_derivation_setup(&operation, algorithm); + VerifyOrExit(status == PSA_SUCCESS); + + status = psa_key_derivation_input_integer(&operation, PSA_KEY_DERIVATION_INPUT_COST, aIterationCounter); + VerifyOrExit(status == PSA_SUCCESS); + + status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, aSalt, aSaltLen); + VerifyOrExit(status == PSA_SUCCESS); + + status = psa_key_derivation_input_key(&operation, PSA_KEY_DERIVATION_INPUT_PASSWORD, key_id); + VerifyOrExit(status == PSA_SUCCESS); + + status = psa_key_derivation_output_bytes(&operation, aKey, aKeyLen); + VerifyOrExit(status == PSA_SUCCESS); + +exit: + psa_reset_key_attributes(&attributes); + psa_key_derivation_abort(&operation); + psa_destroy_key(key_id); + + return psaToOtError(status); +} + +#endif // #if OPENTHREAD_FTD + +#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA diff --git a/src/core/crypto/storage.hpp b/src/core/crypto/storage.hpp index 5649c08d2d7..afb38b864b4 100644 --- a/src/core/crypto/storage.hpp +++ b/src/core/crypto/storage.hpp @@ -57,10 +57,11 @@ namespace Storage { */ enum KeyType : uint8_t { - kKeyTypeRaw = OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data. - kKeyTypeAes = OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES. - kKeyTypeHmac = OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC. - kKeyTypeEcdsa = OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA. + kKeyTypeRaw = OT_CRYPTO_KEY_TYPE_RAW, ///< Key Type: Raw Data. + kKeyTypeAes = OT_CRYPTO_KEY_TYPE_AES, ///< Key Type: AES. + kKeyTypeHmac = OT_CRYPTO_KEY_TYPE_HMAC, ///< Key Type: HMAC. + kKeyTypeEcdsa = OT_CRYPTO_KEY_TYPE_ECDSA, ///< Key Type: ECDSA. + kKeyTypeDerive = OT_CRYPTO_KEY_TYPE_DERIVE, ///< Key Type: Derive. }; /** @@ -72,6 +73,7 @@ enum KeyAlgorithm : uint8_t kKeyAlgorithmAesEcb = OT_CRYPTO_KEY_ALG_AES_ECB, ///< Key Algorithm: AES ECB. kKeyAlgorithmHmacSha256 = OT_CRYPTO_KEY_ALG_HMAC_SHA_256, ///< Key Algorithm: HMAC SHA-256. kKeyAlgorithmEcdsa = OT_CRYPTO_KEY_ALG_ECDSA, ///< Key Algorithm: ECDSA. + kKeyAlgorithmHkdfSha256 = OT_CRYPTO_KEY_ALG_HKDF_SHA256, ///< Key Algorithm: HKDF SHA-256. }; constexpr uint8_t kUsageNone = OT_CRYPTO_KEY_USAGE_NONE; ///< Key Usage: Key Usage is empty. @@ -80,6 +82,7 @@ constexpr uint8_t kUsageEncrypt = OT_CRYPTO_KEY_USAGE_ENCRYPT; ///< Key U constexpr uint8_t kUsageDecrypt = OT_CRYPTO_KEY_USAGE_DECRYPT; ///< Key Usage: AES ECB. constexpr uint8_t kUsageSignHash = OT_CRYPTO_KEY_USAGE_SIGN_HASH; ///< Key Usage: Sign Hash. constexpr uint8_t kUsageVerifyHash = OT_CRYPTO_KEY_USAGE_VERIFY_HASH; ///< Key Usage: Verify Hash. +constexpr uint8_t kUsageDerive = OT_CRYPTO_KEY_USAGE_DERIVE; ///< Key Usage: Derive. /** * Defines the key storage types. From 81c72e5d701bd92f1d96bd24366b4a7a9662308d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Sun, 22 Sep 2024 01:57:39 +0200 Subject: [PATCH 02/12] [crypto] enable PSA Crypto API by default --- examples/platforms/simulation/CMakeLists.txt | 2 +- examples/platforms/simulation/crypto.c | 121 ------------------ examples/platforms/simulation/entropy.c | 34 +++++ .../openthread-core-simulation-config.h | 12 ++ src/core/meshcop/tcat_agent.cpp | 19 +++ src/posix/platform/CMakeLists.txt | 1 + src/posix/platform/entropy.cpp | 34 +++++ .../platform/openthread-core-posix-config.h | 8 ++ tests/unit/CMakeLists.txt | 1 + tests/unit/test_platform.cpp | 119 +++++------------ third_party/mbedtls/CMakeLists.txt | 31 ++++- third_party/mbedtls/mbedtls-config.h | 121 +++++++++++++----- third_party/mbedtls/psa-crypto-config.h | 82 ++++++++++++ 13 files changed, 340 insertions(+), 245 deletions(-) delete mode 100644 examples/platforms/simulation/crypto.c create mode 100644 third_party/mbedtls/psa-crypto-config.h diff --git a/examples/platforms/simulation/CMakeLists.txt b/examples/platforms/simulation/CMakeLists.txt index 6506c413a9e..714f00452b4 100644 --- a/examples/platforms/simulation/CMakeLists.txt +++ b/examples/platforms/simulation/CMakeLists.txt @@ -74,7 +74,6 @@ set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE) add_library(openthread-simulation alarm.c ble.c - crypto.c diag.c dns.c dnssd.c @@ -106,6 +105,7 @@ target_link_libraries(openthread-simulation PRIVATE openthread-platform ot-simulation-config ot-config + mbedtls ) target_compile_options(openthread-simulation PRIVATE diff --git a/examples/platforms/simulation/crypto.c b/examples/platforms/simulation/crypto.c deleted file mode 100644 index 20c151b46b2..00000000000 --- a/examples/platforms/simulation/crypto.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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; -} - -otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef) -{ - OT_UNUSED_VARIABLE(aKeyRef); - - return OT_ERROR_NONE; -} - -otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey) -{ - OT_UNUSED_VARIABLE(aKeyRef); - OT_UNUSED_VARIABLE(aPublicKey); - - return OT_ERROR_NONE; -} - -otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef, - const otPlatCryptoSha256Hash *aHash, - otPlatCryptoEcdsaSignature *aSignature) -{ - OT_UNUSED_VARIABLE(aKeyRef); - OT_UNUSED_VARIABLE(aHash); - OT_UNUSED_VARIABLE(aSignature); - - return OT_ERROR_NONE; -} - -otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef, - const otPlatCryptoSha256Hash *aHash, - const otPlatCryptoEcdsaSignature *aSignature) -{ - OT_UNUSED_VARIABLE(aKeyRef); - OT_UNUSED_VARIABLE(aHash); - OT_UNUSED_VARIABLE(aSignature); - - return OT_ERROR_NONE; -} - -#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE diff --git a/examples/platforms/simulation/entropy.c b/examples/platforms/simulation/entropy.c index 951bddeba31..19bd30ab6af 100644 --- a/examples/platforms/simulation/entropy.c +++ b/examples/platforms/simulation/entropy.c @@ -38,6 +38,10 @@ #include +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) +#include +#endif + #include "utils/code_utils.h" #ifndef __SANITIZE_ADDRESS__ @@ -133,3 +137,33 @@ otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength) return error; } + +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** + * When OpenThread is compiled with the PSA Crypto backend using Mbed TLS 3.x, there is no + * API to configure a dedicated non-default entropy source. It is documented that a future version of + * Mbed TLS (likely 4.x) will include a PSA interface for configuring entropy sources. + * + * For now, we need to define the external RNG. Since the implementation of `otPlatEntropyGet` already + * uses CSPRNG, we will call it here as well. + */ +psa_status_t mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t *context, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + OT_UNUSED_VARIABLE(context); + + otError error; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + error = otPlatEntropyGet(output, (uint16_t)output_size); + if (error == OT_ERROR_NONE) + { + *output_length = output_size; + status = PSA_SUCCESS; + } + + return status; +} +#endif diff --git a/examples/platforms/simulation/openthread-core-simulation-config.h b/examples/platforms/simulation/openthread-core-simulation-config.h index 9cee9af8bea..4cc6339adca 100644 --- a/examples/platforms/simulation/openthread-core-simulation-config.h +++ b/examples/platforms/simulation/openthread-core-simulation-config.h @@ -39,6 +39,18 @@ #define OPENTHREAD_RADIO 0 #endif +#if !OPENTHREAD_RADIO + +#ifndef OPENTHREAD_CONFIG_CRYPTO_LIB +#define OPENTHREAD_CONFIG_CRYPTO_LIB OPENTHREAD_CONFIG_CRYPTO_LIB_PSA +#endif + +#ifndef OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +#define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 1 +#endif + +#endif + #ifndef OPENTHREAD_CONFIG_PLATFORM_INFO #define OPENTHREAD_CONFIG_PLATFORM_INFO "SIMULATION" #endif diff --git a/src/core/meshcop/tcat_agent.cpp b/src/core/meshcop/tcat_agent.cpp index c98850aa5eb..6ab326a7640 100644 --- a/src/core/meshcop/tcat_agent.cpp +++ b/src/core/meshcop/tcat_agent.cpp @@ -839,12 +839,31 @@ void TcatAgent::CalculateHash(uint64_t aChallenge, const char *aBuf, size_t aBuf Crypto::Key cryptoKey; Crypto::HmacSha256 hmac; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::KeyRef keyRef; + Error error; + + error = Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeHmac, Crypto::Storage::kKeyAlgorithmHmacSha256, + Crypto::Storage::kUsageSignHash, Crypto::Storage::kTypeVolatile, + reinterpret_cast(aBuf), aBufLen); + SuccessOrExit(error); + + cryptoKey.SetAsKeyRef(keyRef); +#else cryptoKey.Set(reinterpret_cast(aBuf), static_cast(aBufLen)); +#endif hmac.Start(cryptoKey); hmac.Update(aChallenge); hmac.Update(rawKey.p, static_cast(rawKey.len)); hmac.Finish(aHash); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::DestroyKey(keyRef); + +exit: + return; +#endif } Error TcatAgent::HandleStartThreadInterface(void) diff --git a/src/posix/platform/CMakeLists.txt b/src/posix/platform/CMakeLists.txt index 923c4e284a3..ce0440ab7f5 100644 --- a/src/posix/platform/CMakeLists.txt +++ b/src/posix/platform/CMakeLists.txt @@ -172,6 +172,7 @@ target_link_libraries(openthread-posix ot-config-ftd ot-config ot-posix-config + mbedtls $<$>:util> $<$:rt> ) diff --git a/src/posix/platform/entropy.cpp b/src/posix/platform/entropy.cpp index 2dc98e3d22a..d9a3d80eca1 100644 --- a/src/posix/platform/entropy.cpp +++ b/src/posix/platform/entropy.cpp @@ -40,6 +40,10 @@ #include #include +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) +#include +#endif + #include "common/code_utils.hpp" #ifndef __SANITIZE_ADDRESS__ @@ -135,3 +139,33 @@ otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength) return error; } + +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** + * When OpenThread is compiled with the PSA Crypto backend using Mbed TLS 3.x, there is no + * API to configure a dedicated non-default entropy source. It is documented that a future version of + * Mbed TLS (likely 4.x) will include a PSA interface for configuring entropy sources. + * + * For now, we need to define the external RNG. Since the implementation of `otPlatEntropyGet` already + * uses CSPRNG, we will call it here as well. + */ +extern "C" psa_status_t mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t *context, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + OT_UNUSED_VARIABLE(context); + + otError error; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + error = otPlatEntropyGet(output, (uint16_t)output_size); + if (error == OT_ERROR_NONE) + { + *output_length = output_size; + status = PSA_SUCCESS; + } + + return status; +} +#endif diff --git a/src/posix/platform/openthread-core-posix-config.h b/src/posix/platform/openthread-core-posix-config.h index 582117494f4..fcce4cee063 100644 --- a/src/posix/platform/openthread-core-posix-config.h +++ b/src/posix/platform/openthread-core-posix-config.h @@ -156,6 +156,14 @@ #define OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE 1 #endif +#ifndef OPENTHREAD_CONFIG_CRYPTO_LIB +#define OPENTHREAD_CONFIG_CRYPTO_LIB OPENTHREAD_CONFIG_CRYPTO_LIB_PSA +#endif + +#ifndef OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +#define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 1 +#endif + #ifndef OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS /** * The `system.cpp` has registered a state-changed callback handler. Another state-changed callback handler diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index af89d17d776..412189e2957 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -101,6 +101,7 @@ endif() target_link_libraries(ot-test-platform-ftd PRIVATE ot-config + mbedtls ${OT_MBEDTLS} ) diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp index f5a246f221b..374b53a5c3e 100644 --- a/tests/unit/test_platform.cpp +++ b/tests/unit/test_platform.cpp @@ -40,6 +40,10 @@ #include #endif +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) +#include +#endif + enum { FLASH_SWAP_SIZE = 2048, @@ -228,6 +232,36 @@ OT_TOOL_WEAK otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength) return error; } +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** + * When OpenThread is compiled with the PSA Crypto backend using Mbed TLS 3.x, there is no + * API to configure a dedicated non-default entropy source. It is documented that a future version of + * Mbed TLS (likely 4.x) will include a PSA interface for configuring entropy sources. + * + * For now, we need to define the external RNG. Since the implementation of `otPlatEntropyGet` already + * uses CSPRNG, we will call it here as well. + */ +extern "C" psa_status_t mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t *context, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + OT_UNUSED_VARIABLE(context); + + otError error; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + error = otPlatEntropyGet(output, (uint16_t)output_size); + if (error == OT_ERROR_NONE) + { + *output_length = output_size; + status = PSA_SUCCESS; + } + + return status; +} +#endif + static void DiagOutput(const char *aFormat, ...) { va_list args; @@ -489,91 +523,6 @@ OT_TOOL_WEAK otError otPlatInfraIfSendIcmp6Nd(uint32_t, const otIp6Address *, co OT_TOOL_WEAK otError otPlatInfraIfDiscoverNat64Prefix(uint32_t) { return OT_ERROR_FAILED; } #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; -} - -otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef) -{ - OT_UNUSED_VARIABLE(aKeyRef); - - return OT_ERROR_NONE; -} - -otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey) -{ - OT_UNUSED_VARIABLE(aKeyRef); - OT_UNUSED_VARIABLE(aPublicKey); - - return OT_ERROR_NONE; -} - -otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef, - const otPlatCryptoSha256Hash *aHash, - otPlatCryptoEcdsaSignature *aSignature) -{ - OT_UNUSED_VARIABLE(aKeyRef); - OT_UNUSED_VARIABLE(aHash); - OT_UNUSED_VARIABLE(aSignature); - - return OT_ERROR_NONE; -} - -otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef, - const otPlatCryptoSha256Hash *aHash, - const otPlatCryptoEcdsaSignature *aSignature) -{ - OT_UNUSED_VARIABLE(aKeyRef); - OT_UNUSED_VARIABLE(aHash); - OT_UNUSED_VARIABLE(aSignature); - - return OT_ERROR_NONE; -} - -#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE - otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold) { OT_UNUSED_VARIABLE(aInstance); diff --git a/third_party/mbedtls/CMakeLists.txt b/third_party/mbedtls/CMakeLists.txt index 5fd9c5eb924..edda48e900a 100644 --- a/third_party/mbedtls/CMakeLists.txt +++ b/third_party/mbedtls/CMakeLists.txt @@ -27,8 +27,10 @@ # set(OT_MBEDTLS_DEFAULT_CONFIG_FILE \"openthread-mbedtls-config.h\") +set(OT_PSA_CRYPTO_DEFAULT_CONFIG_FILE \"openthread-psa-crypto-config.h\") set(OT_MBEDTLS_CONFIG_FILE "" CACHE STRING "The mbedTLS config file") +set(OT_PSA_CRYPTO_CONFIG_FILE "" CACHE STRING "The PCA Crypto config file") set(ENABLE_TESTING OFF CACHE BOOL "Disable mbedtls test" FORCE) set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable mbetls program" FORCE) @@ -42,6 +44,8 @@ if(UNIFDEF_EXE) endif() find_program(SED_EXE sed) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-but-set-variable") + string(REPLACE "-Wconversion" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") string(REPLACE "-Wconversion" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") @@ -63,15 +67,29 @@ if(UNIFDEFALL_EXE AND SED_EXE AND UNIFDEF_VERSION VERSION_GREATER_EQUAL 2.10) COMMAND_EXPAND_LISTS ) + add_custom_command(OUTPUT openthread-psa-crypto-config.h + COMMAND ${UNIFDEFALL_EXE} + "'-D$,';'-D>'" + "-I$,;-I>" + "-I$" + "-I${CMAKE_CURRENT_SOURCE_DIR}/repo/include" + "${CMAKE_CURRENT_SOURCE_DIR}/psa-crypto-config.h" | + ${SED_EXE} '/openthread-core-config\.h/d' > + openthread-psa-crypto-config.h + MAIN_DEPENDENCY psa-crypto-config.h + COMMAND_EXPAND_LISTS + ) + add_custom_target(openthread-mbedtls-config - DEPENDS openthread-mbedtls-config.h) + DEPENDS openthread-mbedtls-config.h openthread-psa-crypto-config.h) - add_dependencies(ot-config openthread-mbedtls-config) - add_dependencies(mbedtls openthread-mbedtls-config) - add_dependencies(mbedx509 openthread-mbedtls-config) - add_dependencies(mbedcrypto openthread-mbedtls-config) + add_dependencies(ot-config openthread-mbedtls-config openthread-psa-crypto-config) + add_dependencies(mbedtls openthread-mbedtls-config openthread-psa-crypto-config) + add_dependencies(mbedx509 openthread-mbedtls-config openthread-psa-crypto-config) + add_dependencies(mbedcrypto openthread-mbedtls-config openthread-psa-crypto-config) else() configure_file(mbedtls-config.h openthread-mbedtls-config.h COPYONLY) + configure_file(psa-crypto-config.h openthread-psa-crypto-config.h COPYONLY) endif() target_include_directories(ot-config SYSTEM @@ -82,6 +100,7 @@ target_include_directories(ot-config SYSTEM target_compile_definitions(mbedtls PUBLIC "MBEDTLS_CONFIG_FILE=$,${OT_MBEDTLS_CONFIG_FILE},${OT_MBEDTLS_DEFAULT_CONFIG_FILE}>" + "MBEDTLS_PSA_CRYPTO_CONFIG_FILE=$,${OT_PSA_CRYPTO_CONFIG_FILE},${OT_PSA_CRYPTO_DEFAULT_CONFIG_FILE}>" PRIVATE $ ) @@ -96,6 +115,7 @@ target_include_directories(mbedtls target_compile_definitions(mbedx509 PUBLIC "MBEDTLS_CONFIG_FILE=$,${OT_MBEDTLS_CONFIG_FILE},${OT_MBEDTLS_DEFAULT_CONFIG_FILE}>" + "MBEDTLS_PSA_CRYPTO_CONFIG_FILE=$,${OT_PSA_CRYPTO_CONFIG_FILE},${OT_PSA_CRYPTO_DEFAULT_CONFIG_FILE}>" PRIVATE $ ) @@ -110,6 +130,7 @@ target_include_directories(mbedx509 target_compile_definitions(mbedcrypto PUBLIC "MBEDTLS_CONFIG_FILE=$,${OT_MBEDTLS_CONFIG_FILE},${OT_MBEDTLS_DEFAULT_CONFIG_FILE}>" + "MBEDTLS_PSA_CRYPTO_CONFIG_FILE=$,${OT_PSA_CRYPTO_CONFIG_FILE},${OT_PSA_CRYPTO_DEFAULT_CONFIG_FILE}>" PRIVATE $ ) diff --git a/third_party/mbedtls/mbedtls-config.h b/third_party/mbedtls/mbedtls-config.h index 32ced0a9e62..104b0bcbfc3 100644 --- a/third_party/mbedtls/mbedtls-config.h +++ b/third_party/mbedtls/mbedtls-config.h @@ -40,7 +40,11 @@ #include #include -#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf +// ============================================================================== +// mbedTLS legacy/PSA configuration +// ============================================================================== + +#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS #define MBEDTLS_AES_C #if (MBEDTLS_VERSION_NUMBER >= 0x03050000) @@ -66,19 +70,46 @@ #define MBEDTLS_ENTROPY_C #define MBEDTLS_HAVE_ASM #define MBEDTLS_HMAC_DRBG_C -#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED #define MBEDTLS_MD_C -#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -#define MBEDTLS_NO_PLATFORM_ENTROPY -#define MBEDTLS_OID_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_PLATFORM_MEMORY -#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS #define MBEDTLS_SHA224_C #define MBEDTLS_SHA256_C #define MBEDTLS_SHA256_SMALLER + +#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_TLS_ENABLE +#define MBEDTLS_BASE64_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDSA_C +#endif + +#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE +#define MBEDTLS_GCM_C +#endif + +#if OPENTHREAD_CONFIG_ECDSA_ENABLE +#define MBEDTLS_BASE64_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDSA_C +#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE +#define MBEDTLS_ECDSA_DETERMINISTIC +#endif +#endif + +#elif OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA + +#define MBEDTLS_USE_PSA_CRYPTO + +#define MBEDTLS_PSA_CRYPTO_C +#define MBEDTLS_PSA_CRYPTO_CLIENT +#define MBEDTLS_PSA_CRYPTO_STORAGE_C +#define MBEDTLS_PSA_CRYPTO_CONFIG +#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + +#endif + +// ============================================================================== +// SSL configuration +// ============================================================================== + #define MBEDTLS_SSL_CLI_C #define MBEDTLS_SSL_DTLS_ANTI_REPLAY #define MBEDTLS_SSL_DTLS_HELLO_VERIFY @@ -93,6 +124,12 @@ #define MBEDTLS_SSL_SRV_C #endif +#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE +#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE +#endif + +#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED #endif @@ -102,36 +139,59 @@ #endif #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE -#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE -#define MBEDTLS_GCM_C +#define MBEDTLS_SSL_MAX_CONTENT_LEN 2000 /**< Maxium fragment length in bytes */ +#elif OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE +#define MBEDTLS_SSL_MAX_CONTENT_LEN 900 /**< Maxium fragment length in bytes */ +#else +#define MBEDTLS_SSL_MAX_CONTENT_LEN 768 /**< Maxium fragment length in bytes */ #endif -#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + +// ============================================================================== +// x509 & PK configuration +// ============================================================================== + +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C + +#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_TLS_ENABLE #define MBEDTLS_BASE64_C -#define MBEDTLS_ECDH_C -#define MBEDTLS_ECDSA_C #define MBEDTLS_PEM_PARSE_C #define MBEDTLS_X509_USE_C #define MBEDTLS_X509_CRT_PARSE_C #endif #if OPENTHREAD_CONFIG_ECDSA_ENABLE -#define MBEDTLS_BASE64_C -#define MBEDTLS_ECDH_C -#define MBEDTLS_ECDSA_C -#if OPENTHREAD_CONFIG_DETERMINISTIC_ECDSA_ENABLE -#define MBEDTLS_ECDSA_DETERMINISTIC -#endif #define MBEDTLS_PEM_PARSE_C #define MBEDTLS_PK_WRITE_C #endif +// ============================================================================== +// MPI configuration +// ============================================================================== + #define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */ #define MBEDTLS_MPI_MAX_SIZE 32 /**< Maximum number of bytes for usable MPIs. */ + +// ============================================================================== +// ECP configuration +// ============================================================================== + +#if (MBEDTLS_VERSION_NUMBER < 0x03000000) #define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */ +#endif #define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */ #define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */ -#define MBEDTLS_ENTROPY_MAX_SOURCES 1 /**< Maximum number of sources supported */ + +// ============================================================================== +// Platform configuration +// ============================================================================== + +#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE #define MBEDTLS_PLATFORM_STD_CALLOC otPlatCAlloc /**< Default allocator to use, can be undefined */ @@ -140,17 +200,12 @@ #define MBEDTLS_MEMORY_BUFFER_ALLOC_C #endif -#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE -#define MBEDTLS_SSL_MAX_CONTENT_LEN 2000 /**< Maxium fragment length in bytes */ -#elif OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE -#define MBEDTLS_SSL_MAX_CONTENT_LEN 900 /**< Maxium fragment length in bytes */ -#else -#define MBEDTLS_SSL_MAX_CONTENT_LEN 768 /**< Maxium fragment length in bytes */ -#endif - -#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN -#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN -#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_ENTROPY_MAX_SOURCES 1 // Spans multiple lines to avoid being processed by unifdef #if defined(\ diff --git a/third_party/mbedtls/psa-crypto-config.h b/third_party/mbedtls/psa-crypto-config.h new file mode 100644 index 00000000000..43a7c907ef7 --- /dev/null +++ b/third_party/mbedtls/psa-crypto-config.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024, 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. + */ + +// Spans multiple lines to avoid being processed by unifdef +#ifndef \ + PSA_CRYPTO_CONFIG_H +#define PSA_CRYPTO_CONFIG_H + +#include "openthread-core-config.h" + +#include + +#define PSA_WANT_ALG_CBC_NO_PADDING 1 +#define PSA_WANT_ALG_CBC_PKCS7 1 +#define PSA_WANT_ALG_CCM 1 +#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 +#define PSA_WANT_ALG_CMAC 1 +#define PSA_WANT_ALG_CFB 1 +#define PSA_WANT_ALG_CTR 1 +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 +#define PSA_WANT_ALG_ECB_NO_PADDING 1 +#define PSA_WANT_ALG_ECDH 1 +#define PSA_WANT_ALG_ECDSA 1 +#define PSA_WANT_ALG_JPAKE 1 +#define PSA_WANT_ALG_GCM 1 +#define PSA_WANT_ALG_HKDF 1 +#define PSA_WANT_ALG_HKDF_EXTRACT 1 +#define PSA_WANT_ALG_HKDF_EXPAND 1 +#define PSA_WANT_ALG_HMAC 1 +#define PSA_WANT_ALG_PBKDF2_HMAC 1 +#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 1 +#define PSA_WANT_ALG_RIPEMD160 1 +#define PSA_WANT_ALG_SHA_1 1 +#define PSA_WANT_ALG_SHA_224 1 +#define PSA_WANT_ALG_SHA_256 1 +#define PSA_WANT_ALG_TLS12_PRF 1 +#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 +#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 + +#define PSA_WANT_ECC_SECP_K1_256 1 +#define PSA_WANT_ECC_SECP_R1_256 1 + +#define PSA_WANT_KEY_TYPE_DERIVE 1 +#define PSA_WANT_KEY_TYPE_PASSWORD 1 +#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 +#define PSA_WANT_KEY_TYPE_HMAC 1 +#define PSA_WANT_KEY_TYPE_AES 1 +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_RAW_DATA 1 + +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 + +#endif /* PSA_CRYPTO_CONFIG_H */ From b9efa8bbd1f2dea5066874290e6a4a5e41b55d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Tue, 24 Sep 2024 22:20:07 +0200 Subject: [PATCH 03/12] [crypto] PSA API: Align AES unit tests --- tests/unit/test_aes.cpp | 76 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/tests/unit/test_aes.cpp b/tests/unit/test_aes.cpp index b6351ddcabb..82b50e94312 100644 --- a/tests/unit/test_aes.cpp +++ b/tests/unit/test_aes.cpp @@ -41,7 +41,7 @@ namespace ot { */ void TestMacBeaconFrame(void) { - uint8_t key[] = { + uint8_t rawKey[] = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, }; @@ -57,19 +57,34 @@ void TestMacBeaconFrame(void) 0xAC, 0x02, 0x05, 0x00, 0x00, 0x00, 0x55, 0xCF, 0x00, 0x00, 0x51, 0x52, 0x53, 0x54, 0x22, 0x3B, 0xC1, 0xEC, 0x84, 0x1A, 0xB5, 0x53}; + uint8_t nonce[] = { + 0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x02, + }; + otInstance *instance = testInitInstance(); Crypto::AesCcm aesCcm; uint32_t headerLength = sizeof(test) - 8; uint32_t payloadLength = 0; uint8_t tagLength = 8; - uint8_t nonce[] = { - 0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x02, - }; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Key key; + Crypto::Storage::KeyRef keyRef; +#endif VerifyOrQuit(instance != nullptr); - aesCcm.SetKey(key, sizeof(key)); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes, Crypto::Storage::kKeyAlgorithmAesEcb, + Crypto::Storage::kUsageEncrypt, Crypto::Storage::kTypeVolatile, rawKey, + sizeof(rawKey))); + + key.SetAsKeyRef(keyRef); + aesCcm.SetKey(key); +#else + aesCcm.SetKey(rawKey, sizeof(rawKey)); +#endif + aesCcm.Init(headerLength, payloadLength, tagLength, nonce, sizeof(nonce)); aesCcm.Header(test, headerLength); VerifyOrQuit(aesCcm.GetTagLength() == tagLength); @@ -84,6 +99,10 @@ void TestMacBeaconFrame(void) VerifyOrQuit(memcmp(test, decrypted, sizeof(decrypted)) == 0); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::DestroyKey(keyRef); +#endif + testFreeInstance(instance); } @@ -92,7 +111,7 @@ void TestMacBeaconFrame(void) */ void TestMacCommandFrame(void) { - uint8_t key[] = { + uint8_t rawKey[] = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, }; @@ -128,9 +147,24 @@ void TestMacCommandFrame(void) Message *message; Crypto::AesCcm aesCcm; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Key key; + Crypto::Storage::KeyRef keyRef; +#endif + VerifyOrQuit(instance != nullptr); - aesCcm.SetKey(key, sizeof(key)); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes, Crypto::Storage::kKeyAlgorithmAesEcb, + Crypto::Storage::kUsageEncrypt, Crypto::Storage::kTypeVolatile, rawKey, + sizeof(rawKey))); + + key.SetAsKeyRef(keyRef); + aesCcm.SetKey(key); +#else + aesCcm.SetKey(rawKey, sizeof(rawKey)); +#endif + aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce)); aesCcm.Header(test, kHeaderLength); aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, Crypto::AesCcm::kEncrypt); @@ -171,6 +205,11 @@ void TestMacCommandFrame(void) VerifyOrQuit(message->Compare(0, decrypted)); message->Free(); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::DestroyKey(keyRef); +#endif + testFreeInstance(instance); } @@ -182,7 +221,7 @@ void TestInPlaceAesCcmProcessing(void) static constexpr uint16_t kTagLength = 4; static constexpr uint32_t kHeaderLength = 19; - static const uint8_t kKey[] = { + static const uint8_t kRawKey[] = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, }; @@ -200,12 +239,26 @@ void TestInPlaceAesCcmProcessing(void) Message *message; Message *messageClone; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Key key; + Crypto::Storage::KeyRef keyRef; +#endif + VerifyOrQuit(instance != nullptr); message = instance->Get().Allocate(Message::kTypeIp6); VerifyOrQuit(message != nullptr); - aesCcm.SetKey(kKey, sizeof(kKey)); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes, Crypto::Storage::kKeyAlgorithmAesEcb, + Crypto::Storage::kUsageEncrypt, Crypto::Storage::kTypeVolatile, kRawKey, + sizeof(kRawKey))); + + key.SetAsKeyRef(keyRef); + aesCcm.SetKey(key); +#else + aesCcm.SetKey(kRawKey, sizeof(kRawKey)); +#endif for (uint16_t msgLength : kMessageLengths) { @@ -251,6 +304,11 @@ void TestInPlaceAesCcmProcessing(void) } message->Free(); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::DestroyKey(keyRef); +#endif + testFreeInstance(instance); } From 1e4c6a3f947920de6998687dd88753398a52056a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Tue, 24 Sep 2024 23:05:49 +0200 Subject: [PATCH 04/12] [crypto] PSA API: Align HMAC-SHA256 unit tests --- tests/unit/test_hmac_sha256.cpp | 49 +++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/tests/unit/test_hmac_sha256.cpp b/tests/unit/test_hmac_sha256.cpp index 7b9e20ad1ae..241ca41f71a 100644 --- a/tests/unit/test_hmac_sha256.cpp +++ b/tests/unit/test_hmac_sha256.cpp @@ -141,10 +141,15 @@ void TestHmacSha256(void) { struct TestCase { - otCryptoKey mKey; + const uint8_t *mKey; + uint16_t mKeyLength; const void *mData; uint16_t mDataLength; otCryptoSha256Hash mHash; + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::KeyRef mKeyRef; +#endif }; // Test-cases from RFC 4231. @@ -218,12 +223,12 @@ void TestHmacSha256(void) 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2, }}; - static const TestCase kTestCases[] = { - {{&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}, + static TestCase kTestCases[] = { + {kKey1, sizeof(kKey1), kData1, sizeof(kData1) - 1, kHash1}, + {reinterpret_cast(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}, }; Instance *instance = testInitInstance(); @@ -239,12 +244,23 @@ void TestHmacSha256(void) messagePool = &instance->Get(); VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr); - for (const TestCase &testCase : kTestCases) + for (TestCase &testCase : kTestCases) { Crypto::HmacSha256 hmac; Crypto::HmacSha256::Hash hash; + Crypto::Key key; + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrQuit(Crypto::Storage::ImportKey( + testCase.mKeyRef, Crypto::Storage::kKeyTypeHmac, Crypto::Storage::kKeyAlgorithmHmacSha256, + Crypto::Storage::kUsageSignHash, Crypto::Storage::kTypeVolatile, testCase.mKey, testCase.mKeyLength)); - hmac.Start(static_cast(testCase.mKey)); + key.SetAsKeyRef(testCase.mKeyRef); +#else + key.Set(testCase.mKey, testCase.mKeyLength); +#endif + + hmac.Start(key); hmac.Update(testCase.mData, testCase.mDataLength); hmac.Finish(hash); @@ -255,7 +271,7 @@ void TestHmacSha256(void) index = 0; - for (const TestCase &testCase : kTestCases) + for (TestCase &testCase : kTestCases) { SuccessOrQuit(message->Append("Hello")); offsets[index++] = message->GetLength(); @@ -269,12 +285,23 @@ void TestHmacSha256(void) { Crypto::HmacSha256 hmac; Crypto::HmacSha256::Hash hash; + Crypto::Key key; - hmac.Start(static_cast(testCase.mKey)); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + key.SetAsKeyRef(testCase.mKeyRef); +#else + key.Set(testCase.mKey, testCase.mKeyLength); +#endif + + hmac.Start(key); hmac.Update(*message, offsets[index++], testCase.mDataLength); hmac.Finish(hash); VerifyOrQuit(hash == static_cast(testCase.mHash)); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::DestroyKey(testCase.mKeyRef); +#endif } message->Free(); From 87e2b2145108016c05a6b3976c46cda4f7fcbaa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Thu, 26 Sep 2024 23:32:29 +0200 Subject: [PATCH 05/12] [crypto] PSA API: Align HKDF_SHA256 unit tests --- tests/unit/test_hkdf_sha256.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_hkdf_sha256.cpp b/tests/unit/test_hkdf_sha256.cpp index 2b3c01dc371..219272c707a 100644 --- a/tests/unit/test_hkdf_sha256.cpp +++ b/tests/unit/test_hkdf_sha256.cpp @@ -134,6 +134,10 @@ void TestHkdfSha256(void) uint8_t outKey[kMaxOuttKey]; Crypto::Key testInputKey; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::KeyRef keyRef; +#endif + printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); DumpBuffer("\nInput Key", test->mInKey, test->mInKeyLength); DumpBuffer("\nSalt", test->mSalt, test->mSaltLength); @@ -141,9 +145,16 @@ 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; + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrQuit(Crypto::Storage::ImportKey( + keyRef, Crypto::Storage::kKeyTypeDerive, Crypto::Storage::kKeyAlgorithmHkdfSha256, + Crypto::Storage::kUsageDerive, Crypto::Storage::kTypeVolatile, test->mInKey, test->mInKeyLength)); + + testInputKey.SetAsKeyRef(keyRef); +#else + testInputKey.Set(test->mInKey, test->mInKeyLength); +#endif hkdf.Extract(test->mSalt, test->mSaltLength, testInputKey); hkdf.Expand(test->mInfo, test->mInfoLength, outKey, test->mOutKeyLength); @@ -156,6 +167,10 @@ void TestHkdfSha256(void) { VerifyOrQuit(outKey[i] == kFillByte, "HKDF-SHA-256 wrote beyond output key length"); } + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::DestroyKey(keyRef); +#endif } testFreeInstance(instance); From ac7b35a2c5fce3fd6c724cd96822b37d53d26a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Sun, 29 Sep 2024 01:17:10 +0200 Subject: [PATCH 06/12] [crypto] PSA API: Align ECDSA unit tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Łukasz Duda --- src/core/net/srp_client.cpp | 9 +++++++-- tests/unit/test_ecdsa.cpp | 31 +++++++++++++++++++++++++++++-- tests/unit/test_srp_server.cpp | 2 ++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/core/net/srp_client.cpp b/src/core/net/srp_client.cpp index 121a2941707..2d2e4852c4d 100644 --- a/src/core/net/srp_client.cpp +++ b/src/core/net/srp_client.cpp @@ -391,6 +391,11 @@ Client::Client(Instance &aInstance) }; mHostInfo.Init(); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + KeyInfo keyInfo(Get().KeyRefFor(Crypto::Storage::KeyRefManager::kEcdsa)); + IgnoreError(ReadOrGenerateKey(keyInfo)); +#endif } Error Client::Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester) @@ -1111,9 +1116,9 @@ Error Client::PrepareUpdateMessage(MsgInfo &aInfo) #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE aInfo.mKeyInfo.SetKeyRef(Get().KeyRefFor(Crypto::Storage::KeyRefManager::kEcdsa)); -#endif - +#else SuccessOrExit(error = ReadOrGenerateKey(aInfo.mKeyInfo)); +#endif header.SetMessageId(mNextMessageId); diff --git a/tests/unit/test_ecdsa.cpp b/tests/unit/test_ecdsa.cpp index aad13a74882..d0bb6c3172e 100644 --- a/tests/unit/test_ecdsa.cpp +++ b/tests/unit/test_ecdsa.cpp @@ -77,7 +77,13 @@ void TestEcdsaVector(void) Instance *instance = testInitInstance(); - Ecdsa::P256::KeyPair keyPair; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Ecdsa::P256::KeyPairAsRef keyPair; + Crypto::Storage::KeyRef keyRef; +#else + Ecdsa::P256::KeyPair keyPair; +#endif + Ecdsa::P256::PublicKey publicKey; Ecdsa::P256::Signature signature; Sha256 sha256; @@ -89,10 +95,18 @@ void TestEcdsaVector(void) printf("Test ECDA with test vector from RFC 6979 (A.2.5)\n"); printf("\nLoading key-pair ----------------------------------------------------------\n"); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + SuccessOrQuit(Crypto::Storage::ImportKey(keyRef, Storage::kKeyTypeEcdsa, Storage::kKeyAlgorithmEcdsa, + (Storage::kUsageSignHash | Storage::kUsageVerifyHash), + Storage::kTypeVolatile, kKeyPairInfo, sizeof(kKeyPairInfo))); + keyPair.SetKeyRef(keyRef); +#else memcpy(keyPair.GetDerBytes(), kKeyPairInfo, sizeof(kKeyPairInfo)); keyPair.SetDerLength(sizeof(kKeyPairInfo)); DumpBuffer("KeyPair", keyPair.GetDerBytes(), keyPair.GetDerLength()); +#endif SuccessOrQuit(keyPair.GetPublicKey(publicKey)); DumpBuffer("PublicKey", publicKey.GetBytes(), Ecdsa::P256::PublicKey::kSize); @@ -109,6 +123,7 @@ void TestEcdsaVector(void) DumpBuffer("Hash", hash.GetBytes(), sizeof(hash)); printf("\nSign the message ----------------------------------------------------------\n"); + SuccessOrQuit(keyPair.Sign(hash, signature)); DumpBuffer("Signature", signature.GetBytes(), sizeof(signature)); @@ -135,7 +150,13 @@ void TestEcdsaKeyGenerationSignAndVerify(void) const char kMessage[] = "You are not a drop in the ocean. You are the entire ocean in a drop."; - Ecdsa::P256::KeyPair keyPair; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::KeyRef keyRef = 0x1234; + Ecdsa::P256::KeyPairAsRef keyPair(keyRef); +#else + Ecdsa::P256::KeyPair keyPair; +#endif + Ecdsa::P256::PublicKey publicKey; Ecdsa::P256::Signature signature; Sha256 sha256; @@ -149,7 +170,9 @@ void TestEcdsaKeyGenerationSignAndVerify(void) printf("\nGenerating key-pair -------------------------------------------------------\n"); SuccessOrQuit(keyPair.Generate()); +#if !OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE DumpBuffer("KeyPair", keyPair.GetDerBytes(), keyPair.GetDerLength()); +#endif SuccessOrQuit(keyPair.GetPublicKey(publicKey)); DumpBuffer("PublicKey", publicKey.GetBytes(), Ecdsa::P256::PublicKey::kSize); @@ -175,6 +198,10 @@ void TestEcdsaKeyGenerationSignAndVerify(void) VerifyOrQuit(publicKey.Verify(hash, signature) != kErrorNone, "PublicKey::Verify() passed for invalid signature"); printf("\nSignature verification correctly failed with incorrect hash/signature.\n\n"); +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::DestroyKey(keyRef); +#endif + testFreeInstance(instance); } diff --git a/tests/unit/test_srp_server.cpp b/tests/unit/test_srp_server.cpp index 07fac57519d..4ac198a91f9 100644 --- a/tests/unit/test_srp_server.cpp +++ b/tests/unit/test_srp_server.cpp @@ -225,6 +225,8 @@ void FinalizeTest(void) SuccessOrQuit(otThreadSetEnabled(sInstance, false)); SuccessOrQuit(otInstanceErasePersistentInfo(sInstance)); testFreeInstance(sInstance); + + VerifyOrQuit(sHeapAllocatedPtrs.GetLength() == 0); } //--------------------------------------------------------------------------------------------------------------------- From e2f908d644173a0894f699d012bd6ab822a38175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Sun, 29 Sep 2024 11:10:20 +0200 Subject: [PATCH 07/12] [crypto] PSA API: Align derivation of TREL key --- src/core/thread/key_manager.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp index a9ab0b0ff70..4a93e8fa51a 100644 --- a/src/core/thread/key_manager.cpp +++ b/src/core/thread/key_manager.cpp @@ -313,7 +313,18 @@ void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const Crypto::Key cryptoKey; #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE - cryptoKey.SetAsKeyRef(mNetworkKeyRef); + Crypto::Storage::KeyRef keyRef; + NetworkKey networkKey; + + GetNetworkKey(networkKey); + + // Create temporary key to perform derive operation. This might be improved by using key copy operation, + // however NetworkKey is exported for the other cases. + SuccessOrAssert(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeDerive, + Crypto::Storage::kKeyAlgorithmHkdfSha256, Crypto::Storage::kUsageDerive, + Crypto::Storage::kTypeVolatile, networkKey.m8, NetworkKey::kSize)); + + cryptoKey.SetAsKeyRef(keyRef); #else cryptoKey.Set(mNetworkKey.m8, NetworkKey::kSize); #endif @@ -323,6 +334,10 @@ void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const hkdf.Extract(salt, sizeof(salt), cryptoKey); hkdf.Expand(kTrelInfoString, sizeof(kTrelInfoString), aKey.m8, Mac::Key::kSize); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + Crypto::Storage::DestroyKey(keyRef); +#endif } #endif From 497d1e40674566db771b35d056cb8f09a447a705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Sun, 9 Feb 2025 17:08:07 +0100 Subject: [PATCH 08/12] [crypto] PSA API: Introduce example native ITS implementation --- third_party/mbedtls/native_its/BUILD.gn | 58 +++ third_party/mbedtls/native_its/CMakeLists.txt | 60 +++ .../mbedtls/native_its/include/psa/error.h | 48 +++ .../include/psa/internal_trusted_storage.h | 149 +++++++ .../mbedtls/native_its/src/file/its_file.c | 384 ++++++++++++++++++ .../mbedtls/native_its/src/ram/its_ram.c | 269 ++++++++++++ 6 files changed, 968 insertions(+) create mode 100644 third_party/mbedtls/native_its/BUILD.gn create mode 100644 third_party/mbedtls/native_its/CMakeLists.txt create mode 100644 third_party/mbedtls/native_its/include/psa/error.h create mode 100644 third_party/mbedtls/native_its/include/psa/internal_trusted_storage.h create mode 100644 third_party/mbedtls/native_its/src/file/its_file.c create mode 100644 third_party/mbedtls/native_its/src/ram/its_ram.c diff --git a/third_party/mbedtls/native_its/BUILD.gn b/third_party/mbedtls/native_its/BUILD.gn new file mode 100644 index 00000000000..130f28fb2ed --- /dev/null +++ b/third_party/mbedtls/native_its/BUILD.gn @@ -0,0 +1,58 @@ +# Copyright (c) 2025, 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. +# + + +config("openthread-native-its-config") { + include_dirs = [ + "include", + ] +} + +static_library("openthread-native-its-file") { + sources = [ + "src/file/its_file.c" + ] + + configs += [ + ":openthread-native-its-config", + ] + + defines = [ "OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE=1" ] +} + +static_library("openthread-native-its-ram") { + sources = [ + "src/ram/its_ram.c" + ] + + configs += [ + ":openthread-native-its-config", + ] + + defines = [ "OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_RAM=1" ] +} + diff --git a/third_party/mbedtls/native_its/CMakeLists.txt b/third_party/mbedtls/native_its/CMakeLists.txt new file mode 100644 index 00000000000..d37f35799aa --- /dev/null +++ b/third_party/mbedtls/native_its/CMakeLists.txt @@ -0,0 +1,60 @@ +# +# Copyright (c) 2024, 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. +# + +add_library(openthread-native-its-file STATIC) +target_sources(openthread-native-its-file PRIVATE + src/file/its_file.c +) +target_include_directories(openthread-native-its-file PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/include" + ${OT_PUBLIC_INCLUDES} + $ +) +target_compile_definitions(openthread-native-its-file + PRIVATE + $ + PUBLIC + OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE=1 +) + +add_library(openthread-native-its-ram STATIC) +target_sources(openthread-native-its-ram PRIVATE + src/ram/its_ram.c +) +target_include_directories(openthread-native-its-ram PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/include" + ${OT_PUBLIC_INCLUDES} + $ +) +target_compile_definitions(openthread-native-its-ram + PRIVATE + $ + PUBLIC + OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_RAM=1 +) + diff --git a/third_party/mbedtls/native_its/include/psa/error.h b/third_party/mbedtls/native_its/include/psa/error.h new file mode 100644 index 00000000000..aabad40232e --- /dev/null +++ b/third_party/mbedtls/native_its/include/psa/error.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024, 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. + */ + +#ifndef PSA_ERROR_H__ +#define PSA_ERROR_H__ + +#include + +typedef int32_t psa_status_t; + +#define PSA_SUCCESS ((psa_status_t)0) +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#endif /* PSA_ERROR_H__ */ diff --git a/third_party/mbedtls/native_its/include/psa/internal_trusted_storage.h b/third_party/mbedtls/native_its/include/psa/internal_trusted_storage.h new file mode 100644 index 00000000000..c607411f0b7 --- /dev/null +++ b/third_party/mbedtls/native_its/include/psa/internal_trusted_storage.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2024, 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. + */ + +#ifndef PSA_INTERNAL_TRUSTED_STORAGE_H__ +#define PSA_INTERNAL_TRUSTED_STORAGE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psa/error.h" + +/** \brief Flags used when creating a data entry + */ +typedef uint32_t psa_storage_create_flags_t; + +/** \brief A type for UIDs used for identifying data + */ +typedef uint64_t psa_storage_uid_t; + +#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ +#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ + +/** + * \brief A container for metadata associated with a specific uid + */ +struct psa_storage_info_t { + uint32_t size; /**< The size of the data associated with a uid **/ + psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ +}; + +/** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) + +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ +#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ + +/** + * \brief Create a new or modify an existing uid/value pair + * + * \param[in] aUid The identifier for the data + * \param[in] aDataLength The size in bytes of the data in `p_data` + * \param[in] aData A buffer containing the data + * \param[in] aCreateFlags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + * + * \retval #PSA_SUCCESS The operation completed successfully + * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE + * \retval #PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium + * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_set(psa_storage_uid_t aUid, + uint32_t aDataLength, + const void *aData, + psa_storage_create_flags_t aCreateFlags); + +/** + * \brief Retrieve the value associated with a provided uid + * + * \param[in] aUid The uid value + * \param[in] aDataOffset The starting offset of the data requested + * \param[in] aDataLength The amount of data requested (and the minimum allocated size of the `p_data` buffer) + * \param[out] aData The buffer where the data will be placed upon successful completion + * \param[out] aDataLengthOut The amount of data returned in the p_data buffer + * + * + * \return A status indicating the success/failure of the operation + * + * \retval #PSA_SUCCESS The operation completed successfully + * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage + * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted + * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) + * is invalid. For example is `NULL` or references memory the caller cannot access. + * In addition, this can also happen if an invalid offset was provided. + */ +psa_status_t psa_its_get(psa_storage_uid_t aUid, + uint32_t aDataOffset, + uint32_t aDataLength, + void *aData, + size_t *aDataLengthOut); + +/** + * \brief Retrieve the metadata about the provided uid + * + * \param[in] aUid The uid value + * \param[out] aInfo A pointer to the `psa_storage_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval #PSA_SUCCESS The operation completed successfully + * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted + * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_get_info(psa_storage_uid_t aUid, + struct psa_storage_info_t *aInfo); + +/** + * \brief Remove the provided key and its associated data from the storage + * + * \param[in] aUid The uid value + * + * \return A status indicating the success/failure of the operation + * + * \retval #PSA_SUCCESS The operation completed successfully + * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage + * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE + * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + */ +psa_status_t psa_its_remove(psa_storage_uid_t aUid); + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_INTERNAL_TRUSTED_STORAGE_H__ */ diff --git a/third_party/mbedtls/native_its/src/file/its_file.c b/third_party/mbedtls/native_its/src/file/its_file.c new file mode 100644 index 00000000000..4056665bf35 --- /dev/null +++ b/third_party/mbedtls/native_its/src/file/its_file.c @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2024, 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 TBD TBD.. + */ + +#include "openthread-core-config.h" + +#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA + +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" + +#include +#include +#include +#include +#include + +#define VerifyOrExit(aCondition, aAction) \ + do \ + { \ + if (!(aCondition)) \ + { \ + aAction; \ + goto exit; \ + } \ + } while (0) + + +/** + * @def ITS_FILE_DEFAULT_FILE_PREFIX + * + * The default directory prefix if the user does not override it by changing + * the global variable @c gItsFileNamePrefix. + */ +#define ITS_FILE_DEFAULT_FILE_PREFIX "tmp/" + +/** + * @def ITS_FILE_PATH_MAX + * + * The maximum allowed length (in bytes) for file paths. + */ +#define ITS_FILE_PATH_MAX 256 + +/** + * @def ITS_DIR_MODE + * + * The mode used when creating directories (0777 gives full permissions to owner, + * group, and others). + */ +#define ITS_DIR_MODE 0777 + +/** + * @def ITS_FILE_HEADER_SIZE + * + * The size (in bytes) of the file header: 4 bytes for flags plus 4 bytes for total data length. + */ +#define ITS_FILE_HEADER_SIZE (sizeof(uint32_t) + sizeof(uint32_t)) + +/** + * @def ITS_FILE_NAME_FORMAT + * + * The format string for building the file path. + */ +#define ITS_FILE_NAME_FORMAT "%suid_%llu.psa_its" + +/** + * A global variable that determines where PSA ITS files are stored. + * + * By default, it is @ref ITS_FILE_DEFAULT_FILE_PREFIX. You can override + * it at runtime: + * @code + * gItsFileNamePrefix = "tmp/its_node_3_offset_12"; + * @endcode + */ +const char *gItsFileNamePrefix = ITS_FILE_DEFAULT_FILE_PREFIX; + + +/** + * Ensures that the directory (specified by `gItsFileNamePrefix`) exists. + */ +static bool ensureDirectoryExists(void) +{ + bool success = true; + struct stat st; + char filePrefix[ITS_FILE_PATH_MAX]; + char *dir; + + // Copy prefix to local buffer, because dirname() modifies its argument + strncpy(filePrefix, gItsFileNamePrefix, sizeof(filePrefix)); + filePrefix[sizeof(filePrefix) - 1] = '\0'; + + dir = dirname(filePrefix); + + // 1) Check if path already exists + if (stat(dir, &st) == 0) + { + // Exists - must be a directory + if (!S_ISDIR(st.st_mode)) + { + success = false; + } + } + else + { + // Path doesn't exist, attempt to create one. + if (mkdir(dir, ITS_DIR_MODE) != 0) + { + // Retry with stat again. + if (stat(dir, &st) != 0 || !S_ISDIR(st.st_mode)) + { + success = false; + } + } + } + + return success; +} + +/** + * Builds the file path for a given UID. + * Returns 0 on success, -1 on error. + */ +static int buildFilePath(psa_storage_uid_t aUid, char *aPath, size_t aPathSize) +{ + int result = 0; + + // Attempt to format + int ret = snprintf(aPath, aPathSize, ITS_FILE_NAME_FORMAT, + gItsFileNamePrefix, (unsigned long long)aUid); + + // If ret < 0 or ret >= aPathSize, return an error. + VerifyOrExit((ret >= 0) && ((size_t)ret < aPathSize), result = -1); + +exit: + return result; +} + +/** + * Reads an 8-byte header from the given file: + * - 4 bytes for flags (psa_storage_create_flags_t) + * - 4 bytes for data length + * + * Returns 0 on success, -1 on error. + */ +static int readHeader(FILE *aFile, psa_storage_create_flags_t *aFlags, uint32_t *aDataLen) +{ + int result = 0; + uint32_t flagsTmp; + uint32_t lenTmp; + + // Read flags + VerifyOrExit(fread(&flagsTmp, sizeof(flagsTmp), 1, aFile) == 1, result = -1); + + // Read length + VerifyOrExit(fread(&lenTmp, sizeof(lenTmp), 1, aFile) == 1, result = -1); + + *aFlags = flagsTmp; + *aDataLen = lenTmp; + +exit: + return result; +} + +/** + * Writes an 8-byte header to the given file: + * - 4 bytes for flags + * - 4 bytes for data length + * + * Returns 0 on success, -1 on error. + */ +static int writeHeader(FILE *aFile, psa_storage_create_flags_t aFlags, uint32_t aDataLen) +{ + int result = 0; + + // Write flags + VerifyOrExit(fwrite(&aFlags, sizeof(aFlags), 1, aFile) == 1, result = -1); + + // Write length + VerifyOrExit(fwrite(&aDataLen, sizeof(aDataLen), 1, aFile) == 1, result = -1); + +exit: + return result; +} + +psa_status_t psa_its_set(psa_storage_uid_t aUid, + uint32_t aDataLength, + const void *aData, + psa_storage_create_flags_t aCreateFlags) +{ + psa_status_t status = PSA_SUCCESS; + FILE *file = NULL; + char path[ITS_FILE_PATH_MAX]; + + // Validate arguments + VerifyOrExit((aData != NULL && aDataLength > 0), status = PSA_ERROR_INVALID_ARGUMENT); + // Only NONE or WRITE_ONCE => no other flags supported + VerifyOrExit((aCreateFlags & ~(PSA_STORAGE_FLAG_WRITE_ONCE)) == 0, status = PSA_ERROR_NOT_SUPPORTED); + + // Ensure directory + VerifyOrExit(ensureDirectoryExists(), status = PSA_ERROR_GENERIC_ERROR); + + // Build path + VerifyOrExit(buildFilePath(aUid, path, sizeof(path)) == 0, status = PSA_ERROR_GENERIC_ERROR); + + // If file exists, check WRITE_ONCE + file = fopen(path, "rb"); + if (file) + { + psa_storage_create_flags_t oldFlags; + uint32_t oldLen; + + if (readHeader(file, &oldFlags, &oldLen) == 0) + { + VerifyOrExit(!(oldFlags & PSA_STORAGE_FLAG_WRITE_ONCE), status = PSA_ERROR_NOT_PERMITTED); + } + + fclose(file); + file = NULL; + } + + // Create/overwrite + file = fopen(path, "wb"); + VerifyOrExit(file != NULL, status = PSA_ERROR_GENERIC_ERROR); + + // Write header + VerifyOrExit(writeHeader(file, aCreateFlags, aDataLength) == 0, status = PSA_ERROR_GENERIC_ERROR); + + // Write data + if (aDataLength > 0 && aData != NULL) + { + size_t written = fwrite(aData, 1, aDataLength, file); + VerifyOrExit(written == aDataLength, status = PSA_ERROR_GENERIC_ERROR); + } + +exit: + if (file) + { + fclose(file); + } + + return status; +} + +psa_status_t psa_its_get(psa_storage_uid_t aUid, + uint32_t aDataOffset, + uint32_t aDataLength, + void *aData, + size_t *aDataLengthOut) +{ + psa_status_t status = PSA_SUCCESS; + FILE *file = NULL; + char path[ITS_FILE_PATH_MAX]; + + VerifyOrExit(aDataLengthOut != NULL, status = PSA_ERROR_INVALID_ARGUMENT); + + if (aDataLength > 0) + { + VerifyOrExit(aData != NULL, status = PSA_ERROR_INVALID_ARGUMENT); + } + + VerifyOrExit(buildFilePath(aUid, path, sizeof(path)) == 0, status = PSA_ERROR_GENERIC_ERROR); + + file = fopen(path, "rb"); + VerifyOrExit(file != NULL, status = PSA_ERROR_DOES_NOT_EXIST); + + { + psa_storage_create_flags_t flags; + uint32_t totalLen; + + VerifyOrExit(readHeader(file, &flags, &totalLen) == 0, status = PSA_ERROR_GENERIC_ERROR); + VerifyOrExit(aDataOffset <= totalLen, status = PSA_ERROR_INVALID_ARGUMENT); + + size_t available = totalLen - aDataOffset; + size_t toCopy = (aDataLength <= available) ? aDataLength : available; + + VerifyOrExit(fseek(file, aDataOffset, SEEK_CUR) == 0, status = PSA_ERROR_GENERIC_ERROR); + + if (toCopy > 0 && aData != NULL) + { + VerifyOrExit(fread(aData, 1, toCopy, file) == toCopy, status = PSA_ERROR_GENERIC_ERROR); + } + + *aDataLengthOut = toCopy; + } + +exit: + if (file) + { + fclose(file); + } + + return status; +} + +psa_status_t psa_its_get_info(psa_storage_uid_t aUid, + struct psa_storage_info_t *aInfo) +{ + psa_status_t status = PSA_SUCCESS; + FILE *file = NULL; + char path[ITS_FILE_PATH_MAX]; + psa_storage_create_flags_t flags; + uint32_t totalLen; + + VerifyOrExit(aInfo != NULL, status = PSA_ERROR_INVALID_ARGUMENT); + VerifyOrExit(buildFilePath(aUid, path, sizeof(path)) == 0, status = PSA_ERROR_GENERIC_ERROR); + + file = fopen(path, "rb"); + VerifyOrExit(file != NULL, status = PSA_ERROR_DOES_NOT_EXIST); + + VerifyOrExit(readHeader(file, &flags, &totalLen) == 0, status = PSA_ERROR_GENERIC_ERROR); + + aInfo->size = totalLen; + aInfo->flags = flags; + +exit: + if (file) + { + fclose(file); + } + + return status; +} + +psa_status_t psa_its_remove(psa_storage_uid_t aUid) +{ + psa_status_t status = PSA_SUCCESS; + FILE *file = NULL; + char path[ITS_FILE_PATH_MAX]; + psa_storage_create_flags_t flags; + uint32_t totalLen; + + VerifyOrExit(buildFilePath(aUid, path, sizeof(path)) == 0, status = PSA_ERROR_GENERIC_ERROR); + + file = fopen(path, "rb"); + VerifyOrExit(file != NULL, status = PSA_ERROR_DOES_NOT_EXIST); + + VerifyOrExit(readHeader(file, &flags, &totalLen) == 0, status = PSA_ERROR_GENERIC_ERROR); + + // If WRITE_ONCE is set, we cannot remove it. + VerifyOrExit(!(flags & PSA_STORAGE_FLAG_WRITE_ONCE), status = PSA_ERROR_NOT_PERMITTED); + + fclose(file); + file = NULL; + + VerifyOrExit((unlink(path) == 0), status = PSA_ERROR_GENERIC_ERROR); + +exit: + if (file) + { + fclose(file); + } + + return status; +} + +#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA diff --git a/third_party/mbedtls/native_its/src/ram/its_ram.c b/third_party/mbedtls/native_its/src/ram/its_ram.c new file mode 100644 index 00000000000..2dcc9caedc3 --- /dev/null +++ b/third_party/mbedtls/native_its/src/ram/its_ram.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2024, 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 a simple in-RAM PSA ITS backend for demonstration and testing. + * + * All data is stored in memory and is not persisted after process termination. + */ + +#include "openthread-core-config.h" + +#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA + +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" + +#include + +#if !OPENTHREAD_RADIO + +#define VerifyOrExit(aCondition, aAction) \ + do \ + { \ + if (!(aCondition)) \ + { \ + aAction; \ + goto exit; \ + } \ + } while (0) + +/** + * @def RAM_ITS_MAX_KEYS + * + * The maximum number of PSA ITS entries that can be stored in RAM. + */ +#define RAM_ITS_MAX_KEYS 64 + +/** + * @def RAM_ITS_MAX_DATA_SIZE + * + * The maximum size (in bytes) of data that can be stored for each entry. + */ +#define RAM_ITS_MAX_DATA_SIZE 128 + + +/** + * Represents a single PSA ITS record stored in RAM. + * + */ +typedef struct +{ + bool mInUse; // Whether this slot is occupied + psa_storage_uid_t mUid; // Unique ID + psa_storage_create_flags_t mFlags; // Storage flags (e.g. WRITE_ONCE) + uint32_t mDataLen; // Current size of stored data + uint8_t mData[RAM_ITS_MAX_DATA_SIZE]; // Raw data storage +} RamItsEntry; + +/** + * Array of entries for RAM-based ITS storage. + * + */ +static RamItsEntry sRamItsEntries[RAM_ITS_MAX_KEYS]; + +/** + * Finds an existing entry by UID. + * + * @param[in] aUid The UID value to search for. + * + * @returns The index of the matching entry, or -1 if not found. + * + */ +static int RamItsFindEntry(psa_storage_uid_t aUid) +{ + for (int i = 0; i < RAM_ITS_MAX_KEYS; i++) + { + if (sRamItsEntries[i].mInUse && (sRamItsEntries[i].mUid == aUid)) + { + return i; + } + } + + return -1; +} + +/** + * Finds a free slot in the storage array. + * + * @returns The index of a free slot, or -1 if none is available. + * + */ +static int RamItsFindFreeSlot(void) +{ + for (int i = 0; i < RAM_ITS_MAX_KEYS; i++) + { + if (!sRamItsEntries[i].mInUse) + { + return i; + } + } + + return -1; +} + +psa_status_t psa_its_set(psa_storage_uid_t aUid, + uint32_t aDataLength, + const void *aData, + psa_storage_create_flags_t aCreateFlags) +{ + psa_status_t status = PSA_SUCCESS; + int idx = -1; + + VerifyOrExit(!(aData == NULL && aDataLength > 0), status = PSA_ERROR_INVALID_ARGUMENT); + + // Allow only NONE or WRITE_ONCE flags. Any others => Not supported. + VerifyOrExit((aCreateFlags & ~(PSA_STORAGE_FLAG_WRITE_ONCE)) == 0, + status = PSA_ERROR_NOT_SUPPORTED); + + // Data length must not exceed our internal buffer size. + VerifyOrExit(aDataLength <= RAM_ITS_MAX_DATA_SIZE, status = PSA_ERROR_INVALID_ARGUMENT); + + // Find existing entry, if any. + idx = RamItsFindEntry(aUid); + if (idx >= 0) + { + // Entry already exists. + + // If WRITE_ONCE is set, we cannot overwrite it. + VerifyOrExit(!(sRamItsEntries[idx].mFlags & PSA_STORAGE_FLAG_WRITE_ONCE), status = PSA_ERROR_NOT_PERMITTED); + + // Overwrite existing entry. + sRamItsEntries[idx].mDataLen = aDataLength; + + if (aDataLength > 0 && aData != NULL) + { + memcpy(sRamItsEntries[idx].mData, aData, aDataLength); + } + + sRamItsEntries[idx].mFlags = aCreateFlags; + } + else + { + // Need a new entry. + idx = RamItsFindFreeSlot(); + VerifyOrExit(idx >= 0, status = PSA_ERROR_INSUFFICIENT_STORAGE); + + sRamItsEntries[idx].mInUse = true; + sRamItsEntries[idx].mUid = aUid; + sRamItsEntries[idx].mFlags = aCreateFlags; + sRamItsEntries[idx].mDataLen = aDataLength; + + if (aDataLength > 0 && aData != NULL) + { + memcpy(sRamItsEntries[idx].mData, aData, aDataLength); + } + } + +exit: + return status; +} + +psa_status_t psa_its_get(psa_storage_uid_t aUid, + uint32_t aDataOffset, + uint32_t aDataLength, + void *aData, + size_t *aDataLengthOut) +{ + psa_status_t status = PSA_SUCCESS; + int idx; + + // Validate pointers. + VerifyOrExit(aDataLengthOut != NULL, status = PSA_ERROR_INVALID_ARGUMENT); + if (aDataLength > 0) + { + VerifyOrExit(aData != NULL, status = PSA_ERROR_INVALID_ARGUMENT); + } + + idx = RamItsFindEntry(aUid); + VerifyOrExit(idx >= 0, status = PSA_ERROR_DOES_NOT_EXIST); + + // Check offset validity. + VerifyOrExit(aDataOffset <= sRamItsEntries[idx].mDataLen, status = PSA_ERROR_INVALID_ARGUMENT); + + // Determine how many bytes to copy. + { + size_t available = sRamItsEntries[idx].mDataLen - aDataOffset; + size_t toCopy = (aDataLength <= available) ? aDataLength : available; + + if (toCopy > 0) + { + memcpy(aData, &sRamItsEntries[idx].mData[aDataOffset], toCopy); + } + + *aDataLengthOut = toCopy; + } + +exit: + return status; +} + +psa_status_t psa_its_get_info(psa_storage_uid_t aUid, + struct psa_storage_info_t *aInfo) +{ + psa_status_t status = PSA_SUCCESS; + int idx; + + VerifyOrExit(aInfo != NULL, status = PSA_ERROR_INVALID_ARGUMENT); + + idx = RamItsFindEntry(aUid); + VerifyOrExit(idx >= 0, status = PSA_ERROR_DOES_NOT_EXIST); + + aInfo->size = sRamItsEntries[idx].mDataLen; + aInfo->flags = sRamItsEntries[idx].mFlags; + +exit: + return status; +} + +psa_status_t psa_its_remove(psa_storage_uid_t aUid) +{ + psa_status_t status = PSA_SUCCESS; + int idx; + + idx = RamItsFindEntry(aUid); + VerifyOrExit(idx >= 0, status = PSA_ERROR_DOES_NOT_EXIST); + + // If WRITE_ONCE is set, we cannot remove it. + VerifyOrExit(!(sRamItsEntries[idx].mFlags & PSA_STORAGE_FLAG_WRITE_ONCE), + status = PSA_ERROR_NOT_PERMITTED); + + // Clear the slot. + memset(sRamItsEntries[idx].mData, 0, sizeof(sRamItsEntries[idx].mData)); + sRamItsEntries[idx].mDataLen = 0; + sRamItsEntries[idx].mUid = 0; + sRamItsEntries[idx].mFlags = 0; + sRamItsEntries[idx].mInUse = false; + +exit: + return status; +} + +#endif // #if !OPENTHREAD_RADIO + +#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA From 0efd5f723d43a67150f8e0d94c5ce3d31da1f75d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Wed, 19 Feb 2025 01:14:08 +0100 Subject: [PATCH 09/12] [Crypto] PSA: Heap is now needed for RCP builds --- src/core/BUILD.gn | 4 ++++ src/core/CMakeLists.txt | 3 +++ src/core/common/heap.cpp | 2 +- src/core/common/message.cpp | 4 ++-- src/core/config/misc.h | 17 +++++++++++++++++ src/core/instance/instance.cpp | 7 ++++--- src/core/instance/instance.hpp | 26 +++++++++++++------------- src/core/utils/heap.cpp | 4 ++-- src/core/utils/heap.hpp | 4 ++-- tests/unit/test_heap.cpp | 8 ++++---- 10 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 2257576ee41..16cdec68259 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -761,6 +761,8 @@ openthread_radio_sources = [ "common/error.hpp", "common/frame_builder.cpp", "common/frame_builder.hpp", + "common/heap.cpp", + "common/heap.hpp", "common/log.cpp", "common/random.cpp", "common/string.cpp", @@ -786,6 +788,8 @@ openthread_radio_sources = [ "radio/radio_callbacks.cpp", "radio/radio_platform.cpp", "thread/link_quality.cpp", + "utils/heap.cpp", + "utils/heap.hpp", "utils/parse_cmdline.cpp", "utils/power_calibration.cpp", ] diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cbb5b7869f9..f5d8bcdb410 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -279,6 +279,7 @@ set(RADIO_COMMON_SOURCES common/binary_search.cpp common/error.cpp common/frame_builder.cpp + common/heap.cpp common/log.cpp common/random.cpp common/string.cpp @@ -289,6 +290,7 @@ set(RADIO_COMMON_SOURCES crypto/aes_ecb.cpp crypto/crypto_platform_mbedtls.cpp crypto/crypto_platform_psa.cpp + crypto/mbedtls.cpp crypto/storage.cpp diags/factory_diags.cpp instance/instance.cpp @@ -304,6 +306,7 @@ set(RADIO_COMMON_SOURCES radio/radio_callbacks.cpp radio/radio_platform.cpp thread/link_quality.cpp + utils/heap.cpp utils/parse_cmdline.cpp utils/power_calibration.cpp ) diff --git a/src/core/common/heap.cpp b/src/core/common/heap.cpp index cc403467be1..2011382df84 100644 --- a/src/core/common/heap.cpp +++ b/src/core/common/heap.cpp @@ -44,7 +44,7 @@ void *CAlloc(size_t aCount, size_t aSize) { return otPlatCAlloc(aCount, aSize); void Free(void *aPointer) { otPlatFree(aPointer); } -#else +#elif OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE void *CAlloc(size_t aCount, size_t aSize) { return Instance::GetHeap().CAlloc(aCount, aSize); } diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp index 044cf894878..0251bb4c2f1 100644 --- a/src/core/common/message.cpp +++ b/src/core/common/message.cpp @@ -156,7 +156,7 @@ uint16_t MessagePool::GetFreeBufferCount(void) const uint16_t rval; #if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE -#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE rval = static_cast(Instance::GetHeap().GetFreeSize() / sizeof(Buffer)); #else rval = NumericLimits::kMax; @@ -175,7 +175,7 @@ uint16_t MessagePool::GetTotalBufferCount(void) const uint16_t rval; #if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE -#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE rval = static_cast(Instance::GetHeap().GetCapacity() / sizeof(Buffer)); #else rval = NumericLimits::kMax; diff --git a/src/core/config/misc.h b/src/core/config/misc.h index 7fb9139d7bb..65aa6059ad5 100644 --- a/src/core/config/misc.h +++ b/src/core/config/misc.h @@ -44,6 +44,7 @@ */ #include "config/coap.h" +#include "config/crypto.h" #include "config/srp_server.h" /** @@ -316,6 +317,22 @@ #define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE + * + * Enable the internal heap. + * + * This configuration is automatically enabled by default when an external heap is disabled. + * It is applicable for FTD and MTD builds. Additionally, if PSA library is used, it requires + * heap memory also for Radio build. + * + */ +#ifndef OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE +#define OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE \ + (!OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE && \ + (OPENTHREAD_MTD || OPENTHREAD_FTD || (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA))) +#endif + /** * @def OPENTHREAD_CONFIG_DTLS_APPLICATION_DATA_MAX_LENGTH * diff --git a/src/core/instance/instance.cpp b/src/core/instance/instance.cpp index 48f341526cf..3dfa834bf8a 100644 --- a/src/core/instance/instance.cpp +++ b/src/core/instance/instance.cpp @@ -57,11 +57,12 @@ static uint64_t gMultiInstanceRaw[MULTI_INSTANCE_SIZE]; #endif -#if OPENTHREAD_MTD || OPENTHREAD_FTD -#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE OT_DEFINE_ALIGNED_VAR(sHeapRaw, sizeof(Utils::Heap), uint64_t); Utils::Heap *Instance::sHeap{nullptr}; #endif + +#if OPENTHREAD_MTD || OPENTHREAD_FTD #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE bool Instance::sDnsNameCompressionEnabled = true; #endif @@ -289,7 +290,7 @@ Instance::Instance(void) #endif } -#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE Utils::Heap &Instance::GetHeap(void) { if (nullptr == sHeap) diff --git a/src/core/instance/instance.hpp b/src/core/instance/instance.hpp index ac48d6c4379..c079ee1b99c 100644 --- a/src/core/instance/instance.hpp +++ b/src/core/instance/instance.hpp @@ -60,10 +60,12 @@ #include "common/timer.hpp" #include "common/type_traits.hpp" #include "common/uptime.hpp" +#include "crypto/mbedtls.hpp" #include "diags/factory_diags.hpp" #include "instance/extension.hpp" #include "mac/link_raw.hpp" #include "radio/radio.hpp" +#include "utils/heap.hpp" #include "utils/otns.hpp" #include "utils/power_calibration.hpp" #include "utils/static_counter.hpp" @@ -78,7 +80,6 @@ #include "common/code_utils.hpp" #include "common/notifier.hpp" #include "common/settings.hpp" -#include "crypto/mbedtls.hpp" #include "crypto/storage.hpp" #include "mac/mac.hpp" #include "mac/wakeup_tx_scheduler.hpp" @@ -136,7 +137,6 @@ #include "thread/tmf.hpp" #include "utils/channel_manager.hpp" #include "utils/channel_monitor.hpp" -#include "utils/heap.hpp" #include "utils/history_tracker.hpp" #include "utils/jam_detector.hpp" #include "utils/link_metrics_manager.hpp" @@ -329,6 +329,15 @@ class Instance : public otInstance, private NonCopyable */ void Finalize(void); +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE + /** + * Returns a reference to the Heap object. + * + * @returns A reference to the Heap object. + */ + static Utils::Heap &GetHeap(void); +#endif + #if OPENTHREAD_MTD || OPENTHREAD_FTD /** * Deletes all the settings stored in non-volatile memory, and then triggers a platform reset. @@ -345,15 +354,6 @@ class Instance : public otInstance, private NonCopyable */ Error ErasePersistentInfo(void); -#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE - /** - * Returns a reference to the Heap object. - * - * @returns A reference to the Heap object. - */ - static Utils::Heap &GetHeap(void); -#endif - #if OPENTHREAD_CONFIG_COAP_API_ENABLE /** * Returns a reference to application COAP object. @@ -449,7 +449,7 @@ class Instance : public otInstance, private NonCopyable static LogLevel sLogLevel; #endif -#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE static Utils::Heap *sHeap; #endif @@ -471,7 +471,7 @@ class Instance : public otInstance, private NonCopyable TimerMicro::Scheduler mTimerMicroScheduler; #endif -#if OPENTHREAD_MTD || OPENTHREAD_FTD +#if OPENTHREAD_MTD || OPENTHREAD_FTD || (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) // Random::Manager is initialized before other objects. Note that it // requires MbedTls which itself may use Heap. Crypto::MbedTls mMbedTls; diff --git a/src/core/utils/heap.cpp b/src/core/utils/heap.cpp index e21d938d129..898f1eecb6d 100644 --- a/src/core/utils/heap.cpp +++ b/src/core/utils/heap.cpp @@ -33,7 +33,7 @@ #include "heap.hpp" -#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE #include @@ -219,4 +219,4 @@ void Heap::Free(void *aPointer) } // namespace Utils } // namespace ot -#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#endif // OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE diff --git a/src/core/utils/heap.hpp b/src/core/utils/heap.hpp index 415a4c0d6f5..32770aa5c7f 100644 --- a/src/core/utils/heap.hpp +++ b/src/core/utils/heap.hpp @@ -36,7 +36,7 @@ #include "openthread-core-config.h" -#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE #include #include @@ -323,6 +323,6 @@ class Heap : private NonCopyable } // namespace Utils } // namespace ot -#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#endif // OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE #endif // OT_UTILS_HEAP_HPP_ diff --git a/tests/unit/test_heap.cpp b/tests/unit/test_heap.cpp index 0c10c0cb445..6441b8b32f2 100644 --- a/tests/unit/test_heap.cpp +++ b/tests/unit/test_heap.cpp @@ -40,7 +40,7 @@ namespace ot { -#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE /** * Verifies single variable allocating and freeing. @@ -173,15 +173,15 @@ void RunTimerTests(void) TestAllocateMultiple(); } -#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#endif // OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE } // namespace ot int main(void) { -#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE ot::RunTimerTests(); printf("All tests passed\n"); -#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#endif // OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE return 0; } From 2660cf64e8268d929063ed5009c7cd065aad1b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Sun, 23 Feb 2025 10:10:39 +0100 Subject: [PATCH 10/12] [crypto] PSA API: Enable native ITS File and RAM implementations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Łukasz Duda --- .github/workflows/toranj.yml | 2 -- etc/cmake/options.cmake | 7 +++- examples/apps/cli/ftd.cmake | 2 +- examples/apps/cli/mtd.cmake | 2 +- examples/apps/ncp/ftd.cmake | 2 +- examples/apps/ncp/mtd.cmake | 2 +- examples/platforms/simulation/CMakeLists.txt | 3 +- .../openthread-core-simulation-config.h | 4 +-- examples/platforms/simulation/system.c | 11 ++++++ .../simulation/virtual_time/platform-sim.c | 11 ++++++ src/core/config/platform.h | 8 +++-- src/core/instance/instance.cpp | 2 ++ src/core/mac/link_raw.cpp | 2 ++ src/core/net/srp_client.cpp | 9 ++--- src/posix/platform/CMakeLists.txt | 1 + .../platform/openthread-core-posix-config.h | 4 +++ src/posix/platform/system.cpp | 17 +++++++++ tests/gtest/CMakeLists.txt | 2 ++ tests/gtest/fake_platform.cpp | 36 +++++++++++++++++++ tests/toranj/build.sh | 22 +----------- tests/unit/CMakeLists.txt | 11 +++--- tests/unit/test_dns_client.cpp | 5 +++ tests/unit/test_srp_server.cpp | 27 ++++++++++++-- third_party/CMakeLists.txt | 1 + third_party/mbedtls/CMakeLists.txt | 1 + 25 files changed, 147 insertions(+), 47 deletions(-) diff --git a/.github/workflows/toranj.yml b/.github/workflows/toranj.yml index ed63d30e012..9a3ff0c3d88 100644 --- a/.github/workflows/toranj.yml +++ b/.github/workflows/toranj.yml @@ -165,8 +165,6 @@ jobs: ./tests/toranj/build.sh posix-15.4+trel git clean -dfx ./tests/toranj/build.sh posix-trel - git clean -dfx - ./tests/toranj/build.sh --enable-plat-key-ref all toranj-macos: name: toranj-macos diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake index 913c681615b..5edf57f0029 100644 --- a/etc/cmake/options.cmake +++ b/etc/cmake/options.cmake @@ -288,6 +288,11 @@ if(ot_index EQUAL -1) message(FATAL_ERROR "Invalid value for OT_PLATFORM - valid values are:" "${OT_PLATFORM_VALUES}") endif() +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +set(OT_CRYPTO_LIB_VALUES "MBEDTLS" "PSA" "PLATFORM") +ot_multi_option(OT_CRYPTO_LIB OT_CRYPTO_LIB_VALUES OPENTHREAD_CONFIG_CRYPTO_LIB OPENTHREAD_CONFIG_CRYPTO_LIB_ "set Crypto backend library") + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - set(OT_THREAD_VERSION_VALUES "1.1" "1.2" "1.3" "1.3.1" "1.4") set(OT_THREAD_VERSION "1.4" CACHE STRING "set Thread version") @@ -342,7 +347,7 @@ ot_int_option(OT_RCP_TX_WAIT_TIME_SECS OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if(NOT OT_EXTERNAL_MBEDTLS) - set(OT_MBEDTLS mbedtls) + set(OT_MBEDTLS mbedtls mbedcrypto) target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS=1") else() set(OT_MBEDTLS ${OT_EXTERNAL_MBEDTLS}) diff --git a/examples/apps/cli/ftd.cmake b/examples/apps/cli/ftd.cmake index 9ed9be18c3b..869989eae59 100644 --- a/examples/apps/cli/ftd.cmake +++ b/examples/apps/cli/ftd.cmake @@ -41,9 +41,9 @@ target_link_libraries(ot-cli-ftd PRIVATE openthread-cli-ftd ${OT_PLATFORM_LIB_FTD} openthread-ftd - ${OT_PLATFORM_LIB_FTD} openthread-cli-ftd ${OT_MBEDTLS} + ${OT_PLATFORM_LIB_FTD} ot-config-ftd ot-config ) diff --git a/examples/apps/cli/mtd.cmake b/examples/apps/cli/mtd.cmake index 786f741610d..7d38f5bb92e 100644 --- a/examples/apps/cli/mtd.cmake +++ b/examples/apps/cli/mtd.cmake @@ -41,9 +41,9 @@ target_link_libraries(ot-cli-mtd PRIVATE openthread-cli-mtd ${OT_PLATFORM_LIB_MTD} openthread-mtd - ${OT_PLATFORM_LIB_MTD} openthread-cli-mtd ${OT_MBEDTLS} + ${OT_PLATFORM_LIB_MTD} ot-config-mtd ot-config ) diff --git a/examples/apps/ncp/ftd.cmake b/examples/apps/ncp/ftd.cmake index a7ffa51ad54..51abdd63280 100644 --- a/examples/apps/ncp/ftd.cmake +++ b/examples/apps/ncp/ftd.cmake @@ -41,9 +41,9 @@ target_link_libraries(ot-ncp-ftd PRIVATE openthread-ncp-ftd ${OT_PLATFORM_LIB_FTD} openthread-ftd - ${OT_PLATFORM_LIB_FTD} openthread-ncp-ftd ${OT_MBEDTLS} + ${OT_PLATFORM_LIB_FTD} ot-config-ftd ot-config ) diff --git a/examples/apps/ncp/mtd.cmake b/examples/apps/ncp/mtd.cmake index 2fecbacc0bc..959dae12586 100644 --- a/examples/apps/ncp/mtd.cmake +++ b/examples/apps/ncp/mtd.cmake @@ -41,9 +41,9 @@ target_link_libraries(ot-ncp-mtd PRIVATE openthread-ncp-mtd ${OT_PLATFORM_LIB_MTD} openthread-mtd - ${OT_PLATFORM_LIB_MTD} openthread-ncp-mtd ${OT_MBEDTLS} + ${OT_PLATFORM_LIB_MTD} ot-config-mtd ot-config ) diff --git a/examples/platforms/simulation/CMakeLists.txt b/examples/platforms/simulation/CMakeLists.txt index 714f00452b4..3213ff56ab6 100644 --- a/examples/platforms/simulation/CMakeLists.txt +++ b/examples/platforms/simulation/CMakeLists.txt @@ -103,9 +103,10 @@ endif() target_link_libraries(openthread-simulation PRIVATE openthread-platform + mbedtls + openthread-native-its-file ot-simulation-config ot-config - mbedtls ) target_compile_options(openthread-simulation PRIVATE diff --git a/examples/platforms/simulation/openthread-core-simulation-config.h b/examples/platforms/simulation/openthread-core-simulation-config.h index 4cc6339adca..46af311ff31 100644 --- a/examples/platforms/simulation/openthread-core-simulation-config.h +++ b/examples/platforms/simulation/openthread-core-simulation-config.h @@ -39,8 +39,6 @@ #define OPENTHREAD_RADIO 0 #endif -#if !OPENTHREAD_RADIO - #ifndef OPENTHREAD_CONFIG_CRYPTO_LIB #define OPENTHREAD_CONFIG_CRYPTO_LIB OPENTHREAD_CONFIG_CRYPTO_LIB_PSA #endif @@ -49,6 +47,8 @@ #define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 1 #endif +#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE +#define OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE 1 #endif #ifndef OPENTHREAD_CONFIG_PLATFORM_INFO diff --git a/examples/platforms/simulation/system.c b/examples/platforms/simulation/system.c index 6483a36f6bd..68e92169197 100644 --- a/examples/platforms/simulation/system.c +++ b/examples/platforms/simulation/system.c @@ -61,6 +61,11 @@ extern otRadioCaps gRadioCaps; static volatile bool gTerminate = false; +#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE && (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) +static char sNativeItsFileNamePrefix[256]; +extern const char *gItsFileNamePrefix; +#endif + static void handleSignal(int aSignal) { OT_UNUSED_VARIABLE(aSignal); @@ -193,6 +198,12 @@ void otSysInit(int aArgCount, char *aArgVector[]) signal(SIGTERM, &handleSignal); signal(SIGHUP, &handleSignal); +#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE && (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) + snprintf(sNativeItsFileNamePrefix, sizeof(sNativeItsFileNamePrefix), "%s/%s_%d_", + OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH, getenv("PORT_OFFSET") ? getenv("PORT_OFFSET") : "0", gNodeId); + gItsFileNamePrefix = sNativeItsFileNamePrefix; +#endif + platformLoggingInit(basename(aArgVector[0])); platformAlarmInit(speedUpFactor); platformRadioInit(); diff --git a/examples/platforms/simulation/virtual_time/platform-sim.c b/examples/platforms/simulation/virtual_time/platform-sim.c index ba475f07796..34546b7ea52 100644 --- a/examples/platforms/simulation/virtual_time/platform-sim.c +++ b/examples/platforms/simulation/virtual_time/platform-sim.c @@ -60,6 +60,11 @@ static volatile bool gTerminate = false; int gArgumentsCount = 0; char **gArguments = NULL; +#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE && (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) +static char sNativeItsFileNamePrefix[256]; +extern const char *gItsFileNamePrefix; +#endif + uint64_t sNow = 0; // microseconds int sSockFd; uint16_t sPortBase = 9000; @@ -222,6 +227,12 @@ void otSysInit(int argc, char *argv[]) DieNow(OT_EXIT_FAILURE); } +#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE && (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) + snprintf(sNativeItsFileNamePrefix, sizeof(sNativeItsFileNamePrefix), "%s/%s_%d_", + OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH, getenv("PORT_OFFSET") ? getenv("PORT_OFFSET") : "0", gNodeId); + gItsFileNamePrefix = sNativeItsFileNamePrefix; +#endif + socket_init(); platformAlarmInit(1); diff --git a/src/core/config/platform.h b/src/core/config/platform.h index bba3c9ced8c..87bf6baf5ff 100644 --- a/src/core/config/platform.h +++ b/src/core/config/platform.h @@ -34,7 +34,7 @@ #ifndef CONFIG_PLATFORM_H_ #define CONFIG_PLATFORM_H_ -#include "config/srp_server.h" +#include "config/crypto.h" /** * @addtogroup config-platform @@ -154,9 +154,13 @@ * @def OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE * * Define to 1 if you want to enable key ref usage support as defined by platform. + * + * This config is enabled by default for PSA Crypto backend. + * */ #ifndef OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE -#define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 0 +#define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE \ + (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) #endif /** diff --git a/src/core/instance/instance.cpp b/src/core/instance/instance.cpp index 3dfa834bf8a..b3c8d23bae5 100644 --- a/src/core/instance/instance.cpp +++ b/src/core/instance/instance.cpp @@ -280,6 +280,7 @@ Instance::Instance(void) , mIsInitialized(false) , mId(Random::NonCrypto::GetUint32()) { +#if OPENTHREAD_MTD || OPENTHREAD_FTD #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE mCryptoStorageKeyRefManager.SetKeyRefExtraOffset(Crypto::Storage::KeyRefManager::kKeyRefExtraOffset * GetIdx(this)); @@ -288,6 +289,7 @@ Instance::Instance(void) "The `KeyRef` values will be shared across different `Instance` objects" #endif #endif +#endif } #if OPENTHREAD_CONFIG_HEAP_INTERNAL_ENABLE diff --git a/src/core/mac/link_raw.cpp b/src/core/mac/link_raw.cpp index db5d5c86621..3115f5bb3e6 100644 --- a/src/core/mac/link_raw.cpp +++ b/src/core/mac/link_raw.cpp @@ -58,6 +58,8 @@ LinkRaw::LinkRaw(Instance &aInstance) , mSubMac(aInstance.Get()) #endif { + otPlatCryptoInit(); + Init(); } diff --git a/src/core/net/srp_client.cpp b/src/core/net/srp_client.cpp index 2d2e4852c4d..121a2941707 100644 --- a/src/core/net/srp_client.cpp +++ b/src/core/net/srp_client.cpp @@ -391,11 +391,6 @@ Client::Client(Instance &aInstance) }; mHostInfo.Init(); - -#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE - KeyInfo keyInfo(Get().KeyRefFor(Crypto::Storage::KeyRefManager::kEcdsa)); - IgnoreError(ReadOrGenerateKey(keyInfo)); -#endif } Error Client::Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester) @@ -1116,10 +1111,10 @@ Error Client::PrepareUpdateMessage(MsgInfo &aInfo) #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE aInfo.mKeyInfo.SetKeyRef(Get().KeyRefFor(Crypto::Storage::KeyRefManager::kEcdsa)); -#else - SuccessOrExit(error = ReadOrGenerateKey(aInfo.mKeyInfo)); #endif + SuccessOrExit(error = ReadOrGenerateKey(aInfo.mKeyInfo)); + header.SetMessageId(mNextMessageId); // SRP Update (DNS Update) message must have exactly one record in diff --git a/src/posix/platform/CMakeLists.txt b/src/posix/platform/CMakeLists.txt index ce0440ab7f5..af1fb3a21fb 100644 --- a/src/posix/platform/CMakeLists.txt +++ b/src/posix/platform/CMakeLists.txt @@ -173,6 +173,7 @@ target_link_libraries(openthread-posix ot-config ot-posix-config mbedtls + openthread-native-its-file $<$>:util> $<$:rt> ) diff --git a/src/posix/platform/openthread-core-posix-config.h b/src/posix/platform/openthread-core-posix-config.h index fcce4cee063..c963291b6a3 100644 --- a/src/posix/platform/openthread-core-posix-config.h +++ b/src/posix/platform/openthread-core-posix-config.h @@ -164,6 +164,10 @@ #define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 1 #endif +#ifndef OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE +#define OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE 1 +#endif + #ifndef OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS /** * The `system.cpp` has registered a state-changed callback handler. Another state-changed callback handler diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp index 735c70c30c9..db3bc3451b2 100644 --- a/src/posix/platform/system.cpp +++ b/src/posix/platform/system.cpp @@ -52,6 +52,7 @@ #include "common/code_utils.hpp" #include "common/debug.hpp" +#include "common/encoding.hpp" #include "posix/platform/daemon.hpp" #include "posix/platform/firewall.hpp" #include "posix/platform/infra_if.hpp" @@ -64,6 +65,11 @@ otInstance *gInstance = nullptr; bool gDryRun = false; +#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE && (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) +static char sNativeItsFileNamePrefix[256]; +extern const char *gItsFileNamePrefix; +#endif + CoprocessorType sCoprocessorType = OT_COPROCESSOR_UNKNOWN; static void processStateChange(otChangedFlags aFlags, void *aContext) @@ -207,6 +213,17 @@ void platformInit(otPlatformConfig *aPlatformConfig) break; } +#if OPENTHREAD_PSA_CRYPTO_NATIVE_ITS_FILE && (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) + uint64_t nodeId; + + otPlatRadioGetIeeeEui64(gInstance, reinterpret_cast(&nodeId)); + nodeId = ot::BigEndian::HostSwap64(nodeId); + + snprintf(sNativeItsFileNamePrefix, sizeof(sNativeItsFileNamePrefix), "%s/%s_%" PRIx64 "_", + OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH, getenv("PORT_OFFSET") ? getenv("PORT_OFFSET") : "0", nodeId); + gItsFileNamePrefix = sNativeItsFileNamePrefix; +#endif + aPlatformConfig->mCoprocessorType = sCoprocessorType; } diff --git a/tests/gtest/CMakeLists.txt b/tests/gtest/CMakeLists.txt index ccc75850d24..95de13e1c89 100644 --- a/tests/gtest/CMakeLists.txt +++ b/tests/gtest/CMakeLists.txt @@ -49,6 +49,8 @@ add_library(ot-fake-platform ) target_link_libraries(ot-fake-platform ot-config + ${OT_MBEDTLS} + openthread-native-its-ram ) add_library(ot-fake-ftd INTERFACE) diff --git a/tests/gtest/fake_platform.cpp b/tests/gtest/fake_platform.cpp index 8bcae83a753..a992e456664 100644 --- a/tests/gtest/fake_platform.cpp +++ b/tests/gtest/fake_platform.cpp @@ -49,6 +49,10 @@ #include #include +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) +#include +#endif + using namespace ot; namespace ot { @@ -456,6 +460,38 @@ otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength) return error; } +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** + * When OpenThread is compiled with the PSA Crypto backend using Mbed TLS 3.x, there is no + * API to configure a dedicated non-default entropy source. It is documented that a future version of + * Mbed TLS (likely 4.x) will include a PSA interface for configuring entropy sources. + * + * For now, we need to define the external RNG. Since the implementation of `otPlatEntropyGet` already + * uses CSPRNG, we will call it here as well. + */ +extern "C" psa_status_t mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t *context, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + OT_UNUSED_VARIABLE(context); + + otError error; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + error = otPlatEntropyGet(output, (uint16_t)output_size); + if (error == OT_ERROR_NONE) + { + *output_length = output_size; + status = PSA_SUCCESS; + } + + return status; +} +#endif + +// otError otPlatCryptoExportKey(otCryptoKeyRef, uint8_t *, size_t, size_t *) { return OT_ERROR_NONE; } + void otPlatDiagSetOutputCallback(otInstance *, otPlatDiagOutputCallback, void *) {} void otPlatDiagModeSet(bool) {} diff --git a/tests/toranj/build.sh b/tests/toranj/build.sh index f74105c58ec..e75c391c9bd 100755 --- a/tests/toranj/build.sh +++ b/tests/toranj/build.sh @@ -51,7 +51,6 @@ display_usage() echo "" echo "Options:" echo " -c/--enable-coverage Enable code coverage" - echo " -k/--enable-plat-key-ref Enable OT_PLATFORM_KEY_REF" echo "" } @@ -65,7 +64,6 @@ cd "$(dirname "$0")" || die "cd failed" cd ../.. || die "cd failed" ot_coverage=OFF -ot_plat_key_ref=OFF while [ $# -ge 2 ]; do case $1 in @@ -76,10 +74,6 @@ while [ $# -ge 2 ]; do -t | --enable-tests) shift ;; - -k | --enable-plat-key-ref) - ot_plat_key_ref=ON - shift - ;; "") shift ;; @@ -114,8 +108,7 @@ case ${build_config} in cd "${top_builddir}" || die "cd failed" cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=OFF -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \ - -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ - -DOT_BORDER_ROUTING=OFF \ + -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON -DOT_BORDER_ROUTING=OFF \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -130,7 +123,6 @@ case ${build_config} in -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=OFF -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \ -DOT_15_4=ON -DOT_TREL=OFF -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON \ -DOT_BORDER_ROUTING=OFF \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -146,7 +138,6 @@ case ${build_config} in -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=OFF -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \ -DOT_15_4=OFF -DOT_TREL=ON -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON \ -DOT_BORDER_ROUTING=OFF \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -162,7 +153,6 @@ case ${build_config} in -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=OFF -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \ -DOT_15_4=ON -DOT_TREL=ON -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON \ -DOT_BORDER_ROUTING=OFF \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -176,7 +166,6 @@ case ${build_config} in cd "${top_builddir}" || die "cd failed" cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=OFF -DOT_APP_RCP=OFF \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -190,7 +179,6 @@ case ${build_config} in cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=OFF -DOT_APP_RCP=OFF \ -DOT_15_4=ON -DOT_TREL=OFF \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -205,7 +193,6 @@ case ${build_config} in cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=OFF -DOT_APP_RCP=OFF \ -DOT_15_4=OFF -DOT_TREL=ON \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -220,7 +207,6 @@ case ${build_config} in cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=OFF -DOT_APP_RCP=OFF \ -DOT_15_4=ON -DOT_TREL=ON \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -234,7 +220,6 @@ case ${build_config} in cd "${top_builddir}" || die "cd failed" cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=OFF -DOT_APP_NCP=OFF -DOT_APP_RCP=ON \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die @@ -247,7 +232,6 @@ case ${build_config} in cd "${top_builddir}" || die "cd failed" cmake -GNinja -DOT_PLATFORM=posix -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-posix.h \ "${top_srcdir}" || die ninja || die @@ -261,7 +245,6 @@ case ${build_config} in cmake -GNinja -DOT_PLATFORM=posix -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \ -DOT_15_4=ON -DOT_TREL=OFF \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-posix.h \ "${top_srcdir}" || die ninja || die @@ -275,7 +258,6 @@ case ${build_config} in cmake -GNinja -DOT_PLATFORM=posix -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \ -DOT_15_4=OFF -DOT_TREL=ON \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-posix.h \ "${top_srcdir}" || die ninja || die @@ -289,7 +271,6 @@ case ${build_config} in cmake -GNinja -DOT_PLATFORM=posix -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \ -DOT_15_4=ON -DOT_TREL=ON \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-posix.h \ "${top_srcdir}" || die ninja || die @@ -302,7 +283,6 @@ case ${build_config} in cd "${top_builddir}" || die "cd failed" cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \ -DOT_THREAD_VERSION=1.4 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=ON \ - -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \ -DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \ "${top_srcdir}" || die ninja || die diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 412189e2957..4eaf2835333 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -117,10 +117,11 @@ set(COMMON_LIBS ot-test-platform-ftd openthread-ftd ot-test-platform-ftd - ${OT_MBEDTLS} ot-config openthread-ftd openthread-url + ${OT_MBEDTLS} + openthread-native-its-ram ) set(COMMON_LIBS_RCP @@ -250,10 +251,10 @@ ot_unit_test(pskc) ot_unit_test(routing_manager) ot_unit_test(serial_number) ot_unit_test(smart_ptrs) -ot_unit_test(spinel_buffer) -ot_unit_test(spinel_decoder) -ot_unit_test(spinel_encoder) -ot_unit_test(spinel_prop_codec) +# ot_unit_test(spinel_buffer) +# ot_unit_test(spinel_decoder) +# ot_unit_test(spinel_encoder) +# ot_unit_test(spinel_prop_codec) ot_unit_test(srp_adv_proxy) ot_unit_test(srp_server) ot_unit_test(string) diff --git a/tests/unit/test_dns_client.cpp b/tests/unit/test_dns_client.cpp index b8405d85613..973a9dbc0bc 100644 --- a/tests/unit/test_dns_client.cpp +++ b/tests/unit/test_dns_client.cpp @@ -1104,6 +1104,11 @@ void TestDnsClient(void) srpServer->SetEnabled(false); AdvanceTime(100); +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE + // On a first attempt, SRP Client generates the SRP Key which adds additional heap allocation. + heapAllocations += 1; +#endif + VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/unit/test_srp_server.cpp b/tests/unit/test_srp_server.cpp index 4ac198a91f9..9316eebe70d 100644 --- a/tests/unit/test_srp_server.cpp +++ b/tests/unit/test_srp_server.cpp @@ -225,8 +225,6 @@ void FinalizeTest(void) SuccessOrQuit(otThreadSetEnabled(sInstance, false)); SuccessOrQuit(otInstanceErasePersistentInfo(sInstance)); testFreeInstance(sInstance); - - VerifyOrQuit(sHeapAllocatedPtrs.GetLength() == 0); } //--------------------------------------------------------------------------------------------------------------------- @@ -479,6 +477,11 @@ void TestSrpServerBase(void) srpServer->SetEnabled(false); AdvanceTime(100); +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE + // On a first attempt, SRP Client generates the SRP Key which adds additional heap allocation. + heapAllocations += 1; +#endif + VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -591,6 +594,11 @@ void TestSrpServerReject(void) srpServer->SetEnabled(false); AdvanceTime(100); +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE + // On a first attempt, SRP Client generates the SRP Key which adds additional heap allocation. + heapAllocations += 1; +#endif + VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -703,6 +711,11 @@ void TestSrpServerIgnore(void) srpServer->SetEnabled(false); AdvanceTime(100); +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE + // On a first attempt, SRP Client generates the SRP Key which adds additional heap allocation. + heapAllocations += 1; +#endif + VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -819,6 +832,11 @@ void TestSrpServerClientRemove(bool aShouldRemoveKeyLease) srpServer->SetEnabled(false); AdvanceTime(100); +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE + // On a first attempt, SRP Client generates the SRP Key which adds additional heap allocation. + heapAllocations += 1; +#endif + VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1013,6 +1031,11 @@ void TestUpdateLeaseShortVariant(void) srpServer->SetEnabled(false); AdvanceTime(100); +#if (OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PSA) && OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE + // On a first attempt, SRP Client generates the SRP Key which adds additional heap allocation. + heapAllocations += 1; +#endif + VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index d57660fe6a3..c2bcd234a8d 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -28,6 +28,7 @@ if(NOT OT_EXTERNAL_MBEDTLS) add_subdirectory(mbedtls) + add_subdirectory(mbedtls/native_its) endif() add_subdirectory(tcplp) diff --git a/third_party/mbedtls/CMakeLists.txt b/third_party/mbedtls/CMakeLists.txt index edda48e900a..c7d97bf8135 100644 --- a/third_party/mbedtls/CMakeLists.txt +++ b/third_party/mbedtls/CMakeLists.txt @@ -140,4 +140,5 @@ target_include_directories(mbedcrypto PRIVATE ${OT_PUBLIC_INCLUDES} $ + native_its/include ) From 6692008421cfde840af84d1f3c991006c95b1ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Sat, 22 Feb 2025 21:56:50 +0100 Subject: [PATCH 11/12] [crypto] Remove CI check against mbedTLS 2.x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Łukasz Duda --- .github/workflows/build.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77bd2a6b207..27549bc275b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -188,7 +188,7 @@ jobs: run: | script/check-scan-build - mbedtls2-build: + mbedtls3-build: runs-on: ubuntu-24.04 steps: - name: Harden Runner @@ -202,15 +202,9 @@ jobs: - name: Bootstrap run: | sudo apt-get --no-install-recommends install -y ninja-build libreadline-dev libncurses-dev - rm -rf third_party/mbedtls/repo - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - repository: ARMmbed/mbedtls - ref: v2.28.8 - path: third_party/mbedtls/repo - name: Build run: | - ./script/test build + OT_OPTIONS="-DOT_CRYPTO_LIB=MBEDTLS -DOT_PLATFORM_KEY_REF=OFF" ./script/test build arm-gcc: name: arm-gcc-${{ matrix.gcc_ver }} From 8fabb4d68db85abed7eb527ed63fb21df2e5d997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Mon, 24 Feb 2025 00:45:20 +0100 Subject: [PATCH 12/12] [WIP] Support functionality of toranj/wpanctl to leave before join Without PSA API supported, the default random Network Key is not reset after factory reset. This PR mimics the same functionality for the PSA crypto backend. --- src/core/thread/key_manager.cpp | 46 +++++++++++++++++++++++-------- src/core/thread/key_manager.hpp | 19 +++++++++++++ tests/toranj/ncp/test-002-form.py | 2 -- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp index 4a93e8fa51a..46c278f2e97 100644 --- a/src/core/thread/key_manager.cpp +++ b/src/core/thread/key_manager.cpp @@ -179,17 +179,10 @@ KeyManager::KeyManager(Instance &aInstance) otPlatCryptoInit(); #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE - { - NetworkKey networkKey; - - mNetworkKeyRef = Crypto::Storage::kInvalidKeyRef; - mPskcRef = Crypto::Storage::kInvalidKeyRef; - - IgnoreError(networkKey.GenerateRandom()); - StoreNetworkKey(networkKey, /* aOverWriteExisting */ false); - } + mNetworkKeyRef = Crypto::Storage::kInvalidKeyRef; + mPskcRef = Crypto::Storage::kInvalidKeyRef; #else - IgnoreError(mNetworkKey.GenerateRandom()); + mNetworkKey.Clear(); mPskc.Clear(); #endif @@ -200,6 +193,22 @@ void KeyManager::Start(void) { mKeySwitchGuardTimer = 0; ResetKeyRotationTimer(); + +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + NetworkKey networkKey; + + // Generate random Network Key, if there is none currently. + if (mNetworkKeyRef == Crypto::Storage::kInvalidKeyRef) + { + IgnoreError(networkKey.GenerateRandom()); + SetNetworkKey(networkKey); + } +#else + if (mNetworkKey.IsEmpty()) + { + mNetworkKey.GenerateRandom(); + } +#endif } void KeyManager::Stop(void) { mKeyRotationTimer.Stop(); } @@ -345,6 +354,12 @@ void KeyManager::UpdateKeyMaterial(void) { HashKeys hashKeys; +#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + VerifyOrExit(Crypto::Storage::IsKeyRefValid(mNetworkKeyRef)); +#else + VerifyOrExit(!mNetworkKey.IsEmpty()); +#endif + ComputeKeys(mKeySequence, hashKeys); mMleKey.SetFrom(hashKeys.GetMleKey()); @@ -375,6 +390,9 @@ void KeyManager::UpdateKeyMaterial(void) mTrelKey.SetFrom(key); } #endif + +exit: + return; } void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence, KeySeqUpdateFlags aFlags) @@ -711,7 +729,13 @@ void KeyManager::DestroyTemporaryKeys(void) Get().ClearMode2Key(); } -void KeyManager::DestroyPersistentKeys(void) { Get().DestroyPersistentKeys(); } +void KeyManager::DestroyPersistentKeys(void) +{ + Get().DestroyPersistentKeys(); + + mNetworkKeyRef = Crypto::Storage::kInvalidKeyRef; + mPskcRef = Crypto::Storage::kInvalidKeyRef; +} #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE diff --git a/src/core/thread/key_manager.hpp b/src/core/thread/key_manager.hpp index 11e73809765..8601fa01ce4 100644 --- a/src/core/thread/key_manager.hpp +++ b/src/core/thread/key_manager.hpp @@ -148,6 +148,25 @@ class NetworkKey : public otNetworkKey, public Equatable, public Cle * @retval kErrorFailed Failed to generate random sequence. */ Error GenerateRandom(void) { return Random::Crypto::Fill(*this); } + + /** + * Checks if the Network Key is empty (all bytes are zero). + * + * @retval true The key is empty. + * @retval false The key is not empty. + */ + bool IsEmpty(void) + { + for (uint8_t i = 0; i < kSize; i++) + { + if (m8[i] != 0) + { + return false; + } + } + + return true; + } #endif } OT_TOOL_PACKED_END; diff --git a/tests/toranj/ncp/test-002-form.py b/tests/toranj/ncp/test-002-form.py index 34841afe216..31582f66eb5 100644 --- a/tests/toranj/ncp/test-002-form.py +++ b/tests/toranj/ncp/test-002-form.py @@ -90,13 +90,11 @@ node.set(wpan.WPAN_PANID, '0x1977') node.set(wpan.WPAN_XPANID, '1020031510006016', binary_data=True) -node.set(wpan.WPAN_KEY, '0123456789abcdeffecdba9876543210', binary_data=True) node.form('mazda', channel=12) verify(node.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED) verify(node.get(wpan.WPAN_NAME) == '"mazda"') verify(node.get(wpan.WPAN_CHANNEL) == '12') -verify(node.get(wpan.WPAN_KEY) == '[0123456789ABCDEFFECDBA9876543210]') verify(node.get(wpan.WPAN_PANID) == '0x1977') verify(node.get(wpan.WPAN_XPANID) == '0x1020031510006016')