OCV: Include and verify OCI in the FT handshake
Include and verify the the OCI element in (Re)Association Request and Response frames of the FT handshake. In case verification fails, the handshake message is silently ignored. Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
This commit is contained in:
parent
6734ba0c00
commit
dd8df6af0b
2 changed files with 109 additions and 0 deletions
|
@ -13,6 +13,8 @@
|
|||
#include "utils/list.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "common/ocv.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "crypto/aes.h"
|
||||
#include "crypto/aes_siv.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
|
@ -727,6 +729,17 @@ static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_OCV
|
||||
static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_channel_info *ci)
|
||||
{
|
||||
if (!wpa_auth->cb->channel_info)
|
||||
return -1;
|
||||
return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
|
||||
|
||||
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
{
|
||||
u8 *pos = buf;
|
||||
|
@ -2430,6 +2443,35 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||
os_free(igtk);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_OCV
|
||||
if (wpa_auth_uses_ocv(sm)) {
|
||||
struct wpa_channel_info ci;
|
||||
u8 *nbuf, *ocipos;
|
||||
|
||||
if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
|
||||
wpa_printf(MSG_WARNING,
|
||||
"Failed to get channel info for OCI element");
|
||||
os_free(subelem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
subelem_len += 2 + OCV_OCI_LEN;
|
||||
nbuf = os_realloc(subelem, subelem_len);
|
||||
if (!nbuf) {
|
||||
os_free(subelem);
|
||||
return NULL;
|
||||
}
|
||||
subelem = nbuf;
|
||||
|
||||
ocipos = subelem + subelem_len - 2 - OCV_OCI_LEN;
|
||||
*ocipos++ = FTIE_SUBELEM_OCI;
|
||||
*ocipos++ = OCV_OCI_LEN;
|
||||
if (ocv_insert_oci(&ci, &ocipos) < 0) {
|
||||
os_free(subelem);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
} else {
|
||||
r0kh_id = conf->r0_key_holder;
|
||||
r0kh_id_len = conf->r0_key_holder_len;
|
||||
|
@ -3178,6 +3220,32 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||
return WLAN_STATUS_INVALID_FTIE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OCV
|
||||
if (wpa_auth_uses_ocv(sm)) {
|
||||
struct wpa_channel_info ci;
|
||||
int tx_chanwidth;
|
||||
int tx_seg1_idx;
|
||||
|
||||
if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
|
||||
wpa_printf(MSG_WARNING,
|
||||
"Failed to get channel info to validate received OCI in (Re)Assoc Request");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
if (get_sta_tx_parameters(sm,
|
||||
channel_width_to_int(ci.chanwidth),
|
||||
ci.seg1_idx, &tx_chanwidth,
|
||||
&tx_seg1_idx) < 0)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
|
||||
if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci,
|
||||
tx_chanwidth, tx_seg1_idx) != 0) {
|
||||
wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_OCV */
|
||||
|
||||
return WLAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#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"
|
||||
|
||||
|
@ -325,6 +327,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) {
|
||||
|
@ -963,6 +985,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)
|
||||
|
|
Loading…
Reference in a new issue