summaryrefslogtreecommitdiffstats
path: root/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c')
-rw-r--r--freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c62
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)