diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index ff00b2813..c7e8ec7a3 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2126,17 +2126,21 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, if (fils_ft_len) { struct wpa_authenticator *wpa_auth = sm->wpa_auth; struct wpa_auth_config *conf = &wpa_auth->conf; - u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN]; + u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN]; + int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; if (wpa_derive_pmk_r0(fils_ft, fils_ft_len, conf->ssid, conf->ssid_len, conf->mobility_domain, conf->r0_key_holder, conf->r0_key_holder_len, - sm->addr, pmk_r0, pmk_r0_name) < 0) + sm->addr, pmk_r0, pmk_r0_name, + use_sha384) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", pmk_r0, PMK_LEN); + wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", + pmk_r0, pmk_r0_len); wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 52e5779d9..d6735a124 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -1980,7 +1980,8 @@ int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, const u8 *identity, *radius_cui; size_t identity_len, radius_cui_len; int session_timeout; - size_t pmk_r0_len = PMK_LEN; + size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ? + SHA384_MAC_LEN : PMK_LEN; if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR, @@ -2004,7 +2005,8 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_ptk *ptk) { u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN]; - size_t pmk_r0_len = PMK_LEN; + size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ? + SHA384_MAC_LEN : PMK_LEN; size_t pmk_r1_len = pmk_r0_len; u8 pmk_r1[PMK_LEN_MAX]; u8 ptk_name[WPA_PMK_NAME_LEN]; @@ -2040,7 +2042,8 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid, r0kh, r0kh_len, sm->addr, - pmk_r0, pmk_r0_name) < 0) + pmk_r0, pmk_r0_name, + wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0) return -1; wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len); wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); @@ -2512,7 +2515,7 @@ static int wpa_ft_psk_pmk_r1(struct wpa_state_machine *sm, if (wpa_derive_pmk_r0(pmk, PMK_LEN, ssid, ssid_len, mdid, r0kh, r0kh_len, sm->addr, - pmk_r0, pmk_r0_name) < 0 || + pmk_r0, pmk_r0_name, 0) < 0 || wpa_derive_pmk_r1(pmk_r0, PMK_LEN, pmk_r0_name, r1kh, sm->addr, pmk_r1, pmk_r1_name) < 0 || os_memcmp_const(pmk_r1_name, req_pmk_r1_name, diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 9a79e0ce1..02f539511 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -1420,24 +1420,36 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, const u8 *ssid, size_t ssid_len, const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) + const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name, + int use_sha384) { u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + FT_R0KH_ID_MAX_LEN + ETH_ALEN]; - u8 *pos, r0_key_data[48], hash[32]; + u8 *pos, r0_key_data[64], hash[32]; const u8 *addr[2]; size_t len[2]; + size_t q = use_sha384 ? 48 : 32; + size_t r0_key_data_len = q + 16; /* * R0-Key-Data = KDF-384(XXKey, "FT-R0", * SSIDlength || SSID || MDID || R0KHlength || * R0KH-ID || S0KH-ID) - * XXKey is either the second 256 bits of MSK or PSK. - * PMK-R0 = L(R0-Key-Data, 0, 256) - * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) + * XXKey is either the second 256 bits of MSK or PSK; or the first + * 384 bits of MSK for FT-EAP-SHA384. + * PMK-R0 = L(R0-Key-Data, 0, Q) + * PMK-R0Name-Salt = L(R0-Key-Data, Q, 128) + * Q = 384 for FT-EAP-SHA384; otherwise, 256 */ if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) return -1; + wpa_printf(MSG_DEBUG, "FT: Derive PMK-R0 using KDF-%s", + use_sha384 ? "SHA384" : "SHA256"); + wpa_hexdump_key(MSG_DEBUG, "FT: XXKey", xxkey, xxkey_len); + wpa_hexdump_ascii(MSG_DEBUG, "FT: SSID", ssid, ssid_len); + wpa_hexdump(MSG_DEBUG, "FT: MDID", mdid, MOBILITY_DOMAIN_ID_LEN); + wpa_hexdump_ascii(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len); + wpa_printf(MSG_DEBUG, "FT: S0KH-ID: " MACSTR, MAC2STR(s0kh_id)); pos = buf; *pos++ = ssid_len; os_memcpy(pos, ssid, ssid_len); @@ -1450,22 +1462,46 @@ int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, os_memcpy(pos, s0kh_id, ETH_ALEN); pos += ETH_ALEN; - if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, - r0_key_data, sizeof(r0_key_data)) < 0) - return -1; - os_memcpy(pmk_r0, r0_key_data, PMK_LEN); +#ifdef CONFIG_SHA384 + if (use_sha384) { + if (xxkey_len != SHA384_MAC_LEN) { + wpa_printf(MSG_ERROR, + "FT: Unexpected XXKey length %d (expected %d)", + (int) xxkey_len, SHA384_MAC_LEN); + return -1; + } + if (sha384_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, + r0_key_data, r0_key_data_len) < 0) + return -1; + } +#endif /* CONFIG_SHA384 */ + if (!use_sha384) { + if (xxkey_len != PMK_LEN) { + wpa_printf(MSG_ERROR, + "FT: Unexpected XXKey length %d (expected %d)", + (int) xxkey_len, PMK_LEN); + return -1; + } + if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, + r0_key_data, r0_key_data_len) < 0) + return -1; + } + os_memcpy(pmk_r0, r0_key_data, q); + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, q); + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0Name-Salt", &r0_key_data[q], 16); /* * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) */ addr[0] = (const u8 *) "FT-R0N"; len[0] = 6; - addr[1] = r0_key_data + PMK_LEN; + addr[1] = &r0_key_data[q]; len[1] = 16; if (sha256_vector(2, addr, len, hash) < 0) return -1; os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); + os_memset(r0_key_data, 0, sizeof(r0_key_data)); return 0; } diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 3843167f0..bb0765acf 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -364,7 +364,8 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, const u8 *ssid, size_t ssid_len, const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name); + const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name, + int use_sha384); int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1_name); int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len, diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 226cafaf6..4dd209b38 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3747,6 +3747,7 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) struct rsn_ie_hdr *rsnie; u16 capab; u8 *pos; + int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); /* RSNIE[PMKR0Name/PMKR1Name] */ rsnie = wpabuf_put(buf, sizeof(*rsnie)); @@ -3814,11 +3815,13 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) if (wpa_derive_pmk_r0(sm->fils_ft, sm->fils_ft_len, sm->ssid, sm->ssid_len, sm->mobility_domain, sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, - sm->pmk_r0, sm->pmk_r0_name) < 0) { + sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) { wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMK-R0"); return -1; } - wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", sm->pmk_r0, PMK_LEN); + sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; + wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", + sm->pmk_r0, sm->pmk_r0_len); wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", sm->pmk_r0_name, WPA_PMK_NAME_LEN); wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR, diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index da1ce39f0..696571222 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -10,6 +10,7 @@ #include "common.h" #include "crypto/aes_wrap.h" +#include "crypto/sha384.h" #include "crypto/random.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" @@ -23,6 +24,7 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, { u8 ptk_name[WPA_PMK_NAME_LEN]; const u8 *anonce = key->key_nonce; + int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); if (sm->xxkey_len == 0) { wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " @@ -30,11 +32,11 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, return -1; } - sm->pmk_r0_len = PMK_LEN; + sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid, sm->ssid_len, sm->mobility_domain, sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, - sm->pmk_r0, sm->pmk_r0_name) < 0) + sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) return -1; wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, sm->pmk_r0_len); wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 069e63476..9c52fbac4 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -109,7 +109,7 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss, wpa_derive_pmk_r0(pmk->pmk, PMK_LEN, bss->ssid, bss->ssid_len, bss->mdid, bss->r0kh_id, bss->r0kh_id_len, - sta->addr, pmk_r0, pmk_r0_name); + sta->addr, pmk_r0, pmk_r0_name, 0); wpa_hexdump(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);