From: Kavitha Velayutham Date: Tue, 30 Oct 2018 13:39:34 +0000 (+0530) Subject: [NEUS7920-218] [9610][7885][7872][7570] wlbt: Drv Changes for Wpa3 X-Git-Tag: MMI-QSAS30.62-33-3~930 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=9b5afb62ff5c308f0cd696601bfc22eb0a7aa308;p=GitHub%2FMotorolaMobilityLLC%2Fkernel-slsi.git [NEUS7920-218] [9610][7885][7872][7570] wlbt: Drv Changes for Wpa3 Driver changes for Wpa3 SCSC-Bug-Id: SSB-48137 Change-Id: Ifc30ea1c04dab0de30756752efe6c86faf1a7ce8 Signed-off-by: Kavitha Velayutham --- diff --git a/arch/arm64/configs/erd9610_defconfig b/arch/arm64/configs/erd9610_defconfig index 07fdaf8d3e34..33ef5b27d7a0 100644 --- a/arch/arm64/configs/erd9610_defconfig +++ b/arch/arm64/configs/erd9610_defconfig @@ -262,6 +262,7 @@ CONFIG_SCSC_WLAN_DEBUG=y CONFIG_SCSC_WLAN_WIFI_SHARING=y # CONFIG_SCSC_WLAN_SINGLE_ANTENNA is not set # CONFIG_SCSC_WLAN_MHS_STATIC_INTERFACE is not set +CONFIG_SCSC_WLAN_SAE_CONFIG=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y CONFIG_KEYBOARD_GPIO=y diff --git a/drivers/net/wireless/scsc/Kconfig b/drivers/net/wireless/scsc/Kconfig index 675aa64314ab..3acc6cfb3dec 100755 --- a/drivers/net/wireless/scsc/Kconfig +++ b/drivers/net/wireless/scsc/Kconfig @@ -156,6 +156,12 @@ config SCSC_WLAN_WIFI_SHARING ---help--- This option tells if wifi sharing is supported or not. +config SCSC_WLAN_SAE_CONFIG + bool "Wpa3 Support" + default n + ---help--- + This option tells if wpa3 is supported or not. + config SCSC_WLAN_ENABLE_MAC_RANDOMISATION bool "Wifi Mac Randomization Support" default n diff --git a/drivers/net/wireless/scsc/cfg80211_ops.c b/drivers/net/wireless/scsc/cfg80211_ops.c index e3d2eff6ec7d..42c2da2a624a 100755 --- a/drivers/net/wireless/scsc/cfg80211_ops.c +++ b/drivers/net/wireless/scsc/cfg80211_ops.c @@ -1075,8 +1075,24 @@ int slsi_connect(struct wiphy *wiphy, struct net_device *dev, */ netif_carrier_on(dev); ndev_vif->sta.vif_status = SLSI_VIF_STATUS_CONNECTING; - r = slsi_mlme_connect(sdev, dev, sme, channel, bssid); + if (sme->auth_type == NL80211_AUTHTYPE_SAE && (sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) { + const u8 *rsn; + + ndev_vif->sta.crypto.wpa_versions = 3; + rsn = cfg80211_find_ie(WLAN_EID_RSN, ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len); + if (rsn) { + int pos; + + pos = 7 + 2 + (rsn[8] * 4) + 2; + ndev_vif->sta.crypto.akm_suites[0] = ((rsn[pos + 4] << 24) | (rsn[pos + 3] << 16) | (rsn[pos + 2] << 8) | (rsn[pos + 1])); + } + + SLSI_NET_DBG1(dev, SLSI_CFG80211, "RSN IE: : %1d\n", ndev_vif->sta.crypto.akm_suites[0]); + } else { + ndev_vif->sta.crypto.wpa_versions = 0; + } + r = slsi_mlme_connect(sdev, dev, sme, channel, bssid); if (r != 0) { ndev_vif->sta.is_wps = false; SLSI_NET_ERR(dev, "connect failed: %d\n", r); @@ -2681,8 +2697,8 @@ static int slsi_wlan_mgmt_tx(struct slsi_dev *sdev, struct net_device *dev, int r = 0; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; - slsi_wlan_dump_public_action_subtype(sdev, mgmt, true); - + if (!ieee80211_is_auth(mgmt->frame_control)) + slsi_wlan_dump_public_action_subtype(sdev, mgmt, true); if (!ndev_vif->activated) { r = slsi_wlan_unsync_vif_activate(sdev, dev, chan, wait); if (r) @@ -2696,7 +2712,12 @@ static int slsi_wlan_mgmt_tx(struct slsi_dev *sdev, struct net_device *dev, queue_delayed_work(sdev->device_wq, &ndev_vif->unsync.hs2_del_vif_work, msecs_to_jiffies(wait)); } else { /* vif is active*/ - if (ndev_vif->vif_type == FAPI_VIFTYPE_UNSYNCHRONISED) { + if (ieee80211_is_auth(mgmt->frame_control)) { + SLSI_NET_DBG1(dev, SLSI_CFG80211, "Transmit on the current frequency\n"); + r = slsi_mlme_send_frame_mgmt(sdev, dev, buf, len, FAPI_DATAUNITDESCRIPTOR_IEEE802_11_FRAME, FAPI_MESSAGETYPE_IEEE80211_MGMT_NOT_ACTION, host_tag, 0, wait * 1000, 0); + if (r) + return r; + } else if (ndev_vif->vif_type == FAPI_VIFTYPE_UNSYNCHRONISED) { cancel_delayed_work(&ndev_vif->unsync.hs2_del_vif_work); /*even if we fail to cancel the delayed work, we shall go ahead and send action frames*/ if (ndev_vif->driver_channel != chan->hw_value) { @@ -2791,16 +2812,19 @@ int slsi_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - SLSI_NET_DBG2(dev, SLSI_CFG80211, "Mgmt Frame Tx: iface_num = %d, channel = %d, wait = %d, noAck = %d," - "offchannel = %d, mgmt->frame_control = %d, vif_type = %d\n", ndev_vif->ifnum, chan->hw_value, - wait, dont_wait_for_ack, offchan, mgmt->frame_control, ndev_vif->vif_type); + if (!(ieee80211_is_auth(mgmt->frame_control))) { + SLSI_NET_DBG2(dev, SLSI_CFG80211, "Mgmt Frame Tx: iface_num = %d, channel = %d, wait = %d, noAck = %d," + "offchannel = %d, mgmt->frame_control = %d, vif_type = %d\n", ndev_vif->ifnum, chan->hw_value, + wait, dont_wait_for_ack, offchan, mgmt->frame_control, ndev_vif->vif_type); + } else { + SLSI_NET_DBG2(dev, SLSI_CFG80211, "Received Auth Frame"); + } if (!(ieee80211_is_mgmt(mgmt->frame_control))) { SLSI_NET_ERR(dev, "Drop Tx frame: Not a Management frame\n"); r = -EINVAL; goto exit; } - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { r = slsi_wlan_mgmt_tx(SDEV_FROM_WIPHY(wiphy), dev, chan, wait, buf, len, dont_wait_for_ack, cookie); goto exit; @@ -2912,6 +2936,18 @@ int slsi_set_txq_params(struct wiphy *wiphy, struct net_device *ndev, return r; } +int slsi_synchronised_response(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_external_auth_params *params) +{ + struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); + struct netdev_vif *ndev_vif = netdev_priv(dev); + int r; + + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); + r = slsi_mlme_synchronised_response(sdev, dev, params); + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); + return r; +} #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) static int slsi_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie) { @@ -3004,6 +3040,7 @@ static struct cfg80211_ops slsi_ops = { .mgmt_tx = slsi_mgmt_tx, .mgmt_tx_cancel_wait = slsi_mgmt_tx_cancel_wait, .set_txq_params = slsi_set_txq_params, + .external_auth = slsi_synchronised_response, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9)) .set_mac_acl = slsi_set_mac_acl, .update_ft_ies = slsi_update_ft_ies, @@ -3178,12 +3215,14 @@ static const struct ieee80211_txrx_stypes ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { [NL80211_IFTYPE_AP] = { .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) }, [NL80211_IFTYPE_STATION] = { .tx = 0xffff, .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) }, [NL80211_IFTYPE_P2P_GO] = { .tx = 0xffff, @@ -3408,6 +3447,9 @@ struct slsi_dev *slsi_cfg80211_new(struct device *dev) #ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; #endif +#endif +#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG + wiphy->features |= NL80211_FEATURE_SAE; #endif return sdev; } diff --git a/drivers/net/wireless/scsc/dev.h b/drivers/net/wireless/scsc/dev.h index f74715cae579..b808dcaa4848 100755 --- a/drivers/net/wireless/scsc/dev.h +++ b/drivers/net/wireless/scsc/dev.h @@ -555,6 +555,7 @@ struct slsi_vif_sta { /*This structure is used to store last disconnected bss info and valid even when vif is deactivated. */ struct slsi_last_connected_bss last_connected_bss; + struct cfg80211_crypto_settings crypto; }; struct slsi_vif_unsync { diff --git a/drivers/net/wireless/scsc/fapi.h b/drivers/net/wireless/scsc/fapi.h index b72e3a9dffbd..e167d8d70fa0 100644 --- a/drivers/net/wireless/scsc/fapi.h +++ b/drivers/net/wireless/scsc/fapi.h @@ -424,6 +424,8 @@ static inline struct slsi_skb_cb *slsi_skb_cb_init(struct sk_buff *skb) #define FAPI_MESSAGETYPE_WAI_MESSAGE 0x0007 #define FAPI_MESSAGETYPE_PERIODIC_OFFLOAD 0x0008 #define FAPI_MESSAGETYPE_IEEE80211_ACTION 0x0010 +/* TBD: Auto generate to add this */ +#define FAPI_MESSAGETYPE_IEEE80211_MGMT_NOT_ACTION 0x0011 #define FAPI_MODE_SOURCE 0x0001 #define FAPI_MODE_SINK 0x0002 diff --git a/drivers/net/wireless/scsc/mlme.c b/drivers/net/wireless/scsc/mlme.c index d38507b3dc71..fc23b078969a 100755 --- a/drivers/net/wireless/scsc/mlme.c +++ b/drivers/net/wireless/scsc/mlme.c @@ -2169,6 +2169,9 @@ int slsi_mlme_connect(struct slsi_dev *sdev, struct net_device *dev, struct cfg8 case NL80211_AUTHTYPE_OPEN_SYSTEM: case NL80211_AUTHTYPE_SHARED_KEY: break; + case NL80211_AUTHTYPE_SAE: + auth_type = NL80211_AUTHTYPE_NETWORK_EAP; + break; case NL80211_AUTHTYPE_AUTOMATIC: /* In case of WEP, need to try both open and shared. * FW does this if auth is shared_key. So set it to shared. @@ -2889,6 +2892,33 @@ int slsi_mlme_powermgt(struct slsi_dev *sdev, struct net_device *dev, u16 power_ return slsi_mlme_powermgt_unlocked(sdev, dev, power_mode); } +int slsi_mlme_synchronised_response(struct slsi_dev *sdev, struct net_device *dev, + struct cfg80211_external_auth_params *params) +{ + struct netdev_vif *ndev_vif = netdev_priv(dev); + struct sk_buff *req; + struct sk_buff *cfm; + if (ndev_vif->activated) { + SLSI_NET_DBG3(dev, SLSI_MLME, "MLME_SPARE_SIGNAL_1_RES\n"); + + req = fapi_alloc(mlme_spare_signal_1_res, MLME_SPARE_SIGNAL_1_RES, ndev_vif->ifnum, 0); + if (!req) + return -ENOMEM; + + fapi_set_low16_u32(req, u.mlme_spare_signal_1_res.spare_1, params->status); + fapi_set_high16_u32(req, u.mlme_spare_signal_1_res.spare_1, *(u16 *)(¶ms->bssid[0])); + fapi_set_u32(req, u.mlme_spare_signal_1_res.spare_2, *(u32 *)(¶ms->bssid[2])); + + SLSI_NET_DBG2(dev, SLSI_MLME, "mlme_synchronised_response(vif:%d) status:%d\n", + ndev_vif->ifnum, params->status); + cfm = slsi_mlme_req_no_cfm(sdev, dev, req); + if (cfm) + SLSI_NET_ERR(dev, "Received cfm for MLME_SPARE_SIGNAL_1_RES\n"); + } else + SLSI_NET_DBG1(dev, SLSI_MLME, "vif is not active"); + + return 0; +} int slsi_mlme_register_action_frame(struct slsi_dev *sdev, struct net_device *dev, u32 af_bitmap_active, u32 af_bitmap_suspended) { struct netdev_vif *ndev_vif = netdev_priv(dev); diff --git a/drivers/net/wireless/scsc/mlme.h b/drivers/net/wireless/scsc/mlme.h index dd9e6ed8c15b..230d1602dc85 100755 --- a/drivers/net/wireless/scsc/mlme.h +++ b/drivers/net/wireless/scsc/mlme.h @@ -212,6 +212,8 @@ int slsi_mlme_connect_scan(struct slsi_dev *sdev, struct net_device *dev, int slsi_mlme_powermgt(struct slsi_dev *sdev, struct net_device *dev, u16 ps_mode); int slsi_mlme_powermgt_unlocked(struct slsi_dev *sdev, struct net_device *dev, u16 ps_mode); int slsi_mlme_register_action_frame(struct slsi_dev *sdev, struct net_device *dev, u32 af_bitmap_active, u32 af_bitmap_suspended); +int slsi_mlme_synchronised_response(struct slsi_dev *sdev, struct net_device *dev, + struct cfg80211_external_auth_params *params); int slsi_mlme_channel_switch(struct slsi_dev *sdev, struct net_device *dev, u16 center_freq, u16 chan_info); int slsi_mlme_add_info_elements(struct slsi_dev *sdev, struct net_device *dev, u16 purpose, const u8 *ies, const u16 ies_len); int slsi_mlme_send_frame_mgmt(struct slsi_dev *sdev, struct net_device *dev, const u8 *frame, int frame_len, u16 data_desc, u16 msg_type, u16 host_tag, u16 freq, u32 dwell_time, u32 period); diff --git a/drivers/net/wireless/scsc/rx.c b/drivers/net/wireless/scsc/rx.c index f8a24d3069dc..aacfe0a32091 100755 --- a/drivers/net/wireless/scsc/rx.c +++ b/drivers/net/wireless/scsc/rx.c @@ -1588,6 +1588,32 @@ void slsi_rx_buffered_frames(struct slsi_dev *sdev, struct net_device *dev, stru } } +void slsi_rx_synchronised_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) +{ + struct netdev_vif *ndev_vif = netdev_priv(dev); + const u8 *connecting_ssid = NULL; + struct cfg80211_external_auth_params auth_request; + int r; + + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); + SLSI_NET_DBG1(dev, SLSI_MLME, "Received slsi_rx_synchronised_ind\n"); + if (ndev_vif->sta.sta_bss->ies->len) + connecting_ssid = cfg80211_find_ie(WLAN_EID_SSID, ndev_vif->sta.sta_bss->ies->data, + ndev_vif->sta.sta_bss->ies->len); + + auth_request.action = NL80211_EXTERNAL_AUTH_START; + memcpy(auth_request.bssid, ndev_vif->sta.sta_bss->bssid, ETH_ALEN); + if (connecting_ssid && (connecting_ssid[1] > 0)) { + memcpy(auth_request.ssid.ssid, &connecting_ssid[2], connecting_ssid[1]); + auth_request.ssid.ssid_len = connecting_ssid[1]; + } + auth_request.key_mgmt_suite = ndev_vif->sta.crypto.akm_suites[0]; + r = cfg80211_external_auth_request(dev, &auth_request, GFP_KERNEL); + if (r) + SLSI_NET_DBG1(dev, SLSI_MLME, "cfg80211_external_auth_request failed"); + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); +} + void slsi_rx_connected_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) { struct netdev_vif *ndev_vif = netdev_priv(dev); @@ -1817,6 +1843,28 @@ void slsi_rx_connect_ind(struct slsi_dev *sdev, struct net_device *dev, struct s scsc_log_collector_schedule_collection(SCSC_LOG_HOST_WLAN, SCSC_LOG_HOST_WLAN_REASON_CONNECT_ERR); #endif status = fw_result_code; +#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG + if (ndev_vif->sta.crypto.wpa_versions == 3) { + const u8 *connecting_ssid = NULL; + int r; + struct cfg80211_external_auth_params auth_request; + + if (ndev_vif->sta.sta_bss->ies->len) + connecting_ssid = cfg80211_find_ie(WLAN_EID_SSID, ndev_vif->sta.sta_bss->ies->data, + ndev_vif->sta.sta_bss->ies->len); + + auth_request.action = NL80211_EXTERNAL_AUTH_ABORT; + memcpy(auth_request.bssid, ndev_vif->sta.sta_bss->bssid, ETH_ALEN); + if (connecting_ssid && (connecting_ssid[1] > 0)) { + memcpy(auth_request.ssid.ssid, &connecting_ssid[2], connecting_ssid[1]); + auth_request.ssid.ssid_len = connecting_ssid[1]; + } + auth_request.key_mgmt_suite = ndev_vif->sta.crypto.akm_suites[0]; + r = cfg80211_external_auth_request(dev, &auth_request, GFP_KERNEL); + if (r) + SLSI_NET_DBG1(dev, SLSI_MLME, "cfg80211_external_auth_request Abort failed"); + } +#endif } else { SLSI_INFO(sdev, "Received Association Response\n"); if (!peer || !peer->assoc_ie) { @@ -2314,9 +2362,12 @@ void slsi_rx_received_frame_ind(struct slsi_dev *sdev, struct net_device *dev, s if (!mgmt_len) goto exit; mgmt = fapi_get_mgmt(skb); + if (ieee80211_is_auth(mgmt->frame_control)) { + cfg80211_rx_mgmt(&ndev_vif->wdev, frequency, 0, (const u8 *)mgmt, mgmt_len, GFP_ATOMIC); + goto exit; + } if (WARN_ON(!(ieee80211_is_action(mgmt->frame_control)))) goto exit; - if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { #ifdef CONFIG_SCSC_WLAN_WES_NCHO if (slsi_is_wes_action_frame(mgmt)) { diff --git a/drivers/net/wireless/scsc/sap_mlme.c b/drivers/net/wireless/scsc/sap_mlme.c index 2610eb0f3fac..35936de57e16 100755 --- a/drivers/net/wireless/scsc/sap_mlme.c +++ b/drivers/net/wireless/scsc/sap_mlme.c @@ -191,6 +191,10 @@ static int slsi_rx_netdev_mlme(struct slsi_dev *sdev, struct net_device *dev, st slsi_kfree_skb(skb); break; #endif + case MLME_SPARE_SIGNAL_1_IND: + slsi_rx_synchronised_ind(sdev, dev, skb); + slsi_kfree_skb(skb); + break; default: slsi_kfree_skb(skb); SLSI_NET_ERR(dev, "Unhandled Ind: 0x%.4x\n", id); diff --git a/drivers/net/wireless/scsc/sap_mlme.h b/drivers/net/wireless/scsc/sap_mlme.h index e30887e7f31d..29e8efa71a03 100755 --- a/drivers/net/wireless/scsc/sap_mlme.h +++ b/drivers/net/wireless/scsc/sap_mlme.h @@ -15,6 +15,7 @@ int sap_mlme_deinit(void); void slsi_rx_scan_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); void slsi_rx_scan_done_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); void slsi_rx_channel_switched_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); +void slsi_rx_synchronised_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); void slsi_rx_connect_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); void slsi_rx_connected_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); void slsi_rx_received_frame_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ea0ed58db97e..7c57ce16a9bd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1897,11 +1897,18 @@ struct cfg80211_auth_request { * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n) * @ASSOC_REQ_DISABLE_VHT: Disable VHT * @ASSOC_REQ_USE_RRM: Declare RRM capability in this association + * @CONNECT_REQ_EXTERNAL_AUTH_SUPPORT: User space indicates external + * authentication capability. Drivers can offload authentication to + * userspace if this flag is set. Only applicable for cfg80211_connect() + * request (connect callback). */ enum cfg80211_assoc_req_flags { - ASSOC_REQ_DISABLE_HT = BIT(0), - ASSOC_REQ_DISABLE_VHT = BIT(1), - ASSOC_REQ_USE_RRM = BIT(2), + ASSOC_REQ_DISABLE_HT = BIT(0), + ASSOC_REQ_DISABLE_VHT = BIT(1), + ASSOC_REQ_USE_RRM = BIT(2), +#ifdef CONFIG_CFG80211_SLSI_SAE + CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3), +#endif }; /** @@ -2586,6 +2593,34 @@ struct cfg80211_pmk_conf { const u8 *pmk; const u8 *pmk_r0_name; }; +#ifdef CONFIG_CFG80211_SLSI_SAE +/** + * struct cfg80211_external_auth_params - Trigger External authentication. + * + * Commonly used across the external auth request and event interfaces. + * + * @action: action type / trigger for external authentication. Only significant + * for the authentication request event interface (driver to user space). + * @bssid: BSSID of the peer with which the authentication has + * to happen. Used by both the authentication request event and + * authentication response command interface. + * @ssid: SSID of the AP. Used by both the authentication request event and + * authentication response command interface. + * @key_mgmt_suite: AKM suite of the respective authentication. Used by the + * authentication request event interface. + * @status: status code, %WLAN_STATUS_SUCCESS for successful authentication, + * use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space cannot give you + * the real status code for failures. Used only for the authentication + * response command interface (user space to driver). + */ +struct cfg80211_external_auth_params { + enum nl80211_external_auth_action action; + u8 bssid[ETH_ALEN] __aligned(2); + struct cfg80211_ssid ssid; + unsigned int key_mgmt_suite; + u16 status; +}; +#endif /** * struct cfg80211_ops - backend description for wireless configuration @@ -2910,6 +2945,9 @@ struct cfg80211_pmk_conf { * (invoked with the wireless_dev mutex held) * @del_pmk: delete the previously configured PMK for the given authenticator. * (invoked with the wireless_dev mutex held) + * + * @external_auth: indicates result of offloaded authentication processing from + * user space */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -3203,6 +3241,10 @@ struct cfg80211_ops { const struct cfg80211_pmk_conf *conf); int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev, const u8 *aa); +#ifdef CONFIG_CFG80211_SLSI_SAE + int (*external_auth)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_external_auth_params *params); +#endif }; /* @@ -6188,6 +6230,19 @@ void cfg80211_nan_func_terminated(struct wireless_dev *wdev, /* ethtool helper */ void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info); +#ifdef CONFIG_CFG80211_SLSI_SAE +/** + * cfg80211_external_auth_request - userspace request for authentication + * @netdev: network device + * @params: External authentication parameters + * @gfp: allocation flags + * Returns: 0 on success, < 0 on error + */ +int cfg80211_external_auth_request(struct net_device *netdev, + struct cfg80211_external_auth_params *params, + gfp_t gfp); +#endif + /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f41ea5af22ee..3b456638071f 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -983,6 +983,27 @@ * configured PMK for the authenticator address identified by * &NL80211_ATTR_MAC. * + * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host + * drivers that do not define separate commands for authentication and + * association, but rely on user space for the authentication to happen. + * This interface acts both as the event request (driver to user space) + * to trigger the authentication and command response (userspace to + * driver) to indicate the authentication status. + * + * User space uses the %NL80211_CMD_CONNECT command to the host driver to + * trigger a connection. The host driver selects a BSS and further uses + * this interface to offload only the authentication part to the user + * space. Authentication frames are passed between the driver and user + * space through the %NL80211_CMD_FRAME interface. Host driver proceeds + * further with the association after getting successful authentication + * status. User space indicates the authentication status through + * %NL80211_ATTR_STATUS_CODE attribute in %NL80211_CMD_EXTERNAL_AUTH + * command interface. + * + * Host driver reports this status on an authentication failure to the + * user space through the connect result as the user space would have + * initiated the connection through the connect request. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1184,7 +1205,9 @@ enum nl80211_commands { NL80211_CMD_SET_PMK, NL80211_CMD_DEL_PMK, - +#ifdef CONFIG_CFG80211_SLSI_SAE + NL80211_CMD_EXTERNAL_AUTH, +#endif /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -2139,6 +2162,16 @@ enum nl80211_commands { * the driver or is not needed (because roaming used the Fast Transition * protocol). * + * @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external + * authentication operation (u32 attribute with an + * &enum nl80211_external_auth_action value). This is used with the + * &NL80211_CMD_EXTERNAL_AUTH request event. + * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user + * space supports external authentication. This attribute shall be used + * only with %NL80211_CMD_CONNECT request. The driver may offload + * authentication processing to user space if this capability is indicated + * in NL80211_CMD_CONNECT requests from the user space. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2564,6 +2597,10 @@ enum nl80211_attrs { NL80211_ATTR_WANT_1X_4WAY_HS, NL80211_ATTR_PMKR0_NAME, NL80211_ATTR_PORT_AUTHORIZED, +#ifdef CONFIG_CFG80211_SLSI_SAE + NL80211_ATTR_EXTERNAL_AUTH_ACTION, + NL80211_ATTR_EXTERNAL_AUTH_SUPPORT, +#endif /* add attributes here, update the policy in nl80211.c */ @@ -5418,5 +5455,16 @@ enum nl80211_nan_match_attributes { NUM_NL80211_NAN_MATCH_ATTR, NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1 }; - +#ifdef CONFIG_CFG80211_SLSI_SAE +/** + * nl80211_external_auth_action - Action to perform with external + * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION. + * @NL80211_EXTERNAL_AUTH_START: Start the authentication. + * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication. + */ +enum nl80211_external_auth_action { + NL80211_EXTERNAL_AUTH_START, + NL80211_EXTERNAL_AUTH_ABORT, +}; +#endif #endif /* __LINUX_NL80211_H */ diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 01ff97b5d277..f168e98eb1ce 100755 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -130,6 +130,17 @@ config CFG80211_DEFAULT_PS applications instead -- they need to register their network latency requirement, see Documentation/power/pm_qos_interface.txt. +config CFG80211_SLSI_SAE + bool "Enable SAE in Kernel" + depends on CFG80211 + default y + help + This option enables sae in kernel. + + This Option enables SAE in CFG. + This option needs to be enabled if the kernel version by default doesnt + support SAE. + config CFG80211_DEBUGFS bool "cfg80211 DebugFS entries" depends on CFG80211 diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 46e9812d13c0..108db3b84bd5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -421,6 +421,9 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 }, [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN }, [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG }, +#ifdef CONFIG_CFG80211_SLSI_SAE + [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG }, +#endif }; /* policy for the key attributes */ @@ -3864,8 +3867,8 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev, return false; return true; case NL80211_CMD_CONNECT: - /* SAE not supported yet */ - if (auth_type == NL80211_AUTHTYPE_SAE) + if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) && + auth_type == NL80211_AUTHTYPE_SAE) return false; /* FILS with SK PFS or PK not supported yet */ if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS || @@ -9051,7 +9054,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) kzfree(connkeys); return -EINVAL; } - +#ifdef CONFIG_CFG80211_SLSI_SAE + if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) + connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT; +#endif wdev_lock(dev->ieee80211_ptr); err = cfg80211_connect(rdev, dev, &connect, connkeys, @@ -12376,6 +12382,43 @@ static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info) return ret; } +#ifdef CONFIG_CFG80211_SLSI_SAE +static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct cfg80211_external_auth_params params; + + if (!rdev->ops->external_auth) + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_SSID]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_BSSID]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_STATUS_CODE]) + return -EINVAL; + + memset(¶ms, 0, sizeof(params)); + + params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); + if (params.ssid.ssid_len == 0 || + params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; + memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]), + params.ssid.ssid_len); + + memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]), + ETH_ALEN); + + params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); + + return rdev_external_auth(rdev, dev, ¶ms); +} +#endif + #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -13265,6 +13308,16 @@ static const struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, +#ifdef CONFIG_CFG80211_SLSI_SAE + { + .cmd = NL80211_CMD_EXTERNAL_AUTH, + .doit = nl80211_external_auth, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, +#endif }; @@ -13591,7 +13644,6 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, { struct sk_buff *msg; void *hdr; - msg = nlmsg_new(100 + len, gfp); if (!msg) return; @@ -15248,6 +15300,48 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev) nlmsg_free(msg); } +#ifdef CONFIG_CFG80211_SLSI_SAE +int cfg80211_external_auth_request(struct net_device *dev, + struct cfg80211_external_auth_params *params, + gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct sk_buff *msg; + void *hdr; + + if (!wdev->conn_owner_nlportid) + return -EINVAL; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return -ENOMEM; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH); + if (!hdr) + goto nla_put_failure; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) || + nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION, + params->action) || + nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) || + nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len, + params->ssid.ssid)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, + wdev->conn_owner_nlportid); + return 0; + + nla_put_failure: + nlmsg_free(msg); + return -ENOBUFS; +} +EXPORT_SYMBOL(cfg80211_external_auth_request); +#endif /* initialisation/exit functions */ int __init nl80211_init(void) diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 0c06240d25af..0081dc3ef343 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -1190,4 +1190,21 @@ static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev, trace_rdev_return_int(&rdev->wiphy, ret); return ret; } + +#ifdef CONFIG_CFG80211_SLSI_SAE +static inline int +rdev_external_auth(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_external_auth_params *params) +{ + int ret = -EOPNOTSUPP; + + trace_rdev_external_auth(&rdev->wiphy, dev, params); + if (rdev->ops->external_auth) + ret = rdev->ops->external_auth(&rdev->wiphy, dev, params); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; +} +#endif + #endif /* __CFG80211_RDEV_OPS */ diff --git a/net/wireless/trace.h b/net/wireless/trace.h index f3353fe5b35b..0580f278d6d7 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2319,6 +2319,31 @@ TRACE_EVENT(rdev_del_pmk, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa)) ); +#ifdef CONFIG_CFG80211_SLSI_SAE +TRACE_EVENT(rdev_external_auth, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_external_auth_params *params), + TP_ARGS(wiphy, netdev, params), + TP_STRUCT__entry(WIPHY_ENTRY + NETDEV_ENTRY + MAC_ENTRY(bssid) + __array(u8, ssid, IEEE80211_MAX_SSID_LEN + 1) + __field(u16, status) + ), + TP_fast_assign(WIPHY_ASSIGN; + NETDEV_ASSIGN; + MAC_ASSIGN(bssid, params->bssid); + memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); + memcpy(__entry->ssid, params->ssid.ssid, + params->ssid.ssid_len); + __entry->status = params->status; + ), + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT + ", ssid: %s, status: %u", WIPHY_PR_ARG, NETDEV_PR_ARG, + __entry->bssid, __entry->ssid, __entry->status) +); +#endif + /************************************************************* * cfg80211 exported functions traces * *************************************************************/