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:
parent
cc9c805a51
commit
f8e09bc57e
3 changed files with 17 additions and 10 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue