FT: Add RIC Request generation and validation (but not processing)

This adds first part of FT resource request as part of Reassocition
Request frame (i.e., FT Protocol, not FT Resource Request Protocol).
wpa_supplicant can generate a test resource request when driver_test.c
is used with internal MLME code and hostapd can verify the FTIE MIC
properly with the included RIC Request.

The actual RIC Request IEs are not processed yet and hostapd does not
yet reply with RIC Response (nor would wpa_supplicant be able to
validate the FTIE MIC for a frame with RIC Response).
This commit is contained in:
Jouni Malinen 2009-03-09 20:45:17 +02:00 committed by Jouni Malinen
parent 143a4bf632
commit babfbf15cc
9 changed files with 173 additions and 48 deletions

View file

@ -284,7 +284,8 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
const u8 *r1kh_id);
int wpa_ft_prepare_auth_request(struct wpa_sm *sm);
int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap);
int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len);
int wpa_ft_is_completed(struct wpa_sm *sm);
int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
size_t ies_len, const u8 *src_addr);

View file

@ -20,6 +20,7 @@
#include "wpa_ie.h"
#include "aes_wrap.h"
#include "ieee802_11_defs.h"
#include "ieee802_11_common.h"
#ifdef CONFIG_IEEE80211R
@ -105,20 +106,23 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
/**
* wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth Request
* wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth/ReAssoc Request
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @len: Buffer for returning the length of the IEs
* @anonce: ANonce or %NULL if not yet available
* @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List
* @kck: 128-bit KCK for MIC or %NULL if no MIC is used
* @target_ap: Target AP address
* @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
* @ric_ies_len: Length of ric_ies buffer in octets
* Returns: Pointer to buffer with IEs or %NULL on failure
*
* Caller is responsible for freeing the returned buffer with os_free();
*/
static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
const u8 *anonce, const u8 *pmk_name,
const u8 *kck, const u8 *target_ap)
const u8 *kck, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len)
{
size_t buf_len;
u8 *buf, *pos, *ftie_len, *ftie_pos;
@ -130,13 +134,13 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
sm->ft_completed = 0;
buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
2 + sm->r0kh_id_len + 100;
2 + sm->r0kh_id_len + ric_ies_len + 100;
buf = os_zalloc(buf_len);
if (buf == NULL)
return NULL;
pos = buf;
/* RSNIE[PMKR0Name] */
/* RSNIE[PMKR0Name/PMKR1Name] */
rsnie = (struct rsn_ie_hdr *) pos;
rsnie->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(rsnie->version, RSN_VERSION);
@ -241,6 +245,12 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
pos += sm->r0kh_id_len;
*ftie_len = pos - ftie_len - 1;
if (ric_ies) {
/* RIC Request */
os_memcpy(pos, ric_ies, ric_ies_len);
pos += ric_ies_len;
}
if (kck) {
/*
* IEEE Std 802.11r-2008, 11A.8.4
@ -253,12 +263,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
* FTIE (with MIC field set to 0)
* RIC-Request (if present)
*/
ftie->mic_control[1] = 3; /* Information element count */
/* Information element count */
ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
ric_ies_len);
if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5,
((u8 *) mdie) - 2, 2 + sizeof(*mdie),
ftie_pos, 2 + *ftie_len,
(u8 *) rsnie, 2 + rsnie->len, NULL, 0,
ftie->mic) < 0) {
(u8 *) rsnie, 2 + rsnie->len, ric_ies,
ric_ies_len, ftie->mic) < 0) {
wpa_printf(MSG_INFO, "FT: Failed to calculate MIC");
os_free(buf);
return NULL;
@ -440,7 +452,7 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
}
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
NULL, sm->bssid);
NULL, sm->bssid, NULL, 0);
if (ft_ies) {
wpa_sm_update_ft_ies(sm, sm->mobility_domain,
ft_ies, ft_ies_len);
@ -452,7 +464,8 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap)
int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len)
{
u8 *ft_ies;
size_t ft_ies_len;
@ -464,6 +477,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
const u8 *bssid;
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len);
if (ft_action) {
if (!sm->over_the_ds_in_progress) {
@ -553,7 +567,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
sm->pmk_r1_name, sm->ptk.kck, bssid);
sm->pmk_r1_name, sm->ptk.kck, bssid,
ric_ies, ric_ies_len);
if (ft_ies) {
wpa_sm_update_ft_ies(sm, sm->mobility_domain,
ft_ies, ft_ies_len);
@ -857,7 +872,7 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap)
}
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
NULL, target_ap);
NULL, target_ap, NULL, 0);
if (ft_ies) {
sm->over_the_ds_in_progress = 1;
os_memcpy(sm->target_ap, target_ap, ETH_ALEN);