SAE: Add RSNXE in Association Request and EAPOL-Key msg 2/4
Add the new RSNXE into (Re)Association Request frames and EAPOL-Key msg 2/4 when using SAE with hash-to-element mechanism enabled. This allows the AP to verify that there was no downgrade attack when both PWE derivation mechanisms are enabled. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
8401cdc8d4
commit
6d6c887751
9 changed files with 187 additions and 33 deletions
|
@ -655,51 +655,51 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
|
|||
|
||||
kde = sm->assoc_wpa_ie;
|
||||
kde_len = sm->assoc_wpa_ie_len;
|
||||
kde_buf = os_malloc(kde_len +
|
||||
2 + RSN_SELECTOR_LEN + 3 +
|
||||
sm->assoc_rsnxe_len +
|
||||
2 + RSN_SELECTOR_LEN + 1);
|
||||
if (!kde_buf)
|
||||
goto failed;
|
||||
os_memcpy(kde_buf, kde, kde_len);
|
||||
kde = kde_buf;
|
||||
|
||||
#ifdef CONFIG_OCV
|
||||
if (wpa_sm_ocv_enabled(sm)) {
|
||||
struct wpa_channel_info ci;
|
||||
u8 *pos;
|
||||
|
||||
pos = kde + kde_len;
|
||||
if (wpa_sm_channel_info(sm, &ci) != 0) {
|
||||
wpa_printf(MSG_WARNING,
|
||||
"Failed to get channel info for OCI element in EAPOL-Key 2/4");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 3);
|
||||
if (!kde_buf) {
|
||||
wpa_printf(MSG_WARNING,
|
||||
"Failed to allocate memory for KDE with OCI in EAPOL-Key 2/4");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
os_memcpy(kde_buf, kde, kde_len);
|
||||
kde = kde_buf;
|
||||
pos = kde + kde_len;
|
||||
if (ocv_insert_oci_kde(&ci, &pos) < 0)
|
||||
goto failed;
|
||||
kde_len = pos - kde;
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
|
||||
if (sm->assoc_rsnxe && sm->assoc_rsnxe_len) {
|
||||
os_memcpy(kde + kde_len, sm->assoc_rsnxe, sm->assoc_rsnxe_len);
|
||||
kde_len += sm->assoc_rsnxe_len;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (sm->p2p) {
|
||||
kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 1);
|
||||
if (kde_buf) {
|
||||
u8 *pos;
|
||||
wpa_printf(MSG_DEBUG, "P2P: Add IP Address Request KDE "
|
||||
"into EAPOL-Key 2/4");
|
||||
os_memcpy(kde_buf, kde, kde_len);
|
||||
kde = kde_buf;
|
||||
pos = kde + kde_len;
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = RSN_SELECTOR_LEN + 1;
|
||||
RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
*pos++ = 0x01;
|
||||
kde_len = pos - kde;
|
||||
}
|
||||
u8 *pos;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"P2P: Add IP Address Request KDE into EAPOL-Key 2/4");
|
||||
pos = kde + kde_len;
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = RSN_SELECTOR_LEN + 1;
|
||||
RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
*pos++ = 0x01;
|
||||
kde_len = pos - kde;
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
|
@ -2672,6 +2672,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
|
|||
eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
|
||||
eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
|
||||
os_free(sm->assoc_wpa_ie);
|
||||
os_free(sm->assoc_rsnxe);
|
||||
os_free(sm->ap_wpa_ie);
|
||||
os_free(sm->ap_rsn_ie);
|
||||
os_free(sm->ap_rsnxe);
|
||||
|
@ -3049,6 +3050,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
|
|||
case WPA_PARAM_OCV:
|
||||
sm->ocv = value;
|
||||
break;
|
||||
case WPA_PARAM_SAE_PWE:
|
||||
sm->sae_pwe = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -3226,6 +3230,83 @@ int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_sm_set_assoc_rsnxe_default - Generate own RSNXE from configuration
|
||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||
* @rsnxe: Pointer to buffer for RSNXE
|
||||
* @rsnxe_len: Pointer to the length of the rsne buffer
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int wpa_sm_set_assoc_rsnxe_default(struct wpa_sm *sm, u8 *rsnxe,
|
||||
size_t *rsnxe_len)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!sm)
|
||||
return -1;
|
||||
|
||||
res = wpa_gen_rsnxe(sm, rsnxe, *rsnxe_len);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
*rsnxe_len = res;
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "RSN: Set own RSNXE default", rsnxe, *rsnxe_len);
|
||||
|
||||
if (sm->assoc_rsnxe) {
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"RSN: Leave previously set RSNXE default",
|
||||
sm->assoc_rsnxe, sm->assoc_rsnxe_len);
|
||||
} else if (*rsnxe_len > 0) {
|
||||
/*
|
||||
* Make a copy of the RSNXE so that 4-Way Handshake gets the
|
||||
* correct version of the IE even if it gets changed.
|
||||
*/
|
||||
sm->assoc_rsnxe = os_memdup(rsnxe, *rsnxe_len);
|
||||
if (!sm->assoc_rsnxe)
|
||||
return -1;
|
||||
|
||||
sm->assoc_rsnxe_len = *rsnxe_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_sm_set_assoc_rsnxe - Set own RSNXE from (Re)AssocReq
|
||||
* @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 (Re)Association Request
|
||||
* frame. The IE will be used to override the default value generated
|
||||
* with wpa_sm_set_assoc_rsnxe_default().
|
||||
*/
|
||||
int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||
{
|
||||
if (!sm)
|
||||
return -1;
|
||||
|
||||
os_free(sm->assoc_rsnxe);
|
||||
if (!ie || len == 0) {
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||
"RSN: clearing own RSNXE");
|
||||
sm->assoc_rsnxe = NULL;
|
||||
sm->assoc_rsnxe_len = 0;
|
||||
} else {
|
||||
wpa_hexdump(MSG_DEBUG, "RSN: set own RSNXE", ie, len);
|
||||
sm->assoc_rsnxe = os_memdup(ie, len);
|
||||
if (!sm->assoc_rsnxe)
|
||||
return -1;
|
||||
|
||||
sm->assoc_rsnxe_len = len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp
|
||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||
|
|
|
@ -98,7 +98,8 @@ enum wpa_sm_conf_params {
|
|||
WPA_PARAM_MGMT_GROUP,
|
||||
WPA_PARAM_RSN_ENABLED,
|
||||
WPA_PARAM_MFP,
|
||||
WPA_PARAM_OCV
|
||||
WPA_PARAM_OCV,
|
||||
WPA_PARAM_SAE_PWE,
|
||||
};
|
||||
|
||||
struct rsn_supp_config {
|
||||
|
@ -134,6 +135,9 @@ void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol);
|
|||
int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||
int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
|
||||
size_t *wpa_ie_len);
|
||||
int wpa_sm_set_assoc_rsnxe_default(struct wpa_sm *sm, u8 *rsnxe,
|
||||
size_t *rsnxe_len);
|
||||
int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t 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);
|
||||
|
|
|
@ -85,9 +85,12 @@ struct wpa_sm {
|
|||
int rsn_enabled; /* Whether RSN is enabled in configuration */
|
||||
int mfp; /* 0 = disabled, 1 = optional, 2 = mandatory */
|
||||
int ocv; /* Operating Channel Validation */
|
||||
int sae_pwe; /* SAE PWE generation options */
|
||||
|
||||
u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
|
||||
size_t assoc_wpa_ie_len;
|
||||
u8 *assoc_rsnxe; /* Own RSNXE from (Re)AssocReq */
|
||||
size_t assoc_rsnxe_len;
|
||||
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
|
||||
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
|
||||
|
||||
|
|
|
@ -342,6 +342,28 @@ 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;
|
||||
|
||||
if (!wpa_key_mgmt_sae(sm->key_mgmt))
|
||||
return 0; /* SAE not in use */
|
||||
if (sm->sae_pwe != 1 && sm->sae_pwe != 2)
|
||||
return 0; /* no supported extended RSN capabilities */
|
||||
|
||||
if (rsnxe_len < 3)
|
||||
return -1;
|
||||
|
||||
*pos++ = WLAN_EID_RSNX;
|
||||
*pos++ = 1;
|
||||
/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
|
||||
* used for now */
|
||||
*pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||
|
||||
return pos - rsnxe;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_parse_vendor_specific - Parse Vendor Specific IEs
|
||||
* @pos: Pointer to the IE header
|
||||
|
|
|
@ -62,5 +62,6 @@ struct wpa_eapol_ie_parse {
|
|||
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
|
||||
struct wpa_eapol_ie_parse *ie);
|
||||
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);
|
||||
|
||||
#endif /* WPA_IE_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue