From f47329b6bb9367985727d0b16944f012844d43cf Mon Sep 17 00:00:00 2001 From: Maciej Baczmanski Date: Mon, 15 Apr 2024 12:50:00 +0200 Subject: [PATCH] [nrf noup] net: openthread: fix `otPlatCryptoPbkdf2GenerateKey` implementation OpenThread requires `otPlatCryptoPbkdf2GenerateKey` to be implemented by platform if PSA Crypto API is used. For ncs v2.6.0 PSA Crypto API doesn't yet fully support PBKDF2 generation. Because of that, calling `otPlatCryptoPbkdf2GenerateKey` results with `OT_ERROR_NOT_CAPABLE` error. This commit provides a patch that allows a fallback to legacy MbedTLS implementation that follows the one provided by OpenThread. Signed-off-by: Maciej Baczmanski --- modules/openthread/platform/crypto_psa.c | 90 ++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/modules/openthread/platform/crypto_psa.c b/modules/openthread/platform/crypto_psa.c index c818c5695a3..73b7bb24fdf 100644 --- a/modules/openthread/platform/crypto_psa.c +++ b/modules/openthread/platform/crypto_psa.c @@ -19,6 +19,13 @@ #include #endif +#if defined(CONFIG_OPENTHREAD_FTD) && defined(CONFIG_PSA_WANT_ALG_CMAC) && \ + !defined(CONFIG_BUILD_WITH_TFM) +#include +#include +#include +#endif + static otError psaToOtError(psa_status_t aStatus) { switch (aStatus) { @@ -604,3 +611,86 @@ otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef) } #endif /* #if CONFIG_OPENTHREAD_ECDSA */ + +#if defined(CONFIG_OPENTHREAD_FTD) && defined(CONFIG_PSA_WANT_ALG_CMAC) && \ + !defined(CONFIG_BUILD_WITH_TFM) + +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) +{ + /* + * This is a fallback for legacy MbedTLS implementation for PBKDF2 generation, + * as PSA support for these operations is not yet available. + * Openthread requires platform to implement PBKDF2 generation if PSA Crypto API is used. + */ + const size_t block_size = MBEDTLS_CMAC_MAX_BLOCK_SIZE; + uint8_t prf_input[OT_CRYPTO_PBDKF2_MAX_SALT_SIZE + sizeof(uint32_t)]; + uint32_t prf_one[block_size / sizeof(uint32_t)]; + uint32_t prf_two[block_size / sizeof(uint32_t)]; + uint32_t key_block[block_size / sizeof(uint32_t)]; + uint32_t block_counter = 0; + uint8_t *key = aKey; + uint16_t key_len = aKeyLen; + uint16_t use_len = 0; + int ret; + + __ASSERT_NO_MSG(aSaltLen <= sizeof(prf_input)); + memcpy(prf_input, aSalt, aSaltLen); + __ASSERT_NO_MSG(aIterationCounter % 2 == 0); + aIterationCounter /= 2; + + while (key_len) { + block_counter++; + sys_put_be32(block_counter, &prf_input[aSaltLen]); + + /* Calculate U_1 */ + ret = mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, (const uint8_t *)prf_input, + aSaltLen + sizeof(uint32_t), (uint8_t *)key_block); + if (ret != 0) { + return OT_ERROR_FAILED; + } + + /* Calculate U_2 */ + ret = mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, (const uint8_t *)key_block, + block_size, (uint8_t *)prf_one); + if (ret != 0) { + return OT_ERROR_FAILED; + } + + for (uint32_t j = 0; j < block_size / sizeof(uint32_t); j++) { + key_block[j] ^= prf_one[j]; + } + + for (uint32_t i = 1; i < aIterationCounter; i++) { + /* Calculate U_{2 * i - 1} */ + ret = mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, + (const uint8_t *)prf_one, + block_size, (uint8_t *)prf_two); + if (ret != 0) { + return OT_ERROR_FAILED; + } + + /* Calculate U_{2 * i} */ + ret = mbedtls_aes_cmac_prf_128(aPassword, aPasswordLen, + (const uint8_t *)prf_two, + block_size, (uint8_t *)prf_one); + if (ret != 0) { + return OT_ERROR_FAILED; + } + + for (uint32_t j = 0; j < block_size / sizeof(uint32_t); j++) { + key_block[j] ^= prf_one[j] ^ prf_two[j]; + } + } + + use_len = MIN(key_len, (uint16_t)block_size); + memcpy(key, key_block, use_len); + key += use_len; + key_len -= use_len; + } + + return OT_ERROR_NONE; +} + +#endif /* #if CONFIG_OPENTHREAD_FTD && CONFIG_PSA_WANT_ALG_CMAC && !CONFIG_BUILD_WITH_TFM */