From: lihz <lihz@xxxxxxxxxxx> This patch adds key management offload feature. It needs to be advertised through NL80211_EXT_FEATURE_KEY_MGMT_OFFLOAD flag. Existing cfg80211_roamed API has been extended to report keys for roaming offload. Signed-off-by: Huazeng Li <lihz@xxxxxxxxxxx> Signed-off-by: Amitkumar Karwar <akarwar@xxxxxxxxxxx> --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 ++- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 3 ++- drivers/net/wireless/rndis_wlan.c | 3 ++- drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c | 2 +- drivers/staging/wlan-ng/cfg80211.c | 2 +- include/linux/ieee80211.h | 3 +++ include/net/cfg80211.h | 8 +++++-- include/uapi/linux/nl80211.h | 11 +++++++++ net/wireless/core.h | 8 ++++++- net/wireless/nl80211.c | 19 ++++++++++++++-- net/wireless/nl80211.h | 4 +++- net/wireless/sme.c | 26 +++++++++++++++++----- net/wireless/util.c | 4 +++- 13 files changed, 79 insertions(+), 17 deletions(-) mode change 100644 => 100755 net/wireless/nl80211.c diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index b7fe0af..9511f73 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -809,7 +809,8 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, } else if (vif->sme_state == SME_CONNECTED) { /* inform roam event to cfg80211 */ cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len, - assoc_resp_ie, assoc_resp_len, GFP_KERNEL); + assoc_resp_ie, assoc_resp_len, GFP_KERNEL, + NULL, NULL, NULL, 0); } } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 748eaa6..5934b77 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -5450,7 +5450,8 @@ done: kfree(buf); cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid, conn_info->req_ie, conn_info->req_ie_len, - conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); + conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL, + NULL, NULL, NULL, 0); brcmf_dbg(CONN, "Report roaming result\n"); set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 603c904..ad9535f 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2838,7 +2838,8 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) cfg80211_roamed(usbdev->net, get_current_channel(usbdev, NULL), bssid, req_ie, req_ie_len, - resp_ie, resp_ie_len, GFP_KERNEL); + resp_ie, resp_ie_len, GFP_KERNEL, + NULL, NULL, NULL, 0); } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) cfg80211_ibss_joined(usbdev->net, bssid, get_current_channel(usbdev, NULL), diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c index d0ba377..e74216a 100644 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c @@ -341,7 +341,7 @@ void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter) sizeof(struct ieee80211_hdr_3addr) + 6, pmlmepriv->assoc_rsp_len - sizeof(struct ieee80211_hdr_3addr) - 6, - GFP_ATOMIC); + GFP_ATOMIC, NULL, NULL, NULL, 0); } else { cfg80211_connect_result(padapter->pnetdev, cur_network->network.MacAddress, diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index f46dfe6..178d955 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -722,7 +722,7 @@ void prism2_disconnected(wlandevice_t *wlandev) void prism2_roamed(wlandevice_t *wlandev) { cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid, - NULL, 0, NULL, 0, GFP_KERNEL); + NULL, 0, NULL, 0, GFP_KERNEL, NULL, NULL, NULL, 0); } /* Structures for declaring wiphy interface */ diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index a80516f..8cf3535 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -2312,6 +2312,9 @@ enum ieee80211_sa_query_action { #define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D #define WLAN_CIPHER_SUITE_SMS4 0x00147201 +#define WLAN_CIPHER_SUITE_PMK 0x00147202 +#define WLAN_CIPHER_SUITE_PMK_R0 0x00147203 +#define WLAN_CIPHER_SUITE_PMK_R0_NAME 0x00147204 /* AKM suite selectors */ #define WLAN_AKM_SUITE_8021X 0x000FAC01 diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ed37304..817df07 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4865,7 +4865,9 @@ void cfg80211_roamed(struct net_device *dev, struct ieee80211_channel *channel, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); + const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp, + const u8 *key_replay_ctr, const u8 *ptk_kck, + const u8 *ptk_kek, const u8 authorized); /** * cfg80211_roamed_bss - notify cfg80211 of roaming @@ -4891,7 +4893,9 @@ void cfg80211_roamed(struct net_device *dev, */ void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); + const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp, + const u8 *key_replay_ctr, const u8 *ptk_kck, + const u8 *ptk_kek, const u8 authorized); /** * cfg80211_disconnected - notify cfg80211 that connection was dropped diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index ec10d1b..c56df53 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1873,6 +1873,9 @@ enum nl80211_commands { * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is * used to pull the stored data for mesh peer in power save state. * + * @NL80211_ATTR_AUTHORIZED: flag attribute, if set indicates that the + * connection is authorized. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2267,6 +2270,8 @@ enum nl80211_attrs { NL80211_ATTR_MESH_PEER_AID, + NL80211_ATTR_AUTHORIZED, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -3687,6 +3692,9 @@ enum nl80211_key_attributes { NL80211_KEY_DEFAULT_MGMT, NL80211_KEY_TYPE, NL80211_KEY_DEFAULT_TYPES, + NL80211_KEY_REPLAY_CTR, + NL80211_KEY_KCK, + NL80211_KEY_KEK, /* keep last */ __NL80211_KEY_AFTER_LAST, @@ -4563,6 +4571,8 @@ enum nl80211_feature_flags { * configuration (AP/mesh) with HT rates. * @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate * configuration (AP/mesh) with VHT rates. + * @NL80211_EXT_FEATURE_KEY_MGMT_OFFLOAD: This driver supports key management + * auth offload. * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. @@ -4577,6 +4587,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, NL80211_EXT_FEATURE_BEACON_RATE_HT, NL80211_EXT_FEATURE_BEACON_RATE_VHT, + NL80211_EXT_FEATURE_KEY_MGMT_OFFLOAD, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, diff --git a/net/wireless/core.h b/net/wireless/core.h index 5555e3c..bd9914b2 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -231,8 +231,12 @@ struct cfg80211_event { struct { const u8 *req_ie; const u8 *resp_ie; + const u8 *key_replay_ctr; + const u8 *key_kck; + const u8 *key_kek; size_t req_ie_len; size_t resp_ie_len; + u8 authorized; struct cfg80211_bss *bss; } rm; struct { @@ -396,7 +400,9 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, void __cfg80211_roamed(struct wireless_dev *wdev, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len); + const u8 *resp_ie, size_t resp_ie_len, + const u8 authorized, const u8 *key_replay_ctr, + const u8 *key_kck, const u8 *key_kek); int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c old mode 100644 new mode 100755 index b8441e6..06754f9 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -928,7 +928,9 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: - if (!wdev->current_bss) + if (!wdev->current_bss && + !wiphy_ext_feature_isset(wdev->wiphy, + NL80211_EXT_FEATURE_KEY_MGMT_OFFLOAD)) return -ENOLINK; break; case NL80211_IFTYPE_UNSPECIFIED: @@ -12481,7 +12483,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, void nl80211_send_roamed(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) + const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp, + const u8 authorized, const u8 *key_replay_ctr, + const u8 *key_kck, const u8 *key_kek) { struct sk_buff *msg; void *hdr; @@ -12505,6 +12509,17 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev, nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie))) goto nla_put_failure; + if (wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_KEY_MGMT_OFFLOAD) && + (nla_put_u8(msg, NL80211_ATTR_AUTHORIZED, authorized) || + (key_replay_ctr && nla_put(msg, NL80211_KEY_REPLAY_CTR, + NL80211_REPLAY_CTR_LEN, key_replay_ctr)) || + (key_kck && + nla_put(msg, NL80211_KEY_KCK, NL80211_KCK_LEN, key_kck)) || + (key_kek && + nla_put(msg, NL80211_KEY_KEK, NL80211_KEK_LEN, key_kek)))) + goto nla_put_failure; + genlmsg_end(msg, hdr); genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 7e3821d..5d2fe3a 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -62,7 +62,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, void nl80211_send_roamed(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); + const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp, + const u8 authorized, const u8 *key_replay_ctr, + const u8 *key_kck, const u8 *key_kek); void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, struct net_device *netdev, u16 reason, const u8 *ie, size_t ie_len, bool from_ap); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index c08a3b5..a6ddbb4 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -807,7 +807,9 @@ EXPORT_SYMBOL(cfg80211_connect_bss); void __cfg80211_roamed(struct wireless_dev *wdev, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len) + const u8 *resp_ie, size_t resp_ie_len, + const u8 authorized, const u8 *key_replay_ctr, + const u8 *key_kck, const u8 *key_kek) { #ifdef CONFIG_CFG80211_WEXT union iwreq_data wrqu; @@ -831,7 +833,8 @@ void __cfg80211_roamed(struct wireless_dev *wdev, nl80211_send_roamed(wiphy_to_rdev(wdev->wiphy), wdev->netdev, bss->bssid, req_ie, req_ie_len, resp_ie, resp_ie_len, - GFP_KERNEL); + GFP_KERNEL, authorized, key_replay_ctr, + key_kck, key_kek); #ifdef CONFIG_CFG80211_WEXT if (req_ie) { @@ -865,7 +868,9 @@ void cfg80211_roamed(struct net_device *dev, struct ieee80211_channel *channel, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) + const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp, + const u8 *key_replay_ctr, const u8 *ptk_kck, + const u8 *ptk_kek, const u8 authorized) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_bss *bss; @@ -877,7 +882,8 @@ void cfg80211_roamed(struct net_device *dev, return; cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie, - resp_ie_len, gfp); + resp_ie_len, gfp, key_replay_ctr, ptk_kck, + ptk_kek, authorized); } EXPORT_SYMBOL(cfg80211_roamed); @@ -885,7 +891,9 @@ EXPORT_SYMBOL(cfg80211_roamed); void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, - size_t resp_ie_len, gfp_t gfp) + size_t resp_ie_len, gfp_t gfp, + const u8 *key_replay_ctr, const u8 *ptk_kck, + const u8 *ptk_kek, const u8 authorized) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); @@ -908,6 +916,14 @@ void cfg80211_roamed_bss(struct net_device *dev, ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; ev->rm.resp_ie_len = resp_ie_len; memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len); + ev->rm.key_replay_ctr = ((u8 *)ev) + sizeof(*ev) + resp_ie_len; + memcpy((void *)ev->rm.key_replay_ctr, key_replay_ctr, + NL80211_REPLAY_CTR_LEN); + ev->rm.key_kck = ((u8 *)ev) + sizeof(*ev) + NL80211_REPLAY_CTR_LEN; + memcpy((void *)ev->rm.key_kck, ptk_kck, NL80211_KCK_LEN); + ev->rm.key_kek = ((u8 *)ev) + sizeof(*ev) + NL80211_KCK_LEN; + memcpy((void *)ev->rm.key_kek, ptk_kek, NL80211_KEK_LEN); + ev->rm.authorized = authorized; ev->rm.bss = bss; spin_lock_irqsave(&wdev->event_lock, flags); diff --git a/net/wireless/util.c b/net/wireless/util.c index 9e6e2aa..30c4628 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -960,7 +960,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) case EVENT_ROAMED: __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, ev->rm.req_ie_len, ev->rm.resp_ie, - ev->rm.resp_ie_len); + ev->rm.resp_ie_len, ev->rm.authorized, + ev->rm.key_replay_ctr, ev->rm.key_kck, + ev->rm.key_kek); break; case EVENT_DISCONNECTED: __cfg80211_disconnected(wdev->netdev, -- 1.9.1