SSID protection in 4-way handshake on STA
Add support for SSID protection in 4-way handshake based on the mechanism added in IEEE 802.11REVme/D6.0. This is a mitigation against CVE-2023-52424 (a.k.a. the SSID Confusion Attack). This functionality is disabled by default and can be enabled with ssid_protection=1 in the network profile. Once there has been more testing of this to confirm there is no significant interoperability issues, the goal is to be able to change this to be enabled by default. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
9a022cdc70
commit
dab7549d68
12 changed files with 98 additions and 6 deletions
|
@ -2542,6 +2542,28 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
|
|||
if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
|
||||
goto failed;
|
||||
|
||||
if (sm->ssid_protection) {
|
||||
if (!ie.ssid) {
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||
"RSN: No SSID included in EAPOL-Key msg 3/4");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ie.ssid_len != sm->ssid_len ||
|
||||
os_memcmp(ie.ssid, sm->ssid, sm->ssid_len) != 0) {
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||
"RSN: SSID mismatch in EAPOL-Key msg 3/4");
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "RSN: Received SSID",
|
||||
ie.ssid, ie.ssid_len);
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "RSN: Expected SSID",
|
||||
sm->ssid, sm->ssid_len);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||
"RSN: SSID matched expected value");
|
||||
}
|
||||
|
||||
if (mlo && !ie.valid_mlo_gtks) {
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||
"MLO RSN: No GTK KDE included in EAPOL-Key msg 3/4");
|
||||
|
@ -4460,6 +4482,20 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
|
|||
}
|
||||
|
||||
|
||||
void wpa_sm_set_ssid(struct wpa_sm *sm, const u8 *ssid, size_t ssid_len)
|
||||
{
|
||||
if (!sm)
|
||||
return;
|
||||
|
||||
if (ssid) {
|
||||
os_memcpy(sm->ssid, ssid, ssid_len);
|
||||
sm->ssid_len = ssid_len;
|
||||
} else {
|
||||
sm->ssid_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
|
||||
{
|
||||
int i;
|
||||
|
@ -4689,6 +4725,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
|||
case WPA_PARAM_FT_PREPEND_PMKID:
|
||||
sm->ft_prepend_pmkid = value;
|
||||
break;
|
||||
case WPA_PARAM_SSID_PROTECTION:
|
||||
sm->ssid_protection = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -4960,6 +4999,14 @@ int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
|
|||
sm->assoc_rsnxe_len = len;
|
||||
}
|
||||
|
||||
if (sm->ssid_protection &&
|
||||
!ieee802_11_rsnx_capab(sm->assoc_rsnxe,
|
||||
WLAN_RSNX_CAPAB_SSID_PROTECTION)) {
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||
"RSN: Disabling SSID protection based on own RSNXE update");
|
||||
sm->ssid_protection = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,7 @@ enum wpa_sm_conf_params {
|
|||
WPA_PARAM_ENCRYPT_EAPOL_M2,
|
||||
WPA_PARAM_ENCRYPT_EAPOL_M4,
|
||||
WPA_PARAM_FT_PREPEND_PMKID,
|
||||
WPA_PARAM_SSID_PROTECTION,
|
||||
};
|
||||
|
||||
struct rsn_supp_config {
|
||||
|
@ -188,6 +189,7 @@ void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm);
|
|||
void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth);
|
||||
void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx);
|
||||
void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config);
|
||||
void wpa_sm_set_ssid(struct wpa_sm *sm, const u8 *ssid, size_t ssid_len);
|
||||
void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr);
|
||||
void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
|
||||
const char *bridge_ifname);
|
||||
|
|
|
@ -112,6 +112,7 @@ struct wpa_sm {
|
|||
unsigned int secure_ltf:1;
|
||||
unsigned int secure_rtt:1;
|
||||
unsigned int prot_range_neg:1;
|
||||
unsigned int ssid_protection:1;
|
||||
|
||||
u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
|
||||
size_t assoc_wpa_ie_len;
|
||||
|
|
|
@ -366,7 +366,7 @@ int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
|
|||
int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
|
||||
{
|
||||
u8 *pos = rsnxe;
|
||||
u16 capab = 0;
|
||||
u32 capab = 0, tmp;
|
||||
size_t flen;
|
||||
|
||||
if (wpa_key_mgmt_sae(sm->key_mgmt) &&
|
||||
|
@ -385,20 +385,27 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
|
|||
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
|
||||
if (sm->prot_range_neg)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
|
||||
if (sm->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 (rsnxe_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 - rsnxe;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue