@ -19,6 +19,7 @@
# include "wpa.h"
# include "aes_wrap.h"
# include "ieee802_11.h"
# include "wme.h"
# include "defs.h"
# include "wpa_auth_i.h"
# include "wpa_auth_ie.h"
@ -26,6 +27,28 @@
# ifdef CONFIG_IEEE80211R
struct wpa_ft_ies {
const u8 * mdie ;
size_t mdie_len ;
const u8 * ftie ;
size_t ftie_len ;
const u8 * r1kh_id ;
const u8 * gtk ;
size_t gtk_len ;
const u8 * r0kh_id ;
size_t r0kh_id_len ;
const u8 * rsn ;
size_t rsn_len ;
const u8 * rsn_pmkid ;
const u8 * ric ;
size_t ric_len ;
} ;
static int wpa_ft_parse_ies ( const u8 * ies , size_t ies_len ,
struct wpa_ft_ies * parse ) ;
static int wpa_ft_rrb_send ( struct wpa_authenticator * wpa_auth , const u8 * dst ,
const u8 * data , size_t data_len )
{
@ -471,14 +494,122 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
# endif /* CONFIG_IEEE80211W */
static u8 * wpa_ft_process_rdie ( u8 * pos , u8 * end , u8 id , u8 descr_count ,
const u8 * ies , size_t ies_len )
{
struct ieee802_11_elems parse ;
struct rsn_rdie * rdie ;
wpa_printf ( MSG_DEBUG , " FT: Resource Request: id=%d descr_count=%d " ,
id , descr_count ) ;
wpa_hexdump ( MSG_MSGDUMP , " FT: Resource descriptor IE(s) " ,
ies , ies_len ) ;
if ( end - pos < ( int ) sizeof ( * rdie ) ) {
wpa_printf ( MSG_ERROR , " FT: Not enough room for response RDIE " ) ;
return pos ;
}
* pos + + = WLAN_EID_RIC_DATA ;
* pos + + = sizeof ( * rdie ) ;
rdie = ( struct rsn_rdie * ) pos ;
rdie - > id = id ;
rdie - > descr_count = 0 ;
rdie - > status_code = host_to_le16 ( WLAN_STATUS_SUCCESS ) ;
pos + = sizeof ( * rdie ) ;
if ( ieee802_11_parse_elems ( ( u8 * ) ies , ies_len , & parse , 1 ) = =
ParseFailed ) {
wpa_printf ( MSG_DEBUG , " FT: Failed to parse request IEs " ) ;
rdie - > status_code =
host_to_le16 ( WLAN_STATUS_UNSPECIFIED_FAILURE ) ;
return pos ;
}
if ( parse . wmm_tspec ) {
struct wmm_tspec_element * tspec ;
int res ;
if ( parse . wmm_tspec_len + 2 < ( int ) sizeof ( * tspec ) ) {
wpa_printf ( MSG_DEBUG , " FT: Too short WMM TSPEC IE "
" (%d) " , ( int ) parse . wmm_tspec_len ) ;
rdie - > status_code =
host_to_le16 ( WLAN_STATUS_UNSPECIFIED_FAILURE ) ;
return pos ;
}
if ( end - pos < ( int ) sizeof ( * tspec ) ) {
wpa_printf ( MSG_ERROR , " FT: Not enough room for "
" response TSPEC " ) ;
rdie - > status_code =
host_to_le16 ( WLAN_STATUS_UNSPECIFIED_FAILURE ) ;
return pos ;
}
tspec = ( struct wmm_tspec_element * ) pos ;
os_memcpy ( tspec , parse . wmm_tspec - 2 , sizeof ( * tspec ) ) ;
res = wmm_process_tspec ( tspec ) ;
wpa_printf ( MSG_DEBUG , " FT: ADDTS processing result: %d " , res ) ;
if ( res = = WMM_ADDTS_STATUS_INVALID_PARAMETERS )
rdie - > status_code =
host_to_le16 ( WLAN_STATUS_INVALID_PARAMETERS ) ;
else if ( res = = WMM_ADDTS_STATUS_REFUSED )
rdie - > status_code =
host_to_le16 ( WLAN_STATUS_REQUEST_DECLINED ) ;
else {
/* TSPEC accepted; include updated TSPEC in response */
rdie - > descr_count = 1 ;
pos + = sizeof ( * tspec ) ;
}
return pos ;
}
wpa_printf ( MSG_DEBUG , " FT: No supported resource requested " ) ;
rdie - > status_code = host_to_le16 ( WLAN_STATUS_UNSPECIFIED_FAILURE ) ;
return pos ;
}
static u8 * wpa_ft_process_ric ( u8 * pos , u8 * end , const u8 * ric , size_t ric_len )
{
const u8 * rpos , * start ;
const struct rsn_rdie * rdie ;
wpa_hexdump ( MSG_MSGDUMP , " FT: RIC Request " , ric , ric_len ) ;
rpos = ric ;
while ( rpos + sizeof ( * rdie ) < ric + ric_len ) {
if ( rpos [ 0 ] ! = WLAN_EID_RIC_DATA | | rpos [ 1 ] < sizeof ( * rdie ) | |
rpos + 2 + rpos [ 1 ] > ric + ric_len )
break ;
rdie = ( const struct rsn_rdie * ) ( rpos + 2 ) ;
rpos + = 2 + rpos [ 1 ] ;
start = rpos ;
while ( rpos + 2 < = ric + ric_len & &
rpos + 2 + rpos [ 1 ] < = ric + ric_len ) {
if ( rpos [ 0 ] = = WLAN_EID_RIC_DATA )
break ;
rpos + = 2 + rpos [ 1 ] ;
}
pos = wpa_ft_process_rdie ( pos , end , rdie - > id ,
rdie - > descr_count ,
start , rpos - start ) ;
}
return pos ;
}
u8 * wpa_sm_write_assoc_resp_ies ( struct wpa_state_machine * sm , u8 * pos ,
size_t max_len , int auth_alg )
size_t max_len , int auth_alg ,
const u8 * req_ies , size_t req_ies_len )
{
u8 * end , * mdie , * ftie , * rsnie , * r0kh_id , * subelem = NULL ;
size_t mdie_len , ftie_len , rsnie_len , r0kh_id_len , subelem_len = 0 ;
int res ;
struct wpa_auth_config * conf ;
struct rsn_ftie * _ftie ;
struct wpa_ft_ies parse ;
u8 * ric_start ;
if ( sm = = NULL )
return pos ;
@ -549,33 +680,27 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
_ftie = ( struct rsn_ftie * ) ( ftie + 2 ) ;
_ftie - > mic_control [ 1 ] = 3 ; /* Information element count */
ric_start = pos ;
if ( wpa_ft_parse_ies ( req_ies , req_ies_len , & parse ) = = 0 & & parse . ric ) {
pos = wpa_ft_process_ric ( pos , end , parse . ric , parse . ric_len ) ;
_ftie - > mic_control [ 1 ] + = ieee802_11_ie_count ( ric_start ,
pos - ric_start ) ;
}
if ( ric_start = = pos )
ric_start = NULL ;
if ( wpa_ft_mic ( sm - > PTK . kck , sm - > addr , sm - > wpa_auth - > addr , 6 ,
mdie , mdie_len , ftie , ftie_len ,
rsnie , rsnie_len , NULL , 0 , _ftie - > mic ) < 0 )
rsnie , rsnie_len ,
ric_start , ric_start ? pos - ric_start : 0 ,
_ftie - > mic ) < 0 )
wpa_printf ( MSG_DEBUG , " FT: Failed to calculate MIC " ) ;
return pos ;
}
struct wpa_ft_ies {
const u8 * mdie ;
size_t mdie_len ;
const u8 * ftie ;
size_t ftie_len ;
const u8 * r1kh_id ;
const u8 * gtk ;
size_t gtk_len ;
const u8 * r0kh_id ;
size_t r0kh_id_len ;
const u8 * rsn ;
size_t rsn_len ;
const u8 * rsn_pmkid ;
const u8 * ric ;
size_t ric_len ;
} ;
static int wpa_ft_parse_ftie ( const u8 * ie , size_t ie_len ,
struct wpa_ft_ies * parse )
{