@ -14,6 +14,8 @@
# include "utils/eloop.h"
# include "crypto/crypto.h"
# include "crypto/sha256.h"
# include "crypto/sha384.h"
# include "crypto/sha512.h"
# include "crypto/random.h"
# include "common/ieee802_11_defs.h"
# include "common/ieee802_11_common.h"
@ -2131,21 +2133,32 @@ static u16 owe_process_assoc_req(struct sta_info *sta, const u8 *owe_dh,
{
struct wpabuf * secret , * pub , * hkey ;
int res ;
u8 prk [ SHA 256_MAC_LEN] , pmkid [ SHA256 _MAC_LEN] ;
u8 prk [ SHA 512_MAC_LEN] , pmkid [ SHA512 _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 )
u16 group ;
size_t hash_len , prime_len ;
group = WPA_GET_LE16 ( owe_dh ) ;
if ( group = = 19 )
prime_len = 32 ;
else if ( group = = 20 )
prime_len = 48 ;
else if ( group = = 21 )
prime_len = 66 ;
else
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED ;
crypto_ecdh_deinit ( sta - > owe_ecdh ) ;
sta - > owe_ecdh = crypto_ecdh_init ( OWE_DH_GROUP ) ;
sta - > owe_ecdh = crypto_ecdh_init ( group ) ;
if ( ! sta - > owe_ecdh )
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED ;
sta - > owe_group = group ;
secret = crypto_ecdh_set_peerkey ( sta - > owe_ecdh , 0 , owe_dh + 2 ,
owe_dh_len - 2 ) ;
secret = wpabuf_zeropad ( secret , prime_len ) ;
if ( ! secret ) {
wpa_printf ( MSG_DEBUG , " OWE: Invalid peer DH public key " ) ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
@ -2165,8 +2178,22 @@ static u16 owe_process_assoc_req(struct sta_info *sta, const u8 *owe_dh,
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 ) {
if ( group = = 19 ) {
res = sha256_vector ( 2 , addr , len , pmkid ) ;
hash_len = SHA256_MAC_LEN ;
} else if ( group = = 20 ) {
res = sha384_vector ( 2 , addr , len , pmkid ) ;
hash_len = SHA384_MAC_LEN ;
} else if ( group = = 21 ) {
res = sha512_vector ( 2 , addr , len , pmkid ) ;
hash_len = SHA512_MAC_LEN ;
} else {
wpabuf_free ( pub ) ;
wpabuf_clear_free ( secret ) ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
}
pub = wpabuf_zeropad ( pub , prime_len ) ;
if ( res < 0 | | ! pub ) {
wpabuf_free ( pub ) ;
wpabuf_clear_free ( secret ) ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
@ -2182,35 +2209,50 @@ static u16 owe_process_assoc_req(struct sta_info *sta, const u8 *owe_dh,
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_put_le16 ( hkey , group ) ; /* group */
if ( group = = 19 )
res = hmac_sha256 ( wpabuf_head ( hkey ) , wpabuf_len ( hkey ) ,
wpabuf_head ( secret ) , wpabuf_len ( secret ) , prk ) ;
else if ( group = = 20 )
res = hmac_sha384 ( wpabuf_head ( hkey ) , wpabuf_len ( hkey ) ,
wpabuf_head ( secret ) , wpabuf_len ( secret ) , prk ) ;
else if ( group = = 21 )
res = hmac_sha512 ( 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 ) ;
wpa_hexdump_key ( MSG_DEBUG , " OWE: prk " , prk , hash_len ) ;
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
os_free ( sta - > owe_pmk ) ;
sta - > owe_pmk = os_malloc ( PMK_LEN ) ;
sta - > owe_pmk = os_malloc ( hash_len ) ;
if ( ! sta - > owe_pmk ) {
os_memset ( prk , 0 , SHA 256 _MAC_LEN) ;
os_memset ( prk , 0 , SHA 512 _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 ( group = = 19 )
res = hmac_sha256_kdf ( prk , hash_len , NULL , ( const u8 * ) info ,
os_strlen ( info ) , sta - > owe_pmk , hash_len ) ;
else if ( group = = 20 )
res = hmac_sha384_kdf ( prk , hash_len , NULL , ( const u8 * ) info ,
os_strlen ( info ) , sta - > owe_pmk , hash_len ) ;
else if ( group = = 21 )
res = hmac_sha512_kdf ( prk , hash_len , NULL , ( const u8 * ) info ,
os_strlen ( info ) , sta - > owe_pmk , hash_len ) ;
os_memset ( prk , 0 , SHA512_MAC_LEN ) ;
if ( res < 0 ) {
os_free ( sta - > owe_pmk ) ;
sta - > owe_pmk = NULL ;
return WLAN_STATUS_UNSPECIFIED_FAILURE ;
}
sta - > owe_pmk_len = hash_len ;
wpa_hexdump_key ( MSG_DEBUG , " OWE: PMK " , sta - > owe_pmk , PMK_LEN ) ;
wpa_hexdump_key ( MSG_DEBUG , " OWE: PMK " , sta - > owe_pmk , sta- > owe_pmk_len ) ;
wpa_hexdump ( MSG_DEBUG , " OWE: PMKID " , pmkid , PMKID_LEN ) ;
/* TODO: Add PMKSA cache entry */
@ -2822,7 +2864,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
* 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 ) ;
WPA_PUT_LE16 ( p , sta- > owe_group ) ;
p + = 2 ;
os_memcpy ( p , wpabuf_head ( pub ) , wpabuf_len ( pub ) ) ;
p + = wpabuf_len ( pub ) ;