brcmfmac: support 4-way handshake offloading for WPA/WPA2-PSK in AP mode
authorChung-Hsien Hsu <stanley.hsu@cypress.com>
Mon, 17 Aug 2020 07:33:14 +0000 (02:33 -0500)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 16 Sep 2020 05:56:04 +0000 (08:56 +0300)
Firmware may have authenticator code built-in. This is detected by the
driver and indicated in the wiphy features flags. User space can use
this flag to determine whether or not to provide the pre-shared key
material in the nl80211 start AP command to offload the 4-way handshake
in AP mode.

Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>
Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200817073316.33402-3-stanley.hsu@cypress.com
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h

index 8b5fda9bb8539f7a031685288446866ab85f51cc..4b06e4dbe867c38bece7022f04d565d4430f2c40 100644 (file)
@@ -4679,6 +4679,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
        struct brcmf_if *ifp = netdev_priv(ndev);
        struct brcmf_pub *drvr = cfg->pub;
+       struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+       struct cfg80211_crypto_settings *crypto = &settings->crypto;
        const struct brcmf_tlv *ssid_ie;
        const struct brcmf_tlv *country_ie;
        struct brcmf_ssid_le ssid_le;
@@ -4818,6 +4820,17 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
                        goto exit;
                }
 
+               if (crypto->psk) {
+                       brcmf_dbg(INFO, "using PSK offload\n");
+                       profile->use_fwauth |= BIT(BRCMF_PROFILE_FWAUTH_PSK);
+                       err = brcmf_set_pmk(ifp, crypto->psk,
+                                           BRCMF_WSEC_MAX_PSK_LEN);
+                       if (err < 0)
+                               goto exit;
+               }
+               if (profile->use_fwauth == 0)
+                       profile->use_fwauth = BIT(BRCMF_PROFILE_FWAUTH_NONE);
+
                err = brcmf_parse_configure_security(ifp, settings,
                                                     NL80211_IFTYPE_AP);
                if (err < 0) {
@@ -4904,6 +4917,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
        struct brcmf_if *ifp = netdev_priv(ndev);
        struct brcmf_pub *drvr = cfg->pub;
+       struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
        s32 err;
        struct brcmf_fil_bss_enable_le bss_enable;
        struct brcmf_join_params join_params;
@@ -4915,6 +4929,12 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
                /* first to make sure they get processed by fw. */
                msleep(400);
 
+               if (profile->use_fwauth != BIT(BRCMF_PROFILE_FWAUTH_NONE)) {
+                       if (profile->use_fwauth & BIT(BRCMF_PROFILE_FWAUTH_PSK))
+                               brcmf_set_pmk(ifp, NULL, 0);
+                       profile->use_fwauth = BIT(BRCMF_PROFILE_FWAUTH_NONE);
+               }
+
                if (ifp->vif->mbss) {
                        err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
                        return err;
@@ -7063,6 +7083,9 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
                        wiphy_ext_feature_set(wiphy,
                                              NL80211_EXT_FEATURE_SAE_OFFLOAD);
        }
+       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWAUTH))
+               wiphy_ext_feature_set(wiphy,
+                                     NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK);
        wiphy->mgmt_stypes = brcmf_txrx_stypes;
        wiphy->max_remain_on_channel_duration = 5000;
        if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
index 333fdf394f95a1f7734aa38e5685e1aaba9a7ab9..bf86e0ca941e88fa0d8d89902a394f9ff76867f3 100644 (file)
@@ -128,6 +128,17 @@ enum brcmf_profile_fwsup {
        BRCMF_PROFILE_FWSUP_SAE
 };
 
+/**
+ * enum brcmf_profile_fwauth - firmware authenticator profile
+ *
+ * @BRCMF_PROFILE_FWAUTH_NONE: no firmware authenticator
+ * @BRCMF_PROFILE_FWAUTH_PSK: authenticator for WPA/WPA2-PSK
+ */
+enum brcmf_profile_fwauth {
+       BRCMF_PROFILE_FWAUTH_NONE,
+       BRCMF_PROFILE_FWAUTH_PSK
+};
+
 /**
  * struct brcmf_cfg80211_profile - profile information.
  *
@@ -140,6 +151,7 @@ struct brcmf_cfg80211_profile {
        struct brcmf_cfg80211_security sec;
        struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
        enum brcmf_profile_fwsup use_fwsup;
+       u16 use_fwauth;
        bool is_ft;
 };
 
index 0dcefbd0c0003a59a536812b6ed718d9265c3413..7c68d98493246c45c1ef73ab5f34fd7c4f789cd8 100644 (file)
@@ -42,6 +42,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
        { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
        { BRCMF_FEAT_DOT11H, "802.11h" },
        { BRCMF_FEAT_SAE, "sae" },
+       { BRCMF_FEAT_FWAUTH, "idauth" },
 };
 
 #ifdef DEBUG
index cda3fc1bab7f37ab7b39773cae0406338bcb557a..d1f4257af696b4e6e90c283cdafc0e6b64e66da5 100644 (file)
@@ -28,6 +28,7 @@
  * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header
  * DOT11H: firmware supports 802.11h
  * SAE: simultaneous authentication of equals
+ * FWAUTH: Firmware authenticator
  */
 #define BRCMF_FEAT_LIST \
        BRCMF_FEAT_DEF(MBSS) \
@@ -49,7 +50,8 @@
        BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \
        BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \
        BRCMF_FEAT_DEF(DOT11H) \
-       BRCMF_FEAT_DEF(SAE)
+       BRCMF_FEAT_DEF(SAE) \
+       BRCMF_FEAT_DEF(FWAUTH)
 
 /*
  * Quirks: