summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2016-10-26 17:42:05 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-10-27 10:03:25 -0400
commit39404feee691a2dc524a629ed6eb5cfe5d8898d1 (patch)
treee56b8589724efff836d7878f5e7793151effb945 /net/mac80211/mlme.c
parentdbc0c2cb2f0a02fcb034732cb3d55ea6359b9c8b (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.c27
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) {