From: Ilan Peer <ilan.peer@xxxxxxxxx> Add support for Authentication negotiated over IEEE Std 802.1X with key derivation function using SHA-384 Signed-off-by: Ilan Peer <ilan.peer@xxxxxxxxx> --- hostapd/config_file.c | 2 ++ hostapd/ctrl_iface.c | 8 ++++++++ src/ap/wpa_auth_ie.c | 11 +++++++++++ src/common/defs.h | 7 +++++-- src/common/wpa_common.c | 6 ++++++ src/drivers/driver_nl80211.c | 9 +++++++-- src/rsn_supp/preauth.c | 3 ++- src/rsn_supp/wpa.c | 2 ++ src/rsn_supp/wpa_ie.c | 4 ++++ wlantest/bss.c | 4 +++- wlantest/ctrl.c | 3 +++ wlantest/sta.c | 4 +++- wpa_supplicant/config.c | 13 +++++++++++++ wpa_supplicant/ctrl_iface.c | 10 ++++++++++ wpa_supplicant/dbus/dbus_new_handlers.c | 4 ++++ wpa_supplicant/dpp_supplicant.c | 2 +- wpa_supplicant/wpa_supplicant.c | 12 ++++++++++-- wpa_supplicant/wpas_glue.c | 3 ++- 18 files changed, 96 insertions(+), 11 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 8e179d1519..92ea23a31f 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -665,6 +665,8 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) #ifdef CONFIG_SHA384 else if (os_strcmp(start, "FT-EAP-SHA384") == 0) val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384; + else if (os_strcmp(start, "WPA-EAP-SHA384") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SHA384; #endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R_AP */ else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index b5a1c8a5d6..7395d2e331 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -956,6 +956,14 @@ static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd, pos += ret; } #endif /* CONFIG_DPP */ +#ifdef CONFIG_SHA384 + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) { + ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA384 "); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SHA384 */ if (pos > buf && *(pos - 1) == ' ') { *(pos - 1) = '\0'; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 43ccec9bed..35d095753d 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -205,6 +205,11 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, pos += RSN_SELECTOR_LEN; num_suites++; } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384); + pos += RSN_SELECTOR_LEN; + num_suites++; + } #endif /* CONFIG_SHA384 */ if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); @@ -705,6 +710,10 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else if (data.key_mgmt & WPA_KEY_MGMT_OSEN) selector = RSN_AUTH_KEY_MGMT_OSEN; #endif /* CONFIG_HS20 */ +#ifdef CONFIG_SHA384 + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) + selector = RSN_AUTH_KEY_MGMT_802_1X_SHA384; +#endif /* CONFIG_SHA384 */ wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; selector = wpa_cipher_to_suite(WPA_PROTO_RSN, @@ -781,6 +790,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_SHA384 else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384; + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384; #endif /* CONFIG_SHA384 */ else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; diff --git a/src/common/defs.h b/src/common/defs.h index c0c6dbe843..8cca094e8f 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -52,6 +52,7 @@ #define WPA_KEY_MGMT_PASN BIT(25) #define WPA_KEY_MGMT_SAE_EXT_KEY BIT(26) #define WPA_KEY_MGMT_FT_SAE_EXT_KEY BIT(27) +#define WPA_KEY_MGMT_IEEE8021X_SHA384 BIT(28) #define WPA_KEY_MGMT_FT (WPA_KEY_MGMT_FT_PSK | \ @@ -75,7 +76,8 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) WPA_KEY_MGMT_FILS_SHA256 | WPA_KEY_MGMT_FILS_SHA384 | WPA_KEY_MGMT_FT_FILS_SHA256 | - WPA_KEY_MGMT_FT_FILS_SHA384)); + WPA_KEY_MGMT_FT_FILS_SHA384 | + WPA_KEY_MGMT_IEEE8021X_SHA384)); } static inline int wpa_key_mgmt_wpa_psk_no_sae(int akm) @@ -153,7 +155,8 @@ static inline int wpa_key_mgmt_sha384(int akm) return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 | WPA_KEY_MGMT_FT_IEEE8021X_SHA384 | WPA_KEY_MGMT_FILS_SHA384 | - WPA_KEY_MGMT_FT_FILS_SHA384)); + WPA_KEY_MGMT_FT_FILS_SHA384 | + WPA_KEY_MGMT_IEEE8021X_SHA384)); } static inline int wpa_key_mgmt_suite_b(int akm) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 367af8f631..9a337517aa 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -1647,6 +1647,8 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) #ifdef CONFIG_SHA384 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384) return WPA_KEY_MGMT_FT_IEEE8021X_SHA384; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA384) + return WPA_KEY_MGMT_IEEE8021X_SHA384; #endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R */ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) @@ -2665,6 +2667,8 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) return "DPP"; case WPA_KEY_MGMT_PASN: return "PASN"; + case WPA_KEY_MGMT_IEEE8021X_SHA384: + return "WPA2-EAP-SHA384"; default: return "UNKNOWN"; } @@ -2715,6 +2719,8 @@ u32 wpa_akm_to_suite(int akm) return RSN_AUTH_KEY_MGMT_OWE; if (akm & WPA_KEY_MGMT_DPP) return RSN_AUTH_KEY_MGMT_DPP; + if (akm & WPA_KEY_MGMT_IEEE8021X_SHA384) + return RSN_AUTH_KEY_MGMT_802_1X_SHA384; return 0; } diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index eb25730c56..d0458dd596 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -6379,7 +6379,8 @@ retry: if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || params->key_mgmt_suite == WPA_KEY_MGMT_PSK || params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || - params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) { + params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 || + params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384) { wpa_printf(MSG_DEBUG, " * control port"); if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT)) goto fail; @@ -6679,7 +6680,8 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, params->key_mgmt_suite == WPA_KEY_MGMT_FT_FILS_SHA256 || params->key_mgmt_suite == WPA_KEY_MGMT_FT_FILS_SHA384 || params->key_mgmt_suite == WPA_KEY_MGMT_OWE || - params->key_mgmt_suite == WPA_KEY_MGMT_DPP) { + params->key_mgmt_suite == WPA_KEY_MGMT_DPP || + params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384) { u32 *mgmt; unsigned int akm_count = 1, i; @@ -6763,6 +6765,9 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, case WPA_KEY_MGMT_DPP: mgmt[0] = RSN_AUTH_KEY_MGMT_DPP; break; + case WPA_KEY_MGMT_IEEE8021X_SHA384: + mgmt[0] = RSN_AUTH_KEY_MGMT_802_1X_SHA384; + break; case WPA_KEY_MGMT_PSK: default: mgmt[0] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index 8f86820a76..1a288844a1 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -54,7 +54,8 @@ static int rsn_preauth_key_mgmt(int akmp) return !!(akmp & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_IEEE8021X_SHA256 | WPA_KEY_MGMT_IEEE8021X_SUITE_B | - WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)); + WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 | + WPA_KEY_MGMT_IEEE8021X_SHA384)); } diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 9c7c526fc0..b590589174 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3828,6 +3828,8 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm) return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B; case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192; + case WPA_KEY_MGMT_IEEE8021X_SHA384: + return RSN_AUTH_KEY_MGMT_802_1X_SHA384; default: return 0; } diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 2a6c79b263..d1510aad78 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -230,6 +230,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } else if (key_mgmt & WPA_KEY_MGMT_OSEN) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN); #endif /* CONFIG_HS20 */ +#ifdef CONFIG_SHA384 + } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA384) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384); +#endif /* CONFIG_SHA384 */ } else { wpa_printf(MSG_WARNING, "Invalid key management type (%d).", key_mgmt); diff --git a/wlantest/bss.c b/wlantest/bss.c index 4fc0b17a7b..f05803126d 100644 --- a/wlantest/bss.c +++ b/wlantest/bss.c @@ -296,7 +296,7 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, "pairwise=%s%s%s%s%s%s%s" "group=%s%s%s%s%s%s%s%s%s" "mgmt_group_cipher=%s%s%s%s%s" - "key_mgmt=%s%s%s%s%s%s%s%s%s%s%s%s%s%s" + "key_mgmt=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" "rsn_capab=%s%s%s%s%s%s%s%s%s%s", MAC2STR(bss->bssid), bss->proto == 0 ? "OPEN " : "", @@ -348,6 +348,8 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, "EAP-SUITE-B " : "", bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ? "EAP-SUITE-B-192 " : "", + bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384 ? + "EAP-SHA384 " : "", bss->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "", bss->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ? "NO_PAIRWISE " : "", diff --git a/wlantest/ctrl.c b/wlantest/ctrl.c index 587a0d3e1d..68a2b410ca 100644 --- a/wlantest/ctrl.c +++ b/wlantest/ctrl.c @@ -957,6 +957,9 @@ static void info_print_key_mgmt(char *buf, size_t len, int key_mgmt) if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) pos += os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192", pos == buf ? "" : " "); + if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) + pos += os_snprintf(pos, end - pos, "%sEAP-SHA384", + pos == buf ? "" : " "); } diff --git a/wlantest/sta.c b/wlantest/sta.c index 6b5573e3af..ea9728e980 100644 --- a/wlantest/sta.c +++ b/wlantest/sta.c @@ -242,7 +242,7 @@ skip_rsn_wpa: wpa_printf(MSG_INFO, "STA " MACSTR " proto=%s%s%s%s" "pairwise=%s%s%s%s%s%s%s" - "key_mgmt=%s%s%s%s%s%s%s%s%s%s%s%s%s%s" + "key_mgmt=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" "rsn_capab=%s%s%s%s%s%s%s%s%s%s", MAC2STR(sta->addr), sta->proto == 0 ? "OPEN " : "", @@ -276,6 +276,8 @@ skip_rsn_wpa: "EAP-SUITE-B " : "", sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ? "EAP-SUITE-B-192 " : "", + sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384 ? + "EAP-SHA384 " : "", sta->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "", sta->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ? "NO_PAIRWISE " : "", diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index de9b9b30fd..0d6130bc56 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -791,6 +791,8 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, #ifdef CONFIG_SHA384 else if (os_strcmp(start, "FT-EAP-SHA384") == 0) val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384; + else if (os_strcmp(start, "WPA-EAP-SHA384") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SHA384; #endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R */ else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) @@ -962,6 +964,17 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, } pos += ret; } + + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) { + ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA384", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + #endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 9abfeb2168..a0d11779a2 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2967,6 +2967,16 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, pos += ret; } +#ifdef CONFIG_SHA384 + if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) { + ret = os_snprintf(pos, end - pos, "%sEAP-SHA384", + pos == start ? "" : "+"); + if (os_snprintf_error(end - pos, ret)) + return pos; + pos += ret; + } +#endif /* CONFIG_SHA384 */ + pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); if (data.capabilities & WPA_CAPABILITY_PREAUTH) { diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 67ce970d01..0684489cd8 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -5341,6 +5341,10 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop( #endif /* CONFIG_OWE */ if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE) key_mgmt[n++] = "wpa-none"; +#ifdef CONFIG_SHA384 + if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) + key_mgmt[n++] = "wpa-eap-sha384"; +#endif /* CONFIG_SHA384 */ if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt", key_mgmt, n)) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index afadd789f7..a436fa564d 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1362,7 +1362,7 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_IEEE8021X_SHA256 | - WPA_KEY_MGMT_IEEE8021X_SHA256; + WPA_KEY_MGMT_IEEE8021X_SHA384; ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; if (conf->cacert) { diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 909a4bcfe4..18463b5999 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1888,6 +1888,12 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_s->key_mgmt = WPA_KEY_MGMT_OWE; wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE"); #endif /* CONFIG_OWE */ +#ifdef CONFIG_SHA384 + } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA384) { + wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA384; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: using KEY_MGMT 802.1X with SHA384"); +#endif /* CONFIG_SHA384 */ } else { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select " "authenticated key management type"); @@ -4231,14 +4237,16 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B || - params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)) + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384)) params.req_handshake_offload = 1; if (wpa_s->conf->key_mgmt_offload) { if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B || - params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA384) params.req_key_mgmt_offload = ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : ssid->proactive_key_caching; diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index c4cfca50e6..24950e6e15 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1327,7 +1327,8 @@ void wpas_transition_disable(struct wpa_supplicant *wpa_s, u8 bitmap) wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_FT_IEEE8021X | - WPA_KEY_MGMT_IEEE8021X_SHA256)) && + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA384)) && (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || (ssid->group_cipher & WPA_CIPHER_TKIP))) { disable_wpa_wpa2(ssid); -- 2.38.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap