aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJouni Malinen <jouni@codeaurora.org>2019-03-01 20:05:52 (GMT)
committerJouni Malinen <j@w1.fi>2019-03-06 11:07:03 (GMT)
commita9af1da0b544faecf8cc03ec2f418db1dc9ced43 (patch)
treee10650054438f9f768f84b1c9cf64b9277d7eec1 /src
parentff9f40aee1e405b40bd9ffdf1f5e4edd79f54b19 (diff)
downloadhostap-a9af1da0b544faecf8cc03ec2f418db1dc9ced43.zip
hostap-a9af1da0b544faecf8cc03ec2f418db1dc9ced43.tar.gz
hostap-a9af1da0b544faecf8cc03ec2f418db1dc9ced43.tar.bz2
SAE: Enforce single use for anti-clogging tokens
Add a 16-bit token index into the anti-clogging token. This can be used to enforce only a single use of each issued anti-clogging token request. The token value is now token-index | last-30-octets-of(HMAC-SHA256(sae_token_key, STA-MAC-address | token-index)), i.e., the first two octets of the SHA256 hash value are replaced with the token-index and token-index itself is protected as part of the HMAC context data. Track the used 16-bit token index values and accept received tokens only if they use an index value that has been requested, but has not yet been used. This makes it a bit more difficult for an attacker to perform DoS attacks against the heavy CPU operations needed for processing SAE commit since the attacker cannot simply replay the same frame multiple times and instead, needs to request each token separately. While this does not add significant extra processing/CPU need for the attacker, this can be helpful in combination with the queued processing of SAE commit messages in enforcing more delay during flooding of SAE commit messages since the new anti-clogging token values are not returned before the new message goes through the processing queue. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Diffstat (limited to 'src')
-rw-r--r--src/ap/hostapd.h2
-rw-r--r--src/ap/ieee802_11.c66
2 files changed, 62 insertions, 6 deletions
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 733f3f2..b8637c4 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -314,6 +314,8 @@ struct hostapd_data {
/** Key used for generating SAE anti-clogging tokens */
u8 sae_token_key[8];
struct os_reltime last_sae_token_key_update;
+ u16 sae_token_idx;
+ u16 sae_pending_token_idx[256];
int dot11RSNASAERetransPeriod; /* msec */
struct dl_list sae_commit_queue; /* struct hostapd_sae_commit_queue */
#endif /* CONFIG_SAE */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 0da1d42..afa17db 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -532,18 +532,47 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd)
}
+static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr)
+{
+ u8 hash[SHA256_MAC_LEN];
+
+ hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
+ addr, ETH_ALEN, hash);
+ return hash[0];
+}
+
+
static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
const u8 *token, size_t token_len)
{
u8 mac[SHA256_MAC_LEN];
+ const u8 *addrs[2];
+ size_t len[2];
+ u16 token_idx;
+ u8 idx;
if (token_len != SHA256_MAC_LEN)
return -1;
- if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
- addr, ETH_ALEN, mac) < 0 ||
- os_memcmp_const(token, mac, SHA256_MAC_LEN) != 0)
+ idx = sae_token_hash(hapd, addr);
+ token_idx = hapd->sae_pending_token_idx[idx];
+ if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
+ wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from "
+ MACSTR " - token_idx 0x%04x, expected 0x%04x",
+ MAC2STR(addr), WPA_GET_BE16(token), token_idx);
+ return -1;
+ }
+
+ addrs[0] = addr;
+ len[0] = ETH_ALEN;
+ addrs[1] = token;
+ len[1] = 2;
+ if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key),
+ 2, addrs, len, mac) < 0 ||
+ os_memcmp_const(token + 2, &mac[2], SHA256_MAC_LEN - 2) != 0)
return -1;
+ hapd->sae_pending_token_idx[idx] = 0; /* invalidate used token */
+
return 0;
}
@@ -554,16 +583,25 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
struct wpabuf *buf;
u8 *token;
struct os_reltime now;
+ u8 idx[2];
+ const u8 *addrs[2];
+ size_t len[2];
+ u8 p_idx;
+ u16 token_idx;
os_get_reltime(&now);
if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
- os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60)) {
+ os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60) ||
+ hapd->sae_token_idx == 0xffff) {
if (random_get_bytes(hapd->sae_token_key,
sizeof(hapd->sae_token_key)) < 0)
return NULL;
wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
hapd->sae_token_key, sizeof(hapd->sae_token_key));
hapd->last_sae_token_key_update = now;
+ hapd->sae_token_idx = 0;
+ os_memset(hapd->sae_pending_token_idx, 0,
+ sizeof(hapd->sae_pending_token_idx));
}
buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
@@ -572,9 +610,25 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
+ p_idx = sae_token_hash(hapd, addr);
+ token_idx = hapd->sae_pending_token_idx[p_idx];
+ if (!token_idx) {
+ hapd->sae_token_idx++;
+ token_idx = hapd->sae_token_idx;
+ hapd->sae_pending_token_idx[p_idx] = token_idx;
+ }
+ WPA_PUT_BE16(idx, token_idx);
token = wpabuf_put(buf, SHA256_MAC_LEN);
- hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
- addr, ETH_ALEN, token);
+ addrs[0] = addr;
+ len[0] = ETH_ALEN;
+ addrs[1] = idx;
+ len[1] = sizeof(idx);
+ if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key),
+ 2, addrs, len, token) < 0) {
+ wpabuf_free(buf);
+ return NULL;
+ }
+ WPA_PUT_BE16(token, token_idx);
return buf;
}