3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-12-23 06:02:37 +01:00

ft: rework ft_parse_ies

This adds the RSNE verification to ft_parse_ies which will
be common between over-Air and over-DS. The MDE check was
also factored out into its own minimal function as to
retain the spec comment but allow reuse elsewhere.
This commit is contained in:
James Prestwood 2021-04-29 16:08:35 -07:00 committed by Denis Kenzior
parent 2697af428e
commit 2c0234e161

155
src/ft.c
View File

@ -329,57 +329,6 @@ error:
return -EINVAL; return -EINVAL;
} }
static int ft_parse_ies(const uint8_t *ies, size_t ies_len,
const uint8_t **rsne_out, const uint8_t **mde_out,
const uint8_t **fte_out)
{
struct ie_tlv_iter iter;
const uint8_t *rsne = NULL;
const uint8_t *mde = NULL;
const uint8_t *fte = NULL;
ie_tlv_iter_init(&iter, ies, ies_len);
while (ie_tlv_iter_next(&iter)) {
switch (ie_tlv_iter_get_tag(&iter)) {
case IE_TYPE_RSN:
if (rsne)
goto ft_error;
rsne = ie_tlv_iter_get_data(&iter) - 2;
break;
case IE_TYPE_MOBILITY_DOMAIN:
if (mde)
goto ft_error;
mde = ie_tlv_iter_get_data(&iter) - 2;
break;
case IE_TYPE_FAST_BSS_TRANSITION:
if (fte)
goto ft_error;
fte = ie_tlv_iter_get_data(&iter) - 2;
break;
}
}
if (rsne_out)
*rsne_out = rsne;
if (mde_out)
*mde_out = mde;
if (fte_out)
*fte_out = fte;
return 0;
ft_error:
return -EINVAL;
}
static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name, static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name,
const uint8_t *authenticator_ie) const uint8_t *authenticator_ie)
{ {
@ -416,6 +365,65 @@ static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name,
return true; return true;
} }
static int ft_parse_ies(struct handshake_state *hs,
const uint8_t *ies, size_t ies_len,
const uint8_t **mde_out,
const uint8_t **fte_out)
{
struct ie_tlv_iter iter;
const uint8_t *rsne = NULL;
const uint8_t *mde = NULL;
const uint8_t *fte = NULL;
bool is_rsn;
ie_tlv_iter_init(&iter, ies, ies_len);
while (ie_tlv_iter_next(&iter)) {
switch (ie_tlv_iter_get_tag(&iter)) {
case IE_TYPE_RSN:
if (rsne)
goto ft_error;
rsne = ie_tlv_iter_get_data(&iter) - 2;
break;
case IE_TYPE_MOBILITY_DOMAIN:
if (mde)
goto ft_error;
mde = ie_tlv_iter_get_data(&iter) - 2;
break;
case IE_TYPE_FAST_BSS_TRANSITION:
if (fte)
goto ft_error;
fte = ie_tlv_iter_get_data(&iter) - 2;
break;
}
}
is_rsn = hs->supplicant_ie != NULL;
if (is_rsn) {
if (!ft_verify_rsne(rsne, hs->pmk_r0_name,
hs->authenticator_ie))
goto ft_error;
} else if (rsne)
goto ft_error;
if (mde_out)
*mde_out = mde;
if (fte_out)
*fte_out = fte;
return 0;
ft_error:
return -EINVAL;
}
static bool ft_parse_fte(struct handshake_state *hs, static bool ft_parse_fte(struct handshake_state *hs,
const uint8_t *snonce, const uint8_t *snonce,
const uint8_t *fte, const uint8_t *fte,
@ -465,29 +473,10 @@ static bool ft_parse_fte(struct handshake_state *hs,
return true; return true;
} }
static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies, static bool mde_equal(const uint8_t *mde1, const uint8_t *mde2)
size_t ies_len)
{ {
const uint8_t *rsne = NULL; if (!mde1 || !mde2)
const uint8_t *mde = NULL; return false;
const uint8_t *fte = NULL;
bool is_rsn;
/* Check 802.11r IEs */
if (!ies)
goto ft_error;
if (ft_parse_ies(ies, ies_len, &rsne, &mde, &fte) < 0)
goto ft_error;
is_rsn = hs->supplicant_ie != NULL;
if (is_rsn) {
if (!ft_verify_rsne(rsne, hs->pmk_r0_name,
hs->authenticator_ie))
goto ft_error;
} else if (rsne)
goto ft_error;
/* /*
* Check for an MD IE identical to the one we sent in message 1 * Check for an MD IE identical to the one we sent in message 1
@ -496,7 +485,25 @@ static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies,
* Policy fields. This element shall be the same as the MDE * Policy fields. This element shall be the same as the MDE
* advertised by the target AP in Beacon and Probe Response frames." * advertised by the target AP in Beacon and Probe Response frames."
*/ */
if (!mde || memcmp(hs->mde, mde, hs->mde[1] + 2)) return memcmp(mde1, mde1, mde1[1] + 2) == 0;
}
static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies,
size_t ies_len)
{
const uint8_t *mde = NULL;
const uint8_t *fte = NULL;
bool is_rsn = hs->supplicant_ie != NULL;
/* Check 802.11r IEs */
if (!ies)
goto ft_error;
if (ft_parse_ies(hs, ies, ies_len, &mde, &fte) < 0)
goto ft_error;
if (!mde_equal(hs->mde, mde))
goto ft_error; goto ft_error;
if (is_rsn) { if (is_rsn) {