@ -1918,7 +1918,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
static int ieee80211w_kde_len ( struct wpa_state_machine * sm )
{
if ( sm - > mgmt_frame_prot ) {
return 2 + RSN_SELECTOR_LEN + sizeof ( struct wpa_igtk_kde ) ;
size_t len ;
len = wpa_cipher_key_len ( sm - > wpa_auth - > conf . group_mgmt_cipher ) ;
return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len ;
}
return 0 ;
@ -1930,6 +1932,7 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
struct wpa_igtk_kde igtk ;
struct wpa_group * gsm = sm - > group ;
u8 rsc [ WPA_KEY_RSC_LEN ] ;
size_t len = wpa_cipher_key_len ( sm - > wpa_auth - > conf . group_mgmt_cipher ) ;
if ( ! sm - > mgmt_frame_prot )
return pos ;
@ -1941,17 +1944,18 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
os_memset ( igtk . pn , 0 , sizeof ( igtk . pn ) ) ;
else
os_memcpy ( igtk . pn , rsc , sizeof ( igtk . pn ) ) ;
os_memcpy ( igtk . igtk , gsm - > IGTK [ gsm - > GN_igtk - 4 ] , WPA_IGTK_LEN ) ;
os_memcpy ( igtk . igtk , gsm - > IGTK [ gsm - > GN_igtk - 4 ] , len ) ;
if ( sm - > wpa_auth - > conf . disable_gtk ) {
/*
* Provide unique random IGTK to each STA to prevent use of
* IGTK in the BSS .
*/
if ( random_get_bytes ( igtk . igtk , WPA_IGTK_LEN ) < 0 )
if ( random_get_bytes ( igtk . igtk , len ) < 0 )
return pos ;
}
pos = wpa_add_kde ( pos , RSN_KEY_DATA_IGTK ,
( const u8 * ) & igtk , sizeof ( igtk ) , NULL , 0 ) ;
( const u8 * ) & igtk , WPA_IGTK_KDE_PREFIX_LEN + len ,
NULL , 0 ) ;
return pos ;
}
@ -2457,15 +2461,16 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
# ifdef CONFIG_IEEE80211W
if ( wpa_auth - > conf . ieee80211w ! = NO_MGMT_FRAME_PROTECTION ) {
size_t len ;
len = wpa_cipher_key_len ( wpa_auth - > conf . group_mgmt_cipher ) ;
os_memcpy ( group - > GNonce , group - > Counter , WPA_NONCE_LEN ) ;
inc_byte_array ( group - > Counter , WPA_NONCE_LEN ) ;
if ( wpa_gmk_to_gtk ( group - > GMK , " IGTK key expansion " ,
wpa_auth - > addr , group - > GNonce ,
group - > IGTK [ group - > GN_igtk - 4 ] ,
WPA_IGTK_LEN ) < 0 )
group - > IGTK [ group - > GN_igtk - 4 ] , len ) < 0 )
ret = - 1 ;
wpa_hexdump_key ( MSG_DEBUG , " IGTK " ,
group - > IGTK [ group - > GN_igtk - 4 ] , WPA_IGTK_LEN ) ;
group - > IGTK [ group - > GN_igtk - 4 ] , len ) ;
}
# endif /* CONFIG_IEEE80211W */
@ -2582,26 +2587,27 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
{
struct wpa_group * gsm = sm - > group ;
u8 * start = pos ;
size_t len = wpa_cipher_key_len ( sm - > wpa_auth - > conf . group_mgmt_cipher ) ;
/*
* IGTK subelement :
* Sub - elem ID [ 1 ] | Length [ 1 ] | KeyID [ 2 ] | PN [ 6 ] | Key [ 16 ]
*/
* pos + + = WNM_SLEEP_SUBELEM_IGTK ;
* pos + + = 2 + 6 + WPA_IGTK_LEN ;
* pos + + = 2 + 6 + len ;
WPA_PUT_LE16 ( pos , gsm - > GN_igtk ) ;
pos + = 2 ;
if ( wpa_auth_get_seqnum ( sm - > wpa_auth , NULL , gsm - > GN_igtk , pos ) ! = 0 )
return 0 ;
pos + = 6 ;
os_memcpy ( pos , gsm - > IGTK [ gsm - > GN_igtk - 4 ] , WPA_IGTK_LEN ) ;
pos + = WPA_IGTK_LEN ;
os_memcpy ( pos , gsm - > IGTK [ gsm - > GN_igtk - 4 ] , len ) ;
pos + = len ;
wpa_printf ( MSG_DEBUG , " WNM: IGTK Key ID %u in WNM-Sleep Mode exit " ,
gsm - > GN_igtk ) ;
wpa_hexdump_key ( MSG_DEBUG , " WNM: IGTK in WNM-Sleep Mode exit " ,
gsm - > IGTK [ gsm - > GN_igtk - 4 ] , WPA_IGTK_LEN ) ;
gsm - > IGTK [ gsm - > GN_igtk - 4 ] , len ) ;
return pos - start ;
}
@ -2656,12 +2662,19 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
ret = - 1 ;
# ifdef CONFIG_IEEE80211W
if ( wpa_auth - > conf . ieee80211w ! = NO_MGMT_FRAME_PROTECTION & &
wpa_auth_set_key ( wpa_auth , group - > vlan_id , WPA_ALG_IGTK ,
broadcast_ether_addr , group - > GN_igtk ,
group - > IGTK [ group - > GN_igtk - 4 ] ,
WPA_IGTK_LEN ) < 0 )
ret = - 1 ;
if ( wpa_auth - > conf . ieee80211w ! = NO_MGMT_FRAME_PROTECTION ) {
enum wpa_alg alg ;
size_t len ;
alg = wpa_cipher_to_alg ( wpa_auth - > conf . group_mgmt_cipher ) ;
len = wpa_cipher_key_len ( wpa_auth - > conf . group_mgmt_cipher ) ;
if ( ret = = 0 & &
wpa_auth_set_key ( wpa_auth , group - > vlan_id , alg ,
broadcast_ether_addr , group - > GN_igtk ,
group - > IGTK [ group - > GN_igtk - 4 ] , len ) < 0 )
ret = - 1 ;
}
# endif /* CONFIG_IEEE80211W */
return ret ;