@ -39,7 +39,7 @@ static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver,
struct ieee802_1x_hdr * hdr ;
struct wpa_eapol_key * key ;
u8 rx_mic [ WPA_EAPOL_KEY_MIC_MAX_LEN ] ;
size_t mic_len = 16 ;
size_t mic_len = wpa_mic_len ( akmp ) ;
buf = os_malloc ( len ) ;
if ( buf = = NULL )
@ -48,12 +48,12 @@ static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver,
hdr = ( struct ieee802_1x_hdr * ) buf ;
key = ( struct wpa_eapol_key * ) ( hdr + 1 ) ;
os_memcpy ( rx_mic , key - > key_mic , mic_len ) ;
os_memset ( key - > key_mic , 0 , mic_len ) ;
os_memcpy ( rx_mic , key + 1 , mic_len ) ;
os_memset ( key + 1 , 0 , mic_len ) ;
if ( wpa_eapol_key_mic ( kck , kck_len , akmp , ver , buf , len ,
key - > key_mic ) = = 0 & &
os_memcmp ( rx_mic , key - > key_mic , mic_len ) = = 0 )
( u8 * ) ( key + 1 ) ) = = 0 & &
os_memcmp ( rx_mic , key + 1 , mic_len ) = = 0 )
ret = 0 ;
os_free ( buf ) ;
@ -229,8 +229,8 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
struct wlantest_sta * sta ;
const struct ieee802_1x_hdr * eapol ;
const struct wpa_eapol_key * hdr ;
const u8 * key_data , * kck ;
size_t kck_len ;
const u8 * key_data , * kck , * mic ;
size_t kck_len , mic_len ;
u16 key_info , key_data_len ;
struct wpa_eapol_ie_parse ie ;
@ -245,6 +245,8 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
eapol = ( const struct ieee802_1x_hdr * ) data ;
hdr = ( const struct wpa_eapol_key * ) ( eapol + 1 ) ;
mic_len = wpa_mic_len ( sta - > key_mgmt ) ;
mic = ( const u8 * ) ( hdr + 1 ) ;
if ( is_zero ( hdr - > key_nonce , WPA_NONCE_LEN ) ) {
add_note ( wt , MSG_INFO , " EAPOL-Key 2/4 from " MACSTR
" used zero nonce " , MAC2STR ( src ) ) ;
@ -255,7 +257,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
}
os_memcpy ( sta - > snonce , hdr - > key_nonce , WPA_NONCE_LEN ) ;
key_info = WPA_GET_BE16 ( hdr - > key_info ) ;
key_data_len = WPA_GET_BE16 ( hdr- > key_data_length ) ;
key_data_len = WPA_GET_BE16 ( mic + mic_len ) ;
derive_ptk ( wt , bss , sta , key_info & WPA_KEY_INFO_TYPE_MASK , data , len ) ;
if ( ! sta - > ptk_set & & ! sta - > tptk_set ) {
@ -279,7 +281,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
}
add_note ( wt , MSG_DEBUG , " Valid MIC found in EAPOL-Key 2/4 " ) ;
key_data = ( const u8 * ) ( hdr + 1 ) ;
key_data = mic + mic_len + 2 ;
if ( wpa_supplicant_parse_ies ( key_data , key_data_len , & ie ) < 0 ) {
add_note ( wt , MSG_INFO , " Failed to parse EAPOL-Key Key Data " ) ;
@ -348,10 +350,10 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
static u8 * decrypt_eapol_key_data_rc4 ( struct wlantest * wt , const u8 * kek ,
const struct wpa_eapol_key * hdr ,
const u8 * keydata , u16 keydatalen ,
size_t * len )
{
u8 ek [ 32 ] , * buf ;
u16 keydatalen = WPA_GET_BE16 ( hdr - > key_data_length ) ;
buf = os_malloc ( keydatalen ) ;
if ( buf = = NULL )
@ -359,7 +361,7 @@ static u8 * decrypt_eapol_key_data_rc4(struct wlantest *wt, const u8 *kek,
os_memcpy ( ek , hdr - > key_iv , 16 ) ;
os_memcpy ( ek + 16 , kek , 16 ) ;
os_memcpy ( buf , hdr + 1 , keydatalen ) ;
os_memcpy ( buf , keydata , keydatalen ) ;
if ( rc4_skip ( ek , 32 , 256 , buf , keydatalen ) ) {
add_note ( wt , MSG_INFO , " RC4 failed " ) ;
os_free ( buf ) ;
@ -373,10 +375,10 @@ static u8 * decrypt_eapol_key_data_rc4(struct wlantest *wt, const u8 *kek,
static u8 * decrypt_eapol_key_data_aes ( struct wlantest * wt , const u8 * kek ,
const struct wpa_eapol_key * hdr ,
const u8 * keydata , u16 keydatalen ,
size_t * len )
{
u8 * buf ;
u16 keydatalen = WPA_GET_BE16 ( hdr - > key_data_length ) ;
if ( keydatalen % 8 ) {
add_note ( wt , MSG_INFO , " Unsupported AES-WRAP len %d " ,
@ -387,7 +389,7 @@ static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
buf = os_malloc ( keydatalen ) ;
if ( buf = = NULL )
return NULL ;
if ( aes_unwrap ( kek , 16 , keydatalen / 8 , ( u8 * ) ( hdr + 1 ) , buf ) ) {
if ( aes_unwrap ( kek , 16 , keydatalen / 8 , keydata , buf ) ) {
os_free ( buf ) ;
add_note ( wt , MSG_INFO ,
" AES unwrap failed - could not decrypt EAPOL-Key "
@ -400,22 +402,35 @@ static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
}
static u8 * decrypt_eapol_key_data ( struct wlantest * wt , const u8 * kek ,
static u8 * decrypt_eapol_key_data ( struct wlantest * wt , int akmp , const u8 * kek ,
size_t kek_len , u16 ver ,
const struct wpa_eapol_key * hdr ,
size_t * len )
{
size_t mic_len ;
u16 keydatalen ;
const u8 * mic , * keydata ;
if ( kek_len ! = 16 )
return NULL ;
mic = ( const u8 * ) ( hdr + 1 ) ;
mic_len = wpa_mic_len ( akmp ) ;
keydata = mic + mic_len + 2 ;
keydatalen = WPA_GET_BE16 ( mic + mic_len ) ;
switch ( ver ) {
case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 :
return decrypt_eapol_key_data_rc4 ( wt , kek , hdr , len ) ;
return decrypt_eapol_key_data_rc4 ( wt , kek , hdr , keydata ,
keydatalen , len ) ;
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES :
case WPA_KEY_INFO_TYPE_AES_128_CMAC :
return decrypt_eapol_key_data_aes ( wt , kek , hdr , len ) ;
return decrypt_eapol_key_data_aes ( wt , kek , hdr , keydata ,
keydatalen , len ) ;
case WPA_KEY_INFO_TYPE_AKM_DEFINED :
/* For now, assume this is OSEN */
return decrypt_eapol_key_data_aes ( wt , kek , hdr , len ) ;
return decrypt_eapol_key_data_aes ( wt , kek , hdr , keydata ,
keydatalen , len ) ;
default :
add_note ( wt , MSG_INFO ,
" Unsupported EAPOL-Key Key Descriptor Version %u " ,
@ -544,8 +559,8 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
struct wlantest_sta * sta ;
const struct ieee802_1x_hdr * eapol ;
const struct wpa_eapol_key * hdr ;
const u8 * key_data , * kck , * kek ;
size_t kck_len , kek_len ;
const u8 * key_data , * kck , * kek , * mic ;
size_t kck_len , kek_len , mic_len ;
int recalc = 0 ;
u16 key_info , ver ;
u8 * decrypted_buf = NULL ;
@ -561,9 +576,11 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
sta = sta_get ( bss , dst ) ;
if ( sta = = NULL )
return ;
mic_len = wpa_mic_len ( sta - > key_mgmt ) ;
eapol = ( const struct ieee802_1x_hdr * ) data ;
hdr = ( const struct wpa_eapol_key * ) ( eapol + 1 ) ;
mic = ( const u8 * ) ( hdr + 1 ) ;
key_info = WPA_GET_BE16 ( hdr - > key_info ) ;
if ( os_memcmp ( sta - > anonce , hdr - > key_nonce , WPA_NONCE_LEN ) ! = 0 ) {
@ -602,16 +619,17 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
}
add_note ( wt , MSG_DEBUG , " Valid MIC found in EAPOL-Key 3/4 " ) ;
key_data = ( const u8 * ) ( hdr + 1 ) ;
key_data = mic + mic_len + 2 ;
if ( ! ( key_info & WPA_KEY_INFO_ENCR_KEY_DATA ) ) {
if ( sta - > proto & WPA_PROTO_RSN )
add_note ( wt , MSG_INFO ,
" EAPOL-Key 3/4 without EncrKeyData bit " ) ;
decrypted = key_data ;
decrypted_len = WPA_GET_BE16 ( hdr- > key_data_length ) ;
decrypted_len = WPA_GET_BE16 ( mic + mic_len ) ;
} else {
ver = key_info & WPA_KEY_INFO_TYPE_MASK ;
decrypted_buf = decrypt_eapol_key_data ( wt , kek , kek_len , ver ,
decrypted_buf = decrypt_eapol_key_data ( wt , sta - > key_mgmt ,
kek , kek_len , ver ,
hdr , & decrypted_len ) ;
if ( decrypted_buf = = NULL ) {
add_note ( wt , MSG_INFO ,
@ -653,11 +671,12 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
pos + = 8 ;
os_memcpy ( pos , eapol , sizeof ( * eapol ) ) ;
pos + = sizeof ( * eapol ) ;
os_memcpy ( pos , hdr , sizeof ( * hdr ) ) ;
os_memcpy ( pos , hdr , sizeof ( * hdr ) + mic_len ) ;
k = ( struct wpa_eapol_key * ) pos ;
pos + = sizeof ( struct wpa_eapol_key ) + mic_len ;
WPA_PUT_BE16 ( k - > key_info ,
key_info & ~ WPA_KEY_INFO_ENCR_KEY_DATA ) ;
WPA_PUT_BE16 ( k- > key_data_length , plain_len ) ;
WPA_PUT_BE16 ( pos , plain_len ) ;
write_pcap_decrypted ( wt , buf , sizeof ( buf ) ,
decrypted , plain_len ) ;
}
@ -770,6 +789,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
u16 key_info , ver ;
u8 * decrypted ;
size_t decrypted_len = 0 ;
size_t mic_len ;
wpa_printf ( MSG_DEBUG , " EAPOL-Key 1/2 " MACSTR " -> " MACSTR ,
MAC2STR ( src ) , MAC2STR ( dst ) ) ;
@ -779,6 +799,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
sta = sta_get ( bss , dst ) ;
if ( sta = = NULL )
return ;
mic_len = wpa_mic_len ( sta - > key_mgmt ) ;
eapol = ( const struct ieee802_1x_hdr * ) data ;
hdr = ( const struct wpa_eapol_key * ) ( eapol + 1 ) ;
@ -805,7 +826,8 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
return ;
}
ver = key_info & WPA_KEY_INFO_TYPE_MASK ;
decrypted = decrypt_eapol_key_data ( wt , sta - > ptk . kek , sta - > ptk . kek_len ,
decrypted = decrypt_eapol_key_data ( wt , sta - > key_mgmt ,
sta - > ptk . kek , sta - > ptk . kek_len ,
ver , hdr , & decrypted_len ) ;
if ( decrypted = = NULL ) {
add_note ( wt , MSG_INFO , " Failed to decrypt EAPOL-Key Key Data " ) ;
@ -843,11 +865,12 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
pos + = 8 ;
os_memcpy ( pos , eapol , sizeof ( * eapol ) ) ;
pos + = sizeof ( * eapol ) ;
os_memcpy ( pos , hdr , sizeof ( * hdr ) ) ;
os_memcpy ( pos , hdr , sizeof ( * hdr ) + mic_len ) ;
k = ( struct wpa_eapol_key * ) pos ;
pos + = sizeof ( struct wpa_eapol_key ) + mic_len ;
WPA_PUT_BE16 ( k - > key_info ,
key_info & ~ WPA_KEY_INFO_ENCR_KEY_DATA ) ;
WPA_PUT_BE16 ( k- > key_data_length , plain_len ) ;
WPA_PUT_BE16 ( pos , plain_len ) ;
write_pcap_decrypted ( wt , buf , sizeof ( buf ) ,
decrypted , plain_len ) ;
}
@ -926,7 +949,8 @@ static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
}
static void rx_data_eapol_key ( struct wlantest * wt , const u8 * dst ,
static void rx_data_eapol_key ( struct wlantest * wt , const u8 * bssid ,
const u8 * sta_addr , const u8 * dst ,
const u8 * src , const u8 * data , size_t len ,
int prot )
{
@ -934,17 +958,29 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
const struct wpa_eapol_key * hdr ;
const u8 * key_data ;
u16 key_info , key_length , ver , key_data_length ;
size_t mic_len = 16 ;
const u8 * mic ;
struct wlantest_bss * bss ;
struct wlantest_sta * sta ;
bss = bss_get ( wt , bssid ) ;
if ( bss ) {
sta = sta_get ( bss , sta_addr ) ;
if ( sta )
mic_len = wpa_mic_len ( sta - > key_mgmt ) ;
}
eapol = ( const struct ieee802_1x_hdr * ) data ;
hdr = ( const struct wpa_eapol_key * ) ( eapol + 1 ) ;
wpa_hexdump ( MSG_MSGDUMP , " EAPOL-Key " ,
( const u8 * ) hdr , len - sizeof ( * eapol ) ) ;
if ( len < sizeof ( * hdr ) ) {
if ( len < sizeof ( * hdr ) + mic_len + 2 ) {
add_note ( wt , MSG_INFO , " Too short EAPOL-Key frame from " MACSTR ,
MAC2STR ( src ) ) ;
return ;
}
mic = ( const u8 * ) ( hdr + 1 ) ;
if ( hdr - > type = = EAPOL_KEY_TYPE_RC4 ) {
/* TODO: EAPOL-Key RC4 for WEP */
@ -962,8 +998,8 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
key_info = WPA_GET_BE16 ( hdr - > key_info ) ;
key_length = WPA_GET_BE16 ( hdr - > key_length ) ;
key_data_length = WPA_GET_BE16 ( hdr- > key_data_length ) ;
key_data = ( const u8 * ) ( hdr + 1 ) ;
key_data_length = WPA_GET_BE16 ( mic + mic_len ) ;
key_data = mic + mic_len + 2 ;
if ( key_data + key_data_length > data + len ) {
add_note ( wt , MSG_INFO , " Truncated EAPOL-Key from " MACSTR ,
MAC2STR ( src ) ) ;
@ -1010,7 +1046,7 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
wpa_hexdump ( MSG_MSGDUMP , " EAPOL-Key RSC " ,
hdr - > key_rsc , WPA_KEY_RSC_LEN ) ;
wpa_hexdump ( MSG_MSGDUMP , " EAPOL-Key Key MIC " ,
hdr- > key_mic , 16 ) ;
mic, mic_len ) ;
wpa_hexdump ( MSG_MSGDUMP , " EAPOL-Key Key Data " ,
key_data , key_data_length ) ;
@ -1120,7 +1156,8 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
}
void rx_data_eapol ( struct wlantest * wt , const u8 * dst , const u8 * src ,
void rx_data_eapol ( struct wlantest * wt , const u8 * bssid , const u8 * sta_addr ,
const u8 * dst , const u8 * src ,
const u8 * data , size_t len , int prot )
{
const struct ieee802_1x_hdr * hdr ;
@ -1167,8 +1204,8 @@ void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
wpa_hexdump ( MSG_MSGDUMP , " EAPOL-Logoff " , p , length ) ;
break ;
case IEEE802_1X_TYPE_EAPOL_KEY :
rx_data_eapol_key ( wt , dst, src , data , sizeof ( * hdr ) + length ,
prot ) ;
rx_data_eapol_key ( wt , bssid, sta_addr , dst , src , data ,
sizeof ( * hdr ) + length , prot ) ;
break ;
case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT :
wpa_hexdump ( MSG_MSGDUMP , " EAPOL - Encapsulated ASF alert " ,