OWE: PTK derivation workaround in AP mode

Initial OWE implementation used SHA256 when deriving the PTK for all OWE
groups. This was supposed to change to SHA384 for group 20 and SHA512
for group 21. The new owe_ptk_workaround parameter can be used to enable
workaround for interoperability with stations that use SHA256 with
groups 20 and 21. By default, only the appropriate hash function is
accepted. When workaround is enabled (owe_ptk_workaround=1), the
appropriate hash function is tried first and if that fails, SHA256-based
PTK derivation is attempted. This workaround can result in reduced
security for groups 20 and 21, but is required for interoperability with
older implementations. There is no impact to group 19 behavior.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2020-01-23 20:56:51 +02:00 committed by Jouni Malinen
parent bd50805e40
commit 65a44e849a
6 changed files with 42 additions and 5 deletions

View file

@ -4412,6 +4412,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
} else if (os_strcmp(buf, "owe_ptk_workaround") == 0) {
bss->owe_ptk_workaround = atoi(pos);
#endif /* CONFIG_OWE */
} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
bss->coloc_intf_reporting = atoi(pos);

View file

@ -1817,6 +1817,19 @@ own_ip_addr=127.0.0.1
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
#owe_groups=19 20 21
# OWE PTK derivation workaround
# Initial OWE implementation used SHA256 when deriving the PTK for all OWE
# groups. This was supposed to change to SHA384 for group 20 and SHA512 for
# group 21. This parameter can be used to enable workaround for interoperability
# with stations that use SHA256 with groups 20 and 21. By default (0) only the
# appropriate hash function is accepted. When workaround is enabled (1), the
# appropriate hash function is tried first and if that fails, SHA256-based PTK
# derivation is attempted. This workaround can result in reduced security for
# groups 20 and 21, but is required for interoperability with older
# implementations. There is no impact to group 19 behavior. The workaround is
# disabled by default and can be enabled by uncommenting the following line.
#owe_ptk_workaround=1
# OWE transition mode configuration
# Pointer to the matching open/OWE BSS
#owe_transition_bssid=<bssid>

View file

@ -733,6 +733,7 @@ struct hostapd_bss_config {
size_t owe_transition_ssid_len;
char owe_transition_ifname[IFNAMSIZ + 1];
int *owe_groups;
int owe_ptk_workaround;
#endif /* CONFIG_OWE */
int coloc_intf_reporting;

View file

@ -56,7 +56,7 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, unsigned int pmk_len,
struct wpa_ptk *ptk);
struct wpa_ptk *ptk, int force_sha256);
static void wpa_group_free(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_group_get(struct wpa_authenticator *wpa_auth,
@ -926,7 +926,8 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
pmk_len = sm->pmk_len;
}
if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0)
if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
0)
break;
if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
@ -2233,10 +2234,11 @@ SM_STATE(WPA_PTK, PTKSTART)
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, unsigned int pmk_len,
struct wpa_ptk *ptk)
struct wpa_ptk *ptk, int force_sha256)
{
const u8 *z = NULL;
size_t z_len = 0;
int akmp;
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
@ -2262,9 +2264,12 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
}
#endif /* CONFIG_DPP2 */
akmp = sm->wpa_key_mgmt;
if (force_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, sm->wpa_key_mgmt, sm->pairwise, z, z_len);
ptk, akmp, sm->pairwise, z, z_len);
}
@ -2844,6 +2849,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
struct wpa_eapol_key *key;
struct wpa_eapol_ie_parse kde;
int vlan_id = 0;
int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
sm->EAPOLKeyReceived = FALSE;
@ -2881,7 +2887,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
pmk_len = sm->pmksa->pmk_len;
}
if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0)
if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
owe_ptk_workaround == 2) < 0)
break;
if (mic_len &&
@ -2905,6 +2912,16 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
}
#endif /* CONFIG_FILS */
#ifdef CONFIG_OWE
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
owe_ptk_workaround == 1) {
wpa_printf(MSG_DEBUG,
"OWE: Try PTK derivation workaround with SHA256");
owe_ptk_workaround = 2;
continue;
}
#endif /* CONFIG_OWE */
if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
wpa_key_mgmt_sae(sm->wpa_key_mgmt))
break;

View file

@ -237,6 +237,7 @@ struct wpa_auth_config {
u8 fils_cache_id[FILS_CACHE_ID_LEN];
#endif /* CONFIG_FILS */
int sae_pwe;
int owe_ptk_workaround;
};
typedef enum {

View file

@ -162,6 +162,9 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->sae_pwe = 1;
else if (sae_pw_id == 1 && wconf->sae_pwe == 0)
wconf->sae_pwe = 2;
#ifdef CONFIG_OWE
wconf->owe_ptk_workaround = conf->owe_ptk_workaround;
#endif /* CONFIG_OWE */
}