diff mbox series

[v2,09/18] ap: add support to handle SAE authentication

Message ID 20240506003518.320176-10-brandtwjohn@gmail.com (mailing list archive)
State New
Headers show
Series Basic WPA3 support in AP mode | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
prestwoj/iwd-ci-gitlint success GitLint

Commit Message

John Brandt May 6, 2024, 12:30 a.m. UTC
When the client requests SAE authentication, and it is enabled, allocate
an auth_proto instance to handle SAE authentication. This also adds a
new function to send SAE frames in AP mode that can be used by the
auth_proto instance.
---
 src/ap.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 58 insertions(+), 9 deletions(-)

Comments

Denis Kenzior May 7, 2024, 3:44 p.m. UTC | #1
Hi John,

On 5/5/24 7:30 PM, John Brandt wrote:
> When the client requests SAE authentication, and it is enabled, allocate
> an auth_proto instance to handle SAE authentication. This also adds a
> new function to send SAE frames in AP mode that can be used by the
> auth_proto instance.
> ---
>   src/ap.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++--------
>   1 file changed, 58 insertions(+), 9 deletions(-)
> 

<snip>

> @@ -2595,6 +2598,38 @@ static void ap_auth_reply(struct ap_state *ap, const uint8_t *dest,
>   				ap_auth_reply_cb, NULL);
>   }
>   
> +static void sae_auth_reply(const uint8_t *data, size_t len, void *user_data)
> +{
> +	struct sta_state *sta = (struct sta_state *)user_data;
> +	struct ap_state *ap = (struct ap_state *)sta->ap;

This cast isn't needed?

> +	const uint8_t *addr = netdev_get_address(ap->netdev);
> +	uint8_t sae_buf[512];
> +	struct mmpdu_header *mpdu = (struct mmpdu_header *) sae_buf;
> +	struct mmpdu_authentication *auth;
> +
> +	if (L_WARN_ON(26 + len > sizeof(sae_buf)))
> +		return;
> +
> +	memset(mpdu, 0, sizeof(*mpdu));
> +
> +	/* Header */
> +	mpdu->fc.protocol_version = 0;
> +	mpdu->fc.type = MPDU_TYPE_MANAGEMENT;
> +	mpdu->fc.subtype = MPDU_MANAGEMENT_SUBTYPE_AUTHENTICATION;
> +	memcpy(mpdu->address_1, sta->addr, 6);	/* DA */
> +	memcpy(mpdu->address_2, addr, 6);	/* SA */
> +	memcpy(mpdu->address_3, addr, 6);	/* BSSID */
> +
> +	/* Authentication body */
> +	auth = (void *) mmpdu_body(mpdu);
> +	auth->algorithm = L_CPU_TO_LE16(MMPDU_AUTH_ALGO_SAE);
> +
> +	/* SAE elements */
> +	memcpy(sae_buf + 26, data, len);
> +	ap_send_mgmt_frame(ap, mpdu, 26 + len,
> +				ap_auth_reply_cb, NULL);
> +}
> +
>   /*
>    * 802.11-2016 9.3.3.12 (frame format), 802.11-2016 11.3.4.3 and
>    * 802.11-2016 12.3.3.2 (MLME/SME)

<snip>

> @@ -2680,18 +2715,32 @@ static void ap_auth_cb(const struct mmpdu_header *hdr, const void *body,
>   		ap->sta_states = l_queue_new();
>   
>   	sta->akm_suite = akm_suite;
> +	if (sta->akm_suite == IE_RSN_AKM_SUITE_SAE_SHA256) {
> +		sta->hs = netdev_handshake_state_new(sta->ap->netdev);
> +		handshake_state_set_authenticator(sta->hs, true);
> +		handshake_state_set_passphrase(sta->hs, ap->passphrase);
> +		handshake_state_set_supplicant_address(sta->hs, sta->addr);
> +		handshake_state_set_authenticator_address(sta->hs, bssid);
> +
> +		sta->auth_proto = sae_sm_new(sta->hs, sae_auth_reply, NULL, sta);
> +	}
>   
>   	l_queue_push_tail(ap->sta_states, sta);
>   
> -	/*
> -	 * Nothing to do here netlink-wise as we can't receive any data
> -	 * frames until after association anyway.  We do need to add a
> -	 * timeout for the authentication and possibly the kernel could
> -	 * handle that if we registered the STA with NEW_STATION now (TODO)
> -	 */
>   
> -done:
> -	ap_auth_reply(ap, from, 0);
> +have_sta:
> +	if (sta->akm_suite == IE_RSN_AKM_SUITE_SAE_SHA256) {
> +		auth_proto_rx_authenticate(sta->auth_proto, (const uint8_t *)hdr,
> +					   body + body_len - (void *) hdr);

nit: This line is also > 80 chars.

To be more future proof, maybe:

if (sta->auth_proto) {
	auth_proto_rx_authenticate(...);
	return;
}

/* comment */
ap_auth_reply(...);

> +	} else {
> +		/*
> +		 * Nothing to do here netlink-wise as we can't receive any data
> +		 * frames until after association anyway.  We do need to add a
> +		 * timeout for the authentication and possibly the kernel could
> +		 * handle that if we registered the STA with NEW_STATION now (TODO)
> +		 */
> +		ap_auth_reply(ap, from, 0);
> +	}
>   }
>   
>   /* 802.11-2016 9.3.3.13 (frame format), 802.11-2016 11.3.4.5 (MLME/SME) */

Regards,
-Denis
diff mbox series

Patch

diff --git a/src/ap.c b/src/ap.c
index cd253ce3..ec27180e 100644
--- a/src/ap.c
+++ b/src/ap.c
@@ -59,6 +59,8 @@ 
 #include "src/diagnostic.h"
 #include "src/band.h"
 #include "src/common.h"
+#include "src/sae.h"
+#include "src/auth-proto.h"
 
 struct ap_state {
 	struct netdev *netdev;
@@ -132,6 +134,7 @@  struct sta_state {
 	uint8_t *assoc_ies;
 	size_t assoc_ies_len;
 	uint8_t *assoc_rsne;
+	struct auth_proto *auth_proto;
 	enum ie_rsn_akm_suite akm_suite;
 	struct eapol_sm *sm;
 	struct handshake_state *hs;
@@ -2595,6 +2598,38 @@  static void ap_auth_reply(struct ap_state *ap, const uint8_t *dest,
 				ap_auth_reply_cb, NULL);
 }
 
+static void sae_auth_reply(const uint8_t *data, size_t len, void *user_data)
+{
+	struct sta_state *sta = (struct sta_state *)user_data;
+	struct ap_state *ap = (struct ap_state *)sta->ap;
+	const uint8_t *addr = netdev_get_address(ap->netdev);
+	uint8_t sae_buf[512];
+	struct mmpdu_header *mpdu = (struct mmpdu_header *) sae_buf;
+	struct mmpdu_authentication *auth;
+
+	if (L_WARN_ON(26 + len > sizeof(sae_buf)))
+		return;
+
+	memset(mpdu, 0, sizeof(*mpdu));
+
+	/* Header */
+	mpdu->fc.protocol_version = 0;
+	mpdu->fc.type = MPDU_TYPE_MANAGEMENT;
+	mpdu->fc.subtype = MPDU_MANAGEMENT_SUBTYPE_AUTHENTICATION;
+	memcpy(mpdu->address_1, sta->addr, 6);	/* DA */
+	memcpy(mpdu->address_2, addr, 6);	/* SA */
+	memcpy(mpdu->address_3, addr, 6);	/* BSSID */
+
+	/* Authentication body */
+	auth = (void *) mmpdu_body(mpdu);
+	auth->algorithm = L_CPU_TO_LE16(MMPDU_AUTH_ALGO_SAE);
+
+	/* SAE elements */
+	memcpy(sae_buf + 26, data, len);
+	ap_send_mgmt_frame(ap, mpdu, 26 + len,
+				ap_auth_reply_cb, NULL);
+}
+
 /*
  * 802.11-2016 9.3.3.12 (frame format), 802.11-2016 11.3.4.3 and
  * 802.11-2016 12.3.3.2 (MLME/SME)
@@ -2665,7 +2700,7 @@  static void ap_auth_cb(const struct mmpdu_header *hdr, const void *body,
 	 * than State 1."
 	 */
 	if (sta)
-		goto done;
+		goto have_sta;
 
 	/*
 	 * Per 12.3.3.2.3 with Open System the state change is immediate,
@@ -2680,18 +2715,32 @@  static void ap_auth_cb(const struct mmpdu_header *hdr, const void *body,
 		ap->sta_states = l_queue_new();
 
 	sta->akm_suite = akm_suite;
+	if (sta->akm_suite == IE_RSN_AKM_SUITE_SAE_SHA256) {
+		sta->hs = netdev_handshake_state_new(sta->ap->netdev);
+		handshake_state_set_authenticator(sta->hs, true);
+		handshake_state_set_passphrase(sta->hs, ap->passphrase);
+		handshake_state_set_supplicant_address(sta->hs, sta->addr);
+		handshake_state_set_authenticator_address(sta->hs, bssid);
+
+		sta->auth_proto = sae_sm_new(sta->hs, sae_auth_reply, NULL, sta);
+	}
 
 	l_queue_push_tail(ap->sta_states, sta);
 
-	/*
-	 * Nothing to do here netlink-wise as we can't receive any data
-	 * frames until after association anyway.  We do need to add a
-	 * timeout for the authentication and possibly the kernel could
-	 * handle that if we registered the STA with NEW_STATION now (TODO)
-	 */
 
-done:
-	ap_auth_reply(ap, from, 0);
+have_sta:
+	if (sta->akm_suite == IE_RSN_AKM_SUITE_SAE_SHA256) {
+		auth_proto_rx_authenticate(sta->auth_proto, (const uint8_t *)hdr,
+					   body + body_len - (void *) hdr);
+	} else {
+		/*
+		 * Nothing to do here netlink-wise as we can't receive any data
+		 * frames until after association anyway.  We do need to add a
+		 * timeout for the authentication and possibly the kernel could
+		 * handle that if we registered the STA with NEW_STATION now (TODO)
+		 */
+		ap_auth_reply(ap, from, 0);
+	}
 }
 
 /* 802.11-2016 9.3.3.13 (frame format), 802.11-2016 11.3.4.5 (MLME/SME) */