diff mbox series

[v3,1/4] network: add support for SAE password identifiers

Message ID 20231207140049.2614514-1-prestwoj@gmail.com (mailing list archive)
State New
Headers show
Series [v3,1/4] network: add support for SAE password identifiers | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
prestwoj/iwd-alpine-ci-fetch success Fetch PR
prestwoj/iwd-ci-fetch success Fetch PR
prestwoj/iwd-ci-gitlint success GitLint
prestwoj/iwd-ci-makedistcheck success Make Distcheck
prestwoj/iwd-alpine-ci-makedistcheck success Make Distcheck
prestwoj/iwd-ci-build success Build - Configure
prestwoj/iwd-alpine-ci-build success Build - Configure
prestwoj/iwd-ci-makecheckvalgrind success Make Check w/Valgrind
prestwoj/iwd-ci-makecheck success Make Check
prestwoj/iwd-ci-clang success clang PASS
prestwoj/iwd-alpine-ci-makecheckvalgrind success Make Check w/Valgrind
prestwoj/iwd-alpine-ci-makecheck success Make Check
prestwoj/iwd-ci-incremental_build success Incremental Build with patches
prestwoj/iwd-alpine-ci-incremental_build success Incremental Build with patches
prestwoj/iwd-ci-testrunner success test-runner PASS

Commit Message

James Prestwood Dec. 7, 2023, 2 p.m. UTC
Adds a new network profile setting [Security].PasswordIdentifier.
When set (and the BSS enables SAE password identifiers) the network
and handshake object will read this and use it for the SAE
exchange.

Loading the PSK will fail if:
 - there is no password identifier set and the BSS sets the
   "exclusive" bit.
 - there is a password identifier set and the BSS does not set
   the "in-use" bit.
---
 src/network.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)

v3:
 * fix outdated commit description

Comments

Denis Kenzior Dec. 13, 2023, 4:05 p.m. UTC | #1
Hi James,

On 12/7/23 08:00, James Prestwood wrote:
> Adds a new network profile setting [Security].PasswordIdentifier.
> When set (and the BSS enables SAE password identifiers) the network
> and handshake object will read this and use it for the SAE
> exchange.
> 
> Loading the PSK will fail if:
>   - there is no password identifier set and the BSS sets the
>     "exclusive" bit.
>   - there is a password identifier set and the BSS does not set
>     the "in-use" bit.
> ---
>   src/network.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 48 insertions(+), 1 deletion(-)
> 
> v3:
>   * fix outdated commit description
> 
> diff --git a/src/network.c b/src/network.c
> index 79f964b2..70a5434b 100644
> --- a/src/network.c
> +++ b/src/network.c

<snip>

> @@ -641,6 +657,31 @@ static int network_load_psk(struct network *network, struct scan_bss *bss)
>   		psk_len = 0;
>   	}
>   
> +	if (is_sae) {
> +		/*
> +		 * Fail if:
> +		 *   - the BSS exclusively uses password IDs and the profile
> +		 *     does not have one set.
> +		 *   - the BSS does not use password IDs and the profile has
> +		 *     one set.
> +		 *
> +		 * In theory you could have a network with a mix of BSS's that
> +		 * use IDs and those that don't, but this is a strange
> +		 * configuration (arguably broken).
> +		 */
> +		if (bss->sae_pw_id_exclusive && !password_id) {
> +			l_error("[Security].PasswordIdentifier is not set but "
> +				"BSS requires SAE password identifiers");
> +			return -ENOKEY;
> +		}
> +
> +		if (!bss->sae_pw_id_used && password_id) {
> +			l_debug("[Security].PasswordIdentifier set but BSS "
> +				"does not not use password identifiers");
> +			return -ENOKEY;
> +		}

So I thought the plan was to check this at handshake build time, not here?

> +	}
> +
>   	/* PSK can be generated from the passphrase but not the other way */
>   	if (!psk || is_sae) {
>   		if (!passphrase)

Regards,
-Denis
diff mbox series

Patch

diff --git a/src/network.c b/src/network.c
index 79f964b2..70a5434b 100644
--- a/src/network.c
+++ b/src/network.c
@@ -70,6 +70,7 @@  struct network {
 	struct network_info *info;
 	unsigned char *psk;
 	char *passphrase;
+	char *password_identifier;
 	struct l_ecc_point *sae_pt_19; /* SAE PT for Group 19 */
 	struct l_ecc_point *sae_pt_20; /* SAE PT for Group 20 */
 	unsigned int agent_request;
@@ -124,6 +125,13 @@  static void network_reset_passphrase(struct network *network)
 		network->passphrase = NULL;
 	}
 
+	if (network->password_identifier) {
+		explicit_bzero(network->password_identifier,
+				strlen(network->password_identifier));
+		l_free(network->password_identifier);
+		network->password_identifier = NULL;
+	}
+
 	if (network->sae_pt_19) {
 		l_ecc_point_free(network->sae_pt_19);
 		network->sae_pt_19 = NULL;
@@ -317,7 +325,8 @@  static struct l_ecc_point *network_generate_sae_pt(struct network *network,
 	l_debug("Generating PT for Group %u", group);
 
 	pt = crypto_derive_sae_pt_ecc(group, network->ssid,
-						network->passphrase, NULL);
+						network->passphrase,
+						network->password_identifier);
 	if (!pt)
 		l_warn("SAE PT generation for Group %u failed", group);
 
@@ -462,6 +471,10 @@  static int network_set_handshake_secrets_psk(struct network *network,
 
 		handshake_state_set_passphrase(hs, network->passphrase);
 
+		if (network->password_identifier)
+			handshake_state_set_password_identifier(hs,
+						network->password_identifier);
+
 		if (ie_rsnxe_capable(hs->authenticator_rsnxe,
 							IE_RSNX_SAE_H2E)) {
 			l_debug("Authenticator is SAE H2E capable");
@@ -631,6 +644,9 @@  static int network_load_psk(struct network *network, struct scan_bss *bss)
 	_auto_(l_free) char *passphrase =
 			l_settings_get_string(network->settings,
 						"Security", "Passphrase");
+	_auto_(l_free) char *password_id =
+			l_settings_get_string(network->settings, "Security",
+						"PasswordIdentifier");
 	_auto_(l_free) char *path =
 		storage_get_network_file_path(security, ssid);
 
@@ -641,6 +657,31 @@  static int network_load_psk(struct network *network, struct scan_bss *bss)
 		psk_len = 0;
 	}
 
+	if (is_sae) {
+		/*
+		 * Fail if:
+		 *   - the BSS exclusively uses password IDs and the profile
+		 *     does not have one set.
+		 *   - the BSS does not use password IDs and the profile has
+		 *     one set.
+		 *
+		 * In theory you could have a network with a mix of BSS's that
+		 * use IDs and those that don't, but this is a strange
+		 * configuration (arguably broken).
+		 */
+		if (bss->sae_pw_id_exclusive && !password_id) {
+			l_error("[Security].PasswordIdentifier is not set but "
+				"BSS requires SAE password identifiers");
+			return -ENOKEY;
+		}
+
+		if (!bss->sae_pw_id_used && password_id) {
+			l_debug("[Security].PasswordIdentifier set but BSS "
+				"does not not use password identifiers");
+			return -ENOKEY;
+		}
+	}
+
 	/* PSK can be generated from the passphrase but not the other way */
 	if (!psk || is_sae) {
 		if (!passphrase)
@@ -655,6 +696,7 @@  static int network_load_psk(struct network *network, struct scan_bss *bss)
 	network_reset_passphrase(network);
 	network_reset_psk(network);
 	network->passphrase = l_steal_ptr(passphrase);
+	network->password_identifier = l_steal_ptr(password_id);
 
 	if (network_settings_load_pt_ecc(network, path,
 						19, &network->sae_pt_19) > 0)
@@ -726,6 +768,11 @@  static void network_settings_save(struct network *network,
 		l_settings_set_string(settings, "Security", "Passphrase",
 					network->passphrase);
 
+	if (network->password_identifier)
+		l_settings_set_string(settings, "Security",
+					"PasswordIdentifier",
+					network->password_identifier);
+
 	if (network->sae_pt_19)
 		network_settings_save_sae_pt_ecc(settings, network->sae_pt_19);