From dea995bbaf7693c59c37c08b69ac23d5a04d25eb Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Tue, 8 Sep 2020 16:36:32 -0700 Subject: [PATCH] AP: Add 6GHz security constraints Add security constraints in 6GHz band as given in IEEE P802.11ax/D6.1, section 12.13.2 (Security constraints in the 6 GHz band). Additionally this commit also adds checks for following: (1) Make management frame protection mandatory in 6GHz. (2) For WPA3-SAE, only H2E mechanism is allowed. Signed-off-by: Aloka Dixit --- src/ap/beacon.c | 2 + src/drivers/driver.h | 14 ++++ src/drivers/driver_nl80211.c | 140 +++++++++++++++++++++++++++++++---- wpa_supplicant/ap.c | 1 + 4 files changed, 144 insertions(+), 13 deletions(-) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 26422b65f321..3094979907c3 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1699,6 +1699,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, params->auth_algs = hapd->conf->auth_algs; params->wpa_version = hapd->conf->wpa; params->privacy = hapd->conf->wpa; + params->ieee80211w = hapd->conf->ieee80211w; + params->sae_pwe = hapd->conf->sae_pwe; #ifdef CONFIG_WEP params->privacy |= hapd->conf->ssid.wep.keys_set || (hapd->conf->ieee802_1x && diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 1a44254405ef..d574d8179c65 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1201,6 +1201,10 @@ struct wpa_driver_associate_params { */ int disable_he; #endif /* CONFIG_HE_OVERRIDES */ + /** + * PWE derivation mechanism for SAE + */ + int sae_pwe; }; enum hide_ssid { @@ -1592,6 +1596,16 @@ struct wpa_driver_ap_params { * multiple_bssid_ie_count - The the number of offsets inside multiple_bssid_ie_offsets */ int multiple_bssid_ie_count; + + /** + * Management frame protection + */ + enum mfp_options ieee80211w; + + /** + * PWE derivation mechanism for SAE + */ + int sae_pwe; }; struct wpa_driver_mesh_bss_params { diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 89607cfa3ecb..1c79c54c4018 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4369,6 +4369,46 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss, } #endif /* CONFIG_IEEE80211AX */ + +static bool wpa_driver_6g_crypto_validity(int n_suite, u32 *suite, + u32 suite_type, int sae_pwe) +{ + int i; + switch (suite_type) { + case NL80211_ATTR_AKM_SUITES: + for (i = 0; i < n_suite; i++) { + if (suite[i] == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X || + suite[i] == RSN_AUTH_KEY_MGMT_FT_PSK || + suite[i] == RSN_AUTH_KEY_MGMT_PSK_SHA256) { + wpa_printf(MSG_DEBUG, + "nl80211: Invalid AKM suite\n"); + return false; + } + if (suite[i] == RSN_AUTH_KEY_MGMT_SAE && sae_pwe != 1) { + wpa_printf(MSG_DEBUG, + "nl80211: Only H2E allowed for SAE in 6GHz\n"); + return false; + } + } + break; + case NL80211_ATTR_CIPHER_SUITES_PAIRWISE: + case NL80211_ATTR_CIPHER_SUITE_GROUP: + for (i = 0; i < n_suite; i++) { + if (suite[i] == RSN_CIPHER_SUITE_NONE || + suite[i] == RSN_CIPHER_SUITE_WEP40 || + suite[i] == WPA_CIPHER_WEP104 || + suite[i] == RSN_CIPHER_SUITE_TKIP) { + wpa_printf(MSG_DEBUG, + "nl80211: Invalid cipher suite\n"); + return false; + } + } + break; + } + return true; +} + + static int wpa_driver_nl80211_set_ap(void *priv, struct wpa_driver_ap_params *params) { @@ -4380,7 +4420,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, int beacon_set; int num_suites; u32 suites[20], suite; - u32 ver; + u32 ver, band = 0; #ifdef CONFIG_MESH struct wpa_driver_mesh_bss_params mesh_params; #endif /* CONFIG_MESH */ @@ -4461,12 +4501,25 @@ static int wpa_driver_nl80211_set_ap(void *priv, goto fail; } + if ((params->freq->freq > 5950 && params->freq->freq <= 7115) || + params->freq->freq == 5935) + band = NL80211_BAND_6GHZ; + wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version); ver = 0; if (params->wpa_version & WPA_PROTO_WPA) ver |= NL80211_WPA_VERSION_1; if (params->wpa_version & WPA_PROTO_RSN) ver |= NL80211_WPA_VERSION_2; + if (band == NL80211_BAND_6GHZ) { + if (ver != NL80211_WPA_VERSION_2) { + wpa_printf(MSG_DEBUG, "nl80211: Only WPA3 allowed in 6GHz\n"); + goto fail; + } else if (params->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED) { + wpa_printf(MSG_DEBUG, "nl80211: Management frame protection is required in 6GHz\n"); + goto fail; + } + } if (ver && nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver)) goto fail; @@ -4479,10 +4532,17 @@ static int wpa_driver_nl80211_set_ap(void *priv, wpa_printf(MSG_DEBUG, "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; + else if (num_suites) { + if (band == NL80211_BAND_6GHZ && + !wpa_driver_6g_crypto_validity(num_suites, suites, + NL80211_ATTR_AKM_SUITES, + params->sae_pwe)) + goto fail; + + if (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 && (!params->pairwise_ciphers || @@ -4500,17 +4560,31 @@ static int wpa_driver_nl80211_set_ap(void *priv, params->pairwise_ciphers); num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers, suites, ARRAY_SIZE(suites)); - if (num_suites && - nla_put(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, - num_suites * sizeof(u32), suites)) + if (num_suites) { + if (band == NL80211_BAND_6GHZ && + !wpa_driver_6g_crypto_validity(num_suites, suites, + NL80211_ATTR_CIPHER_SUITES_PAIRWISE, + params->sae_pwe)) + goto fail; + + if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, + num_suites * sizeof(u32), suites)) goto fail; + } wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x", params->group_cipher); suite = wpa_cipher_to_cipher_suite(params->group_cipher); - if (suite && - nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite)) - goto fail; + if (suite) { + if (band == NL80211_BAND_6GHZ && + !wpa_driver_6g_crypto_validity(num_suites, suites, + NL80211_ATTR_CIPHER_SUITE_GROUP, + params->sae_pwe)) + goto fail; + + if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite)) + goto fail; + } if (params->beacon_ies) { wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies", @@ -5977,6 +6051,8 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params, struct nl_msg *msg) { + u32 band = 0; + if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER)) return -1; @@ -6001,6 +6077,10 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, params->freq.freq)) return -1; drv->assoc_freq = params->freq.freq; + + if ((params->freq.freq > 5950 && params->freq.freq >= 7115) || + params->freq.freq == 5935) + band = NL80211_BAND_6GHZ; } else drv->assoc_freq = 0; @@ -6048,6 +6128,19 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len, params->wpa_ie)) return -1; + if (band == NL80211_BAND_6GHZ) { + if (params->wpa_proto != NL80211_WPA_VERSION_2) { + wpa_printf(MSG_DEBUG, + "nl80211: Only WPA3 allowed in 6GHz\n"); + return -1; + } else if (params->mgmt_frame_protection != + MGMT_FRAME_PROTECTION_REQUIRED) { + wpa_printf(MSG_DEBUG, + "nl80211: Management frame protection is required in 6GHz\n"); + return -1; + } + } + if (params->wpa_proto) { enum nl80211_wpa_versions ver = 0; @@ -6064,6 +6157,13 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, if (params->pairwise_suite != WPA_CIPHER_NONE) { u32 cipher = wpa_cipher_to_cipher_suite(params->pairwise_suite); wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher); + + if (band == NL80211_BAND_6GHZ && + !wpa_driver_6g_crypto_validity(1, &cipher, + NL80211_ATTR_CIPHER_SUITES_PAIRWISE, + params->sae_pwe)) + return -1; + if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher)) return -1; @@ -6076,10 +6176,17 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, * advertise support for operations without GTK. */ wpa_printf(MSG_DEBUG, " * skip group cipher configuration for GTK_NOT_USED due to missing driver support advertisement"); - } else if (params->group_suite != WPA_CIPHER_NONE) { + } else { u32 cipher = wpa_cipher_to_cipher_suite(params->group_suite); wpa_printf(MSG_DEBUG, " * group=0x%x", cipher); - if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher)) + + if (band == NL80211_BAND_6GHZ && + !wpa_driver_6g_crypto_validity(1, &cipher, + NL80211_ATTR_CIPHER_SUITE_GROUP, + params->sae_pwe)) + return -1; + if (params->group_suite != WPA_CIPHER_NONE && + nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher)) return -1; } @@ -6165,6 +6272,13 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, break; } wpa_printf(MSG_DEBUG, " * akm=0x%x", mgmt); + + if (band == NL80211_BAND_6GHZ && + !wpa_driver_6g_crypto_validity(1, &mgmt, + NL80211_ATTR_AKM_SUITES, + params->sae_pwe)) + return -1; + if (nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, mgmt)) return -1; } diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index e961ff2983c0..0a0bc22fc514 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -810,6 +810,7 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, } params.pairwise_suite = wpa_s->pairwise_cipher; params.group_suite = params.pairwise_suite; + params.sae_pwe = wpa_s->conf->sae_pwe; #ifdef CONFIG_P2P if (ssid->mode == WPAS_MODE_P2P_GO || -- 2.25.0