mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 17:37:46 +00:00
[crypto] move Pskc generation to platform API (#8468)
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -32,7 +32,10 @@
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/cmac.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/ecdsa.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
@@ -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<uint8_t>(blockCounter >> 24);
|
||||
prfInput[aSaltLen + 1] = static_cast<uint8_t>(blockCounter >> 16);
|
||||
prfInput[aSaltLen + 2] = static_cast<uint8_t>(blockCounter >> 8);
|
||||
prfInput[aSaltLen + 3] = static_cast<uint8_t>(blockCounter);
|
||||
|
||||
// Calculate U_1
|
||||
mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, prfInput, aSaltLen + 4,
|
||||
reinterpret_cast<uint8_t *>(keyBlock));
|
||||
|
||||
// Calculate U_2
|
||||
mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast<const uint8_t *>(keyBlock), kBlockSize,
|
||||
reinterpret_cast<uint8_t *>(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<const uint8_t *>(prfOne), kBlockSize,
|
||||
reinterpret_cast<uint8_t *>(prfTwo));
|
||||
// Calculate U_{2 * i}
|
||||
mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast<const uint8_t *>(prfTwo), kBlockSize,
|
||||
reinterpret_cast<uint8_t *>(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
|
||||
|
||||
@@ -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 <mbedtls/cmac.h>
|
||||
#include <string.h>
|
||||
|
||||
#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<uint8_t>(blockCounter >> 24);
|
||||
prfInput[aSaltLen + 1] = static_cast<uint8_t>(blockCounter >> 16);
|
||||
prfInput[aSaltLen + 2] = static_cast<uint8_t>(blockCounter >> 8);
|
||||
prfInput[aSaltLen + 3] = static_cast<uint8_t>(blockCounter);
|
||||
|
||||
// Calculate U_1
|
||||
mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, prfInput, aSaltLen + 4,
|
||||
reinterpret_cast<uint8_t *>(keyBlock));
|
||||
|
||||
// Calculate U_2
|
||||
mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast<const uint8_t *>(keyBlock), kBlockSize,
|
||||
reinterpret_cast<uint8_t *>(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<const uint8_t *>(prfOne), kBlockSize,
|
||||
reinterpret_cast<uint8_t *>(prfTwo));
|
||||
// Calculate U_{2 * i}
|
||||
mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, reinterpret_cast<const uint8_t *>(prfTwo), kBlockSize,
|
||||
reinterpret_cast<uint8_t *>(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
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
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_
|
||||
@@ -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<const uint8_t *>(aPassPhrase), passphraseLen, salt, saltLen, 16384,
|
||||
OT_PSKC_MAX_SIZE, aPskc.m8);
|
||||
otPlatCryptoPbkdf2GenerateKey(reinterpret_cast<const uint8_t *>(aPassPhrase), passphraseLen, salt, saltLen, 16384,
|
||||
OT_PSKC_MAX_SIZE, aPskc.m8);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
Reference in New Issue
Block a user