#include "wlantest.h"
-u8 * bip_protect(const u8 *igtk, u8 *frame, size_t len, u8 *ipn, int keyid,
- size_t *prot_len)
+u8 * bip_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len,
+ u8 *ipn, int keyid, size_t *prot_len)
{
u8 *prot, *pos, *buf;
u8 mic[16];
struct ieee80211_hdr *hdr;
size_t plen;
- plen = len + 18;
+ plen = len + igtk_len == 32 ? 26 : 18;
prot = os_malloc(plen);
if (prot == NULL)
return NULL;
os_memcpy(prot, frame, len);
pos = prot + len;
*pos++ = WLAN_EID_MMIE;
- *pos++ = 16;
+ *pos++ = igtk_len == 32 ? 24 : 16;
WPA_PUT_LE16(pos, keyid);
pos += 2;
os_memcpy(pos, ipn, 6);
pos += 6;
- os_memset(pos, 0, 8); /* MIC */
+ os_memset(pos, 0, igtk_len == 32 ? 16 : 8); /* MIC */
buf = os_malloc(plen + 20 - 24);
if (buf == NULL) {
}
os_free(buf);
- os_memcpy(pos, mic, 8);
- wpa_hexdump(MSG_DEBUG, "BIP MMIE MIC", pos, 8);
+ os_memcpy(pos, mic, igtk_len == 32 ? 16 : 8);
+ wpa_hexdump(MSG_DEBUG, "BIP MMIE MIC", pos, igtk_len == 32 ? 16 : 8);
*prot_len = plen;
return prot;
u8 *frame, size_t len, int incorrect_key)
{
u8 *prot;
- u8 dummy[16];
+ u8 dummy[32];
int ret;
size_t plen;
- if (!bss->igtk_set[bss->igtk_idx])
+ if (!bss->igtk_len[bss->igtk_idx])
return -1;
os_memset(dummy, 0x11, sizeof(dummy));
inc_byte_array(bss->ipn[bss->igtk_idx], 6);
prot = bip_protect(incorrect_key ? dummy : bss->igtk[bss->igtk_idx],
+ bss->igtk_len[bss->igtk_idx],
frame, len, bss->ipn[bss->igtk_idx],
bss->igtk_idx, &plen);
if (prot == NULL)
prot == WLANTEST_INJECT_INCORRECT_KEY) && bss) {
if (!sta &&
((WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
- !bss->igtk_set[bss->igtk_idx]) ||
+ !bss->igtk_len[bss->igtk_idx]) ||
(WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA &&
!bss->gtk_len[bss->gtk_idx]))) {
wpa_printf(MSG_INFO, "No GTK/IGTK known for "
bss->gtk_len[bss->gtk_idx])
protect = 1;
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
- bss->igtk_set[bss->igtk_idx])
+ bss->igtk_len[bss->igtk_idx])
protect = 1;
}
}
wpa_hexdump(MSG_DEBUG, "IGTK", ie.igtk + 8,
16);
os_memcpy(bss->igtk[id], ie.igtk + 8, 16);
- bss->igtk_set[id] = 1;
+ bss->igtk_len[id] = 16;
+ ipn = ie.igtk + 2;
+ bss->ipn[id][0] = ipn[5];
+ bss->ipn[id][1] = ipn[4];
+ bss->ipn[id][2] = ipn[3];
+ bss->ipn[id][3] = ipn[2];
+ bss->ipn[id][4] = ipn[1];
+ bss->ipn[id][5] = ipn[0];
+ bss->igtk_idx = id;
+ }
+ } else if (ie.igtk_len == 40) {
+ u16 id;
+ id = WPA_GET_LE16(ie.igtk);
+ if (id > 5) {
+ add_note(wt, MSG_INFO,
+ "Unexpected IGTK KeyID %u", id);
+ } else {
+ const u8 *ipn;
+ add_note(wt, MSG_DEBUG, "IGTK KeyID %u", id);
+ wpa_hexdump(MSG_DEBUG, "IPN", ie.igtk + 2, 6);
+ wpa_hexdump(MSG_DEBUG, "IGTK", ie.igtk + 8,
+ 32);
+ os_memcpy(bss->igtk[id], ie.igtk + 8, 32);
+ bss->igtk_len[id] = 32;
ipn = ie.igtk + 2;
bss->ipn[id][0] = ipn[5];
bss->ipn[id][1] = ipn[4];
}
-static int check_mmie_mic(const u8 *igtk, const u8 *data, size_t len)
+static int check_mmie_mic(const u8 *igtk, size_t igtk_len,
+ const u8 *data, size_t len)
{
u8 *buf;
u8 mic[16];
u16 fc;
const struct ieee80211_hdr *hdr;
+ int ret, mic_len;
+
+ if (igtk_len == 32)
+ mic_len = 16;
+ else if (igtk_len == 16)
+ mic_len = 8;
+ else
+ return -1;
+
+ if (len < 24 || len - 24 < mic_len)
+ return -1;
buf = os_malloc(len + 20 - 24);
if (buf == NULL)
os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN);
/* Frame body with MMIE MIC masked to zero */
- os_memcpy(buf + 20, data + 24, len - 24 - 8);
- os_memset(buf + 20 + len - 24 - 8, 0, 8);
+ os_memcpy(buf + 20, data + 24, len - 24 - mic_len);
+ os_memset(buf + 20 + len - 24 - mic_len, 0, mic_len);
wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24);
/* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */
- if (omac1_aes_128(igtk, buf, len + 20 - 24, mic) < 0) {
+ if (igtk_len == 32)
+ ret = omac1_aes_256(igtk, buf, len + 20 - 24, mic);
+ else
+ ret = omac1_aes_128(igtk, buf, len + 20 - 24, mic);
+ if (ret < 0) {
os_free(buf);
return -1;
}
os_free(buf);
- if (os_memcmp(data + len - 8, mic, 8) != 0)
+ if (os_memcmp(data + len - mic_len, mic, mic_len) != 0)
return -1;
return 0;
const u8 *mmie;
u16 keyid;
struct wlantest_bss *bss;
+ size_t mic_len;
mgmt = (const struct ieee80211_mgmt *) data;
fc = le_to_host16(mgmt->frame_control);
if (bss == NULL)
return 0; /* No key known yet */
- if (len < 24 + 18 || data[len - 18] != WLAN_EID_MMIE ||
- data[len - 17] != 16) {
+ mic_len = bss->igtk_len[4] == 32 || bss->igtk_len[5] == 32 ? 16 : 8;
+
+ if (len < 24 + 10 + mic_len ||
+ data[len - (10 + mic_len)] != WLAN_EID_MMIE ||
+ data[len - (10 + mic_len - 1)] != 8 + mic_len) {
/* No MMIE */
if (bss->rsn_capab & WPA_CAPABILITY_MFPC) {
add_note(wt, MSG_INFO, "Robust group-addressed "
return 0;
}
- mmie = data + len - 16;
+ mmie = data + len - (8 + mic_len);
keyid = WPA_GET_LE16(mmie);
if (keyid & 0xf000) {
add_note(wt, MSG_INFO, "MMIE KeyID reserved bits not zero "
}
wpa_printf(MSG_DEBUG, "MMIE KeyID %u", keyid);
wpa_hexdump(MSG_MSGDUMP, "MMIE IPN", mmie + 2, 6);
- wpa_hexdump(MSG_MSGDUMP, "MMIE MIC", mmie + 8, 8);
+ wpa_hexdump(MSG_MSGDUMP, "MMIE MIC", mmie + 8, mic_len);
- if (!bss->igtk_set[keyid]) {
+ if (!bss->igtk_len[keyid]) {
add_note(wt, MSG_DEBUG, "No IGTK known to validate BIP frame");
return 0;
}
wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6);
}
- if (check_mmie_mic(bss->igtk[keyid], data, len) < 0) {
+ if (check_mmie_mic(bss->igtk[keyid], bss->igtk_len[keyid], data, len) <
+ 0) {
add_note(wt, MSG_INFO, "Invalid MMIE MIC in a frame from "
MACSTR, MAC2STR(mgmt->sa));
bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn));
wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame));
- prot = bip_protect(igtk, frame, sizeof(frame), ipn, 4, &prot_len);
+ prot = bip_protect(igtk, sizeof(igtk), frame, sizeof(frame),
+ ipn, 4, &prot_len);
if (prot == NULL) {
wpa_printf(MSG_ERROR, "Failed to protect BIP frame");
return;
size_t gtk_len[4];
int gtk_idx;
u8 rsc[4][6];
- u8 igtk[6][16];
- int igtk_set[6];
+ u8 igtk[6][32];
+ size_t igtk_len[6];
int igtk_idx;
u8 ipn[6][6];
u32 counters[NUM_WLANTEST_BSS_COUNTER];
u8 * wep_decrypt(struct wlantest *wt, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len);
-u8 * bip_protect(const u8 *igtk, u8 *frame, size_t len, u8 *ipn, int keyid,
- size_t *prot_len);
+u8 * bip_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len,
+ u8 *ipn, int keyid, size_t *prot_len);
u8 * bip_gmac_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len,
u8 *ipn, int keyid, size_t *prot_len);