wlantest: Validate EAPOL-Key reserved fields
In addition, this handles WPA difference in Key Info for Secure bit in msg 3/4 and 4/4 (not set, since GTK is not yet available).
This commit is contained in:
parent
ad41bb2ea9
commit
77ac47278a
1 changed files with 93 additions and 5 deletions
|
@ -25,6 +25,17 @@
|
||||||
#include "wlantest.h"
|
#include "wlantest.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int is_zero(const u8 *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (buf[i])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char * data_stype(u16 stype)
|
static const char * data_stype(u16 stype)
|
||||||
{
|
{
|
||||||
switch (stype) {
|
switch (stype) {
|
||||||
|
@ -110,6 +121,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);
|
||||||
|
if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key 1/4 from " MACSTR " used "
|
||||||
|
"zero nonce", MAC2STR(src));
|
||||||
|
}
|
||||||
|
if (!is_zero(hdr->key_rsc, 8)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key 1/4 from " MACSTR " 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +202,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);
|
||||||
|
if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key 2/4 from " MACSTR " used "
|
||||||
|
"zero nonce", MAC2STR(src));
|
||||||
|
}
|
||||||
|
if (!is_zero(hdr->key_rsc, 8)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key 2/4 from " MACSTR " used "
|
||||||
|
"non-zero Key RSC", MAC2STR(src));
|
||||||
|
}
|
||||||
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);
|
||||||
key_data_len = WPA_GET_BE16(hdr->key_data_length);
|
key_data_len = WPA_GET_BE16(hdr->key_data_length);
|
||||||
|
@ -556,6 +583,10 @@ static void rx_data_eapol_key_4_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);
|
||||||
|
if (!is_zero(hdr->key_rsc, 8)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key 4/4 from " MACSTR " used "
|
||||||
|
"non-zero Key RSC", MAC2STR(src));
|
||||||
|
}
|
||||||
key_info = WPA_GET_BE16(hdr->key_info);
|
key_info = WPA_GET_BE16(hdr->key_info);
|
||||||
|
|
||||||
if (!sta->ptk_set) {
|
if (!sta->ptk_set) {
|
||||||
|
@ -715,6 +746,10 @@ static void rx_data_eapol_key_2_of_2(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);
|
||||||
|
if (!is_zero(hdr->key_rsc, 8)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key 2/2 from " MACSTR " used "
|
||||||
|
"non-zero Key RSC", MAC2STR(src));
|
||||||
|
}
|
||||||
key_info = WPA_GET_BE16(hdr->key_info);
|
key_info = WPA_GET_BE16(hdr->key_info);
|
||||||
|
|
||||||
if (!sta->ptk_set) {
|
if (!sta->ptk_set) {
|
||||||
|
@ -754,13 +789,15 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
|
||||||
|
|
||||||
if (hdr->type == EAPOL_KEY_TYPE_RC4) {
|
if (hdr->type == EAPOL_KEY_TYPE_RC4) {
|
||||||
/* TODO: EAPOL-Key RC4 for WEP */
|
/* TODO: EAPOL-Key RC4 for WEP */
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key Descriptor Type RC4 from "
|
||||||
|
MACSTR, MAC2STR(src));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdr->type != EAPOL_KEY_TYPE_RSN &&
|
if (hdr->type != EAPOL_KEY_TYPE_RSN &&
|
||||||
hdr->type != EAPOL_KEY_TYPE_WPA) {
|
hdr->type != EAPOL_KEY_TYPE_WPA) {
|
||||||
wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key type %u",
|
wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Descriptor Type "
|
||||||
hdr->type);
|
"%u from " MACSTR, hdr->type, MAC2STR(src));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,8 +836,8 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
|
||||||
if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
|
if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
|
||||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
|
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
|
||||||
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||||
wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key Key Descriptor "
|
wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Key Descriptor "
|
||||||
"Version %u", ver);
|
"Version %u from " MACSTR, ver, MAC2STR(src));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,6 +854,48 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
|
||||||
wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data",
|
wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data",
|
||||||
key_data, key_data_length);
|
key_data, key_data_length);
|
||||||
|
|
||||||
|
if (hdr->type == EAPOL_KEY_TYPE_RSN &&
|
||||||
|
(key_info & (WPA_KEY_INFO_KEY_INDEX_MASK | BIT(14) | BIT(15))) !=
|
||||||
|
0) {
|
||||||
|
wpa_printf(MSG_INFO, "RSN EAPOL-Key with non-zero reserved "
|
||||||
|
"Key Info bits 0x%x from " MACSTR,
|
||||||
|
key_info, MAC2STR(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->type == EAPOL_KEY_TYPE_WPA &&
|
||||||
|
(key_info & (WPA_KEY_INFO_ENCR_KEY_DATA |
|
||||||
|
WPA_KEY_INFO_SMK_MESSAGE |BIT(14) | BIT(15))) != 0) {
|
||||||
|
wpa_printf(MSG_INFO, "WPA EAPOL-Key with non-zero reserved "
|
||||||
|
"Key Info bits 0x%x from " MACSTR,
|
||||||
|
key_info, MAC2STR(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_length > 32) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key with invalid Key Length %d "
|
||||||
|
"from " MACSTR, key_length, MAC2STR(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
|
||||||
|
!is_zero(hdr->key_iv, 16)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key IV "
|
||||||
|
"(reserved with ver=%d) field from " MACSTR,
|
||||||
|
ver, MAC2STR(src));
|
||||||
|
wpa_hexdump(MSG_INFO, "EAPOL-Key Key IV (reserved)",
|
||||||
|
hdr->key_iv, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_zero(hdr->key_id, 8)) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key ID "
|
||||||
|
"(reserved) field from " MACSTR, MAC2STR(src));
|
||||||
|
wpa_hexdump(MSG_INFO, "EAPOL-Key Key ID (reserved)",
|
||||||
|
hdr->key_id, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->key_rsc[6] || hdr->key_rsc[7]) {
|
||||||
|
wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key RSC octets "
|
||||||
|
"(last two are unused)" MACSTR, MAC2STR(src));
|
||||||
|
}
|
||||||
|
|
||||||
if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
|
if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -833,7 +912,12 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
|
||||||
rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
|
rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
|
||||||
break;
|
break;
|
||||||
case WPA_KEY_INFO_MIC:
|
case WPA_KEY_INFO_MIC:
|
||||||
rx_data_eapol_key_2_of_4(wt, dst, src, data, len);
|
if (key_data_length == 0)
|
||||||
|
rx_data_eapol_key_4_of_4(wt, dst, src, data,
|
||||||
|
len);
|
||||||
|
else
|
||||||
|
rx_data_eapol_key_2_of_4(wt, dst, src, data,
|
||||||
|
len);
|
||||||
break;
|
break;
|
||||||
case WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK |
|
case WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK |
|
||||||
WPA_KEY_INFO_INSTALL:
|
WPA_KEY_INFO_INSTALL:
|
||||||
|
@ -891,6 +975,10 @@ static void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
|
||||||
"type=%u len=%u",
|
"type=%u len=%u",
|
||||||
MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
|
MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
|
||||||
hdr->version, hdr->type, length);
|
hdr->version, hdr->type, length);
|
||||||
|
if (hdr->version < 1 || hdr->version > 3) {
|
||||||
|
wpa_printf(MSG_INFO, "Unexpected EAPOL version %u from "
|
||||||
|
MACSTR, hdr->version, MAC2STR(src));
|
||||||
|
}
|
||||||
if (sizeof(*hdr) + length > len) {
|
if (sizeof(*hdr) + length > len) {
|
||||||
wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
|
wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
|
||||||
MAC2STR(src));
|
MAC2STR(src));
|
||||||
|
|
Loading…
Reference in a new issue