diff options
author | Jouni Malinen <jouni@qca.qualcomm.com> | 2016-10-26 17:42:05 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2016-10-27 10:03:25 -0400 |
commit | 39404feee691a2dc524a629ed6eb5cfe5d8898d1 (patch) | |
tree | e56b8589724efff836d7878f5e7793151effb945 /net/mac80211/mlme.c | |
parent | dbc0c2cb2f0a02fcb034732cb3d55ea6359b9c8b (diff) |
mac80211: FILS AEAD protection for station mode association frames
This adds support for encrypting (Re)Association Request frame and
decryption (Re)Association Response frame when using FILS in station
mode.
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index bf553797bdff..d157b250ff77 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "driver-ops.h" | 30 | #include "driver-ops.h" |
31 | #include "rate.h" | 31 | #include "rate.h" |
32 | #include "led.h" | 32 | #include "led.h" |
33 | #include "fils_aead.h" | ||
33 | 34 | ||
34 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | 35 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) |
35 | #define IEEE80211_AUTH_TIMEOUT_LONG (HZ / 2) | 36 | #define IEEE80211_AUTH_TIMEOUT_LONG (HZ / 2) |
@@ -652,6 +653,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
652 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ | 653 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ |
653 | 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */ | 654 | 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */ |
654 | assoc_data->ie_len + /* extra IEs */ | 655 | assoc_data->ie_len + /* extra IEs */ |
656 | (assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) + | ||
655 | 9, /* WMM */ | 657 | 9, /* WMM */ |
656 | GFP_KERNEL); | 658 | GFP_KERNEL); |
657 | if (!skb) | 659 | if (!skb) |
@@ -875,6 +877,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
875 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | 877 | memcpy(pos, assoc_data->ie + offset, noffset - offset); |
876 | } | 878 | } |
877 | 879 | ||
880 | if (assoc_data->fils_kek_len && | ||
881 | fils_encrypt_assoc_req(skb, assoc_data) < 0) { | ||
882 | dev_kfree_skb(skb); | ||
883 | return; | ||
884 | } | ||
885 | |||
878 | drv_mgd_prepare_tx(local, sdata); | 886 | drv_mgd_prepare_tx(local, sdata); |
879 | 887 | ||
880 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 888 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
@@ -3146,6 +3154,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
3146 | reassoc ? "Rea" : "A", mgmt->sa, | 3154 | reassoc ? "Rea" : "A", mgmt->sa, |
3147 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | 3155 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
3148 | 3156 | ||
3157 | if (assoc_data->fils_kek_len && | ||
3158 | fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0) | ||
3159 | return; | ||
3160 | |||
3149 | pos = mgmt->u.assoc_resp.variable; | 3161 | pos = mgmt->u.assoc_resp.variable; |
3150 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems); | 3162 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems); |
3151 | 3163 | ||
@@ -4707,6 +4719,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4707 | assoc_data->ie_len = req->ie_len; | 4719 | assoc_data->ie_len = req->ie_len; |
4708 | } | 4720 | } |
4709 | 4721 | ||
4722 | if (req->fils_kek) { | ||
4723 | /* should already be checked in cfg80211 - so warn */ | ||
4724 | if (WARN_ON(req->fils_kek_len > FILS_MAX_KEK_LEN)) { | ||
4725 | err = -EINVAL; | ||
4726 | goto err_free; | ||
4727 | } | ||
4728 | memcpy(assoc_data->fils_kek, req->fils_kek, | ||
4729 | req->fils_kek_len); | ||
4730 | assoc_data->fils_kek_len = req->fils_kek_len; | ||
4731 | } | ||
4732 | |||
4733 | if (req->fils_nonces) | ||
4734 | memcpy(assoc_data->fils_nonces, req->fils_nonces, | ||
4735 | 2 * FILS_NONCE_LEN); | ||
4736 | |||
4710 | assoc_data->bss = req->bss; | 4737 | assoc_data->bss = req->bss; |
4711 | 4738 | ||
4712 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { | 4739 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { |