wlantest: Key derivation for SAE-EXT-KEY
Extend wlantest capabilities to cover the new SAE-EXT-KEY AKM and variable length MIC field and key lengths for it based on the used SAE group. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
2e0400061f
commit
7f20a0a0bc
4 changed files with 132 additions and 38 deletions
|
@ -25,6 +25,7 @@ CFLAGS += -DCONFIG_SAE
|
||||||
CFLAGS += -DCONFIG_OWE
|
CFLAGS += -DCONFIG_OWE
|
||||||
CFLAGS += -DCONFIG_DPP
|
CFLAGS += -DCONFIG_DPP
|
||||||
CFLAGS += -DCONFIG_SHA384
|
CFLAGS += -DCONFIG_SHA384
|
||||||
|
CFLAGS += -DCONFIG_SHA512
|
||||||
CFLAGS += -DCONFIG_PASN
|
CFLAGS += -DCONFIG_PASN
|
||||||
|
|
||||||
OBJS += ../src/common/ieee802_11_common.o
|
OBJS += ../src/common/ieee802_11_common.o
|
||||||
|
|
|
@ -31,15 +31,35 @@ static int is_zero(const u8 *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver,
|
static size_t determine_mic_len(struct wlantest_sta *sta)
|
||||||
const u8 *data, size_t len)
|
{
|
||||||
|
size_t pmk_len = PMK_LEN;
|
||||||
|
|
||||||
|
if (sta && wpa_key_mgmt_sae_ext_key(sta->key_mgmt) &&
|
||||||
|
sta->sae_group) {
|
||||||
|
switch (sta->sae_group) {
|
||||||
|
case 20:
|
||||||
|
pmk_len = 48;
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
pmk_len = 64;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wpa_mic_len(sta->key_mgmt, pmk_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int check_mic(struct wlantest_sta *sta, const u8 *kck, size_t kck_len,
|
||||||
|
int ver, const u8 *data, size_t len)
|
||||||
{
|
{
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct ieee802_1x_hdr *hdr;
|
struct ieee802_1x_hdr *hdr;
|
||||||
struct wpa_eapol_key *key;
|
struct wpa_eapol_key *key;
|
||||||
u8 rx_mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
|
u8 rx_mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
|
||||||
size_t mic_len = wpa_mic_len(akmp, PMK_LEN);
|
size_t mic_len = determine_mic_len(sta);
|
||||||
|
|
||||||
buf = os_memdup(data, len);
|
buf = os_memdup(data, len);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
|
@ -50,7 +70,7 @@ static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver,
|
||||||
os_memcpy(rx_mic, key + 1, mic_len);
|
os_memcpy(rx_mic, key + 1, mic_len);
|
||||||
os_memset(key + 1, 0, mic_len);
|
os_memset(key + 1, 0, mic_len);
|
||||||
|
|
||||||
if (wpa_eapol_key_mic(kck, kck_len, akmp, ver, buf, len,
|
if (wpa_eapol_key_mic(kck, kck_len, sta->key_mgmt, ver, buf, len,
|
||||||
(u8 *) (key + 1)) == 0 &&
|
(u8 *) (key + 1)) == 0 &&
|
||||||
os_memcmp(rx_mic, key + 1, mic_len) == 0)
|
os_memcmp(rx_mic, key + 1, mic_len) == 0)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -70,7 +90,7 @@ static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
const struct ieee802_1x_hdr *eapol;
|
const struct ieee802_1x_hdr *eapol;
|
||||||
const struct wpa_eapol_key *hdr;
|
const struct wpa_eapol_key *hdr;
|
||||||
const u8 *key_data, *mic;
|
const u8 *key_data, *mic;
|
||||||
size_t mic_len;
|
size_t mic_len, left;
|
||||||
u16 key_data_len;
|
u16 key_data_len;
|
||||||
struct wpa_eapol_ie_parse ie;
|
struct wpa_eapol_ie_parse ie;
|
||||||
|
|
||||||
|
@ -94,7 +114,14 @@ static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
|
|
||||||
eapol = (const struct ieee802_1x_hdr *) data;
|
eapol = (const struct ieee802_1x_hdr *) data;
|
||||||
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
||||||
mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN);
|
left = len - sizeof(*hdr);
|
||||||
|
mic_len = determine_mic_len(sta);
|
||||||
|
if (mic_len > left) {
|
||||||
|
add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
|
||||||
|
" has a truncated MIC field", MAC2STR(src));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
left -= mic_len;
|
||||||
mic = (const u8 *) (hdr + 1);
|
mic = (const u8 *) (hdr + 1);
|
||||||
if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) {
|
if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) {
|
||||||
add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
|
add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
|
||||||
|
@ -105,8 +132,21 @@ static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
" used non-zero Key RSC", MAC2STR(src));
|
" used non-zero Key RSC", MAC2STR(src));
|
||||||
}
|
}
|
||||||
os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
|
os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
|
||||||
|
if (left < 2) {
|
||||||
|
add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
|
||||||
|
" has a truncated Key Data Length field",
|
||||||
|
MAC2STR(src));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
left -= 2;
|
||||||
key_data = mic + mic_len + 2;
|
key_data = mic + mic_len + 2;
|
||||||
key_data_len = WPA_GET_BE16(mic + mic_len);
|
key_data_len = WPA_GET_BE16(mic + mic_len);
|
||||||
|
if (key_data_len > left) {
|
||||||
|
add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
|
||||||
|
" has a truncated Key Data field",
|
||||||
|
MAC2STR(src));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (wpa_parse_kde_ies(key_data, key_data_len, &ie) < 0) {
|
if (wpa_parse_kde_ies(key_data, key_data_len, &ie) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
|
add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
|
||||||
|
@ -166,16 +206,14 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
|
||||||
aa, sta->pmk_r1_name,
|
aa, sta->pmk_r1_name,
|
||||||
&ptk, ptk_name, sta->key_mgmt,
|
&ptk, ptk_name, sta->key_mgmt,
|
||||||
sta->pairwise_cipher, 0) < 0 ||
|
sta->pairwise_cipher, 0) < 0 ||
|
||||||
check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data,
|
check_mic(sta, ptk.kck, ptk.kck_len, ver, data, len) < 0)
|
||||||
len) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
} else if (wpa_pmk_to_ptk(pmk->pmk, pmk->pmk_len,
|
} else if (wpa_pmk_to_ptk(pmk->pmk, pmk->pmk_len,
|
||||||
"Pairwise key expansion",
|
"Pairwise key expansion",
|
||||||
aa, sa, sta->anonce,
|
aa, sa, sta->anonce,
|
||||||
sta->snonce, &ptk, sta->key_mgmt,
|
sta->snonce, &ptk, sta->key_mgmt,
|
||||||
sta->pairwise_cipher, NULL, 0, 0) < 0 ||
|
sta->pairwise_cipher, NULL, 0, 0) < 0 ||
|
||||||
check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data,
|
check_mic(sta, ptk.kck, ptk.kck_len, ver, data, len) < 0) {
|
||||||
len) < 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,8 +283,8 @@ static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
|
||||||
|
|
||||||
wpa_debug_level = MSG_WARNING;
|
wpa_debug_level = MSG_WARNING;
|
||||||
dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
|
dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
|
||||||
if (check_mic(ptk->ptk.kck, ptk->ptk.kck_len,
|
if (check_mic(sta, ptk->ptk.kck, ptk->ptk.kck_len,
|
||||||
sta->key_mgmt, ver, data, len) < 0)
|
ver, data, len) < 0)
|
||||||
continue;
|
continue;
|
||||||
wpa_printf(MSG_INFO, "Pre-set PTK matches for STA "
|
wpa_printf(MSG_INFO, "Pre-set PTK matches for STA "
|
||||||
MACSTR " BSSID " MACSTR,
|
MACSTR " BSSID " MACSTR,
|
||||||
|
@ -300,7 +338,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
const struct ieee802_1x_hdr *eapol;
|
const struct ieee802_1x_hdr *eapol;
|
||||||
const struct wpa_eapol_key *hdr;
|
const struct wpa_eapol_key *hdr;
|
||||||
const u8 *key_data, *kck, *mic;
|
const u8 *key_data, *kck, *mic;
|
||||||
size_t kck_len, mic_len;
|
size_t kck_len, mic_len, left;
|
||||||
u16 key_info, key_data_len;
|
u16 key_info, key_data_len;
|
||||||
struct wpa_eapol_ie_parse ie;
|
struct wpa_eapol_ie_parse ie;
|
||||||
int link_id;
|
int link_id;
|
||||||
|
@ -325,7 +363,14 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
|
|
||||||
eapol = (const struct ieee802_1x_hdr *) data;
|
eapol = (const struct ieee802_1x_hdr *) data;
|
||||||
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
||||||
mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN);
|
left = len - sizeof(*hdr);
|
||||||
|
mic_len = determine_mic_len(sta);
|
||||||
|
if (mic_len > left) {
|
||||||
|
add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
|
||||||
|
" has a truncated MIC field", MAC2STR(src));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
left -= mic_len;
|
||||||
mic = (const u8 *) (hdr + 1);
|
mic = (const u8 *) (hdr + 1);
|
||||||
if (!is_zero(hdr->key_rsc, 8)) {
|
if (!is_zero(hdr->key_rsc, 8)) {
|
||||||
add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
|
add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
|
||||||
|
@ -333,8 +378,21 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
}
|
}
|
||||||
os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN);
|
os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN);
|
||||||
key_info = WPA_GET_BE16(hdr->key_info);
|
key_info = WPA_GET_BE16(hdr->key_info);
|
||||||
|
if (left < 2) {
|
||||||
|
add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
|
||||||
|
" has a truncated Key Data Length field",
|
||||||
|
MAC2STR(src));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
left -= 2;
|
||||||
key_data = mic + mic_len + 2;
|
key_data = mic + mic_len + 2;
|
||||||
key_data_len = WPA_GET_BE16(mic + mic_len);
|
key_data_len = WPA_GET_BE16(mic + mic_len);
|
||||||
|
if (key_data_len > left) {
|
||||||
|
add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
|
||||||
|
" has a truncated Key Data field",
|
||||||
|
MAC2STR(src));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (wpa_parse_kde_ies(key_data, key_data_len, &ie) < 0) {
|
if (wpa_parse_kde_ies(key_data, key_data_len, &ie) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
|
add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
|
||||||
|
@ -381,7 +439,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
kck = sta->tptk.kck;
|
kck = sta->tptk.kck;
|
||||||
kck_len = sta->tptk.kck_len;
|
kck_len = sta->tptk.kck_len;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, kck_len, sta->key_mgmt,
|
if (check_mic(sta, kck, kck_len,
|
||||||
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC");
|
||||||
return;
|
return;
|
||||||
|
@ -462,6 +520,7 @@ static u8 * decrypt_eapol_key_data_rc4(struct wlantest *wt, const u8 *kek,
|
||||||
|
|
||||||
|
|
||||||
static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
|
static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
|
||||||
|
size_t kek_len,
|
||||||
const struct wpa_eapol_key *hdr,
|
const struct wpa_eapol_key *hdr,
|
||||||
const u8 *keydata, u16 keydatalen,
|
const u8 *keydata, u16 keydatalen,
|
||||||
size_t *len)
|
size_t *len)
|
||||||
|
@ -477,7 +536,7 @@ static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
|
||||||
buf = os_malloc(keydatalen);
|
buf = os_malloc(keydatalen);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (aes_unwrap(kek, 16, keydatalen / 8, keydata, buf)) {
|
if (aes_unwrap(kek, kek_len, keydatalen / 8, keydata, buf)) {
|
||||||
os_free(buf);
|
os_free(buf);
|
||||||
add_note(wt, MSG_INFO,
|
add_note(wt, MSG_INFO,
|
||||||
"AES unwrap failed - could not decrypt EAPOL-Key "
|
"AES unwrap failed - could not decrypt EAPOL-Key "
|
||||||
|
@ -490,35 +549,39 @@ static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 * decrypt_eapol_key_data(struct wlantest *wt, int akmp, const u8 *kek,
|
static u8 * decrypt_eapol_key_data(struct wlantest *wt,
|
||||||
|
struct wlantest_sta *sta, const u8 *kek,
|
||||||
size_t kek_len, u16 ver,
|
size_t kek_len, u16 ver,
|
||||||
const struct wpa_eapol_key *hdr,
|
const struct wpa_eapol_key *hdr,
|
||||||
size_t *len)
|
const u8 *end, size_t *len)
|
||||||
{
|
{
|
||||||
size_t mic_len;
|
size_t mic_len;
|
||||||
u16 keydatalen;
|
u16 keydatalen;
|
||||||
const u8 *mic, *keydata;
|
const u8 *mic, *keydata;
|
||||||
|
|
||||||
if (kek_len != 16)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
mic = (const u8 *) (hdr + 1);
|
mic = (const u8 *) (hdr + 1);
|
||||||
mic_len = wpa_mic_len(akmp, PMK_LEN);
|
mic_len = determine_mic_len(sta);
|
||||||
|
if (mic_len + 2 > end - mic)
|
||||||
|
return NULL;
|
||||||
keydata = mic + mic_len + 2;
|
keydata = mic + mic_len + 2;
|
||||||
keydatalen = WPA_GET_BE16(mic + mic_len);
|
keydatalen = WPA_GET_BE16(mic + mic_len);
|
||||||
|
if (keydatalen > end - keydata)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
switch (ver) {
|
switch (ver) {
|
||||||
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
|
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
|
||||||
|
if (kek_len != 16)
|
||||||
|
return NULL;
|
||||||
return decrypt_eapol_key_data_rc4(wt, kek, hdr, keydata,
|
return decrypt_eapol_key_data_rc4(wt, kek, hdr, keydata,
|
||||||
keydatalen, len);
|
keydatalen, len);
|
||||||
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
|
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
|
||||||
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
|
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
|
||||||
return decrypt_eapol_key_data_aes(wt, kek, hdr, keydata,
|
return decrypt_eapol_key_data_aes(wt, kek, kek_len, hdr,
|
||||||
keydatalen, len);
|
keydata, keydatalen, len);
|
||||||
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
|
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
|
||||||
/* For now, assume this is OSEN */
|
/* For now, assume this is OSEN */
|
||||||
return decrypt_eapol_key_data_aes(wt, kek, hdr, keydata,
|
return decrypt_eapol_key_data_aes(wt, kek, kek_len, hdr,
|
||||||
keydatalen, len);
|
keydata, keydatalen, len);
|
||||||
default:
|
default:
|
||||||
add_note(wt, MSG_INFO,
|
add_note(wt, MSG_INFO,
|
||||||
"Unsupported EAPOL-Key Key Descriptor Version %u",
|
"Unsupported EAPOL-Key Key Descriptor Version %u",
|
||||||
|
@ -879,7 +942,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
sta = sta_get(bss, dst);
|
sta = sta_get(bss, dst);
|
||||||
if (sta == NULL)
|
if (sta == NULL)
|
||||||
return;
|
return;
|
||||||
mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN);
|
mic_len = determine_mic_len(sta);
|
||||||
|
|
||||||
eapol = (const struct ieee802_1x_hdr *) data;
|
eapol = (const struct ieee802_1x_hdr *) data;
|
||||||
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
||||||
|
@ -915,7 +978,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
kek = sta->tptk.kek;
|
kek = sta->tptk.kek;
|
||||||
kek_len = sta->tptk.kek_len;
|
kek_len = sta->tptk.kek_len;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, kck_len, sta->key_mgmt,
|
if (check_mic(sta, kck, kck_len,
|
||||||
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
|
||||||
return;
|
return;
|
||||||
|
@ -931,9 +994,10 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
decrypted_len = WPA_GET_BE16(mic + mic_len);
|
decrypted_len = WPA_GET_BE16(mic + mic_len);
|
||||||
} else {
|
} else {
|
||||||
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
||||||
decrypted_buf = decrypt_eapol_key_data(wt, sta->key_mgmt,
|
decrypted_buf = decrypt_eapol_key_data(wt, sta,
|
||||||
kek, kek_len, ver,
|
kek, kek_len, ver,
|
||||||
hdr, &decrypted_len);
|
hdr, data + len,
|
||||||
|
&decrypted_len);
|
||||||
if (decrypted_buf == NULL) {
|
if (decrypted_buf == NULL) {
|
||||||
add_note(wt, MSG_INFO,
|
add_note(wt, MSG_INFO,
|
||||||
"Failed to decrypt EAPOL-Key Key Data");
|
"Failed to decrypt EAPOL-Key Key Data");
|
||||||
|
@ -1132,7 +1196,7 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
kck = sta->tptk.kck;
|
kck = sta->tptk.kck;
|
||||||
kck_len = sta->tptk.kck_len;
|
kck_len = sta->tptk.kck_len;
|
||||||
}
|
}
|
||||||
if (check_mic(kck, kck_len, sta->key_mgmt,
|
if (check_mic(sta, kck, kck_len,
|
||||||
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
|
||||||
return;
|
return;
|
||||||
|
@ -1179,7 +1243,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
|
||||||
sta = sta_get(bss, dst);
|
sta = sta_get(bss, dst);
|
||||||
if (sta == NULL)
|
if (sta == NULL)
|
||||||
return;
|
return;
|
||||||
mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN);
|
mic_len = determine_mic_len(sta);
|
||||||
|
|
||||||
eapol = (const struct ieee802_1x_hdr *) data;
|
eapol = (const struct ieee802_1x_hdr *) data;
|
||||||
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
||||||
|
@ -1192,7 +1256,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta->ptk_set &&
|
if (sta->ptk_set &&
|
||||||
check_mic(sta->ptk.kck, sta->ptk.kck_len, sta->key_mgmt,
|
check_mic(sta, sta->ptk.kck, sta->ptk.kck_len,
|
||||||
key_info & WPA_KEY_INFO_TYPE_MASK,
|
key_info & WPA_KEY_INFO_TYPE_MASK,
|
||||||
data, len) < 0) {
|
data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC");
|
||||||
|
@ -1206,9 +1270,10 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
||||||
decrypted = decrypt_eapol_key_data(wt, sta->key_mgmt,
|
decrypted = decrypt_eapol_key_data(wt, sta,
|
||||||
sta->ptk.kek, sta->ptk.kek_len,
|
sta->ptk.kek, sta->ptk.kek_len,
|
||||||
ver, hdr, &decrypted_len);
|
ver, hdr, data + len,
|
||||||
|
&decrypted_len);
|
||||||
if (decrypted == NULL) {
|
if (decrypted == NULL) {
|
||||||
add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
|
add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
|
||||||
return;
|
return;
|
||||||
|
@ -1330,7 +1395,7 @@ static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta->ptk_set &&
|
if (sta->ptk_set &&
|
||||||
check_mic(sta->ptk.kck, sta->ptk.kck_len, sta->key_mgmt,
|
check_mic(sta, sta->ptk.kck, sta->ptk.kck_len,
|
||||||
key_info & WPA_KEY_INFO_TYPE_MASK,
|
key_info & WPA_KEY_INFO_TYPE_MASK,
|
||||||
data, len) < 0) {
|
data, len) < 0) {
|
||||||
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");
|
add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");
|
||||||
|
@ -1360,8 +1425,7 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *bssid,
|
||||||
sta = sta_get(bss, sta_addr);
|
sta = sta_get(bss, sta_addr);
|
||||||
else
|
else
|
||||||
sta = NULL;
|
sta = NULL;
|
||||||
if (sta)
|
mic_len = determine_mic_len(sta);
|
||||||
mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eapol = (const struct ieee802_1x_hdr *) data;
|
eapol = (const struct ieee802_1x_hdr *) data;
|
||||||
|
|
|
@ -306,6 +306,32 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void process_sae_auth(struct wlantest *wt, struct wlantest_bss *bss,
|
||||||
|
struct wlantest_sta *sta,
|
||||||
|
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||||
|
{
|
||||||
|
u16 trans, status, group;
|
||||||
|
|
||||||
|
if (sta->auth_alg != WLAN_AUTH_SAE ||
|
||||||
|
len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
trans = le_to_host16(mgmt->u.auth.auth_transaction);
|
||||||
|
if (trans != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
status = le_to_host16(mgmt->u.auth.status_code);
|
||||||
|
if (status != WLAN_STATUS_SUCCESS &&
|
||||||
|
status != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
|
||||||
|
status != WLAN_STATUS_SAE_PK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
group = WPA_GET_LE16(mgmt->u.auth.variable);
|
||||||
|
wpa_printf(MSG_DEBUG, "SAE Commit using group %u", group);
|
||||||
|
sta->sae_group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
|
static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
|
||||||
{
|
{
|
||||||
const struct ieee80211_mgmt *mgmt;
|
const struct ieee80211_mgmt *mgmt;
|
||||||
|
@ -359,6 +385,7 @@ static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
|
||||||
|
|
||||||
process_fils_auth(wt, bss, sta, mgmt, len);
|
process_fils_auth(wt, bss, sta, mgmt, len);
|
||||||
process_ft_auth(wt, bss, sta, mgmt, len);
|
process_ft_auth(wt, bss, sta, mgmt, len);
|
||||||
|
process_sae_auth(wt, bss, sta, mgmt, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,8 @@ struct wlantest_sta {
|
||||||
|
|
||||||
u32 tx_tid[16 + 1];
|
u32 tx_tid[16 + 1];
|
||||||
u32 rx_tid[16 + 1];
|
u32 rx_tid[16 + 1];
|
||||||
|
|
||||||
|
u16 sae_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlantest_tdls {
|
struct wlantest_tdls {
|
||||||
|
|
Loading…
Reference in a new issue