SAE: Verify that own/peer commit-scalar and COMMIT-ELEMENT are different
This check explicitly for reflection attack and stops authentication immediately if that is detected instead of continuing to the following 4-way handshake that would fail due to the attacker not knowing the key from the SAE exchange. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
4e7e68890a
commit
6a58444d27
4 changed files with 47 additions and 3 deletions
|
@ -769,6 +769,12 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
((const u8 *) mgmt) + len -
|
||||
mgmt->u.auth.variable, &token,
|
||||
&token_len, hapd->conf->sae_groups);
|
||||
if (resp == SAE_SILENTLY_DISCARD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"SAE: Drop commit message from " MACSTR " due to reflection attack",
|
||||
MAC2STR(sta->addr));
|
||||
return;
|
||||
}
|
||||
if (token && check_sae_token(hapd, sta->addr, token, token_len)
|
||||
< 0) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
|
||||
|
|
|
@ -915,7 +915,34 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
|
|||
return res;
|
||||
|
||||
/* commit-element */
|
||||
return sae_parse_commit_element(sae, pos, end);
|
||||
res = sae_parse_commit_element(sae, pos, end);
|
||||
if (res != WLAN_STATUS_SUCCESS)
|
||||
return res;
|
||||
|
||||
/*
|
||||
* Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
|
||||
* the values we sent which would be evidence of a reflection attack.
|
||||
*/
|
||||
if (!sae->tmp->own_commit_scalar ||
|
||||
crypto_bignum_cmp(sae->tmp->own_commit_scalar,
|
||||
sae->peer_commit_scalar) != 0 ||
|
||||
(sae->tmp->dh &&
|
||||
(!sae->tmp->own_commit_element_ffc ||
|
||||
crypto_bignum_cmp(sae->tmp->own_commit_element_ffc,
|
||||
sae->tmp->peer_commit_element_ffc) != 0)) ||
|
||||
(sae->tmp->ec &&
|
||||
(!sae->tmp->own_commit_element_ecc ||
|
||||
crypto_ec_point_cmp(sae->tmp->ec,
|
||||
sae->tmp->own_commit_element_ecc,
|
||||
sae->tmp->peer_commit_element_ecc) != 0)))
|
||||
return WLAN_STATUS_SUCCESS; /* scalars/elements are different */
|
||||
|
||||
/*
|
||||
* This is a reflection attack - return special value to trigger caller
|
||||
* to silently discard the frame instead of replying with a specific
|
||||
* status code.
|
||||
*/
|
||||
return SAE_SILENTLY_DISCARD;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN)
|
||||
#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_PRIME_LEN)
|
||||
|
||||
/* Special value returned by sae_parse_commit() */
|
||||
#define SAE_SILENTLY_DISCARD 65535
|
||||
|
||||
struct sae_temporary_data {
|
||||
u8 kck[SAE_KCK_LEN];
|
||||
struct crypto_bignum *own_commit_scalar;
|
||||
|
|
|
@ -698,6 +698,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
|
|||
return -1;
|
||||
|
||||
if (auth_transaction == 1) {
|
||||
u16 res;
|
||||
|
||||
groups = wpa_s->conf->sae_groups;
|
||||
|
||||
wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
|
||||
|
@ -708,8 +710,14 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
|
|||
return -1;
|
||||
if (groups && groups[0] <= 0)
|
||||
groups = NULL;
|
||||
if (sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
|
||||
groups) != WLAN_STATUS_SUCCESS)
|
||||
res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
|
||||
groups);
|
||||
if (res == SAE_SILENTLY_DISCARD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"SAE: Drop commit message due to reflection attack");
|
||||
return 0;
|
||||
}
|
||||
if (res != WLAN_STATUS_SUCCESS)
|
||||
return -1;
|
||||
|
||||
if (sae_process_commit(&wpa_s->sme.sae) < 0) {
|
||||
|
|
Loading…
Reference in a new issue