wlantest: Support HT Control field in Robust Management frames

Check the +HTC bit in FC to determine if the HT Control field is present
when decrypting Robust Management frames. This was already done for QoS
Data frames, but the Management frame case had not been extended to
cover this option.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2023-06-22 22:44:51 +03:00 committed by Jouni Malinen
parent 30f5bdc34c
commit 599d00be9d

View file

@ -2665,14 +2665,18 @@ static u8 * mgmt_decrypt(struct wlantest *wt, const u8 *data, size_t len,
u8 pn[6], *rsc; u8 pn[6], *rsc;
u16 fc; u16 fc;
u8 mask; u8 mask;
size_t hdrlen = 24;
hdr = (const struct ieee80211_hdr *) data; hdr = (const struct ieee80211_hdr *) data;
fc = le_to_host16(hdr->frame_control); fc = le_to_host16(hdr->frame_control);
if (len < 24 + 4) if (fc & WLAN_FC_HTC)
hdrlen += 4; /* HT Control field */
if (len < hdrlen + 4)
return NULL; return NULL;
if (!(data[24 + 3] & 0x20)) { if (!(data[hdrlen + 3] & 0x20)) {
add_note(wt, MSG_INFO, "Expected CCMP/GCMP frame from " MACSTR add_note(wt, MSG_INFO, "Expected CCMP/GCMP frame from " MACSTR
" did not have ExtIV bit set to 1", " did not have ExtIV bit set to 1",
MAC2STR(hdr->addr2)); MAC2STR(hdr->addr2));
@ -2683,12 +2687,12 @@ static u8 * mgmt_decrypt(struct wlantest *wt, const u8 *data, size_t len,
if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION || if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION ||
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION_NO_ACK) WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION_NO_ACK)
mask &= ~0x10; /* FTM */ mask &= ~0x10; /* FTM */
if (data[24 + 2] != 0 || (data[24 + 3] & mask) != 0) { if (data[hdrlen + 2] != 0 || (data[hdrlen + 3] & mask) != 0) {
add_note(wt, MSG_INFO, "CCMP/GCMP mgmt frame from " MACSTR add_note(wt, MSG_INFO, "CCMP/GCMP mgmt frame from " MACSTR
" used non-zero reserved bit", MAC2STR(hdr->addr2)); " used non-zero reserved bit", MAC2STR(hdr->addr2));
} }
keyid = data[24 + 3] >> 6; keyid = data[hdrlen + 3] >> 6;
if (keyid != 0) { if (keyid != 0) {
add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in " add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in "
"individually addressed Management frame from " "individually addressed Management frame from "
@ -2720,7 +2724,7 @@ static u8 * mgmt_decrypt(struct wlantest *wt, const u8 *data, size_t len,
else else
rsc = sta->rsc_fromds[16]; rsc = sta->rsc_fromds[16];
ccmp_get_pn(pn, data + 24); ccmp_get_pn(pn, data + hdrlen);
if (os_memcmp(pn, rsc, 6) <= 0) { if (os_memcmp(pn, rsc, 6) <= 0) {
u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR
@ -2737,27 +2741,27 @@ static u8 * mgmt_decrypt(struct wlantest *wt, const u8 *data, size_t len,
if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) { if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) {
decrypted = ccmp_256_decrypt(sta->ptk.tk, hdr, NULL, NULL, NULL, decrypted = ccmp_256_decrypt(sta->ptk.tk, hdr, NULL, NULL, NULL,
data + 24, len - 24, dlen); data + hdrlen, len - hdrlen, dlen);
write_decrypted_note(wt, decrypted, sta->ptk.tk, 32, keyid); write_decrypted_note(wt, decrypted, sta->ptk.tk, 32, keyid);
} else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || } else if (sta->pairwise_cipher == WPA_CIPHER_GCMP ||
sta->pairwise_cipher == WPA_CIPHER_GCMP_256) { sta->pairwise_cipher == WPA_CIPHER_GCMP_256) {
decrypted = gcmp_decrypt(sta->ptk.tk, sta->ptk.tk_len, hdr, decrypted = gcmp_decrypt(sta->ptk.tk, sta->ptk.tk_len, hdr,
NULL, NULL, NULL, NULL, NULL, NULL,
data + 24, len - 24, dlen); data + hdrlen, len - hdrlen, dlen);
write_decrypted_note(wt, decrypted, sta->ptk.tk, write_decrypted_note(wt, decrypted, sta->ptk.tk,
sta->ptk.tk_len, keyid); sta->ptk.tk_len, keyid);
} else { } else {
decrypted = ccmp_decrypt(sta->ptk.tk, hdr, NULL, NULL, NULL, decrypted = ccmp_decrypt(sta->ptk.tk, hdr, NULL, NULL, NULL,
data + 24, len - 24, dlen); data + hdrlen, len - hdrlen, dlen);
write_decrypted_note(wt, decrypted, sta->ptk.tk, 16, keyid); write_decrypted_note(wt, decrypted, sta->ptk.tk, 16, keyid);
} }
if (decrypted) { if (decrypted) {
os_memcpy(rsc, pn, 6); os_memcpy(rsc, pn, 6);
frame = os_malloc(24 + *dlen); frame = os_malloc(hdrlen + *dlen);
if (frame) { if (frame) {
os_memcpy(frame, data, 24); os_memcpy(frame, data, hdrlen);
os_memcpy(frame + 24, decrypted, *dlen); os_memcpy(frame + hdrlen, decrypted, *dlen);
*dlen += 24; *dlen += hdrlen;
} }
} else { } else {
/* Assume the frame was corrupted and there was no FCS to check. /* Assume the frame was corrupted and there was no FCS to check.