change(esp_wifi): Port fast_pbkdf2 implementation for mbedlts

Add changes to use fast_pbkdf2 as default for PMK calculations.
fast_pbkdf2 is significantly faster than current implementations
for esp chips.

Also removes unnecessary code for pbkdf-sha256 and pbkdf-sha512.
This commit is contained in:
Kapil Gupta
2023-06-16 20:31:56 +05:30
committed by Shreyas Sheth
parent e8fcdc3ebf
commit 3e4f49606b
6 changed files with 126 additions and 192 deletions

View File

@ -50,6 +50,24 @@ typedef struct {
esp_mbedtls_sha1_mode mode; esp_mbedtls_sha1_mode mode;
} mbedtls_sha1_context; } mbedtls_sha1_context;
/**
* \brief Set the SHA-1 mode for a mbedtls_sha1_context.
*
* \param ctx The SHA-1 context structure.
* \param mode The SHA-1 mode to be set. It can be one of the following:
* - ESP_MBEDTLS_SHA1_UNUSED: Indicates that the first block hasn't been processed yet.
* - ESP_MBEDTLS_SHA1_HARDWARE: Specifies the use of hardware SHA engine for SHA-1 calculations.
* - ESP_MBEDTLS_SHA1_SOFTWARE: Specifies the use of software-based SHA-1 calculations.
*
* \return None.
*/
static inline void esp_mbedtls_set_sha1_mode(mbedtls_sha1_context *ctx, esp_mbedtls_sha1_mode mode)
{
if (ctx) {
ctx->mode = mode;
}
}
#elif SOC_SHA_SUPPORT_DMA #elif SOC_SHA_SUPPORT_DMA
typedef enum { typedef enum {

View File

@ -91,6 +91,7 @@ endif()
if(CONFIG_WPA_MBEDTLS_CRYPTO) if(CONFIG_WPA_MBEDTLS_CRYPTO)
set(crypto_src set(crypto_src
"src/crypto/fastpbkdf2.c"
"src/crypto/crypto_mbedtls.c" "src/crypto/crypto_mbedtls.c"
"src/crypto/crypto_mbedtls-bignum.c" "src/crypto/crypto_mbedtls-bignum.c"
"src/crypto/crypto_mbedtls-ec.c") "src/crypto/crypto_mbedtls-ec.c")
@ -202,6 +203,7 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE
CONFIG_IEEE80211W CONFIG_IEEE80211W
CONFIG_SHA256 CONFIG_SHA256
CONFIG_WNM CONFIG_WNM
CONFIG_FAST_PBKDF2
) )
if(CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE) if(CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE)

View File

@ -37,6 +37,10 @@
#include "crypto.h" #include "crypto.h"
#include "mbedtls/esp_config.h" #include "mbedtls/esp_config.h"
#ifdef CONFIG_FAST_PBKDF2
#include "fastpbkdf2.h"
#endif
static int digest_vector(mbedtls_md_type_t md_type, size_t num_elem, static int digest_vector(mbedtls_md_type_t md_type, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac) const u8 *addr[], const size_t *len, u8 *mac)
{ {
@ -658,6 +662,12 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
int iterations, u8 *buf, size_t buflen) int iterations, u8 *buf, size_t buflen)
{ {
#ifdef CONFIG_FAST_PBKDF2
fastpbkdf2_hmac_sha1((const u8 *) passphrase, os_strlen(passphrase),
ssid, ssid_len, iterations, buf, buflen);
return 0;
#else
mbedtls_md_context_t sha1_ctx; mbedtls_md_context_t sha1_ctx;
const mbedtls_md_info_t *info_sha1; const mbedtls_md_info_t *info_sha1;
int ret; int ret;
@ -677,7 +687,7 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
ret = mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const u8 *) passphrase, ret = mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const u8 *) passphrase,
os_strlen(passphrase) , ssid, os_strlen(passphrase) , ssid,
ssid_len, iterations, 32, buf); ssid_len, iterations, buflen, buf);
if (ret != 0) { if (ret != 0) {
ret = -1; ret = -1;
goto cleanup; goto cleanup;
@ -686,6 +696,7 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
cleanup: cleanup:
mbedtls_md_free(&sha1_ctx); mbedtls_md_free(&sha1_ctx);
return ret; return ret;
#endif
} }
#ifdef MBEDTLS_DES_C #ifdef MBEDTLS_DES_C

View File

@ -1,3 +1,9 @@
/*
* SPDX-FileCopyrightText: 2015 Joseph Birr-Pixton <jpixton@gmail.com>
*
* SPDX-License-Identifier: CC0-1.0
*/
/* /*
* fast-pbkdf2 - Optimal PBKDF2-HMAC calculation * fast-pbkdf2 - Optimal PBKDF2-HMAC calculation
* Written in 2015 by Joseph Birr-Pixton <jpixton@gmail.com> * Written in 2015 by Joseph Birr-Pixton <jpixton@gmail.com>
@ -11,7 +17,7 @@
* along with this software. If not, see * along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>. * <http://creativecommons.org/publicdomain/zero/1.0/>.
*/ */
#include "utils/common.h"
#include "fastpbkdf2.h" #include "fastpbkdf2.h"
#include <assert.h> #include <assert.h>
@ -20,7 +26,9 @@
#include <endian.h> #include <endian.h>
#endif #endif
#include <openssl/sha.h> #include <mbedtls/sha1.h>
#include "mbedtls/esp_config.h"
#include "utils/wpa_debug.h"
/* --- MSVC doesn't support C99 --- */ /* --- MSVC doesn't support C99 --- */
#ifdef _MSC_VER #ifdef _MSC_VER
@ -29,7 +37,9 @@
#endif #endif
/* --- Common useful things --- */ /* --- Common useful things --- */
#ifndef MIN
#define MIN(a, b) ((a) > (b)) ? (b) : (a) #define MIN(a, b) ((a) > (b)) ? (b) : (a)
#endif
static inline void write32_be(uint32_t n, uint8_t out[4]) static inline void write32_be(uint32_t n, uint8_t out[4])
{ {
@ -43,23 +53,6 @@ static inline void write32_be(uint32_t n, uint8_t out[4])
#endif #endif
} }
static inline void write64_be(uint64_t n, uint8_t out[8])
{
#if defined(__GNUC__) && __GNUC__ >= 4 && __BYTE_ORDER == __LITTLE_ENDIAN
*(uint64_t *)(out) = __builtin_bswap64(n);
#else
write32_be((n >> 32) & 0xffffffff, out);
write32_be(n & 0xffffffff, out + 4);
#endif
}
/* --- Optional OpenMP parallelisation of consecutive blocks --- */
#ifdef WITH_OPENMP
# define OPENMP_PARALLEL_FOR _Pragma("omp parallel for")
#else
# define OPENMP_PARALLEL_FOR
#endif
/* Prepare block (of blocksz bytes) to contain md padding denoting a msg-size /* Prepare block (of blocksz bytes) to contain md padding denoting a msg-size
* message (in bytes). block has a prefix of used bytes. * message (in bytes). block has a prefix of used bytes.
* *
@ -93,7 +86,7 @@ static inline void md_pad(uint8_t *block, size_t blocksz, size_t used, size_t ms
* _update hash context update function * _update hash context update function
* args: (_ctx *c, const void *data, size_t ndata) * args: (_ctx *c, const void *data, size_t ndata)
* _final hash context finish function * _final hash context finish function
* args: (void *out, _ctx *c) * args: (_ctx *c, void *out)
* _xform hash context raw block update function * _xform hash context raw block update function
* args: (_ctx *c, const void *data) * args: (_ctx *c, const void *data)
* _xcpy hash context raw copy function (only need copy hash state) * _xcpy hash context raw copy function (only need copy hash state)
@ -123,7 +116,7 @@ static inline void md_pad(uint8_t *block, size_t blocksz, size_t used, size_t ms
{ \ { \
_init(&ctx->inner); \ _init(&ctx->inner); \
_update(&ctx->inner, key, nkey); \ _update(&ctx->inner, key, nkey); \
_final(k, &ctx->inner); \ _final(&ctx->inner, k); \
\ \
key = k; \ key = k; \
nkey = _hashsz; \ nkey = _hashsz; \
@ -165,9 +158,9 @@ static inline void md_pad(uint8_t *block, size_t blocksz, size_t used, size_t ms
static inline void HMAC_FINAL(_name)(HMAC_CTX(_name) *ctx, \ static inline void HMAC_FINAL(_name)(HMAC_CTX(_name) *ctx, \
uint8_t out[_hashsz]) \ uint8_t out[_hashsz]) \
{ \ { \
_final(out, &ctx->inner); \ _final(&ctx->inner, out); \
_update(&ctx->outer, out, _hashsz); \ _update(&ctx->outer, out, _hashsz); \
_final(out, &ctx->outer); \ _final(&ctx->outer, out); \
} \ } \
\ \
\ \
@ -229,7 +222,6 @@ static inline void md_pad(uint8_t *block, size_t blocksz, size_t used, size_t ms
/* How many blocks do we need? */ \ /* How many blocks do we need? */ \
uint32_t blocks_needed = (uint32_t)(nout + _hashsz - 1) / _hashsz; \ uint32_t blocks_needed = (uint32_t)(nout + _hashsz - 1) / _hashsz; \
\ \
OPENMP_PARALLEL_FOR \
for (uint32_t counter = 1; counter <= blocks_needed; counter++) \ for (uint32_t counter = 1; counter <= blocks_needed; counter++) \
{ \ { \
uint8_t block[_hashsz]; \ uint8_t block[_hashsz]; \
@ -241,140 +233,88 @@ static inline void md_pad(uint8_t *block, size_t blocksz, size_t used, size_t ms
} \ } \
} }
static inline void sha1_extract(SHA_CTX *restrict ctx, uint8_t *restrict out) static inline void sha1_extract(mbedtls_sha1_context *restrict ctx, uint8_t *restrict out)
{ {
write32_be(ctx->h0, out); #if defined(MBEDTLS_SHA1_ALT)
write32_be(ctx->h1, out + 4); #if CONFIG_IDF_TARGET_ESP32
write32_be(ctx->h2, out + 8); /* ESP32 stores internal SHA state in BE format similar to software */
write32_be(ctx->h3, out + 12); write32_be(ctx->state[0], out);
write32_be(ctx->h4, out + 16); write32_be(ctx->state[1], out + 4);
write32_be(ctx->state[2], out + 8);
write32_be(ctx->state[3], out + 12);
write32_be(ctx->state[4], out + 16);
#else
*(uint32_t *)(out) = ctx->state[0];
*(uint32_t *)(out + 4) = ctx->state[1];
*(uint32_t *)(out + 8) = ctx->state[2];
*(uint32_t *)(out + 12) = ctx->state[3];
*(uint32_t *)(out + 16) = ctx->state[4];
#endif
#else
write32_be(ctx->MBEDTLS_PRIVATE(state)[0], out);
write32_be(ctx->MBEDTLS_PRIVATE(state)[1], out + 4);
write32_be(ctx->MBEDTLS_PRIVATE(state)[2], out + 8);
write32_be(ctx->MBEDTLS_PRIVATE(state)[3], out + 12);
write32_be(ctx->MBEDTLS_PRIVATE(state)[4], out + 16);
#endif
} }
static inline void sha1_cpy(SHA_CTX *restrict out, const SHA_CTX *restrict in) static inline void sha1_cpy(mbedtls_sha1_context *restrict out, const mbedtls_sha1_context *restrict in)
{ {
out->h0 = in->h0; #if defined(MBEDTLS_SHA1_ALT)
out->h1 = in->h1; out->state[0] = in->state[0];
out->h2 = in->h2; out->state[1] = in->state[1];
out->h3 = in->h3; out->state[2] = in->state[2];
out->h4 = in->h4; out->state[3] = in->state[3];
out->state[4] = in->state[4];
#else
out->MBEDTLS_PRIVATE(state)[0] = in->MBEDTLS_PRIVATE(state)[0];
out->MBEDTLS_PRIVATE(state)[1] = in->MBEDTLS_PRIVATE(state)[1];
out->MBEDTLS_PRIVATE(state)[2] = in->MBEDTLS_PRIVATE(state)[2];
out->MBEDTLS_PRIVATE(state)[3] = in->MBEDTLS_PRIVATE(state)[3];
out->MBEDTLS_PRIVATE(state)[4] = in->MBEDTLS_PRIVATE(state)[4];
#endif
} }
static inline void sha1_xor(SHA_CTX *restrict out, const SHA_CTX *restrict in) static inline void sha1_xor(mbedtls_sha1_context *restrict out, const mbedtls_sha1_context *restrict in)
{ {
out->h0 ^= in->h0; #if defined(MBEDTLS_SHA1_ALT)
out->h1 ^= in->h1; out->state[0] ^= in->state[0];
out->h2 ^= in->h2; out->state[1] ^= in->state[1];
out->h3 ^= in->h3; out->state[2] ^= in->state[2];
out->h4 ^= in->h4; out->state[3] ^= in->state[3];
out->state[4] ^= in->state[4];
#else
out->MBEDTLS_PRIVATE(state)[0] ^= in->MBEDTLS_PRIVATE(state)[0];
out->MBEDTLS_PRIVATE(state)[1] ^= in->MBEDTLS_PRIVATE(state)[1];
out->MBEDTLS_PRIVATE(state)[2] ^= in->MBEDTLS_PRIVATE(state)[2];
out->MBEDTLS_PRIVATE(state)[3] ^= in->MBEDTLS_PRIVATE(state)[3];
out->MBEDTLS_PRIVATE(state)[4] ^= in->MBEDTLS_PRIVATE(state)[4];
#endif
} }
DECL_PBKDF2(sha1, static int mbedtls_sha1_init_start(mbedtls_sha1_context *ctx)
SHA_CBLOCK,
SHA_DIGEST_LENGTH,
SHA_CTX,
SHA1_Init,
SHA1_Update,
SHA1_Transform,
SHA1_Final,
sha1_cpy,
sha1_extract,
sha1_xor)
static inline void sha256_extract(SHA256_CTX *restrict ctx, uint8_t *restrict out)
{ {
write32_be(ctx->h[0], out); mbedtls_sha1_init(ctx);
write32_be(ctx->h[1], out + 4); mbedtls_sha1_starts(ctx);
write32_be(ctx->h[2], out + 8); #if defined(CONFIG_IDF_TARGET_ESP32) && defined(MBEDTLS_SHA1_ALT)
write32_be(ctx->h[3], out + 12); /* Use software mode for esp32 since hardware can't give output more than 20 */
write32_be(ctx->h[4], out + 16); esp_mbedtls_set_sha1_mode(ctx, ESP_MBEDTLS_SHA1_SOFTWARE);
write32_be(ctx->h[5], out + 20); #endif
write32_be(ctx->h[6], out + 24); return 0;
write32_be(ctx->h[7], out + 28);
} }
static inline void sha256_cpy(SHA256_CTX *restrict out, const SHA256_CTX *restrict in) DECL_PBKDF2(sha1, // _name
{ 64, // _blocksz
out->h[0] = in->h[0]; 20, // _hashsz
out->h[1] = in->h[1]; mbedtls_sha1_context, // _ctx
out->h[2] = in->h[2]; mbedtls_sha1_init_start, // _init
out->h[3] = in->h[3]; mbedtls_sha1_update, // _update
out->h[4] = in->h[4]; mbedtls_internal_sha1_process, // _xform
out->h[5] = in->h[5]; mbedtls_sha1_finish, // _final
out->h[6] = in->h[6]; sha1_cpy, // _xcpy
out->h[7] = in->h[7]; sha1_extract, // _xtract
} sha1_xor) // _xxor
static inline void sha256_xor(SHA256_CTX *restrict out, const SHA256_CTX *restrict in)
{
out->h[0] ^= in->h[0];
out->h[1] ^= in->h[1];
out->h[2] ^= in->h[2];
out->h[3] ^= in->h[3];
out->h[4] ^= in->h[4];
out->h[5] ^= in->h[5];
out->h[6] ^= in->h[6];
out->h[7] ^= in->h[7];
}
DECL_PBKDF2(sha256,
SHA256_CBLOCK,
SHA256_DIGEST_LENGTH,
SHA256_CTX,
SHA256_Init,
SHA256_Update,
SHA256_Transform,
SHA256_Final,
sha256_cpy,
sha256_extract,
sha256_xor)
static inline void sha512_extract(SHA512_CTX *restrict ctx, uint8_t *restrict out)
{
write64_be(ctx->h[0], out);
write64_be(ctx->h[1], out + 8);
write64_be(ctx->h[2], out + 16);
write64_be(ctx->h[3], out + 24);
write64_be(ctx->h[4], out + 32);
write64_be(ctx->h[5], out + 40);
write64_be(ctx->h[6], out + 48);
write64_be(ctx->h[7], out + 56);
}
static inline void sha512_cpy(SHA512_CTX *restrict out, const SHA512_CTX *restrict in)
{
out->h[0] = in->h[0];
out->h[1] = in->h[1];
out->h[2] = in->h[2];
out->h[3] = in->h[3];
out->h[4] = in->h[4];
out->h[5] = in->h[5];
out->h[6] = in->h[6];
out->h[7] = in->h[7];
}
static inline void sha512_xor(SHA512_CTX *restrict out, const SHA512_CTX *restrict in)
{
out->h[0] ^= in->h[0];
out->h[1] ^= in->h[1];
out->h[2] ^= in->h[2];
out->h[3] ^= in->h[3];
out->h[4] ^= in->h[4];
out->h[5] ^= in->h[5];
out->h[6] ^= in->h[6];
out->h[7] ^= in->h[7];
}
DECL_PBKDF2(sha512,
SHA512_CBLOCK,
SHA512_DIGEST_LENGTH,
SHA512_CTX,
SHA512_Init,
SHA512_Update,
SHA512_Transform,
SHA512_Final,
sha512_cpy,
sha512_extract,
sha512_xor)
void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt, const uint8_t *salt, size_t nsalt,
@ -383,19 +323,3 @@ void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw,
{ {
PBKDF2(sha1)(pw, npw, salt, nsalt, iterations, out, nout); PBKDF2(sha1)(pw, npw, salt, nsalt, iterations, out, nout);
} }
void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout)
{
PBKDF2(sha256)(pw, npw, salt, nsalt, iterations, out, nout);
}
void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout)
{
PBKDF2(sha512)(pw, npw, salt, nsalt, iterations, out, nout);
}

View File

@ -1,3 +1,9 @@
/*
* SPDX-FileCopyrightText: 2015 Joseph Birr-Pixton <jpixton@gmail.com>
*
* SPDX-License-Identifier: CC0-1.0
*/
/* /*
* fastpbkdf2 - Faster PBKDF2-HMAC calculation * fastpbkdf2 - Faster PBKDF2-HMAC calculation
* Written in 2015 by Joseph Birr-Pixton <jpixton@gmail.com> * Written in 2015 by Joseph Birr-Pixton <jpixton@gmail.com>
@ -35,35 +41,6 @@ void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt, const uint8_t *salt, size_t nsalt,
uint32_t iterations, uint32_t iterations,
uint8_t *out, size_t nout); uint8_t *out, size_t nout);
/** Calculates PBKDF2-HMAC-SHA256.
*
* @p npw bytes at @p pw are the password input.
* @p nsalt bytes at @p salt are the salt input.
* @p iterations is the PBKDF2 iteration count and must be non-zero.
* @p nout bytes of output are written to @p out. @p nout must be non-zero.
*
* This function cannot fail; it does not report errors.
*/
void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout);
/** Calculates PBKDF2-HMAC-SHA512.
*
* @p npw bytes at @p pw are the password input.
* @p nsalt bytes at @p salt are the salt input.
* @p iterations is the PBKDF2 iteration count and must be non-zero.
* @p nout bytes of output are written to @p out. @p nout must be non-zero.
*
* This function cannot fail; it does not report errors.
*/
void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -25,6 +25,8 @@ These third party libraries can be included into the application (firmware) prod
* `wpa_supplicant`_ Copyright (c) 2003-2005 Jouni Malinen and licensed under the BSD license. * `wpa_supplicant`_ Copyright (c) 2003-2005 Jouni Malinen and licensed under the BSD license.
* :component_file:`Fast PBKDF2 <wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c>` Copyright (c) 2015 Joseph Birr-Pixton and licensed under CC0 Public Domain Dedication license.
* `FreeBSD net80211`_ Copyright (c) 2004-2008 Sam Leffler, Errno Consulting and licensed under the BSD license. * `FreeBSD net80211`_ Copyright (c) 2004-2008 Sam Leffler, Errno Consulting and licensed under the BSD license.
* `JSMN`_ JSON Parser (components/jsmn) Copyright (c) 2010 Serge A. Zaitsev and licensed under the MIT license. * `JSMN`_ JSON Parser (components/jsmn) Copyright (c) 2010 Serge A. Zaitsev and licensed under the MIT license.