wlantest: MLD MAC Address in CCMP/GCMP AAD/nonce

Use the MLD MAC Address instead of link address in CCMP/GCMP AAD/nonce
construction when processing an individually addressed Data frame with
FromDS=1 or ToDS=1 between an AP MLD and non-AP MLD.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-09-05 23:08:43 +03:00 committed by Jouni Malinen
parent 0cc6f985d1
commit b20991da69
7 changed files with 134 additions and 71 deletions

View file

@ -16,7 +16,8 @@
static void ccmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data, static void ccmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data,
u8 *aad, size_t *aad_len, u8 *nonce) const u8 *a1, const u8 *a2, u8 *aad, size_t *aad_len,
u8 *nonce)
{ {
u16 fc, stype, seq; u16 fc, stype, seq;
int qos = 0, addr4 = 0; int qos = 0, addr4 = 0;
@ -49,6 +50,10 @@ static void ccmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data,
WPA_PUT_LE16(aad, fc); WPA_PUT_LE16(aad, fc);
pos = aad + 2; pos = aad + 2;
os_memcpy(pos, hdr->addr1, 3 * ETH_ALEN); os_memcpy(pos, hdr->addr1, 3 * ETH_ALEN);
if (a1)
os_memcpy(pos, a1, ETH_ALEN);
if (a2)
os_memcpy(pos + ETH_ALEN, a2, ETH_ALEN);
pos += 3 * ETH_ALEN; pos += 3 * ETH_ALEN;
seq = le_to_host16(hdr->seq_ctrl); seq = le_to_host16(hdr->seq_ctrl);
seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */ seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */
@ -67,6 +72,9 @@ static void ccmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data,
*aad_len = pos - aad; *aad_len = pos - aad;
if (a2)
os_memcpy(nonce + 1, a2, ETH_ALEN);
else
os_memcpy(nonce + 1, hdr->addr2, ETH_ALEN); os_memcpy(nonce + 1, hdr->addr2, ETH_ALEN);
nonce[7] = data[7]; /* PN5 */ nonce[7] = data[7]; /* PN5 */
nonce[8] = data[6]; /* PN4 */ nonce[8] = data[6]; /* PN4 */
@ -136,7 +144,8 @@ static void ccmp_aad_nonce_pv1(const u8 *hdr, const u8 *a1, const u8 *a2,
u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len) const u8 *a1, const u8 *a2, const u8 *data, size_t data_len,
size_t *decrypted_len)
{ {
u8 aad[30], nonce[13]; u8 aad[30], nonce[13];
size_t aad_len; size_t aad_len;
@ -153,7 +162,7 @@ u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
mlen = data_len - 8 - 8; mlen = data_len - 8 - 8;
os_memset(aad, 0, sizeof(aad)); os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce(hdr, data, aad, &aad_len, nonce); ccmp_aad_nonce(hdr, data, a1, a2, aad, &aad_len, nonce);
wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", aad, aad_len);
wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13); wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13);
@ -187,8 +196,9 @@ void ccmp_get_pn(u8 *pn, const u8 *data)
} }
u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos, u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
u8 *pn, int keyid, size_t *encrypted_len) const u8 *qos, const u8 *a1, const u8 *a2, const u8 *pn,
int keyid, size_t *encrypted_len)
{ {
u8 aad[30], nonce[13]; u8 aad[30], nonce[13];
size_t aad_len, plen; size_t aad_len, plen;
@ -217,7 +227,7 @@ u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos,
*pos++ = pn[0]; /* PN5 */ *pos++ = pn[0]; /* PN5 */
os_memset(aad, 0, sizeof(aad)); os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce(hdr, crypt + hdrlen, aad, &aad_len, nonce); ccmp_aad_nonce(hdr, crypt + hdrlen, a1, a2, aad, &aad_len, nonce);
wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", aad, aad_len);
wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13); wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, 13);
@ -278,6 +288,7 @@ u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3,
u8 * ccmp_256_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, u8 * ccmp_256_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *a1, const u8 *a2,
const u8 *data, size_t data_len, size_t *decrypted_len) const u8 *data, size_t data_len, size_t *decrypted_len)
{ {
u8 aad[30], nonce[13]; u8 aad[30], nonce[13];
@ -295,7 +306,7 @@ u8 * ccmp_256_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
mlen = data_len - 8 - 16; mlen = data_len - 8 - 16;
os_memset(aad, 0, sizeof(aad)); os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce(hdr, data, aad, &aad_len, nonce); ccmp_aad_nonce(hdr, data, a1, a2, aad, &aad_len, nonce);
wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 AAD", aad, aad_len);
wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 nonce", nonce, 13); wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 nonce", nonce, 13);
@ -319,7 +330,8 @@ u8 * ccmp_256_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
u8 * ccmp_256_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 * ccmp_256_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
u8 *qos, u8 *pn, int keyid, size_t *encrypted_len) const u8 *qos, const u8 *a1, const u8 *a2, const u8 *pn,
int keyid, size_t *encrypted_len)
{ {
u8 aad[30], nonce[13]; u8 aad[30], nonce[13];
size_t aad_len, plen; size_t aad_len, plen;
@ -348,7 +360,7 @@ u8 * ccmp_256_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
*pos++ = pn[0]; /* PN5 */ *pos++ = pn[0]; /* PN5 */
os_memset(aad, 0, sizeof(aad)); os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce(hdr, crypt + hdrlen, aad, &aad_len, nonce); ccmp_aad_nonce(hdr, crypt + hdrlen, a1, a2, aad, &aad_len, nonce);
wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 AAD", aad, aad_len);
wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 nonce", nonce, 13); wpa_hexdump(MSG_EXCESSIVE, "CCMP-256 nonce", nonce, 13);

View file

@ -16,7 +16,8 @@
static void gcmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data, static void gcmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data,
u8 *aad, size_t *aad_len, u8 *nonce) const u8 *a1, const u8 *a2, u8 *aad, size_t *aad_len,
u8 *nonce)
{ {
u16 fc, stype, seq; u16 fc, stype, seq;
int qos = 0, addr4 = 0; int qos = 0, addr4 = 0;
@ -44,6 +45,10 @@ static void gcmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data,
WPA_PUT_LE16(aad, fc); WPA_PUT_LE16(aad, fc);
pos = aad + 2; pos = aad + 2;
os_memcpy(pos, hdr->addr1, 3 * ETH_ALEN); os_memcpy(pos, hdr->addr1, 3 * ETH_ALEN);
if (a1)
os_memcpy(pos, a1, ETH_ALEN);
if (a2)
os_memcpy(pos + ETH_ALEN, a2, ETH_ALEN);
pos += 3 * ETH_ALEN; pos += 3 * ETH_ALEN;
seq = le_to_host16(hdr->seq_ctrl); seq = le_to_host16(hdr->seq_ctrl);
seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */ seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */
@ -62,6 +67,9 @@ static void gcmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data,
*aad_len = pos - aad; *aad_len = pos - aad;
if (a2)
os_memcpy(nonce, a2, ETH_ALEN);
else
os_memcpy(nonce, hdr->addr2, ETH_ALEN); os_memcpy(nonce, hdr->addr2, ETH_ALEN);
nonce[6] = data[7]; /* PN5 */ nonce[6] = data[7]; /* PN5 */
nonce[7] = data[6]; /* PN4 */ nonce[7] = data[6]; /* PN4 */
@ -73,7 +81,8 @@ static void gcmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data,
u8 * gcmp_decrypt(const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr, 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) const u8 *a1, const u8 *a2, const u8 *data, size_t data_len,
size_t *decrypted_len)
{ {
u8 aad[30], nonce[12], *plain; u8 aad[30], nonce[12], *plain;
size_t aad_len, mlen; size_t aad_len, mlen;
@ -90,7 +99,7 @@ u8 * gcmp_decrypt(const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr,
mlen = data_len - 8 - 16; mlen = data_len - 8 - 16;
os_memset(aad, 0, sizeof(aad)); os_memset(aad, 0, sizeof(aad));
gcmp_aad_nonce(hdr, data, aad, &aad_len, nonce); gcmp_aad_nonce(hdr, data, a1, a2, aad, &aad_len, nonce);
wpa_hexdump(MSG_EXCESSIVE, "GCMP AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "GCMP AAD", aad, aad_len);
wpa_hexdump(MSG_EXCESSIVE, "GCMP nonce", nonce, sizeof(nonce)); wpa_hexdump(MSG_EXCESSIVE, "GCMP nonce", nonce, sizeof(nonce));
@ -113,7 +122,7 @@ u8 * gcmp_decrypt(const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr,
u8 * gcmp_encrypt(const u8 *tk, size_t tk_len, const u8 *frame, size_t len, u8 * gcmp_encrypt(const u8 *tk, size_t tk_len, const u8 *frame, size_t len,
size_t hdrlen, const u8 *qos, size_t hdrlen, const u8 *qos, const u8 *a1, const u8 *a2,
const u8 *pn, int keyid, size_t *encrypted_len) const u8 *pn, int keyid, size_t *encrypted_len)
{ {
u8 aad[30], nonce[12], *crypt, *pos; u8 aad[30], nonce[12], *crypt, *pos;
@ -141,7 +150,7 @@ u8 * gcmp_encrypt(const u8 *tk, size_t tk_len, const u8 *frame, size_t len,
*pos++ = pn[0]; /* PN5 */ *pos++ = pn[0]; /* PN5 */
os_memset(aad, 0, sizeof(aad)); os_memset(aad, 0, sizeof(aad));
gcmp_aad_nonce(hdr, crypt + hdrlen, aad, &aad_len, nonce); gcmp_aad_nonce(hdr, crypt + hdrlen, a1, a2, aad, &aad_len, nonce);
wpa_hexdump(MSG_EXCESSIVE, "GCMP AAD", aad, aad_len); wpa_hexdump(MSG_EXCESSIVE, "GCMP AAD", aad, aad_len);
wpa_hexdump(MSG_EXCESSIVE, "GCMP nonce", nonce, sizeof(nonce)); wpa_hexdump(MSG_EXCESSIVE, "GCMP nonce", nonce, sizeof(nonce));

View file

@ -143,7 +143,7 @@ static int wlantest_inject_prot_bc(struct wlantest *wt,
else else
crypt = ccmp_encrypt(incorrect_key ? stub : crypt = ccmp_encrypt(incorrect_key ? stub :
bss->gtk[bss->gtk_idx], bss->gtk[bss->gtk_idx],
frame, len, hdrlen, NULL, pn, frame, len, hdrlen, NULL, NULL, NULL, pn,
bss->gtk_idx, &crypt_len); bss->gtk_idx, &crypt_len);
if (crypt == NULL) if (crypt == NULL)
@ -246,7 +246,7 @@ static int wlantest_inject_prot(struct wlantest *wt, struct wlantest_bss *bss,
os_memset(stub, 0x11, sizeof(stub)); os_memset(stub, 0x11, sizeof(stub));
if (tk) if (tk)
crypt = ccmp_encrypt(incorrect_key ? stub : tk, crypt = ccmp_encrypt(incorrect_key ? stub : tk,
frame, len, hdrlen, qos, pn, 0, frame, len, hdrlen, qos, NULL, NULL, pn, 0,
&crypt_len); &crypt_len);
else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) else if (sta->pairwise_cipher == WPA_CIPHER_TKIP)
crypt = tkip_encrypt(incorrect_key ? stub : sta->ptk.tk, crypt = tkip_encrypt(incorrect_key ? stub : sta->ptk.tk,
@ -254,7 +254,7 @@ static int wlantest_inject_prot(struct wlantest *wt, struct wlantest_bss *bss,
&crypt_len); &crypt_len);
else else
crypt = ccmp_encrypt(incorrect_key ? stub : sta->ptk.tk, crypt = ccmp_encrypt(incorrect_key ? stub : sta->ptk.tk,
frame, len, hdrlen, qos, pn, 0, frame, len, hdrlen, qos, NULL, NULL, pn, 0,
&crypt_len); &crypt_len);
if (crypt == NULL) { if (crypt == NULL) {

View file

@ -152,6 +152,7 @@ static void rx_data_process(struct wlantest *wt, struct wlantest_bss *bss,
static u8 * try_ptk(struct wlantest *wt, int pairwise_cipher, static u8 * try_ptk(struct wlantest *wt, int pairwise_cipher,
struct wpa_ptk *ptk, const struct ieee80211_hdr *hdr, struct wpa_ptk *ptk, const struct ieee80211_hdr *hdr,
const u8 *a1, const u8 *a2,
const u8 *data, size_t data_len, size_t *decrypted_len) const u8 *data, size_t data_len, size_t *decrypted_len)
{ {
u8 *decrypted; u8 *decrypted;
@ -160,17 +161,17 @@ static u8 * try_ptk(struct wlantest *wt, int pairwise_cipher,
decrypted = NULL; decrypted = NULL;
if ((pairwise_cipher == WPA_CIPHER_CCMP || if ((pairwise_cipher == WPA_CIPHER_CCMP ||
pairwise_cipher == 0) && tk_len == 16) { pairwise_cipher == 0) && tk_len == 16) {
decrypted = ccmp_decrypt(ptk->tk, hdr, data, decrypted = ccmp_decrypt(ptk->tk, hdr, a1, a2, data,
data_len, decrypted_len); data_len, decrypted_len);
} else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 || } else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 ||
pairwise_cipher == 0) && tk_len == 32) { pairwise_cipher == 0) && tk_len == 32) {
decrypted = ccmp_256_decrypt(ptk->tk, hdr, data, decrypted = ccmp_256_decrypt(ptk->tk, hdr, a1, a2, data,
data_len, decrypted_len); data_len, decrypted_len);
} else if ((pairwise_cipher == WPA_CIPHER_GCMP || } else if ((pairwise_cipher == WPA_CIPHER_GCMP ||
pairwise_cipher == WPA_CIPHER_GCMP_256 || pairwise_cipher == WPA_CIPHER_GCMP_256 ||
pairwise_cipher == 0) && pairwise_cipher == 0) &&
(tk_len == 16 || tk_len == 32)) { (tk_len == 16 || tk_len == 32)) {
decrypted = gcmp_decrypt(ptk->tk, tk_len, hdr, decrypted = gcmp_decrypt(ptk->tk, tk_len, hdr, a1, a2,
data, data_len, decrypted_len); data, data_len, decrypted_len);
} else if ((pairwise_cipher == WPA_CIPHER_TKIP || } else if ((pairwise_cipher == WPA_CIPHER_TKIP ||
pairwise_cipher == 0) && tk_len == 32) { pairwise_cipher == 0) && tk_len == 32) {
@ -190,7 +191,8 @@ static u8 * try_ptk(struct wlantest *wt, int pairwise_cipher,
static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher,
const struct ieee80211_hdr *hdr, int keyid, const struct ieee80211_hdr *hdr,
const u8 *a1, const u8 *a2, int keyid,
const u8 *data, size_t data_len, size_t *decrypted_len) const u8 *data, size_t data_len, size_t *decrypted_len)
{ {
struct wlantest_ptk *ptk; struct wlantest_ptk *ptk;
@ -199,7 +201,7 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher,
wpa_debug_level = MSG_WARNING; wpa_debug_level = MSG_WARNING;
dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) { dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
decrypted = try_ptk(wt, pairwise_cipher, &ptk->ptk, hdr, decrypted = try_ptk(wt, pairwise_cipher, &ptk->ptk, hdr, a1, a2,
data, data_len, decrypted_len); data, data_len, decrypted_len);
if (decrypted) { if (decrypted) {
wpa_debug_level = prev_level; wpa_debug_level = prev_level;
@ -288,8 +290,8 @@ static void rx_data_bss_prot_group(struct wlantest *wt,
if (bss->gtk_len[keyid] == 0 && if (bss->gtk_len[keyid] == 0 &&
(bss->group_cipher != WPA_CIPHER_WEP40 || (bss->group_cipher != WPA_CIPHER_WEP40 ||
dl_list_empty(&wt->wep))) { dl_list_empty(&wt->wep))) {
decrypted = try_all_ptk(wt, bss->group_cipher, hdr, keyid, decrypted = try_all_ptk(wt, bss->group_cipher, hdr, NULL, NULL,
data, len, &dlen); keyid, data, len, &dlen);
if (decrypted) if (decrypted)
goto process; goto process;
add_note(wt, MSG_MSGDUMP, add_note(wt, MSG_MSGDUMP,
@ -337,15 +339,15 @@ skip_replay_det:
} else if (bss->group_cipher == WPA_CIPHER_WEP40) { } else if (bss->group_cipher == WPA_CIPHER_WEP40) {
decrypted = wep_decrypt(wt, hdr, data, len, &dlen); decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
} else if (bss->group_cipher == WPA_CIPHER_CCMP) { } else if (bss->group_cipher == WPA_CIPHER_CCMP) {
decrypted = ccmp_decrypt(bss->gtk[keyid], hdr, data, len, decrypted = ccmp_decrypt(bss->gtk[keyid], hdr, NULL, NULL,
&dlen); data, len, &dlen);
} else if (bss->group_cipher == WPA_CIPHER_CCMP_256) { } else if (bss->group_cipher == WPA_CIPHER_CCMP_256) {
decrypted = ccmp_256_decrypt(bss->gtk[keyid], hdr, data, len, decrypted = ccmp_256_decrypt(bss->gtk[keyid], hdr, NULL, NULL,
&dlen); data, len, &dlen);
} else if (bss->group_cipher == WPA_CIPHER_GCMP || } else if (bss->group_cipher == WPA_CIPHER_GCMP ||
bss->group_cipher == WPA_CIPHER_GCMP_256) { bss->group_cipher == WPA_CIPHER_GCMP_256) {
decrypted = gcmp_decrypt(bss->gtk[keyid], bss->gtk_len[keyid], decrypted = gcmp_decrypt(bss->gtk[keyid], bss->gtk_len[keyid],
hdr, data, len, &dlen); hdr, NULL, NULL, data, len, &dlen);
} }
if (decrypted) { if (decrypted) {
@ -378,14 +380,29 @@ static u8 * try_ptk_decrypt(struct wlantest *wt, struct wlantest_sta *sta,
const u8 *tk, size_t tk_len, size_t *dlen) const u8 *tk, size_t tk_len, size_t *dlen)
{ {
u8 *decrypted = NULL; u8 *decrypted = NULL;
u16 fc = le_to_host16(hdr->frame_control);
const u8 *a1 = NULL, *a2 = NULL;
if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) &&
!is_zero_ether_addr(sta->mld_mac_addr) &&
!is_zero_ether_addr(sta->bss->mld_mac_addr)) {
if (os_memcmp(hdr->addr1, sta->addr, ETH_ALEN) == 0) {
a1 = sta->mld_mac_addr;
a2 = sta->bss->mld_mac_addr;
} else {
a1 = sta->bss->mld_mac_addr;
a2 = sta->mld_mac_addr;
}
}
if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256)
decrypted = ccmp_256_decrypt(tk, hdr, data, len, dlen); decrypted = ccmp_256_decrypt(tk, hdr, a1, a2, data, len, dlen);
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(tk, tk_len, hdr, data, len, dlen); decrypted = gcmp_decrypt(tk, tk_len, hdr, a1, a2,
data, len, dlen);
else else
decrypted = ccmp_decrypt(tk, hdr, data, len, dlen); decrypted = ccmp_decrypt(tk, hdr, a1, a2, data, len, dlen);
write_decrypted_note(wt, decrypted, tk, tk_len, keyid); write_decrypted_note(wt, decrypted, tk, tk_len, keyid);
return decrypted; return decrypted;
@ -412,6 +429,7 @@ static void rx_data_bss_prot(struct wlantest *wt,
int replay = 0; int replay = 0;
int only_zero_tk = 0; int only_zero_tk = 0;
u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
const u8 *a1 = NULL, *a2 = NULL;
if (hdr->addr1[0] & 0x01) { if (hdr->addr1[0] & 0x01) {
rx_data_bss_prot_group(wt, hdr, hdrlen, qos, dst, src, rx_data_bss_prot_group(wt, hdr, hdrlen, qos, dst, src,
@ -607,18 +625,32 @@ static void rx_data_bss_prot(struct wlantest *wt,
} }
skip_replay_det: skip_replay_det:
if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) &&
!is_zero_ether_addr(sta->mld_mac_addr) &&
!is_zero_ether_addr(bss->mld_mac_addr)) {
if (os_memcmp(hdr->addr1, sta->addr, ETH_ALEN) == 0) {
a1 = sta->mld_mac_addr;
a2 = bss->mld_mac_addr;
} else {
a1 = bss->mld_mac_addr;
a2 = sta->mld_mac_addr;
}
}
if (tk) { if (tk) {
if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) { if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) {
decrypted = ccmp_256_decrypt(tk, hdr, data, len, &dlen); decrypted = ccmp_256_decrypt(tk, hdr, a1, a2, data, len,
&dlen);
write_decrypted_note(wt, decrypted, tk, 32, keyid); write_decrypted_note(wt, decrypted, 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(tk, sta->ptk.tk_len, hdr, data, decrypted = gcmp_decrypt(tk, sta->ptk.tk_len, hdr,
len, &dlen); a1, a2, data, len, &dlen);
write_decrypted_note(wt, decrypted, tk, sta->ptk.tk_len, write_decrypted_note(wt, decrypted, tk, sta->ptk.tk_len,
keyid); keyid);
} else { } else {
decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen); decrypted = ccmp_decrypt(tk, hdr, a1, a2, data, len,
&dlen);
write_decrypted_note(wt, decrypted, tk, 16, keyid); write_decrypted_note(wt, decrypted, tk, 16, keyid);
} }
} else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) { } else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) {
@ -638,13 +670,13 @@ skip_replay_det:
sta->ptk.tk, sta->ptk.tk_len, sta->ptk.tk, sta->ptk.tk_len,
&dlen); &dlen);
} else { } else {
decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, keyid, decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, a1, a2,
data, len, &dlen); keyid, data, len, &dlen);
ptk_iter_done = 1; ptk_iter_done = 1;
} }
if (!decrypted && !ptk_iter_done) { if (!decrypted && !ptk_iter_done) {
decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, keyid, decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, a1, a2,
data, len, &dlen); keyid, data, len, &dlen);
if (decrypted) { if (decrypted) {
add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs"); add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs");
} }
@ -658,7 +690,7 @@ check_zero_tk:
zero_ptk.tk_len = wpa_cipher_key_len(sta->pairwise_cipher); zero_ptk.tk_len = wpa_cipher_key_len(sta->pairwise_cipher);
wpa_debug_level = MSG_ERROR; wpa_debug_level = MSG_ERROR;
decrypted = try_ptk(wt, sta->pairwise_cipher, &zero_ptk, hdr, decrypted = try_ptk(wt, sta->pairwise_cipher, &zero_ptk, hdr,
data, len, &dlen); a1, a2, data, len, &dlen);
wpa_debug_level = old_debug_level; wpa_debug_level = old_debug_level;
if (decrypted) { if (decrypted) {
add_note(wt, MSG_DEBUG, add_note(wt, MSG_DEBUG,

View file

@ -2274,17 +2274,17 @@ static u8 * try_tk(struct wpa_ptk *ptk, size_t ptk_len,
hdr = (const struct ieee80211_hdr *) data; hdr = (const struct ieee80211_hdr *) data;
if (ptk_len == 16) { if (ptk_len == 16) {
decrypted = ccmp_decrypt(ptk->tk, hdr, data + 24, len - 24, decrypted = ccmp_decrypt(ptk->tk, hdr, NULL, NULL,
dlen); data + 24, len - 24, dlen);
if (!decrypted) if (!decrypted)
decrypted = gcmp_decrypt(ptk->tk, 16, hdr, data + 24, decrypted = gcmp_decrypt(ptk->tk, 16, hdr, NULL, NULL,
len - 24, dlen); data + 24, len - 24, dlen);
} else if (ptk_len == 32) { } else if (ptk_len == 32) {
decrypted = ccmp_256_decrypt(ptk->tk, hdr, data + 24, len - 24, decrypted = ccmp_256_decrypt(ptk->tk, hdr, NULL, NULL,
dlen); data + 24, len - 24, dlen);
if (!decrypted) if (!decrypted)
decrypted = gcmp_decrypt(ptk->tk, 32, hdr, data + 24, decrypted = gcmp_decrypt(ptk->tk, 32, hdr, NULL, NULL,
len - 24, dlen); data + 24, len - 24, dlen);
} else { } else {
decrypted = NULL; decrypted = NULL;
} }
@ -2407,18 +2407,19 @@ 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, data + 24, decrypted = ccmp_256_decrypt(sta->ptk.tk, hdr, NULL, NULL,
len - 24, dlen); data + 24, len - 24, 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,
data + 24, len - 24, dlen); data + 24, len - 24, 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, data + 24, len - 24, decrypted = ccmp_decrypt(sta->ptk.tk, hdr, NULL, NULL,
dlen); data + 24, len - 24, 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) {

View file

@ -107,7 +107,8 @@ static void test_vector_ccmp(void)
wpa_hexdump(MSG_INFO, "802.11 Header", frame, 24); wpa_hexdump(MSG_INFO, "802.11 Header", frame, 24);
wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 24, sizeof(frame) - 24); wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 24, sizeof(frame) - 24);
enc = ccmp_encrypt(tk, frame, sizeof(frame), 24, NULL, pn, 0, &enc_len); enc = ccmp_encrypt(tk, frame, sizeof(frame), 24, NULL, NULL, NULL, pn,
0, &enc_len);
if (enc == NULL) { if (enc == NULL) {
wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame"); wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame");
return; return;
@ -119,7 +120,7 @@ static void test_vector_ccmp(void)
wpa_debug_level = MSG_INFO; wpa_debug_level = MSG_INFO;
plain = ccmp_decrypt(tk, (const struct ieee80211_hdr *) enc, plain = ccmp_decrypt(tk, (const struct ieee80211_hdr *) enc,
enc + 24, enc_len - 24, &plain_len); enc + 24, NULL, NULL, enc_len - 24, &plain_len);
wpa_debug_level = MSG_EXCESSIVE; wpa_debug_level = MSG_EXCESSIVE;
os_free(enc); os_free(enc);
@ -401,7 +402,8 @@ static void test_vector_ccmp_mgmt(void)
wpa_hexdump(MSG_INFO, "802.11 Header", frame, 24); wpa_hexdump(MSG_INFO, "802.11 Header", frame, 24);
wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 24, sizeof(frame) - 24); wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 24, sizeof(frame) - 24);
enc = ccmp_encrypt(tk, frame, sizeof(frame), 24, NULL, pn, 0, &enc_len); enc = ccmp_encrypt(tk, frame, sizeof(frame), 24, NULL, NULL, NULL, pn,
0, &enc_len);
if (enc == NULL) { if (enc == NULL) {
wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame"); wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame");
return; return;
@ -411,7 +413,7 @@ static void test_vector_ccmp_mgmt(void)
wpa_debug_level = MSG_INFO; wpa_debug_level = MSG_INFO;
plain = ccmp_decrypt(tk, (const struct ieee80211_hdr *) enc, plain = ccmp_decrypt(tk, (const struct ieee80211_hdr *) enc,
enc + 24, enc_len - 24, &plain_len); enc + 24, NULL, NULL, enc_len - 24, &plain_len);
wpa_debug_level = MSG_EXCESSIVE; wpa_debug_level = MSG_EXCESSIVE;
os_free(enc); os_free(enc);
@ -580,6 +582,7 @@ static int run_gcmp(int idx, const struct gcmp_test *vector)
vector->hdr_len, vector->hdr_len,
vector->hdr_len == 26 ? vector->hdr_len == 26 ?
vector->frame + vector->hdr_len - 2 : NULL, vector->frame + vector->hdr_len - 2 : NULL,
NULL, NULL,
vector->pn, 0, &enc_len); vector->pn, 0, &enc_len);
if (enc == NULL) { if (enc == NULL) {
wpa_printf(MSG_ERROR, "Failed to encrypt GCMP frame"); wpa_printf(MSG_ERROR, "Failed to encrypt GCMP frame");
@ -603,7 +606,7 @@ static int run_gcmp(int idx, const struct gcmp_test *vector)
wpa_debug_level = MSG_INFO; wpa_debug_level = MSG_INFO;
plain = gcmp_decrypt(vector->tk, sizeof(vector->tk), plain = gcmp_decrypt(vector->tk, sizeof(vector->tk),
(const struct ieee80211_hdr *) enc, (const struct ieee80211_hdr *) enc, NULL, NULL,
enc + vector->hdr_len, enc + vector->hdr_len,
enc_len - vector->hdr_len, &plain_len); enc_len - vector->hdr_len, &plain_len);
wpa_debug_level = MSG_EXCESSIVE; wpa_debug_level = MSG_EXCESSIVE;
@ -689,7 +692,7 @@ static int test_vector_gcmp_256(void)
wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 26, sizeof(frame) - 26); wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 26, sizeof(frame) - 26);
enc = gcmp_encrypt(tk, sizeof(tk), frame, sizeof(frame), 26, frame + 24, enc = gcmp_encrypt(tk, sizeof(tk), frame, sizeof(frame), 26, frame + 24,
pn, 0, &enc_len); NULL, NULL, pn, 0, &enc_len);
if (enc == NULL) { if (enc == NULL) {
wpa_printf(MSG_ERROR, "Failed to encrypt GCMP frame"); wpa_printf(MSG_ERROR, "Failed to encrypt GCMP frame");
return 1; return 1;
@ -705,7 +708,7 @@ static int test_vector_gcmp_256(void)
wpa_debug_level = MSG_INFO; wpa_debug_level = MSG_INFO;
plain = gcmp_decrypt(tk, sizeof(tk), (const struct ieee80211_hdr *) enc, plain = gcmp_decrypt(tk, sizeof(tk), (const struct ieee80211_hdr *) enc,
enc + 26, enc_len - 26, &plain_len); NULL, NULL, enc + 26, enc_len - 26, &plain_len);
wpa_debug_level = MSG_EXCESSIVE; wpa_debug_level = MSG_EXCESSIVE;
os_free(enc); os_free(enc);
@ -766,8 +769,8 @@ static int test_vector_ccmp_256(void)
wpa_hexdump(MSG_INFO, "802.11 Header", frame, 24); wpa_hexdump(MSG_INFO, "802.11 Header", frame, 24);
wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 24, sizeof(frame) - 24); wpa_hexdump(MSG_INFO, "Plaintext Data", frame + 24, sizeof(frame) - 24);
enc = ccmp_256_encrypt(tk, frame, sizeof(frame), 24, NULL, pn, 0, enc = ccmp_256_encrypt(tk, frame, sizeof(frame), 24, NULL, NULL, NULL,
&enc_len); pn, 0, &enc_len);
if (enc == NULL) { if (enc == NULL) {
wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame"); wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame");
return 1; return 1;
@ -783,7 +786,8 @@ static int test_vector_ccmp_256(void)
wpa_debug_level = MSG_INFO; wpa_debug_level = MSG_INFO;
plain = ccmp_256_decrypt(tk, (const struct ieee80211_hdr *) enc, plain = ccmp_256_decrypt(tk, (const struct ieee80211_hdr *) enc,
enc + 24, enc_len - 24, &plain_len); enc + 24, NULL, NULL, enc_len - 24,
&plain_len);
wpa_debug_level = MSG_EXCESSIVE; wpa_debug_level = MSG_EXCESSIVE;
os_free(enc); os_free(enc);

View file

@ -303,18 +303,22 @@ void sta_update_assoc(struct wlantest_sta *sta,
struct ieee802_11_elems *elems); struct ieee802_11_elems *elems);
u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len); const u8 *a1, const u8 *a2, const u8 *data, size_t data_len,
u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos, size_t *decrypted_len);
u8 *pn, int keyid, size_t *encrypted_len); u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
const u8 *qos, const u8 *a1, const u8 *a2, const u8 *pn,
int keyid, size_t *encrypted_len);
u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3, u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3,
const u8 *frame, size_t len, const u8 *frame, size_t len,
size_t hdrlen, const u8 *pn, int keyid, size_t hdrlen, const u8 *pn, int keyid,
size_t *encrypted_len); size_t *encrypted_len);
void ccmp_get_pn(u8 *pn, const u8 *data); void ccmp_get_pn(u8 *pn, const u8 *data);
u8 * ccmp_256_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr, u8 * ccmp_256_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *a1, const u8 *a2,
const u8 *data, size_t data_len, size_t *decrypted_len); const u8 *data, size_t data_len, size_t *decrypted_len);
u8 * ccmp_256_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 * ccmp_256_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
u8 *qos, u8 *pn, int keyid, size_t *encrypted_len); const u8 *qos, const u8 *a1, const u8 *a2, const u8 *pn,
int keyid, size_t *encrypted_len);
enum michael_mic_result { enum michael_mic_result {
MICHAEL_MIC_OK, MICHAEL_MIC_OK,
@ -337,9 +341,10 @@ 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 *ipn, int keyid, size_t *prot_len);
u8 * gcmp_decrypt(const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr, 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); const u8 *a1, const u8 *a2, const u8 *data, size_t data_len,
size_t *decrypted_len);
u8 * gcmp_encrypt(const u8 *tk, size_t tk_len, const u8 *frame, size_t len, u8 * gcmp_encrypt(const u8 *tk, size_t tk_len, const u8 *frame, size_t len,
size_t hdrlen, const u8 *qos, size_t hdrlen, const u8 *qos, const u8 *a1, const u8 *a2,
const u8 *pn, int keyid, size_t *encrypted_len); const u8 *pn, int keyid, size_t *encrypted_len);
int ctrl_init(struct wlantest *wt); int ctrl_init(struct wlantest *wt);