ソースを参照

Merge branch 'feature/pbkdf2_fast_implementation' into 'master'

esp_wifi: Port fast_pbkdf2 implementation to calculate PMK

See merge request espressif/esp-idf!24287
Jiang Jiang Jian 2 年 前
コミット
62720ffa8c

+ 2 - 0
.gitlab/ci/target-test.yml

@@ -1398,6 +1398,7 @@ UT_S2_SDSPI:
 
 UT_C2:
   extends: .unit_test_esp32c2_template
+  parallel: 2
   tags:
     - ESP32C2_IDF
     - UT_T1_1
@@ -1419,6 +1420,7 @@ UT_C3_SDSPI:
 
 UT_C6:
   extends: .unit_test_esp32c6_template
+  parallel: 2
   tags:
     - ESP32C6_IDF
     - UT_T1_1

+ 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

+ 325 - 0
components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.c

@@ -0,0 +1,325 @@
+/*
+ * 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>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+#include "utils/common.h"
+#include "fastpbkdf2.h"
+
+#include <assert.h>
+#include <string.h>
+#if defined(__GNUC__)
+#include <endian.h>
+#endif
+
+#include <mbedtls/sha1.h>
+#include "mbedtls/esp_config.h"
+#include "utils/wpa_debug.h"
+
+/* --- MSVC doesn't support C99 --- */
+#ifdef _MSC_VER
+#define restrict
+#define _Pragma __pragma
+#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])
+{
+#if defined(__GNUC__) && __GNUC__ >= 4 && __BYTE_ORDER == __LITTLE_ENDIAN
+  *(uint32_t *)(out) = __builtin_bswap32(n);
+#else
+  out[0] = (n >> 24) & 0xff;
+  out[1] = (n >> 16) & 0xff;
+  out[2] = (n >> 8) & 0xff;
+  out[3] = n & 0xff;
+#endif
+}
+
+/* Prepare block (of blocksz bytes) to contain md padding denoting a msg-size
+ * message (in bytes).  block has a prefix of used bytes.
+ *
+ * Message length is expressed in 32 bits (so suitable for sha1, sha256, sha512). */
+static inline void md_pad(uint8_t *block, size_t blocksz, size_t used, size_t msg)
+{
+  memset(block + used, 0, blocksz - used - 4);
+  block[used] = 0x80;
+  block += blocksz - 4;
+  write32_be((uint32_t) (msg * 8), block);
+}
+
+/* Internal function/type names for hash-specific things. */
+#define HMAC_CTX(_name) HMAC_ ## _name ## _ctx
+#define HMAC_INIT(_name) HMAC_ ## _name ## _init
+#define HMAC_UPDATE(_name) HMAC_ ## _name ## _update
+#define HMAC_FINAL(_name) HMAC_ ## _name ## _final
+
+#define PBKDF2_F(_name) pbkdf2_f_ ## _name
+#define PBKDF2(_name) pbkdf2_ ## _name
+
+/* This macro expands to decls for the whole implementation for a given
+ * hash function.  Arguments are:
+ *
+ * _name like 'sha1', added to symbol names
+ * _blocksz block size, in bytes
+ * _hashsz digest output, in bytes
+ * _ctx hash context type
+ * _init hash context initialisation function
+ *    args: (_ctx *c)
+ * _update hash context update function
+ *    args: (_ctx *c, const void *data, size_t ndata)
+ * _final hash context finish function
+ *    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)
+ *    args: (_ctx * restrict out, const _ctx *restrict in)
+ * _xtract hash context state extraction
+ *    args: args (_ctx *restrict c, uint8_t *restrict out)
+ * _xxor hash context xor function (only need xor hash state)
+ *    args: (_ctx *restrict out, const _ctx *restrict in)
+ *
+ * The resulting function is named PBKDF2(_name).
+ */
+#define DECL_PBKDF2(_name, _blocksz, _hashsz, _ctx,                           \
+                    _init, _update, _xform, _final, _xcpy, _xtract, _xxor)    \
+  typedef struct {                                                            \
+    _ctx inner;                                                               \
+    _ctx outer;                                                               \
+  } HMAC_CTX(_name);                                                          \
+                                                                              \
+  static inline void HMAC_INIT(_name)(HMAC_CTX(_name) *ctx,                   \
+                                      const uint8_t *key, size_t nkey)        \
+  {                                                                           \
+    /* Prepare key: */                                                        \
+    uint8_t k[_blocksz];                                                      \
+                                                                              \
+    /* Shorten long keys. */                                                  \
+    if (nkey > _blocksz)                                                      \
+    {                                                                         \
+      _init(&ctx->inner);                                                     \
+      _update(&ctx->inner, key, nkey);                                        \
+      _final(&ctx->inner, k);                                                 \
+                                                                              \
+      key = k;                                                                \
+      nkey = _hashsz;                                                         \
+    }                                                                         \
+                                                                              \
+    /* Standard doesn't cover case where blocksz < hashsz. */                 \
+    assert(nkey <= _blocksz);                                                 \
+                                                                              \
+    /* Right zero-pad short keys. */                                          \
+    if (k != key)                                                             \
+      memcpy(k, key, nkey);                                                   \
+    if (_blocksz > nkey)                                                      \
+      memset(k + nkey, 0, _blocksz - nkey);                                   \
+                                                                              \
+    /* Start inner hash computation */                                        \
+    uint8_t blk_inner[_blocksz];                                              \
+    uint8_t blk_outer[_blocksz];                                              \
+                                                                              \
+    for (size_t i = 0; i < _blocksz; i++)                                     \
+    {                                                                         \
+      blk_inner[i] = 0x36 ^ k[i];                                             \
+      blk_outer[i] = 0x5c ^ k[i];                                             \
+    }                                                                         \
+                                                                              \
+    _init(&ctx->inner);                                                       \
+    _update(&ctx->inner, blk_inner, sizeof blk_inner);                        \
+                                                                              \
+    /* And outer. */                                                          \
+    _init(&ctx->outer);                                                       \
+    _update(&ctx->outer, blk_outer, sizeof blk_outer);                        \
+  }                                                                           \
+                                                                              \
+  static inline void HMAC_UPDATE(_name)(HMAC_CTX(_name) *ctx,                 \
+                                        const void *data, size_t ndata)       \
+  {                                                                           \
+    _update(&ctx->inner, data, ndata);                                        \
+  }                                                                           \
+                                                                              \
+  static inline void HMAC_FINAL(_name)(HMAC_CTX(_name) *ctx,                  \
+                                       uint8_t out[_hashsz])                  \
+  {                                                                           \
+    _final(&ctx->inner, out);                                                 \
+    _update(&ctx->outer, out, _hashsz);                                       \
+    _final(&ctx->outer, out);                                                 \
+  }                                                                           \
+                                                                              \
+                                                                              \
+  /* --- PBKDF2 --- */                                                        \
+  static inline void PBKDF2_F(_name)(const HMAC_CTX(_name) *startctx,         \
+                                     uint32_t counter,                        \
+                                     const uint8_t *salt, size_t nsalt,       \
+                                     uint32_t iterations,                     \
+                                     uint8_t *out)                            \
+  {                                                                           \
+    uint8_t countbuf[4];                                                      \
+    write32_be(counter, countbuf);                                            \
+                                                                              \
+    /* Prepare loop-invariant padding block. */                               \
+    uint8_t Ublock[_blocksz];                                                 \
+    md_pad(Ublock, _blocksz, _hashsz, _blocksz + _hashsz);                    \
+                                                                              \
+    /* First iteration:                                                       \
+     *   U_1 = PRF(P, S || INT_32_BE(i))                                      \
+     */                                                                       \
+    HMAC_CTX(_name) ctx = *startctx;                                          \
+    HMAC_UPDATE(_name)(&ctx, salt, nsalt);                                    \
+    HMAC_UPDATE(_name)(&ctx, countbuf, sizeof countbuf);                      \
+    HMAC_FINAL(_name)(&ctx, Ublock);                                          \
+    _ctx result = ctx.outer;                                                  \
+                                                                              \
+    /* Subsequent iterations:                                                 \
+     *   U_c = PRF(P, U_{c-1})                                                \
+     */                                                                       \
+    for (uint32_t i = 1; i < iterations; i++)                                 \
+    {                                                                         \
+      /* Complete inner hash with previous U */                               \
+      _xcpy(&ctx.inner, &startctx->inner);                                    \
+      _xform(&ctx.inner, Ublock);                                             \
+      _xtract(&ctx.inner, Ublock);                                            \
+      /* Complete outer hash with inner output */                             \
+      _xcpy(&ctx.outer, &startctx->outer);                                    \
+      _xform(&ctx.outer, Ublock);                                             \
+      _xtract(&ctx.outer, Ublock);                                            \
+      _xxor(&result, &ctx.outer);                                             \
+    }                                                                         \
+                                                                              \
+    /* Reform result into output buffer. */                                   \
+    _xtract(&result, out);                                                    \
+  }                                                                           \
+                                                                              \
+  static inline void PBKDF2(_name)(const uint8_t *pw, size_t npw,             \
+                     const uint8_t *salt, size_t nsalt,                       \
+                     uint32_t iterations,                                     \
+                     uint8_t *out, size_t nout)                               \
+  {                                                                           \
+    assert(iterations);                                                       \
+    assert(out && nout);                                                      \
+                                                                              \
+    /* Starting point for inner loop. */                                      \
+    HMAC_CTX(_name) ctx;                                                      \
+    HMAC_INIT(_name)(&ctx, pw, npw);                                          \
+                                                                              \
+    /* How many blocks do we need? */                                         \
+    uint32_t blocks_needed = (uint32_t)(nout + _hashsz - 1) / _hashsz;        \
+                                                                              \
+    for (uint32_t counter = 1; counter <= blocks_needed; counter++)           \
+    {                                                                         \
+      uint8_t block[_hashsz];                                                 \
+      PBKDF2_F(_name)(&ctx, counter, salt, nsalt, iterations, block);         \
+                                                                              \
+      size_t offset = (counter - 1) * _hashsz;                                \
+      size_t taken = MIN(nout - offset, _hashsz);                             \
+      memcpy(out + offset, block, taken);                                     \
+    }                                                                         \
+  }
+
+static inline void sha1_extract(mbedtls_sha1_context *restrict ctx, uint8_t *restrict out)
+{
+#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(mbedtls_sha1_context *restrict out, const mbedtls_sha1_context *restrict in)
+{
+#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(mbedtls_sha1_context *restrict out, const mbedtls_sha1_context *restrict in)
+{
+#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 int mbedtls_sha1_init_start(mbedtls_sha1_context *ctx)
+{
+  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(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,
+                          uint32_t iterations,
+                          uint8_t *out, size_t nout)
+{
+  PBKDF2(sha1)(pw, npw, salt, nsalt, iterations, out, nout);
+}

+ 48 - 0
components/wpa_supplicant/esp_supplicant/src/crypto/fastpbkdf2.h

@@ -0,0 +1,48 @@
+/*
+ * 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>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef FASTPBKDF2_H
+#define FASTPBKDF2_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Calculates PBKDF2-HMAC-SHA1.
+ *
+ *  @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_sha1(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
+
+#endif

+ 68 - 0
components/wpa_supplicant/test/test_fast_pbkdf2.c

@@ -0,0 +1,68 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+#include "string.h"
+#include <inttypes.h>
+#include "unity.h"
+#include "utils/common.h"
+#include "mbedtls/pkcs5.h"
+#include "crypto/sha1.h"
+
+#if SOC_WIFI_SUPPORTED
+
+#define PMK_LEN 32
+
+TEST_CASE("Test pbkdf2", "[crypto-pbkdf2]")
+{
+	uint8_t PMK[PMK_LEN];
+	uint8_t ssid_len;
+	uint8_t passphrase_len;
+	uint8_t ssid[MAX_SSID_LEN];
+	uint8_t passphrase[MAX_PASSPHRASE_LEN];
+	uint8_t expected_pmk1[PMK_LEN] =
+	{0xe7, 0x90, 0xd0, 0x65, 0x67, 0xf0, 0xbf, 0xca, 0xca, 0x10, 0x88, 0x0b, 0x85, 0xb2, 0x33, 0xe5,
+	 0xe1, 0xd5, 0xe5, 0xb8, 0xd0, 0xfd, 0x94, 0x60, 0x56, 0x95, 0x5e, 0x41, 0x5a, 0x7f, 0xfa, 0xfa};
+
+	uint8_t expected_pmk[PMK_LEN];
+
+	/* Compare Fast PBKDF output with expected output*/
+	pbkdf2_sha1("espressif", (uint8_t *)"espressif", strlen("espressif"), 4096, PMK, PMK_LEN);
+	TEST_ASSERT(memcmp(PMK, expected_pmk1, PMK_LEN) == 0);
+
+	/* Compare fast PBKDF output with mbedtls pbkdf2 function's output */
+	pbkdf2_sha1("espressif2", (uint8_t *)"espressif2", strlen("espressif2"), 4096, PMK, PMK_LEN);
+	mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (const unsigned char *) "espressif2",
+					strlen("espressif2") , (const unsigned char *)"espressif2",
+					strlen("espressif2"), 4096, PMK_LEN, expected_pmk);
+	TEST_ASSERT(memcmp(PMK, expected_pmk, PMK_LEN) == 0);
+
+	/* Calculate PMK using random ssid and passphrase and compare */
+	os_memset(ssid, 0, MAX_SSID_LEN);
+	os_memset(passphrase, 0, MAX_PASSPHRASE_LEN);
+	ssid_len = os_random();
+	ssid_len %= MAX_SSID_LEN;
+
+	os_get_random(ssid, ssid_len);
+
+	passphrase_len = os_random();
+	passphrase_len %= MAX_PASSPHRASE_LEN;
+
+	os_get_random(passphrase, passphrase_len);
+	pbkdf2_sha1((char *)passphrase, ssid, ssid_len, 4096, PMK, PMK_LEN);
+	mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (const unsigned char *) passphrase,
+					strlen((char *)passphrase) , (const unsigned char *)ssid,
+					ssid_len, 4096, PMK_LEN, expected_pmk);
+
+	/* Dump values if fails */
+	if (memcmp(PMK, expected_pmk, PMK_LEN) != 0) {
+		ESP_LOG_BUFFER_HEXDUMP("passphrase", passphrase, passphrase_len, ESP_LOG_INFO);
+		ESP_LOG_BUFFER_HEXDUMP("ssid", ssid, ssid_len, ESP_LOG_INFO);
+		ESP_LOG_BUFFER_HEXDUMP("PMK", PMK, PMK_LEN, ESP_LOG_INFO);
+		ESP_LOG_BUFFER_HEXDUMP("expected_pmk", expected_pmk, PMK_LEN, ESP_LOG_INFO);
+	}
+	TEST_ASSERT(memcmp(PMK, expected_pmk, PMK_LEN) == 0);
+}
+
+#endif /* SOC_WIFI_SUPPORTED */

+ 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/'