From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.01.org
Subject: [PATCH v3 3/3] owe: netdev: refactor to remove OWE as an auth-proto
Date: Fri, 03 Sep 2021 12:35:44 -0700 [thread overview]
Message-ID: <20210903193544.13897-3-prestwoj@gmail.com> (raw)
In-Reply-To: <20210903193544.13897-1-prestwoj@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 26525 bytes --]
---
src/netdev.c | 545 +++++++++++++++++++++++++++------------------------
src/owe.c | 148 ++------------
src/owe.h | 12 +-
3 files changed, 312 insertions(+), 393 deletions(-)
v3:
* Deauth if OWE AKM is not in associate response RSN IE
* Remove owe_sm forward declaration from netdev.h
diff --git a/src/netdev.c b/src/netdev.c
index 8592685c..db304c0d 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -119,6 +119,7 @@ struct netdev {
void *user_data;
struct eapol_sm *sm;
struct auth_proto *ap;
+ struct owe_sm *owe_sm;
struct handshake_state *handshake;
uint32_t connect_cmd_id;
uint32_t disconnect_cmd_id;
@@ -752,6 +753,11 @@ static void netdev_connect_free(struct netdev *netdev)
netdev->ap = NULL;
}
+ if (netdev->owe_sm) {
+ owe_sm_free(netdev->owe_sm);
+ netdev->owe_sm = NULL;
+ }
+
eapol_preauth_cancel(netdev->index);
if (netdev->handshake) {
@@ -2094,6 +2100,228 @@ static void netdev_driver_connected(struct netdev *netdev)
eapol_register(netdev->sm);
}
+static unsigned int ie_rsn_akm_suite_to_nl80211(enum ie_rsn_akm_suite akm)
+{
+ switch (akm) {
+ case IE_RSN_AKM_SUITE_8021X:
+ return CRYPTO_AKM_8021X;
+ case IE_RSN_AKM_SUITE_PSK:
+ return CRYPTO_AKM_PSK;
+ case IE_RSN_AKM_SUITE_FT_OVER_8021X:
+ return CRYPTO_AKM_FT_OVER_8021X;
+ case IE_RSN_AKM_SUITE_FT_USING_PSK:
+ return CRYPTO_AKM_FT_USING_PSK;
+ case IE_RSN_AKM_SUITE_8021X_SHA256:
+ return CRYPTO_AKM_8021X_SHA256;
+ case IE_RSN_AKM_SUITE_PSK_SHA256:
+ return CRYPTO_AKM_PSK_SHA256;
+ case IE_RSN_AKM_SUITE_TDLS:
+ return CRYPTO_AKM_TDLS;
+ case IE_RSN_AKM_SUITE_SAE_SHA256:
+ return CRYPTO_AKM_SAE_SHA256;
+ case IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256:
+ return CRYPTO_AKM_FT_OVER_SAE_SHA256;
+ case IE_RSN_AKM_SUITE_AP_PEER_KEY_SHA256:
+ return CRYPTO_AKM_AP_PEER_KEY_SHA256;
+ case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
+ return CRYPTO_AKM_8021X_SUITE_B_SHA256;
+ case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384:
+ return CRYPTO_AKM_8021X_SUITE_B_SHA384;
+ case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
+ return CRYPTO_AKM_FT_OVER_8021X_SHA384;
+ case IE_RSN_AKM_SUITE_FILS_SHA256:
+ return CRYPTO_AKM_FILS_SHA256;
+ case IE_RSN_AKM_SUITE_FILS_SHA384:
+ return CRYPTO_AKM_FILS_SHA384;
+ case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
+ return CRYPTO_AKM_FT_OVER_FILS_SHA256;
+ case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
+ return CRYPTO_AKM_FT_OVER_FILS_SHA384;
+ case IE_RSN_AKM_SUITE_OWE:
+ return CRYPTO_AKM_OWE;
+ case IE_RSN_AKM_SUITE_OSEN:
+ return CRYPTO_AKM_OSEN;
+ }
+
+ return 0;
+}
+
+static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
+ struct handshake_state *hs,
+ const uint8_t *prev_bssid,
+ const struct iovec *vendor_ies,
+ size_t num_vendor_ies)
+{
+ struct netdev_handshake_state *nhs =
+ l_container_of(hs, struct netdev_handshake_state, super);
+ uint32_t auth_type = IE_AKM_IS_SAE(hs->akm_suite) ?
+ NL80211_AUTHTYPE_SAE :
+ NL80211_AUTHTYPE_OPEN_SYSTEM;
+ enum mpdu_management_subtype subtype = prev_bssid ?
+ MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST :
+ MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
+ struct l_genl_msg *msg;
+ struct iovec iov[64];
+ unsigned int n_iov = L_ARRAY_SIZE(iov);
+ unsigned int c_iov = 0;
+ bool is_rsn = hs->supplicant_ie != NULL;
+ uint8_t owe_dh_ie[5 + L_ECC_SCALAR_MAX_BYTES];
+ size_t dh_ie_len;
+
+ msg = l_genl_msg_new_sized(NL80211_CMD_CONNECT, 512);
+ l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
+ l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
+ 4, &netdev->frequency);
+ l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
+ l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
+ l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
+
+ switch (nhs->type) {
+ case CONNECTION_TYPE_SOFTMAC:
+ case CONNECTION_TYPE_FULLMAC:
+ break;
+ case CONNECTION_TYPE_SAE_OFFLOAD:
+ l_genl_msg_append_attr(msg, NL80211_ATTR_SAE_PASSWORD,
+ strlen(hs->passphrase), hs->passphrase);
+ break;
+ case CONNECTION_TYPE_PSK_OFFLOAD:
+ l_genl_msg_append_attr(msg, NL80211_ATTR_PMK, 32, hs->pmk);
+ break;
+ case CONNECTION_TYPE_8021X_OFFLOAD:
+ l_genl_msg_append_attr(msg, NL80211_ATTR_WANT_1X_4WAY_HS,
+ 0, NULL);
+ }
+
+ if (prev_bssid)
+ l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
+ prev_bssid);
+
+ if (netdev->privacy)
+ l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
+
+ l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, NULL);
+
+ if (is_rsn) {
+ uint32_t nl_cipher;
+ uint32_t nl_akm;
+ uint32_t wpa_version;
+
+ if (hs->pairwise_cipher == IE_RSN_CIPHER_SUITE_CCMP)
+ nl_cipher = CRYPTO_CIPHER_CCMP;
+ else
+ nl_cipher = CRYPTO_CIPHER_TKIP;
+
+ l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+ 4, &nl_cipher);
+
+ if (hs->group_cipher == IE_RSN_CIPHER_SUITE_CCMP)
+ nl_cipher = CRYPTO_CIPHER_CCMP;
+ else
+ nl_cipher = CRYPTO_CIPHER_TKIP;
+
+ l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
+ 4, &nl_cipher);
+
+ if (hs->mfp) {
+ uint32_t use_mfp = NL80211_MFP_REQUIRED;
+ l_genl_msg_append_attr(msg, NL80211_ATTR_USE_MFP,
+ 4, &use_mfp);
+ }
+
+ nl_akm = ie_rsn_akm_suite_to_nl80211(hs->akm_suite);
+ if (nl_akm)
+ l_genl_msg_append_attr(msg, NL80211_ATTR_AKM_SUITES,
+ 4, &nl_akm);
+
+ if (IE_AKM_IS_SAE(hs->akm_suite))
+ wpa_version = NL80211_WPA_VERSION_3;
+ else if (hs->wpa_ie)
+ wpa_version = NL80211_WPA_VERSION_1;
+ else
+ wpa_version = NL80211_WPA_VERSION_2;
+
+ l_genl_msg_append_attr(msg, NL80211_ATTR_WPA_VERSIONS,
+ 4, &wpa_version);
+
+ l_genl_msg_append_attr(msg, NL80211_ATTR_CONTROL_PORT, 0, NULL);
+ c_iov = iov_ie_append(iov, n_iov, c_iov, hs->supplicant_ie);
+ }
+
+ if (netdev->owe_sm) {
+ owe_build_dh_ie(netdev->owe_sm, owe_dh_ie, &dh_ie_len);
+ c_iov = iov_ie_append(iov, n_iov, c_iov, owe_dh_ie);
+ }
+
+ if (netdev->pae_over_nl80211)
+ l_genl_msg_append_attr(msg,
+ NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
+ 0, NULL);
+
+ c_iov = iov_ie_append(iov, n_iov, c_iov, hs->mde);
+ c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
+
+ mpdu_sort_ies(subtype, iov, c_iov);
+
+ if (vendor_ies && !L_WARN_ON(n_iov - c_iov < num_vendor_ies)) {
+ memcpy(iov + c_iov, vendor_ies,
+ sizeof(*vendor_ies) * num_vendor_ies);
+ c_iov += num_vendor_ies;
+ }
+
+ if (c_iov)
+ l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
+
+ return msg;
+}
+
+static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
+{
+ struct netdev *netdev = user_data;
+
+ netdev->connect_cmd_id = 0;
+
+ if (l_genl_msg_get_error(msg) >= 0) {
+ /*
+ * connected should be false if the connect event hasn't come
+ * in yet. i.e. the CMD_CONNECT ack arrived first (typical).
+ * Mark the connection as 'connected'
+ */
+ if (!netdev->connected)
+ netdev_driver_connected(netdev);
+
+ return;
+ }
+
+ netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
+ MMPDU_STATUS_CODE_UNSPECIFIED);
+}
+
+static bool netdev_retry_owe(struct netdev *netdev)
+{
+ struct iovec iov;
+
+ if (!owe_next_group(netdev->owe_sm))
+ return false;
+
+ iov.iov_base = netdev->handshake->vendor_ies;
+ iov.iov_len = netdev->handshake->vendor_ies_len;
+
+ netdev->connect_cmd = netdev_build_cmd_connect(netdev,
+ netdev->handshake, NULL, &iov, 1);
+
+ netdev->connect_cmd_id = l_genl_family_send(nl80211,
+ netdev->connect_cmd,
+ netdev_cmd_connect_cb, netdev,
+ NULL);
+
+ if (!netdev->connect_cmd_id)
+ return false;
+
+ netdev->connect_cmd = NULL;
+
+ return true;
+}
+
static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev)
{
struct l_genl_attr attr;
@@ -2162,6 +2390,14 @@ static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev)
goto error;
}
+ if (netdev->owe_sm && status_code && *status_code ==
+ MMPDU_STATUS_CODE_UNSUPP_FINITE_CYCLIC_GROUP) {
+ if (!netdev_retry_owe(netdev))
+ goto error;
+
+ return;
+ }
+
/* AP Rejected the authenticate / associate */
if (!status_code || *status_code != 0)
goto error;
@@ -2175,8 +2411,12 @@ process_resp_ies:
if (resp_ies) {
const uint8_t *fte = NULL;
const uint8_t *qos_set = NULL;
+ const uint8_t *owe_dh = NULL;
+ size_t owe_dh_len = 0;
size_t qos_len = 0;
struct ie_ft_info ft_info;
+ struct ie_rsn_info info;
+ bool owe_akm_found = false;
ie_tlv_iter_init(&iter, resp_ies, resp_ies_len);
@@ -2203,7 +2443,53 @@ process_resp_ies:
data - 3,
ie_tlv_iter_get_length(&iter) + 3);
break;
+ case IE_TYPE_OWE_DH_PARAM:
+ if (!netdev->owe_sm)
+ continue;
+
+ owe_dh = data;
+ owe_dh_len = len;
+
+ break;
+
+ case IE_TYPE_RSN:
+ if (!netdev->owe_sm)
+ continue;
+
+ if (ie_parse_rsne(&iter, &info) < 0) {
+ l_error("could not parse RSN IE");
+ goto error;
+ }
+
+ /*
+ * RFC 8110 Section 4.2
+ * An AP agreeing to do OWE MUST include the OWE AKM in
+ * the RSN element portion of the 802.11 association
+ * response.
+ */
+ if (info.akm_suites != IE_RSN_AKM_SUITE_OWE) {
+ l_error("OWE AKM not included");
+ goto deauth;
+ }
+
+ owe_akm_found = true;
+
+ break;
+ }
+ }
+
+ if (netdev->owe_sm) {
+ if (!owe_dh || !owe_akm_found) {
+ l_error("OWE DH element/RSN not found");
+ goto error;
}
+
+ if (owe_process_dh_ie(netdev->owe_sm, owe_dh,
+ owe_dh_len) != 0)
+ goto error;
+
+ owe_sm_free(netdev->owe_sm);
+ netdev->owe_sm = NULL;
}
/* FILS handles its own FT key derivation */
@@ -2271,52 +2557,6 @@ deauth:
netdev, NULL);
}
-static unsigned int ie_rsn_akm_suite_to_nl80211(enum ie_rsn_akm_suite akm)
-{
- switch (akm) {
- case IE_RSN_AKM_SUITE_8021X:
- return CRYPTO_AKM_8021X;
- case IE_RSN_AKM_SUITE_PSK:
- return CRYPTO_AKM_PSK;
- case IE_RSN_AKM_SUITE_FT_OVER_8021X:
- return CRYPTO_AKM_FT_OVER_8021X;
- case IE_RSN_AKM_SUITE_FT_USING_PSK:
- return CRYPTO_AKM_FT_USING_PSK;
- case IE_RSN_AKM_SUITE_8021X_SHA256:
- return CRYPTO_AKM_8021X_SHA256;
- case IE_RSN_AKM_SUITE_PSK_SHA256:
- return CRYPTO_AKM_PSK_SHA256;
- case IE_RSN_AKM_SUITE_TDLS:
- return CRYPTO_AKM_TDLS;
- case IE_RSN_AKM_SUITE_SAE_SHA256:
- return CRYPTO_AKM_SAE_SHA256;
- case IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256:
- return CRYPTO_AKM_FT_OVER_SAE_SHA256;
- case IE_RSN_AKM_SUITE_AP_PEER_KEY_SHA256:
- return CRYPTO_AKM_AP_PEER_KEY_SHA256;
- case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
- return CRYPTO_AKM_8021X_SUITE_B_SHA256;
- case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384:
- return CRYPTO_AKM_8021X_SUITE_B_SHA384;
- case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
- return CRYPTO_AKM_FT_OVER_8021X_SHA384;
- case IE_RSN_AKM_SUITE_FILS_SHA256:
- return CRYPTO_AKM_FILS_SHA256;
- case IE_RSN_AKM_SUITE_FILS_SHA384:
- return CRYPTO_AKM_FILS_SHA384;
- case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
- return CRYPTO_AKM_FT_OVER_FILS_SHA256;
- case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
- return CRYPTO_AKM_FT_OVER_FILS_SHA384;
- case IE_RSN_AKM_SUITE_OWE:
- return CRYPTO_AKM_OWE;
- case IE_RSN_AKM_SUITE_OSEN:
- return CRYPTO_AKM_OSEN;
- }
-
- return 0;
-}
-
static struct l_genl_msg *netdev_build_cmd_associate_common(
struct netdev *netdev)
{
@@ -2602,28 +2842,6 @@ assoc_failed:
netdev->expect_connect_failure = true;
}
-static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
-{
- struct netdev *netdev = user_data;
-
- netdev->connect_cmd_id = 0;
-
- if (l_genl_msg_get_error(msg) >= 0) {
- /*
- * connected should be false if the connect event hasn't come
- * in yet. i.e. the CMD_CONNECT ack arrived first (typical).
- * Mark the connection as 'connected'
- */
- if (!netdev->connected)
- netdev_driver_connected(netdev);
-
- return;
- }
-
- netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
- MMPDU_STATUS_CODE_UNSPECIFIED);
-}
-
static struct l_genl_msg *netdev_build_cmd_authenticate(struct netdev *netdev,
uint32_t auth_type)
{
@@ -2777,64 +2995,6 @@ static void netdev_sae_tx_associate(void *user_data)
}
}
-static void netdev_owe_tx_authenticate(void *user_data)
-{
- struct netdev *netdev = user_data;
- struct l_genl_msg *msg;
-
- msg = netdev_build_cmd_authenticate(netdev,
- NL80211_AUTHTYPE_OPEN_SYSTEM);
-
- if (!l_genl_family_send(nl80211, msg, netdev_auth_cb,
- netdev, NULL)) {
- l_genl_msg_unref(msg);
- netdev_connect_failed(netdev,
- NETDEV_RESULT_AUTHENTICATION_FAILED,
- MMPDU_STATUS_CODE_UNSPECIFIED);
- return;
- }
-
- netdev->auth_cmd = l_genl_msg_ref(msg);
-}
-
-static void netdev_owe_tx_associate(struct iovec *owe_iov, size_t n_owe_iov,
- void *user_data)
-{
- struct netdev *netdev = user_data;
- struct handshake_state *hs = netdev->handshake;
- struct l_genl_msg *msg;
- struct iovec iov[64];
- unsigned int n_iov = L_ARRAY_SIZE(iov);
- unsigned int c_iov = 0;
- enum mpdu_management_subtype subtype =
- MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
-
- msg = netdev_build_cmd_associate_common(netdev);
-
- c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
-
- if (!L_WARN_ON(n_iov - c_iov < n_owe_iov)) {
- memcpy(iov + c_iov, owe_iov, sizeof(*owe_iov) * n_owe_iov);
- c_iov += n_owe_iov;
- }
-
- mpdu_sort_ies(subtype, iov, c_iov);
-
- l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
-
- /* If doing a non-FT Reassociation */
- if (netdev->in_reassoc)
- l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, 6,
- netdev->ap->prev_bssid);
-
- if (!l_genl_family_send(nl80211, msg, netdev_assoc_cb,
- netdev, NULL)) {
- l_genl_msg_unref(msg);
- netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
- MMPDU_STATUS_CODE_UNSPECIFIED);
- }
-}
-
static void netdev_fils_tx_authenticate(const uint8_t *body,
size_t body_len,
void *user_data)
@@ -2902,127 +3062,6 @@ static void netdev_fils_tx_associate(struct iovec *fils_iov, size_t n_fils_iov,
}
}
-static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
- struct handshake_state *hs,
- const uint8_t *prev_bssid,
- const struct iovec *vendor_ies,
- size_t num_vendor_ies)
-{
- struct netdev_handshake_state *nhs =
- l_container_of(hs, struct netdev_handshake_state, super);
- uint32_t auth_type = IE_AKM_IS_SAE(hs->akm_suite) ?
- NL80211_AUTHTYPE_SAE :
- NL80211_AUTHTYPE_OPEN_SYSTEM;
- enum mpdu_management_subtype subtype = prev_bssid ?
- MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST :
- MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
- struct l_genl_msg *msg;
- struct iovec iov[64];
- unsigned int n_iov = L_ARRAY_SIZE(iov);
- unsigned int c_iov = 0;
- bool is_rsn = hs->supplicant_ie != NULL;
-
- msg = l_genl_msg_new_sized(NL80211_CMD_CONNECT, 512);
- l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
- l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
- 4, &netdev->frequency);
- l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
- l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
- l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
-
- switch (nhs->type) {
- case CONNECTION_TYPE_SOFTMAC:
- case CONNECTION_TYPE_FULLMAC:
- break;
- case CONNECTION_TYPE_SAE_OFFLOAD:
- l_genl_msg_append_attr(msg, NL80211_ATTR_SAE_PASSWORD,
- strlen(hs->passphrase), hs->passphrase);
- break;
- case CONNECTION_TYPE_PSK_OFFLOAD:
- l_genl_msg_append_attr(msg, NL80211_ATTR_PMK, 32, hs->pmk);
- break;
- case CONNECTION_TYPE_8021X_OFFLOAD:
- l_genl_msg_append_attr(msg, NL80211_ATTR_WANT_1X_4WAY_HS,
- 0, NULL);
- }
-
- if (prev_bssid)
- l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
- prev_bssid);
-
- if (netdev->privacy)
- l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
-
- l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, NULL);
-
- if (is_rsn) {
- uint32_t nl_cipher;
- uint32_t nl_akm;
- uint32_t wpa_version;
-
- if (hs->pairwise_cipher == IE_RSN_CIPHER_SUITE_CCMP)
- nl_cipher = CRYPTO_CIPHER_CCMP;
- else
- nl_cipher = CRYPTO_CIPHER_TKIP;
-
- l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
- 4, &nl_cipher);
-
- if (hs->group_cipher == IE_RSN_CIPHER_SUITE_CCMP)
- nl_cipher = CRYPTO_CIPHER_CCMP;
- else
- nl_cipher = CRYPTO_CIPHER_TKIP;
-
- l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
- 4, &nl_cipher);
-
- if (hs->mfp) {
- uint32_t use_mfp = NL80211_MFP_REQUIRED;
- l_genl_msg_append_attr(msg, NL80211_ATTR_USE_MFP,
- 4, &use_mfp);
- }
-
- nl_akm = ie_rsn_akm_suite_to_nl80211(hs->akm_suite);
- if (nl_akm)
- l_genl_msg_append_attr(msg, NL80211_ATTR_AKM_SUITES,
- 4, &nl_akm);
-
- if (IE_AKM_IS_SAE(hs->akm_suite))
- wpa_version = NL80211_WPA_VERSION_3;
- else if (hs->wpa_ie)
- wpa_version = NL80211_WPA_VERSION_1;
- else
- wpa_version = NL80211_WPA_VERSION_2;
-
- l_genl_msg_append_attr(msg, NL80211_ATTR_WPA_VERSIONS,
- 4, &wpa_version);
-
- l_genl_msg_append_attr(msg, NL80211_ATTR_CONTROL_PORT, 0, NULL);
- c_iov = iov_ie_append(iov, n_iov, c_iov, hs->supplicant_ie);
- }
-
- if (netdev->pae_over_nl80211)
- l_genl_msg_append_attr(msg,
- NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
- 0, NULL);
-
- c_iov = iov_ie_append(iov, n_iov, c_iov, hs->mde);
- c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
-
- mpdu_sort_ies(subtype, iov, c_iov);
-
- if (vendor_ies && !L_WARN_ON(n_iov - c_iov < num_vendor_ies)) {
- memcpy(iov + c_iov, vendor_ies,
- sizeof(*vendor_ies) * num_vendor_ies);
- c_iov += num_vendor_ies;
- }
-
- if (c_iov)
- l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
-
- return msg;
-}
-
struct rtnl_data {
struct netdev *netdev;
uint8_t addr[ETH_ALEN];
@@ -3397,6 +3436,8 @@ static int netdev_handshake_state_setup_connection_type(
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
goto psk_offload;
+ /* fall through */
+ case IE_RSN_AKM_SUITE_OWE:
if (softmac)
goto softmac;
@@ -3425,12 +3466,11 @@ static int netdev_handshake_state_setup_connection_type(
goto softmac;
return -EINVAL;
- case IE_RSN_AKM_SUITE_OWE:
case IE_RSN_AKM_SUITE_FILS_SHA256:
case IE_RSN_AKM_SUITE_FILS_SHA384:
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
- /* FILS and OWE have no offload in any upstream driver */
+ /* FILS has no offload in any upstream driver */
if (softmac)
goto softmac;
@@ -3509,10 +3549,9 @@ static void netdev_connect_common(struct netdev *netdev,
break;
case IE_RSN_AKM_SUITE_OWE:
- netdev->ap = owe_sm_new(hs, netdev_owe_tx_authenticate,
- netdev_owe_tx_associate,
- netdev);
- break;
+ netdev->owe_sm = owe_sm_new(hs);
+
+ goto build_cmd_connect;
case IE_RSN_AKM_SUITE_FILS_SHA256:
case IE_RSN_AKM_SUITE_FILS_SHA384:
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
diff --git a/src/owe.c b/src/owe.c
index b1eea025..eed3e266 100644
--- a/src/owe.c
+++ b/src/owe.c
@@ -34,7 +34,6 @@
#include "src/auth-proto.h"
struct owe_sm {
- struct auth_proto ap;
struct handshake_state *hs;
const struct l_ecc_curve *curve;
struct l_ecc_scalar *private;
@@ -42,10 +41,6 @@ struct owe_sm {
uint8_t retry;
uint16_t group;
const unsigned int *ecc_groups;
-
- owe_tx_authenticate_func_t auth_tx;
- owe_tx_associate_func_t assoc_tx;
- void *user_data;
};
static bool owe_reset(struct owe_sm *owe)
@@ -72,62 +67,28 @@ static bool owe_reset(struct owe_sm *owe)
return true;
}
-static void owe_free(struct auth_proto *ap)
+void owe_sm_free(struct owe_sm *owe)
{
- struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
-
l_ecc_scalar_free(owe->private);
l_ecc_point_free(owe->public_key);
l_free(owe);
}
-static bool owe_start(struct auth_proto *ap)
+void owe_build_dh_ie(struct owe_sm *owe, uint8_t *buf, size_t *len_out)
{
- struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
-
- owe->auth_tx(owe->user_data);
-
- return true;
-}
-
-static int owe_rx_authenticate(struct auth_proto *ap, const uint8_t *frame,
- size_t frame_len)
-{
- struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
-
- uint8_t buf[5 + L_ECC_SCALAR_MAX_BYTES];
- struct iovec iov[3];
- int iov_elems = 0;
- size_t len;
-
- /*
- * RFC 8110 Section 4.3
- * A client wishing to do OWE MUST indicate the OWE AKM in the RSN
- * element portion of the 802.11 association request ...
- */
- iov[iov_elems].iov_base = owe->hs->supplicant_ie;
- iov[iov_elems].iov_len = owe->hs->supplicant_ie[1] + 2;
- iov_elems++;
-
/*
- * ... and MUST include a Diffie-Hellman Parameter element to its
- * 802.11 association request.
+ * A client wishing to do OWE ... MUST include a Diffie-Hellman
+ * Parameter element to its 802.11 association request.
*/
buf[0] = IE_TYPE_EXTENSION;
buf[2] = IE_TYPE_OWE_DH_PARAM - 256;
l_put_le16(owe->group, buf + 3); /* group */
- len = l_ecc_point_get_x(owe->public_key, buf + 5,
+ *len_out = l_ecc_point_get_x(owe->public_key, buf + 5,
L_ECC_SCALAR_MAX_BYTES);
- buf[1] = 3 + len; /* length */
-
- iov[iov_elems].iov_base = (void *) buf;
- iov[iov_elems].iov_len = buf[1] + 2;
- iov_elems++;
+ buf[1] = 3 + *len_out; /* length */
- owe->assoc_tx(iov, iov_elems, owe->user_data);
-
- return 0;
+ *len_out += 5;
}
/*
@@ -220,7 +181,7 @@ failed:
return false;
}
-static bool owe_retry(struct owe_sm *owe)
+bool owe_next_group(struct owe_sm *owe)
{
/* retry with another group, if possible */
owe->retry++;
@@ -228,88 +189,23 @@ static bool owe_retry(struct owe_sm *owe)
if (!owe_reset(owe))
return false;
- l_debug("OWE retrying with group %u", owe->group);
-
- owe_rx_authenticate(&owe->ap, NULL, 0);
-
return true;
}
-static int owe_rx_associate(struct auth_proto *ap, const uint8_t *frame,
- size_t len)
+int owe_process_dh_ie(struct owe_sm *owe, const uint8_t *dh, size_t len)
{
- struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
-
- const struct mmpdu_header *mpdu = (const struct mmpdu_header *) frame;
- const struct mmpdu_association_response *body = mmpdu_body(mpdu);
- struct ie_tlv_iter iter;
- size_t owe_dh_len = 0;
- const uint8_t *owe_dh = NULL;
- struct ie_rsn_info info;
- bool akm_found = false;
- const void *data;
-
- if (L_LE16_TO_CPU(body->status_code) ==
- MMPDU_STATUS_CODE_UNSUPP_FINITE_CYCLIC_GROUP) {
- if (!owe_retry(owe))
- goto owe_bad_status;
-
- return -EAGAIN;
- } else if (body->status_code)
- goto owe_bad_status;
-
- ie_tlv_iter_init(&iter, body->ies, (const uint8_t *) mpdu + len -
- body->ies);
-
- while (ie_tlv_iter_next(&iter)) {
- uint16_t tag = ie_tlv_iter_get_tag(&iter);
-
- data = ie_tlv_iter_get_data(&iter);
- len = ie_tlv_iter_get_length(&iter);
-
- switch (tag) {
- case IE_TYPE_OWE_DH_PARAM:
- owe_dh = data;
- owe_dh_len = len;
-
- break;
- case IE_TYPE_RSN:
- if (ie_parse_rsne(&iter, &info) < 0) {
- l_error("could not parse RSN IE");
- goto invalid_ies;
- }
-
- /*
- * RFC 8110 Section 4.2
- * An AP agreeing to do OWE MUST include the OWE AKM in
- * the RSN element portion of the 802.11 association
- * response.
- */
- if (info.akm_suites != IE_RSN_AKM_SUITE_OWE) {
- l_error("OWE AKM not included");
- goto invalid_ies;
- }
-
- akm_found = true;
-
- break;
- default:
- continue;
- }
- }
-
- if (!owe_dh || owe_dh_len < 34 || !akm_found) {
+ if (!dh || len < 34) {
l_error("associate response did not include proper OWE IE's");
goto invalid_ies;
}
- if (l_get_le16(owe_dh) != owe->group) {
+ if (l_get_le16(dh) != owe->group) {
l_error("associate response contained unsupported group %u",
- l_get_le16(owe_dh));
+ l_get_le16(dh));
return -EBADMSG;
}
- if (!owe_compute_keys(owe, owe_dh + 2, owe_dh_len - 2)) {
+ if (!owe_compute_keys(owe, dh + 2, len - 2)) {
l_error("could not compute OWE keys");
return -EBADMSG;
}
@@ -318,33 +214,19 @@ static int owe_rx_associate(struct auth_proto *ap, const uint8_t *frame,
invalid_ies:
return MMPDU_STATUS_CODE_INVALID_ELEMENT;
-
-owe_bad_status:
- return L_LE16_TO_CPU(body->status_code);
}
-struct auth_proto *owe_sm_new(struct handshake_state *hs,
- owe_tx_authenticate_func_t auth,
- owe_tx_associate_func_t assoc,
- void *user_data)
+struct owe_sm *owe_sm_new(struct handshake_state *hs)
{
struct owe_sm *owe = l_new(struct owe_sm, 1);
owe->hs = hs;
- owe->auth_tx = auth;
- owe->assoc_tx = assoc;
- owe->user_data = user_data;
owe->ecc_groups = l_ecc_supported_ike_groups();
- owe->ap.start = owe_start;
- owe->ap.free = owe_free;
- owe->ap.rx_authenticate = owe_rx_authenticate;
- owe->ap.rx_associate = owe_rx_associate;
-
if (!owe_reset(owe)) {
l_free(owe);
return NULL;
}
- return &owe->ap;
+ return owe;
}
diff --git a/src/owe.h b/src/owe.h
index 9a21505f..8a734a00 100644
--- a/src/owe.h
+++ b/src/owe.h
@@ -23,11 +23,9 @@
struct owe_sm;
struct handshake_state;
-typedef void (*owe_tx_authenticate_func_t)(void *user_data);
-typedef void (*owe_tx_associate_func_t)(struct iovec *ie_iov, size_t iov_len,
- void *user_data);
+struct owe_sm *owe_sm_new(struct handshake_state *hs);
+void owe_sm_free(struct owe_sm *sm);
-struct auth_proto *owe_sm_new(struct handshake_state *hs,
- owe_tx_authenticate_func_t auth,
- owe_tx_associate_func_t assoc,
- void *user_data);
+void owe_build_dh_ie(struct owe_sm *sm, uint8_t *buf, size_t *len_out);
+int owe_process_dh_ie(struct owe_sm *sm, const uint8_t *dh, size_t len);
+bool owe_next_group(struct owe_sm *sm);
--
2.31.1
next prev parent reply other threads:[~2021-09-03 19:35 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-03 19:35 [PATCH v3 1/3] netdev: factor out scan_bss from CMD_CONNECT builder James Prestwood
2021-09-03 19:35 ` [PATCH v3 2/3] wsc: set ssid in handshake James Prestwood
2021-09-03 19:35 ` James Prestwood [this message]
2021-09-03 19:44 ` [PATCH v3 3/3] owe: netdev: refactor to remove OWE as an auth-proto Denis Kenzior
2023-07-12 11:17 ` Wen Gong
2023-07-12 14:52 ` James Prestwood
[not found] ` <00246aa8-fe45-f5c2-cf2a-3450cee414f2@quicinc.com>
2023-07-13 2:33 ` James Prestwood
2023-07-13 2:52 ` Wen Gong
2023-07-13 3:04 ` James Prestwood
2023-07-13 3:07 ` Wen Gong
2023-07-13 3:56 ` Wen Gong
2023-07-13 14:14 ` Denis Kenzior
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210903193544.13897-3-prestwoj@gmail.com \
--to=prestwoj@gmail.com \
--cc=iwd@lists.01.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.