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 MAX_PASSPHRASE_LEN 63
struct hostapd_sta_wpa_psk_short {
struct hostapd_sta_wpa_psk_short *next;
unsigned int is_passphrase:1;
u8 psk[PMK_LEN];
char passphrase[MAX_PASSPHRASE_LEN + 1];
};
struct hostapd_wpa_psk {

View file

@ -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"
@ -443,7 +442,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;
@ -464,19 +463,16 @@ 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 > MAX_PASSPHRASE_LEN)
passphraselen = MAX_PASSPHRASE_LEN;
os_memcpy(psk->passphrase, passphrase, passphraselen);
psk->is_passphrase = 1;
psk->next = cache->psk;
cache->psk = psk;
psk = NULL;
}
os_free(strpassphrase);
os_free(psk);
os_free(passphrase);
}

View file

@ -12,6 +12,7 @@
#include "common/ieee802_11_defs.h"
#include "common/sae.h"
#include "common/wpa_ctrl.h"
#include "crypto/sha1.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.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;
psk = sta->psk->psk;
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) {
psk = pos->next ? pos->next->psk : NULL;
break;