static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst, 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; wpa_printf(MSG_DEBUG, "EAPOL-Key 1/4 " MACSTR " -> " MACSTR, 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); 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); }
static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst, 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; const u8 *kck; wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR, 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); if (!is_zero(hdr->key_rsc, 8)) { add_note(wt, MSG_INFO, "EAPOL-Key 4/4 from " MACSTR " used " "non-zero Key RSC", MAC2STR(src)); } key_info = WPA_GET_BE16(hdr->key_info); if (!sta->ptk_set && !sta->tptk_set) { add_note(wt, MSG_DEBUG, "No PTK known to process EAPOL-Key 4/4"); return; } kck = sta->ptk.kck; if (sta->tptk_set) { add_note(wt, MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); kck = sta->tptk.kck; } if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC"); return; } add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4"); if (sta->tptk_set) { add_note(wt, MSG_DEBUG, "Update PTK (rekeying)"); os_memcpy(&sta->ptk, &sta->tptk, sizeof(sta->ptk)); sta->ptk_set = 1; sta->tptk_set = 0; os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods)); os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); } }
static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, 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, 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); if (sta->proto & WPA_PROTO_RSN && !(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); if (wt->write_pcap_dumper) { /* Fill in a dummy Data frame header */ u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr)]; struct ieee80211_hdr *h; struct wpa_eapol_key *k; u8 *pos; size_t plain_len; plain_len = decrypted_len; pos = decrypted; while (pos + 1 < decrypted + decrypted_len) { if (pos[0] == 0xdd && pos[1] == 0x00) { /* Remove padding */ plain_len = pos - decrypted; break; } pos += 2 + pos[1]; } os_memset(buf, 0, sizeof(buf)); h = (struct ieee80211_hdr *) buf; h->frame_control = host_to_le16(0x0208); os_memcpy(h->addr1, dst, ETH_ALEN); os_memcpy(h->addr2, src, ETH_ALEN); os_memcpy(h->addr3, src, ETH_ALEN); pos = (u8 *) (h + 1); os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8); pos += 8; os_memcpy(pos, eapol, sizeof(*eapol)); pos += sizeof(*eapol); os_memcpy(pos, hdr, sizeof(*hdr)); k = (struct wpa_eapol_key *) pos; WPA_PUT_BE16(k->key_info, key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA); WPA_PUT_BE16(k->key_data_length, plain_len); write_pcap_decrypted(wt, buf, sizeof(buf), decrypted, plain_len); } if (sta->proto & WPA_PROTO_RSN) learn_kde_keys(bss, decrypted, decrypted_len, hdr->key_rsc); else { int klen = bss->group_cipher == WPA_CIPHER_TKIP ? 32 : 16; if (decrypted_len == klen) { const u8 *rsc = hdr->key_rsc; int id; id = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> WPA_KEY_INFO_KEY_INDEX_SHIFT; wpa_printf(MSG_DEBUG, "GTK key index %d", id); wpa_hexdump(MSG_DEBUG, "GTK", decrypted, decrypted_len); bss->gtk_len[id] = decrypted_len; os_memcpy(bss->gtk[id], decrypted, decrypted_len); bss->rsc[id][0] = rsc[5]; bss->rsc[id][1] = rsc[4]; bss->rsc[id][2] = rsc[3]; bss->rsc[id][3] = rsc[2]; bss->rsc[id][4] = rsc[1]; bss->rsc[id][5] = rsc[0]; wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6); } else { wpa_printf(MSG_INFO, "Unexpected WPA Key Data length " "in Group Key msg 1/2 from " MACSTR, MAC2STR(src)); } }
static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, 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, *kck; int recalc = 0; u16 key_info, ver; u8 *decrypted_buf = NULL; const u8 *decrypted; size_t decrypted_len = 0; struct wpa_eapol_ie_parse ie; wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR, 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 (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_INFO, "EAPOL-Key ANonce mismatch between 1/4 " "and 3/4"); recalc = 1; } os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN); if (recalc) { derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len); } if (!sta->ptk_set && !sta->tptk_set) { wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 3/4"); return; } kck = sta->ptk.kck; if (sta->tptk_set) { wpa_printf(MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); kck = sta->tptk.kck; } if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC"); return; } wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4"); key_data = (const u8 *) (hdr + 1); if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { if (sta->proto & WPA_PROTO_RSN) wpa_printf(MSG_INFO, "EAPOL-Key 3/4 without " "EncrKeyData bit"); decrypted = key_data; decrypted_len = WPA_GET_BE16(hdr->key_data_length); } else { ver = key_info & WPA_KEY_INFO_TYPE_MASK; decrypted_buf = decrypt_eapol_key_data(sta->ptk.kek, ver, hdr, &decrypted_len); if (decrypted_buf == NULL) { wpa_printf(MSG_INFO, "Failed to decrypt EAPOL-Key Key " "Data"); return; } decrypted = decrypted_buf; wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data", decrypted, decrypted_len); } if (wt->write_pcap_dumper && decrypted != key_data) { /* Fill in a dummy Data frame header */ u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr)]; struct ieee80211_hdr *h; struct wpa_eapol_key *k; const u8 *p; u8 *pos; size_t plain_len; plain_len = decrypted_len; p = decrypted; while (p + 1 < decrypted + decrypted_len) { if (p[0] == 0xdd && p[1] == 0x00) { /* Remove padding */ plain_len = p - decrypted; break; } p += 2 + p[1]; } os_memset(buf, 0, sizeof(buf)); h = (struct ieee80211_hdr *) buf; h->frame_control = host_to_le16(0x0208); os_memcpy(h->addr1, dst, ETH_ALEN); os_memcpy(h->addr2, src, ETH_ALEN); os_memcpy(h->addr3, src, ETH_ALEN); pos = (u8 *) (h + 1); os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8); pos += 8; os_memcpy(pos, eapol, sizeof(*eapol)); pos += sizeof(*eapol); os_memcpy(pos, hdr, sizeof(*hdr)); k = (struct wpa_eapol_key *) pos; WPA_PUT_BE16(k->key_info, key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA); WPA_PUT_BE16(k->key_data_length, plain_len); write_pcap_decrypted(wt, buf, sizeof(buf), decrypted, plain_len); } if (wpa_supplicant_parse_ies(decrypted, decrypted_len, &ie) < 0) { wpa_printf(MSG_INFO, "Failed to parse EAPOL-Key Key Data"); os_free(decrypted_buf); return; } if ((ie.wpa_ie && os_memcmp(ie.wpa_ie, bss->wpaie, ie.wpa_ie_len) != 0) || (ie.wpa_ie == NULL && bss->wpaie[0])) { wpa_printf(MSG_INFO, "Mismatch in WPA IE between " "EAPOL-Key 3/4 and Beacon/Probe Response " "from " MACSTR, MAC2STR(bss->bssid)); wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key", ie.wpa_ie, ie.wpa_ie_len); wpa_hexdump(MSG_INFO, "WPA IE in Beacon/Probe " "Response", bss->wpaie, bss->wpaie[0] ? 2 + bss->wpaie[1] : 0); } if ((ie.rsn_ie && os_memcmp(ie.rsn_ie, bss->rsnie, ie.rsn_ie_len) != 0) || (ie.rsn_ie == NULL && bss->rsnie[0])) { wpa_printf(MSG_INFO, "Mismatch in RSN IE between " "EAPOL-Key 3/4 and Beacon/Probe Response " "from " MACSTR, MAC2STR(bss->bssid)); wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key", ie.rsn_ie, ie.rsn_ie_len); wpa_hexdump(MSG_INFO, "RSN IE in (Re)Association " "Request", bss->rsnie, bss->rsnie[0] ? 2 + bss->rsnie[1] : 0); } learn_kde_keys(bss, decrypted, decrypted_len, hdr->key_rsc); os_free(decrypted_buf); }
static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, 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, *kck; u16 key_info, key_data_len; struct wpa_eapol_ie_parse ie; wpa_printf(MSG_DEBUG, "EAPOL-Key 2/4 " MACSTR " -> " MACSTR, 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); 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); key_info = WPA_GET_BE16(hdr->key_info); key_data_len = WPA_GET_BE16(hdr->key_data_length); derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len); if (!sta->ptk_set && !sta->tptk_set) { wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 2/4"); return; } kck = sta->ptk.kck; if (sta->tptk_set) { wpa_printf(MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); kck = sta->tptk.kck; } if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC"); return; } wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/4"); key_data = (const u8 *) (hdr + 1); if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { wpa_printf(MSG_INFO, "Failed to parse EAPOL-Key Key Data"); return; } if (ie.wpa_ie) { wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE", ie.wpa_ie, ie.wpa_ie_len); if (os_memcmp(ie.wpa_ie, sta->rsnie, ie.wpa_ie_len) != 0) { wpa_printf(MSG_INFO, "Mismatch in WPA IE between " "EAPOL-Key 2/4 and (Re)Association " "Request from " MACSTR, MAC2STR(sta->addr)); wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key", ie.wpa_ie, ie.wpa_ie_len); wpa_hexdump(MSG_INFO, "WPA IE in (Re)Association " "Request", sta->rsnie, sta->rsnie[0] ? 2 + sta->rsnie[1] : 0); } } if (ie.rsn_ie) { wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE", ie.rsn_ie, ie.rsn_ie_len); if (os_memcmp(ie.rsn_ie, sta->rsnie, ie.rsn_ie_len) != 0) { wpa_printf(MSG_INFO, "Mismatch in RSN IE between " "EAPOL-Key 2/4 and (Re)Association " "Request from " MACSTR, MAC2STR(sta->addr)); wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key", ie.rsn_ie, ie.rsn_ie_len); wpa_hexdump(MSG_INFO, "RSN IE in (Re)Association " "Request", sta->rsnie, sta->rsnie[0] ? 2 + sta->rsnie[1] : 0); } } }
static void rx_data_bss_prot(struct wlantest *wt, const struct ieee80211_hdr *hdr, const u8 *qos, const u8 *dst, const u8 *src, const u8 *data, size_t len) { struct wlantest_bss *bss; struct wlantest_sta *sta, *sta2; int keyid; u16 fc = le_to_host16(hdr->frame_control); u8 *decrypted; size_t dlen; int tid; u8 pn[6], *rsc; struct wlantest_tdls *tdls = NULL, *found; const u8 *tk = NULL; int ptk_iter_done = 0; int try_ptk_iter = 0; if (hdr->addr1[0] & 0x01) { rx_data_bss_prot_group(wt, hdr, qos, dst, src, data, len); return; } if (fc & WLAN_FC_TODS) { bss = bss_get(wt, hdr->addr1); if (bss == NULL) return; sta = sta_get(bss, hdr->addr2); if (sta) sta->counters[WLANTEST_STA_COUNTER_PROT_DATA_TX]++; } else if (fc & WLAN_FC_FROMDS) { bss = bss_get(wt, hdr->addr2); if (bss == NULL) return; sta = sta_get(bss, hdr->addr1); } else { bss = bss_get(wt, hdr->addr3); if (bss == NULL) return; sta = sta_find(bss, hdr->addr2); sta2 = sta_find(bss, hdr->addr1); if (sta == NULL || sta2 == NULL) return; found = NULL; dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { if ((tdls->init == sta && tdls->resp == sta2) || (tdls->init == sta2 && tdls->resp == sta)) { found = tdls; if (tdls->link_up) break; } } if (found) { if (!found->link_up) add_note(wt, MSG_DEBUG, "TDLS: Link not up, but Data " "frame seen"); tk = found->tpk.tk; tdls = found; } } if ((sta == NULL || (!sta->ptk_set && sta->pairwise_cipher != WPA_CIPHER_WEP40)) && tk == NULL) { add_note(wt, MSG_MSGDUMP, "No PTK known to decrypt the frame"); if (dl_list_empty(&wt->ptk)) return; try_ptk_iter = 1; } if (len < 4) { add_note(wt, MSG_INFO, "Too short encrypted data frame"); return; } if (sta == NULL) return; if (sta->pairwise_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP) && !(data[3] & 0x20)) { add_note(wt, MSG_INFO, "Expected TKIP/CCMP frame from " MACSTR " did not have ExtIV bit set to 1", MAC2STR(src)); return; } if (tk == NULL && sta->pairwise_cipher == WPA_CIPHER_TKIP) { if (data[3] & 0x1f) { add_note(wt, MSG_INFO, "TKIP frame from " MACSTR " used non-zero reserved bit", MAC2STR(hdr->addr2)); } if (data[1] != ((data[0] | 0x20) & 0x7f)) { add_note(wt, MSG_INFO, "TKIP frame from " MACSTR " used incorrect WEPSeed[1] (was 0x%x, " "expected 0x%x)", MAC2STR(hdr->addr2), data[1], (data[0] | 0x20) & 0x7f); } } else if (tk || sta->pairwise_cipher == WPA_CIPHER_CCMP) { if (data[2] != 0 || (data[3] & 0x1f) != 0) { add_note(wt, MSG_INFO, "CCMP frame from " MACSTR " used non-zero reserved bit", MAC2STR(hdr->addr2)); } } keyid = data[3] >> 6; if (keyid != 0) { add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in " "individually addressed Data frame from " MACSTR, keyid, MAC2STR(hdr->addr2)); } if (qos) { tid = qos[0] & 0x0f; if (fc & WLAN_FC_TODS) sta->tx_tid[tid]++; else sta->rx_tid[tid]++; } else { tid = 0; if (fc & WLAN_FC_TODS) sta->tx_tid[16]++; else sta->rx_tid[16]++; } if (tk) { if (os_memcmp(hdr->addr2, tdls->init->addr, ETH_ALEN) == 0) rsc = tdls->rsc_init[tid]; else rsc = tdls->rsc_resp[tid]; } else if (fc & WLAN_FC_TODS) rsc = sta->rsc_tods[tid]; else rsc = sta->rsc_fromds[tid]; if (tk == NULL && sta->pairwise_cipher == WPA_CIPHER_TKIP) tkip_get_pn(pn, data); else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) goto skip_replay_det; else ccmp_get_pn(pn, data); if (os_memcmp(pn, rsc, 6) <= 0) { u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); add_note(wt, MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl)); wpa_hexdump(MSG_INFO, "RX PN", pn, 6); wpa_hexdump(MSG_INFO, "RSC", rsc, 6); } skip_replay_det: if (tk) decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen); else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) decrypted = tkip_decrypt(sta->ptk.tk1, hdr, data, len, &dlen); else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) decrypted = wep_decrypt(wt, hdr, data, len, &dlen); else if (sta->ptk_set) decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len, &dlen); else { decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, len, &dlen); ptk_iter_done = 1; } if (!decrypted && !ptk_iter_done) { decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, len, &dlen); if (decrypted) { add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs"); } } if (decrypted) { u16 fc = le_to_host16(hdr->frame_control); const u8 *peer_addr = NULL; if (!(fc & (WLAN_FC_FROMDS | WLAN_FC_TODS))) peer_addr = hdr->addr1; os_memcpy(rsc, pn, 6); rx_data_process(wt, bss->bssid, sta->addr, dst, src, decrypted, dlen, 1, peer_addr); write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0), decrypted, dlen); } else if (!try_ptk_iter) add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); os_free(decrypted); }
static void rx_data_bss_prot_group(struct wlantest *wt, const struct ieee80211_hdr *hdr, const u8 *qos, const u8 *dst, const u8 *src, const u8 *data, size_t len) { struct wlantest_bss *bss; int keyid; u8 *decrypted; size_t dlen; u8 pn[6]; bss = bss_get(wt, hdr->addr2); if (bss == NULL) return; if (len < 4) { add_note(wt, MSG_INFO, "Too short group addressed data frame"); return; } if (bss->group_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP) && !(data[3] & 0x20)) { add_note(wt, MSG_INFO, "Expected TKIP/CCMP frame from " MACSTR " did not have ExtIV bit set to 1", MAC2STR(bss->bssid)); return; } if (bss->group_cipher == WPA_CIPHER_TKIP) { if (data[3] & 0x1f) { add_note(wt, MSG_INFO, "TKIP frame from " MACSTR " used non-zero reserved bit", MAC2STR(bss->bssid)); } if (data[1] != ((data[0] | 0x20) & 0x7f)) { add_note(wt, MSG_INFO, "TKIP frame from " MACSTR " used incorrect WEPSeed[1] (was 0x%x, " "expected 0x%x)", MAC2STR(bss->bssid), data[1], (data[0] | 0x20) & 0x7f); } } else if (bss->group_cipher == WPA_CIPHER_CCMP) { if (data[2] != 0 || (data[3] & 0x1f) != 0) { add_note(wt, MSG_INFO, "CCMP frame from " MACSTR " used non-zero reserved bit", MAC2STR(bss->bssid)); } } keyid = data[3] >> 6; if (bss->gtk_len[keyid] == 0 && bss->group_cipher != WPA_CIPHER_WEP40) { add_note(wt, MSG_MSGDUMP, "No GTK known to decrypt the frame " "(A2=" MACSTR " KeyID=%d)", MAC2STR(hdr->addr2), keyid); return; } if (bss->group_cipher == WPA_CIPHER_TKIP) tkip_get_pn(pn, data); else if (bss->group_cipher == WPA_CIPHER_WEP40) goto skip_replay_det; else ccmp_get_pn(pn, data); if (os_memcmp(pn, bss->rsc[keyid], 6) <= 0) { u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); add_note(wt, MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl)); wpa_hexdump(MSG_INFO, "RX PN", pn, 6); wpa_hexdump(MSG_INFO, "RSC", bss->rsc[keyid], 6); } skip_replay_det: if (bss->group_cipher == WPA_CIPHER_TKIP) decrypted = tkip_decrypt(bss->gtk[keyid], hdr, data, len, &dlen); else if (bss->group_cipher == WPA_CIPHER_WEP40) decrypted = wep_decrypt(wt, hdr, data, len, &dlen); else decrypted = ccmp_decrypt(bss->gtk[keyid], hdr, data, len, &dlen); if (decrypted) { rx_data_process(wt, bss->bssid, NULL, dst, src, decrypted, dlen, 1, NULL); os_memcpy(bss->rsc[keyid], pn, 6); write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0), decrypted, dlen); } else add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); os_free(decrypted); }