From cb80fadaa7374a9ab8191d0ac45f3cb5e7ddcca4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 23 Jan 2015 17:24:24 +0200 Subject: [PATCH] wlantest: Extend BIP support to cover BIP-CMAC-256 Signed-off-by: Jouni Malinen --- wlantest/bip.c | 14 +++++++------- wlantest/inject.c | 9 +++++---- wlantest/rx_eapol.c | 25 +++++++++++++++++++++++- wlantest/rx_mgmt.c | 43 ++++++++++++++++++++++++++++++----------- wlantest/test_vectors.c | 3 ++- wlantest/wlantest.h | 8 ++++---- 6 files changed, 74 insertions(+), 28 deletions(-) diff --git a/wlantest/bip.c b/wlantest/bip.c index d9a52e937..bda8036c5 100644 --- a/wlantest/bip.c +++ b/wlantest/bip.c @@ -14,8 +14,8 @@ #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]; @@ -23,19 +23,19 @@ u8 * bip_protect(const u8 *igtk, u8 *frame, size_t len, u8 *ipn, int keyid, 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) { @@ -59,8 +59,8 @@ u8 * bip_protect(const u8 *igtk, u8 *frame, size_t len, u8 *ipn, int keyid, } 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; diff --git a/wlantest/inject.c b/wlantest/inject.c index 22a9e2afd..04cd96183 100644 --- a/wlantest/inject.c +++ b/wlantest/inject.c @@ -82,17 +82,18 @@ static int wlantest_inject_bip(struct wlantest *wt, struct wlantest_bss *bss, 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) @@ -300,7 +301,7 @@ int wlantest_inject(struct wlantest *wt, struct wlantest_bss *bss, 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 " @@ -323,7 +324,7 @@ int wlantest_inject(struct wlantest *wt, struct wlantest_bss *bss, 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; } } diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 13510ef7a..704c0eb9f 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -464,7 +464,30 @@ static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss, 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]; diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 367a6b5f7..09688c6d5 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -753,12 +753,24 @@ static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len, } -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) @@ -772,19 +784,23 @@ static int check_mmie_mic(const u8 *igtk, const u8 *data, size_t len) 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; @@ -798,6 +814,7 @@ static int check_bip(struct wlantest *wt, const u8 *data, size_t len) 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); @@ -814,8 +831,11 @@ static int check_bip(struct wlantest *wt, const u8 *data, size_t len) 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 " @@ -827,7 +847,7 @@ static int check_bip(struct wlantest *wt, const u8 *data, size_t len) 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 " @@ -842,9 +862,9 @@ static int check_bip(struct wlantest *wt, const u8 *data, size_t len) } 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; } @@ -856,7 +876,8 @@ static int check_bip(struct wlantest *wt, const u8 *data, size_t len) 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]++; diff --git a/wlantest/test_vectors.c b/wlantest/test_vectors.c index 0800db7f3..321d930ae 100644 --- a/wlantest/test_vectors.c +++ b/wlantest/test_vectors.c @@ -159,7 +159,8 @@ static void test_vector_bip(void) 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; diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 574714946..1d8088fa6 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -145,8 +145,8 @@ struct wlantest_bss { 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]; @@ -284,8 +284,8 @@ void tkip_get_pn(u8 *pn, const u8 *data); 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);