Parcourir la source

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.
Kapil Gupta il y a 2 ans
Parent
commit
c82a792bc3

+ 18 - 0
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 {

+ 2 - 0
components/wpa_supplicant/CMakeLists.txt

@@ -96,6 +96,7 @@ endif()
 
 if(CONFIG_ESP_WIFI_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"
@@ -229,6 +230,7 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE
     CONFIG_IEEE80211W
     CONFIG_SHA256
     CONFIG_NO_RADIUS
+    CONFIG_FAST_PBKDF2
     )
 
 if(CONFIG_ESP_WIFI_ENABLE_WPA3_SAE)

+ 12 - 2
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)
 {
@@ -745,9 +749,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;
@@ -755,6 +764,7 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
 
 cleanup:
 	return ret;
+#endif
 }
 
 #ifdef MBEDTLS_DES_C

+ 86 - 162
components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.c

@@ -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
  * Written in 2015 by Joseph Birr-Pixton <jpixton@gmail.com>
@@ -11,7 +17,7 @@
  * along with this software. If not, see
  * <http://creativecommons.org/publicdomain/zero/1.0/>.
  */
-
+#include "utils/common.h"
 #include "fastpbkdf2.h"
 
 #include <assert.h>
@@ -20,7 +26,9 @@
 #include <endian.h>
 #endif
 
-#include <openssl/sha.h>
+#include <mbedtls/sha1.h>
+#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)
-{
-  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);
-}
-
-static inline void sha1_cpy(SHA_CTX *restrict out, const SHA_CTX *restrict in)
-{
-  out->h0 = in->h0;
-  out->h1 = in->h1;
-  out->h2 = in->h2;
-  out->h3 = in->h3;
-  out->h4 = in->h4;
-}
-
-static inline void sha1_xor(SHA_CTX *restrict out, const SHA_CTX *restrict in)
-{
-  out->h0 ^= in->h0;
-  out->h1 ^= in->h1;
-  out->h2 ^= in->h2;
-  out->h3 ^= in->h3;
-  out->h4 ^= in->h4;
-}
-
-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)
-{
-  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);
-}
-
-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)
+static inline void sha1_extract(mbedtls_sha1_context *restrict ctx, uint8_t *restrict out)
 {
-  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];
+#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
 }
 
-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)
+static inline void sha1_cpy(mbedtls_sha1_context *restrict out, const mbedtls_sha1_context *restrict in)
 {
-  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);
+#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 sha512_cpy(SHA512_CTX *restrict out, const SHA512_CTX *restrict in)
+static inline void sha1_xor(mbedtls_sha1_context *restrict out, const mbedtls_sha1_context *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];
+#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 sha512_xor(SHA512_CTX *restrict out, const SHA512_CTX *restrict in)
+static int mbedtls_sha1_init_start(mbedtls_sha1_context *ctx)
 {
-  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];
+  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;
 }
 
-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);
-}

+ 6 - 29
components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.h

@@ -1,3 +1,9 @@
+/*
+ * SPDX-FileCopyrightText: 2015 Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
 /*
  * fastpbkdf2 - Faster PBKDF2-HMAC calculation
  * 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,
                           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

+ 2 - 0
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-2022 Jouni Malinen <j@w1.fi> and contributors 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.
 
 * `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<console/argtable3/LICENSE>`.

+ 1 - 0
tools/ci/check_copyright_config.yaml

@@ -195,6 +195,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/'

+ 0 - 2
tools/ci/check_copyright_ignore.txt

@@ -850,8 +850,6 @@ components/wifi_provisioning/python/wifi_scan_pb2.py
 components/wifi_provisioning/src/scheme_console.c
 components/wifi_provisioning/src/wifi_config.c
 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_wpa_err.h
 components/wpa_supplicant/include/utils/wpa_debug.h