@ -1066,7 +1066,7 @@ static void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
res = wpa_validate_wpa_ie ( hapd - > wpa_auth , sta - > wpa_sm ,
elems . rsn_ie - 2 , elems . rsn_ie_len + 2 ,
elems . mdie , elems . mdie_len );
elems . mdie , elems . mdie_len , NULL , 0 );
resp = wpa_res_to_status_code ( res ) ;
if ( resp ! = WLAN_STATUS_SUCCESS )
goto fail ;
@ -1893,6 +1893,100 @@ static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
}
# ifdef CONFIG_OWE
static u16 owe_process_assoc_req ( struct sta_info * sta , const u8 * owe_dh ,
u8 owe_dh_len )
{
struct wpabuf * secret , * pub , * hkey ;
int res ;
u8 prk [ SHA256_MAC_LEN ] , pmkid [ SHA256_MAC_LEN ] ;
const char * info = " OWE Key Generation " ;
const u8 * addr [ 2 ] ;
size_t len [ 2 ] ;
if ( WPA_GET_LE16 ( owe_dh ) ! = OWE_DH_GROUP )
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED ;
crypto_ecdh_deinit ( sta - > owe_ecdh ) ;
sta - > owe_ecdh = crypto_ecdh_init ( OWE_DH_GROUP ) ;
if ( ! sta - > owe_ecdh )
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED ;
secret = crypto_ecdh_set_peerkey ( sta - > owe_ecdh , 0 , owe_dh + 2 ,
owe_dh_len - 2 ) ;
if ( ! secret ) {
wpa_printf ( MSG_DEBUG , " OWE: Invalid peer DH public key " ) ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
}
wpa_hexdump_buf_key ( MSG_DEBUG , " OWE: DH shared secret " , secret ) ;
/* prk = HKDF-extract(C | A | group, z) */
pub = crypto_ecdh_get_pubkey ( sta - > owe_ecdh , 0 ) ;
if ( ! pub ) {
wpabuf_clear_free ( secret ) ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
}
/* PMKID = Truncate-128(Hash(C | A)) */
addr [ 0 ] = owe_dh + 2 ;
len [ 0 ] = owe_dh_len - 2 ;
addr [ 1 ] = wpabuf_head ( pub ) ;
len [ 1 ] = wpabuf_len ( pub ) ;
res = sha256_vector ( 2 , addr , len , pmkid ) ;
if ( res < 0 ) {
wpabuf_free ( pub ) ;
wpabuf_clear_free ( secret ) ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
}
hkey = wpabuf_alloc ( owe_dh_len - 2 + wpabuf_len ( pub ) + 2 ) ;
if ( ! hkey ) {
wpabuf_free ( pub ) ;
wpabuf_clear_free ( secret ) ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
}
wpabuf_put_data ( hkey , owe_dh + 2 , owe_dh_len - 2 ) ; /* C */
wpabuf_put_buf ( hkey , pub ) ; /* A */
wpabuf_free ( pub ) ;
wpabuf_put_le16 ( hkey , OWE_DH_GROUP ) ; /* group */
res = hmac_sha256 ( wpabuf_head ( hkey ) , wpabuf_len ( hkey ) ,
wpabuf_head ( secret ) , wpabuf_len ( secret ) , prk ) ;
wpabuf_clear_free ( hkey ) ;
wpabuf_clear_free ( secret ) ;
if ( res < 0 )
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
wpa_hexdump_key ( MSG_DEBUG , " OWE: prk " , prk , SHA256_MAC_LEN ) ;
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
os_free ( sta - > owe_pmk ) ;
sta - > owe_pmk = os_malloc ( PMK_LEN ) ;
if ( ! sta - > owe_pmk ) {
os_memset ( prk , 0 , SHA256_MAC_LEN ) ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
}
res = hmac_sha256_kdf ( prk , SHA256_MAC_LEN , NULL , ( const u8 * ) info ,
os_strlen ( info ) , sta - > owe_pmk , PMK_LEN ) ;
os_memset ( prk , 0 , SHA256_MAC_LEN ) ;
if ( res < 0 ) {
os_free ( sta - > owe_pmk ) ;
sta - > owe_pmk = NULL ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
}
wpa_hexdump_key ( MSG_DEBUG , " OWE: PMK " , sta - > owe_pmk , PMK_LEN ) ;
wpa_hexdump ( MSG_DEBUG , " OWE: PMKID " , pmkid , PMKID_LEN ) ;
/* TODO: Add PMKSA cache entry */
return WLAN_STATUS_SUCCESS ;
}
# endif /* CONFIG_OWE */
static u16 check_assoc_ies ( struct hostapd_data * hapd , struct sta_info * sta ,
const u8 * ies , size_t ies_len , int reassoc )
{
@ -2034,7 +2128,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
}
res = wpa_validate_wpa_ie ( hapd - > wpa_auth , sta - > wpa_sm ,
wpa_ie , wpa_ie_len ,
elems . mdie , elems . mdie_len ) ;
elems . mdie , elems . mdie_len ,
elems . owe_dh , elems . owe_dh_len ) ;
resp = wpa_res_to_status_code ( res ) ;
if ( resp ! = WLAN_STATUS_SUCCESS )
return resp ;
@ -2104,6 +2199,17 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
}
# endif /* CONFIG_SAE */
# ifdef CONFIG_OWE
if ( ( hapd - > conf - > wpa_key_mgmt & WPA_KEY_MGMT_OWE ) & &
wpa_auth_sta_key_mgmt ( sta - > wpa_sm ) = = WPA_KEY_MGMT_OWE & &
elems . owe_dh ) {
resp = owe_process_assoc_req ( sta , elems . owe_dh ,
elems . owe_dh_len ) ;
if ( resp ! = WLAN_STATUS_SUCCESS )
return resp ;
}
# endif /* CONFIG_OWE */
# ifdef CONFIG_IEEE80211N
if ( ( sta - > flags & ( WLAN_STA_HT | WLAN_STA_VHT ) ) & &
wpa_auth_get_pairwise ( sta - > wpa_sm ) = = WPA_CIPHER_TKIP ) {
@ -2282,6 +2388,10 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
if ( sta & & sta - > fils_hlp_resp )
buflen + = wpabuf_len ( sta - > fils_hlp_resp ) ;
# endif /* CONFIG_FILS */
# ifdef CONFIG_OWE
if ( sta & & ( hapd - > conf - > wpa_key_mgmt & WPA_KEY_MGMT_OWE ) )
buflen + = 50 ;
# endif /* CONFIG_OWE */
buf = os_zalloc ( buflen ) ;
if ( ! buf ) {
res = WLAN_STATUS_UNSPECIFIED_FAILURE ;
@ -2458,6 +2568,30 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
}
# endif /* CONFIG_FILS */
# ifdef CONFIG_OWE
if ( ( hapd - > conf - > wpa_key_mgmt & WPA_KEY_MGMT_OWE ) & &
sta & & sta - > owe_ecdh & &
wpa_auth_sta_key_mgmt ( sta - > wpa_sm ) = = WPA_KEY_MGMT_OWE ) {
struct wpabuf * pub ;
pub = crypto_ecdh_get_pubkey ( sta - > owe_ecdh , 0 ) ;
if ( ! pub ) {
res = WLAN_STATUS_UNSPECIFIED_FAILURE ;
goto done ;
}
/* OWE Diffie-Hellman Parameter element */
* p + + = WLAN_EID_EXTENSION ; /* Element ID */
* p + + = 1 + 2 + wpabuf_len ( pub ) ; /* Length */
* p + + = WLAN_EID_EXT_OWE_DH_PARAM ; /* Element ID Extension */
WPA_PUT_LE16 ( p , OWE_DH_GROUP ) ;
p + = 2 ;
os_memcpy ( p , wpabuf_head ( pub ) , wpabuf_len ( pub ) ) ;
p + = wpabuf_len ( pub ) ;
send_len + = 3 + 2 + wpabuf_len ( pub ) ;
wpabuf_free ( pub ) ;
}
# endif /* CONFIG_OWE */
if ( hostapd_drv_send_mlme ( hapd , reply , send_len , 0 ) < 0 ) {
wpa_printf ( MSG_INFO , " Failed to send assoc resp: %s " ,
strerror ( errno ) ) ;