From 8ada894f706229c49a3512629c23ad32ef7d148d Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 20 Sep 2021 14:29:05 -0500 Subject: [PATCH] handshake: Add OCV utilities Add a utility for setting the OCI obtained from the hardware (prior to handshake starting) as well as a utility to validate the OCI obtained from the peer. --- src/handshake.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ src/handshake.h | 8 ++++++++ 2 files changed, 62 insertions(+) diff --git a/src/handshake.c b/src/handshake.c index eb060365..10923fbf 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -42,6 +42,7 @@ #include "src/util.h" #include "src/handshake.h" #include "src/erp.h" +#include "src/band.h" static inline unsigned int n_ecc_groups() { @@ -112,6 +113,8 @@ void handshake_state_free(struct handshake_state *s) if (s->erp_cache) erp_cache_put(s->erp_cache); + l_free(s->chandef); + if (s->passphrase) { explicit_bzero(s->passphrase, strlen(s->passphrase)); l_free(s->passphrase); @@ -188,6 +191,8 @@ valid_ie: l_free(s->authenticator_ie); s->authenticator_ie = l_memdup(ie, ie[1] + 2u); + s->authenticator_ocvc = info.ocvc; + return true; } @@ -228,6 +233,7 @@ valid_ie: s->group_cipher = info.group_cipher; s->group_management_cipher = info.group_management_cipher; s->akm_suite = info.akm_suites; + s->supplicant_ocvc = info.ocvc; /* * Don't set MFP for OSEN otherwise EAPoL will attempt to negotiate a @@ -1014,3 +1020,51 @@ bool handshake_state_add_ecc_sae_pt(struct handshake_state *s, s->ecc_sae_pts[i] = l_ecc_point_clone(pt); return true; } + +void handshake_state_set_chandef(struct handshake_state *s, + struct band_chandef *chandef) +{ + s->chandef = chandef; +} + +int handshake_state_verify_oci(struct handshake_state *s, const uint8_t *oci, + size_t oci_len) +{ + int r = -ENOENT; + bool ocvc; + + l_debug("oci_len: %zu", oci ? oci_len : 0); + + if (!oci) + goto done; + + r = -EBADMSG; + if (oci_len != 3) + goto done; + + l_debug("operating_class: %hu", oci[0]); + l_debug("primary_channel_number: %hu", oci[1]); + l_debug("frequency segment 1 channel number: %hu", oci[2]); + + r = -EINVAL; + + if (!s->chandef) { + l_debug("Own chandef unavailable"); + goto done; + } + + r = oci_verify(oci, s->chandef); + if (r < 0) + l_debug("OCI verification failed: %s", strerror(-r)); + +done: + if (!r) + return r; + + /* Only enforce validation if we're configured to do so */ + ocvc = s->authenticator ? s->authenticator_ocvc : s->supplicant_ocvc; + if (!ocvc) + r = 0; + + return r; +} diff --git a/src/handshake.h b/src/handshake.h index fa12faa7..36ccc3a2 100644 --- a/src/handshake.h +++ b/src/handshake.h @@ -126,6 +126,8 @@ struct handshake_state { bool wait_for_gtk : 1; bool no_rekey : 1; bool support_fils : 1; + bool authenticator_ocvc : 1; + bool supplicant_ocvc : 1; uint8_t ssid[32]; size_t ssid_len; char *passphrase; @@ -143,6 +145,7 @@ struct handshake_state { uint32_t go_ip_addr; uint8_t *fils_ip_req_ie; uint8_t *fils_ip_resp_ie; + struct band_chandef *chandef; void *user_data; void (*free)(struct handshake_state *s); @@ -242,6 +245,11 @@ bool handshake_decode_fte_key(struct handshake_state *s, const uint8_t *wrapped, void handshake_state_set_gtk(struct handshake_state *s, const uint8_t *key, unsigned int key_index, const uint8_t *rsc); +void handshake_state_set_chandef(struct handshake_state *s, + struct band_chandef *chandef); +int handshake_state_verify_oci(struct handshake_state *s, const uint8_t *oci, + size_t oci_len); + bool handshake_util_ap_ie_matches(const struct ie_rsn_info *msg_info, const uint8_t *scan_ie, bool is_wpa);