@ -2466,6 +2466,9 @@ void wpa_sm_deinit(struct wpa_sm *sm)
# ifdef CONFIG_FILS_SK_PFS
crypto_ecdh_deinit ( sm - > fils_ecdh ) ;
# endif /* CONFIG_FILS_SK_PFS */
# ifdef CONFIG_FILS
wpabuf_free ( sm - > fils_ft_ies ) ;
# endif /* CONFIG_FILS */
# ifdef CONFIG_OWE
crypto_ecdh_deinit ( sm - > owe_ecdh ) ;
# endif /* CONFIG_OWE */
@ -3503,8 +3506,53 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
os_memcpy ( sm - > fils_anonce , elems . fils_nonce , FILS_NONCE_LEN ) ;
wpa_hexdump ( MSG_DEBUG , " FILS: ANonce " , sm - > fils_anonce , FILS_NONCE_LEN ) ;
/* TODO: MDE when using FILS+FT */
/* TODO: FTE when using FILS+FT */
if ( wpa_key_mgmt_ft ( sm - > key_mgmt ) ) {
struct wpa_ft_ies parse ;
if ( ! elems . mdie | | ! elems . ftie ) {
wpa_printf ( MSG_DEBUG , " FILS+FT: No MDE or FTE " ) ;
goto fail ;
}
if ( wpa_ft_parse_ies ( pos , end - pos , & parse ) < 0 ) {
wpa_printf ( MSG_DEBUG , " FILS+FT: Failed to parse IEs " ) ;
goto fail ;
}
if ( ! parse . r0kh_id ) {
wpa_printf ( MSG_DEBUG ,
" FILS+FT: No R0KH-ID subelem in FTE " ) ;
goto fail ;
}
os_memcpy ( sm - > r0kh_id , parse . r0kh_id , parse . r0kh_id_len ) ;
sm - > r0kh_id_len = parse . r0kh_id_len ;
wpa_hexdump_ascii ( MSG_DEBUG , " FILS+FT: R0KH-ID " ,
sm - > r0kh_id , sm - > r0kh_id_len ) ;
if ( ! parse . r1kh_id ) {
wpa_printf ( MSG_DEBUG ,
" FILS+FT: No R1KH-ID subelem in FTE " ) ;
goto fail ;
}
os_memcpy ( sm - > r1kh_id , parse . r1kh_id , FT_R1KH_ID_LEN ) ;
wpa_hexdump ( MSG_DEBUG , " FILS+FT: R1KH-ID " ,
sm - > r1kh_id , FT_R1KH_ID_LEN ) ;
/* TODO: Check MDE and FTE payload */
wpabuf_free ( sm - > fils_ft_ies ) ;
sm - > fils_ft_ies = wpabuf_alloc ( 2 + elems . mdie_len +
2 + elems . ftie_len ) ;
if ( ! sm - > fils_ft_ies )
goto fail ;
wpabuf_put_data ( sm - > fils_ft_ies , elems . mdie - 2 ,
2 + elems . mdie_len ) ;
wpabuf_put_data ( sm - > fils_ft_ies , elems . ftie - 2 ,
2 + elems . ftie_len ) ;
} else {
wpabuf_free ( sm - > fils_ft_ies ) ;
sm - > fils_ft_ies = NULL ;
}
/* PMKID List */
if ( rsn . pmkid & & rsn . num_pmkid > 0 ) {
@ -3604,7 +3652,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
if ( fils_pmk_to_ptk ( sm - > pmk , sm - > pmk_len , sm - > own_addr , sm - > bssid ,
sm - > fils_nonce , sm - > fils_anonce , & sm - > ptk ,
ick , & ick_len , sm - > key_mgmt , sm - > pairwise_cipher ,
NULL , NULL ) < 0 ) {
sm - > fils_ft , & sm - > fils_ft_len ) < 0 ) {
wpa_printf ( MSG_DEBUG , " FILS: Failed to derive PTK " ) ;
goto fail ;
}
@ -3648,6 +3696,110 @@ fail:
}
# ifdef CONFIG_IEEE80211R
static int fils_ft_build_assoc_req_rsne ( struct wpa_sm * sm , struct wpabuf * buf )
{
struct rsn_ie_hdr * rsnie ;
u16 capab ;
u8 * pos ;
/* RSNIE[PMKR0Name/PMKR1Name] */
rsnie = wpabuf_put ( buf , sizeof ( * rsnie ) ) ;
rsnie - > elem_id = WLAN_EID_RSN ;
WPA_PUT_LE16 ( rsnie - > version , RSN_VERSION ) ;
/* Group Suite Selector */
if ( ! wpa_cipher_valid_group ( sm - > group_cipher ) ) {
wpa_printf ( MSG_WARNING , " FT: Invalid group cipher (%d) " ,
sm - > group_cipher ) ;
return - 1 ;
}
pos = wpabuf_put ( buf , RSN_SELECTOR_LEN ) ;
RSN_SELECTOR_PUT ( pos , wpa_cipher_to_suite ( WPA_PROTO_RSN ,
sm - > group_cipher ) ) ;
/* Pairwise Suite Count */
wpabuf_put_le16 ( buf , 1 ) ;
/* Pairwise Suite List */
if ( ! wpa_cipher_valid_pairwise ( sm - > pairwise_cipher ) ) {
wpa_printf ( MSG_WARNING , " FT: Invalid pairwise cipher (%d) " ,
sm - > pairwise_cipher ) ;
return - 1 ;
}
pos = wpabuf_put ( buf , RSN_SELECTOR_LEN ) ;
RSN_SELECTOR_PUT ( pos , wpa_cipher_to_suite ( WPA_PROTO_RSN ,
sm - > pairwise_cipher ) ) ;
/* Authenticated Key Management Suite Count */
wpabuf_put_le16 ( buf , 1 ) ;
/* Authenticated Key Management Suite List */
pos = wpabuf_put ( buf , RSN_SELECTOR_LEN ) ;
if ( sm - > key_mgmt = = WPA_KEY_MGMT_FT_FILS_SHA256 )
RSN_SELECTOR_PUT ( pos , RSN_AUTH_KEY_MGMT_FT_FILS_SHA256 ) ;
else if ( sm - > key_mgmt = = WPA_KEY_MGMT_FT_FILS_SHA384 )
RSN_SELECTOR_PUT ( pos , RSN_AUTH_KEY_MGMT_FT_FILS_SHA384 ) ;
else {
wpa_printf ( MSG_WARNING ,
" FILS+FT: Invalid key management type (%d) " ,
sm - > key_mgmt ) ;
return - 1 ;
}
/* RSN Capabilities */
capab = 0 ;
# ifdef CONFIG_IEEE80211W
if ( sm - > mgmt_group_cipher = = WPA_CIPHER_AES_128_CMAC )
capab | = WPA_CAPABILITY_MFPC ;
# endif /* CONFIG_IEEE80211W */
wpabuf_put_le16 ( buf , capab ) ;
/* PMKID Count */
wpabuf_put_le16 ( buf , 1 ) ;
/* PMKID List [PMKR1Name] */
wpa_hexdump_key ( MSG_DEBUG , " FILS+FT: XXKey (FILS-FT) " ,
sm - > fils_ft , sm - > fils_ft_len ) ;
wpa_hexdump_ascii ( MSG_DEBUG , " FILS+FT: SSID " , sm - > ssid , sm - > ssid_len ) ;
wpa_hexdump ( MSG_DEBUG , " FILS+FT: MDID " ,
sm - > mobility_domain , MOBILITY_DOMAIN_ID_LEN ) ;
wpa_hexdump_ascii ( MSG_DEBUG , " FILS+FT: R0KH-ID " ,
sm - > r0kh_id , sm - > r0kh_id_len ) ;
if ( wpa_derive_pmk_r0 ( sm - > fils_ft , sm - > fils_ft_len , sm - > ssid ,
sm - > ssid_len , sm - > mobility_domain ,
sm - > r0kh_id , sm - > r0kh_id_len , sm - > own_addr ,
sm - > pmk_r0 , sm - > pmk_r0_name ) < 0 ) {
wpa_printf ( MSG_WARNING , " FILS+FT: Could not derive PMK-R0 " ) ;
return - 1 ;
}
wpa_hexdump_key ( MSG_DEBUG , " FILS+FT: PMK-R0 " , sm - > pmk_r0 , PMK_LEN ) ;
wpa_hexdump ( MSG_DEBUG , " FILS+FT: PMKR0Name " ,
sm - > pmk_r0_name , WPA_PMK_NAME_LEN ) ;
wpa_printf ( MSG_DEBUG , " FILS+FT: R1KH-ID: " MACSTR ,
MAC2STR ( sm - > r1kh_id ) ) ;
pos = wpabuf_put ( buf , WPA_PMK_NAME_LEN ) ;
if ( wpa_derive_pmk_r1_name ( sm - > pmk_r0_name , sm - > r1kh_id , sm - > own_addr ,
pos ) < 0 ) {
wpa_printf ( MSG_WARNING , " FILS+FT: Could not derive PMKR1Name " ) ;
return - 1 ;
}
wpa_hexdump ( MSG_DEBUG , " FILS+FT: PMKR1Name " , pos , WPA_PMK_NAME_LEN ) ;
# ifdef CONFIG_IEEE80211W
if ( sm - > mgmt_group_cipher = = WPA_CIPHER_AES_128_CMAC ) {
/* Management Group Cipher Suite */
pos = wpabuf_put ( buf , RSN_SELECTOR_LEN ) ;
RSN_SELECTOR_PUT ( pos , RSN_CIPHER_SUITE_AES_128_CMAC ) ;
}
# endif /* CONFIG_IEEE80211W */
rsnie - > len = ( ( u8 * ) wpabuf_put ( buf , 0 ) - ( u8 * ) rsnie ) - 2 ;
return 0 ;
}
# endif /* CONFIG_IEEE80211R */
struct wpabuf * fils_build_assoc_req ( struct wpa_sm * sm , const u8 * * kek ,
size_t * kek_len , const u8 * * snonce ,
const u8 * * anonce ,
@ -3659,12 +3811,30 @@ struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
unsigned int i ;
len = 1000 ;
# ifdef CONFIG_IEEE80211R
if ( sm - > fils_ft_ies )
len + = wpabuf_len ( sm - > fils_ft_ies ) ;
if ( wpa_key_mgmt_ft ( sm - > key_mgmt ) )
len + = 256 ;
# endif /* CONFIG_IEEE80211R */
for ( i = 0 ; hlp & & i < num_hlp ; i + + )
len + = 10 + wpabuf_len ( hlp [ i ] ) ;
buf = wpabuf_alloc ( len ) ;
if ( ! buf )
return NULL ;
# ifdef CONFIG_IEEE80211R
if ( wpa_key_mgmt_ft ( sm - > key_mgmt ) & & sm - > fils_ft_ies ) {
/* MDE and FTE when using FILS+FT */
wpabuf_put_buf ( buf , sm - > fils_ft_ies ) ;
/* RSNE with PMKR1Name in PMKID field */
if ( fils_ft_build_assoc_req_rsne ( sm , buf ) < 0 ) {
wpabuf_free ( buf ) ;
return NULL ;
}
}
# endif /* CONFIG_IEEE80211R */
/* FILS Session */
wpabuf_put_u8 ( buf , WLAN_EID_EXTENSION ) ; /* Element ID */
wpabuf_put_u8 ( buf , 1 + FILS_SESSION_LEN ) ; /* Length */