wlantest: Add Group Key handshake processing
Decrypt GTK/IGTK updates in Group Key message 1/2 and update the keys. In addition, verify the MIC on both Group Key handshake messages.
This commit is contained in:
parent
30febd7001
commit
5db8cf314e
1 changed files with 80 additions and 2 deletions
|
@ -372,7 +372,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
const struct wpa_eapol_key *hdr;
|
const struct wpa_eapol_key *hdr;
|
||||||
const u8 *key_data;
|
const u8 *key_data;
|
||||||
int recalc = 0;
|
int recalc = 0;
|
||||||
u16 key_info, ver, key_data_len;
|
u16 key_info, ver;
|
||||||
u8 *decrypted;
|
u8 *decrypted;
|
||||||
size_t decrypted_len = 0;
|
size_t decrypted_len = 0;
|
||||||
|
|
||||||
|
@ -388,7 +388,6 @@ static void rx_data_eapol_key_3_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);
|
||||||
key_info = WPA_GET_BE16(hdr->key_info);
|
key_info = WPA_GET_BE16(hdr->key_info);
|
||||||
key_data_len = WPA_GET_BE16(hdr->key_data_length);
|
|
||||||
|
|
||||||
if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
|
if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
|
||||||
wpa_printf(MSG_INFO, "EAPOL-Key ANonce mismatch between 1/4 "
|
wpa_printf(MSG_INFO, "EAPOL-Key ANonce mismatch between 1/4 "
|
||||||
|
@ -473,16 +472,95 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
|
||||||
static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
|
static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
|
||||||
const u8 *src, const u8 *data, size_t len)
|
const u8 *src, const u8 *data, size_t len)
|
||||||
{
|
{
|
||||||
|
struct wlantest_bss *bss;
|
||||||
|
struct wlantest_sta *sta;
|
||||||
|
const struct ieee802_1x_hdr *eapol;
|
||||||
|
const struct wpa_eapol_key *hdr;
|
||||||
|
const u8 *key_data;
|
||||||
|
u16 key_info, ver;
|
||||||
|
u8 *decrypted;
|
||||||
|
size_t decrypted_len = 0;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
|
wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
|
||||||
MAC2STR(src), MAC2STR(dst));
|
MAC2STR(src), MAC2STR(dst));
|
||||||
|
bss = bss_get(wt, src);
|
||||||
|
if (bss == NULL)
|
||||||
|
return;
|
||||||
|
sta = sta_get(bss, dst);
|
||||||
|
if (sta == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eapol = (const struct ieee802_1x_hdr *) data;
|
||||||
|
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
||||||
|
key_info = WPA_GET_BE16(hdr->key_info);
|
||||||
|
|
||||||
|
if (!sta->ptk_set) {
|
||||||
|
wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 1/2");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sta->ptk_set &&
|
||||||
|
check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
|
||||||
|
data, len) < 0) {
|
||||||
|
wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 1/2");
|
||||||
|
|
||||||
|
key_data = (const u8 *) (hdr + 1);
|
||||||
|
/* TODO: handle WPA without EncrKeyData bit */
|
||||||
|
if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key 1/2 without EncrKeyData bit");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
||||||
|
decrypted = decrypt_eapol_key_data(sta->ptk.kek, ver, hdr,
|
||||||
|
&decrypted_len);
|
||||||
|
if (decrypted == NULL) {
|
||||||
|
wpa_printf(MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
|
||||||
|
decrypted, decrypted_len);
|
||||||
|
learn_kde_keys(bss, decrypted, decrypted_len, hdr->key_rsc);
|
||||||
|
os_free(decrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
|
static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
|
||||||
const u8 *src, const u8 *data, size_t len)
|
const u8 *src, const u8 *data, size_t len)
|
||||||
{
|
{
|
||||||
|
struct wlantest_bss *bss;
|
||||||
|
struct wlantest_sta *sta;
|
||||||
|
const struct ieee802_1x_hdr *eapol;
|
||||||
|
const struct wpa_eapol_key *hdr;
|
||||||
|
u16 key_info;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
|
wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
|
||||||
MAC2STR(src), MAC2STR(dst));
|
MAC2STR(src), MAC2STR(dst));
|
||||||
|
bss = bss_get(wt, dst);
|
||||||
|
if (bss == NULL)
|
||||||
|
return;
|
||||||
|
sta = sta_get(bss, src);
|
||||||
|
if (sta == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eapol = (const struct ieee802_1x_hdr *) data;
|
||||||
|
hdr = (const struct wpa_eapol_key *) (eapol + 1);
|
||||||
|
key_info = WPA_GET_BE16(hdr->key_info);
|
||||||
|
|
||||||
|
if (!sta->ptk_set) {
|
||||||
|
wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 2/2");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sta->ptk_set &&
|
||||||
|
check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
|
||||||
|
data, len) < 0) {
|
||||||
|
wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue