From 35f51e2b174269864e7e4ce3c3acf72c3bbf7027 Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Sat, 10 Dec 2022 07:05:06 +0100 Subject: [PATCH] [crypto] move Pskc generation to platform API (#8468) --- Android.mk | 1 - include/openthread/instance.h | 2 +- include/openthread/platform/crypto.h | 26 ++++++ src/core/BUILD.gn | 2 - src/core/CMakeLists.txt | 1 - src/core/Makefile.am | 2 - src/core/crypto/crypto_platform.cpp | 81 ++++++++++++++++++ src/core/crypto/pbkdf2_cmac.cpp | 121 --------------------------- src/core/crypto/pbkdf2_cmac.hpp | 84 ------------------- src/core/meshcop/meshcop.cpp | 7 +- 10 files changed, 111 insertions(+), 216 deletions(-) delete mode 100644 src/core/crypto/pbkdf2_cmac.cpp delete mode 100644 src/core/crypto/pbkdf2_cmac.hpp diff --git a/Android.mk b/Android.mk index ab9697c77..3adbc442e 100644 --- a/Android.mk +++ b/Android.mk @@ -257,7 +257,6 @@ LOCAL_SRC_FILES := \ src/core/crypto/hkdf_sha256.cpp \ src/core/crypto/hmac_sha256.cpp \ src/core/crypto/mbedtls.cpp \ - src/core/crypto/pbkdf2_cmac.cpp \ src/core/crypto/sha256.cpp \ src/core/crypto/storage.cpp \ src/core/diags/factory_diags.cpp \ diff --git a/include/openthread/instance.h b/include/openthread/instance.h index eb4f6e661..c42e74d31 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (266) +#define OPENTHREAD_API_VERSION (267) /** * @addtogroup api-instance diff --git a/include/openthread/platform/crypto.h b/include/openthread/platform/crypto.h index ee1e67933..9d9981990 100644 --- a/include/openthread/platform/crypto.h +++ b/include/openthread/platform/crypto.h @@ -219,6 +219,12 @@ struct otPlatCryptoEcdsaSignature typedef struct otPlatCryptoEcdsaSignature otPlatCryptoEcdsaSignature; +/** + * Max PBKDF2 SALT length: salt prefix (6) + extended panid (8) + network name (16) + * + */ +#define OT_CRYPTO_PBDKF2_MAX_SALT_SIZE 30 + /** * Initialize the Crypto module. * @@ -644,6 +650,26 @@ otError otPlatCryptoEcdsaVerify(const otPlatCryptoEcdsaPublicKey *aPublicKey, const otPlatCryptoSha256Hash *aHash, const otPlatCryptoEcdsaSignature *aSignature); +/** + * Perform PKCS#5 PBKDF2 using CMAC (AES-CMAC-PRF-128). + * + * @param[in] aPassword Password to use when generating key. + * @param[in] aPasswordLen Length of password. + * @param[in] aSalt Salt to use when generating key. + * @param[in] aSaltLen Length of salt. + * @param[in] aIterationCounter Iteration count. + * @param[in] aKeyLen Length of generated key in bytes. + * @param[out] aKey A pointer to the generated key. + * + */ +void otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword, + uint16_t aPasswordLen, + const uint8_t *aSalt, + uint16_t aSaltLen, + uint32_t aIterationCounter, + uint16_t aKeyLen, + uint8_t *aKey); + /** * @} * diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 7f431bc9e..4e29200fc 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -469,8 +469,6 @@ openthread_core_files = [ "crypto/hmac_sha256.hpp", "crypto/mbedtls.cpp", "crypto/mbedtls.hpp", - "crypto/pbkdf2_cmac.cpp", - "crypto/pbkdf2_cmac.hpp", "crypto/sha256.cpp", "crypto/sha256.hpp", "crypto/storage.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2cb0d4b79..e3e00aa84 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -124,7 +124,6 @@ set(COMMON_SOURCES crypto/hkdf_sha256.cpp crypto/hmac_sha256.cpp crypto/mbedtls.cpp - crypto/pbkdf2_cmac.cpp crypto/sha256.cpp crypto/storage.cpp diags/factory_diags.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 7fb841e36..4e487afad 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -214,7 +214,6 @@ SOURCES_COMMON = \ crypto/hkdf_sha256.cpp \ crypto/hmac_sha256.cpp \ crypto/mbedtls.cpp \ - crypto/pbkdf2_cmac.cpp \ crypto/sha256.cpp \ crypto/storage.cpp \ diags/factory_diags.cpp \ @@ -529,7 +528,6 @@ HEADERS_COMMON = \ crypto/hkdf_sha256.hpp \ crypto/hmac_sha256.hpp \ crypto/mbedtls.hpp \ - crypto/pbkdf2_cmac.hpp \ crypto/sha256.hpp \ crypto/storage.hpp \ diags/factory_diags.hpp \ diff --git a/src/core/crypto/crypto_platform.cpp b/src/core/crypto/crypto_platform.cpp index cba4de61c..625f44157 100644 --- a/src/core/crypto/crypto_platform.cpp +++ b/src/core/crypto/crypto_platform.cpp @@ -32,7 +32,10 @@ #include "openthread-core-config.h" +#include + #include +#include #include #include #include @@ -660,3 +663,81 @@ exit: #endif // #if !OPENTHREAD_RADIO #endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS + +//--------------------------------------------------------------------------------------------------------------------- +// APIs to be used in "hybrid" mode by every OPENTHREAD_CONFIG_CRYPTO_LIB variant until full PSA support is ready + +#if OPENTHREAD_FTD + +OT_TOOL_WEAK void otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword, + uint16_t aPasswordLen, + const uint8_t *aSalt, + uint16_t aSaltLen, + uint32_t aIterationCounter, + uint16_t aKeyLen, + uint8_t *aKey) +{ + const size_t kBlockSize = MBEDTLS_CIPHER_BLKSIZE_MAX; + uint8_t prfInput[OT_CRYPTO_PBDKF2_MAX_SALT_SIZE + 4]; // Salt || INT(), for U1 calculation + long prfOne[kBlockSize / sizeof(long)]; + long prfTwo[kBlockSize / sizeof(long)]; + long keyBlock[kBlockSize / sizeof(long)]; + uint32_t blockCounter = 0; + uint8_t *key = aKey; + uint16_t keyLen = aKeyLen; + uint16_t useLen = 0; + + OT_ASSERT(aSaltLen <= sizeof(prfInput)); + memcpy(prfInput, aSalt, aSaltLen); + OT_ASSERT(aIterationCounter % 2 == 0); + aIterationCounter /= 2; + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + // limit iterations to avoid OSS-Fuzz timeouts + aIterationCounter = 2; +#endif + + while (keyLen) + { + ++blockCounter; + prfInput[aSaltLen + 0] = static_cast(blockCounter >> 24); + prfInput[aSaltLen + 1] = static_cast(blockCounter >> 16); + prfInput[aSaltLen + 2] = static_cast(blockCounter >> 8); + prfInput[aSaltLen + 3] = static_cast(blockCounter); + + // Calculate U_1 + mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, prfInput, aSaltLen + 4, + reinterpret_cast(keyBlock)); + + // Calculate U_2 + mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast(keyBlock), kBlockSize, + reinterpret_cast(prfOne)); + + for (uint32_t j = 0; j < kBlockSize / sizeof(long); ++j) + { + keyBlock[j] ^= prfOne[j]; + } + + for (uint32_t i = 1; i < aIterationCounter; ++i) + { + // Calculate U_{2 * i - 1} + mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast(prfOne), kBlockSize, + reinterpret_cast(prfTwo)); + // Calculate U_{2 * i} + mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast(prfTwo), kBlockSize, + reinterpret_cast(prfOne)); + + for (uint32_t j = 0; j < kBlockSize / sizeof(long); ++j) + { + keyBlock[j] ^= prfOne[j] ^ prfTwo[j]; + } + } + + useLen = (keyLen < kBlockSize) ? keyLen : kBlockSize; + memcpy(key, keyBlock, useLen); + key += useLen; + keyLen -= useLen; + } +} + +#endif // #if OPENTHREAD_FTD diff --git a/src/core/crypto/pbkdf2_cmac.cpp b/src/core/crypto/pbkdf2_cmac.cpp deleted file mode 100644 index 57cc1b75b..000000000 --- a/src/core/crypto/pbkdf2_cmac.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2016, 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 PBKDF2 using AES-CMAC-PRF-128 - */ - -#include "pbkdf2_cmac.hpp" - -#include -#include - -#include "common/debug.hpp" - -namespace ot { -namespace Crypto { -namespace Pbkdf2 { - -#if OPENTHREAD_FTD - -void GenerateKey(const uint8_t *aPassword, - uint16_t aPasswordLen, - const uint8_t *aSalt, - uint16_t aSaltLen, - uint32_t aIterationCounter, - uint16_t aKeyLen, - uint8_t *aKey) -{ - const size_t kBlockSize = MBEDTLS_CIPHER_BLKSIZE_MAX; - uint8_t prfInput[kMaxSaltLength + 4]; // Salt || INT(), for U1 calculation - long prfOne[kBlockSize / sizeof(long)]; - long prfTwo[kBlockSize / sizeof(long)]; - long keyBlock[kBlockSize / sizeof(long)]; - uint32_t blockCounter = 0; - uint8_t *key = aKey; - uint16_t keyLen = aKeyLen; - uint16_t useLen = 0; - - memcpy(prfInput, aSalt, aSaltLen); - OT_ASSERT(aIterationCounter % 2 == 0); - aIterationCounter /= 2; - -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - // limit iterations to avoid OSS-Fuzz timeouts - aIterationCounter = 2; -#endif - - while (keyLen) - { - ++blockCounter; - prfInput[aSaltLen + 0] = static_cast(blockCounter >> 24); - prfInput[aSaltLen + 1] = static_cast(blockCounter >> 16); - prfInput[aSaltLen + 2] = static_cast(blockCounter >> 8); - prfInput[aSaltLen + 3] = static_cast(blockCounter); - - // Calculate U_1 - mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, prfInput, aSaltLen + 4, - reinterpret_cast(keyBlock)); - - // Calculate U_2 - mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast(keyBlock), kBlockSize, - reinterpret_cast(prfOne)); - - for (uint32_t j = 0; j < kBlockSize / sizeof(long); ++j) - { - keyBlock[j] ^= prfOne[j]; - } - - for (uint32_t i = 1; i < aIterationCounter; ++i) - { - // Calculate U_{2 * i - 1} - mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast(prfOne), kBlockSize, - reinterpret_cast(prfTwo)); - // Calculate U_{2 * i} - mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast(prfTwo), kBlockSize, - reinterpret_cast(prfOne)); - - for (uint32_t j = 0; j < kBlockSize / sizeof(long); ++j) - { - keyBlock[j] ^= prfOne[j] ^ prfTwo[j]; - } - } - - useLen = (keyLen < kBlockSize) ? keyLen : kBlockSize; - memcpy(key, keyBlock, useLen); - key += useLen; - keyLen -= useLen; - } -} - -#endif // OPENTHREAD_FTD - -} // namespace Pbkdf2 -} // namespace Crypto -} // namespace ot diff --git a/src/core/crypto/pbkdf2_cmac.hpp b/src/core/crypto/pbkdf2_cmac.hpp deleted file mode 100644 index 0615f6d82..000000000 --- a/src/core/crypto/pbkdf2_cmac.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2016, The OpenThread Authors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief - * This file includes definitions for performing Password-Based Key Derivation Function 2 (PBKDF2) using CMAC. - */ - -#ifndef PBKDF2_CMAC_HPP_ -#define PBKDF2_CMAC_HPP_ - -#include "openthread-core-config.h" - -#include - -namespace ot { -namespace Crypto { -namespace Pbkdf2 { - -/** - * @addtogroup core-security - * - * @{ - * - */ - -constexpr uint16_t kMaxSaltLength = 30; ///< Max SALT length: salt prefix (6) + extended panid (8) + network name (16) - -/** - * This function performs PKCS#5 PBKDF2 using CMAC (AES-CMAC-PRF-128). - * - * @param[in] aPassword Password to use when generating key. - * @param[in] aPasswordLen Length of password. - * @param[in] aSalt Salt to use when generating key. - * @param[in] aSaltLen Length of salt. - * @param[in] aIterationCounter Iteration count. - * @param[in] aKeyLen Length of generated key in bytes. - * @param[out] aKey A pointer to the generated key. - * - */ -void GenerateKey(const uint8_t *aPassword, - uint16_t aPasswordLen, - const uint8_t *aSalt, - uint16_t aSaltLen, - uint32_t aIterationCounter, - uint16_t aKeyLen, - uint8_t *aKey); - -/** - * @} - * - */ - -} // namespace Pbkdf2 -} // namespace Crypto -} // namespace ot - -#endif // PBKDF2_CMAC_HPP_ diff --git a/src/core/meshcop/meshcop.cpp b/src/core/meshcop/meshcop.cpp index 793adc858..6fb17b020 100644 --- a/src/core/meshcop/meshcop.cpp +++ b/src/core/meshcop/meshcop.cpp @@ -37,7 +37,6 @@ #include "common/debug.hpp" #include "common/locator_getters.hpp" #include "common/string.hpp" -#include "crypto/pbkdf2_cmac.hpp" #include "crypto/sha256.hpp" #include "mac/mac_types.hpp" #include "thread/thread_netif.hpp" @@ -324,7 +323,7 @@ Error GeneratePskc(const char *aPassPhrase, { Error error = kErrorNone; const char saltPrefix[] = "Thread"; - uint8_t salt[Crypto::Pbkdf2::kMaxSaltLength]; + uint8_t salt[OT_CRYPTO_PBDKF2_MAX_SALT_SIZE]; uint16_t saltLen = 0; uint16_t passphraseLen; uint8_t networkNameLen; @@ -349,8 +348,8 @@ Error GeneratePskc(const char *aPassPhrase, memcpy(salt + saltLen, aNetworkName.GetAsCString(), networkNameLen); saltLen += networkNameLen; - Crypto::Pbkdf2::GenerateKey(reinterpret_cast(aPassPhrase), passphraseLen, salt, saltLen, 16384, - OT_PSKC_MAX_SIZE, aPskc.m8); + otPlatCryptoPbkdf2GenerateKey(reinterpret_cast(aPassPhrase), passphraseLen, salt, saltLen, 16384, + OT_PSKC_MAX_SIZE, aPskc.m8); exit: return error;