From ba3d435fe43495911d25b52522d88a98c399b527 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 27 Dec 2017 18:26:31 +0200 Subject: [PATCH] SAE: Add option to require MFP for SAE associations The new hostapd.conf parameter sae_require_pmf=<0/1> can now be used to enforce negotiation of MFP for all associations that negotiate use of SAE. This is used in cases where SAE-capable devices are known to be MFP-capable and the BSS is configured with optional MFP (ieee80211w=1) for legacy support. The non-SAE stations can connect without MFP while SAE stations are required to negotiate MFP if sae_require_mfp=1. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 ++ hostapd/hostapd.conf | 8 ++++++++ src/ap/ap_config.h | 1 + src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 1 + src/ap/wpa_auth_ie.c | 10 ++++++++++ 6 files changed, 23 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 3211e1d29..4cd34481c 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3643,6 +3643,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, pos); return 1; } + } else if (os_strcmp(buf, "sae_require_mfp") == 0) { + bss->sae_require_mfp = atoi(pos); } else if (os_strcmp(buf, "local_pwr_constraint") == 0) { int val = atoi(pos); if (val < 0 || val > 255) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 083942d1c..73e8fc39f 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1443,6 +1443,14 @@ own_ip_addr=127.0.0.1 # http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-9 #sae_groups=19 20 21 25 26 +# Require MFP for all associations using SAE +# This parameter can be used to enforce negotiation of MFP for all associations +# that negotiate use of SAE. This is used in cases where SAE-capable devices are +# known to be MFP-capable and the BSS is configured with optional MFP +# (ieee80211w=1) for legacy support. The non-SAE stations can connect without +# MFP while SAE stations are required to negotiate MFP if sae_require_mfp=1. +#sae_require_mfp=0 + # FILS Cache Identifier (16-bit value in hexdump format) #fils_cache_id=0011 diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index c21307220..304378234 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -585,6 +585,7 @@ struct hostapd_bss_config { unsigned int sae_anti_clogging_threshold; unsigned int sae_sync; + int sae_require_mfp; int *sae_groups; char *sae_password; diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index d21dd81c9..1bfacdc7a 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -177,6 +177,7 @@ struct wpa_auth_config { #ifdef CONFIG_IEEE80211W enum mfp_options ieee80211w; int group_mgmt_cipher; + int sae_require_mfp; #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R_AP u8 ssid[SSID_MAX_LEN]; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 98133a087..e2a42016d 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -59,6 +59,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, #ifdef CONFIG_IEEE80211W wconf->ieee80211w = conf->ieee80211w; wconf->group_mgmt_cipher = conf->group_mgmt_cipher; + wconf->sae_require_mfp = conf->sae_require_mfp; #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R_AP wconf->ssid_len = conf->ssid.ssid_len; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 0196d009e..64dd78773 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -725,6 +725,16 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } } +#ifdef CONFIG_SAE + if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_OPTIONAL && + wpa_key_mgmt_sae(sm->wpa_key_mgmt) && + !(data.capabilities & WPA_CAPABILITY_MFPC)) { + wpa_printf(MSG_DEBUG, + "Management frame protection required with SAE, but client did not enable it"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } +#endif /* CONFIG_SAE */ + if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || !(data.capabilities & WPA_CAPABILITY_MFPC)) sm->mgmt_frame_prot = 0;