kopia lustrzana https://github.com/espressif/esp-idf
wpa_supplicant: Support WPA3 4-way handshake, add config option
1. Add changes in 4-way handshake path to allow SAE key mgmt. 2. Support for configuring WAP3 at init time, added Kconfig option. 3. Handle and propagate error conditions properly.pull/5815/head
rodzic
6b76228fcb
commit
d36663b798
|
@ -295,6 +295,14 @@ menu "Wi-Fi"
|
|||
When this option is disabled, more than 17Kbytes of IRAM memory will be saved
|
||||
but Wi-Fi performance will be reduced.
|
||||
|
||||
config ESP32_WIFI_ENABLE_WPA3_SAE
|
||||
bool "Enable WPA3-Personal"
|
||||
default n
|
||||
help
|
||||
Select this option to allow the device to establish a WPA3-Personal connection with eligible AP's.
|
||||
PMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be
|
||||
explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details.
|
||||
|
||||
endmenu # Wi-Fi
|
||||
|
||||
menu "PHY"
|
||||
|
|
|
@ -110,6 +110,7 @@ typedef struct {
|
|||
int wifi_task_core_id; /**< WiFi Task Core ID */
|
||||
int beacon_max_len; /**< WiFi softAP maximum length of the beacon */
|
||||
int mgmt_sbuf_num; /**< WiFi management short buffer number, the minimum value is 6, the maximum value is 32 */
|
||||
uint64_t feature_caps; /**< Enables additional WiFi features and capabilities */
|
||||
int magic; /**< WiFi init magic number, it should be the last field */
|
||||
} wifi_init_config_t;
|
||||
|
||||
|
@ -156,6 +157,7 @@ typedef struct {
|
|||
#endif
|
||||
|
||||
extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
|
||||
extern uint64_t g_wifi_feature_caps;
|
||||
|
||||
#define WIFI_INIT_CONFIG_MAGIC 0x1F2F3F4F
|
||||
|
||||
|
@ -189,6 +191,8 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
|
|||
#define WIFI_MGMT_SBUF_NUM 32
|
||||
#endif
|
||||
|
||||
#define CONFIG_FEATURE_WPA3_SAE_BIT (1<<0)
|
||||
|
||||
#define WIFI_INIT_CONFIG_DEFAULT() { \
|
||||
.event_handler = &esp_event_send, \
|
||||
.osi_funcs = &g_wifi_osi_funcs, \
|
||||
|
@ -208,6 +212,7 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
|
|||
.wifi_task_core_id = WIFI_TASK_CORE_ID,\
|
||||
.beacon_max_len = WIFI_SOFTAP_BEACON_MAX_LEN, \
|
||||
.mgmt_sbuf_num = WIFI_MGMT_SBUF_NUM, \
|
||||
.feature_caps = g_wifi_feature_caps, \
|
||||
.magic = WIFI_INIT_CONFIG_MAGIC\
|
||||
};
|
||||
|
||||
|
|
|
@ -37,6 +37,13 @@ static esp_pm_lock_handle_t s_wifi_modem_sleep_lock;
|
|||
/* Callback function to update WiFi MAC time */
|
||||
wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb = NULL;
|
||||
|
||||
/* Set additional WiFi features and capabilities */
|
||||
uint64_t g_wifi_feature_caps =
|
||||
#if CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE
|
||||
CONFIG_FEATURE_WPA3_SAE_BIT |
|
||||
#endif
|
||||
0;
|
||||
|
||||
static const char* TAG = "wifi_init";
|
||||
|
||||
static void __attribute__((constructor)) s_set_default_wifi_log_level()
|
||||
|
|
|
@ -2,4 +2,4 @@ COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant
|
|||
COMPONENT_PRIV_INCLUDEDIRS := src
|
||||
COMPONENT_SRCDIRS := port src/ap src/common src/crypto src/eap_peer src/rsn_supp src/tls src/utils src/esp_supplicant src/wps
|
||||
|
||||
CFLAGS += -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing
|
||||
CFLAGS += -DCONFIG_WPA3_SAE -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing
|
||||
|
|
|
@ -50,6 +50,7 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
|
|||
WPA_KEY_MGMT_FT_IEEE8021X |
|
||||
WPA_KEY_MGMT_CCKM |
|
||||
WPA_KEY_MGMT_OSEN |
|
||||
WPA_KEY_MGMT_SAE |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256 |
|
||||
WPA_KEY_MGMT_IEEE8021X_SUITE_B |
|
||||
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
|
||||
|
@ -82,6 +83,7 @@ static inline int wpa_key_mgmt_sha256(int akm)
|
|||
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
|
||||
WPA_KEY_MGMT_IEEE8021X_SHA256 |
|
||||
WPA_KEY_MGMT_OSEN |
|
||||
WPA_KEY_MGMT_SAE |
|
||||
WPA_KEY_MGMT_IEEE8021X_SUITE_B));
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ int sae_set_group(struct sae_data *sae, int group)
|
|||
sae_clear_data(sae);
|
||||
tmp = sae->tmp = os_zalloc(sizeof(*tmp));
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
|
||||
/* First, check if this is an ECC group */
|
||||
tmp->ec = crypto_ec_init(group);
|
||||
|
@ -53,7 +53,7 @@ int sae_set_group(struct sae_data *sae, int 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;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Not an ECC group, check FFC */
|
||||
|
@ -65,14 +65,14 @@ int sae_set_group(struct sae_data *sae, int group)
|
|||
tmp->prime_len = tmp->dh->prime_len;
|
||||
if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
|
||||
sae_clear_data(sae);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime,
|
||||
tmp->prime_len);
|
||||
if (tmp->prime_buf == NULL) {
|
||||
sae_clear_data(sae);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
tmp->prime = tmp->prime_buf;
|
||||
|
||||
|
@ -80,17 +80,17 @@ int sae_set_group(struct sae_data *sae, int group)
|
|||
tmp->dh->order_len);
|
||||
if (tmp->order_buf == NULL) {
|
||||
sae_clear_data(sae);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
tmp->order = tmp->order_buf;
|
||||
|
||||
return 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Unsupported group */
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"SAE: Group %d not supported by the crypto library", group);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
void sae_clear_temp_data(struct sae_data *sae)
|
||||
|
@ -236,7 +236,7 @@ static int is_quadratic_residue_blind(struct sae_data *sae,
|
|||
*/
|
||||
r = get_rand_1_to_p_1(prime, sae->tmp->prime_len, bits, &r_odd);
|
||||
if (!r)
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
|
||||
num = crypto_bignum_init();
|
||||
if (!num ||
|
||||
|
@ -293,22 +293,22 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
|
|||
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;
|
||||
return ESP_FAIL;
|
||||
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;
|
||||
return ESP_OK;
|
||||
|
||||
x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
|
||||
if (!x_cand)
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
|
||||
if (!y_sqr) {
|
||||
crypto_bignum_deinit(x_cand, 1);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr);
|
||||
|
@ -337,14 +337,14 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
|
|||
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;
|
||||
return ESP_FAIL;
|
||||
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;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* PWE = pwd-value^((p-1)/r) modulo p */
|
||||
|
@ -380,13 +380,13 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
|
|||
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* if (PWE > 1) --> found */
|
||||
if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
|
||||
return 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "SAE: PWE found");
|
||||
|
@ -450,12 +450,12 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
|||
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;
|
||||
return ESP_FAIL;
|
||||
|
||||
prime_len = sae->tmp->prime_len;
|
||||
if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
|
||||
prime_len) < 0)
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
bits = crypto_ec_prime_len_bits(sae->tmp->ec);
|
||||
|
||||
/*
|
||||
|
@ -464,7 +464,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
|||
*/
|
||||
if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
|
||||
&qr, &qnr) < 0)
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
|
||||
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
|
||||
password, password_len);
|
||||
|
@ -579,7 +579,7 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
|
|||
if (sae->tmp->pwe_ffc == NULL) {
|
||||
sae->tmp->pwe_ffc = crypto_bignum_init();
|
||||
if (sae->tmp->pwe_ffc == NULL)
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
|
||||
|
@ -638,7 +638,7 @@ static int sae_derive_commit_element_ecc(struct sae_data *sae,
|
|||
sae->tmp->own_commit_element_ecc =
|
||||
crypto_ec_point_init(sae->tmp->ec);
|
||||
if (!sae->tmp->own_commit_element_ecc)
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
|
||||
|
@ -646,10 +646,10 @@ static int sae_derive_commit_element_ecc(struct sae_data *sae,
|
|||
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 ESP_FAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int sae_derive_commit_element_ffc(struct sae_data *sae,
|
||||
|
@ -659,7 +659,7 @@ static int sae_derive_commit_element_ffc(struct sae_data *sae,
|
|||
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;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
|
||||
|
@ -668,10 +668,10 @@ static int sae_derive_commit_element_ffc(struct sae_data *sae,
|
|||
sae->tmp->prime,
|
||||
sae->tmp->own_commit_element_ffc) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int sae_derive_commit(struct sae_data *sae)
|
||||
|
@ -689,13 +689,13 @@ static int sae_derive_commit(struct sae_data *sae)
|
|||
* theoretical infinite loop, break out after 100
|
||||
* attemps.
|
||||
*/
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
mask = sae_get_rand_and_mask(sae);
|
||||
if (mask == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* commit-scalar = (rand + mask) modulo r */
|
||||
|
@ -733,8 +733,8 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
|||
password_len,
|
||||
identifier) < 0) ||
|
||||
sae_derive_commit(sae) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
return ESP_FAIL;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
|
||||
|
@ -861,17 +861,17 @@ int sae_process_commit(struct sae_data *sae)
|
|||
(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;
|
||||
return ESP_FAIL;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
||||
int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
||||
const struct wpabuf *token, const char *identifier)
|
||||
{
|
||||
u8 *pos;
|
||||
|
||||
if (sae->tmp == NULL)
|
||||
return;
|
||||
return ESP_FAIL;
|
||||
|
||||
wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
|
||||
if (token) {
|
||||
|
@ -880,23 +880,32 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
|||
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);
|
||||
if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
|
||||
sae->tmp->prime_len, sae->tmp->prime_len) < 0) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed bignum operation on own commit scalar");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
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);
|
||||
if (crypto_ec_point_to_bin(sae->tmp->ec,
|
||||
sae->tmp->own_commit_element_ecc,
|
||||
pos, pos + sae->tmp->prime_len) < 0) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed bignum op while deriving ec point");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
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);
|
||||
if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
|
||||
sae->tmp->prime_len, sae->tmp->prime_len) < 0) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed bignum operation on commit elem ffc");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
|
||||
pos, sae->tmp->prime_len);
|
||||
}
|
||||
|
@ -910,6 +919,7 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
|||
wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s",
|
||||
identifier);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
|
||||
|
@ -1299,7 +1309,7 @@ static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
|
|||
confirm);
|
||||
}
|
||||
|
||||
static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
|
||||
static int 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,
|
||||
|
@ -1309,40 +1319,54 @@ static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
|
|||
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);
|
||||
if (crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
|
||||
element_b1 + sae->tmp->prime_len) < 0) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed bignum op while deriving ec point");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
|
||||
element_b2 + sae->tmp->prime_len) < 0) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed bignum op while deriving ec point");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len,
|
||||
scalar2, element_b2, 2 * sae->tmp->prime_len, confirm);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
static int 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);
|
||||
if (crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
|
||||
sae->tmp->prime_len) < 0) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed bignum op while generating SAE confirm - e1");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
|
||||
sae->tmp->prime_len) < 0) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed bignum op while generating SAE confirm - e2");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
|
||||
scalar2, element_b2, sae->tmp->prime_len, confirm);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
|
||||
int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
|
||||
{
|
||||
const u8 *sc;
|
||||
|
||||
if (sae->tmp == NULL)
|
||||
return;
|
||||
return ESP_FAIL;
|
||||
|
||||
/* Send-Confirm */
|
||||
sc = wpabuf_put(buf, 0);
|
||||
|
@ -1350,18 +1374,26 @@ void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
|
|||
if (sae->send_confirm < 0xffff)
|
||||
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));
|
||||
if (sae->tmp->ec) {
|
||||
if (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))) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed generate SAE confirm (ecc)");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
if (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))) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed generate SAE confirm (ffc)");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
|
||||
|
@ -1370,28 +1402,35 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
|
|||
|
||||
if (len < 2 + SHA256_MAC_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
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;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
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 (sae->tmp->ec) {
|
||||
if (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)) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed to check SAE confirm (ecc)");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
if (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)) {
|
||||
wpa_printf(MSG_ERROR, "SAE: failed check SAE confirm (ffc)");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
|
||||
|
@ -1399,10 +1438,10 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
|
|||
data + 2, SHA256_MAC_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
|
||||
verifier, SHA256_MAC_LEN);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const char * sae_state_txt(enum sae_state state)
|
||||
|
|
|
@ -77,11 +77,11 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
|||
const u8 *password, size_t password_len,
|
||||
const char *identifier, struct sae_data *sae);
|
||||
int sae_process_commit(struct sae_data *sae);
|
||||
void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
||||
int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
||||
const struct wpabuf *token, const char *identifier);
|
||||
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_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);
|
||||
const char * sae_state_txt(enum sae_state state);
|
||||
|
|
|
@ -394,6 +394,9 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
|
|||
memcpy(mic, hash, MD5_MAC_LEN);
|
||||
break;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#ifdef CONFIG_WPA3_SAE
|
||||
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
|
||||
#endif
|
||||
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
|
||||
return omac1_aes_128(key, buf, len, mic);
|
||||
#endif
|
||||
|
@ -514,13 +517,11 @@ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
|
|||
WPA_NONCE_LEN);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (use_sha256) {
|
||||
sha256_prf(pmk, pmk_len, label, data, sizeof(data),
|
||||
ptk, ptk_len);
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
{
|
||||
sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len);
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@
|
|||
|
||||
/* IEEE 802.11, 8.5.2 EAPOL-Key frames */
|
||||
#define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2)))
|
||||
#define WPA_KEY_INFO_TYPE_AKM_DEFINED 0
|
||||
#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)
|
||||
#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)
|
||||
#define WPA_KEY_INFO_TYPE_AES_128_CMAC 3
|
||||
|
|
|
@ -24,11 +24,16 @@
|
|||
|
||||
int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
|
||||
int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
|
||||
int __must_check omac1_aes_vector(const u8 *key, size_t key_len,
|
||||
size_t num_elem, const u8 *addr[],
|
||||
const size_t *len, u8 *mac);
|
||||
int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
|
||||
u8 *mac);
|
||||
int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len,
|
||||
u8 *mac);
|
||||
int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
|
||||
int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
|
||||
u8 *data, size_t data_len);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#ifdef CONFIG_WPA3_SAE
|
||||
|
||||
#include "../common/sae.h"
|
||||
#include "common/sae.h"
|
||||
#include "esp_wifi_driver.h"
|
||||
#include "rsn_supp/wpa.h"
|
||||
|
||||
|
@ -47,11 +47,17 @@ static struct wpabuf *wpa3_build_sae_commit(u8 *bssid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// For reuse PWE after retry case
|
||||
// memcpy(g_sae_data.tmp->bssid, bssid, ETH_ALEN);
|
||||
|
||||
buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
|
||||
sae_write_commit(&g_sae_data, buf, NULL, NULL); //no token
|
||||
if (!buf) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for commit msg");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sae_write_commit(&g_sae_data, buf, NULL, NULL) != ESP_OK) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: failed to write SAE commit msg");
|
||||
wpabuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
g_sae_data.state = SAE_COMMITTED;
|
||||
|
||||
return buf;
|
||||
|
@ -65,7 +71,16 @@ static struct wpabuf *wpa3_build_sae_confirm(void)
|
|||
return NULL;
|
||||
|
||||
buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
|
||||
sae_write_confirm(&g_sae_data, buf);
|
||||
if (!buf) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for confirm msg");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sae_write_confirm(&g_sae_data, buf) != ESP_OK) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: failed to write SAE confirm msg");
|
||||
wpabuf_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
g_sae_data.state = SAE_CONFIRMED;
|
||||
|
||||
return buf;
|
||||
|
@ -100,22 +115,22 @@ static int wpa3_parse_sae_commit(u8 *buf, u32 len)
|
|||
if (g_sae_data.state != SAE_COMMITTED) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
|
||||
g_sae_data.state);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ret = sae_process_commit(&g_sae_data);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: could not process commit(%d)", ret);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
|
||||
|
@ -123,21 +138,24 @@ static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
|
|||
if (g_sae_data.state != SAE_CONFIRMED) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
|
||||
g_sae_data.state);
|
||||
return -1;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
sae_check_confirm(&g_sae_data, buf, len);
|
||||
if (sae_check_confirm(&g_sae_data, buf, len) != ESP_OK) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE confirm");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
g_sae_data.state = SAE_ACCEPTED;
|
||||
|
||||
wpa_set_pmk(g_sae_data.pmk);
|
||||
memcpy(esp_wifi_sta_get_ap_info_prof_pmk_internal(), g_sae_data.pmk, PMK_LEN);
|
||||
|
||||
return 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int wpa3_parse_sae_msg(u8 *buf, u32 len, u32 sae_msg_type)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = ESP_OK;
|
||||
|
||||
switch (sae_msg_type) {
|
||||
case SAE_MSG_COMMIT:
|
||||
|
@ -149,7 +167,7 @@ static int wpa3_parse_sae_msg(u8 *buf, u32 len, u32 sae_msg_type)
|
|||
default:
|
||||
wpa_printf(MSG_ERROR, "wpa3: Invalid SAE msg type(%d)!",
|
||||
sae_msg_type);
|
||||
ret = -1;
|
||||
ret = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -245,6 +245,8 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
|
|||
ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
|
||||
else if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
|
||||
ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
|
||||
else if (sm->key_mgmt == WPA_KEY_MGMT_SAE)
|
||||
ver = 0;
|
||||
else
|
||||
ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
|
||||
|
||||
|
@ -1661,7 +1663,8 @@ failed:
|
|||
return -1;
|
||||
}
|
||||
} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
|
||||
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
|
||||
sm->key_mgmt == WPA_KEY_MGMT_SAE) {
|
||||
u8 *buf;
|
||||
if (keydatalen % 8) {
|
||||
#ifdef DEBUG_PRINT
|
||||
|
@ -1832,6 +1835,9 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
|
|||
if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
|
||||
#ifdef CONFIG_WPA3_SAE
|
||||
sm->key_mgmt != WPA_KEY_MGMT_SAE &&
|
||||
#endif
|
||||
#endif
|
||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
|
||||
#ifdef DEBUG_PRINT
|
||||
|
@ -1843,14 +1849,16 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
|
|||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
|
||||
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
|
||||
sm->key_mgmt != WPA_KEY_MGMT_SAE) {
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
||||
if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
|
||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
|
||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
|
||||
sm->key_mgmt != WPA_KEY_MGMT_SAE) {
|
||||
#ifdef DEBUG_PRINT
|
||||
wpa_printf(MSG_DEBUG, "WPA: CCMP is used, but EAPOL-Key "
|
||||
"descriptor version (%d) is not 2.", ver);
|
||||
|
@ -2073,8 +2081,6 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode)
|
|||
sm->proto = wpa_proto;
|
||||
if (auth_mode == WPA2_AUTH_ENT) {
|
||||
sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X; /* for wpa2 enterprise */
|
||||
} else if (auth_mode == WPA2_AUTH_PSK) {
|
||||
sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */
|
||||
} else if (auth_mode == WPA2_AUTH_PSK_SHA256) {
|
||||
sm->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
|
||||
} else if (auth_mode == WPA3_AUTH_PSK) {
|
||||
|
|
|
@ -85,7 +85,7 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
|
|||
|
||||
TEST_ASSERT( buf != NULL);
|
||||
|
||||
sae_write_commit(&sae, buf, NULL);// No anti-clogging token
|
||||
sae_write_commit(&sae, buf, NULL, NULL);// No anti-clogging token
|
||||
|
||||
/* Parsing commit created by self will be detected as reflection attack*/
|
||||
TEST_ASSERT(sae_parse_commit(&sae,
|
||||
|
@ -125,14 +125,14 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
|
|||
/* 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
|
||||
sae_write_commit(&sae1, buf1, NULL, 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
|
||||
sae_write_commit(&sae2, buf2, NULL, 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;
|
||||
|
@ -205,20 +205,20 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
|
|||
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);
|
||||
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd1, strlen((const char *)pwd1), NULL, &sae1) == 0);
|
||||
|
||||
/* STA2 prepares for commit*/
|
||||
TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd), NULL, &sae2) == 0);
|
||||
TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd2), 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
|
||||
sae_write_commit(&sae1, buf1, NULL, 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
|
||||
sae_write_commit(&sae2, buf2, NULL, NULL);// No anti-clogging token
|
||||
|
||||
sae1.state = SAE_COMMITTED;
|
||||
sae2.state = SAE_COMMITTED;
|
||||
|
|
Ładowanie…
Reference in New Issue