From dd74ddd0dff67c59e416bee9f764b27044a2ade5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 17:43:11 +0200 Subject: [PATCH] nl80211: Handle AKM suite selectors for AP configuration Previously only couple of AKM suite selectors were converted into NL80211_ATTR_AKM_SUITES. Add rest of the AKM suites here. However, since the current kernel interface has a very small limit (NL80211_MAX_NR_AKM_SUITES = 2), add the attribute only when no more than that limit entries are included. cfg80211 would reject the command with any more entries listed. This needs to be extended in cfg80211/nl80211 in a backwards compatible manner, so this seems to be the best that can be done for now in user space. Many drivers do not use this attribute, so must not reject the configuration completely when larger number of AKM suites is configured. Such cases may not work properly with drivers that depend on NL80211_ATTR_AKM_SUITES value. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 53 ++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 6c26e8ba8..d55d8e8f5 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2942,6 +2942,40 @@ static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[], } +static int wpa_key_mgmt_to_suites(unsigned int key_mgmt_suites, u32 suites[], + int max_suites) +{ + int num_suites = 0; + +#define __AKM(a, b) \ + if (num_suites < max_suites && \ + (key_mgmt_suites & (WPA_KEY_MGMT_ ## a))) \ + suites[num_suites++] = (RSN_AUTH_KEY_MGMT_ ## b) + __AKM(IEEE8021X, UNSPEC_802_1X); + __AKM(PSK, PSK_OVER_802_1X); + __AKM(FT_IEEE8021X, FT_802_1X); + __AKM(FT_PSK, FT_PSK); + __AKM(IEEE8021X_SHA256, 802_1X_SHA256); + __AKM(PSK_SHA256, PSK_SHA256); + __AKM(SAE, SAE); + __AKM(FT_SAE, FT_SAE); + __AKM(CCKM, CCKM); + __AKM(OSEN, OSEN); + __AKM(IEEE8021X_SUITE_B, 802_1X_SUITE_B); + __AKM(IEEE8021X_SUITE_B_192, 802_1X_SUITE_B_192); + __AKM(FILS_SHA256, FILS_SHA256); + __AKM(FILS_SHA384, FILS_SHA384); + __AKM(FT_FILS_SHA256, FT_FILS_SHA256); + __AKM(FT_FILS_SHA384, FT_FILS_SHA384); + __AKM(OWE, OWE); + __AKM(DPP, DPP); + __AKM(FT_IEEE8021X_SHA384, FT_802_1X_SHA384); +#undef __AKM + + return num_suites; +} + + #ifdef CONFIG_DRIVER_NL80211_QCA static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv, const u8 *key, size_t key_len) @@ -4102,7 +4136,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, int ret = -ENOBUFS; int beacon_set; int num_suites; - u32 suites[10], suite; + u32 suites[20], suite; u32 ver; #ifdef CONFIG_MESH struct wpa_driver_mesh_bss_params mesh_params; @@ -4196,14 +4230,15 @@ static int wpa_driver_nl80211_set_ap(void *priv, wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x", params->key_mgmt_suites); - num_suites = 0; - if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X) - suites[num_suites++] = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; - if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK) - suites[num_suites++] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; - if (num_suites && - nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), - suites)) + num_suites = wpa_key_mgmt_to_suites(params->key_mgmt_suites, + suites, ARRAY_SIZE(suites)); + if (num_suites > NL80211_MAX_NR_AKM_SUITES) + wpa_printf(MSG_WARNING, + "nl80211: Not enough room for all AKM suites (num_suites=%d > NL80211_MAX_NR_AKM_SUITES)", + num_suites); + else if (num_suites && + nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), + suites)) goto fail; if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&