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 <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2020-02-17 17:43:11 +02:00 committed by Jouni Malinen
parent 139f6deaff
commit dd74ddd0df

View file

@ -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 #ifdef CONFIG_DRIVER_NL80211_QCA
static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv, static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
const u8 *key, size_t key_len) const u8 *key, size_t key_len)
@ -4102,7 +4136,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
int ret = -ENOBUFS; int ret = -ENOBUFS;
int beacon_set; int beacon_set;
int num_suites; int num_suites;
u32 suites[10], suite; u32 suites[20], suite;
u32 ver; u32 ver;
#ifdef CONFIG_MESH #ifdef CONFIG_MESH
struct wpa_driver_mesh_bss_params mesh_params; struct wpa_driver_mesh_bss_params mesh_params;
@ -4196,12 +4230,13 @@ static int wpa_driver_nl80211_set_ap(void *priv,
wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x", wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x",
params->key_mgmt_suites); params->key_mgmt_suites);
num_suites = 0; num_suites = wpa_key_mgmt_to_suites(params->key_mgmt_suites,
if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X) suites, ARRAY_SIZE(suites));
suites[num_suites++] = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; if (num_suites > NL80211_MAX_NR_AKM_SUITES)
if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK) wpa_printf(MSG_WARNING,
suites[num_suites++] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; "nl80211: Not enough room for all AKM suites (num_suites=%d > NL80211_MAX_NR_AKM_SUITES)",
if (num_suites && num_suites);
else if (num_suites &&
nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32),
suites)) suites))
goto fail; goto fail;