[PATCH 1/2] Fix external passwords with 4-way handshake offloading
Ben Wolsieffer
benwolsieffer at gmail.com
Fri Sep 16 21:21:01 PDT 2022
Passphrases/PSKs from external password databases were ignored if 4-way
handshake offloading was supported by the driver. This patch splits the PSK
loading functionality into a separate function and calls if to get the PSK for
handshake offloading.
I tested connecting to a WPA2-PSK network with both inline and external
passphrases, using the iwlwifi and brcmfmac drivers.
Signed-off-by: Ben Wolsieffer <benwolsieffer at gmail.com>
---
wpa_supplicant/wpa_supplicant.c | 214 +++++++++++++++++---------------
1 file changed, 113 insertions(+), 101 deletions(-)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index e085391e2..f4dfd1382 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1346,6 +1346,106 @@ void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
wpas_get_ssid_pmf(wpa_s, ssid));
}
+/**
+ * wpa_supplicant_get_psk - Get PSK from config or external database
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bss: Scan results for the selected BSS, or %NULL if not available
+ * @ssid: Configuration data for the selected network
+ * @psk: Buffer for the PSK
+ *
+ * This function obtains the PSK for a network, either included inline in the
+ * config or retrieved from an external database.
+ */
+static int wpa_supplicant_get_psk(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, struct wpa_ssid *ssid,
+ u8 *psk)
+{
+ if (ssid->psk_set) {
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)", ssid->psk,
+ PMK_LEN);
+ os_memcpy(psk, ssid->psk, PMK_LEN);
+ return 0;
+ }
+
+#ifndef CONFIG_NO_PBKDF2
+ if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) {
+ if (pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
+ 4096, psk, PMK_LEN) != 0) {
+ wpa_msg(wpa_s, MSG_WARNING, "Error in pbkdf2_sha1()");
+ return -1;
+ }
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
+ psk, PMK_LEN);
+ return 0;
+ }
+#endif /* CONFIG_NO_PBKDF2 */
+
+#ifdef CONFIG_EXT_PASSWORD
+ if (ssid->ext_psk) {
+ struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
+ ssid->ext_psk);
+ char pw_str[64 + 1];
+
+ if (pw == NULL) {
+ wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK found from "
+ "external storage");
+ return -1;
+ }
+
+ if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
+ wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected PSK "
+ "length %d in external storage",
+ (int) wpabuf_len(pw));
+ ext_password_free(pw);
+ return -1;
+ }
+
+ os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
+ pw_str[wpabuf_len(pw)] = '\0';
+
+#ifndef CONFIG_NO_PBKDF2
+ if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
+ {
+ if (pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
+ 4096, psk, PMK_LEN) != 0) {
+ wpa_msg(wpa_s, MSG_WARNING,
+ "Error in pbkdf2_sha1()");
+ ext_password_free(pw);
+ return -1;
+ }
+ os_memset(pw_str, 0, sizeof(pw_str));
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external "
+ "passphrase)",
+ psk, PMK_LEN);
+ } else
+#endif /* CONFIG_NO_PBKDF2 */
+ if (wpabuf_len(pw) == 2 * PMK_LEN) {
+ if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
+ wpa_msg(wpa_s, MSG_INFO, "EXT PW: Invalid PSK "
+ "hex string");
+ os_memset(pw_str, 0, sizeof(pw_str));
+ ext_password_free(pw);
+ return -1;
+ }
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (from external PSK)",
+ psk, PMK_LEN);
+ } else {
+ wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable PSK "
+ "available");
+ os_memset(pw_str, 0, sizeof(pw_str));
+ ext_password_free(pw);
+ return -1;
+ }
+
+ os_memset(pw_str, 0, sizeof(pw_str));
+ ext_password_free(pw);
+
+ return 0;
+ }
+#endif /* CONFIG_EXT_PASSWORD */
+
+ return -1;
+}
static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
@@ -1884,109 +1984,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_PSK_SHA256)) == 0;
- if (ssid->psk_set && !sae_only) {
- wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)",
- ssid->psk, PMK_LEN);
- wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
- NULL);
- psk_set = 1;
- }
-
- if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
- (ssid->sae_password || ssid->passphrase))
- psk_set = 1;
-
-#ifndef CONFIG_NO_PBKDF2
- if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
- ssid->passphrase && !sae_only) {
- u8 psk[PMK_LEN];
-
- if (pbkdf2_sha1(ssid->passphrase, bss->ssid,
- bss->ssid_len,
- 4096, psk, PMK_LEN) != 0) {
- wpa_msg(wpa_s, MSG_WARNING,
- "Error in pbkdf2_sha1()");
- return -1;
- }
- wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
- psk, PMK_LEN);
- wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
- psk_set = 1;
- os_memset(psk, 0, sizeof(psk));
- }
-#endif /* CONFIG_NO_PBKDF2 */
-#ifdef CONFIG_EXT_PASSWORD
- if (ssid->ext_psk && !sae_only) {
- struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
- ssid->ext_psk);
- char pw_str[64 + 1];
+ if (!sae_only) {
u8 psk[PMK_LEN];
-
- if (pw == NULL) {
- wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
- "found from external storage");
- return -1;
- }
-
- if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
- wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
- "PSK length %d in external storage",
- (int) wpabuf_len(pw));
- ext_password_free(pw);
- return -1;
- }
-
- os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
- pw_str[wpabuf_len(pw)] = '\0';
-
-#ifndef CONFIG_NO_PBKDF2
- if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
- {
- if (pbkdf2_sha1(pw_str, bss->ssid,
- bss->ssid_len,
- 4096, psk, PMK_LEN) != 0) {
- wpa_msg(wpa_s, MSG_WARNING,
- "Error in pbkdf2_sha1()");
- ext_password_free(pw);
- return -1;
- }
- os_memset(pw_str, 0, sizeof(pw_str));
- wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
- "external passphrase)",
- psk, PMK_LEN);
- wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
- NULL);
- psk_set = 1;
- os_memset(psk, 0, sizeof(psk));
- } else
-#endif /* CONFIG_NO_PBKDF2 */
- if (wpabuf_len(pw) == 2 * PMK_LEN) {
- if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
- wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
- "Invalid PSK hex string");
- os_memset(pw_str, 0, sizeof(pw_str));
- ext_password_free(pw);
- return -1;
- }
- wpa_hexdump_key(MSG_MSGDUMP,
- "PSK (from external PSK)",
- psk, PMK_LEN);
+ if (wpa_supplicant_get_psk(wpa_s, bss, ssid,
+ psk) >= 0) {
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
NULL);
psk_set = 1;
- os_memset(psk, 0, sizeof(psk));
- } else {
- wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
- "PSK available");
- os_memset(pw_str, 0, sizeof(pw_str));
- ext_password_free(pw);
- return -1;
}
-
- os_memset(pw_str, 0, sizeof(pw_str));
- ext_password_free(pw);
+ os_memset(psk, 0, sizeof(psk));
}
-#endif /* CONFIG_EXT_PASSWORD */
+
+ if (wpa_key_mgmt_sae(ssid->key_mgmt) &&
+ (ssid->sae_password || ssid->passphrase))
+ psk_set = 1;
if (!psk_set) {
wpa_msg(wpa_s, MSG_INFO,
@@ -3754,6 +3765,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
int use_crypt, ret, bssid_changed;
unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
struct wpa_driver_associate_params params;
+ u8 psk[PMK_LEN];
#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL)
int wep_keys_set = 0;
#endif /* CONFIG_WEP || IEEE8021X_EAPOL */
@@ -4046,8 +4058,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
(params.allowed_key_mgmts &
(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
params.passphrase = ssid->passphrase;
- if (ssid->psk_set)
- params.psk = ssid->psk;
+ if (wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) >= 0)
+ params.psk = psk;
}
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) &&
@@ -4070,8 +4082,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
- ssid->psk_set)
- params.psk = ssid->psk;
+ wpa_supplicant_get_psk(wpa_s, bss, ssid, psk) >= 0)
+ params.psk = psk;
}
params.drop_unencrypted = use_crypt;
--
2.37.2
More information about the Hostap
mailing list