aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant/sme.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2012-09-30 16:51:07 (GMT)
committerJouni Malinen <j@w1.fi>2012-09-30 16:51:07 (GMT)
commitc10347f246d2fa0b84fbcf7b59ea634542837071 (patch)
tree2a0572faed0d5942dbc5f6eb4564884007bab805 /wpa_supplicant/sme.c
parent905029097ca5d052b6173c2cb75ed705e1a41fc5 (diff)
downloadhostap-c10347f246d2fa0b84fbcf7b59ea634542837071.zip
hostap-c10347f246d2fa0b84fbcf7b59ea634542837071.tar.gz
hostap-c10347f246d2fa0b84fbcf7b59ea634542837071.tar.bz2
Add initial parts for SAE
This introduces new AKM for SAE and FT-SAE and adds the initial parts for going through the SAE Authentication frame exchange. The actual SAE algorithm and new fields in Authentication frames are not yet included in this commit and will be added separately. This version is able to complete a dummy authentication with the correct authentication algorithm and transaction values to allow cfg80211/mac80211 drivers to be tested (all the missing parts can be handled with hostapd/wpa_supplicant changes). Signed-hostap: Jouni Malinen <j@w1.fi>
Diffstat (limited to 'wpa_supplicant/sme.c')
-rw-r--r--wpa_supplicant/sme.c124
1 files changed, 120 insertions, 4 deletions
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index b09e5f1..02c44d4 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,7 +366,45 @@ 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)
@@ -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);