SAE: Parse Rejected Groups element from H2E SAE commit
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
86f6084862
commit
ecd7114072
2 changed files with 67 additions and 12 deletions
|
@ -107,6 +107,7 @@ void sae_clear_temp_data(struct sae_data *sae)
|
||||||
crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
|
crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
|
||||||
crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
|
crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
|
||||||
wpabuf_free(tmp->anti_clogging_token);
|
wpabuf_free(tmp->anti_clogging_token);
|
||||||
|
wpabuf_free(tmp->peer_rejected_groups);
|
||||||
os_free(tmp->pw_id);
|
os_free(tmp->pw_id);
|
||||||
bin_clear_free(tmp, sizeof(*tmp));
|
bin_clear_free(tmp, sizeof(*tmp));
|
||||||
sae->tmp = NULL;
|
sae->tmp = NULL;
|
||||||
|
@ -849,9 +850,19 @@ static int sae_is_password_id_elem(const u8 *pos, const u8 *end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sae_is_rejected_groups_elem(const u8 *pos, const u8 *end)
|
||||||
|
{
|
||||||
|
return end - pos >= 3 &&
|
||||||
|
pos[0] == WLAN_EID_EXTENSION &&
|
||||||
|
pos[1] >= 2 &&
|
||||||
|
end - pos - 2 >= pos[1] &&
|
||||||
|
pos[2] == WLAN_EID_EXT_REJECTED_GROUPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
|
static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
|
||||||
const u8 *end, const u8 **token,
|
const u8 *end, const u8 **token,
|
||||||
size_t *token_len)
|
size_t *token_len, int h2e)
|
||||||
{
|
{
|
||||||
size_t scalar_elem_len, tlen;
|
size_t scalar_elem_len, tlen;
|
||||||
const u8 *elem;
|
const u8 *elem;
|
||||||
|
@ -872,6 +883,8 @@ static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
|
||||||
* fields, so use that length as a requirement for the received
|
* fields, so use that length as a requirement for the received
|
||||||
* token and check for the presence of possible Password
|
* token and check for the presence of possible Password
|
||||||
* Identifier element based on the element header information.
|
* Identifier element based on the element header information.
|
||||||
|
* When parsing H2E case, also consider the Rejected Groupd element
|
||||||
|
* similarly.
|
||||||
*/
|
*/
|
||||||
tlen = end - (*pos + scalar_elem_len);
|
tlen = end - (*pos + scalar_elem_len);
|
||||||
|
|
||||||
|
@ -889,12 +902,27 @@ static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
|
||||||
* this frame. */
|
* this frame. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (h2e && sae_is_rejected_groups_elem(elem, end)) {
|
||||||
|
/* Rejected Groups takes out all available extra octets, so
|
||||||
|
* there can be no Anti-Clogging token in this frame. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
elem += SHA256_MAC_LEN;
|
elem += SHA256_MAC_LEN;
|
||||||
if (sae_is_password_id_elem(elem, end)) {
|
if (sae_is_password_id_elem(elem, end)) {
|
||||||
/* Password Identifier element is included in the end, so
|
/* Password Identifier element is included in the end, so
|
||||||
* remove its length from the Anti-Clogging token field. */
|
* remove its length from the Anti-Clogging token field. */
|
||||||
tlen -= 2 + elem[1];
|
tlen -= 2 + elem[1];
|
||||||
|
elem += 2 + elem[1];
|
||||||
|
if (h2e && sae_is_rejected_groups_elem(elem, end)) {
|
||||||
|
/* Also remove Rejected Groups element from the
|
||||||
|
* Anti-Clogging token field length */
|
||||||
|
tlen -= 2 + elem[1];
|
||||||
|
}
|
||||||
|
} else if (h2e && sae_is_rejected_groups_elem(elem, end)) {
|
||||||
|
/* Rejected Groups element is included in the end, so
|
||||||
|
* remove its length from the Anti-Clogging token field. */
|
||||||
|
tlen -= 2 + elem[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
|
wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
|
||||||
|
@ -1061,11 +1089,11 @@ static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos,
|
||||||
|
|
||||||
|
|
||||||
static int sae_parse_password_identifier(struct sae_data *sae,
|
static int sae_parse_password_identifier(struct sae_data *sae,
|
||||||
const u8 *pos, const u8 *end)
|
const u8 **pos, const u8 *end)
|
||||||
{
|
{
|
||||||
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
|
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
|
||||||
pos, end - pos);
|
*pos, end - *pos);
|
||||||
if (!sae_is_password_id_elem(pos, end)) {
|
if (!sae_is_password_id_elem(*pos, end)) {
|
||||||
if (sae->tmp->pw_id) {
|
if (sae->tmp->pw_id) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"SAE: No Password Identifier included, but expected one (%s)",
|
"SAE: No Password Identifier included, but expected one (%s)",
|
||||||
|
@ -1078,8 +1106,8 @@ static int sae_parse_password_identifier(struct sae_data *sae,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sae->tmp->pw_id &&
|
if (sae->tmp->pw_id &&
|
||||||
(pos[1] - 1 != (int) os_strlen(sae->tmp->pw_id) ||
|
((*pos)[1] - 1 != (int) os_strlen(sae->tmp->pw_id) ||
|
||||||
os_memcmp(sae->tmp->pw_id, pos + 3, pos[1] - 1) != 0)) {
|
os_memcmp(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1) != 0)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"SAE: The included Password Identifier does not match the expected one (%s)",
|
"SAE: The included Password Identifier does not match the expected one (%s)",
|
||||||
sae->tmp->pw_id);
|
sae->tmp->pw_id);
|
||||||
|
@ -1087,13 +1115,32 @@ static int sae_parse_password_identifier(struct sae_data *sae,
|
||||||
}
|
}
|
||||||
|
|
||||||
os_free(sae->tmp->pw_id);
|
os_free(sae->tmp->pw_id);
|
||||||
sae->tmp->pw_id = os_malloc(pos[1]);
|
sae->tmp->pw_id = os_malloc((*pos)[1]);
|
||||||
if (!sae->tmp->pw_id)
|
if (!sae->tmp->pw_id)
|
||||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
os_memcpy(sae->tmp->pw_id, pos + 3, pos[1] - 1);
|
os_memcpy(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1);
|
||||||
sae->tmp->pw_id[pos[1] - 1] = '\0';
|
sae->tmp->pw_id[(*pos)[1] - 1] = '\0';
|
||||||
wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
|
wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
|
||||||
sae->tmp->pw_id, pos[1] - 1);
|
sae->tmp->pw_id, (*pos)[1] - 1);
|
||||||
|
*pos = *pos + 2 + (*pos)[1];
|
||||||
|
return WLAN_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sae_parse_rejected_groups(struct sae_data *sae,
|
||||||
|
const u8 *pos, const u8 *end)
|
||||||
|
{
|
||||||
|
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
|
||||||
|
pos, end - pos);
|
||||||
|
if (!sae_is_rejected_groups_elem(pos, end))
|
||||||
|
return WLAN_STATUS_SUCCESS;
|
||||||
|
wpabuf_free(sae->tmp->peer_rejected_groups);
|
||||||
|
sae->tmp->peer_rejected_groups = wpabuf_alloc(pos[1] - 1);
|
||||||
|
if (!sae->tmp->peer_rejected_groups)
|
||||||
|
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
wpabuf_put_data(sae->tmp->peer_rejected_groups, pos + 3, pos[1] - 1);
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list",
|
||||||
|
sae->tmp->peer_rejected_groups);
|
||||||
return WLAN_STATUS_SUCCESS;
|
return WLAN_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1114,7 +1161,7 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
/* Optional Anti-Clogging Token */
|
/* Optional Anti-Clogging Token */
|
||||||
sae_parse_commit_token(sae, &pos, end, token, token_len);
|
sae_parse_commit_token(sae, &pos, end, token, token_len, h2e);
|
||||||
|
|
||||||
/* commit-scalar */
|
/* commit-scalar */
|
||||||
res = sae_parse_commit_scalar(sae, &pos, end);
|
res = sae_parse_commit_scalar(sae, &pos, end);
|
||||||
|
@ -1127,10 +1174,17 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
/* Optional Password Identifier element */
|
/* Optional Password Identifier element */
|
||||||
res = sae_parse_password_identifier(sae, pos, end);
|
res = sae_parse_password_identifier(sae, &pos, end);
|
||||||
if (res != WLAN_STATUS_SUCCESS)
|
if (res != WLAN_STATUS_SUCCESS)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
/* Conditional Rejected Groups element */
|
||||||
|
if (h2e) {
|
||||||
|
res = sae_parse_rejected_groups(sae, pos, end);
|
||||||
|
if (res != WLAN_STATUS_SUCCESS)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
|
* Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
|
||||||
* the values we sent which would be evidence of a reflection attack.
|
* the values we sent which would be evidence of a reflection attack.
|
||||||
|
|
|
@ -43,6 +43,7 @@ struct sae_temporary_data {
|
||||||
char *pw_id;
|
char *pw_id;
|
||||||
int vlan_id;
|
int vlan_id;
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
|
struct wpabuf *peer_rejected_groups;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sae_state {
|
enum sae_state {
|
||||||
|
|
Loading…
Reference in a new issue