diff --git a/wlantest/bip.c b/wlantest/bip.c index a239d49d6..d9a52e937 100644 --- a/wlantest/bip.c +++ b/wlantest/bip.c @@ -65,3 +65,69 @@ u8 * bip_protect(const u8 *igtk, u8 *frame, size_t len, u8 *ipn, int keyid, *prot_len = plen; return prot; } + + +u8 * bip_gmac_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; + u16 fc; + struct ieee80211_hdr *hdr; + size_t plen; + u8 nonce[12], *npos; + + plen = len + 26; + prot = os_malloc(plen); + if (prot == NULL) + return NULL; + os_memcpy(prot, frame, len); + pos = prot + len; + *pos++ = WLAN_EID_MMIE; + *pos++ = 24; + WPA_PUT_LE16(pos, keyid); + pos += 2; + os_memcpy(pos, ipn, 6); + pos += 6; + os_memset(pos, 0, 16); /* MIC */ + + buf = os_malloc(plen + 20 - 24); + if (buf == NULL) { + os_free(prot); + return NULL; + } + + /* BIP AAD: FC(masked) A1 A2 A3 */ + hdr = (struct ieee80211_hdr *) frame; + fc = le_to_host16(hdr->frame_control); + fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); + WPA_PUT_LE16(buf, fc); + os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN); + os_memcpy(buf + 20, prot + 24, plen - 24); + wpa_hexdump(MSG_MSGDUMP, "BIP-GMAC: AAD|Body(masked)", + buf, plen + 20 - 24); + + /* Nonce: A2 | IPN */ + os_memcpy(nonce, hdr->addr2, ETH_ALEN); + npos = nonce + ETH_ALEN; + *npos++ = ipn[5]; + *npos++ = ipn[4]; + *npos++ = ipn[3]; + *npos++ = ipn[2]; + *npos++ = ipn[1]; + *npos++ = ipn[0]; + wpa_hexdump(MSG_EXCESSIVE, "BIP-GMAC: Nonce", nonce, sizeof(nonce)); + + /* MIC = AES-GMAC(AAD || Frame Body(masked)) */ + if (aes_gmac(igtk, igtk_len, nonce, sizeof(nonce), + buf, plen + 20 - 24, pos) < 0) { + os_free(prot); + os_free(buf); + return NULL; + } + os_free(buf); + + wpa_hexdump(MSG_DEBUG, "BIP-GMAC MMIE MIC", pos, 16); + + *prot_len = plen; + return prot; +} diff --git a/wlantest/test_vectors.c b/wlantest/test_vectors.c index 968ce9932..6c716c458 100644 --- a/wlantest/test_vectors.c +++ b/wlantest/test_vectors.c @@ -408,6 +408,78 @@ static void test_vector_ccmp_256(void) } +static void test_vector_bip_gmac_128(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0xc0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x02, 0x00 + }; + u8 *prot; + size_t prot_len; + + wpa_printf(MSG_INFO, "\nBIP-GMAC-128 with broadcast " + "Deauthentication frame\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 4, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect BIP-GMAC-128 frame"); + return; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + os_free(prot); +} + + +static void test_vector_bip_gmac_256(void) +{ + u8 igtk[] = { + 0x4e, 0xa9, 0x54, 0x3e, 0x09, 0xcf, 0x2b, 0x1e, + 0xca, 0x66, 0xff, 0xc5, 0x8b, 0xde, 0xcb, 0xcf, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + u8 ipn[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 frame[] = { + 0xc0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, + 0x02, 0x00 + }; + u8 *prot; + size_t prot_len; + + wpa_printf(MSG_INFO, "\nBIP-GMAC-256 with broadcast " + "Deauthentication frame\n"); + + wpa_hexdump(MSG_INFO, "IGTK", igtk, sizeof(igtk)); + wpa_hexdump(MSG_INFO, "IPN", ipn, sizeof(ipn)); + wpa_hexdump(MSG_INFO, "Plaintext frame", frame, sizeof(frame)); + + prot = bip_gmac_protect(igtk, sizeof(igtk), frame, sizeof(frame), + ipn, 4, &prot_len); + if (prot == NULL) { + wpa_printf(MSG_ERROR, "Failed to protect BIP-GMAC-256 frame"); + return; + } + + wpa_hexdump(MSG_INFO, "Protected MPDU (without FCS)", prot, prot_len); + os_free(prot); +} + + int main(int argc, char *argv[]) { wpa_debug_level = MSG_EXCESSIVE; @@ -423,6 +495,8 @@ int main(int argc, char *argv[]) test_vector_gcmp(); test_vector_gcmp_256(); test_vector_ccmp_256(); + test_vector_bip_gmac_128(); + test_vector_bip_gmac_256(); os_program_deinit(); diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index a8db20b99..b04e9d068 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -243,6 +243,8 @@ u8 * wep_decrypt(struct wlantest *wt, const struct ieee80211_hdr *hdr, u8 * bip_protect(const u8 *igtk, 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); u8 * gcmp_decrypt(const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr, const u8 *data, size_t data_len, size_t *decrypted_len);