From 8f5f828ad6403888cc455929d6da937c32b6c773 Mon Sep 17 00:00:00 2001 From: Sagar Bijwe Date: Wed, 29 Apr 2020 18:44:10 +0530 Subject: [PATCH] wpa_supplicant: Adding SAE modules with testcase This change ports SAE(Simultaneous Authentication of Equals) feature from wpa_supplicant and makes it work with mbedtls crypto APIs. Currently only group 19 is supported. A sample SAE handshake is included in the testcase. Other minor changes for DH groups are also included. --- .../esp_wifi/include/esp_wifi_crypto_types.h | 4 +- components/wpa_supplicant/CMakeLists.txt | 2 + .../src/common/ieee802_11_defs.h | 18 + components/wpa_supplicant/src/common/sae.c | 1280 +++++++++++++++++ components/wpa_supplicant/src/common/sae.h | 85 ++ .../src/crypto/crypto_mbedtls.c | 6 +- .../wpa_supplicant/src/crypto/dh_groups.c | 682 ++++++++- .../wpa_supplicant/src/crypto/dh_groups.h | 3 + components/wpa_supplicant/src/crypto/sha256.c | 78 +- components/wpa_supplicant/src/crypto/sha256.h | 7 +- components/wpa_supplicant/src/utils/common.h | 2 + components/wpa_supplicant/test/CMakeLists.txt | 1 + components/wpa_supplicant/test/component.mk | 2 +- components/wpa_supplicant/test/test_sae.c | 270 ++++ 14 files changed, 2399 insertions(+), 41 deletions(-) create mode 100644 components/wpa_supplicant/src/common/sae.c create mode 100644 components/wpa_supplicant/src/common/sae.h create mode 100644 components/wpa_supplicant/test/test_sae.c diff --git a/components/esp_wifi/include/esp_wifi_crypto_types.h b/components/esp_wifi/include/esp_wifi_crypto_types.h index b626845c6..47620802e 100644 --- a/components/esp_wifi/include/esp_wifi_crypto_types.h +++ b/components/esp_wifi/include/esp_wifi_crypto_types.h @@ -116,7 +116,7 @@ typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, int n, const unsigned * @param mac Buffer for the hash (32 bytes). * */ -typedef void (*esp_hmac_sha256_vector_t)(const unsigned char *key, int key_len, int num_elem, +typedef int (*esp_hmac_sha256_vector_t)(const unsigned char *key, int key_len, int num_elem, const unsigned char *addr[], const int *len, unsigned char *mac); /** @@ -131,7 +131,7 @@ typedef void (*esp_hmac_sha256_vector_t)(const unsigned char *key, int key_len, * @param buf_len Number of bytes of key to generate. * */ -typedef void (*esp_sha256_prf_t)(const unsigned char *key, int key_len, const char *label, +typedef int (*esp_sha256_prf_t)(const unsigned char *key, int key_len, const char *label, const unsigned char *data, int data_len, unsigned char *buf, int buf_len); /** diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 5692955f9..eed582d85 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -3,6 +3,7 @@ set(srcs "port/os_xtensa.c" "src/ap/ieee802_1x.c" "src/ap/wpa_auth.c" "src/ap/wpa_auth_ie.c" + "src/common/sae.c" "src/common/wpa_common.c" "src/crypto/aes-cbc.c" "src/crypto/aes-ccm.c" @@ -110,4 +111,5 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_TLSV12 CONFIG_SHA256 CONFIG_IEEE80211W + CONFIG_WPA3_SAE ) diff --git a/components/wpa_supplicant/src/common/ieee802_11_defs.h b/components/wpa_supplicant/src/common/ieee802_11_defs.h index 4881e39a0..209ae9362 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_defs.h +++ b/components/wpa_supplicant/src/common/ieee802_11_defs.h @@ -141,6 +141,24 @@ #define WLAN_STATUS_INVALID_PMKID 53 #define WLAN_STATUS_INVALID_MDIE 54 #define WLAN_STATUS_INVALID_FTIE 55 +#define WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59 +#define WLAN_STATUS_NO_OUTSTANDING_GAS_REQ 60 +#define WLAN_STATUS_GAS_RESP_NOT_RECEIVED 61 +#define WLAN_STATUS_STA_TIMED_OUT_WAITING_FOR_GAS_RESP 62 +#define WLAN_STATUS_GAS_RESP_LARGER_THAN_LIMIT 63 +#define WLAN_STATUS_REQ_REFUSED_HOME 64 +#define WLAN_STATUS_ADV_SRV_UNREACHABLE 65 +#define WLAN_STATUS_REQ_REFUSED_SSPN 67 +#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68 +#define WLAN_STATUS_INVALID_RSNIE 72 +#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76 +#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77 +#define WLAN_STATUS_TRANSMISSION_FAILURE 79 +#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION 82 +#define WLAN_STATUS_PENDING_ADMITTING_FST_SESSION 86 +#define WLAN_STATUS_QUERY_RESP_OUTSTANDING 95 +#define WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL 99 +#define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104 /* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ #define WLAN_REASON_UNSPECIFIED 1 diff --git a/components/wpa_supplicant/src/common/sae.c b/components/wpa_supplicant/src/common/sae.c new file mode 100644 index 000000000..ebae4c41e --- /dev/null +++ b/components/wpa_supplicant/src/common/sae.c @@ -0,0 +1,1280 @@ +/* + * Simultaneous authentication of equals + * Copyright (c) 2012-2016, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifdef CONFIG_WPA3_SAE + +#include "utils/includes.h" +#include "utils/common.h" +#include "crypto/crypto.h" +#include "crypto/sha256.h" +#include "crypto/random.h" +#include "crypto/dh_groups.h" +#include "ieee802_11_defs.h" +#include "sae.h" +#include "esp_wifi_crypto_types.h" + +/*TBD Move the this api to proper files once they are taken out of lib*/ +void wpabuf_clear_free(struct wpabuf *buf) +{ + if (buf) { + os_memset(wpabuf_mhead(buf), 0, wpabuf_len(buf)); + wpabuf_free(buf); + } +} + +void bin_clear_free(void *bin, size_t len) +{ + if (bin) { + os_memset(bin, 0, len); + os_free(bin); + } +} + +int sae_set_group(struct sae_data *sae, u16 group) +{ + struct sae_temporary_data *tmp; + + sae_clear_data(sae); + tmp = sae->tmp = os_zalloc(sizeof(*tmp)); + if (tmp == NULL) + return -1; + + /* First, check if this is an ECC group */ + tmp->ec = crypto_ec_init(group); + if (tmp->ec) { + sae->group = group; + tmp->prime_len = crypto_ec_prime_len(tmp->ec); + tmp->prime = crypto_ec_get_prime(tmp->ec); + tmp->order = crypto_ec_get_order(tmp->ec); + return 0; + } + + /* Not an ECC group, check FFC */ + tmp->dh = dh_groups_get(group); + if (tmp->dh) { + sae->group = group; + tmp->prime_len = tmp->dh->prime_len; + if (tmp->prime_len > SAE_MAX_PRIME_LEN) { + sae_clear_data(sae); + return -1; + } + + tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime, + tmp->prime_len); + if (tmp->prime_buf == NULL) { + sae_clear_data(sae); + return -1; + } + tmp->prime = tmp->prime_buf; + + tmp->order_buf = crypto_bignum_init_set(tmp->dh->order, + tmp->dh->order_len); + if (tmp->order_buf == NULL) { + sae_clear_data(sae); + return -1; + } + tmp->order = tmp->order_buf; + + return 0; + } + + /* Unsupported group */ + return -1; +} + +void sae_clear_temp_data(struct sae_data *sae) +{ + struct sae_temporary_data *tmp; + if (sae == NULL || sae->tmp == NULL) + return; + tmp = sae->tmp; + crypto_ec_deinit(tmp->ec); + crypto_bignum_deinit(tmp->prime_buf, 0); + crypto_bignum_deinit(tmp->order_buf, 0); + crypto_bignum_deinit(tmp->sae_rand, 1); + crypto_bignum_deinit(tmp->pwe_ffc, 1); + crypto_bignum_deinit(tmp->own_commit_scalar, 0); + crypto_bignum_deinit(tmp->own_commit_element_ffc, 0); + crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0); + crypto_ec_point_deinit(tmp->pwe_ecc, 1); + crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0); + crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0); + wpabuf_free(tmp->anti_clogging_token); + bin_clear_free(tmp, sizeof(*tmp)); + sae->tmp = NULL; +} + +void sae_clear_data(struct sae_data *sae) +{ + if (sae == NULL) + return; + sae_clear_temp_data(sae); + crypto_bignum_deinit(sae->peer_commit_scalar, 0); + os_memset(sae, 0, sizeof(*sae)); +} + +static void buf_shift_right(u8 *buf, size_t len, size_t bits) +{ + size_t i; + for (i = len - 1; i > 0; i--) + buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits); + buf[0] >>= bits; +} + +static struct crypto_bignum * sae_get_rand(struct sae_data *sae) +{ + u8 val[SAE_MAX_PRIME_LEN]; + int iter = 0; + struct crypto_bignum *bn = NULL; + int order_len_bits = crypto_bignum_bits(sae->tmp->order); + size_t order_len = (order_len_bits + 7) / 8; + + if (order_len > sizeof(val)) + return NULL; + + for (;;) { + if (iter++ > 100 || random_get_bytes(val, order_len) < 0) + return NULL; + if (order_len_bits % 8) + buf_shift_right(val, order_len, 8 - order_len_bits % 8); + bn = crypto_bignum_init_set(val, order_len); + if (bn == NULL) + return NULL; + if (crypto_bignum_is_zero(bn) || + crypto_bignum_is_one(bn) || + crypto_bignum_cmp(bn, sae->tmp->order) >= 0) { + crypto_bignum_deinit(bn, 0); + continue; + } + break; + } + + os_memset(val, 0, order_len); + return bn; +} + +static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae) +{ + crypto_bignum_deinit(sae->tmp->sae_rand, 1); + sae->tmp->sae_rand = sae_get_rand(sae); + if (sae->tmp->sae_rand == NULL) + return NULL; + return sae_get_rand(sae); +} + +static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key) +{ + wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR + " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); + if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) { + os_memcpy(key, addr1, ETH_ALEN); + os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN); + } else { + os_memcpy(key, addr2, ETH_ALEN); + os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN); + } +} + +static struct crypto_bignum * +get_rand_1_to_p_1(const u8 *prime, size_t prime_len, size_t prime_bits, + int *r_odd) +{ + for (;;) { + struct crypto_bignum *r; + u8 tmp[SAE_MAX_ECC_PRIME_LEN]; + + if (random_get_bytes(tmp, prime_len) < 0) + break; + if (prime_bits % 8) + buf_shift_right(tmp, prime_len, 8 - prime_bits % 8); + if (os_memcmp(tmp, prime, prime_len) >= 0) + continue; + r = crypto_bignum_init_set(tmp, prime_len); + if (!r) + break; + if (crypto_bignum_is_zero(r)) { + crypto_bignum_deinit(r, 0); + continue; + } + + *r_odd = tmp[prime_len - 1] & 0x01; + return r; + } + + return NULL; +} + +static int is_quadratic_residue_blind(struct sae_data *sae, + const u8 *prime, size_t bits, + const struct crypto_bignum *qr, + const struct crypto_bignum *qnr, + const struct crypto_bignum *y_sqr) +{ + struct crypto_bignum *r, *num; + int r_odd, check, res = -1; + + /* + * Use the blinding technique to mask y_sqr while determining + * whether it is a quadratic residue modulo p to avoid leaking + * timing information while determining the Legendre symbol. + * + * v = y_sqr + * r = a random number between 1 and p-1, inclusive + * num = (v * r * r) modulo p + */ + r = get_rand_1_to_p_1(prime, sae->tmp->prime_len, bits, &r_odd); + if (!r) + return -1; + + num = crypto_bignum_init(); + if (!num || + crypto_bignum_mulmod(y_sqr, r, sae->tmp->prime, num) < 0 || + crypto_bignum_mulmod(num, r, sae->tmp->prime, num) < 0) + goto fail; + + if (r_odd) { + /* + * num = (num * qr) module p + * LGR(num, p) = 1 ==> quadratic residue + */ + if (crypto_bignum_mulmod(num, qr, sae->tmp->prime, num) < 0) + goto fail; + check = 1; + } else { + /* + * num = (num * qnr) module p + * LGR(num, p) = -1 ==> quadratic residue + */ + if (crypto_bignum_mulmod(num, qnr, sae->tmp->prime, num) < 0) + goto fail; + check = -1; + } + + res = crypto_bignum_legendre(num, sae->tmp->prime); + if (res == -2) { + res = -1; + goto fail; + } + res = res == check; +fail: + crypto_bignum_deinit(num, 1); + crypto_bignum_deinit(r, 1); + return res; +} + +static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, + const u8 *prime, + const struct crypto_bignum *qr, + const struct crypto_bignum *qnr, + struct crypto_bignum **ret_x_cand) +{ + u8 pwd_value[SAE_MAX_ECC_PRIME_LEN]; + struct crypto_bignum *y_sqr, *x_cand; + int res; + size_t bits; + + *ret_x_cand = NULL; + + wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); + + /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ + bits = crypto_ec_prime_len_bits(sae->tmp->ec); + if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", + prime, sae->tmp->prime_len, pwd_value, bits) < 0) + return -1; + if (bits % 8) + buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8); + wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", + pwd_value, sae->tmp->prime_len); + + if (os_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0) + return 0; + + x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); + if (!x_cand) + return -1; + y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand); + if (!y_sqr) { + crypto_bignum_deinit(x_cand, 1); + return -1; + } + + res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr); + crypto_bignum_deinit(y_sqr, 1); + if (res <= 0) { + crypto_bignum_deinit(x_cand, 1); + return res; + } + + *ret_x_cand = x_cand; + return 1; +} + +static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed, + struct crypto_bignum *pwe) +{ + u8 pwd_value[SAE_MAX_PRIME_LEN]; + size_t bits = sae->tmp->prime_len * 8; + u8 exp[1]; + struct crypto_bignum *a, *b; + int res; + + wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); + + /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ + if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", + sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value, + bits) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, + sae->tmp->prime_len); + + if (os_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len) >= 0) + { + wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p"); + return 0; + } + + /* PWE = pwd-value^((p-1)/r) modulo p */ + + a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); + + if (sae->tmp->dh->safe_prime) { + /* + * r = (p-1)/2 for the group used here, so this becomes: + * PWE = pwd-value^2 modulo p + */ + exp[0] = 2; + b = crypto_bignum_init_set(exp, sizeof(exp)); + } else { + /* Calculate exponent: (p-1)/r */ + exp[0] = 1; + b = crypto_bignum_init_set(exp, sizeof(exp)); + if (b == NULL || + crypto_bignum_sub(sae->tmp->prime, b, b) < 0 || + crypto_bignum_div(b, sae->tmp->order, b) < 0) { + crypto_bignum_deinit(b, 0); + b = NULL; + } + } + + if (a == NULL || b == NULL) + res = -1; + else + res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe); + + crypto_bignum_deinit(a, 0); + crypto_bignum_deinit(b, 0); + + if (res < 0) { + wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE"); + return -1; + } + + /* if (PWE > 1) --> found */ + if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) { + wpa_printf(MSG_DEBUG, "SAE: PWE <= 1"); + return 0; + } + + wpa_printf(MSG_DEBUG, "SAE: PWE found"); + return 1; +} + +static int get_random_qr_qnr(const u8 *prime, size_t prime_len, + const struct crypto_bignum *prime_bn, + size_t prime_bits, struct crypto_bignum **qr, + struct crypto_bignum **qnr) +{ + *qr = NULL; + *qnr = NULL; + + while (!(*qr) || !(*qnr)) { + u8 tmp[SAE_MAX_ECC_PRIME_LEN]; + struct crypto_bignum *q; + int res; + + if (random_get_bytes(tmp, prime_len) < 0) + break; + if (prime_bits % 8) + buf_shift_right(tmp, prime_len, 8 - prime_bits % 8); + if (os_memcmp(tmp, prime, prime_len) >= 0) + continue; + q = crypto_bignum_init_set(tmp, prime_len); + if (!q) + break; + res = crypto_bignum_legendre(q, prime_bn); + + if (res == 1 && !(*qr)) + *qr = q; + else if (res == -1 && !(*qnr)) + *qnr = q; + else + crypto_bignum_deinit(q, 0); + } + + return (*qr && *qnr) ? 0 : -1; +} + +static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, + const u8 *addr2, const u8 *password, + size_t password_len) +{ + u8 counter, k = 40; + u8 addrs[2 * ETH_ALEN]; + const u8 *addr[2]; + size_t len[2]; + u8 dummy_password[32]; + size_t dummy_password_len; + int pwd_seed_odd = 0; + u8 prime[SAE_MAX_ECC_PRIME_LEN]; + size_t prime_len; + struct crypto_bignum *x = NULL, *qr, *qnr; + size_t bits; + int res; + + dummy_password_len = password_len; + if (dummy_password_len > sizeof(dummy_password)) + dummy_password_len = sizeof(dummy_password); + if (random_get_bytes(dummy_password, dummy_password_len) < 0) + return -1; + + prime_len = sae->tmp->prime_len; + if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), + prime_len) < 0) + return -1; + bits = crypto_ec_prime_len_bits(sae->tmp->ec); + + /* + * Create a random quadratic residue (qr) and quadratic non-residue + * (qnr) modulo p for blinding purposes during the loop. + */ + if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits, + &qr, &qnr) < 0) + return -1; + + wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", + password, password_len); + + /* + * H(salt, ikm) = HMAC-SHA256(salt, ikm) + * base = password + * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), + * base || counter) + */ + sae_pwd_seed_key(addr1, addr2, addrs); + + addr[0] = password; + len[0] = password_len; + addr[1] = &counter; + len[1] = sizeof(counter); + + /* + * Continue for at least k iterations to protect against side-channel + * attacks that attempt to determine the number of iterations required + * in the loop. + */ + for (counter = 1; counter <= k || !x; counter++) { + u8 pwd_seed[SHA256_MAC_LEN]; + struct crypto_bignum *x_cand; + + if (counter > 200) { + /* This should not happen in practice */ + wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); + break; + } + + wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter); + if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len, + pwd_seed) < 0) + break; + + res = sae_test_pwd_seed_ecc(sae, pwd_seed, + prime, qr, qnr, &x_cand); + if (res < 0) + goto fail; + if (res > 0 && !x) { + wpa_printf(MSG_DEBUG, + "SAE: Selected pwd-seed with counter %u", + counter); + x = x_cand; + pwd_seed_odd = pwd_seed[SHA256_MAC_LEN - 1] & 0x01; + os_memset(pwd_seed, 0, sizeof(pwd_seed)); + + /* + * Use a dummy password for the following rounds, if + * any. + */ + addr[0] = dummy_password; + len[0] = dummy_password_len; + } else if (res > 0) { + crypto_bignum_deinit(x_cand, 1); + } + } + + if (!x) { + wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); + res = -1; + goto fail; + } + + if (!sae->tmp->pwe_ecc) + sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); + if (!sae->tmp->pwe_ecc) + res = -1; + else + res = crypto_ec_point_solve_y_coord(sae->tmp->ec, + sae->tmp->pwe_ecc, x, + pwd_seed_odd); + crypto_bignum_deinit(x, 1); + if (res < 0) { + /* + * This should not happen since we already checked that there + * is a result. + */ + wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); + } + +fail: + crypto_bignum_deinit(qr, 0); + crypto_bignum_deinit(qnr, 0); + + return res; +} + +static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1, + const u8 *addr2, const u8 *password, + size_t password_len) +{ + u8 counter; + u8 addrs[2 * ETH_ALEN]; + const u8 *addr[2]; + size_t len[2]; + int found = 0; + + if (sae->tmp->pwe_ffc == NULL) { + sae->tmp->pwe_ffc = crypto_bignum_init(); + if (sae->tmp->pwe_ffc == NULL) + return -1; + } + + wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", + password, password_len); + + /* + * H(salt, ikm) = HMAC-SHA256(salt, ikm) + * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), + * password || counter) + */ + sae_pwd_seed_key(addr1, addr2, addrs); + + addr[0] = password; + len[0] = password_len; + addr[1] = &counter; + len[1] = sizeof(counter); + + for (counter = 1; !found; counter++) { + u8 pwd_seed[SHA256_MAC_LEN]; + int res; + + if (counter > 200) { + /* This should not happen in practice */ + wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); + break; + } + + wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter); + if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len, + pwd_seed) < 0) + break; + res = sae_test_pwd_seed_ffc(sae, pwd_seed, sae->tmp->pwe_ffc); + if (res < 0) + break; + if (res > 0) { + wpa_printf(MSG_DEBUG, "SAE: Use this PWE"); + found = 1; + } + } + + return found ? 0 : -1; +} + +static int sae_derive_commit_element_ecc(struct sae_data *sae, + struct crypto_bignum *mask) +{ + /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ + if (!sae->tmp->own_commit_element_ecc) { + sae->tmp->own_commit_element_ecc = + crypto_ec_point_init(sae->tmp->ec); + if (!sae->tmp->own_commit_element_ecc) + return -1; + } + + if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask, + sae->tmp->own_commit_element_ecc) < 0 || + crypto_ec_point_invert(sae->tmp->ec, + sae->tmp->own_commit_element_ecc) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); + return -1; + } + + return 0; +} + +static int sae_derive_commit_element_ffc(struct sae_data *sae, + struct crypto_bignum *mask) +{ + /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ + if (!sae->tmp->own_commit_element_ffc) { + sae->tmp->own_commit_element_ffc = crypto_bignum_init(); + if (!sae->tmp->own_commit_element_ffc) + return -1; + } + + if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime, + sae->tmp->own_commit_element_ffc) < 0 || + crypto_bignum_inverse(sae->tmp->own_commit_element_ffc, + sae->tmp->prime, + sae->tmp->own_commit_element_ffc) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); + return -1; + } + + return 0; +} + +static int sae_derive_commit(struct sae_data *sae) +{ + struct crypto_bignum *mask; + int ret = -1; + unsigned int counter = 0; + + do { + counter++; + if (counter > 100) { + /* + * This cannot really happen in practice if the random + * number generator is working. Anyway, to avoid even a + * theoretical infinite loop, break out after 100 + * attemps. + */ + return -1; + } + + mask = sae_get_rand_and_mask(sae); + if (mask == NULL) { + wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask"); + return -1; + } + + /* commit-scalar = (rand + mask) modulo r */ + if (!sae->tmp->own_commit_scalar) { + sae->tmp->own_commit_scalar = crypto_bignum_init(); + if (!sae->tmp->own_commit_scalar) + goto fail; + } + crypto_bignum_add(sae->tmp->sae_rand, mask, + sae->tmp->own_commit_scalar); + crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order, + sae->tmp->own_commit_scalar); + } while (crypto_bignum_is_zero(sae->tmp->own_commit_scalar) || + crypto_bignum_is_one(sae->tmp->own_commit_scalar)); + + if ((sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0) || + (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0)) + goto fail; + + ret = 0; +fail: + crypto_bignum_deinit(mask, 1); + return ret; +} + +int sae_prepare_commit(const u8 *addr1, const u8 *addr2, + const u8 *password, size_t password_len, + struct sae_data *sae) +{ + if (sae->tmp == NULL || + (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password, + password_len) < 0) || + (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password, + password_len) < 0) || + sae_derive_commit(sae) < 0) + return -1; + return 0; +} + +static int sae_derive_k_ecc(struct sae_data *sae, u8 *k) +{ + struct crypto_ec_point *K; + int ret = -1; + + K = crypto_ec_point_init(sae->tmp->ec); + if (K == NULL) + goto fail; + + /* + * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), + * PEER-COMMIT-ELEMENT))) + * If K is identity element (point-at-infinity), reject + * k = F(K) (= x coordinate) + */ + + if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, + sae->peer_commit_scalar, K) < 0 || + crypto_ec_point_add(sae->tmp->ec, K, + sae->tmp->peer_commit_element_ecc, K) < 0 || + crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 || + crypto_ec_point_is_at_infinity(sae->tmp->ec, K) || + crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); + goto fail; + } + + wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); + + ret = 0; +fail: + crypto_ec_point_deinit(K, 1); + return ret; +} + +static int sae_derive_k_ffc(struct sae_data *sae, u8 *k) +{ + struct crypto_bignum *K; + int ret = -1; + + K = crypto_bignum_init(); + if (K == NULL) + goto fail; + + /* + * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), + * PEER-COMMIT-ELEMENT))) + * If K is identity element (one), reject. + * k = F(K) (= x coordinate) + */ + + if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar, + sae->tmp->prime, K) < 0 || + crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc, + sae->tmp->prime, K) < 0 || + crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0 + || + crypto_bignum_is_one(K) || + crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) < + 0) { + wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); + goto fail; + } + + wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); + + ret = 0; +fail: + crypto_bignum_deinit(K, 1); + return ret; +} + +static int sae_derive_keys(struct sae_data *sae, const u8 *k) +{ + u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN]; + u8 keyseed[SHA256_MAC_LEN]; + u8 keys[SAE_KCK_LEN + SAE_PMK_LEN]; + struct crypto_bignum *tmp; + int ret = -1; + + tmp = crypto_bignum_init(); + if (tmp == NULL) + goto fail; + + /* keyseed = H(<0>32, k) + * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK", + * (commit-scalar + peer-commit-scalar) modulo r) + * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128) + */ + + os_memset(null_key, 0, sizeof(null_key)); + hmac_sha256(null_key, sizeof(null_key), k, sae->tmp->prime_len, + keyseed); + wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed)); + + crypto_bignum_add(sae->tmp->own_commit_scalar, sae->peer_commit_scalar, + tmp); + crypto_bignum_mod(tmp, sae->tmp->order, tmp); + crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->prime_len); + wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); + if (sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK", + val, sae->tmp->prime_len, keys, sizeof(keys)) < 0) + goto fail; + os_memset(keyseed, 0, sizeof(keyseed)); + os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN); + os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN); + os_memcpy(sae->pmkid, val, SAE_PMKID_LEN); + os_memset(keys, 0, sizeof(keys)); + wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN); + wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN); + + ret = 0; +fail: + crypto_bignum_deinit(tmp, 0); + return ret; +} + +int sae_process_commit(struct sae_data *sae) +{ + u8 k[SAE_MAX_PRIME_LEN]; + if (sae->tmp == NULL || + (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) || + (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) || + sae_derive_keys(sae, k) < 0) + return -1; + return 0; +} + +void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, + const struct wpabuf *token) +{ + u8 *pos; + + if (sae->tmp == NULL) + return; + + wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ + if (token) { + wpabuf_put_buf(buf, token); + wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token", + wpabuf_head(token), wpabuf_len(token)); + } + pos = wpabuf_put(buf, sae->tmp->prime_len); + crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos, + sae->tmp->prime_len, sae->tmp->prime_len); + wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar", + pos, sae->tmp->prime_len); + if (sae->tmp->ec) { + pos = wpabuf_put(buf, 2 * sae->tmp->prime_len); + crypto_ec_point_to_bin(sae->tmp->ec, + sae->tmp->own_commit_element_ecc, + pos, pos + sae->tmp->prime_len); + wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)", + pos, sae->tmp->prime_len); + wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)", + pos + sae->tmp->prime_len, sae->tmp->prime_len); + } else { + pos = wpabuf_put(buf, sae->tmp->prime_len); + crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, + sae->tmp->prime_len, sae->tmp->prime_len); + wpa_hexdump(MSG_DEBUG, "SAE: own commit-element", + pos, sae->tmp->prime_len); + } +} + +u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group) +{ + if (allowed_groups) { + int i; + for (i = 0; allowed_groups[i] > 0; i++) { + if (allowed_groups[i] == group) + break; + } + if (allowed_groups[i] != group) { + wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not " + "enabled in the current configuration", + group); + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + } + } + + if (sae->state == SAE_COMMITTED && group != sae->group) { + wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed"); + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + } + + if (group != sae->group && sae_set_group(sae, group) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u", + group); + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + } + + if (sae->tmp == NULL) { + wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + if (sae->tmp->dh && !allowed_groups) { + wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without " + "explicit configuration enabling it", group); + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + } + + return WLAN_STATUS_SUCCESS; +} + +static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos, + const u8 *end, const u8 **token, + size_t *token_len) +{ + if ((sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end - *pos) { + size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) * + sae->tmp->prime_len); + wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen); + if (token) + *token = *pos; + if (token_len) + *token_len = tlen; + *pos += tlen; + } else { + if (token) + *token = NULL; + if (token_len) + *token_len = 0; + } +} + +static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos, + const u8 *end) +{ + struct crypto_bignum *peer_scalar; + + if (sae->tmp->prime_len > end - *pos) { + wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len); + if (peer_scalar == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + /* + * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for + * the peer and it is in Authenticated state, the new Commit Message + * shall be dropped if the peer-scalar is identical to the one used in + * the existing protocol instance. + */ + if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar && + crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) { + wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous " + "peer-commit-scalar"); + crypto_bignum_deinit(peer_scalar, 0); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + /* 1 < scalar < r */ + if (crypto_bignum_is_zero(peer_scalar) || + crypto_bignum_is_one(peer_scalar) || + crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) { + wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar"); + crypto_bignum_deinit(peer_scalar, 0); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + + crypto_bignum_deinit(sae->peer_commit_scalar, 0); + sae->peer_commit_scalar = peer_scalar; + wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar", + *pos, sae->tmp->prime_len); + *pos += sae->tmp->prime_len; + + return WLAN_STATUS_SUCCESS; +} + +static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos, + const u8 *end) +{ + u8 prime[SAE_MAX_ECC_PRIME_LEN]; + + if (2 * sae->tmp->prime_len > end - pos) { + wpa_printf(MSG_DEBUG, "SAE: Not enough data for " + "commit-element"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), + sae->tmp->prime_len) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + /* element x and y coordinates < p */ + if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 || + os_memcmp(pos + sae->tmp->prime_len, prime, + sae->tmp->prime_len) >= 0) { + wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer " + "element"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)", + pos, sae->tmp->prime_len); + wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)", + pos + sae->tmp->prime_len, sae->tmp->prime_len); + + crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0); + sae->tmp->peer_commit_element_ecc = + crypto_ec_point_from_bin(sae->tmp->ec, pos); + if (sae->tmp->peer_commit_element_ecc == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + if (!crypto_ec_point_is_on_curve(sae->tmp->ec, + sae->tmp->peer_commit_element_ecc)) { + wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} + +static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos, + const u8 *end) +{ + struct crypto_bignum *res, *one; + const u8 one_bin[1] = { 0x01 }; + + if (sae->tmp->prime_len > end - pos) { + wpa_printf(MSG_DEBUG, "SAE: Not enough data for " + "commit-element"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos, + sae->tmp->prime_len); + + crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0); + sae->tmp->peer_commit_element_ffc = + crypto_bignum_init_set(pos, sae->tmp->prime_len); + if (sae->tmp->peer_commit_element_ffc == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + /* 1 < element < p - 1 */ + res = crypto_bignum_init(); + one = crypto_bignum_init_set(one_bin, sizeof(one_bin)); + if (!res || !one || + crypto_bignum_sub(sae->tmp->prime, one, res) || + crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) || + crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) || + crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) { + crypto_bignum_deinit(res, 0); + crypto_bignum_deinit(one, 0); + wpa_printf(MSG_DEBUG, "SAE: Invalid peer element"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + crypto_bignum_deinit(one, 0); + + /* scalar-op(r, ELEMENT) = 1 modulo p */ + if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc, + sae->tmp->order, sae->tmp->prime, res) < 0 || + !crypto_bignum_is_one(res)) { + wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)"); + crypto_bignum_deinit(res, 0); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + crypto_bignum_deinit(res, 0); + + return WLAN_STATUS_SUCCESS; +} + +static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos, + const u8 *end) +{ + if (sae->tmp->dh) + return sae_parse_commit_element_ffc(sae, pos, end); + return sae_parse_commit_element_ecc(sae, pos, end); +} + +u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, + const u8 **token, size_t *token_len, int *allowed_groups) +{ + const u8 *pos = data, *end = data + len; + u16 res; + + /* Check Finite Cyclic Group */ + if (end - pos < 2) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos)); + if (res != WLAN_STATUS_SUCCESS) + return res; + pos += 2; + + /* Optional Anti-Clogging Token */ + sae_parse_commit_token(sae, &pos, end, token, token_len); + + /* commit-scalar */ + res = sae_parse_commit_scalar(sae, &pos, end); + if (res != WLAN_STATUS_SUCCESS) + return res; + + /* commit-element */ + res = sae_parse_commit_element(sae, pos, end); + if (res != WLAN_STATUS_SUCCESS) + return res; + + /* + * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as + * the values we sent which would be evidence of a reflection attack. + */ + if (!sae->tmp->own_commit_scalar || + crypto_bignum_cmp(sae->tmp->own_commit_scalar, + sae->peer_commit_scalar) != 0 || + (sae->tmp->dh && + (!sae->tmp->own_commit_element_ffc || + crypto_bignum_cmp(sae->tmp->own_commit_element_ffc, + sae->tmp->peer_commit_element_ffc) != 0)) || + (sae->tmp->ec && + (!sae->tmp->own_commit_element_ecc || + crypto_ec_point_cmp(sae->tmp->ec, + sae->tmp->own_commit_element_ecc, + sae->tmp->peer_commit_element_ecc) != 0))) + return WLAN_STATUS_SUCCESS; /* scalars/elements are different */ + + /* + * This is a reflection attack - return special value to trigger caller + * to silently discard the frame instead of replying with a specific + * status code. + */ + return SAE_SILENTLY_DISCARD; +} + +static void sae_cn_confirm(struct sae_data *sae, const u8 *sc, + const struct crypto_bignum *scalar1, + const u8 *element1, size_t element1_len, + const struct crypto_bignum *scalar2, + const u8 *element2, size_t element2_len, + u8 *confirm) +{ + const u8 *addr[5]; + size_t len[5]; + u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN]; + + /* Confirm + * CN(key, X, Y, Z, ...) = + * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...) + * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT, + * peer-commit-scalar, PEER-COMMIT-ELEMENT) + * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar, + * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT) + */ + addr[0] = sc; + len[0] = 2; + crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1), + sae->tmp->prime_len); + addr[1] = scalar_b1; + len[1] = sae->tmp->prime_len; + addr[2] = element1; + len[2] = element1_len; + crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2), + sae->tmp->prime_len); + addr[3] = scalar_b2; + len[3] = sae->tmp->prime_len; + addr[4] = element2; + len[4] = element2_len; + hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len, + confirm); +} + +static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc, + const struct crypto_bignum *scalar1, + const struct crypto_ec_point *element1, + const struct crypto_bignum *scalar2, + const struct crypto_ec_point *element2, + u8 *confirm) +{ + u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN]; + u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN]; + + crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1, + element_b1 + sae->tmp->prime_len); + crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2, + element_b2 + sae->tmp->prime_len); + + sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len, + scalar2, element_b2, 2 * sae->tmp->prime_len, confirm); +} + +static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc, + const struct crypto_bignum *scalar1, + const struct crypto_bignum *element1, + const struct crypto_bignum *scalar2, + const struct crypto_bignum *element2, + u8 *confirm) +{ + u8 element_b1[SAE_MAX_PRIME_LEN]; + u8 element_b2[SAE_MAX_PRIME_LEN]; + + crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1), + sae->tmp->prime_len); + crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2), + sae->tmp->prime_len); + + sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len, + scalar2, element_b2, sae->tmp->prime_len, confirm); +} + +void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) +{ + const u8 *sc; + + if (sae->tmp == NULL) + return; + + /* Send-Confirm */ + sc = wpabuf_put(buf, 0); + wpabuf_put_le16(buf, sae->send_confirm); + sae->send_confirm++; + + if (sae->tmp->ec) + sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, + sae->tmp->own_commit_element_ecc, + sae->peer_commit_scalar, + sae->tmp->peer_commit_element_ecc, + wpabuf_put(buf, SHA256_MAC_LEN)); + else + sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, + sae->tmp->own_commit_element_ffc, + sae->peer_commit_scalar, + sae->tmp->peer_commit_element_ffc, + wpabuf_put(buf, SHA256_MAC_LEN)); +} + +int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) +{ + u8 verifier[SHA256_MAC_LEN]; + + if (len < 2 + SHA256_MAC_LEN) { + wpa_printf(MSG_DEBUG, "SAE: Too short confirm message"); + return -1; + } + + wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data)); + + if (sae->tmp == NULL) { + wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available"); + return -1; + } + + if (sae->tmp->ec) + sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar, + sae->tmp->peer_commit_element_ecc, + sae->tmp->own_commit_scalar, + sae->tmp->own_commit_element_ecc, + verifier); + else + sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar, + sae->tmp->peer_commit_element_ffc, + sae->tmp->own_commit_scalar, + sae->tmp->own_commit_element_ffc, + verifier); + + if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) { + wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch"); + wpa_hexdump(MSG_DEBUG, "SAE: Received confirm", + data + 2, SHA256_MAC_LEN); + wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier", + verifier, SHA256_MAC_LEN); + return -1; + } + + return 0; +} + +#endif /* CONFIG_WPA3_SAE */ diff --git a/components/wpa_supplicant/src/common/sae.h b/components/wpa_supplicant/src/common/sae.h new file mode 100644 index 000000000..41c7ac0cb --- /dev/null +++ b/components/wpa_supplicant/src/common/sae.h @@ -0,0 +1,85 @@ +/* + * Simultaneous authentication of equals + * Copyright (c) 2012-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifdef CONFIG_WPA3_SAE + +#ifndef SAE_H +#define SAE_H + +#include "esp_err.h" + +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/wpa_debug.h" + +#define SAE_KCK_LEN 32 +#define SAE_PMK_LEN 32 +#define SAE_PMKID_LEN 16 +#define SAE_KEYSEED_KEY_LEN 32 +#define SAE_MAX_PRIME_LEN 512 +#define SAE_MAX_ECC_PRIME_LEN 66 +#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN) +#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_PRIME_LEN) + +/* Special value returned by sae_parse_commit() */ +#define SAE_SILENTLY_DISCARD 65535 + +struct sae_temporary_data { + u8 kck[SAE_KCK_LEN]; + struct crypto_bignum *own_commit_scalar; + struct crypto_bignum *own_commit_element_ffc; + struct crypto_ec_point *own_commit_element_ecc; + struct crypto_bignum *peer_commit_element_ffc; + struct crypto_ec_point *peer_commit_element_ecc; + struct crypto_ec_point *pwe_ecc; + struct crypto_bignum *pwe_ffc; + struct crypto_bignum *sae_rand; + struct crypto_ec *ec; + int prime_len; + const struct dh_group *dh; + const struct crypto_bignum *prime; + const struct crypto_bignum *order; + struct crypto_bignum *prime_buf; + struct crypto_bignum *order_buf; + struct wpabuf *anti_clogging_token; +}; + +enum { + SAE_MSG_COMMIT = 1, + SAE_MSG_CONFIRM = 2, +}; + +struct sae_data { + enum { SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED } state; + u16 send_confirm; + u8 pmk[SAE_PMK_LEN]; + u8 pmkid[SAE_PMKID_LEN]; + struct crypto_bignum *peer_commit_scalar; + u16 group; + int sync; + struct sae_temporary_data *tmp; +}; + +int sae_set_group(struct sae_data *sae, u16 group); +void sae_clear_temp_data(struct sae_data *sae); +void sae_clear_data(struct sae_data *sae); + +int sae_prepare_commit(const u8 *addr1, const u8 *addr2, + const u8 *password, size_t password_len, + struct sae_data *sae); +int sae_process_commit(struct sae_data *sae); +void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, + const struct wpabuf *token); +u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, + const u8 **token, size_t *token_len, int *allowed_groups); +void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf); +int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len); +u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group); + +#endif /* SAE_H */ +#endif /* CONFIG_WPA3_SAE */ diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls.c b/components/wpa_supplicant/src/crypto/crypto_mbedtls.c index fbbab1a9e..88c0e732a 100644 --- a/components/wpa_supplicant/src/crypto/crypto_mbedtls.c +++ b/components/wpa_supplicant/src/crypto/crypto_mbedtls.c @@ -25,10 +25,6 @@ #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" - - -#define IANA_SECP256R1 19 - #ifdef ESP_PLATFORM int crypto_get_random(void *buf, size_t len) { @@ -497,6 +493,8 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e, if (y_bit) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(y, &e->group.P, y)); } + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&((mbedtls_ecp_point* )p)->X, (const mbedtls_mpi*) x)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&((mbedtls_ecp_point *)p)->Z, 1)); } else { ret = 1; } diff --git a/components/wpa_supplicant/src/crypto/dh_groups.c b/components/wpa_supplicant/src/crypto/dh_groups.c index 6f699d9be..3d872d3b4 100644 --- a/components/wpa_supplicant/src/crypto/dh_groups.c +++ b/components/wpa_supplicant/src/crypto/dh_groups.c @@ -44,6 +44,21 @@ static const u8 dh_group1_prime[96] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 dh_group1_order[96] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1D, 0x1B, 0x10, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + /* RFC 4306, B.2. Group 2 - 1024 Bit MODP * Generator: 2 * Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } @@ -68,6 +83,25 @@ static const u8 dh_group2_prime[128] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 dh_group2_order[128] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x73, 0x29, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + #endif /* ALL_DH_GROUPS */ /* RFC 3526, 2. Group 5 - 1536 Bit MODP @@ -102,6 +136,33 @@ static const u8 dh_group5_prime[192] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 dh_group5_order[192] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x11, 0xB9, 0x93, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + #ifdef ALL_DH_GROUPS /* RFC 3526, 3. Group 14 - 2048 Bit MODP @@ -144,6 +205,41 @@ static const u8 dh_group14_prime[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 dh_group14_order[256] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x56, 0x55, 0x34, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + /* RFC 3526, 4. Group 15 - 3072 Bit MODP * Generator: 2 * Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } @@ -200,6 +296,57 @@ static const u8 dh_group15_prime[384] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 dh_group15_order[384] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x9D, 0x69, 0x65, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + /* RFC 3526, 5. Group 16 - 4096 Bit MODP * Generator: 2 * Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } @@ -272,6 +419,73 @@ static const u8 dh_group16_prime[512] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 dh_group16_order[512] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00, + 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, + 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, + 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E, + 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED, + 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74, + 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C, + 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53, + 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, + 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, + 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6, + 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7, + 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E, + 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54, + 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0, + 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, + 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x03, 0x18, 0xCC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + /* RFC 3526, 6. Group 17 - 6144 Bit MODP * Generator: 2 * Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } @@ -376,6 +590,105 @@ static const u8 dh_group17_prime[768] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 dh_group17_order[768] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00, + 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, + 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, + 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E, + 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED, + 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74, + 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C, + 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53, + 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, + 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, + 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6, + 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7, + 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E, + 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54, + 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0, + 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, + 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x01, 0x42, 0x49, + 0x1B, 0x61, 0xFD, 0x5A, 0x69, 0x3E, 0x38, 0x13, + 0x60, 0xEA, 0x6E, 0x59, 0x30, 0x13, 0x23, 0x6F, + 0x64, 0xBA, 0x8F, 0x3B, 0x1E, 0xDD, 0x1B, 0xDE, + 0xFC, 0x7F, 0xCA, 0x03, 0x56, 0xCF, 0x29, 0x87, + 0x72, 0xED, 0x9C, 0x17, 0xA0, 0x98, 0x00, 0xD7, + 0x58, 0x35, 0x29, 0xF6, 0xC8, 0x13, 0xEC, 0x18, + 0x8B, 0xCB, 0x93, 0xD8, 0x43, 0x2D, 0x44, 0x8C, + 0x6D, 0x1F, 0x6D, 0xF5, 0xE7, 0xCD, 0x8A, 0x76, + 0xA2, 0x67, 0x36, 0x5D, 0x67, 0x6A, 0x5D, 0x8D, + 0xED, 0xBF, 0x8A, 0x23, 0xF3, 0x66, 0x12, 0xA5, + 0x99, 0x90, 0x28, 0xA8, 0x95, 0xEB, 0xD7, 0xA1, + 0x37, 0xDC, 0x7A, 0x00, 0x9B, 0xC6, 0x69, 0x5F, + 0xAC, 0xC1, 0xE5, 0x00, 0xE3, 0x25, 0xC9, 0x76, + 0x78, 0x19, 0x75, 0x0A, 0xE8, 0xB9, 0x0E, 0x81, + 0xFA, 0x41, 0x6B, 0xE7, 0x37, 0x3A, 0x7F, 0x7B, + 0x6A, 0xAF, 0x38, 0x17, 0xA3, 0x4C, 0x06, 0x41, + 0x5A, 0xD4, 0x20, 0x18, 0xC8, 0x05, 0x8E, 0x4F, + 0x2C, 0xF3, 0xE4, 0xBF, 0xDF, 0x63, 0xF4, 0x79, + 0x91, 0xD4, 0xBD, 0x3F, 0x1B, 0x66, 0x44, 0x5F, + 0x07, 0x8E, 0xA2, 0xDB, 0xFF, 0xAC, 0x2D, 0x62, + 0xA5, 0xEA, 0x03, 0xD9, 0x15, 0xA0, 0xAA, 0x55, + 0x66, 0x47, 0xB6, 0xBF, 0x5F, 0xA4, 0x70, 0xEC, + 0x0A, 0x66, 0x2F, 0x69, 0x07, 0xC0, 0x1B, 0xF0, + 0x53, 0xCB, 0x8A, 0xF7, 0x79, 0x4D, 0xF1, 0x94, + 0x03, 0x50, 0xEA, 0xC5, 0xDB, 0xE2, 0xED, 0x3B, + 0x7A, 0xA8, 0x55, 0x1E, 0xC5, 0x0F, 0xDF, 0xF8, + 0x75, 0x8C, 0xE6, 0x58, 0xD1, 0x89, 0xEA, 0xAE, + 0x6D, 0x2B, 0x64, 0xF6, 0x17, 0x79, 0x4B, 0x19, + 0x1C, 0x3F, 0xF4, 0x6B, 0xB7, 0x1E, 0x02, 0x34, + 0x02, 0x1F, 0x47, 0xB3, 0x1F, 0xA4, 0x30, 0x77, + 0x09, 0x5F, 0x96, 0xAD, 0x85, 0xBA, 0x3A, 0x6B, + 0x73, 0x4A, 0x7C, 0x8F, 0x36, 0xE6, 0x20, 0x12, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + /* RFC 3526, 7. Group 18 - 8192 Bit MODP * Generator: 2 * Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } @@ -512,24 +825,362 @@ static const u8 dh_group18_prime[1024] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const u8 dh_group18_order[1024] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00, + 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, + 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, + 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E, + 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED, + 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74, + 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C, + 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53, + 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, + 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, + 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6, + 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7, + 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E, + 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54, + 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0, + 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, + 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x01, 0x42, 0x49, + 0x1B, 0x61, 0xFD, 0x5A, 0x69, 0x3E, 0x38, 0x13, + 0x60, 0xEA, 0x6E, 0x59, 0x30, 0x13, 0x23, 0x6F, + 0x64, 0xBA, 0x8F, 0x3B, 0x1E, 0xDD, 0x1B, 0xDE, + 0xFC, 0x7F, 0xCA, 0x03, 0x56, 0xCF, 0x29, 0x87, + 0x72, 0xED, 0x9C, 0x17, 0xA0, 0x98, 0x00, 0xD7, + 0x58, 0x35, 0x29, 0xF6, 0xC8, 0x13, 0xEC, 0x18, + 0x8B, 0xCB, 0x93, 0xD8, 0x43, 0x2D, 0x44, 0x8C, + 0x6D, 0x1F, 0x6D, 0xF5, 0xE7, 0xCD, 0x8A, 0x76, + 0xA2, 0x67, 0x36, 0x5D, 0x67, 0x6A, 0x5D, 0x8D, + 0xED, 0xBF, 0x8A, 0x23, 0xF3, 0x66, 0x12, 0xA5, + 0x99, 0x90, 0x28, 0xA8, 0x95, 0xEB, 0xD7, 0xA1, + 0x37, 0xDC, 0x7A, 0x00, 0x9B, 0xC6, 0x69, 0x5F, + 0xAC, 0xC1, 0xE5, 0x00, 0xE3, 0x25, 0xC9, 0x76, + 0x78, 0x19, 0x75, 0x0A, 0xE8, 0xB9, 0x0E, 0x81, + 0xFA, 0x41, 0x6B, 0xE7, 0x37, 0x3A, 0x7F, 0x7B, + 0x6A, 0xAF, 0x38, 0x17, 0xA3, 0x4C, 0x06, 0x41, + 0x5A, 0xD4, 0x20, 0x18, 0xC8, 0x05, 0x8E, 0x4F, + 0x2C, 0xF3, 0xE4, 0xBF, 0xDF, 0x63, 0xF4, 0x79, + 0x91, 0xD4, 0xBD, 0x3F, 0x1B, 0x66, 0x44, 0x5F, + 0x07, 0x8E, 0xA2, 0xDB, 0xFF, 0xAC, 0x2D, 0x62, + 0xA5, 0xEA, 0x03, 0xD9, 0x15, 0xA0, 0xAA, 0x55, + 0x66, 0x47, 0xB6, 0xBF, 0x5F, 0xA4, 0x70, 0xEC, + 0x0A, 0x66, 0x2F, 0x69, 0x07, 0xC0, 0x1B, 0xF0, + 0x53, 0xCB, 0x8A, 0xF7, 0x79, 0x4D, 0xF1, 0x94, + 0x03, 0x50, 0xEA, 0xC5, 0xDB, 0xE2, 0xED, 0x3B, + 0x7A, 0xA8, 0x55, 0x1E, 0xC5, 0x0F, 0xDF, 0xF8, + 0x75, 0x8C, 0xE6, 0x58, 0xD1, 0x89, 0xEA, 0xAE, + 0x6D, 0x2B, 0x64, 0xF6, 0x17, 0x79, 0x4B, 0x19, + 0x1C, 0x3F, 0xF4, 0x6B, 0xB7, 0x1E, 0x02, 0x34, + 0x02, 0x1F, 0x47, 0xB3, 0x1F, 0xA4, 0x30, 0x77, + 0x09, 0x5F, 0x96, 0xAD, 0x85, 0xBA, 0x3A, 0x6B, + 0x73, 0x4A, 0x7C, 0x8F, 0x36, 0xDF, 0x08, 0xAC, + 0xBA, 0x51, 0xC9, 0x37, 0x89, 0x7F, 0x72, 0xF2, + 0x1C, 0x3B, 0xBE, 0x5B, 0x54, 0x99, 0x6F, 0xC6, + 0x6C, 0x5F, 0x62, 0x68, 0x39, 0xDC, 0x98, 0xDD, + 0x1D, 0xE4, 0x19, 0x5B, 0x46, 0xCE, 0xE9, 0x80, + 0x3A, 0x0F, 0xD3, 0xDF, 0xC5, 0x7E, 0x23, 0xF6, + 0x92, 0xBB, 0x7B, 0x49, 0xB5, 0xD2, 0x12, 0x33, + 0x1D, 0x55, 0xB1, 0xCE, 0x2D, 0x72, 0x7A, 0xB4, + 0x1A, 0x11, 0xDA, 0x3A, 0x15, 0xF8, 0xE4, 0xBC, + 0x11, 0xC7, 0x8B, 0x65, 0xF1, 0xCE, 0xB2, 0x96, + 0xF1, 0xFE, 0xDC, 0x5F, 0x7E, 0x42, 0x45, 0x6C, + 0x91, 0x11, 0x17, 0x02, 0x52, 0x01, 0xBE, 0x03, + 0x89, 0xF5, 0xAB, 0xD4, 0x0D, 0x11, 0xF8, 0x63, + 0x9A, 0x39, 0xFE, 0x32, 0x36, 0x75, 0x18, 0x35, + 0xA5, 0xE5, 0xE4, 0x43, 0x17, 0xC1, 0xC2, 0xEE, + 0xFD, 0x4E, 0xA5, 0xBF, 0xD1, 0x60, 0x43, 0xF4, + 0x3C, 0xB4, 0x19, 0x81, 0xF6, 0xAD, 0xEE, 0x9D, + 0x03, 0x15, 0x9E, 0x7A, 0xD9, 0xD1, 0x3C, 0x53, + 0x36, 0x95, 0x09, 0xFC, 0x1F, 0xA2, 0x7C, 0x16, + 0xEF, 0x98, 0x87, 0x70, 0x3A, 0x55, 0xB5, 0x1B, + 0x22, 0xCB, 0xF4, 0x4C, 0xD0, 0x12, 0xAE, 0xE0, + 0xB2, 0x79, 0x8E, 0x62, 0x84, 0x23, 0x42, 0x8E, + 0xFC, 0xD5, 0xA4, 0x0C, 0xAE, 0xF6, 0xBF, 0x50, + 0xD8, 0xEA, 0x88, 0x5E, 0xBF, 0x73, 0xA6, 0xB9, + 0xFD, 0x79, 0xB5, 0xE1, 0x8F, 0x67, 0xD1, 0x34, + 0x1A, 0xC8, 0x23, 0x7A, 0x75, 0xC3, 0xCF, 0xC9, + 0x20, 0x04, 0xA1, 0xC5, 0xA4, 0x0E, 0x36, 0x6B, + 0xC4, 0x4D, 0x00, 0x17, 0x6A, 0xF7, 0x1C, 0x15, + 0xE4, 0x8C, 0x86, 0xD3, 0x7E, 0x01, 0x37, 0x23, + 0xCA, 0xAC, 0x72, 0x23, 0xAB, 0x3B, 0xF4, 0xD5, + 0x4F, 0x18, 0x28, 0x71, 0x3B, 0x2B, 0x4A, 0x6F, + 0xE4, 0x0F, 0xAB, 0x74, 0x40, 0x5C, 0xB7, 0x38, + 0xB0, 0x64, 0xC0, 0x6E, 0xCC, 0x76, 0xE9, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* + * RFC 5114, 2.1. + * Group 22 - 1024-bit MODP Group with 160-bit Prime Order Subgroup + */ +static const u8 dh_group22_generator[] = { + 0xA4, 0xD1, 0xCB, 0xD5, 0xC3, 0xFD, 0x34, 0x12, + 0x67, 0x65, 0xA4, 0x42, 0xEF, 0xB9, 0x99, 0x05, + 0xF8, 0x10, 0x4D, 0xD2, 0x58, 0xAC, 0x50, 0x7F, + 0xD6, 0x40, 0x6C, 0xFF, 0x14, 0x26, 0x6D, 0x31, + 0x26, 0x6F, 0xEA, 0x1E, 0x5C, 0x41, 0x56, 0x4B, + 0x77, 0x7E, 0x69, 0x0F, 0x55, 0x04, 0xF2, 0x13, + 0x16, 0x02, 0x17, 0xB4, 0xB0, 0x1B, 0x88, 0x6A, + 0x5E, 0x91, 0x54, 0x7F, 0x9E, 0x27, 0x49, 0xF4, + 0xD7, 0xFB, 0xD7, 0xD3, 0xB9, 0xA9, 0x2E, 0xE1, + 0x90, 0x9D, 0x0D, 0x22, 0x63, 0xF8, 0x0A, 0x76, + 0xA6, 0xA2, 0x4C, 0x08, 0x7A, 0x09, 0x1F, 0x53, + 0x1D, 0xBF, 0x0A, 0x01, 0x69, 0xB6, 0xA2, 0x8A, + 0xD6, 0x62, 0xA4, 0xD1, 0x8E, 0x73, 0xAF, 0xA3, + 0x2D, 0x77, 0x9D, 0x59, 0x18, 0xD0, 0x8B, 0xC8, + 0x85, 0x8F, 0x4D, 0xCE, 0xF9, 0x7C, 0x2A, 0x24, + 0x85, 0x5E, 0x6E, 0xEB, 0x22, 0xB3, 0xB2, 0xE5 +}; +static const u8 dh_group22_prime[] = { + 0xB1, 0x0B, 0x8F, 0x96, 0xA0, 0x80, 0xE0, 0x1D, + 0xDE, 0x92, 0xDE, 0x5E, 0xAE, 0x5D, 0x54, 0xEC, + 0x52, 0xC9, 0x9F, 0xBC, 0xFB, 0x06, 0xA3, 0xC6, + 0x9A, 0x6A, 0x9D, 0xCA, 0x52, 0xD2, 0x3B, 0x61, + 0x60, 0x73, 0xE2, 0x86, 0x75, 0xA2, 0x3D, 0x18, + 0x98, 0x38, 0xEF, 0x1E, 0x2E, 0xE6, 0x52, 0xC0, + 0x13, 0xEC, 0xB4, 0xAE, 0xA9, 0x06, 0x11, 0x23, + 0x24, 0x97, 0x5C, 0x3C, 0xD4, 0x9B, 0x83, 0xBF, + 0xAC, 0xCB, 0xDD, 0x7D, 0x90, 0xC4, 0xBD, 0x70, + 0x98, 0x48, 0x8E, 0x9C, 0x21, 0x9A, 0x73, 0x72, + 0x4E, 0xFF, 0xD6, 0xFA, 0xE5, 0x64, 0x47, 0x38, + 0xFA, 0xA3, 0x1A, 0x4F, 0xF5, 0x5B, 0xCC, 0xC0, + 0xA1, 0x51, 0xAF, 0x5F, 0x0D, 0xC8, 0xB4, 0xBD, + 0x45, 0xBF, 0x37, 0xDF, 0x36, 0x5C, 0x1A, 0x65, + 0xE6, 0x8C, 0xFD, 0xA7, 0x6D, 0x4D, 0xA7, 0x08, + 0xDF, 0x1F, 0xB2, 0xBC, 0x2E, 0x4A, 0x43, 0x71 +}; +static const u8 dh_group22_order[] = { + 0xF5, 0x18, 0xAA, 0x87, 0x81, 0xA8, 0xDF, 0x27, + 0x8A, 0xBA, 0x4E, 0x7D, 0x64, 0xB7, 0xCB, 0x9D, + 0x49, 0x46, 0x23, 0x53 +}; + +/* + * RFC 5114, 2.2. + * Group 23 - 2048-bit MODP Group with 224-bit Prime Order Subgroup + */ +static const u8 dh_group23_generator[] = { + 0xAC, 0x40, 0x32, 0xEF, 0x4F, 0x2D, 0x9A, 0xE3, + 0x9D, 0xF3, 0x0B, 0x5C, 0x8F, 0xFD, 0xAC, 0x50, + 0x6C, 0xDE, 0xBE, 0x7B, 0x89, 0x99, 0x8C, 0xAF, + 0x74, 0x86, 0x6A, 0x08, 0xCF, 0xE4, 0xFF, 0xE3, + 0xA6, 0x82, 0x4A, 0x4E, 0x10, 0xB9, 0xA6, 0xF0, + 0xDD, 0x92, 0x1F, 0x01, 0xA7, 0x0C, 0x4A, 0xFA, + 0xAB, 0x73, 0x9D, 0x77, 0x00, 0xC2, 0x9F, 0x52, + 0xC5, 0x7D, 0xB1, 0x7C, 0x62, 0x0A, 0x86, 0x52, + 0xBE, 0x5E, 0x90, 0x01, 0xA8, 0xD6, 0x6A, 0xD7, + 0xC1, 0x76, 0x69, 0x10, 0x19, 0x99, 0x02, 0x4A, + 0xF4, 0xD0, 0x27, 0x27, 0x5A, 0xC1, 0x34, 0x8B, + 0xB8, 0xA7, 0x62, 0xD0, 0x52, 0x1B, 0xC9, 0x8A, + 0xE2, 0x47, 0x15, 0x04, 0x22, 0xEA, 0x1E, 0xD4, + 0x09, 0x93, 0x9D, 0x54, 0xDA, 0x74, 0x60, 0xCD, + 0xB5, 0xF6, 0xC6, 0xB2, 0x50, 0x71, 0x7C, 0xBE, + 0xF1, 0x80, 0xEB, 0x34, 0x11, 0x8E, 0x98, 0xD1, + 0x19, 0x52, 0x9A, 0x45, 0xD6, 0xF8, 0x34, 0x56, + 0x6E, 0x30, 0x25, 0xE3, 0x16, 0xA3, 0x30, 0xEF, + 0xBB, 0x77, 0xA8, 0x6F, 0x0C, 0x1A, 0xB1, 0x5B, + 0x05, 0x1A, 0xE3, 0xD4, 0x28, 0xC8, 0xF8, 0xAC, + 0xB7, 0x0A, 0x81, 0x37, 0x15, 0x0B, 0x8E, 0xEB, + 0x10, 0xE1, 0x83, 0xED, 0xD1, 0x99, 0x63, 0xDD, + 0xD9, 0xE2, 0x63, 0xE4, 0x77, 0x05, 0x89, 0xEF, + 0x6A, 0xA2, 0x1E, 0x7F, 0x5F, 0x2F, 0xF3, 0x81, + 0xB5, 0x39, 0xCC, 0xE3, 0x40, 0x9D, 0x13, 0xCD, + 0x56, 0x6A, 0xFB, 0xB4, 0x8D, 0x6C, 0x01, 0x91, + 0x81, 0xE1, 0xBC, 0xFE, 0x94, 0xB3, 0x02, 0x69, + 0xED, 0xFE, 0x72, 0xFE, 0x9B, 0x6A, 0xA4, 0xBD, + 0x7B, 0x5A, 0x0F, 0x1C, 0x71, 0xCF, 0xFF, 0x4C, + 0x19, 0xC4, 0x18, 0xE1, 0xF6, 0xEC, 0x01, 0x79, + 0x81, 0xBC, 0x08, 0x7F, 0x2A, 0x70, 0x65, 0xB3, + 0x84, 0xB8, 0x90, 0xD3, 0x19, 0x1F, 0x2B, 0xFA +}; +static const u8 dh_group23_prime[] = { + 0xAD, 0x10, 0x7E, 0x1E, 0x91, 0x23, 0xA9, 0xD0, + 0xD6, 0x60, 0xFA, 0xA7, 0x95, 0x59, 0xC5, 0x1F, + 0xA2, 0x0D, 0x64, 0xE5, 0x68, 0x3B, 0x9F, 0xD1, + 0xB5, 0x4B, 0x15, 0x97, 0xB6, 0x1D, 0x0A, 0x75, + 0xE6, 0xFA, 0x14, 0x1D, 0xF9, 0x5A, 0x56, 0xDB, + 0xAF, 0x9A, 0x3C, 0x40, 0x7B, 0xA1, 0xDF, 0x15, + 0xEB, 0x3D, 0x68, 0x8A, 0x30, 0x9C, 0x18, 0x0E, + 0x1D, 0xE6, 0xB8, 0x5A, 0x12, 0x74, 0xA0, 0xA6, + 0x6D, 0x3F, 0x81, 0x52, 0xAD, 0x6A, 0xC2, 0x12, + 0x90, 0x37, 0xC9, 0xED, 0xEF, 0xDA, 0x4D, 0xF8, + 0xD9, 0x1E, 0x8F, 0xEF, 0x55, 0xB7, 0x39, 0x4B, + 0x7A, 0xD5, 0xB7, 0xD0, 0xB6, 0xC1, 0x22, 0x07, + 0xC9, 0xF9, 0x8D, 0x11, 0xED, 0x34, 0xDB, 0xF6, + 0xC6, 0xBA, 0x0B, 0x2C, 0x8B, 0xBC, 0x27, 0xBE, + 0x6A, 0x00, 0xE0, 0xA0, 0xB9, 0xC4, 0x97, 0x08, + 0xB3, 0xBF, 0x8A, 0x31, 0x70, 0x91, 0x88, 0x36, + 0x81, 0x28, 0x61, 0x30, 0xBC, 0x89, 0x85, 0xDB, + 0x16, 0x02, 0xE7, 0x14, 0x41, 0x5D, 0x93, 0x30, + 0x27, 0x82, 0x73, 0xC7, 0xDE, 0x31, 0xEF, 0xDC, + 0x73, 0x10, 0xF7, 0x12, 0x1F, 0xD5, 0xA0, 0x74, + 0x15, 0x98, 0x7D, 0x9A, 0xDC, 0x0A, 0x48, 0x6D, + 0xCD, 0xF9, 0x3A, 0xCC, 0x44, 0x32, 0x83, 0x87, + 0x31, 0x5D, 0x75, 0xE1, 0x98, 0xC6, 0x41, 0xA4, + 0x80, 0xCD, 0x86, 0xA1, 0xB9, 0xE5, 0x87, 0xE8, + 0xBE, 0x60, 0xE6, 0x9C, 0xC9, 0x28, 0xB2, 0xB9, + 0xC5, 0x21, 0x72, 0xE4, 0x13, 0x04, 0x2E, 0x9B, + 0x23, 0xF1, 0x0B, 0x0E, 0x16, 0xE7, 0x97, 0x63, + 0xC9, 0xB5, 0x3D, 0xCF, 0x4B, 0xA8, 0x0A, 0x29, + 0xE3, 0xFB, 0x73, 0xC1, 0x6B, 0x8E, 0x75, 0xB9, + 0x7E, 0xF3, 0x63, 0xE2, 0xFF, 0xA3, 0x1F, 0x71, + 0xCF, 0x9D, 0xE5, 0x38, 0x4E, 0x71, 0xB8, 0x1C, + 0x0A, 0xC4, 0xDF, 0xFE, 0x0C, 0x10, 0xE6, 0x4F +}; +static const u8 dh_group23_order[] = { + 0x80, 0x1C, 0x0D, 0x34, 0xC5, 0x8D, 0x93, 0xFE, + 0x99, 0x71, 0x77, 0x10, 0x1F, 0x80, 0x53, 0x5A, + 0x47, 0x38, 0xCE, 0xBC, 0xBF, 0x38, 0x9A, 0x99, + 0xB3, 0x63, 0x71, 0xEB +}; + +/* + * RFC 5114, 2.3. + * Group 24 - 2048-bit MODP Group with 256-bit Prime Order Subgroup + */ +static const u8 dh_group24_generator[] = { + 0x3F, 0xB3, 0x2C, 0x9B, 0x73, 0x13, 0x4D, 0x0B, + 0x2E, 0x77, 0x50, 0x66, 0x60, 0xED, 0xBD, 0x48, + 0x4C, 0xA7, 0xB1, 0x8F, 0x21, 0xEF, 0x20, 0x54, + 0x07, 0xF4, 0x79, 0x3A, 0x1A, 0x0B, 0xA1, 0x25, + 0x10, 0xDB, 0xC1, 0x50, 0x77, 0xBE, 0x46, 0x3F, + 0xFF, 0x4F, 0xED, 0x4A, 0xAC, 0x0B, 0xB5, 0x55, + 0xBE, 0x3A, 0x6C, 0x1B, 0x0C, 0x6B, 0x47, 0xB1, + 0xBC, 0x37, 0x73, 0xBF, 0x7E, 0x8C, 0x6F, 0x62, + 0x90, 0x12, 0x28, 0xF8, 0xC2, 0x8C, 0xBB, 0x18, + 0xA5, 0x5A, 0xE3, 0x13, 0x41, 0x00, 0x0A, 0x65, + 0x01, 0x96, 0xF9, 0x31, 0xC7, 0x7A, 0x57, 0xF2, + 0xDD, 0xF4, 0x63, 0xE5, 0xE9, 0xEC, 0x14, 0x4B, + 0x77, 0x7D, 0xE6, 0x2A, 0xAA, 0xB8, 0xA8, 0x62, + 0x8A, 0xC3, 0x76, 0xD2, 0x82, 0xD6, 0xED, 0x38, + 0x64, 0xE6, 0x79, 0x82, 0x42, 0x8E, 0xBC, 0x83, + 0x1D, 0x14, 0x34, 0x8F, 0x6F, 0x2F, 0x91, 0x93, + 0xB5, 0x04, 0x5A, 0xF2, 0x76, 0x71, 0x64, 0xE1, + 0xDF, 0xC9, 0x67, 0xC1, 0xFB, 0x3F, 0x2E, 0x55, + 0xA4, 0xBD, 0x1B, 0xFF, 0xE8, 0x3B, 0x9C, 0x80, + 0xD0, 0x52, 0xB9, 0x85, 0xD1, 0x82, 0xEA, 0x0A, + 0xDB, 0x2A, 0x3B, 0x73, 0x13, 0xD3, 0xFE, 0x14, + 0xC8, 0x48, 0x4B, 0x1E, 0x05, 0x25, 0x88, 0xB9, + 0xB7, 0xD2, 0xBB, 0xD2, 0xDF, 0x01, 0x61, 0x99, + 0xEC, 0xD0, 0x6E, 0x15, 0x57, 0xCD, 0x09, 0x15, + 0xB3, 0x35, 0x3B, 0xBB, 0x64, 0xE0, 0xEC, 0x37, + 0x7F, 0xD0, 0x28, 0x37, 0x0D, 0xF9, 0x2B, 0x52, + 0xC7, 0x89, 0x14, 0x28, 0xCD, 0xC6, 0x7E, 0xB6, + 0x18, 0x4B, 0x52, 0x3D, 0x1D, 0xB2, 0x46, 0xC3, + 0x2F, 0x63, 0x07, 0x84, 0x90, 0xF0, 0x0E, 0xF8, + 0xD6, 0x47, 0xD1, 0x48, 0xD4, 0x79, 0x54, 0x51, + 0x5E, 0x23, 0x27, 0xCF, 0xEF, 0x98, 0xC5, 0x82, + 0x66, 0x4B, 0x4C, 0x0F, 0x6C, 0xC4, 0x16, 0x59 +}; +static const u8 dh_group24_prime[] = { + 0x87, 0xA8, 0xE6, 0x1D, 0xB4, 0xB6, 0x66, 0x3C, + 0xFF, 0xBB, 0xD1, 0x9C, 0x65, 0x19, 0x59, 0x99, + 0x8C, 0xEE, 0xF6, 0x08, 0x66, 0x0D, 0xD0, 0xF2, + 0x5D, 0x2C, 0xEE, 0xD4, 0x43, 0x5E, 0x3B, 0x00, + 0xE0, 0x0D, 0xF8, 0xF1, 0xD6, 0x19, 0x57, 0xD4, + 0xFA, 0xF7, 0xDF, 0x45, 0x61, 0xB2, 0xAA, 0x30, + 0x16, 0xC3, 0xD9, 0x11, 0x34, 0x09, 0x6F, 0xAA, + 0x3B, 0xF4, 0x29, 0x6D, 0x83, 0x0E, 0x9A, 0x7C, + 0x20, 0x9E, 0x0C, 0x64, 0x97, 0x51, 0x7A, 0xBD, + 0x5A, 0x8A, 0x9D, 0x30, 0x6B, 0xCF, 0x67, 0xED, + 0x91, 0xF9, 0xE6, 0x72, 0x5B, 0x47, 0x58, 0xC0, + 0x22, 0xE0, 0xB1, 0xEF, 0x42, 0x75, 0xBF, 0x7B, + 0x6C, 0x5B, 0xFC, 0x11, 0xD4, 0x5F, 0x90, 0x88, + 0xB9, 0x41, 0xF5, 0x4E, 0xB1, 0xE5, 0x9B, 0xB8, + 0xBC, 0x39, 0xA0, 0xBF, 0x12, 0x30, 0x7F, 0x5C, + 0x4F, 0xDB, 0x70, 0xC5, 0x81, 0xB2, 0x3F, 0x76, + 0xB6, 0x3A, 0xCA, 0xE1, 0xCA, 0xA6, 0xB7, 0x90, + 0x2D, 0x52, 0x52, 0x67, 0x35, 0x48, 0x8A, 0x0E, + 0xF1, 0x3C, 0x6D, 0x9A, 0x51, 0xBF, 0xA4, 0xAB, + 0x3A, 0xD8, 0x34, 0x77, 0x96, 0x52, 0x4D, 0x8E, + 0xF6, 0xA1, 0x67, 0xB5, 0xA4, 0x18, 0x25, 0xD9, + 0x67, 0xE1, 0x44, 0xE5, 0x14, 0x05, 0x64, 0x25, + 0x1C, 0xCA, 0xCB, 0x83, 0xE6, 0xB4, 0x86, 0xF6, + 0xB3, 0xCA, 0x3F, 0x79, 0x71, 0x50, 0x60, 0x26, + 0xC0, 0xB8, 0x57, 0xF6, 0x89, 0x96, 0x28, 0x56, + 0xDE, 0xD4, 0x01, 0x0A, 0xBD, 0x0B, 0xE6, 0x21, + 0xC3, 0xA3, 0x96, 0x0A, 0x54, 0xE7, 0x10, 0xC3, + 0x75, 0xF2, 0x63, 0x75, 0xD7, 0x01, 0x41, 0x03, + 0xA4, 0xB5, 0x43, 0x30, 0xC1, 0x98, 0xAF, 0x12, + 0x61, 0x16, 0xD2, 0x27, 0x6E, 0x11, 0x71, 0x5F, + 0x69, 0x38, 0x77, 0xFA, 0xD7, 0xEF, 0x09, 0xCA, + 0xDB, 0x09, 0x4A, 0xE9, 0x1E, 0x1A, 0x15, 0x97 +}; + +static const u8 dh_group24_order[] = { + 0x8C, 0xF8, 0x36, 0x42, 0xA7, 0x09, 0xA0, 0x97, + 0xB4, 0x47, 0x99, 0x76, 0x40, 0x12, 0x9D, 0xA2, + 0x99, 0xB1, 0xA4, 0x7D, 0x1E, 0xB3, 0x75, 0x0B, + 0xA3, 0x08, 0xB0, 0xFE, 0x64, 0xF5, 0xFB, 0xD3 +}; + #endif /* ALL_DH_GROUPS */ - -#define DH_GROUP(id) \ +#define DH_GROUP(id,safe) \ { id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \ -dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) } - +dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime), \ +dh_group ## id ## _order, sizeof(dh_group ## id ## _order), safe } -static struct dh_group dh_groups[] = { - DH_GROUP(5), +static const struct dh_group dh_groups[] = { + DH_GROUP(5, 1), #ifdef ALL_DH_GROUPS - DH_GROUP(1), - DH_GROUP(2), - DH_GROUP(14), - DH_GROUP(15), - DH_GROUP(16), - DH_GROUP(17), - DH_GROUP(18) + DH_GROUP(1, 1), + DH_GROUP(2, 1), + DH_GROUP(14, 1), + DH_GROUP(15, 1), + DH_GROUP(16, 1), + DH_GROUP(17, 1), + DH_GROUP(18, 1), + DH_GROUP(22, 0), + DH_GROUP(23, 0), + DH_GROUP(24, 0) #endif /* ALL_DH_GROUPS */ }; @@ -583,8 +1234,11 @@ dh_init(const struct dh_group *dh, struct wpabuf **priv) pv_len = dh->prime_len; pv = wpabuf_alloc(pv_len); - if (pv == NULL) + if (pv == NULL) { + wpabuf_free(*priv); + *priv = NULL; return NULL; + } if (crypto_mod_exp(dh->generator, dh->generator_len, wpabuf_head(*priv), wpabuf_len(*priv), diff --git a/components/wpa_supplicant/src/crypto/dh_groups.h b/components/wpa_supplicant/src/crypto/dh_groups.h index 5c61539b7..6ce4a2a18 100644 --- a/components/wpa_supplicant/src/crypto/dh_groups.h +++ b/components/wpa_supplicant/src/crypto/dh_groups.h @@ -21,6 +21,9 @@ struct dh_group { size_t generator_len; const u8 *prime; size_t prime_len; + const u8 *order; + size_t order_len; + unsigned int safe_prime:1; }; const struct dh_group * dh_groups_get(int id); diff --git a/components/wpa_supplicant/src/crypto/sha256.c b/components/wpa_supplicant/src/crypto/sha256.c index 3e955b4d4..6534408d3 100644 --- a/components/wpa_supplicant/src/crypto/sha256.c +++ b/components/wpa_supplicant/src/crypto/sha256.c @@ -42,10 +42,10 @@ * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (32 bytes) + * Returns: 0 on success, -1 on failure */ -void -hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) +int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) { unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ unsigned char tk[32]; @@ -57,12 +57,13 @@ hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ - return; + return -1; } /* if key is longer than 64 bytes reset it to key = SHA256(key) */ if (key_len > 64) { - sha256_vector(1, &key, &key_len, tk); + if (sha256_vector(1, &key, &key_len, tk) < 0) + return -1; key = tk; key_len = 32; } @@ -90,7 +91,8 @@ hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } - sha256_vector(1 + num_elem, _addr, _len, mac); + if (sha256_vector(1 + num_elem, _addr, _len, mac) < 0) + return -1; os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); @@ -103,10 +105,9 @@ hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, _len[0] = 64; _addr[1] = mac; _len[1] = SHA256_MAC_LEN; - sha256_vector(2, _addr, _len, mac); + return sha256_vector(2, _addr, _len, mac); } - /** * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104) * @key: Key for HMAC operations @@ -115,14 +116,13 @@ hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, * @data_len: Length of the data area * @mac: Buffer for the hash (20 bytes) */ -void +void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac) + size_t data_len, u8 *mac) { - hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); + hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); } - /** * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) * @key: Key for PRF @@ -132,13 +132,37 @@ hmac_sha256(const u8 *key, size_t key_len, const u8 *data, * @data_len: Length of the data * @buf: Buffer for the generated pseudo-random key * @buf_len: Number of bytes of key to generate + * Returns: 0 on success, -1 on failure * * This function is used to derive new, cryptographically separate keys from a * given key. */ -void -sha256_prf(const u8 *key, size_t key_len, const char *label, +int sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len) +{ + return sha256_prf_bits(key, key_len, label, data, data_len, buf, + buf_len * 8); +} + +/** + * sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function + * @key: Key for KDF + * @key_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @data: Extra data to bind into the key + * @data_len: Length of the data + * @buf: Buffer for the generated pseudo-random key + * @buf_len: Number of bits of key to generate + * Returns: 0 on success, -1 on failure + * + * This function is used to derive new, cryptographically separate keys from a + * given key. If the requested buf_len is not divisible by eight, the least + * significant 1-7 bits of the last octet in the output are not part of the + * requested output. + */ +int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits) { u16 counter = 1; size_t pos, plen; @@ -146,6 +170,7 @@ sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *addr[4]; size_t len[4]; u8 counter_le[2], length_le[2]; + size_t buf_len = (buf_len_bits + 7) / 8; addr[0] = counter_le; len[0] = 2; @@ -156,20 +181,37 @@ sha256_prf(const u8 *key, size_t key_len, const char *label, addr[3] = length_le; len[3] = sizeof(length_le); - WPA_PUT_LE16(length_le, buf_len * 8); + WPA_PUT_LE16(length_le, buf_len_bits); pos = 0; while (pos < buf_len) { plen = buf_len - pos; WPA_PUT_LE16(counter_le, counter); if (plen >= SHA256_MAC_LEN) { - hmac_sha256_vector(key, key_len, 4, addr, len, - &buf[pos]); + if (hmac_sha256_vector(key, key_len, 4, addr, len, + &buf[pos]) < 0) + return -1; pos += SHA256_MAC_LEN; } else { - hmac_sha256_vector(key, key_len, 4, addr, len, hash); + if (hmac_sha256_vector(key, key_len, 4, addr, len, + hash) < 0) + return -1; os_memcpy(&buf[pos], hash, plen); + pos += plen; break; } counter++; } + + /* + * Mask out unused bits in the last octet if it does not use all the + * bits. + */ + if (buf_len_bits % 8) { + u8 mask = 0xff << (8 - buf_len_bits % 8); + buf[pos - 1] &= mask; + } + + os_memset(hash, 0, sizeof(hash)); + + return 0; } diff --git a/components/wpa_supplicant/src/crypto/sha256.h b/components/wpa_supplicant/src/crypto/sha256.h index 0515e2409..aad9434df 100644 --- a/components/wpa_supplicant/src/crypto/sha256.h +++ b/components/wpa_supplicant/src/crypto/sha256.h @@ -17,12 +17,15 @@ #define SHA256_MAC_LEN 32 -void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, +int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); -void sha256_prf(const u8 *key, size_t key_len, const char *label, +int sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits); void tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label, const u8 *seed, size_t seed_len, diff --git a/components/wpa_supplicant/src/utils/common.h b/components/wpa_supplicant/src/utils/common.h index 7a44beda8..57f3d3c29 100644 --- a/components/wpa_supplicant/src/utils/common.h +++ b/components/wpa_supplicant/src/utils/common.h @@ -454,4 +454,6 @@ void * __hide_aliasing_typecast(void *foo); #define WPA_MEM_DEFINED(ptr, len) do { } while (0) #endif /* CONFIG_VALGRIND */ +#define IANA_SECP256R1 19 + #endif /* COMMON_H */ diff --git a/components/wpa_supplicant/test/CMakeLists.txt b/components/wpa_supplicant/test/CMakeLists.txt index 0fd0a625c..e64539d3e 100644 --- a/components/wpa_supplicant/test/CMakeLists.txt +++ b/components/wpa_supplicant/test/CMakeLists.txt @@ -10,3 +10,4 @@ file(MD5 ${esp_supplicant_dir}/src/esp_supplicant/esp_wifi_driver.h WIFI_SUPPLIC string(SUBSTRING "${WIFI_SUPPLICANT_MD5}" 0 7 WIFI_SUPPLICANT_MD5) add_definitions(-DWIFI_SUPPLICANT_MD5=\"${WIFI_SUPPLICANT_MD5}\") +add_definitions(-DCONFIG_WPA3_SAE) diff --git a/components/wpa_supplicant/test/component.mk b/components/wpa_supplicant/test/component.mk index cfec44f29..21e03c8db 100644 --- a/components/wpa_supplicant/test/component.mk +++ b/components/wpa_supplicant/test/component.mk @@ -8,4 +8,4 @@ COMPONENT_SRCDIRS := . COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive WIFI_SUPPLICANT_MD5_VAL=\"$(shell md5sum $(IDF_PATH)/components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h | cut -c 1-7)\" -CFLAGS+=-DWIFI_SUPPLICANT_MD5=$(WIFI_SUPPLICANT_MD5_VAL) +CFLAGS+=-DWIFI_SUPPLICANT_MD5=$(WIFI_SUPPLICANT_MD5_VAL) -DCONFIG_WPA3_SAE diff --git a/components/wpa_supplicant/test/test_sae.c b/components/wpa_supplicant/test/test_sae.c new file mode 100644 index 000000000..b87783d5f --- /dev/null +++ b/components/wpa_supplicant/test/test_sae.c @@ -0,0 +1,270 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifdef CONFIG_WPA3_SAE + +#include +#include +#include +#include +#include +#include "unity.h" +#include +#include "crypto/crypto.h" +#include "../src/common/sae.h" +#include "utils/wpabuf.h" + +typedef struct crypto_bignum crypto_bignum; + +static struct wpabuf *wpabuf_alloc2(size_t len) +{ + struct wpabuf *buf = (struct wpabuf *)os_zalloc(sizeof(struct wpabuf) + len); + if (buf == NULL) + return NULL; + buf->size = len; + return buf; +} + +/** + * * wpabuf_free - Free a wpabuf + * * @buf: wpabuf buffer + * */ +void wpabuf_free2(struct wpabuf *buf) +{ + if (buf == NULL) + return; + os_free(buf->ext_data); + os_free(buf); +} + + + + +TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]") +{ + ESP_LOGI("SAE Test", "### Beginning SAE init and deinit ###"); + { + /* Test init and deinit*/ + struct sae_data sae; + memset(&sae, 0, sizeof(sae)); + TEST_ASSERT(sae_set_group(&sae, IANA_SECP256R1) == 0); + sae_clear_temp_data(&sae); + sae_clear_data(&sae); + + } + ESP_LOGI("SAE Test", "=========== Complete ============"); + + ESP_LOGI("SAE Test", "### Beginning SAE commit msg formation and parsing ###"); + { + /* Test SAE commit msg formation and parsing*/ + struct sae_data sae; + u8 addr1[ETH_ALEN] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11}; + u8 addr2[ETH_ALEN] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + u8 pwd[] = "ESP32-WPA3"; + struct wpabuf *buf; + int default_groups[] = { IANA_SECP256R1, 0 }; + + memset(&sae, 0, sizeof(sae)); + + TEST_ASSERT(sae_set_group(&sae, IANA_SECP256R1) == 0); + + TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), NULL, &sae) == 0); + + buf = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + + TEST_ASSERT( buf != NULL); + + sae_write_commit(&sae, buf, NULL);// No anti-clogging token + + /* Parsing commit created by self will be detected as reflection attack*/ + TEST_ASSERT(sae_parse_commit(&sae, + wpabuf_mhead(buf), buf->used, NULL, 0, default_groups) == SAE_SILENTLY_DISCARD); + + wpabuf_free2(buf); + sae_clear_temp_data(&sae); + sae_clear_data(&sae); + + } + ESP_LOGI("SAE Test", "=========== Complete ============"); + + ESP_LOGI("SAE Test", "### Beginning SAE handshake ###"); + { + /* SAE handshake*/ + struct sae_data sae1; // STA1 data + struct sae_data sae2; // STA2 data + u8 addr1[ETH_ALEN] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11}; + u8 addr2[ETH_ALEN] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + u8 pwd[] = "ESP32-WPA3"; + + memset(&sae1, 0, sizeof(sae1)); + memset(&sae2, 0, sizeof(sae2)); + + struct wpabuf *buf1, *buf2, *buf3, *buf4; + int default_groups[] = { IANA_SECP256R1, 0 }; + + TEST_ASSERT(sae_set_group(&sae1, IANA_SECP256R1) == 0); + TEST_ASSERT(sae_set_group(&sae2, IANA_SECP256R1) == 0); + + /* STA1 prepares for commit*/ + TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), NULL, &sae1) == 0); + + /* STA2 prepares for commit*/ + TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd, strlen((const char *)pwd), NULL, &sae2) == 0); + + /* STA1 creates commit msg buffer*/ + buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + TEST_ASSERT( buf1 != NULL); + sae_write_commit(&sae1, buf1, NULL);// No anti-clogging token + ESP_LOG_BUFFER_HEXDUMP("SAE: Commit1", wpabuf_mhead_u8(buf1), wpabuf_len(buf1), ESP_LOG_INFO); + + + /* STA2 creates commit msg buffer*/ + buf2 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + TEST_ASSERT( buf2 != NULL); + sae_write_commit(&sae2, buf2, NULL);// No anti-clogging token + ESP_LOG_BUFFER_HEXDUMP("SAE: Commit2", wpabuf_mhead_u8(buf2), wpabuf_len(buf2), ESP_LOG_INFO); + + sae1.state = SAE_COMMITTED; + sae2.state = SAE_COMMITTED; + + /* STA1 parses STA2 commit*/ + TEST_ASSERT(sae_parse_commit(&sae1, + wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups) == 0); + + /* STA2 parses STA1 commit*/ + TEST_ASSERT(sae_parse_commit(&sae2, + wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups) == 0); + + /* STA1 processes commit*/ + TEST_ASSERT(sae_process_commit(&sae1) == 0); + + /* STA2 processes commit*/ + TEST_ASSERT(sae_process_commit(&sae2) == 0); + + /* STA1 creates confirm msg buffer*/ + buf3 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + TEST_ASSERT( buf3 != NULL); + sae_write_confirm(&sae1, buf3); + ESP_LOG_BUFFER_HEXDUMP("SAE: Confirm1", wpabuf_mhead_u8(buf3), wpabuf_len(buf3), ESP_LOG_INFO); + + /* STA2 creates confirm msg buffer*/ + buf4 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + TEST_ASSERT( buf3 != NULL); + sae_write_confirm(&sae2, buf4); + ESP_LOG_BUFFER_HEXDUMP("SAE: Confirm2", wpabuf_mhead_u8(buf4), wpabuf_len(buf4), ESP_LOG_INFO); + + /* STA1 checks confirm from STA2*/ + TEST_ASSERT(sae_check_confirm(&sae1, wpabuf_mhead(buf4), buf4->used) == 0); + + /* STA2 checks confirm from STA1*/ + TEST_ASSERT(sae_check_confirm(&sae2, wpabuf_mhead(buf3), buf3->used) == 0); + + ESP_LOG_BUFFER_HEXDUMP("SAE: PMK1", sae1.pmk, SAE_PMK_LEN, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEXDUMP("SAE: PMK2", sae2.pmk, SAE_PMK_LEN, ESP_LOG_INFO); + + wpabuf_free2(buf1); + wpabuf_free2(buf2); + wpabuf_free2(buf3); + wpabuf_free2(buf4); + sae_clear_temp_data(&sae1); + sae_clear_temp_data(&sae2); + sae_clear_data(&sae1); + sae_clear_data(&sae2); + + } + ESP_LOGI("SAE Test", "=========== Complete ============"); + + ESP_LOGI("SAE Test", "### SAE handshake negative testcase. ###"); + { + /* SAE handshake failure when different passwords are used.*/ + struct sae_data sae1; // STA1 data + struct sae_data sae2; // STA2 data + u8 addr1[ETH_ALEN] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x11}; + u8 addr2[ETH_ALEN] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + u8 pwd1[] = "abcd1234"; + u8 pwd2[] = "wxyz5678"; + + memset(&sae1, 0, sizeof(sae1)); + memset(&sae2, 0, sizeof(sae2)); + + struct wpabuf *buf1, *buf2, *buf3, *buf4; + int default_groups[] = { IANA_SECP256R1, 0 }; + + TEST_ASSERT(sae_set_group(&sae1, IANA_SECP256R1) == 0); + TEST_ASSERT(sae_set_group(&sae2, IANA_SECP256R1) == 0); + + /* STA1 prepares for commit*/ + TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd1, strlen((const char *)pwd), NULL, &sae1) == 0); + + /* STA2 prepares for commit*/ + TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd), NULL, &sae2) == 0); + + /* STA1 creates commit msg buffer*/ + buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + TEST_ASSERT( buf1 != NULL); + sae_write_commit(&sae1, buf1, NULL);// No anti-clogging token + + /* STA2 creates commit msg buffer*/ + buf2 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + TEST_ASSERT( buf2 != NULL); + sae_write_commit(&sae2, buf2, NULL);// No anti-clogging token + + sae1.state = SAE_COMMITTED; + sae2.state = SAE_COMMITTED; + + /* STA1 parses STA2 commit*/ + TEST_ASSERT(sae_parse_commit(&sae1, + wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups) == 0); + + /* STA2 parses STA1 commit*/ + TEST_ASSERT(sae_parse_commit(&sae2, + wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups) == 0); + + /* STA1 processes commit*/ + TEST_ASSERT(sae_process_commit(&sae1) == 0); + + /* STA2 processes commit*/ + TEST_ASSERT(sae_process_commit(&sae2) == 0); + + /* STA1 creates confirm msg buffer*/ + buf3 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + TEST_ASSERT( buf3 != NULL); + sae_write_confirm(&sae1, buf3); + + /* STA2 creates confirm msg buffer*/ + buf4 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN); + TEST_ASSERT( buf3 != NULL); + sae_write_confirm(&sae2, buf4); + + /* STA1 checks confirm from STA2 and the check fails*/ + TEST_ASSERT(sae_check_confirm(&sae1, wpabuf_mhead(buf4), buf4->used) != 0); + + /* STA2 checks confirm from STA1 and the check fails*/ + TEST_ASSERT(sae_check_confirm(&sae2, wpabuf_mhead(buf3), buf3->used) != 0); + + wpabuf_free2(buf1); + wpabuf_free2(buf2); + wpabuf_free2(buf3); + wpabuf_free2(buf4); + sae_clear_temp_data(&sae1); + sae_clear_temp_data(&sae2); + sae_clear_data(&sae1); + sae_clear_data(&sae2); + + } + ESP_LOGI("SAE Test", "=========== Complete ============"); + +} + +#endif /* CONFIG_WPA3_SAE */