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 -
|
((const u8 *) mgmt) + len -
|
||||||
mgmt->u.auth.variable, &token,
|
mgmt->u.auth.variable, &token,
|
||||||
&token_len, hapd->conf->sae_groups);
|
&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)
|
if (token && check_sae_token(hapd, sta->addr, token, token_len)
|
||||||
< 0) {
|
< 0) {
|
||||||
wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
|
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;
|
return res;
|
||||||
|
|
||||||
/* commit-element */
|
/* 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_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN)
|
||||||
#define SAE_CONFIRM_MAX_LEN (2 + 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 {
|
struct sae_temporary_data {
|
||||||
u8 kck[SAE_KCK_LEN];
|
u8 kck[SAE_KCK_LEN];
|
||||||
struct crypto_bignum *own_commit_scalar;
|
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;
|
return -1;
|
||||||
|
|
||||||
if (auth_transaction == 1) {
|
if (auth_transaction == 1) {
|
||||||
|
u16 res;
|
||||||
|
|
||||||
groups = wpa_s->conf->sae_groups;
|
groups = wpa_s->conf->sae_groups;
|
||||||
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
|
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;
|
return -1;
|
||||||
if (groups && groups[0] <= 0)
|
if (groups && groups[0] <= 0)
|
||||||
groups = NULL;
|
groups = NULL;
|
||||||
if (sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
|
res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
|
||||||
groups) != WLAN_STATUS_SUCCESS)
|
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;
|
return -1;
|
||||||
|
|
||||||
if (sae_process_commit(&wpa_s->sme.sae) < 0) {
|
if (sae_process_commit(&wpa_s->sme.sae) < 0) {
|
||||||
|
|
Loading…
Reference in a new issue