mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-22 14:49:24 +01:00
ft: create class for FT-over-DS targets
FT-over-DS is being separated into two independent stages. The first of which is the processing of the action frame response. This new class will hold all the parsed information from the action frame and allowing it to be retrieved at a later time when IWD needs to roam. Initial info class should be created when the action frame is being sent out. Once a response is received it can be parsed with ft_over_ds_parse_action_response. This verifies the frame and updates the ft_ds_info class with the parsed data. ft_over_ds_prepare_handshake is the final step prior to Reassociation. This sets all the stored IEs, anonce, and KH IDs into the handshake and derives the new PTK.
This commit is contained in:
parent
2c0234e161
commit
37811a092c
93
src/ft.c
93
src/ft.c
@ -488,6 +488,35 @@ static bool mde_equal(const uint8_t *mde1, const uint8_t *mde2)
|
||||
return memcmp(mde1, mde1, mde1[1] + 2) == 0;
|
||||
}
|
||||
|
||||
static bool ft_over_ds_process_ies(struct ft_ds_info *info,
|
||||
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;
|
||||
|
||||
if (ft_parse_ies(hs, ies, ies_len, &mde, &fte) < 0)
|
||||
return false;
|
||||
|
||||
if (!mde_equal(info->mde, mde))
|
||||
goto ft_error;
|
||||
|
||||
if (is_rsn) {
|
||||
if (!ft_parse_fte(hs, info->snonce, fte, &info->ft_info))
|
||||
goto ft_error;
|
||||
|
||||
info->fte = l_memdup(fte, fte[1] + 2);
|
||||
} else if (fte)
|
||||
goto ft_error;
|
||||
|
||||
return true;
|
||||
|
||||
ft_error:
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies,
|
||||
size_t ies_len)
|
||||
{
|
||||
@ -530,6 +559,59 @@ ft_error:
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
int ft_over_ds_parse_action_response(struct ft_ds_info *info,
|
||||
struct handshake_state *hs,
|
||||
const uint8_t *frame, size_t frame_len)
|
||||
{
|
||||
uint16_t status;
|
||||
|
||||
if (frame_len < 16)
|
||||
return -EINVAL;
|
||||
|
||||
/* Category FT */
|
||||
if (frame[0] != 6)
|
||||
return -EINVAL;
|
||||
|
||||
/* FT Action */
|
||||
if (frame[1] != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (memcmp(frame + 2, info->spa, 6))
|
||||
return -ENOENT;
|
||||
if (memcmp(frame + 8, info->aa, 6))
|
||||
return -ENOENT;
|
||||
|
||||
status = l_get_le16(frame + 14);
|
||||
if (status != 0)
|
||||
return (int)status;
|
||||
|
||||
if (!ft_over_ds_process_ies(info, hs, frame + 16, frame_len - 16))
|
||||
return -EBADMSG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ft_over_ds_prepare_handshake(struct ft_ds_info *info,
|
||||
struct handshake_state *hs)
|
||||
{
|
||||
if (!hs->supplicant_ie)
|
||||
return true;
|
||||
|
||||
memcpy(hs->snonce, info->snonce, sizeof(hs->snonce));
|
||||
|
||||
handshake_state_set_fte(hs, info->fte);
|
||||
|
||||
handshake_state_set_anonce(hs, info->ft_info.anonce);
|
||||
|
||||
handshake_state_set_kh_ids(hs, info->ft_info.r0khid,
|
||||
info->ft_info.r0khid_len,
|
||||
info->ft_info.r1khid);
|
||||
|
||||
handshake_state_derive_ptk(hs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ft_rx_action(struct auth_proto *ap, const uint8_t *frame,
|
||||
size_t frame_len)
|
||||
{
|
||||
@ -558,6 +640,17 @@ auth_error:
|
||||
return (int)status_code;
|
||||
}
|
||||
|
||||
void ft_ds_info_free(struct ft_ds_info *info)
|
||||
{
|
||||
__typeof__(info->free) destroy = info->free;
|
||||
|
||||
if (info->fte)
|
||||
l_free(info->fte);
|
||||
|
||||
if (destroy)
|
||||
destroy(info);
|
||||
}
|
||||
|
||||
static int ft_rx_authenticate(struct auth_proto *ap, const uint8_t *frame,
|
||||
size_t frame_len)
|
||||
{
|
||||
|
25
src/ft.h
25
src/ft.h
@ -20,15 +20,37 @@
|
||||
*
|
||||
*/
|
||||
|
||||
struct handshake_state;
|
||||
|
||||
typedef void (*ft_tx_authenticate_func_t)(struct iovec *iov, size_t iov_len,
|
||||
void *user_data);
|
||||
typedef void (*ft_tx_associate_func_t)(struct iovec *ie_iov, size_t iov_len,
|
||||
void *user_data);
|
||||
|
||||
typedef void (*ft_ds_free_func_t)(void *user_data);
|
||||
|
||||
struct ft_ds_info {
|
||||
uint8_t spa[6];
|
||||
uint8_t aa[6];
|
||||
uint8_t snonce[32];
|
||||
uint8_t mde[3];
|
||||
uint8_t *fte;
|
||||
|
||||
struct ie_ft_info ft_info;
|
||||
|
||||
void (*free)(struct ft_ds_info *s);
|
||||
};
|
||||
|
||||
void ft_ds_info_free(struct ft_ds_info *info);
|
||||
|
||||
bool ft_build_authenticate_ies(struct handshake_state *hs,
|
||||
const uint8_t *new_snonce, uint8_t *buf,
|
||||
size_t *len);
|
||||
|
||||
int ft_over_ds_parse_action_response(struct ft_ds_info *info,
|
||||
struct handshake_state *hs,
|
||||
const uint8_t *frame, size_t frame_len);
|
||||
|
||||
struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
|
||||
ft_tx_authenticate_func_t tx_auth,
|
||||
ft_tx_associate_func_t tx_assoc,
|
||||
@ -38,3 +60,6 @@ struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
|
||||
ft_tx_authenticate_func_t tx_auth,
|
||||
ft_tx_associate_func_t tx_assoc,
|
||||
void *user_data);
|
||||
|
||||
bool ft_over_ds_prepare_handshake(struct ft_ds_info *info,
|
||||
struct handshake_state *hs);
|
||||
|
Loading…
Reference in New Issue
Block a user