From 0a76a0b96557a129fb11f17f84fdb6d7418dbe32 Mon Sep 17 00:00:00 2001 From: Hu Wang Date: Thu, 5 Mar 2020 19:20:38 +0800 Subject: [PATCH] OWE: Fix PTK derivation workaround for interoperability The initial implementation of the PTK derivation workaround for interoperability with older OWE implementations forced WPA_KEY_MGMT_PSK_SHA256 to be used for all of PTK derivation. While that is needed for selecting which hash algorithm to use, this was also changing the length of the PTK components and by doing so, did not actually address the backwards compatibility issue. Fix this by forcing SHA256 as the hash algorithm in PTK derivation without changing the PTK length calculation for OWE when owe_ptk_workaround is enabled. Fixes: 65a44e849af9 ("OWE: PTK derivation workaround in AP mode") Fixes: 8b138d28264e ("OWE: PTK derivation workaround in STA mode") Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 2 +- src/common/wpa_common.c | 11 ++++++++++- src/rsn_supp/wpa.c | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index e67c34498..07cc514d9 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2286,7 +2286,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, akmp = sm->wpa_key_mgmt; if (force_sha256) - akmp = WPA_KEY_MGMT_PSK_SHA256; + akmp |= WPA_KEY_MGMT_PSK_SHA256; return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, ptk, akmp, sm->pairwise, z, z_len); diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index ee306ff50..c63d7bce1 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -355,6 +355,14 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, size_t data_len = 2 * ETH_ALEN + 2 * WPA_NONCE_LEN; u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; size_t ptk_len; +#ifdef CONFIG_OWE + int owe_ptk_workaround = 0; + + if (akmp == (WPA_KEY_MGMT_OWE | WPA_KEY_MGMT_PSK_SHA256)) { + owe_ptk_workaround = 1; + akmp = WPA_KEY_MGMT_OWE; + } +#endif /* CONFIG_OWE */ if (pmk_len == 0) { wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation"); @@ -413,7 +421,8 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, tmp, ptk_len) < 0) return -1; #ifdef CONFIG_OWE - } else if (akmp == WPA_KEY_MGMT_OWE && pmk_len == 32) { + } else if (akmp == WPA_KEY_MGMT_OWE && (pmk_len == 32 || + owe_ptk_workaround)) { wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)"); if (sha256_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 4ead4c516..548da45f6 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -598,7 +598,7 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, sm->pmk_len > 32) { wpa_printf(MSG_DEBUG, "OWE: Force SHA256 for PTK derivation"); - akmp = WPA_KEY_MGMT_PSK_SHA256; + akmp |= WPA_KEY_MGMT_PSK_SHA256; } #endif /* CONFIG_OWE */ return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",