#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"
{
struct wpabuf *secret, *pub, *hkey;
int res;
- u8 prk[SHA256_MAC_LEN], pmkid[SHA256_MAC_LEN];
+ u8 prk[SHA512_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;
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;
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, SHA256_MAC_LEN);
+ os_memset(prk, 0, SHA512_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 */
*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);
static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
const u8 *addr,
const u8 *p2p_dev_addr,
- const u8 *prev_psk)
+ const u8 *prev_psk, size_t *psk_len)
{
if (wpa_auth->cb->get_psk == NULL)
return NULL;
return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
- prev_psk);
+ prev_psk, psk_len);
}
struct wpa_ptk PTK;
int ok = 0;
const u8 *pmk = NULL;
- unsigned int pmk_len;
+ size_t pmk_len;
os_memset(&PTK, 0, sizeof(PTK));
for (;;) {
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
!wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
- sm->p2p_dev_addr, pmk);
+ sm->p2p_dev_addr, pmk, &pmk_len);
if (pmk == NULL)
break;
- pmk_len = PMK_LEN;
} else {
pmk = sm->PMK;
pmk_len = sm->pmk_len;
SM_STATE(WPA_PTK, INITPSK)
{
const u8 *psk;
+ size_t psk_len;
+
SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
- psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL);
+ psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
+ &psk_len);
if (psk) {
- os_memcpy(sm->PMK, psk, PMK_LEN);
- sm->pmk_len = PMK_LEN;
+ os_memcpy(sm->PMK, psk, psk_len);
+ sm->pmk_len = psk_len;
#ifdef CONFIG_IEEE80211R_AP
os_memcpy(sm->xxkey, psk, PMK_LEN);
sm->xxkey_len = PMK_LEN;
struct wpa_ptk PTK;
int ok = 0, psk_found = 0;
const u8 *pmk = NULL;
- unsigned int pmk_len;
+ size_t pmk_len;
int ft;
const u8 *eapol_key_ie, *key_data, *mic;
u16 key_data_length;
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
!wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
- sm->p2p_dev_addr, pmk);
+ sm->p2p_dev_addr, pmk, &pmk_len);
if (pmk == NULL)
break;
psk_found = 1;
- pmk_len = PMK_LEN;
} else {
pmk = sm->PMK;
pmk_len = sm->pmk_len;
break;
case WPA_PTK_INITPSK:
if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr,
- NULL)) {
+ NULL, NULL)) {
SM_ENTER(WPA_PTK, PTKSTART);
#ifdef CONFIG_SAE
} else if (wpa_auth_uses_sae(sm) && sm->pmksa) {