From 973aca32beac91749ea68871a1ac9f8f78ba90e5 Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Fri, 16 Jun 2023 20:31:56 +0530 Subject: [PATCH] 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. --- components/mbedtls/port/include/sha1_alt.h | 18 ++ components/wpa_supplicant/CMakeLists.txt | 2 + .../src/crypto/crypto_mbedtls.c | 14 +- .../esp_supplicant/src/crypto/fastpbkdf2.c | 248 ++++++------------ .../esp_supplicant/src/crypto/fastpbkdf2.h | 35 +-- docs/en/COPYRIGHT.rst | 2 + tools/ci/check_copyright_config.yaml | 1 + tools/ci/check_copyright_ignore.txt | 2 - 8 files changed, 127 insertions(+), 195 deletions(-) diff --git a/components/mbedtls/port/include/sha1_alt.h b/components/mbedtls/port/include/sha1_alt.h index 530eb5319c..26039378b4 100644 --- a/components/mbedtls/port/include/sha1_alt.h +++ b/components/mbedtls/port/include/sha1_alt.h @@ -50,6 +50,24 @@ typedef struct { esp_mbedtls_sha1_mode mode; } 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 || SOC_SHA_SUPPORT_RESUME typedef enum { diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 27390397bc..4bf44c466e 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -94,6 +94,7 @@ endif() if(CONFIG_WPA_MBEDTLS_CRYPTO) set(crypto_src + "esp_supplicant/src/crypto/fastpbkdf2.c" "esp_supplicant/src/crypto/crypto_mbedtls.c" "esp_supplicant/src/crypto/crypto_mbedtls-bignum.c" "esp_supplicant/src/crypto/crypto_mbedtls-rsa.c" @@ -219,6 +220,7 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_IEEE80211W CONFIG_SHA256 CONFIG_NO_RADIUS + CONFIG_FAST_PBKDF2 ) if(CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE) diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c index 562f076f25..52bc087670 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -36,6 +36,10 @@ #include "crypto.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, const u8 *addr[], const size_t *len, u8 *mac) { @@ -744,9 +748,14 @@ cleanup: int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, 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 int ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (const u8 *) passphrase, os_strlen(passphrase) , ssid, - ssid_len, iterations, 32, buf); + ssid_len, iterations, buflen, buf); if (ret != 0) { ret = -1; goto cleanup; @@ -754,6 +763,7 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, cleanup: return ret; +#endif } #ifdef MBEDTLS_DES_C diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.c b/components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.c index 90b42fac0e..8ac2abbe56 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.c @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2015 Joseph Birr-Pixton + * + * SPDX-License-Identifier: CC0-1.0 + */ + /* * fast-pbkdf2 - Optimal PBKDF2-HMAC calculation * Written in 2015 by Joseph Birr-Pixton @@ -11,7 +17,7 @@ * along with this software. If not, see * . */ - +#include "utils/common.h" #include "fastpbkdf2.h" #include @@ -20,7 +26,9 @@ #include #endif -#include +#include +#include "mbedtls/esp_config.h" +#include "utils/wpa_debug.h" /* --- MSVC doesn't support C99 --- */ #ifdef _MSC_VER @@ -29,7 +37,9 @@ #endif /* --- Common useful things --- */ +#ifndef MIN #define MIN(a, b) ((a) > (b)) ? (b) : (a) +#endif 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 } -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 * 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 * args: (_ctx *c, const void *data, size_t ndata) * _final hash context finish function - * args: (void *out, _ctx *c) + * args: (_ctx *c, void *out) * _xform hash context raw block update function * args: (_ctx *c, const void *data) * _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); \ _update(&ctx->inner, key, nkey); \ - _final(k, &ctx->inner); \ + _final(&ctx->inner, k); \ \ key = k; \ 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, \ uint8_t out[_hashsz]) \ { \ - _final(out, &ctx->inner); \ + _final(&ctx->inner, out); \ _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? */ \ uint32_t blocks_needed = (uint32_t)(nout + _hashsz - 1) / _hashsz; \ \ - OPENMP_PARALLEL_FOR \ for (uint32_t counter = 1; counter <= blocks_needed; counter++) \ { \ 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); - write32_be(ctx->h1, out + 4); - write32_be(ctx->h2, out + 8); - write32_be(ctx->h3, out + 12); - write32_be(ctx->h4, out + 16); +#if defined(MBEDTLS_SHA1_ALT) +#if CONFIG_IDF_TARGET_ESP32 + /* ESP32 stores internal SHA state in BE format similar to software */ + write32_be(ctx->state[0], out); + 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; - out->h1 = in->h1; - out->h2 = in->h2; - out->h3 = in->h3; - out->h4 = in->h4; +#if defined(MBEDTLS_SHA1_ALT) + out->state[0] = in->state[0]; + out->state[1] = in->state[1]; + out->state[2] = in->state[2]; + 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; - out->h1 ^= in->h1; - out->h2 ^= in->h2; - out->h3 ^= in->h3; - out->h4 ^= in->h4; +#if defined(MBEDTLS_SHA1_ALT) + out->state[0] ^= in->state[0]; + out->state[1] ^= in->state[1]; + out->state[2] ^= in->state[2]; + 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, - 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) +static int mbedtls_sha1_init_start(mbedtls_sha1_context *ctx) { - write32_be(ctx->h[0], out); - write32_be(ctx->h[1], out + 4); - write32_be(ctx->h[2], out + 8); - write32_be(ctx->h[3], out + 12); - write32_be(ctx->h[4], out + 16); - write32_be(ctx->h[5], out + 20); - write32_be(ctx->h[6], out + 24); - write32_be(ctx->h[7], out + 28); + mbedtls_sha1_init(ctx); + mbedtls_sha1_starts(ctx); +#if defined(CONFIG_IDF_TARGET_ESP32) && defined(MBEDTLS_SHA1_ALT) + /* Use software mode for esp32 since hardware can't give output more than 20 */ + esp_mbedtls_set_sha1_mode(ctx, ESP_MBEDTLS_SHA1_SOFTWARE); +#endif + return 0; } -static inline void sha256_cpy(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]; -} - -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) +DECL_PBKDF2(sha1, // _name + 64, // _blocksz + 20, // _hashsz + mbedtls_sha1_context, // _ctx + mbedtls_sha1_init_start, // _init + mbedtls_sha1_update, // _update + mbedtls_internal_sha1_process, // _xform + mbedtls_sha1_finish, // _final + sha1_cpy, // _xcpy + sha1_extract, // _xtract + sha1_xor) // _xxor void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, 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); } - -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); -} diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.h b/components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.h index 0a7346ecac..60838942dd 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.h +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.h @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2015 Joseph Birr-Pixton + * + * SPDX-License-Identifier: CC0-1.0 + */ + /* * fastpbkdf2 - Faster PBKDF2-HMAC calculation * Written in 2015 by Joseph Birr-Pixton @@ -35,35 +41,6 @@ void fastpbkdf2_hmac_sha1(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-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 } #endif diff --git a/docs/en/COPYRIGHT.rst b/docs/en/COPYRIGHT.rst index 3701e2439d..2bc340309d 100644 --- a/docs/en/COPYRIGHT.rst +++ b/docs/en/COPYRIGHT.rst @@ -27,6 +27,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. +* :component_file:`Fast PBKDF2 ` 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. * `argtable3`_ argument parsing library Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann and licensed under 3-clause BSD license. argtable3 also includes the following software components. For details, please see argtable3 :component_file:`LICENSE file`. diff --git a/tools/ci/check_copyright_config.yaml b/tools/ci/check_copyright_config.yaml index 385ef169f6..4d051f46ba 100644 --- a/tools/ci/check_copyright_config.yaml +++ b/tools/ci/check_copyright_config.yaml @@ -178,6 +178,7 @@ ignore: - components/http_parser/ - components/wpa_supplicant/src/ - '!components/wpa_supplicant/esp_supplicant/' + - components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2* - components/bt/host/bluedroid/ - '!components/bt/host/bluedroid/api/' - '!components/bt/host/bluedroid/btc/' diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 12d314a7ab..f5938a5442 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1244,8 +1244,6 @@ components/wifi_provisioning/src/scheme_console.c components/wifi_provisioning/src/wifi_config.c components/wifi_provisioning/src/wifi_provisioning_priv.h components/wifi_provisioning/src/wifi_scan.c -components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.c -components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.h components/wpa_supplicant/esp_supplicant/src/esp_scan_i.h components/wpa_supplicant/esp_supplicant/src/esp_wpa3_i.h components/wpa_supplicant/esp_supplicant/src/esp_wpa_err.h