diff mbox

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

Message ID 1456314830-12935-31-git-send-email-michael-dev@fami-braun.de
State Accepted
Headers show

Commit Message

michael-dev Feb. 24, 2016, 11:53 a.m. UTC
From: Michael Braun <michael-dev@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@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 mbox

Patch

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;