diff options
Diffstat (limited to 'freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c')
-rw-r--r-- | freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c b/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c index 852cd781..e30e910e 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c +++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c @@ -16,8 +16,11 @@ #include "crypto/random.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" +#include "common/ocv.h" +#include "drivers/driver.h" #include "wpa.h" #include "wpa_i.h" +#include "pmksa_cache.h" #ifdef CONFIG_IEEE80211R @@ -27,15 +30,23 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, u8 ptk_name[WPA_PMK_NAME_LEN]; const u8 *anonce = key->key_nonce; int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); - - if (sm->xxkey_len == 0) { + const u8 *mpmk; + size_t mpmk_len; + + if (sm->xxkey_len > 0) { + mpmk = sm->xxkey; + mpmk_len = sm->xxkey_len; + } else if (sm->cur_pmksa) { + mpmk = sm->cur_pmksa->pmk; + mpmk_len = sm->cur_pmksa->pmk_len; + } else { wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " "derivation"); return -1; } sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; - if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid, + if (wpa_derive_pmk_r0(mpmk, mpmk_len, sm->ssid, sm->ssid_len, sm->mobility_domain, sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) @@ -244,6 +255,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, sm->mgmt_group_cipher == WPA_CIPHER_BIP_CMAC_256) capab |= WPA_CAPABILITY_MFPC; #endif /* CONFIG_IEEE80211W */ + if (sm->ocv) + capab |= WPA_CAPABILITY_OCVC; WPA_PUT_LE16(pos, capab); pos += 2; @@ -325,6 +338,26 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, *pos++ = sm->r0kh_id_len; os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len); pos += sm->r0kh_id_len; +#ifdef CONFIG_OCV + if (kck && wpa_sm_ocv_enabled(sm)) { + /* OCI sub-element in the third FT message */ + struct wpa_channel_info ci; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element in FTE"); + os_free(buf); + return NULL; + } + + *pos++ = FTIE_SUBELEM_OCI; + *pos++ = OCV_OCI_LEN; + if (ocv_insert_oci(&ci, &pos) < 0) { + os_free(buf); + return NULL; + } + } +#endif /* CONFIG_OCV */ *ftie_len = pos - ftie_len - 1; if (ric_ies) { @@ -797,10 +830,10 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, igtk_elem + 2, 6, igtk, igtk_len) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the " "driver."); - os_memset(igtk, 0, sizeof(igtk)); + forced_memzero(igtk, sizeof(igtk)); return -1; } - os_memset(igtk, 0, sizeof(igtk)); + forced_memzero(igtk, sizeof(igtk)); return 0; } @@ -963,6 +996,25 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return -1; } +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) { + struct wpa_channel_info ci; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info to validate received OCI in (Re)Assoc Response"); + return -1; + } + + if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx) != 0) { + wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + return -1; + } + } +#endif /* CONFIG_OCV */ + sm->ft_reassoc_completed = 1; if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) |