mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
Merge branch 'feat/sae_calculation_optimizations_v5.5' into 'release/v5.5'
fix(esp_wifi): Optimize crypto operations for supplicant (v5.5) See merge request espressif/esp-idf!47233
This commit is contained in:
@@ -721,6 +721,18 @@ menu "Wi-Fi"
|
||||
help
|
||||
Select this option to enable WiFi Easy Connect Support.
|
||||
|
||||
config ESP_WIFI_P256_ACCEL
|
||||
bool "Enable P-256 crypto acceleration"
|
||||
depends on ESP_WIFI_MBEDTLS_CRYPTO
|
||||
default n
|
||||
help
|
||||
Enable Espressif-specific P-256 acceleration in the WPA supplicant
|
||||
crypto layer. This reduces SAE and DPP latency on supported targets
|
||||
at the cost of additional code size.
|
||||
|
||||
If disabled, the supplicant falls back to the generic Mbed TLS
|
||||
implementation.
|
||||
|
||||
config ESP_WIFI_11R_SUPPORT
|
||||
bool "Enable 802.11R (Fast Transition) Support"
|
||||
default n
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -16,6 +16,253 @@
|
||||
#include "random.h"
|
||||
#include "sha256.h"
|
||||
#include "mbedtls/pk.h"
|
||||
#include "p256_common.h"
|
||||
|
||||
#if CONFIG_ESP_WIFI_P256_ACCEL
|
||||
static int mpi_is_secp256r1_prime(const mbedtls_mpi *p)
|
||||
{
|
||||
u8 p_be[P256_LEN_BYTES];
|
||||
|
||||
if (!p || mbedtls_mpi_size(p) != P256_LEN_BYTES) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_write_binary(p, p_be, sizeof(p_be)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return os_memcmp(p_be, p256_p_be, sizeof(p_be)) == 0;
|
||||
}
|
||||
|
||||
static int p256_words_is_one(const u32 *a)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (a[0] != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i < P256_WORDS; i++) {
|
||||
if (a[i] != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int p256_words_cmp(const u32 *a, const u32 *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = P256_WORDS - 1; i >= 0; i--) {
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
}
|
||||
if (a[i] > b[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t p256_words_ctz(const u32 *a)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
if (a[i] != 0) {
|
||||
return i * 32 + __builtin_ctz(a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return P256_WORDS * 32;
|
||||
}
|
||||
|
||||
static void p256_words_rshift(u32 *a, size_t count)
|
||||
{
|
||||
size_t word_shift = count / 32;
|
||||
size_t bit_shift = count % 32;
|
||||
size_t i;
|
||||
|
||||
if (word_shift >= P256_WORDS) {
|
||||
os_memset(a, 0, sizeof(u32) * P256_WORDS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (word_shift > 0) {
|
||||
for (i = 0; i + word_shift < P256_WORDS; i++) {
|
||||
a[i] = a[i + word_shift];
|
||||
}
|
||||
for (; i < P256_WORDS; i++) {
|
||||
a[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bit_shift > 0) {
|
||||
for (i = 0; i < P256_WORDS - 1; i++) {
|
||||
a[i] = (a[i] >> bit_shift) |
|
||||
(a[i + 1] << (32 - bit_shift));
|
||||
}
|
||||
a[P256_WORDS - 1] >>= bit_shift;
|
||||
}
|
||||
}
|
||||
|
||||
static void p256_words_lshift(const u32 *in, size_t count, u32 *out)
|
||||
{
|
||||
size_t word_shift = count / 32;
|
||||
size_t bit_shift = count % 32;
|
||||
size_t i;
|
||||
|
||||
os_memset(out, 0, sizeof(u32) * P256_WORDS);
|
||||
|
||||
if (word_shift >= P256_WORDS) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
u64 val;
|
||||
size_t dst;
|
||||
|
||||
if (in[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dst = i + word_shift;
|
||||
if (dst >= P256_WORDS) {
|
||||
break;
|
||||
}
|
||||
|
||||
val = (u64) in[i] << bit_shift;
|
||||
out[dst] |= (u32) val;
|
||||
if (bit_shift > 0 && dst + 1 < P256_WORDS) {
|
||||
out[dst + 1] |= (u32)(val >> 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void p256_words_sub(u32 *a, const u32 *b)
|
||||
{
|
||||
size_t i;
|
||||
u64 borrow = 0;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
u64 ai = a[i];
|
||||
u64 bi = b[i];
|
||||
u64 res = ai - bi - borrow;
|
||||
|
||||
a[i] = (u32) res;
|
||||
borrow = (ai < bi + borrow) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void p256_words_swap(u32 *a, u32 *b)
|
||||
{
|
||||
u32 tmp[P256_WORDS];
|
||||
|
||||
os_memcpy(tmp, a, sizeof(tmp));
|
||||
os_memcpy(a, b, sizeof(tmp));
|
||||
os_memcpy(b, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static void p256_words_mod(u32 *a, const u32 *n)
|
||||
{
|
||||
u32 tmp[P256_WORDS];
|
||||
|
||||
while (p256_words_cmp(a, n) >= 0) {
|
||||
size_t a_bits = p256_words_bitlen(a);
|
||||
size_t n_bits = p256_words_bitlen(n);
|
||||
size_t shift = a_bits - n_bits;
|
||||
|
||||
p256_words_lshift(n, shift, tmp);
|
||||
if (p256_words_cmp(a, tmp) < 0) {
|
||||
shift--;
|
||||
p256_words_lshift(n, shift, tmp);
|
||||
}
|
||||
p256_words_sub(a, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static int crypto_bignum_mulmod_secp256r1(const mbedtls_mpi *a,
|
||||
const mbedtls_mpi *b,
|
||||
const mbedtls_mpi *mod,
|
||||
mbedtls_mpi *out)
|
||||
{
|
||||
u32 a_words[P256_WORDS];
|
||||
u32 b_words[P256_WORDS];
|
||||
u32 b_mont[P256_WORDS];
|
||||
u32 result[P256_WORDS];
|
||||
|
||||
if (!mpi_is_secp256r1_prime(mod) ||
|
||||
p256_words_from_mpi_reduced(a, a_words) != 0 ||
|
||||
p256_words_from_mpi_reduced(b, b_words) != 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
p256_mont_mul(b_mont, b_words, p256_r2_le);
|
||||
p256_mont_mul(result, a_words, b_mont);
|
||||
|
||||
return p256_words_to_mpi(result, out) == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
static int crypto_bignum_legendre_secp256r1(const mbedtls_mpi *a,
|
||||
const mbedtls_mpi *p)
|
||||
{
|
||||
u32 A[P256_WORDS];
|
||||
u32 N[P256_WORDS];
|
||||
unsigned int n_mod8;
|
||||
unsigned int a_mod4;
|
||||
unsigned int n_mod4;
|
||||
size_t two_power;
|
||||
int sign = 1;
|
||||
|
||||
if (!mpi_is_secp256r1_prime(p) ||
|
||||
p256_words_from_mpi_reduced(a, A) != 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
os_memcpy(N, p256_p_le, sizeof(N));
|
||||
|
||||
if (p256_words_is_zero(A)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!p256_words_is_zero(A)) {
|
||||
if (p256_words_is_one(A)) {
|
||||
return sign;
|
||||
}
|
||||
|
||||
n_mod8 = N[0] & 0x7;
|
||||
two_power = p256_words_ctz(A);
|
||||
if (two_power > 0) {
|
||||
p256_words_rshift(A, two_power);
|
||||
if ((n_mod8 == 3 || n_mod8 == 5) && (two_power & 1U)) {
|
||||
sign = -sign;
|
||||
}
|
||||
}
|
||||
|
||||
p256_words_swap(A, N);
|
||||
|
||||
a_mod4 = A[0] & 0x3;
|
||||
n_mod4 = N[0] & 0x3;
|
||||
if (a_mod4 == 3 && n_mod4 == 3) {
|
||||
sign = -sign;
|
||||
}
|
||||
|
||||
if (p256_words_cmp(A, N) >= 0) {
|
||||
p256_words_mod(A, N);
|
||||
}
|
||||
|
||||
if (p256_words_is_one(N)) {
|
||||
return sign;
|
||||
}
|
||||
}
|
||||
|
||||
return p256_words_is_one(N) ? sign : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct crypto_bignum *crypto_bignum_init(void)
|
||||
{
|
||||
@@ -119,7 +366,43 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *c,
|
||||
struct crypto_bignum *d)
|
||||
{
|
||||
return mbedtls_mpi_exp_mod((mbedtls_mpi *) d, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b, (const mbedtls_mpi *) c, NULL) ? -1 : 0;
|
||||
int ret;
|
||||
|
||||
/* Fast path for small public exponents frequently used in SAE math. */
|
||||
if (mbedtls_mpi_cmp_int((const mbedtls_mpi *) b, 0) >= 0 &&
|
||||
mbedtls_mpi_cmp_int((const mbedtls_mpi *) b, 3) <= 0) {
|
||||
if (mbedtls_mpi_cmp_int((const mbedtls_mpi *) b, 0) == 0) {
|
||||
ret = mbedtls_mpi_lset((mbedtls_mpi *) d, 1) ||
|
||||
mbedtls_mpi_mod_mpi((mbedtls_mpi *) d, (mbedtls_mpi *) d,
|
||||
(const mbedtls_mpi *) c);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_cmp_int((const mbedtls_mpi *) b, 1) == 0) {
|
||||
ret = mbedtls_mpi_copy((mbedtls_mpi *) d, (const mbedtls_mpi *) a) ||
|
||||
mbedtls_mpi_mod_mpi((mbedtls_mpi *) d, (mbedtls_mpi *) d,
|
||||
(const mbedtls_mpi *) c);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_cmp_int((const mbedtls_mpi *) b, 2) == 0) {
|
||||
return crypto_bignum_mulmod(a, a, c, d);
|
||||
} else {
|
||||
mbedtls_mpi tmp;
|
||||
mbedtls_mpi_init(&tmp);
|
||||
ret = crypto_bignum_mulmod(a, a, c, (struct crypto_bignum *) &tmp);
|
||||
if (ret == 0) {
|
||||
ret = crypto_bignum_mulmod((struct crypto_bignum *) &tmp,
|
||||
a, c, d);
|
||||
}
|
||||
mbedtls_mpi_free(&tmp);
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return mbedtls_mpi_exp_mod((mbedtls_mpi *) d, (const mbedtls_mpi *) a,
|
||||
(const mbedtls_mpi *) b,
|
||||
(const mbedtls_mpi *) c, NULL) ? -1 : 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -152,6 +435,15 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *c,
|
||||
struct crypto_bignum *d)
|
||||
{
|
||||
#if CONFIG_ESP_WIFI_P256_ACCEL
|
||||
int fast_ret = crypto_bignum_mulmod_secp256r1((const mbedtls_mpi *) a,
|
||||
(const mbedtls_mpi *) b,
|
||||
(const mbedtls_mpi *) c,
|
||||
(mbedtls_mpi *) d);
|
||||
if (fast_ret != -2) {
|
||||
return fast_ret;
|
||||
}
|
||||
#endif
|
||||
return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d, (const mbedtls_mpi *)a, (const mbedtls_mpi *)b) ||
|
||||
mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, (mbedtls_mpi *)d, (const mbedtls_mpi *)c) ? -1 : 0;
|
||||
}
|
||||
@@ -160,17 +452,7 @@ int crypto_bignum_sqrmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
int res;
|
||||
struct crypto_bignum *tmp = crypto_bignum_init();
|
||||
if (!tmp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mbedtls_mpi_copy((mbedtls_mpi *) tmp, (const mbedtls_mpi *) a);
|
||||
res = crypto_bignum_mulmod(a, tmp, b, c);
|
||||
|
||||
crypto_bignum_deinit(tmp, 0);
|
||||
return res ? -1 : 0;
|
||||
return crypto_bignum_mulmod(a, a, b, c);
|
||||
}
|
||||
|
||||
int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
|
||||
@@ -219,8 +501,8 @@ int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
|
||||
mbedtls_esp_random, NULL) != 0) ? -1 : 0);
|
||||
}
|
||||
|
||||
int crypto_bignum_legendre(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *p)
|
||||
static int mbedtls_bignum_legendre(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *p)
|
||||
{
|
||||
mbedtls_mpi exp, tmp;
|
||||
int res = -2, ret;
|
||||
@@ -252,6 +534,22 @@ cleanup:
|
||||
return res;
|
||||
}
|
||||
|
||||
int crypto_bignum_legendre(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *p)
|
||||
{
|
||||
#if CONFIG_ESP_WIFI_P256_ACCEL
|
||||
int legendre_res;
|
||||
|
||||
legendre_res = crypto_bignum_legendre_secp256r1((const mbedtls_mpi *) a,
|
||||
(const mbedtls_mpi *) p);
|
||||
if (legendre_res != -2) {
|
||||
return legendre_res;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mbedtls_bignum_legendre(a, p);
|
||||
}
|
||||
|
||||
int crypto_bignum_addmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
const struct crypto_bignum *c,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Shared P-256 (secp256r1) word-level and Montgomery arithmetic used by
|
||||
* both the bignum and EC fast paths. All helpers are static inline so
|
||||
* each translation unit gets its own copy without linkage issues.
|
||||
*
|
||||
* Prerequisites: the including .c file must already provide u8/u32/u64
|
||||
* typedefs, os_memcmp/os_memset/os_memcpy (via utils/common.h), and
|
||||
* mbedtls/bignum.h.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define P256_WORDS 8
|
||||
#define P256_LEN_BYTES 32
|
||||
|
||||
static const u8 p256_p_be[P256_LEN_BYTES] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
static const u32 p256_p_le[P256_WORDS] = {
|
||||
0xffffffffU, 0xffffffffU, 0xffffffffU, 0x00000000U,
|
||||
0x00000000U, 0x00000000U, 0x00000001U, 0xffffffffU
|
||||
};
|
||||
|
||||
/* R^2 mod p in little-endian word order, for Montgomery domain entry. */
|
||||
static const u32 p256_r2_le[P256_WORDS] = {
|
||||
0x00000003U, 0x00000000U, 0xffffffffU, 0xfffffffbU,
|
||||
0xfffffffeU, 0xffffffffU, 0xfffffffdU, 0x00000004U
|
||||
};
|
||||
|
||||
static inline int p256_words_is_zero(const u32 *a)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
if (a[i] != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline size_t p256_words_bitlen(const u32 *a)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = P256_WORDS - 1; i >= 0; i--) {
|
||||
if (a[i] != 0) {
|
||||
return (size_t) i * 32 + 32 - __builtin_clz(a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int p256_words_from_mpi(const mbedtls_mpi *in, u32 *out)
|
||||
{
|
||||
u8 in_be[P256_LEN_BYTES];
|
||||
size_t i;
|
||||
|
||||
if (!in || in->MBEDTLS_PRIVATE(s) < 0 ||
|
||||
mbedtls_mpi_size(in) > P256_LEN_BYTES ||
|
||||
mbedtls_mpi_write_binary(in, in_be, sizeof(in_be)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
size_t off = P256_LEN_BYTES - (i + 1) * 4;
|
||||
|
||||
out[i] = ((u32) in_be[off] << 24) |
|
||||
((u32) in_be[off + 1] << 16) |
|
||||
((u32) in_be[off + 2] << 8) |
|
||||
(u32) in_be[off + 3];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int p256_words_from_mpi_reduced(const mbedtls_mpi *in, u32 *out)
|
||||
{
|
||||
u8 in_be[P256_LEN_BYTES];
|
||||
size_t i;
|
||||
size_t in_size;
|
||||
|
||||
if (!in || in->MBEDTLS_PRIVATE(s) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
in_size = mbedtls_mpi_size(in);
|
||||
if (in_size > P256_LEN_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_write_binary(in, in_be, sizeof(in_be)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (in_size == P256_LEN_BYTES &&
|
||||
os_memcmp(in_be, p256_p_be, sizeof(in_be)) >= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
size_t off = P256_LEN_BYTES - (i + 1) * 4;
|
||||
|
||||
out[i] = ((u32) in_be[off] << 24) |
|
||||
((u32) in_be[off + 1] << 16) |
|
||||
((u32) in_be[off + 2] << 8) |
|
||||
(u32) in_be[off + 3];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int p256_words_to_mpi(const u32 *in, mbedtls_mpi *out)
|
||||
{
|
||||
u8 out_be[P256_LEN_BYTES];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
size_t off = P256_LEN_BYTES - (i + 1) * 4;
|
||||
|
||||
out_be[off] = (u8)(in[i] >> 24);
|
||||
out_be[off + 1] = (u8)(in[i] >> 16);
|
||||
out_be[off + 2] = (u8)(in[i] >> 8);
|
||||
out_be[off + 3] = (u8) in[i];
|
||||
}
|
||||
|
||||
return mbedtls_mpi_read_binary(out, out_be, sizeof(out_be));
|
||||
}
|
||||
|
||||
static inline u32 p256_words_sub_borrow(u32 *z, const u32 *x, const u32 *y)
|
||||
{
|
||||
size_t i;
|
||||
u32 borrow = 0;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
u64 diff = (u64) x[i] - y[i] - borrow;
|
||||
|
||||
z[i] = (u32) diff;
|
||||
borrow = -(u32)(diff >> 32);
|
||||
}
|
||||
|
||||
return borrow;
|
||||
}
|
||||
|
||||
static inline void p256_words_cmov(u32 *z, const u32 *x, u32 c)
|
||||
{
|
||||
size_t i;
|
||||
u32 mask = (u32) - (int) c;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
z[i] = (z[i] & ~mask) | (x[i] & mask);
|
||||
}
|
||||
}
|
||||
|
||||
static inline u64 p256_u32_muladd64(u32 x, u32 y, u32 z, u32 t)
|
||||
{
|
||||
return (u64) x * y + z + t;
|
||||
}
|
||||
|
||||
static inline u32 p256_u288_muladd(u32 z[P256_WORDS + 1], u32 x,
|
||||
const u32 y[P256_WORDS])
|
||||
{
|
||||
size_t i;
|
||||
u32 carry = 0;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
u64 prod = p256_u32_muladd64(x, y[i], z[i], carry);
|
||||
|
||||
z[i] = (u32) prod;
|
||||
carry = (u32)(prod >> 32);
|
||||
}
|
||||
|
||||
{
|
||||
u64 sum = (u64) z[P256_WORDS] + carry;
|
||||
z[P256_WORDS] = (u32) sum;
|
||||
carry = (u32)(sum >> 32);
|
||||
}
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
static inline void p256_u288_rshift32(u32 z[P256_WORDS + 1], u32 c)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
z[i] = z[i + 1];
|
||||
}
|
||||
z[P256_WORDS] = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* CIOS Montgomery multiplication for secp256r1.
|
||||
*
|
||||
* The Montgomery constant mu = -p^{-1} mod 2^{32} equals 1 for this prime
|
||||
* because p[0] = 0xFFFFFFFF, i.e. p ≡ -1 (mod 2^{32}). That simplifies
|
||||
* the reduction factor to u = new_a[0] * 1 = new_a[0], which we compute
|
||||
* early as a[0] + x[i]*y[0] (the low word of the partial accumulator after
|
||||
* the multiply step) to break the data dependency.
|
||||
*/
|
||||
static inline void p256_mont_mul(u32 z[P256_WORDS],
|
||||
const u32 x[P256_WORDS],
|
||||
const u32 y[P256_WORDS])
|
||||
{
|
||||
u32 a[P256_WORDS + 1] = {0};
|
||||
u32 reduced[P256_WORDS];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < P256_WORDS; i++) {
|
||||
u32 u = a[0] + x[i] * y[0];
|
||||
u32 c = p256_u288_muladd(a, x[i], y);
|
||||
c += p256_u288_muladd(a, u, p256_p_le);
|
||||
p256_u288_rshift32(a, c);
|
||||
}
|
||||
|
||||
{
|
||||
u32 carry_add = a[P256_WORDS];
|
||||
u32 carry_sub = p256_words_sub_borrow(reduced, a, p256_p_le);
|
||||
u32 use_sub = carry_add | (1U - carry_sub);
|
||||
|
||||
os_memcpy(z, a, sizeof(u32) * P256_WORDS);
|
||||
p256_words_cmov(z, reduced, use_sub);
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,42 @@ struct dpp_global {
|
||||
|
||||
extern struct dpp_curve_params dpp_curves[];
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
u64 dpp_last_auth_req_parse_us;
|
||||
u64 dpp_last_auth_resp_form_us;
|
||||
u64 dpp_last_auth_req_total_us;
|
||||
|
||||
static u64 dpp_time_us(void)
|
||||
{
|
||||
struct os_reltime now;
|
||||
|
||||
if (os_get_reltime(&now) < 0)
|
||||
return 0;
|
||||
|
||||
return ((u64) now.sec * 1000000) + now.usec;
|
||||
}
|
||||
|
||||
static void dpp_auth_req_set_timing(struct dpp_authentication *auth,
|
||||
u64 start_us, u64 parse_done_us)
|
||||
{
|
||||
u64 end_us;
|
||||
|
||||
if (!auth || !start_us || !parse_done_us || parse_done_us < start_us)
|
||||
return;
|
||||
|
||||
end_us = dpp_time_us();
|
||||
if (!end_us || end_us < parse_done_us)
|
||||
return;
|
||||
|
||||
auth->auth_req_parse_us = parse_done_us - start_us;
|
||||
auth->auth_resp_form_us = end_us - parse_done_us;
|
||||
auth->auth_req_total_us = end_us - start_us;
|
||||
dpp_last_auth_req_parse_us = auth->auth_req_parse_us;
|
||||
dpp_last_auth_resp_form_us = auth->auth_resp_form_us;
|
||||
dpp_last_auth_req_total_us = auth->auth_req_total_us;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TRANSACTION_ID_ATTR_SET_LEN 5
|
||||
#define CONNECTOR_ATTR_SET_LEN 4
|
||||
|
||||
@@ -1707,6 +1743,13 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
|
||||
u16 i_capab_len;
|
||||
u16 i_bootstrap_len;
|
||||
struct dpp_authentication *auth = NULL;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
u64 start_us = dpp_time_us();
|
||||
u64 parse_done_us = 0;
|
||||
dpp_last_auth_req_parse_us = 0;
|
||||
dpp_last_auth_resp_form_us = 0;
|
||||
dpp_last_auth_req_total_us = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) {
|
||||
@@ -1892,9 +1935,15 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
parse_done_us = dpp_time_us();
|
||||
#endif
|
||||
if (dpp_auth_build_resp_status(auth,
|
||||
DPP_STATUS_RESPONSE_PENDING) < 0)
|
||||
goto fail;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
dpp_auth_req_set_timing(auth, start_us, parse_done_us);
|
||||
#endif
|
||||
i_bootstrap = dpp_get_attr(attr_start, attr_len,
|
||||
DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
|
||||
&i_bootstrap_len);
|
||||
@@ -1912,8 +1961,14 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
|
||||
"%s", hex);
|
||||
return auth;
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
parse_done_us = dpp_time_us();
|
||||
#endif
|
||||
if (dpp_auth_build_resp_ok(auth) < 0)
|
||||
goto fail;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
dpp_auth_req_set_timing(auth, start_us, parse_done_us);
|
||||
#endif
|
||||
|
||||
return auth;
|
||||
|
||||
@@ -1926,8 +1981,14 @@ not_compatible:
|
||||
auth->configurator = 0;
|
||||
auth->peer_protocol_key = pi;
|
||||
pi = NULL;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
parse_done_us = dpp_time_us();
|
||||
#endif
|
||||
if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
|
||||
goto fail;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
dpp_auth_req_set_timing(auth, start_us, parse_done_us);
|
||||
#endif
|
||||
|
||||
auth->remove_on_tx_status = 1;
|
||||
return auth;
|
||||
|
||||
@@ -317,8 +317,19 @@ struct dpp_authentication {
|
||||
char *groups_override;
|
||||
unsigned int ignore_netaccesskey_mismatch:1;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
u64 auth_req_parse_us;
|
||||
u64 auth_resp_form_us;
|
||||
u64 auth_req_total_us;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
extern u64 dpp_last_auth_req_parse_us;
|
||||
extern u64 dpp_last_auth_resp_form_us;
|
||||
extern u64 dpp_last_auth_req_total_us;
|
||||
#endif
|
||||
|
||||
struct dpp_configurator {
|
||||
struct dl_list list;
|
||||
unsigned int id;
|
||||
|
||||
@@ -9,7 +9,7 @@ idf_component_register(SRCS
|
||||
"test_wpa_supplicant_main.c"
|
||||
"test_wifi_external_bss.c"
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES wpa_supplicant mbedtls esp_wifi esp_event unity esp_psram
|
||||
PRIV_REQUIRES wpa_supplicant mbedtls esp_wifi esp_event unity esp_psram esp_timer
|
||||
WHOLE_ARCHIVE)
|
||||
|
||||
idf_component_get_property(esp_supplicant_dir wpa_supplicant COMPONENT_DIR)
|
||||
@@ -25,3 +25,7 @@ target_include_directories(${COMPONENT_LIB} PRIVATE ${esp_supplicant_dir}/src)
|
||||
add_definitions(-DWIFI_SUPPLICANT_MD5=\"${WIFI_SUPPLICANT_MD5}\")
|
||||
add_definitions(-DCONFIG_WPA3_SAE)
|
||||
add_definitions(-DCONFIG_DPP)
|
||||
|
||||
if(CONFIG_ESP_WIFI_TESTING_OPTIONS)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_TESTING_OPTIONS)
|
||||
endif()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -14,12 +14,211 @@
|
||||
#include "utils/includes.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
#include "esp_timer.h"
|
||||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/pk.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_wpa_supplicant_common.h"
|
||||
|
||||
typedef struct crypto_bignum crypto_bignum;
|
||||
|
||||
static const uint8_t test_secp256r1_prime[32] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
static const uint8_t test_p256_bignum_vals[][32] = {
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,
|
||||
0xca, 0xfe, 0xba, 0xbe, 0x88, 0x99, 0xaa, 0xbb,
|
||||
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
|
||||
0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0
|
||||
},
|
||||
{
|
||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
|
||||
0x0f, 0xed, 0xcb, 0xa9, 0x87, 0x65, 0x43, 0x21,
|
||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
||||
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
|
||||
},
|
||||
{
|
||||
0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a,
|
||||
0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5,
|
||||
0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
|
||||
0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0
|
||||
}
|
||||
};
|
||||
|
||||
static const uint8_t test_p256_scalar_seeds[][32] = {
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef,
|
||||
0xca, 0xfe, 0xba, 0xbe, 0x88, 0x99, 0xaa, 0xbb,
|
||||
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
|
||||
0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0
|
||||
},
|
||||
{
|
||||
0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a,
|
||||
0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5,
|
||||
0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
|
||||
0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0
|
||||
},
|
||||
{
|
||||
0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78,
|
||||
0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0,
|
||||
0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
|
||||
0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned int test_p256_point_multipliers[] = { 7, 13 };
|
||||
static const unsigned int test_small_exponents[] = { 0, 1, 2, 3 };
|
||||
|
||||
static int test_mbedtls_rng(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
(void) ctx;
|
||||
return os_get_random(buf, len) == 0 ? 0 : MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
}
|
||||
|
||||
static void test_load_valid_p256_scalar(const mbedtls_ecp_group *grp,
|
||||
const uint8_t *seed, size_t seed_len,
|
||||
mbedtls_mpi *scalar)
|
||||
{
|
||||
mbedtls_mpi range;
|
||||
|
||||
mbedtls_mpi_init(&range);
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_sub_int(&range, &grp->N, 1));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_read_binary(scalar, seed, seed_len));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(scalar, scalar, &range));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_add_int(scalar, scalar, 1));
|
||||
mbedtls_mpi_free(&range);
|
||||
}
|
||||
|
||||
static void test_make_p256_affine_point(mbedtls_ecp_group *grp,
|
||||
unsigned int multiplier,
|
||||
mbedtls_ecp_point *point)
|
||||
{
|
||||
mbedtls_mpi k;
|
||||
|
||||
mbedtls_mpi_init(&k);
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_lset(&k, multiplier));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_ecp_mul(grp, point, &k, &grp->G,
|
||||
test_mbedtls_rng, NULL));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_cmp_int(&point->MBEDTLS_PRIVATE(Z), 1));
|
||||
mbedtls_mpi_free(&k);
|
||||
}
|
||||
|
||||
static int test_legendre_reference(const mbedtls_mpi *a, const mbedtls_mpi *p)
|
||||
{
|
||||
mbedtls_mpi a_mod, exp, res, one, pm1;
|
||||
int legendre = -2;
|
||||
|
||||
mbedtls_mpi_init(&a_mod);
|
||||
mbedtls_mpi_init(&exp);
|
||||
mbedtls_mpi_init(&res);
|
||||
mbedtls_mpi_init(&one);
|
||||
mbedtls_mpi_init(&pm1);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(&a_mod, a, p));
|
||||
if (mbedtls_mpi_cmp_int(&a_mod, 0) == 0) {
|
||||
legendre = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_copy(&exp, p));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_sub_int(&exp, &exp, 1));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_shift_r(&exp, 1));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_exp_mod(&res, &a_mod, &exp, p, NULL));
|
||||
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_lset(&one, 1));
|
||||
if (mbedtls_mpi_cmp_mpi(&res, &one) == 0) {
|
||||
legendre = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_copy(&pm1, p));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_sub_int(&pm1, &pm1, 1));
|
||||
if (mbedtls_mpi_cmp_mpi(&res, &pm1) == 0) {
|
||||
legendre = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
TEST_FAIL_MESSAGE("Unexpected Legendre reference result");
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&a_mod);
|
||||
mbedtls_mpi_free(&exp);
|
||||
mbedtls_mpi_free(&res);
|
||||
mbedtls_mpi_free(&one);
|
||||
mbedtls_mpi_free(&pm1);
|
||||
return legendre;
|
||||
}
|
||||
|
||||
static void test_print_crypto_timing(const char *label,
|
||||
int64_t generic_total_us, size_t generic_ops,
|
||||
int64_t api_total_us, size_t api_ops)
|
||||
{
|
||||
long long generic_avg = generic_ops ? (long long)(generic_total_us / (int64_t) generic_ops) : 0;
|
||||
long long api_avg = api_ops ? (long long)(api_total_us / (int64_t) api_ops) : 0;
|
||||
|
||||
printf("%s timing(us): generic_avg=%lld api_avg=%lld generic_total=%lld api_total=%lld ops=%u\n",
|
||||
label, generic_avg, api_avg,
|
||||
(long long) generic_total_us, (long long) api_total_us,
|
||||
(unsigned int) api_ops);
|
||||
}
|
||||
|
||||
static int test_mbedtls_ecdh(const struct crypto_ec_key *key_own,
|
||||
const struct crypto_ec_key *key_peer,
|
||||
u8 *secret, size_t *secret_len)
|
||||
{
|
||||
mbedtls_ecdh_context ctx;
|
||||
mbedtls_pk_context *own = (mbedtls_pk_context *) key_own;
|
||||
mbedtls_pk_context *peer = (mbedtls_pk_context *) key_peer;
|
||||
int ret = -1;
|
||||
|
||||
mbedtls_ecdh_init(&ctx);
|
||||
|
||||
if (mbedtls_ecdh_get_params(&ctx, mbedtls_pk_ec(*own),
|
||||
MBEDTLS_ECDH_OURS) != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mbedtls_ecdh_get_params(&ctx, mbedtls_pk_ec(*peer),
|
||||
MBEDTLS_ECDH_THEIRS) != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mbedtls_ecdh_calc_secret(&ctx, secret_len, secret, 66,
|
||||
test_mbedtls_rng, NULL) != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
mbedtls_ecdh_free(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_mbedtls_key_gen_p256(mbedtls_pk_context *kctx)
|
||||
{
|
||||
mbedtls_pk_init(kctx);
|
||||
|
||||
if (mbedtls_pk_setup(kctx,
|
||||
mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(*kctx),
|
||||
test_mbedtls_rng, NULL) != 0) {
|
||||
mbedtls_pk_free(kctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]")
|
||||
{
|
||||
set_leak_threshold(300);
|
||||
@@ -203,6 +402,38 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]")
|
||||
|
||||
}
|
||||
|
||||
{ /** BN mul mod on secp256r1 prime */
|
||||
uint8_t val[32];
|
||||
uint8_t one[32] = {0};
|
||||
crypto_bignum *bn1, *bn2, *bn3, *mulmod;
|
||||
|
||||
one[0] = 1;
|
||||
os_memcpy(val, test_secp256r1_prime, sizeof(val));
|
||||
val[31]--;
|
||||
|
||||
mulmod = crypto_bignum_init();
|
||||
TEST_ASSERT_NOT_NULL(mulmod);
|
||||
|
||||
bn1 = crypto_bignum_init_set(val, sizeof(val));
|
||||
TEST_ASSERT_NOT_NULL(bn1);
|
||||
|
||||
bn2 = crypto_bignum_init_set(val, sizeof(val));
|
||||
TEST_ASSERT_NOT_NULL(bn2);
|
||||
|
||||
bn3 = crypto_bignum_init_set(test_secp256r1_prime,
|
||||
sizeof(test_secp256r1_prime));
|
||||
TEST_ASSERT_NOT_NULL(bn3);
|
||||
|
||||
TEST_ASSERT(crypto_bignum_mulmod(bn1, bn2, bn3, mulmod) == 0);
|
||||
TEST_ASSERT(crypto_bignum_to_bin(mulmod, val, sizeof(val), 0) == 1);
|
||||
TEST_ASSERT_EQUAL_UINT8_ARRAY(one, val, 1);
|
||||
|
||||
crypto_bignum_deinit(bn1, 1);
|
||||
crypto_bignum_deinit(bn2, 1);
|
||||
crypto_bignum_deinit(bn3, 1);
|
||||
crypto_bignum_deinit(mulmod, 1);
|
||||
}
|
||||
|
||||
{ /** BN exp mod*/
|
||||
uint8_t buf1[32], buf2[32], buf3[32], buf4[32], buf5[32];
|
||||
|
||||
@@ -273,6 +504,84 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]")
|
||||
crypto_bignum_deinit(bn2, 1);
|
||||
|
||||
}
|
||||
|
||||
{ /** BN Legendre symbol test on secp256r1 prime */
|
||||
uint8_t val[32] = {0};
|
||||
crypto_bignum *bn_val, *bn_p;
|
||||
|
||||
bn_p = crypto_bignum_init_set(test_secp256r1_prime,
|
||||
sizeof(test_secp256r1_prime));
|
||||
TEST_ASSERT_NOT_NULL(bn_p);
|
||||
|
||||
val[31] = 1;
|
||||
bn_val = crypto_bignum_init_set(val, sizeof(val));
|
||||
TEST_ASSERT_NOT_NULL(bn_val);
|
||||
TEST_ASSERT(crypto_bignum_legendre(bn_val, bn_p) == 1);
|
||||
crypto_bignum_deinit(bn_val, 1);
|
||||
|
||||
os_memset(val, 0, sizeof(val));
|
||||
val[31] = 3;
|
||||
bn_val = crypto_bignum_init_set(val, sizeof(val));
|
||||
TEST_ASSERT_NOT_NULL(bn_val);
|
||||
TEST_ASSERT(crypto_bignum_legendre(bn_val, bn_p) == -1);
|
||||
crypto_bignum_deinit(bn_val, 1);
|
||||
|
||||
os_memset(val, 0, sizeof(val));
|
||||
bn_val = crypto_bignum_init_set(val, sizeof(val));
|
||||
TEST_ASSERT_NOT_NULL(bn_val);
|
||||
TEST_ASSERT(crypto_bignum_legendre(bn_val, bn_p) == 0);
|
||||
crypto_bignum_deinit(bn_val, 1);
|
||||
|
||||
crypto_bignum_deinit(bn_p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test secp256r1 fast bignum paths against mbedtls reference", "[wpa_crypto]")
|
||||
{
|
||||
crypto_bignum *bn_p;
|
||||
int i;
|
||||
|
||||
set_leak_threshold(620);
|
||||
|
||||
bn_p = crypto_bignum_init_set(test_secp256r1_prime,
|
||||
sizeof(test_secp256r1_prime));
|
||||
TEST_ASSERT_NOT_NULL(bn_p);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_p256_bignum_vals); i++) {
|
||||
crypto_bignum *bn_a = crypto_bignum_init_set(test_p256_bignum_vals[i], sizeof(test_p256_bignum_vals[i]));
|
||||
crypto_bignum *bn_b = crypto_bignum_init_set(
|
||||
test_p256_bignum_vals[(i + 1) % ARRAY_SIZE(test_p256_bignum_vals)],
|
||||
sizeof(test_p256_bignum_vals[0]));
|
||||
crypto_bignum *bn_mul = crypto_bignum_init();
|
||||
mbedtls_mpi ref_mul;
|
||||
int ref_legendre;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(bn_a);
|
||||
TEST_ASSERT_NOT_NULL(bn_b);
|
||||
TEST_ASSERT_NOT_NULL(bn_mul);
|
||||
|
||||
mbedtls_mpi_init(&ref_mul);
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mul_mpi(&ref_mul,
|
||||
(const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_b));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(&ref_mul, &ref_mul,
|
||||
(const mbedtls_mpi *) bn_p));
|
||||
|
||||
TEST_ASSERT_EQUAL(0, crypto_bignum_mulmod(bn_a, bn_b, bn_p, bn_mul));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) bn_mul,
|
||||
&ref_mul));
|
||||
|
||||
ref_legendre = test_legendre_reference((const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_p);
|
||||
TEST_ASSERT_EQUAL(ref_legendre, crypto_bignum_legendre(bn_a, bn_p));
|
||||
|
||||
mbedtls_mpi_free(&ref_mul);
|
||||
crypto_bignum_deinit(bn_a, 1);
|
||||
crypto_bignum_deinit(bn_b, 1);
|
||||
crypto_bignum_deinit(bn_mul, 1);
|
||||
}
|
||||
|
||||
crypto_bignum_deinit(bn_p, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -536,3 +845,385 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Test secp256r1 point multiply against mbedtls reference", "[wpa_crypto]")
|
||||
{
|
||||
struct crypto_ec *e;
|
||||
struct crypto_ec_point *p = NULL;
|
||||
struct crypto_ec_point *res = NULL;
|
||||
mbedtls_ecp_point ref;
|
||||
int i, j;
|
||||
|
||||
set_leak_threshold(620);
|
||||
|
||||
e = crypto_ec_init(19);
|
||||
TEST_ASSERT_NOT_NULL(e);
|
||||
|
||||
p = crypto_ec_point_init(e);
|
||||
TEST_ASSERT_NOT_NULL(p);
|
||||
res = crypto_ec_point_init(e);
|
||||
TEST_ASSERT_NOT_NULL(res);
|
||||
mbedtls_ecp_point_init(&ref);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_p256_point_multipliers); i++) {
|
||||
test_make_p256_affine_point((mbedtls_ecp_group *) e,
|
||||
test_p256_point_multipliers[i],
|
||||
(mbedtls_ecp_point *) p);
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(test_p256_scalar_seeds); j++) {
|
||||
mbedtls_mpi scalar;
|
||||
|
||||
mbedtls_mpi_init(&scalar);
|
||||
test_load_valid_p256_scalar((const mbedtls_ecp_group *) e,
|
||||
test_p256_scalar_seeds[j],
|
||||
sizeof(test_p256_scalar_seeds[j]),
|
||||
&scalar);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, crypto_ec_point_mul(e, p,
|
||||
(struct crypto_bignum *) &scalar,
|
||||
res));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_ecp_mul((mbedtls_ecp_group *) e,
|
||||
&ref, &scalar,
|
||||
(const mbedtls_ecp_point *) p,
|
||||
test_mbedtls_rng, NULL));
|
||||
TEST_ASSERT_EQUAL(0, crypto_ec_point_cmp(e, res,
|
||||
(const struct crypto_ec_point *) &ref));
|
||||
|
||||
mbedtls_mpi_free(&scalar);
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_ecp_point_free(&ref);
|
||||
crypto_ec_point_deinit(p, 1);
|
||||
crypto_ec_point_deinit(res, 1);
|
||||
crypto_ec_deinit(e);
|
||||
}
|
||||
|
||||
TEST_CASE("Measure secp256r1 bignum API timings against mbedtls reference", "[wpa_crypto]")
|
||||
{
|
||||
const unsigned int loops = 64;
|
||||
crypto_bignum *bn_p;
|
||||
int64_t generic_total_us = 0;
|
||||
int64_t api_total_us = 0;
|
||||
size_t ops = 0;
|
||||
int i, loop;
|
||||
|
||||
set_leak_threshold(700);
|
||||
|
||||
bn_p = crypto_bignum_init_set(test_secp256r1_prime,
|
||||
sizeof(test_secp256r1_prime));
|
||||
TEST_ASSERT_NOT_NULL(bn_p);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_p256_bignum_vals); i++) {
|
||||
crypto_bignum *bn_a = crypto_bignum_init_set(test_p256_bignum_vals[i],
|
||||
sizeof(test_p256_bignum_vals[i]));
|
||||
crypto_bignum *bn_b = crypto_bignum_init_set(
|
||||
test_p256_bignum_vals[(i + 1) % ARRAY_SIZE(test_p256_bignum_vals)],
|
||||
sizeof(test_p256_bignum_vals[0]));
|
||||
crypto_bignum *bn_mul = crypto_bignum_init();
|
||||
mbedtls_mpi ref_mul;
|
||||
int ref_legendre;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(bn_a);
|
||||
TEST_ASSERT_NOT_NULL(bn_b);
|
||||
TEST_ASSERT_NOT_NULL(bn_mul);
|
||||
|
||||
mbedtls_mpi_init(&ref_mul);
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mul_mpi(&ref_mul,
|
||||
(const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_b));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(&ref_mul, &ref_mul,
|
||||
(const mbedtls_mpi *) bn_p));
|
||||
TEST_ASSERT_EQUAL(0, crypto_bignum_mulmod(bn_a, bn_b, bn_p, bn_mul));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) bn_mul,
|
||||
&ref_mul));
|
||||
ref_legendre = test_legendre_reference((const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_p);
|
||||
TEST_ASSERT_EQUAL(ref_legendre, crypto_bignum_legendre(bn_a, bn_p));
|
||||
|
||||
for (loop = 0; loop < loops; loop++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mul_mpi(&ref_mul,
|
||||
(const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_b));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(&ref_mul, &ref_mul,
|
||||
(const mbedtls_mpi *) bn_p));
|
||||
generic_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
for (loop = 0; loop < loops; loop++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
TEST_ASSERT_EQUAL(0, crypto_bignum_mulmod(bn_a, bn_b, bn_p, bn_mul));
|
||||
api_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
ops += loops;
|
||||
mbedtls_mpi_free(&ref_mul);
|
||||
crypto_bignum_deinit(bn_a, 1);
|
||||
crypto_bignum_deinit(bn_b, 1);
|
||||
crypto_bignum_deinit(bn_mul, 1);
|
||||
}
|
||||
|
||||
test_print_crypto_timing("secp256r1 mulmod", generic_total_us, ops,
|
||||
api_total_us, ops);
|
||||
|
||||
generic_total_us = 0;
|
||||
api_total_us = 0;
|
||||
ops = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_small_exponents); i++) {
|
||||
crypto_bignum *bn_exp = crypto_bignum_init_uint(test_small_exponents[i]);
|
||||
char label[48];
|
||||
|
||||
TEST_ASSERT_NOT_NULL(bn_exp);
|
||||
|
||||
generic_total_us = 0;
|
||||
api_total_us = 0;
|
||||
ops = 0;
|
||||
|
||||
for (loop = 0; loop < ARRAY_SIZE(test_p256_bignum_vals); loop++) {
|
||||
crypto_bignum *bn_a = crypto_bignum_init_set(test_p256_bignum_vals[loop],
|
||||
sizeof(test_p256_bignum_vals[loop]));
|
||||
crypto_bignum *bn_res = crypto_bignum_init();
|
||||
mbedtls_mpi ref_res;
|
||||
int iter;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(bn_a);
|
||||
TEST_ASSERT_NOT_NULL(bn_res);
|
||||
|
||||
mbedtls_mpi_init(&ref_res);
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_exp_mod(&ref_res,
|
||||
(const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_exp,
|
||||
(const mbedtls_mpi *) bn_p,
|
||||
NULL));
|
||||
TEST_ASSERT_EQUAL(0, crypto_bignum_exptmod(bn_a, bn_exp, bn_p,
|
||||
bn_res));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) bn_res,
|
||||
&ref_res));
|
||||
|
||||
for (iter = 0; iter < loops; iter++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_mpi_exp_mod(&ref_res,
|
||||
(const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_exp,
|
||||
(const mbedtls_mpi *) bn_p,
|
||||
NULL));
|
||||
generic_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
for (iter = 0; iter < loops; iter++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
TEST_ASSERT_EQUAL(0, crypto_bignum_exptmod(bn_a, bn_exp, bn_p,
|
||||
bn_res));
|
||||
api_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
ops += loops;
|
||||
mbedtls_mpi_free(&ref_res);
|
||||
crypto_bignum_deinit(bn_a, 1);
|
||||
crypto_bignum_deinit(bn_res, 1);
|
||||
}
|
||||
|
||||
snprintf(label, sizeof(label), "secp256r1 exptmod e=%u",
|
||||
test_small_exponents[i]);
|
||||
test_print_crypto_timing(label, generic_total_us, ops,
|
||||
api_total_us, ops);
|
||||
crypto_bignum_deinit(bn_exp, 1);
|
||||
}
|
||||
|
||||
generic_total_us = 0;
|
||||
api_total_us = 0;
|
||||
ops = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_p256_bignum_vals); i++) {
|
||||
crypto_bignum *bn_a = crypto_bignum_init_set(test_p256_bignum_vals[i],
|
||||
sizeof(test_p256_bignum_vals[i]));
|
||||
TEST_ASSERT_NOT_NULL(bn_a);
|
||||
|
||||
TEST_ASSERT_EQUAL(test_legendre_reference((const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_p),
|
||||
crypto_bignum_legendre(bn_a, bn_p));
|
||||
|
||||
for (loop = 0; loop < loops; loop++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
(void) test_legendre_reference((const mbedtls_mpi *) bn_a,
|
||||
(const mbedtls_mpi *) bn_p);
|
||||
generic_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
for (loop = 0; loop < loops; loop++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
(void) crypto_bignum_legendre(bn_a, bn_p);
|
||||
api_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
ops += loops;
|
||||
crypto_bignum_deinit(bn_a, 1);
|
||||
}
|
||||
|
||||
test_print_crypto_timing("secp256r1 legendre", generic_total_us, ops,
|
||||
api_total_us, ops);
|
||||
|
||||
crypto_bignum_deinit(bn_p, 1);
|
||||
}
|
||||
|
||||
TEST_CASE("Measure secp256r1 EC API timings against mbedtls reference", "[wpa_crypto]")
|
||||
{
|
||||
const unsigned int point_mul_loops = 4;
|
||||
const unsigned int key_gen_loops = 4;
|
||||
const unsigned int ecdh_loops = 4;
|
||||
struct crypto_ec *e;
|
||||
struct crypto_ec_point *p = NULL;
|
||||
struct crypto_ec_point *res = NULL;
|
||||
mbedtls_ecp_point ref;
|
||||
int64_t generic_total_us = 0;
|
||||
int64_t api_total_us = 0;
|
||||
size_t ops = 0;
|
||||
int i, j, loop;
|
||||
|
||||
set_leak_threshold(900);
|
||||
|
||||
e = crypto_ec_init(19);
|
||||
TEST_ASSERT_NOT_NULL(e);
|
||||
|
||||
p = crypto_ec_point_init(e);
|
||||
TEST_ASSERT_NOT_NULL(p);
|
||||
res = crypto_ec_point_init(e);
|
||||
TEST_ASSERT_NOT_NULL(res);
|
||||
mbedtls_ecp_point_init(&ref);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_p256_point_multipliers); i++) {
|
||||
test_make_p256_affine_point((mbedtls_ecp_group *) e,
|
||||
test_p256_point_multipliers[i],
|
||||
(mbedtls_ecp_point *) p);
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(test_p256_scalar_seeds); j++) {
|
||||
mbedtls_mpi scalar;
|
||||
|
||||
mbedtls_mpi_init(&scalar);
|
||||
test_load_valid_p256_scalar((const mbedtls_ecp_group *) e,
|
||||
test_p256_scalar_seeds[j],
|
||||
sizeof(test_p256_scalar_seeds[j]),
|
||||
&scalar);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, crypto_ec_point_mul(e, p,
|
||||
(struct crypto_bignum *) &scalar,
|
||||
res));
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_ecp_mul((mbedtls_ecp_group *) e,
|
||||
&ref, &scalar,
|
||||
(const mbedtls_ecp_point *) p,
|
||||
test_mbedtls_rng, NULL));
|
||||
TEST_ASSERT_EQUAL(0, crypto_ec_point_cmp(e, res,
|
||||
(const struct crypto_ec_point *) &ref));
|
||||
|
||||
for (loop = 0; loop < point_mul_loops; loop++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
TEST_ASSERT_EQUAL(0, mbedtls_ecp_mul((mbedtls_ecp_group *) e,
|
||||
&ref, &scalar,
|
||||
(const mbedtls_ecp_point *) p,
|
||||
test_mbedtls_rng, NULL));
|
||||
generic_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
for (loop = 0; loop < point_mul_loops; loop++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
TEST_ASSERT_EQUAL(0, crypto_ec_point_mul(e, p,
|
||||
(struct crypto_bignum *) &scalar,
|
||||
res));
|
||||
api_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
ops += point_mul_loops;
|
||||
mbedtls_mpi_free(&scalar);
|
||||
}
|
||||
}
|
||||
|
||||
test_print_crypto_timing("secp256r1 point_mul", generic_total_us, ops,
|
||||
api_total_us, ops);
|
||||
|
||||
generic_total_us = 0;
|
||||
api_total_us = 0;
|
||||
|
||||
for (loop = 0; loop < key_gen_loops; loop++) {
|
||||
mbedtls_pk_context kctx;
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
TEST_ASSERT_EQUAL(0, test_mbedtls_key_gen_p256(&kctx));
|
||||
generic_total_us += esp_timer_get_time() - start_us;
|
||||
mbedtls_pk_free(&kctx);
|
||||
}
|
||||
|
||||
for (loop = 0; loop < key_gen_loops; loop++) {
|
||||
struct crypto_ec_key *key;
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
|
||||
key = crypto_ec_key_gen(19);
|
||||
TEST_ASSERT_NOT_NULL(key);
|
||||
api_total_us += esp_timer_get_time() - start_us;
|
||||
crypto_ec_key_deinit(key);
|
||||
}
|
||||
|
||||
test_print_crypto_timing("secp256r1 key_gen", generic_total_us, key_gen_loops,
|
||||
api_total_us, key_gen_loops);
|
||||
|
||||
{
|
||||
struct crypto_ec_key *key_own = crypto_ec_key_gen(19);
|
||||
struct crypto_ec_key *key_peer = crypto_ec_key_gen(19);
|
||||
u8 secret_generic[66];
|
||||
u8 secret_api[66];
|
||||
size_t secret_generic_len = 0;
|
||||
size_t secret_api_len = 0;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(key_own);
|
||||
TEST_ASSERT_NOT_NULL(key_peer);
|
||||
TEST_ASSERT_EQUAL(0, test_mbedtls_ecdh(key_own, key_peer,
|
||||
secret_generic,
|
||||
&secret_generic_len));
|
||||
TEST_ASSERT_EQUAL(0, crypto_ecdh(key_own, key_peer,
|
||||
secret_api, &secret_api_len));
|
||||
TEST_ASSERT_EQUAL(secret_generic_len, secret_api_len);
|
||||
TEST_ASSERT_EQUAL_MEMORY(secret_generic, secret_api, secret_api_len);
|
||||
|
||||
generic_total_us = 0;
|
||||
api_total_us = 0;
|
||||
|
||||
for (loop = 0; loop < ecdh_loops; loop++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
size_t secret_len = 0;
|
||||
|
||||
TEST_ASSERT_EQUAL(0, test_mbedtls_ecdh(key_own, key_peer,
|
||||
secret_generic,
|
||||
&secret_len));
|
||||
generic_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
for (loop = 0; loop < ecdh_loops; loop++) {
|
||||
int64_t start_us = esp_timer_get_time();
|
||||
size_t secret_len = 0;
|
||||
|
||||
TEST_ASSERT_EQUAL(0, crypto_ecdh(key_own, key_peer,
|
||||
secret_api, &secret_len));
|
||||
api_total_us += esp_timer_get_time() - start_us;
|
||||
}
|
||||
|
||||
test_print_crypto_timing("secp256r1 ecdh", generic_total_us, ecdh_loops,
|
||||
api_total_us, ecdh_loops);
|
||||
|
||||
crypto_ec_key_deinit(key_own);
|
||||
crypto_ec_key_deinit(key_peer);
|
||||
}
|
||||
|
||||
mbedtls_ecp_point_free(&ref);
|
||||
crypto_ec_point_deinit(p, 1);
|
||||
crypto_ec_point_deinit(res, 1);
|
||||
crypto_ec_deinit(e);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,8 +18,16 @@
|
||||
#include "common/dpp.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "test_wpa_supplicant_common.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_TESTING_OPTIONS
|
||||
static unsigned int dpp_test_task_stack_high_watermark_bytes(void)
|
||||
{
|
||||
return (unsigned int)(uxTaskGetStackHighWaterMark(NULL) *
|
||||
sizeof(StackType_t));
|
||||
}
|
||||
|
||||
struct dpp_global {
|
||||
void *msg_ctx;
|
||||
struct dl_list bootstrap; /* struct dpp_bootstrap_info */
|
||||
@@ -32,9 +40,46 @@ extern u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
|
||||
extern size_t dpp_nonce_override_len;
|
||||
#define MAX_FRAME_SIZE 1200
|
||||
|
||||
static void dpp_test_clear_overrides(void)
|
||||
{
|
||||
dpp_protocol_key_override_len = 0;
|
||||
dpp_nonce_override_len = 0;
|
||||
os_memset(dpp_protocol_key_override, 0, sizeof(dpp_protocol_key_override));
|
||||
os_memset(dpp_nonce_override, 0, sizeof(dpp_nonce_override));
|
||||
}
|
||||
|
||||
static u32 dpp_test_prod_limit_us(void)
|
||||
{
|
||||
#if CONFIG_MBEDTLS_HARDWARE_ECC
|
||||
return 200000;
|
||||
#else
|
||||
return 425000;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int dpp_test_leak_threshold(void)
|
||||
{
|
||||
return 800;
|
||||
}
|
||||
|
||||
static void dpp_test_log_auth_timing(const char *label,
|
||||
const struct dpp_authentication *auth)
|
||||
{
|
||||
TEST_ASSERT_NOT_NULL(auth);
|
||||
|
||||
ESP_LOGI("DPP Test",
|
||||
"%s timing(us): parse=%llu response_form=%llu total=%llu",
|
||||
label,
|
||||
(unsigned long long) auth->auth_req_parse_us,
|
||||
(unsigned long long) auth->auth_resp_form_us,
|
||||
(unsigned long long) auth->auth_req_total_us);
|
||||
ESP_LOGI("DPP Test", "%s task stack high watermark(bytes): %u",
|
||||
label, dpp_test_task_stack_high_watermark_bytes());
|
||||
}
|
||||
|
||||
TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]")
|
||||
{
|
||||
set_leak_threshold(130);
|
||||
set_leak_threshold(dpp_test_leak_threshold());
|
||||
/* Global variables */
|
||||
char command[1200] = {0};
|
||||
const u8 *frame;
|
||||
@@ -66,6 +111,10 @@ TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]")
|
||||
sprintf(command, "type=qrcode key=%s", key);
|
||||
id = dpp_bootstrap_gen(dpp, command);
|
||||
uri = dpp_bootstrap_get_uri(dpp, id);
|
||||
if (uri == NULL) {
|
||||
ESP_LOGE("DPP Test", "Failed to get URI from bootstrap id");
|
||||
TEST_ASSERT(0);
|
||||
}
|
||||
printf("uri is =%s\n", uri);
|
||||
printf("is be =%s\n", bootstrap_info);
|
||||
TEST_ASSERT((strcmp(uri, bootstrap_info) == 0));
|
||||
@@ -129,6 +178,9 @@ TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]")
|
||||
len -= 26;
|
||||
auth_instance = dpp_auth_req_rx(NULL, 1, 0, NULL,
|
||||
dpp_bootstrap_get_id(dpp, id), 2412, frame, frame + 6, len - 6);
|
||||
TEST_ASSERT_NOT_NULL(auth_instance);
|
||||
TEST_ASSERT_NOT_NULL(auth_instance->resp_msg);
|
||||
dpp_test_log_auth_timing("Vector responder", auth_instance);
|
||||
|
||||
/* auth response u8 */
|
||||
hex_len = os_strlen(auth_resp);
|
||||
@@ -172,7 +224,118 @@ TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]")
|
||||
{
|
||||
dpp_auth_deinit(auth_instance);
|
||||
dpp_global_deinit(dpp);
|
||||
dpp_test_clear_overrides();
|
||||
}
|
||||
ESP_LOGI("DPP Test", "Test case passed");
|
||||
}
|
||||
|
||||
TEST_CASE("Test DPP responder p256 production timing", "[wpa_dpp][performance]")
|
||||
{
|
||||
struct dpp_global_config dpp_conf;
|
||||
struct dpp_global *dpp = NULL;
|
||||
struct dpp_bootstrap_info *responder_bi = NULL;
|
||||
struct dpp_bootstrap_info *initiator_bi = NULL;
|
||||
struct dpp_authentication *initiator_auth = NULL;
|
||||
struct dpp_authentication *responder_auth = NULL;
|
||||
struct wpabuf *conf = NULL;
|
||||
const u8 *frame;
|
||||
size_t len;
|
||||
int responder_id;
|
||||
int initiator_id;
|
||||
u32 limit_us = dpp_test_prod_limit_us();
|
||||
u64 total_us = 0;
|
||||
const char *failure = NULL;
|
||||
|
||||
set_leak_threshold(dpp_test_leak_threshold());
|
||||
os_memset(&dpp_conf, 0, sizeof(dpp_conf));
|
||||
dpp = dpp_global_init(&dpp_conf);
|
||||
if (!dpp) {
|
||||
TEST_FAIL_MESSAGE("Failed to initialize DPP global context");
|
||||
}
|
||||
|
||||
responder_id = dpp_bootstrap_gen(dpp, "type=qrcode curve=P-256");
|
||||
if (responder_id <= 0) {
|
||||
failure = "Failed to generate responder bootstrap";
|
||||
goto cleanup;
|
||||
}
|
||||
initiator_id = dpp_bootstrap_gen(dpp, "type=qrcode curve=P-256");
|
||||
if (initiator_id <= 0) {
|
||||
failure = "Failed to generate initiator bootstrap";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
responder_bi = dpp_bootstrap_get_id(dpp, responder_id);
|
||||
initiator_bi = dpp_bootstrap_get_id(dpp, initiator_id);
|
||||
if (!responder_bi || !initiator_bi) {
|
||||
failure = "Failed to resolve bootstrap info";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dpp_test_clear_overrides();
|
||||
initiator_auth = dpp_auth_init(NULL, responder_bi, initiator_bi,
|
||||
DPP_CAPAB_CONFIGURATOR, 2412, NULL, 0);
|
||||
if (!initiator_auth || !initiator_auth->req_msg) {
|
||||
failure = "Failed to initialize DPP initiator authentication";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
frame = wpabuf_head_u8(initiator_auth->req_msg) + 2;
|
||||
len = wpabuf_len(initiator_auth->req_msg) - 2;
|
||||
responder_auth = dpp_auth_req_rx(NULL, DPP_CAPAB_ENROLLEE, 0,
|
||||
NULL, responder_bi, 2412,
|
||||
frame, frame + DPP_HDR_LEN,
|
||||
len - DPP_HDR_LEN);
|
||||
if (!responder_auth || !responder_auth->resp_msg) {
|
||||
failure = "Failed to process DPP authentication request";
|
||||
goto cleanup;
|
||||
}
|
||||
dpp_test_log_auth_timing("Production responder", responder_auth);
|
||||
total_us = responder_auth->auth_req_total_us;
|
||||
if (limit_us) {
|
||||
ESP_LOGI("DPP Test",
|
||||
"Production responder timing gate(us): total=%llu limit=%u",
|
||||
(unsigned long long) total_us,
|
||||
limit_us);
|
||||
}
|
||||
|
||||
frame = wpabuf_head_u8(responder_auth->resp_msg) + 2;
|
||||
len = wpabuf_len(responder_auth->resp_msg) - 2;
|
||||
conf = dpp_auth_resp_rx(initiator_auth, frame, frame + DPP_HDR_LEN,
|
||||
len - DPP_HDR_LEN);
|
||||
if (!conf) {
|
||||
failure = "Failed to process DPP authentication response";
|
||||
goto cleanup;
|
||||
}
|
||||
if (initiator_auth->auth_success != 1) {
|
||||
failure = "Initiator authentication did not complete successfully";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
frame = wpabuf_head_u8(conf) + 2;
|
||||
len = wpabuf_len(conf) - 2;
|
||||
if (dpp_auth_conf_rx(responder_auth, frame, frame + DPP_HDR_LEN,
|
||||
len - DPP_HDR_LEN) != 0) {
|
||||
failure = "Failed to process DPP authentication confirmation";
|
||||
goto cleanup;
|
||||
}
|
||||
if (responder_auth->auth_success != 1) {
|
||||
failure = "Responder authentication did not complete successfully";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
wpabuf_free(conf);
|
||||
dpp_auth_deinit(responder_auth);
|
||||
dpp_auth_deinit(initiator_auth);
|
||||
dpp_global_deinit(dpp);
|
||||
dpp_test_clear_overrides();
|
||||
|
||||
if (failure) {
|
||||
TEST_FAIL_MESSAGE(failure);
|
||||
}
|
||||
if (limit_us) {
|
||||
TEST_ASSERT_MESSAGE(total_us <= limit_us,
|
||||
"DPP responder production timing regression");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -20,9 +20,41 @@
|
||||
#include "utils/wpabuf.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_wpa_supplicant_common.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
typedef struct crypto_bignum crypto_bignum;
|
||||
|
||||
static unsigned int test_task_stack_high_watermark_bytes(void)
|
||||
{
|
||||
return (unsigned int)(uxTaskGetStackHighWaterMark(NULL) *
|
||||
sizeof(StackType_t));
|
||||
}
|
||||
|
||||
static int sae_commit_parse_limit_us(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return 400000;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
return 300000;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
return 380000;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
return 340000;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
return 130000;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
return 180000;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C61
|
||||
return 200000;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
return 230000;
|
||||
#else
|
||||
return 230000;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct wpabuf *wpabuf_alloc2(size_t len)
|
||||
{
|
||||
struct wpabuf *buf = (struct wpabuf *)os_zalloc(sizeof(struct wpabuf) + len);
|
||||
@@ -233,26 +265,52 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
|
||||
u8 pwd[] = "ESP32-WPA3";
|
||||
struct wpabuf *buf;
|
||||
int default_groups[] = { IANA_SECP256R1, 0 };
|
||||
int64_t start_us;
|
||||
int64_t total_start_us;
|
||||
int64_t total_us;
|
||||
int64_t prepare_us;
|
||||
int64_t write_us;
|
||||
int64_t parse_us;
|
||||
int64_t formation_us;
|
||||
int limit_us = sae_commit_parse_limit_us();
|
||||
|
||||
memset(&sae, 0, sizeof(sae));
|
||||
total_start_us = esp_timer_get_time();
|
||||
|
||||
TEST_ASSERT(sae_set_group(&sae, IANA_SECP256R1) == 0);
|
||||
|
||||
start_us = esp_timer_get_time();
|
||||
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), &sae) == 0);
|
||||
prepare_us = esp_timer_get_time() - start_us;
|
||||
|
||||
buf = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
|
||||
|
||||
TEST_ASSERT(buf != NULL);
|
||||
|
||||
start_us = esp_timer_get_time();
|
||||
sae_write_commit(&sae, buf, NULL, NULL);// No anti-clogging token
|
||||
write_us = esp_timer_get_time() - start_us;
|
||||
formation_us = prepare_us + write_us;
|
||||
|
||||
/* Parsing commit created by self will be detected as reflection attack*/
|
||||
start_us = esp_timer_get_time();
|
||||
TEST_ASSERT(sae_parse_commit(&sae,
|
||||
wpabuf_mhead(buf), buf->used, NULL, 0, default_groups, 0) == SAE_SILENTLY_DISCARD);
|
||||
parse_us = esp_timer_get_time() - start_us;
|
||||
|
||||
wpabuf_free2(buf);
|
||||
sae_clear_temp_data(&sae);
|
||||
sae_clear_data(&sae);
|
||||
total_us = esp_timer_get_time() - total_start_us;
|
||||
|
||||
ESP_LOGI("SAE Test",
|
||||
"Commit/parse timing(us): prepare=%lld write=%lld formation=%lld parse=%lld total=%lld limit=%d",
|
||||
(long long) prepare_us, (long long) write_us,
|
||||
(long long) formation_us, (long long) parse_us,
|
||||
(long long) total_us, limit_us);
|
||||
ESP_LOGI("SAE Test", "Task stack high watermark(bytes): %u",
|
||||
test_task_stack_high_watermark_bytes());
|
||||
TEST_ASSERT_MESSAGE(total_us <= limit_us, "SAE commit/parse timing regression");
|
||||
|
||||
}
|
||||
ESP_LOGI("SAE Test", "=========== Complete ============");
|
||||
|
||||
@@ -30,7 +30,7 @@ static void check_leak(size_t before_free, size_t after_free, const char *type)
|
||||
{
|
||||
ssize_t delta = after_free - before_free;
|
||||
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d, threshold %d)\n", type, before_free, after_free, delta, leak_threshold);
|
||||
TEST_ASSERT_MESSAGE(delta > leak_threshold, "memory leak");
|
||||
TEST_ASSERT_MESSAGE(delta >= leak_threshold, "memory leak");
|
||||
}
|
||||
|
||||
#if SOC_SHA_SUPPORT_SHA512
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_ESP_WIFI_TESTING_OPTIONS=y
|
||||
CONFIG_ESP_WIFI_DEBUG_PRINT=y
|
||||
CONFIG_ESP_WIFI_DPP_SUPPORT=y
|
||||
CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y
|
||||
CONFIG_ESP_WIFI_P256_ACCEL=y
|
||||
|
||||
Reference in New Issue
Block a user