summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2012-09-30 19:47:40 +0300
committerJohannes Berg <johannes.berg@intel.com>2012-10-01 09:23:15 +0200
commit33766368f6532313571534f9112b1796d6651bbe (patch)
tree016c716637d79a60c97f914fde8bb17b1f845282 /net
parent7ce8c7a3433c6d6f4adfec0611d250782f0b4b0c (diff)
downloadlinux-33766368f6532313571534f9112b1796d6651bbe.tar.gz
linux-33766368f6532313571534f9112b1796d6651bbe.tar.xz
mac80211: Fix FC masking in BIP AAD generation
The bits used in the mask were off-by-one and ended up masking PwrMgt, MoreData, Protected fields instead of Retry, PwrMgt, MoreData. Fix this and to mask the correct fields. While doing so, convert the code to mask the full FC using IEEE80211_FCTL_* defines similarly to how CCMP AAD is built. Since BIP is used only with broadcast/multicast management frames, the Retry field is always 0 in these frames. The Protected field is also zero to maintain backwards compatibility. As such, the incorrect mask here does not really cause any problems for valid frames. In theory, an invalid BIP frame with Retry or Protected field set to 1 could be rejected because of BIP validation. However, no such frame should show up with standard compliant implementations, so this does not cause problems in normal BIP use. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/wpa.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index bdb53aba888e..e58bf3fe3ed9 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -545,14 +545,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
static void bip_aad(struct sk_buff *skb, u8 *aad)
{
+ __le16 mask_fc;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
/* BIP AAD: FC(masked) || A1 || A2 || A3 */
/* FC type/subtype */
- aad[0] = skb->data[0];
/* Mask FC Retry, PwrMgt, MoreData flags to zero */
- aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
+ mask_fc = hdr->frame_control;
+ mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM |
+ IEEE80211_FCTL_MOREDATA);
+ put_unaligned(mask_fc, (__le16 *) &aad[0]);
/* A1 || A2 || A3 */
- memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
+ memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
}