[PATCH 30/44] Move password hashing out of 802.11 authentication path

michael-dev at fami-braun.de michael-dev at fami-braun.de
Wed Feb 24 03:53:36 PST 2016


From: Michael Braun <michael-dev at fami-braun.de>

Hashing takes quite some time (about 1s here for each passphrase provided),
so hostapd easily hits the 900ms Wi-Fi client authentication deadline
(mac80211 uses 3x 300ms). This can be fixed by storing the passphrase with
the sta (instead of psk) and defer the hashing into the WPA handshake, when
enumerating all PSKs.

Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
 src/ap/ap_config.h       |  3 +++
 src/ap/ieee802_11_auth.c | 19 +++++++++----------
 src/ap/wpa_auth_glue.c   |  8 ++++++++
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index a2b36c3..9b09c16 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -131,9 +131,12 @@ struct hostapd_vlan {
 };
 
 #define PMK_LEN 32
+#define PASSPHRASE_LEN (2 * PMK_LEN)
 struct hostapd_sta_wpa_psk_short {
 	struct hostapd_sta_wpa_psk_short *next;
+	int ispassphrase;
 	u8 psk[PMK_LEN];
+	char passphrase[PASSPHRASE_LEN];
 };
 
 struct hostapd_wpa_psk {
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index ebc971c..e007a73 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -15,7 +15,6 @@
 
 #include "utils/common.h"
 #include "utils/eloop.h"
-#include "crypto/sha1.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
 #include "hostapd.h"
@@ -454,7 +453,7 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
 				    struct hostapd_cached_radius_acl *cache)
 {
 	int passphraselen;
-	char *passphrase, *strpassphrase;
+	char *passphrase;
 	size_t i;
 	struct hostapd_sta_wpa_psk_short *psk;
 
@@ -475,19 +474,19 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
 		 * passphrase does not contain the NULL termination.
 		 * Add it here as pbkdf2_sha1() requires it.
 		 */
-		strpassphrase = os_zalloc(passphraselen + 1);
 		psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
-		if (strpassphrase && psk) {
-			os_memcpy(strpassphrase, passphrase, passphraselen);
-			pbkdf2_sha1(strpassphrase,
-				    hapd->conf->ssid.ssid,
-				    hapd->conf->ssid.ssid_len, 4096,
-				    psk->psk, PMK_LEN);
+		if (psk) {
+			if (passphraselen > PASSPHRASE_LEN - 1)
+				os_memcpy(psk->passphrase, passphrase,
+					  PASSPHRASE_LEN - 1);
+			else
+				os_memcpy(psk->passphrase, passphrase,
+					  passphraselen);
+			psk->ispassphrase = 1;
 			psk->next = cache->psk;
 			cache->psk = psk;
 			psk = NULL;
 		}
-		os_free(strpassphrase);
 		os_free(psk);
 		os_free(passphrase);
 	}
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index e7fc46a..116c4fb 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -27,6 +27,7 @@
 #include "ap_config.h"
 #include "wpa_auth.h"
 #include "wpa_auth_glue.h"
+#include "crypto/sha1.h"
 #include <stdlib.h>
 
 #ifdef CONFIG_IEEE80211R
@@ -260,6 +261,13 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
 		struct hostapd_sta_wpa_psk_short *pos;
 		psk = sta->psk->psk;
 		for (pos = sta->psk; pos; pos = pos->next) {
+			if (pos->ispassphrase) {
+				pbkdf2_sha1(pos->passphrase,
+					    hapd->conf->ssid.ssid,
+					    hapd->conf->ssid.ssid_len, 4096,
+					    pos->psk, PMK_LEN);
+				pos->ispassphrase = 0;
+			}
 			if (pos->psk == prev_psk) {
 				psk = pos->next ? pos->next->psk : NULL;
 				break;
-- 
1.9.1




More information about the Hostap mailing list