return 1;
} else if (os_strcmp(buf, "rnr") == 0) {
bss->rnr = atoi(pos);
+ } else if (os_strcmp(buf, "ssid_protection") == 0) {
+ int val = atoi(pos);
+
+ if (val < 0 || val > 1)
+ return 1;
+ bss->ssid_protection = val;
#ifdef CONFIG_IEEE80211BE
} else if (os_strcmp(buf, "ieee80211be") == 0) {
conf->ieee80211be = atoi(pos);
# (default: 1 = activated)
#pasn_noauth=1
+# SSID protection in 4-way handshake
+# The IEEE 802.11i-2004 RSN design did not provide means for protecting the
+# SSID in the general case. IEEE P802.11REVme/D6.0 added support for this in
+# 4-way handshake. This capability allows a STA to confirm that the AP has the
+# same understanding on which SSID is being used for an association in a
+# protected manner in cases where both the AP and the STA has this capability.
+# This can be used to mitigate CVE-2023-52424 (a.k.a. the SSID Confusion
+# Attack).
+#
+# Ideally, this capability would be enabled by default on the AP, but since this
+# is new functionality with limited testing, the default is to disable this for
+# now and require explicitly configuration to enable. The default behavior is
+# like to change once this capability has received more testing.
+#
+# 0 = SSID protection in 4-way handshake disabled (default)
+# 1 = SSID protection in 4-way handshake enabled
+#
+#ssid_protection=0
+
##### IEEE 802.11r configuration ##############################################
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
char *config_id;
bool xrates_supported;
+ bool ssid_protection;
+
#ifdef CONFIG_IEEE80211BE
/* The AP is part of an AP MLD */
u8 mld_ap;
"association");
return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
}
+
+ wpa_auth_set_ssid_protection(
+ sta->wpa_sm,
+ hapd->conf->ssid_protection &&
+ ieee802_11_rsnx_capab_len(
+ elems->rsnxe, elems->rsnxe_len,
+ WLAN_RSNX_CAPAB_SSID_PROTECTION));
#ifdef CONFIG_HS20
} else if (hapd->conf->osen) {
if (!elems->osen) {
{
u8 *pos = eid;
bool sae_pk = false;
- u16 capab = 0;
+ u32 capab = 0, tmp;
size_t flen;
if (!(hapd->conf->wpa & WPA_PROTO_RSN))
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
if (hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP)
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
+ if (hapd->conf->ssid_protection)
+ capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
- flen = (capab & 0xff00) ? 2 : 1;
- if (len < 2 + flen || !capab)
+ if (!capab)
+ return eid; /* no supported extended RSN capabilities */
+ tmp = capab;
+ flen = 0;
+ while (tmp) {
+ flen++;
+ tmp >>= 8;
+ }
+
+ if (len < 2 + flen)
return eid; /* no supported extended RSN capabilities */
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
*pos++ = WLAN_EID_RSNX;
*pos++ = flen;
- *pos++ = capab & 0x00ff;
- capab >>= 8;
- if (capab)
- *pos++ = capab;
+ while (capab) {
+ *pos++ = capab & 0xff;
+ capab >>= 8;
+ }
return pos;
}
kde_len += wpa_auth_ml_kdes_len(sm);
+ if (sm->ssid_protection)
+ kde_len += 2 + conf->ssid_len;
+
#ifdef CONFIG_TESTING_OPTIONS
if (conf->eapol_m3_elements)
kde_len += wpabuf_len(conf->eapol_m3_elements);
pos = wpa_auth_ml_kdes(sm, pos);
+ if (sm->ssid_protection) {
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = conf->ssid_len;
+ os_memcpy(pos, conf->ssid, conf->ssid_len);
+ pos += conf->ssid_len;
+ }
+
#ifdef CONFIG_TESTING_OPTIONS
if (conf->eapol_m3_elements) {
os_memcpy(pos, wpabuf_head(conf->eapol_m3_elements),
#endif /* CONFIG_DPP2 */
+void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val)
+{
+ if (sm)
+ sm->ssid_protection = val;
+}
+
+
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
u8 val)
{
#ifdef CONFIG_OCV
int ocv; /* Operating Channel Validation */
#endif /* CONFIG_OCV */
-#ifdef CONFIG_IEEE80211R_AP
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
+#ifdef CONFIG_IEEE80211R_AP
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
u8 r0_key_holder[FT_R0KH_ID_MAX_LEN];
size_t r0_key_holder_len;
int link_id;
struct wpa_authenticator *first_link_auth;
#endif /* CONFIG_IEEE80211BE */
+
+ bool ssid_protection;
};
typedef enum {
u8 *fd_rsn_info);
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
+void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val);
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
u8 val);
wconf->beacon_prot = conf->beacon_prot;
wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
wconf->sae_require_mfp = conf->sae_require_mfp;
-#ifdef CONFIG_IEEE80211R_AP
+ wconf->ssid_protection = conf->ssid_protection;
wconf->ssid_len = conf->ssid.ssid_len;
if (wconf->ssid_len > SSID_MAX_LEN)
wconf->ssid_len = SSID_MAX_LEN;
os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
+#ifdef CONFIG_IEEE80211R_AP
os_memcpy(wconf->mobility_domain, conf->mobility_domain,
MOBILITY_DOMAIN_ID_LEN);
if (conf->nas_identifier &&
struct wpa_authenticator *wpa_auth;
} mld_links[MAX_NUM_MLD_LINKS];
#endif /* CONFIG_IEEE80211BE */
+
+ bool ssid_protection;
};
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
{
u8 *pos = buf;
- u16 capab = 0;
+ u32 capab = 0, tmp;
size_t flen;
if (wpa_key_mgmt_sae(conf->wpa_key_mgmt) &&
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
if (conf->prot_range_neg)
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
+ if (conf->ssid_protection)
+ capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
- flen = (capab & 0xff00) ? 2 : 1;
if (!capab)
return 0; /* no supported extended RSN capabilities */
+ tmp = capab;
+ flen = 0;
+ while (tmp) {
+ flen++;
+ tmp >>= 8;
+ }
if (len < 2 + flen)
return -1;
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
*pos++ = WLAN_EID_RSNX;
*pos++ = flen;
- *pos++ = capab & 0x00ff;
- capab >>= 8;
- if (capab)
- *pos++ = capab;
+ while (capab) {
+ *pos++ = capab & 0xff;
+ capab >>= 8;
+ }
return pos - buf;
}