Defer passphrase-to-PSK hashing out of 802.11 authentication ACL check

Hashing takes quite some time (can be about one second on a low-power
CPU for each passphrase provided), so hostapd can easily hit the 900 ms
Wi-Fi client authentication deadline (mac80211 uses 3x 300 ms). This can
be fixed by storing the passphrase instead of PSK with the STA and defer
the hashing into the WPA/RSN 4-way handshake, when enumerating all PSKs.

This applies for the case where a RADIUS server is used to store the
per-STA passphrases and this passphrase is delivered as part of the MAC
ACL check during IEEE 802.11 Authentication frame processing.

Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
This commit is contained in:
Michael Braun 2016-02-24 12:53:36 +01:00 committed by Jouni Malinen
parent cc9c805a51
commit f8e09bc57e
3 changed files with 17 additions and 10 deletions

View file

@ -128,9 +128,12 @@ struct hostapd_vlan {
}; };
#define PMK_LEN 32 #define PMK_LEN 32
#define MAX_PASSPHRASE_LEN 63
struct hostapd_sta_wpa_psk_short { struct hostapd_sta_wpa_psk_short {
struct hostapd_sta_wpa_psk_short *next; struct hostapd_sta_wpa_psk_short *next;
unsigned int is_passphrase:1;
u8 psk[PMK_LEN]; u8 psk[PMK_LEN];
char passphrase[MAX_PASSPHRASE_LEN + 1];
}; };
struct hostapd_wpa_psk { struct hostapd_wpa_psk {

View file

@ -15,7 +15,6 @@
#include "utils/common.h" #include "utils/common.h"
#include "utils/eloop.h" #include "utils/eloop.h"
#include "crypto/sha1.h"
#include "radius/radius.h" #include "radius/radius.h"
#include "radius/radius_client.h" #include "radius/radius_client.h"
#include "hostapd.h" #include "hostapd.h"
@ -443,7 +442,7 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
struct hostapd_cached_radius_acl *cache) struct hostapd_cached_radius_acl *cache)
{ {
int passphraselen; int passphraselen;
char *passphrase, *strpassphrase; char *passphrase;
size_t i; size_t i;
struct hostapd_sta_wpa_psk_short *psk; struct hostapd_sta_wpa_psk_short *psk;
@ -464,19 +463,16 @@ static void decode_tunnel_passwords(struct hostapd_data *hapd,
* passphrase does not contain the NULL termination. * passphrase does not contain the NULL termination.
* Add it here as pbkdf2_sha1() requires it. * Add it here as pbkdf2_sha1() requires it.
*/ */
strpassphrase = os_zalloc(passphraselen + 1);
psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short)); psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
if (strpassphrase && psk) { if (psk) {
os_memcpy(strpassphrase, passphrase, passphraselen); if (passphraselen > MAX_PASSPHRASE_LEN)
pbkdf2_sha1(strpassphrase, passphraselen = MAX_PASSPHRASE_LEN;
hapd->conf->ssid.ssid, os_memcpy(psk->passphrase, passphrase, passphraselen);
hapd->conf->ssid.ssid_len, 4096, psk->is_passphrase = 1;
psk->psk, PMK_LEN);
psk->next = cache->psk; psk->next = cache->psk;
cache->psk = psk; cache->psk = psk;
psk = NULL; psk = NULL;
} }
os_free(strpassphrase);
os_free(psk); os_free(psk);
os_free(passphrase); os_free(passphrase);
} }

View file

@ -12,6 +12,7 @@
#include "common/ieee802_11_defs.h" #include "common/ieee802_11_defs.h"
#include "common/sae.h" #include "common/sae.h"
#include "common/wpa_ctrl.h" #include "common/wpa_ctrl.h"
#include "crypto/sha1.h"
#include "eapol_auth/eapol_auth_sm.h" #include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h" #include "eapol_auth/eapol_auth_sm_i.h"
#include "eap_server/eap.h" #include "eap_server/eap.h"
@ -246,6 +247,13 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
struct hostapd_sta_wpa_psk_short *pos; struct hostapd_sta_wpa_psk_short *pos;
psk = sta->psk->psk; psk = sta->psk->psk;
for (pos = sta->psk; pos; pos = pos->next) { for (pos = sta->psk; pos; pos = pos->next) {
if (pos->is_passphrase) {
pbkdf2_sha1(pos->passphrase,
hapd->conf->ssid.ssid,
hapd->conf->ssid.ssid_len, 4096,
pos->psk, PMK_LEN);
pos->is_passphrase = 0;
}
if (pos->psk == prev_psk) { if (pos->psk == prev_psk) {
psk = pos->next ? pos->next->psk : NULL; psk = pos->next ? pos->next->psk : NULL;
break; break;