]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE-PK: STA functionality
authorJouni Malinen <jouni@codeaurora.org>
Sat, 30 May 2020 20:30:42 +0000 (23:30 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 2 Jun 2020 20:25:22 +0000 (23:25 +0300)
This adds STA side functionality for SAE-PK. This version enables SAE-PK
automatically based on the configured SAE password value if the selected
AP advertises support for SAE-PK.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c

index d03b0ce8adf4c24786a994322d226ab210fc354d..3ad00652855b88649f763f8d8bb3d1da0ba18059 100644 (file)
@@ -85,16 +85,21 @@ static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
 static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
                                                 struct wpa_ssid *ssid,
                                                 const u8 *bssid, int external,
-                                                int reuse, int *ret_use_pt)
+                                                int reuse, int *ret_use_pt,
+                                                bool *ret_use_pk)
 {
        struct wpabuf *buf;
        size_t len;
        const char *password;
        struct wpa_bss *bss;
        int use_pt = 0;
+       bool use_pk = false;
+       u8 rsnxe_capa = 0;
 
        if (ret_use_pt)
                *ret_use_pt = 0;
+       if (ret_use_pk)
+               *ret_use_pk = false;
 
 #ifdef CONFIG_TESTING_OPTIONS
        if (wpa_s->sae_commit_override) {
@@ -124,6 +129,7 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
                wpa_printf(MSG_DEBUG,
                           "SAE: Reuse previously generated PWE on a retry with the same AP");
                use_pt = wpa_s->sme.sae.tmp->h2e;
+               use_pk = wpa_s->sme.sae.tmp->pk;
                goto reuse_data;
        }
        if (sme_set_sae_group(wpa_s) < 0) {
@@ -131,19 +137,27 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
                return NULL;
        }
 
+       bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+       if (bss) {
+               const u8 *rsnxe;
+
+               rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+               if (rsnxe && rsnxe[1] >= 1)
+                       rsnxe_capa = rsnxe[2];
+       }
+
        if (ssid->sae_password_id && wpa_s->conf->sae_pwe != 3)
                use_pt = 1;
+#ifdef CONFIG_SAE_PK
+       if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
+           ssid->sae_password && sae_pk_valid_password(ssid->sae_password)) {
+               use_pt = 1;
+               use_pk = true;
+       }
+#endif /* CONFIG_SAE_PK */
 
        if (use_pt || wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) {
-               bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
-               if (bss) {
-                       const u8 *rsnxe;
-
-                       rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
-                       if (rsnxe && rsnxe[1] >= 1)
-                               use_pt = !!(rsnxe[2] &
-                                           BIT(WLAN_RSNX_CAPAB_SAE_H2E));
-               }
+               use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
 
                if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) &&
                    wpa_s->conf->sae_pwe != 3 &&
@@ -167,8 +181,17 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
                wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
                return NULL;
        }
-       if (wpa_s->sme.sae.tmp)
+       if (wpa_s->sme.sae.tmp) {
                os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN);
+               if (use_pt && use_pk)
+                       wpa_s->sme.sae.tmp->pk = 1;
+#ifdef CONFIG_SAE_PK
+               os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr,
+                         ETH_ALEN);
+               os_memcpy(wpa_s->sme.sae.tmp->peer_addr, bssid, ETH_ALEN);
+               sae_pk_set_password(&wpa_s->sme.sae, password);
+#endif /* CONFIG_SAE_PK */
+       }
 
 reuse_data:
        len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0;
@@ -179,8 +202,12 @@ reuse_data:
                return NULL;
        if (!external) {
                wpabuf_put_le16(buf, 1); /* Transaction seq# */
-               wpabuf_put_le16(buf, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
-                               WLAN_STATUS_SUCCESS);
+               if (use_pk)
+                       wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK);
+               else if (use_pt)
+                       wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
+               else
+                       wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS);
        }
        if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
                             ssid->sae_password_id) < 0) {
@@ -189,6 +216,8 @@ reuse_data:
        }
        if (ret_use_pt)
                *ret_use_pt = use_pt;
+       if (ret_use_pk)
+               *ret_use_pk = use_pk;
 
        return buf;
 }
@@ -716,7 +745,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
                if (start)
                        resp = sme_auth_build_sae_commit(wpa_s, ssid,
                                                         bss->bssid, 0,
-                                                        start == 2, NULL);
+                                                        start == 2, NULL,
+                                                        NULL);
                else
                        resp = sme_auth_build_sae_confirm(wpa_s, 0);
                if (resp == NULL) {
@@ -1008,8 +1038,11 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
 {
        struct wpabuf *resp, *buf;
        int use_pt;
+       bool use_pk;
+       u16 status;
 
-       resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt);
+       resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt,
+                                        &use_pk);
        if (!resp) {
                wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
                return -1;
@@ -1023,10 +1056,14 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
        }
 
        wpa_s->sme.seq_num++;
+       if (use_pk)
+               status = WLAN_STATUS_SAE_PK;
+       else if (use_pt)
+               status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
+       else
+               status = WLAN_STATUS_SUCCESS;
        sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
-                                   bssid, 1, wpa_s->sme.seq_num,
-                                   use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
-                                   WLAN_STATUS_SUCCESS);
+                                   bssid, 1, wpa_s->sme.seq_num, status);
        wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
        wpabuf_free(resp);
        wpabuf_free(buf);
@@ -1287,7 +1324,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
        }
 
        if (status_code != WLAN_STATUS_SUCCESS &&
-           status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT)
+           status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
+           status_code != WLAN_STATUS_SAE_PK)
                return -1;
 
        if (auth_transaction == 1) {
@@ -1310,18 +1348,26 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                                   "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
                        return -1;
                }
-               if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->h2e &&
+               if (wpa_s->sme.sae.tmp &&
+                   (!wpa_s->sme.sae.tmp->h2e || wpa_s->sme.sae.tmp->pk) &&
                    status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
                        wpa_printf(MSG_DEBUG,
                                   "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
                        return -1;
                }
+               if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->pk &&
+                   status_code == WLAN_STATUS_SAE_PK) {
+                       wpa_printf(MSG_DEBUG,
+                                  "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
+                       return -1;
+               }
 
                if (groups && groups[0] <= 0)
                        groups = NULL;
                res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
                                       groups, status_code ==
-                                      WLAN_STATUS_SAE_HASH_TO_ELEMENT);
+                                      WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+                                      status_code == WLAN_STATUS_SAE_PK);
                if (res == SAE_SILENTLY_DISCARD) {
                        wpa_printf(MSG_DEBUG,
                                   "SAE: Drop commit message due to reflection attack");
index acd0091bc8a916bb129d2e3612a1ae1892e829f4..f5a4c360b6a41392b872ac69201dbb1b6a365d4c 100644 (file)
@@ -2061,7 +2061,9 @@ static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid)
        if (!password)
                password = ssid->passphrase;
 
-       if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password ||
+       if (!password ||
+           (conf->sae_pwe == 0 && !ssid->sae_password_id &&
+            !sae_pk_valid_password(password)) ||
            conf->sae_pwe == 3) {
                /* PT derivation not needed */
                sae_deinit_pt(ssid->pt);