RSN: Verify RSNXE match between Beacon/ProbeResp and EAPOL-Key msg 3/4

If the AP advertises RSN Extension element, it has to be advertised
consistently in the unprotected (Beacon and Probe Response) and
protected (EAPOL-Key msg 3/4) frames. Verify that this is the case.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-09-06 14:51:31 +03:00 committed by Jouni Malinen
parent 3134bb13a8
commit 146889e3ca
9 changed files with 85 additions and 9 deletions

View file

@ -1365,6 +1365,16 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
return -1;
}
if ((sm->ap_rsnxe && !ie->rsnxe) ||
(!sm->ap_rsnxe && ie->rsnxe) ||
(sm->ap_rsnxe && ie->rsnxe &&
(sm->ap_rsnxe_len != ie->rsnxe_len ||
os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0))) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
return -1;
}
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt) &&
wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
@ -2664,6 +2674,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
os_free(sm->assoc_wpa_ie);
os_free(sm->ap_wpa_ie);
os_free(sm->ap_rsn_ie);
os_free(sm->ap_rsnxe);
wpa_sm_drop_sa(sm);
os_free(sm->ctx);
#ifdef CONFIG_IEEE80211R
@ -3283,6 +3294,39 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
}
/**
* wpa_sm_set_ap_rsnxe - Set AP RSNXE from Beacon/ProbeResp
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @ie: Pointer to IE data (starting from id)
* @len: IE length
* Returns: 0 on success, -1 on failure
*
* Inform WPA state machine about the RSNXE used in Beacon / Probe Response
* frame.
*/
int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
{
if (!sm)
return -1;
os_free(sm->ap_rsnxe);
if (!ie || len == 0) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE");
sm->ap_rsnxe = NULL;
sm->ap_rsnxe_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
sm->ap_rsnxe = os_memdup(ie, len);
if (!sm->ap_rsnxe)
return -1;
sm->ap_rsnxe_len = len;
}
return 0;
}
/**
* wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
* @sm: Pointer to WPA state machine data from wpa_sm_init()

View file

@ -136,6 +136,7 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
size_t *wpa_ie_len);
int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen);
int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
@ -260,6 +261,12 @@ static inline int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie,
return -1;
}
static inline int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie,
size_t len)
{
return -1;
}
static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
{
return 0;

View file

@ -88,8 +88,8 @@ struct wpa_sm {
u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
size_t assoc_wpa_ie_len;
u8 *ap_wpa_ie, *ap_rsn_ie;
size_t ap_wpa_ie_len, ap_rsn_ie_len;
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
#ifdef CONFIG_TDLS
struct wpa_tdls_peer *tdls;

View file

@ -506,6 +506,11 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
ie->rsn_ie_len = pos[1] + 2;
wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
ie->rsn_ie, ie->rsn_ie_len);
} else if (*pos == WLAN_EID_RSNX) {
ie->rsnxe = pos;
ie->rsnxe_len = pos[1] + 2;
wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
ie->rsnxe, ie->rsnxe_len);
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN &&
pos[1] >= sizeof(struct rsn_mdie)) {
ie->mdie = pos;

View file

@ -23,6 +23,8 @@ struct wpa_eapol_ie_parse {
size_t mac_addr_len;
const u8 *igtk;
size_t igtk_len;
const u8 *rsnxe;
size_t rsnxe_len;
const u8 *mdie;
size_t mdie_len;
const u8 *ftie;