]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
OCV: Include and verify OCI in the FT handshake
authorMathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
Mon, 6 Aug 2018 19:46:32 +0000 (15:46 -0400)
committerJouni Malinen <j@w1.fi>
Mon, 17 Dec 2018 13:42:23 +0000 (15:42 +0200)
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>
src/ap/wpa_auth_ft.c
src/rsn_supp/wpa_ft.c

index f6792e00f32d80b029bc438d6e57e9e229b74dd3..60f0786a1bb62ef09d4ca3eb6750f7dfebadf775 100644 (file)
@@ -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;
 }
 
index 9caff859dcea526b3cb7bdeef4d3c943dbd84e1b..7dcb1043bfcc4b7e0dd7d702d010b1aff6cd945a 100644 (file)
@@ -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)