diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 3dc3d808a..475bdd8f1 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -199,6 +199,10 @@ NEED_AES_OMAC1=y NEED_AES_UNWRAP=y endif +ifdef CONFIG_SAE +L_CFLAGS += -DCONFIG_SAE +endif + ifdef CONFIG_IEEE80211N L_CFLAGS += -DCONFIG_IEEE80211N endif diff --git a/hostapd/Makefile b/hostapd/Makefile index f5dfce0b2..277e1d462 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -171,6 +171,10 @@ NEED_AES_OMAC1=y NEED_AES_UNWRAP=y endif +ifdef CONFIG_SAE +CFLAGS += -DCONFIG_SAE +endif + ifdef CONFIG_IEEE80211V CFLAGS += -DCONFIG_IEEE80211V OBJS += ../src/ap/wnm_ap.o diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 0a24ec379..f9b398431 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -624,6 +624,12 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value) else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) val |= WPA_KEY_MGMT_IEEE8021X_SHA256; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + else if (os_strcmp(start, "SAE") == 0) + val |= WPA_KEY_MGMT_SAE; + else if (os_strcmp(start, "FT-SAE") == 0) + val |= WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index ce20e5f8d..a3ecce071 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -296,6 +296,51 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid, #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE +static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, + const struct ieee80211_mgmt *mgmt, size_t len, + u8 auth_transaction) +{ + u16 resp = WLAN_STATUS_SUCCESS; + u8 *data = (u8 *) "TEST"; /* TODO */ + size_t data_len = 4; + + if (auth_transaction == 1) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "start SAE authentication (RX commit)"); + sta->sae_state = SAE_COMMIT; + } else if (auth_transaction == 2) { + if (sta->sae_state != SAE_COMMIT) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "SAE confirm before commit"); + resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; + } + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "SAE authentication (RX confirm)"); + sta->flags |= WLAN_STA_AUTH; + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + sta->auth_alg = WLAN_AUTH_SAE; + mlme_authenticate_indication(hapd, sta); + } else { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "unexpected SAE authentication transaction %u", + auth_transaction); + resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; + } + + sta->auth_alg = WLAN_AUTH_SAE; + + send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE, + auth_transaction, resp, data, data_len); +} +#endif /* CONFIG_SAE */ + + static void handle_auth(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { @@ -348,6 +393,10 @@ static void handle_auth(struct hostapd_data *hapd, (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) && auth_alg == WLAN_AUTH_FT) || #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE + (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + auth_alg == WLAN_AUTH_SAE) || +#endif /* CONFIG_SAE */ ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) && auth_alg == WLAN_AUTH_SHARED_KEY))) { printf("Unsupported authentication algorithm (%d)\n", @@ -356,7 +405,7 @@ static void handle_auth(struct hostapd_data *hapd, goto fail; } - if (!(auth_transaction == 1 || + if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE || (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) { printf("Unknown authentication transaction number (%d)\n", auth_transaction); @@ -486,6 +535,11 @@ static void handle_auth(struct hostapd_data *hapd, /* handle_auth_ft_finish() callback will complete auth. */ return; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE + case WLAN_AUTH_SAE: + handle_auth_sae(hapd, sta, mgmt, len, auth_transaction); + return; +#endif /* CONFIG_SAE */ } fail: @@ -779,6 +833,16 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE + if (wpa_auth_uses_sae(sta->wpa_sm) && + sta->auth_alg != WLAN_AUTH_SAE) { + wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use " + "SAE AKM after non-SAE auth_alg %u", + MAC2STR(sta->addr), sta->auth_alg); + return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + } +#endif /* CONFIG_SAE */ + #ifdef CONFIG_IEEE80211N if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) && wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 91d6b34ce..bcebc91b2 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -123,6 +123,10 @@ struct sta_info { struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */ struct os_time connected_time; + +#ifdef CONFIG_SAE + enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state; +#endif /* CONFIG_SAE */ }; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 49d817578..1ba83a5eb 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3056,3 +3056,11 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, wpa_send_eapol_timeout, wpa_auth, sm); } } + + +int wpa_auth_uses_sae(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + return wpa_key_mgmt_sae(sm->wpa_key_mgmt); +} diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 91ba49919..6bcd99ce5 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -291,4 +291,6 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos); #endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_IEEE80211V */ +int wpa_auth_uses_sae(struct wpa_state_machine *sm); + #endif /* WPA_AUTH_H */ diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 17862305f..4fd0135fe 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -188,6 +188,18 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, num_suites++; } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_SAE */ #ifdef CONFIG_RSN_TESTING if (rsn_testing) { @@ -407,6 +419,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + else if (data.key_mgmt & WPA_KEY_MGMT_SAE) + selector = RSN_AUTH_KEY_MGMT_SAE; + else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) + selector = RSN_AUTH_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; else if (data.key_mgmt & WPA_KEY_MGMT_PSK) @@ -479,6 +497,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + else if (key_mgmt & WPA_KEY_MGMT_SAE) + sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE; + else if (key_mgmt & WPA_KEY_MGMT_FT_SAE) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; else diff --git a/src/common/defs.h b/src/common/defs.h index db29b5df0..f50a13302 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -38,6 +38,8 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) #define WPA_KEY_MGMT_PSK_SHA256 BIT(8) #define WPA_KEY_MGMT_WPS BIT(9) +#define WPA_KEY_MGMT_SAE BIT(10) +#define WPA_KEY_MGMT_FT_SAE BIT(11) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) { @@ -50,13 +52,21 @@ static inline int wpa_key_mgmt_wpa_psk(int akm) { return !!(akm & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | - WPA_KEY_MGMT_PSK_SHA256)); + WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_SAE)); } static inline int wpa_key_mgmt_ft(int akm) { return !!(akm & (WPA_KEY_MGMT_FT_PSK | - WPA_KEY_MGMT_FT_IEEE8021X)); + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_FT_SAE)); +} + +static inline int wpa_key_mgmt_sae(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_SAE | + WPA_KEY_MGMT_FT_SAE)); } static inline int wpa_key_mgmt_sha256(int akm) @@ -84,6 +94,7 @@ static inline int wpa_key_mgmt_wpa_any(int akm) #define WPA_AUTH_ALG_SHARED BIT(1) #define WPA_AUTH_ALG_LEAP BIT(2) #define WPA_AUTH_ALG_FT BIT(3) +#define WPA_AUTH_ALG_SAE BIT(4) enum wpa_alg { @@ -121,7 +132,9 @@ enum wpa_key_mgmt { KEY_MGMT_FT_PSK, KEY_MGMT_802_1X_SHA256, KEY_MGMT_PSK_SHA256, - KEY_MGMT_WPS + KEY_MGMT_WPS, + KEY_MGMT_SAE, + KEY_MGMT_FT_SAE }; /** diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 2ab7fbf49..8b21c5321 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -76,6 +76,7 @@ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 #define WLAN_AUTH_FT 2 +#define WLAN_AUTH_SAE 3 #define WLAN_AUTH_LEAP 128 #define WLAN_AUTH_CHALLENGE_LEN 128 @@ -157,6 +158,8 @@ #define WLAN_STATUS_REQ_REFUSED_SSPN 67 #define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68 #define WLAN_STATUS_INVALID_RSNIE 72 +#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76 +#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77 #define WLAN_STATUS_TRANSMISSION_FAILURE 79 /* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 36c308a9f..8d7a11cfc 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -376,6 +376,12 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) return WPA_KEY_MGMT_PSK_SHA256; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE) + return WPA_KEY_MGMT_SAE; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE) + return WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ return 0; } #endif /* CONFIG_NO_WPA2 */ diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 603166b71..d9b32d09a 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -51,6 +51,8 @@ #define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7) +#define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8) +#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9) #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) #define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index a9ca63370..38d0180d3 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -314,6 +314,9 @@ struct wpa_driver_auth_params { */ int p2p; + const u8 *sae_data; + size_t sae_data_len; + }; enum wps_mode { @@ -834,6 +837,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_INACTIVITY_TIMER 0x00800000 /* Driver expects user space implementation of MLME in AP mode */ #define WPA_DRIVER_FLAGS_AP_MLME 0x01000000 +/* Driver supports SAE with user space SME */ +#define WPA_DRIVER_FLAGS_SAE 0x02000000 unsigned int flags; int max_scan_ssids; diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 6a8f9f12b..429f1e5cd 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -164,6 +164,12 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + } else if (key_mgmt == WPA_KEY_MGMT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); + } else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); +#endif /* CONFIG_SAE */ } else { wpa_printf(MSG_WARNING, "Invalid key management type (%d).", key_mgmt); diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 90dd84e06..cc334c8c2 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -179,6 +179,10 @@ NEED_SHA256=y NEED_AES_OMAC1=y endif +ifdef CONFIG_SAE +L_CFLAGS += -DCONFIG_SAE +endif + ifdef CONFIG_TDLS L_CFLAGS += -DCONFIG_TDLS OBJS += src/rsn_supp/tdls.c diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 227fb4fd9..9684cfad9 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -172,6 +172,10 @@ NEED_SHA256=y NEED_AES_OMAC1=y endif +ifdef CONFIG_SAE +CFLAGS += -DCONFIG_SAE +endif + ifdef CONFIG_IEEE80211V CFLAGS += -DCONFIG_IEEE80211V OBJS += wnm_sta.o diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index be2102971..674766ece 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -504,6 +504,12 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, else if (os_strcmp(start, "WPS") == 0) val |= WPA_KEY_MGMT_WPS; #endif /* CONFIG_WPS */ +#ifdef CONFIG_SAE + else if (os_strcmp(start, "SAE") == 0) + val |= WPA_KEY_MGMT_SAE; + else if (os_strcmp(start, "FT-SAE") == 0) + val |= WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index b09e5f180..02c44d436 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -39,8 +39,47 @@ static void sme_stop_sa_query(struct wpa_supplicant *wpa_s); #endif /* CONFIG_IEEE80211W */ -void sme_authenticate(struct wpa_supplicant *wpa_s, - struct wpa_bss *bss, struct wpa_ssid *ssid) +#ifdef CONFIG_SAE + +static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s) +{ + struct wpabuf *buf; + + buf = wpabuf_alloc(4 + 4); + if (buf == NULL) + return NULL; + + wpabuf_put_le16(buf, 1); /* Transaction seq# */ + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + wpabuf_put_str(buf, "TEST"); + /* TODO: full SAE commit */ + + return buf; +} + + +static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s) +{ + struct wpabuf *buf; + + buf = wpabuf_alloc(4 + 4); + if (buf == NULL) + return NULL; + + wpabuf_put_le16(buf, 2); /* Transaction seq# */ + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + wpabuf_put_str(buf, "TEST"); + /* TODO: full SAE confirm */ + + return buf; +} + +#endif /* CONFIG_SAE */ + + +void sme_send_authentication(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_ssid *ssid, + int start) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; @@ -51,6 +90,7 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; + struct wpabuf *resp = NULL; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " @@ -95,6 +135,21 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } +#ifdef CONFIG_SAE + if (wpa_key_mgmt_sae(ssid->key_mgmt)) { + const u8 *rsn; + struct wpa_ie_data ied; + + rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); + if (rsn && + wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0) { + if (wpa_key_mgmt_sae(ied.key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); + params.auth_alg = WPA_AUTH_ALG_SAE; + } + } + } +#endif /* CONFIG_SAE */ for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) @@ -265,6 +320,19 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_SAE + if (params.auth_alg == WPA_AUTH_ALG_SAE) { + if (start) + resp = sme_auth_build_sae_commit(wpa_s); + else + resp = sme_auth_build_sae_confirm(wpa_s); + if (resp == NULL) + return; + params.sae_data = wpabuf_head(resp); + params.sae_data_len = wpabuf_len(resp); + } +#endif /* CONFIG_SAE */ + wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); @@ -287,6 +355,7 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, "driver failed"); wpas_connection_failed(wpa_s, bss->bssid); wpa_supplicant_mark_disassoc(wpa_s); + wpabuf_free(resp); return; } @@ -297,9 +366,47 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, * Association will be started based on the authentication event from * the driver. */ + + wpabuf_free(resp); } +void sme_authenticate(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_ssid *ssid) +{ + sme_send_authentication(wpa_s, bss, ssid, 1); +} + + +#ifdef CONFIG_SAE +static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, + u16 status_code, const u8 *data, size_t len) +{ + wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u " + "status code %u", auth_transaction, status_code); + wpa_hexdump(MSG_DEBUG, "SME: SAE fields", data, len); + + if (status_code != WLAN_STATUS_SUCCESS) + return -1; + + if (auth_transaction == 1) { + wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit"); + if (wpa_s->current_bss == NULL || + wpa_s->current_ssid == NULL) + return -1; + sme_send_authentication(wpa_s, wpa_s->current_bss, + wpa_s->current_ssid, 0); + return 0; + } else if (auth_transaction == 2) { + wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm"); + return 1; + } + + return -1; +} +#endif /* CONFIG_SAE */ + + void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { struct wpa_ssid *ssid = wpa_s->current_ssid; @@ -324,14 +431,23 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) } wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR - " auth_type=%d status_code=%d", + " auth_type=%d auth_transaction=%d status_code=%d", MAC2STR(data->auth.peer), data->auth.auth_type, - data->auth.status_code); + data->auth.auth_transaction, data->auth.status_code); wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", data->auth.ies, data->auth.ies_len); eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); +#ifdef CONFIG_SAE + if (data->auth.auth_type == WLAN_AUTH_SAE) { + if (sme_sae_auth(wpa_s, data->auth.auth_transaction, + data->auth.status_code, data->auth.ies, + data->auth.ies_len) != 1) + return; + } +#endif /* CONFIG_SAE */ + if (data->auth.status_code != WLAN_STATUS_SUCCESS) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status " "code %d)", data->auth.status_code); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index fe2894935..f1efe6ba8 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1073,6 +1073,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } sel = ie.key_mgmt & ssid->key_mgmt; +#ifdef CONFIG_SAE + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) + sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE); +#endif /* CONFIG_SAE */ if (0) { #ifdef CONFIG_IEEE80211R } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) { @@ -1082,6 +1086,14 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK; wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK"); #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE + } else if (sel & WPA_KEY_MGMT_SAE) { + wpa_s->key_mgmt = WPA_KEY_MGMT_SAE; + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE"); + } else if (sel & WPA_KEY_MGMT_FT_SAE) { + wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE; + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE"); +#endif /* CONFIG_SAE */ #ifdef CONFIG_IEEE80211W } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) { wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;