]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
PASN: Change PASN flows to use SAE H2E only
authorIlan Peer <ilan.peer@intel.com>
Thu, 8 Apr 2021 09:06:24 +0000 (12:06 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 10 Apr 2021 09:12:22 +0000 (12:12 +0300)
Do so for both wpa_supplicant and hostapd. While this was not explicitly
required in IEEE P802.11az/D3.0, likely direction for the draft is to
start requiring use of H2E for all cases where SAE is used with PASN.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
src/ap/ieee802_11.c
wpa_supplicant/pasn_supplicant.c

index 1b0384dfc913db6bbd98116d6056f190bec3d343..f7f07b4944bde2964e4f415f29a1058d30bf3ceb 100644 (file)
@@ -2383,11 +2383,12 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
                                     struct wpabuf *wd)
 {
        struct pasn_data *pasn = sta->pasn;
-       const char *password = NULL;
+       const char *password;
        const u8 *data;
        size_t buf_len;
        u16 res, alg, seq, status;
        int groups[] = { pasn->group, 0 };
+       struct sae_pt *pt = NULL;
        int ret;
 
        if (!wd)
@@ -2409,8 +2410,8 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
        wpa_printf(MSG_DEBUG, "PASN: SAE commit: alg=%u, seq=%u, status=%u",
                   alg, seq, status);
 
-       /* TODO: SAE H2E */
-       if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+       if (alg != WLAN_AUTH_SAE || seq != 1 ||
+           status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
                wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE commit");
                return -1;
        }
@@ -2424,15 +2425,14 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
                return -1;
        }
 
-       password = sae_get_password(hapd, sta, NULL, NULL, NULL, NULL);
-       if (!password) {
-               wpa_printf(MSG_DEBUG, "PASN: No SAE password found");
+       password = sae_get_password(hapd, sta, NULL, NULL, &pt, NULL);
+       if (!password || !pt) {
+               wpa_printf(MSG_DEBUG, "PASN: No SAE PT found");
                return -1;
        }
 
-       ret = sae_prepare_commit(hapd->own_addr, sta->addr,
-                                (const u8 *) password, os_strlen(password), 0,
-                                &pasn->sae);
+       ret = sae_prepare_commit_pt(&pasn->sae, pt, hapd->own_addr, sta->addr,
+                                   NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
                return -1;
@@ -2529,7 +2529,7 @@ static struct wpabuf * pasn_get_sae_wd(struct hostapd_data *hapd,
        len_ptr = wpabuf_put(buf, 2);
        wpabuf_put_le16(buf, WLAN_AUTH_SAE);
        wpabuf_put_le16(buf, 1);
-       wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+       wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
 
        /* Write the actual commit and update the length accordingly */
        sae_write_commit(&pasn->sae, buf, NULL, 0);
index d483175b78bb645503987e4f5917fa559662bc3a..edb5508002a1ae79b3b66207a0e1c2883acbdec4 100644 (file)
@@ -102,30 +102,17 @@ static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
 {
        struct wpas_pasn *pasn = &wpa_s->pasn;
        struct wpabuf *buf = NULL;
-       const char *password = NULL;
        int ret;
 
-       if (pasn->ssid) {
-               password = pasn->ssid->sae_password;
-               if (!password)
-                       password = pasn->ssid->passphrase;
-       }
-
-       if (!password) {
-               wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
-               return NULL;
-       }
-
        ret = sae_set_group(&pasn->sae, pasn->group);
        if (ret) {
                wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
                return NULL;
        }
 
-       /* TODO: SAE H2E */
-       ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
-                                (const u8 *) password, os_strlen(password), 0,
-                                &pasn->sae);
+       ret = sae_prepare_commit_pt(&pasn->sae, pasn->ssid->pt,
+                                   wpa_s->own_addr, pasn->bssid,
+                                   NULL, NULL);
        if (ret) {
                wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
                return NULL;
@@ -140,7 +127,7 @@ static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
 
        wpabuf_put_le16(buf, WLAN_AUTH_SAE);
        wpabuf_put_le16(buf, 1);
-       wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+       wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
 
        sae_write_commit(&pasn->sae, buf, NULL, 0);
        pasn->sae.state = SAE_COMMITTED;
@@ -186,14 +173,14 @@ static int wpas_pasn_wd_sae_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
        wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
                   alg, seq, status);
 
-       /* TODO: SAE H2E */
-       if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+       if (alg != WLAN_AUTH_SAE || seq != 1 ||
+           status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
                wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
                return -1;
        }
 
        res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
-                              0);
+                              1);
        if (res != WLAN_STATUS_SUCCESS) {
                wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
                return -1;
@@ -271,6 +258,31 @@ static struct wpabuf * wpas_pasn_wd_sae_confirm(struct wpa_supplicant *wpa_s)
        return buf;
 }
 
+
+static int wpas_pasn_sae_setup_pt(struct wpa_supplicant *wpa_s,
+                                 struct wpa_ssid *ssid, int group)
+{
+       const char *password = ssid->sae_password;
+       int groups[2] = { group, 0 };
+
+       if (!password)
+               password = ssid->passphrase;
+
+       if (!password) {
+               wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
+               return -1;
+       }
+
+       if (ssid->pt)
+               return 0; /* PT already derived */
+
+       ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
+                                (const u8 *) password, os_strlen(password),
+                                ssid->sae_password_id);
+
+       return ssid->pt ? 0 : -1;
+}
+
 #endif /* CONFIG_SAE */
 
 
@@ -718,8 +730,8 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s,
                goto fail;
 
        /* Add own RNSXE */
-       /* TODO: How to handle protected TWT and SAE H2E? */
        capab = 0;
+       capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
        if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
                capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
        if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
@@ -1008,6 +1020,20 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
                                   "PASN: No network profile found for SAE");
                        return -1;
                }
+
+               if (beacon_rsnxe_len < 3 ||
+                   !(beacon_rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
+                       wpa_printf(MSG_DEBUG,
+                                  "PASN: AP does not support SAE H2E");
+                       return -1;
+               }
+
+               if (wpas_pasn_sae_setup_pt(wpa_s, ssid, group) < 0) {
+                       wpa_printf(MSG_DEBUG,
+                                  "PASN: Failed to derive PT");
+                       return -1;
+               }
+
                pasn->sae.state = SAE_NOTHING;
                pasn->sae.send_confirm = 0;
                pasn->ssid = ssid;