]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE-PK: AP 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 AP side functionality for SAE-PK. The new sae_password
configuration parameters can now be used to enable SAE-PK mode whenever
SAE is enabled.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/ieee802_11.c
src/ap/ieee802_11_shared.c
src/ap/wpa_auth.h
src/ap/wpa_auth_glue.c
src/ap/wpa_auth_ie.c

index bc650e949ce596ff5a4f84f080dd32cb07744da0..49894c5ba85acff5ab77777900a37465389491e4 100644 (file)
@@ -14,6 +14,7 @@
 #include "utils/common.h"
 #include "utils/uuid.h"
 #include "common/ieee802_11_defs.h"
+#include "common/sae.h"
 #include "crypto/sha256.h"
 #include "crypto/tls.h"
 #include "drivers/driver.h"
@@ -2290,6 +2291,35 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
                pw->vlan_id = atoi(pos2);
        }
 
+#ifdef CONFIG_SAE_PK
+       pos2 = os_strstr(pos, "|pk=");
+       if (pos2) {
+               const char *epos;
+               char *tmp;
+
+               if (!end)
+                       end = pos2;
+               pos2 += 4;
+               epos = os_strchr(pos2, '|');
+               if (epos) {
+                       tmp = os_malloc(epos - pos2 + 1);
+                       if (!tmp)
+                               goto fail;
+                       os_memcpy(tmp, pos2, epos - pos2);
+                       tmp[epos - pos2] = '\0';
+               } else {
+                       tmp = os_strdup(pos2);
+                       if (!tmp)
+                               goto fail;
+               }
+
+               pw->pk = sae_parse_pk(tmp);
+               str_clear_free(tmp);
+               if (!pw->pk)
+                       goto fail;
+       }
+#endif /* CONFIG_SAE_PK */
+
        pos2 = os_strstr(pos, "|id=");
        if (pos2) {
                if (!end)
@@ -2312,6 +2342,14 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
                pw->password[end - val] = '\0';
        }
 
+#ifdef CONFIG_SAE_PK
+       if (pw->pk && !sae_pk_valid_password(pw->password)) {
+               wpa_printf(MSG_INFO,
+                          "Invalid SAE password for a SAE-PK sae_password entry");
+               goto fail;
+       }
+#endif /* CONFIG_SAE_PK */
+
        pw->next = bss->sae_passwords;
        bss->sae_passwords = pw;
 
@@ -2319,6 +2357,9 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
 fail:
        str_clear_free(pw->password);
        os_free(pw->identifier);
+#ifdef CONFIG_SAE_PK
+       sae_deinit_pk(pw->pk);
+#endif /* CONFIG_SAE_PK */
        os_free(pw);
        return -1;
 }
index 812c09a9f7e1e45c65938415af6806b6bf5235bf..2b0f762e544e82f5753f93c9e358432189092e77 100644 (file)
@@ -1776,7 +1776,8 @@ own_ip_addr=127.0.0.1
 # special meaning of removing all previously added entries.
 #
 # sae_password uses the following encoding:
-#<password/credential>[|mac=<peer mac>][|vlanid=<VLAN ID>][|id=<identifier>]
+#<password/credential>[|mac=<peer mac>][|vlanid=<VLAN ID>]
+#[|pk=<m:ECPrivateKey-base64>][|id=<identifier>]
 # Examples:
 #sae_password=secret
 #sae_password=really secret|mac=ff:ff:ff:ff:ff:ff
index 35a32a13052812f93e4df586b975db3712e12a04..a4e1bbb3d6455c6ce7efd88f7a56fc32f8c81a8e 100644 (file)
@@ -461,7 +461,8 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
        struct hostapd_ssid *ssid = &conf->ssid;
        struct sae_password_entry *pw;
 
-       if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf)) ||
+       if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf) &&
+            !hostapd_sae_pk_in_use(conf)) ||
            conf->sae_pwe == 3 ||
            !wpa_key_mgmt_sae(conf->wpa_key_mgmt))
                return 0; /* PT not needed */
@@ -711,6 +712,9 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
 #ifdef CONFIG_SAE
                sae_deinit_pt(tmp->pt);
 #endif /* CONFIG_SAE */
+#ifdef CONFIG_SAE_PK
+               sae_deinit_pk(tmp->pk);
+#endif /* CONFIG_SAE_PK */
                os_free(tmp);
        }
 }
@@ -1111,6 +1115,25 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
 }
 
 
+#ifdef CONFIG_SAE_PK
+static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss)
+{
+       struct sae_password_entry *pw;
+
+       if (bss->ssid.wpa_passphrase &&
+           sae_pk_valid_password(bss->ssid.wpa_passphrase))
+               return true;
+
+       for (pw = bss->sae_passwords; pw; pw = pw->next) {
+               if (!pw->pk && sae_pk_valid_password(pw->password))
+                       return true;
+       }
+
+       return false;
+}
+#endif /* CONFIG_SAE_PK */
+
+
 static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
                                    struct hostapd_config *conf,
                                    int full_config)
@@ -1294,6 +1317,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
        }
 #endif /* CONFIG_OCV */
 
+#ifdef CONFIG_SAE_PK
+       if (full_config && hostapd_sae_pk_in_use(bss) &&
+           hostapd_sae_pk_password_without_pk(bss)) {
+               wpa_printf(MSG_ERROR,
+                          "SAE-PK: SAE password uses SAE-PK style, but does not have PK configured");
+               return -1;
+       }
+#endif /* CONFIG_SAE_PK */
+
        return 0;
 }
 
@@ -1473,3 +1505,38 @@ int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf)
                return 2;
        return with_id;
 }
+
+
+bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf)
+{
+#ifdef CONFIG_SAE_PK
+       struct sae_password_entry *pw;
+
+       for (pw = conf->sae_passwords; pw; pw = pw->next) {
+               if (pw->pk)
+                       return true;
+       }
+#endif /* CONFIG_SAE_PK */
+
+       return false;
+}
+
+
+#ifdef CONFIG_SAE_PK
+bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf)
+{
+       bool with_pk = false;
+       struct sae_password_entry *pw;
+
+       if (conf->ssid.wpa_passphrase)
+               return false;
+
+       for (pw = conf->sae_passwords; pw; pw = pw->next) {
+               if (!pw->pk)
+                       return false;
+               with_pk = true;
+       }
+
+       return with_pk;
+}
+#endif /* CONFIG_SAE_PK */
index c1b4b1bbb5813c9e6ea7dbeb14b7af634268559b..cafc44edd9a872dede038e00ed968ec3786446d4 100644 (file)
@@ -261,6 +261,7 @@ struct sae_password_entry {
        u8 peer_addr[ETH_ALEN];
        int vlan_id;
        struct sae_pt *pt;
+       struct sae_pk *pk;
 };
 
 struct dpp_controller_conf {
@@ -1147,6 +1148,8 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config);
 void hostapd_set_security_params(struct hostapd_bss_config *bss,
                                 int full_config);
 int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf);
+bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf);
+bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf);
 int hostapd_setup_sae_pt(struct hostapd_bss_config *conf);
 
 #endif /* HOSTAPD_CONFIG_H */
index a10bbdcfb7db20da37278bd933cd257c91973a3b..0822dfd34b2aa49ad24af40ad73e3815a580ae74 100644 (file)
@@ -386,7 +386,8 @@ static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta,
            auth_alg == WLAN_AUTH_SAE) {
                if (auth_transaction == 1 && sta &&
                    (resp == WLAN_STATUS_SUCCESS ||
-                    resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT)) {
+                    resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+                    resp == WLAN_STATUS_SAE_PK)) {
                        wpa_printf(MSG_DEBUG,
                                   "TESTING: Postpone SAE Commit transmission until Confirm is ready");
                        os_free(sta->sae_postponed_commit);
@@ -478,17 +479,23 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
        const char *rx_id = NULL;
        int use_pt = 0;
        struct sae_pt *pt = NULL;
+       const struct sae_pk *pk = NULL;
 
        if (sta->sae->tmp) {
                rx_id = sta->sae->tmp->pw_id;
                use_pt = sta->sae->tmp->h2e;
+#ifdef CONFIG_SAE_PK
+               os_memcpy(sta->sae->tmp->own_addr, hapd->own_addr, ETH_ALEN);
+               os_memcpy(sta->sae->tmp->peer_addr, sta->addr, ETH_ALEN);
+#endif /* CONFIG_SAE_PK */
        }
 
        if (rx_id && hapd->conf->sae_pwe != 3)
                use_pt = 1;
        else if (status_code == WLAN_STATUS_SUCCESS)
                use_pt = 0;
-       else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
+       else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+                status_code == WLAN_STATUS_SAE_PK)
                use_pt = 1;
 
        for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
@@ -502,6 +509,8 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
                        continue;
                password = pw->password;
                pt = pw->pt;
+               if (!(hapd->conf->mesh & MESH_ENABLED))
+                       pk = pw->pk;
                break;
        }
        if (!password) {
@@ -515,7 +524,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
 
        if (update && use_pt &&
            sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr,
-                                 NULL, NULL) < 0)
+                                 NULL, pk) < 0)
                return NULL;
 
        if (update && !use_pt &&
@@ -558,7 +567,10 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
        if (buf == NULL)
                return NULL;
 
-       sae_write_confirm(sta->sae, buf);
+       if (sae_write_confirm(sta->sae, buf) < 0) {
+               wpabuf_free(buf);
+               return NULL;
+       }
 
        return buf;
 }
@@ -575,11 +587,19 @@ static int auth_sae_send_commit(struct hostapd_data *hapd,
        data = auth_build_sae_commit(hapd, sta, update, status_code);
        if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
                return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
+#ifdef CONFIG_SAE_PK
+       if (!data && sta->sae->tmp && sta->sae->tmp->reject_group)
+               return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
+#endif /* CONFIG_SAE_PK */
        if (data == NULL)
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
-       status = (sta->sae->tmp && sta->sae->tmp->h2e) ?
-               WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS;
+       if (sta->sae->tmp && sta->sae->tmp->pk)
+               status = WLAN_STATUS_SAE_PK;
+       else if (sta->sae->tmp && sta->sae->tmp->h2e)
+               status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
+       else
+               status = WLAN_STATUS_SUCCESS;
        reply_res = send_auth_reply(hapd, sta, sta->addr, bssid,
                                    WLAN_AUTH_SAE, 1,
                                    status, wpabuf_head(data),
@@ -900,9 +920,14 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
        switch (sta->sae->state) {
        case SAE_NOTHING:
                if (auth_transaction == 1) {
-                       if (sta->sae->tmp)
-                               sta->sae->tmp->h2e = status_code ==
-                                       WLAN_STATUS_SAE_HASH_TO_ELEMENT;
+                       if (sta->sae->tmp) {
+                               sta->sae->tmp->h2e =
+                                       (status_code ==
+                                        WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+                                        status_code == WLAN_STATUS_SAE_PK);
+                               sta->sae->tmp->pk =
+                                       status_code == WLAN_STATUS_SAE_PK;
+                       }
                        ret = auth_sae_send_commit(hapd, sta, bssid,
                                                   !allow_reuse, status_code);
                        if (ret)
@@ -1118,14 +1143,20 @@ static int sae_status_success(struct hostapd_data *hapd, u16 status_code)
                sae_pwe = 1;
        else if (id_in_use == 1 && sae_pwe == 0)
                sae_pwe = 2;
+#ifdef CONFIG_SAE_PK
+       if (sae_pwe == 0 && hostapd_sae_pk_in_use(hapd->conf))
+               sae_pwe = 2;
+#endif /* CONFIG_SAE_PK */
 
        return ((sae_pwe == 0 || sae_pwe == 3) &&
                status_code == WLAN_STATUS_SUCCESS) ||
                (sae_pwe == 1 &&
-                status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) ||
+                (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+                 status_code == WLAN_STATUS_SAE_PK)) ||
                (sae_pwe == 2 &&
                 (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));
 }
 
 
@@ -1148,11 +1179,15 @@ static int sae_is_group_enabled(struct hostapd_data *hapd, int group)
 
 
 static int check_sae_rejected_groups(struct hostapd_data *hapd,
-                                    const struct wpabuf *groups)
+                                    struct sae_data *sae, bool pk)
 {
+       const struct wpabuf *groups;
        size_t i, count;
        const u8 *pos;
 
+       if (!sae->tmp)
+               return 0;
+       groups = sae->tmp->peer_rejected_groups;
        if (!groups)
                return 0;
 
@@ -1165,8 +1200,29 @@ static int check_sae_rejected_groups(struct hostapd_data *hapd,
                group = WPA_GET_LE16(pos);
                pos += 2;
                enabled = sae_is_group_enabled(hapd, group);
-               wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
-                          group, enabled ? "enabled" : "disabled");
+
+#ifdef CONFIG_SAE_PK
+               /* TODO: Could check more explicitly against the matching
+                * sae_password entry only for the somewhat theoretical case of
+                * different passwords using different groups for SAE-PK K_AP
+                * values. */
+               if (pk) {
+                       struct sae_password_entry *pw;
+
+                       enabled = false;
+                       for (pw = hapd->conf->sae_passwords; pw;
+                            pw = pw->next) {
+                               if (pw->pk && pw->pk->group == group) {
+                                       enabled = true;
+                                       break;
+                               }
+                       }
+               }
+#endif /* CONFIG_SAE_PK */
+
+               wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s%s",
+                          group, enabled ? "enabled" : "disabled",
+                          pk ? " (PK)" : "");
                if (enabled)
                        return 1;
        }
@@ -1339,7 +1395,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                                        ((const u8 *) mgmt) + len -
                                        mgmt->u.auth.variable, &token,
                                        &token_len, groups, status_code ==
-                                       WLAN_STATUS_SAE_HASH_TO_ELEMENT);
+                                       WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+                                       status_code == WLAN_STATUS_SAE_PK);
                if (resp == SAE_SILENTLY_DISCARD) {
                        wpa_printf(MSG_DEBUG,
                                   "SAE: Drop commit message from " MACSTR " due to reflection attack",
@@ -1369,9 +1426,9 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                if (resp != WLAN_STATUS_SUCCESS)
                        goto reply;
 
-               if (sta->sae->tmp &&
-                   check_sae_rejected_groups(
-                           hapd, sta->sae->tmp->peer_rejected_groups)) {
+               if (check_sae_rejected_groups(hapd, sta->sae,
+                                             status_code ==
+                                             WLAN_STATUS_SAE_PK)) {
                        resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
                        goto reply;
                }
@@ -1384,7 +1441,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                                   MACSTR, MAC2STR(sta->addr));
                        if (sta->sae->tmp)
                                h2e = sta->sae->tmp->h2e;
-                       if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
+                       if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+                           status_code == WLAN_STATUS_SAE_PK)
                                h2e = 1;
                        data = auth_build_token_req(hapd, sta->sae->group,
                                                    sta->addr, h2e);
index 45683d76e57e7896c58657ff19df12e9813f4cf8..79ed450e27a84f19d292488749762ecee7aa5523 100644 (file)
@@ -427,6 +427,14 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
                if (hapd->conf->beacon_prot)
                        *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
                break;
+       case 11: /* Bits 88-95 */
+#ifdef CONFIG_SAE_PK
+               if (hapd->conf->wpa &&
+                   wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+                   hostapd_sae_pk_exclusively(hapd->conf))
+                       *pos |= 0x01; /* Bit 88 - SAE PK Exclusively */
+#endif /* CONFIG_SAE_PK */
+               break;
        }
 }
 
@@ -487,6 +495,12 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
 #endif /* CONFIG_SAE */
        if (len < 11 && hapd->conf->beacon_prot)
                len = 11;
+#ifdef CONFIG_SAE_PK
+       if (len < 12 && hapd->conf->wpa &&
+           wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+           hostapd_sae_pk_exclusively(hapd->conf))
+               len = 12;
+#endif /* CONFIG_SAE_PK */
        if (len < hapd->iface->extended_capa_len)
                len = hapd->iface->extended_capa_len;
        if (len == 0)
@@ -1081,11 +1095,16 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
 u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
 {
        u8 *pos = eid;
+       bool sae_pk = false;
+
+#ifdef CONFIG_SAE_PK
+       sae_pk = hostapd_sae_pk_in_use(hapd->conf);
+#endif /* CONFIG_SAE_PK */
 
        if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
            !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) ||
            (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 &&
-            !hostapd_sae_pw_id_in_use(hapd->conf)) ||
+            !hostapd_sae_pw_id_in_use(hapd->conf) && !sae_pk) ||
            hapd->conf->sae_pwe == 3 ||
            len < 3)
                return pos;
@@ -1094,7 +1113,12 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
        *pos++ = 1;
        /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
         * used for now */
-       *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+       *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+#ifdef CONFIG_SAE_PK
+       if (sae_pk)
+               *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
+#endif /* CONFIG_SAE_PK */
+       pos++;
 
        return pos;
 }
index e059f3db3fcba03b35056e150424b08d2a79193f..59794a7f9dd364fab278aae1cba7c4b6a9463afc 100644 (file)
@@ -256,6 +256,7 @@ struct wpa_auth_config {
        u8 fils_cache_id[FILS_CACHE_ID_LEN];
 #endif /* CONFIG_FILS */
        int sae_pwe;
+       bool sae_pk;
        int owe_ptk_workaround;
        u8 transition_disable;
 #ifdef CONFIG_DPP2
index b90c9ef612d2836f62aa33ba3217c6da3c703501..c01654f38c8ba561b6eb966f6bd2dc0dfcff87ad 100644 (file)
@@ -198,6 +198,9 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
                wconf->sae_pwe = 1;
        else if (sae_pw_id == 1 && wconf->sae_pwe == 0)
                wconf->sae_pwe = 2;
+#ifdef CONFIG_SAE_PK
+       wconf->sae_pk = hostapd_sae_pk_in_use(conf);
+#endif /* CONFIG_SAE_PK */
 #ifdef CONFIG_OWE
        wconf->owe_ptk_workaround = conf->owe_ptk_workaround;
 #endif /* CONFIG_OWE */
index 8dfd65700fbd08b0b4c76fdfcb533cb87f7769c0..a7e6354a54f9952ec93f23e4ddcef9dcf1381b9e 100644 (file)
@@ -378,7 +378,7 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
 {
        u8 *pos = buf;
 
-       if (conf->sae_pwe != 1 && conf->sae_pwe != 2)
+       if (conf->sae_pwe != 1 && conf->sae_pwe != 2 && !conf->sae_pk)
                return 0; /* no supported extended RSN capabilities */
 
        if (len < 3)
@@ -388,7 +388,12 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
        *pos++ = 1;
        /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
         * used for now */
-       *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+       *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+#ifdef CONFIG_SAE_PK
+       if (conf->sae_pk)
+               *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
+#endif /* CONFIG_SAE_PK */
+       pos++;
 
        return pos - buf;
 }