aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@codeaurora.org>2019-09-06 11:51:31 (GMT)
committerJouni Malinen <j@w1.fi>2019-10-15 12:39:22 (GMT)
commit146889e3ca4353c99fe1677c98fbd1972f9b5eac (patch)
treed262c3f54ba1eb8b779a594aadcfb7b49dfd7405
parent3134bb13a8bd54975a514a6e46755234ec5831a2 (diff)
downloadhostap-146889e3ca4353c99fe1677c98fbd1972f9b5eac.zip
hostap-146889e3ca4353c99fe1677c98fbd1972f9b5eac.tar.gz
hostap-146889e3ca4353c99fe1677c98fbd1972f9b5eac.tar.bz2
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>
-rw-r--r--src/rsn_supp/wpa.c44
-rw-r--r--src/rsn_supp/wpa.h7
-rw-r--r--src/rsn_supp/wpa_i.h4
-rw-r--r--src/rsn_supp/wpa_ie.c5
-rw-r--r--src/rsn_supp/wpa_ie.h2
-rw-r--r--wpa_supplicant/events.c14
-rw-r--r--wpa_supplicant/ibss_rsn.c1
-rw-r--r--wpa_supplicant/wpa_supplicant.c13
-rw-r--r--wpa_supplicant/wpas_glue.c4
9 files changed, 85 insertions, 9 deletions
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 9707ae7..f5231c1 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -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
@@ -3284,6 +3295,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()
* @data: Pointer to data area for parsing results
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index ae9cd64..125d359 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -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;
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 129dfb1..16224c9 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -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;
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 809f208..e6af6c1 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -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;
diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h
index 77ebe21..6f18bbe 100644
--- a/src/rsn_supp/wpa_ie.h
+++ b/src/rsn_supp/wpa_ie.h
@@ -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;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 523b7bd..c9ead08 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2647,14 +2647,19 @@ no_pfs:
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
}
+ if (p[0] == WLAN_EID_RSNX && p[1] >= 1)
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
+
l -= len;
p += len;
}
if (!wpa_found && data->assoc_info.beacon_ies)
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
- if (!rsn_found && data->assoc_info.beacon_ies)
+ if (!rsn_found && data->assoc_info.beacon_ies) {
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
+ }
if (wpa_found || rsn_found)
wpa_s->ap_ies_from_associnfo = 1;
@@ -2674,7 +2679,7 @@ no_pfs:
static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
{
- const u8 *bss_wpa = NULL, *bss_rsn = NULL;
+ const u8 *bss_wpa = NULL, *bss_rsn = NULL, *bss_rsnx = NULL;
if (!wpa_s->current_bss || !wpa_s->current_ssid)
return -1;
@@ -2685,11 +2690,14 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
WPA_IE_VENDOR_TYPE);
bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
+ bss_rsnx = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSNX);
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
bss_wpa ? 2 + bss_wpa[1] : 0) ||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
- bss_rsn ? 2 + bss_rsn[1] : 0))
+ bss_rsn ? 2 + bss_rsn[1] : 0) ||
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
+ bss_rsnx ? 2 + bss_rsnx[1] : 0))
return -1;
return 0;
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 6934c47..2bf51c6 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -111,6 +111,7 @@ static int supp_get_beacon_ie(void *ctx)
wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
/* TODO: get correct RSN IE */
+ wpa_sm_set_ap_rsnxe(peer->supp, NULL, 0);
return wpa_sm_set_ap_rsn_ie(peer->supp,
(u8 *) "\x30\x14\x01\x00"
"\x00\x0f\xac\x04"
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 94cc8c7..ca8e1cc 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -402,6 +402,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
wpa_s->group_cipher = WPA_CIPHER_NONE;
@@ -1233,14 +1234,16 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
{
struct wpa_ie_data ie;
int sel, proto;
- const u8 *bss_wpa, *bss_rsn, *bss_osen;
+ const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
if (bss) {
bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
- } else
- bss_wpa = bss_rsn = bss_osen = NULL;
+ } else {
+ bss_wpa = bss_rsn = bss_rsnx = bss_osen = NULL;
+ }
if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
@@ -1371,7 +1374,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
bss_wpa ? 2 + bss_wpa[1] : 0) ||
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
- bss_rsn ? 2 + bss_rsn[1] : 0))
+ bss_rsn ? 2 + bss_rsn[1] : 0) ||
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
+ bss_rsnx ? 2 + bss_rsnx[1] : 0))
return -1;
}
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 62af7f6..d80b8f2 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -396,6 +396,10 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
ret = -1;
+
+ ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX);
+ if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
+ ret = -1;
} else {
ret = -1;
}