]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP2: PFS for PTK derivation
authorJouni Malinen <jouni@codeaurora.org>
Sun, 17 Mar 2019 21:51:53 +0000 (23:51 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 18 Mar 2019 16:32:31 +0000 (18:32 +0200)
Use Diffie-Hellman key exchange to derivate additional material for
PMK-to-PTK derivation to get PFS. The Diffie-Hellman Parameter element
(defined in OWE RFC 8110) is used in association frames to exchange the
DH public keys. For backwards compatibility, ignore missing
request/response DH parameter and fall back to no PFS in such cases.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
17 files changed:
src/ap/drv_callbacks.c
src/ap/ieee802_11.c
src/ap/sta_info.c
src/ap/sta_info.h
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_i.h
src/common/dpp.c
src/common/dpp.h
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/dpp_supplicant.c
wpa_supplicant/events.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index cf01854e1505d1873f96cce26dc40a4c725a920e..8ddf754f60a740b0638766ebf49f71e92a91cebd 100644 (file)
@@ -15,6 +15,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "common/wpa_ctrl.h"
+#include "common/dpp.h"
 #include "crypto/random.h"
 #include "p2p/p2p.h"
 #include "wps/wps.h"
@@ -565,6 +566,38 @@ skip_wpa_check:
        }
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_DPP2
+               dpp_pfs_free(sta->dpp_pfs);
+               sta->dpp_pfs = NULL;
+
+               if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
+                   hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
+                   wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
+                   elems.owe_dh) {
+                       sta->dpp_pfs = dpp_pfs_init(
+                               wpabuf_head(hapd->conf->dpp_netaccesskey),
+                               wpabuf_len(hapd->conf->dpp_netaccesskey));
+                       if (!sta->dpp_pfs) {
+                               wpa_printf(MSG_DEBUG,
+                                          "DPP: Could not initialize PFS");
+                               /* Try to continue without PFS */
+                               goto pfs_fail;
+                       }
+
+                       if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh,
+                                           elems.owe_dh_len) < 0) {
+                               dpp_pfs_free(sta->dpp_pfs);
+                               sta->dpp_pfs = NULL;
+                               reason = WLAN_REASON_UNSPECIFIED;
+                               goto fail;
+                       }
+               }
+
+               wpa_auth_set_dpp_z(sta->wpa_sm, sta->dpp_pfs ?
+                                  sta->dpp_pfs->secret : NULL);
+       pfs_fail:
+#endif /* CONFIG_DPP2 */
+
 #if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
        hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
 
index df80b58dc58dad3bd3a3b0b707a4e187d632db52..bb05f1aed6b25b3c4d5b4e9b9eccab2d0a17621d 100644 (file)
@@ -21,6 +21,7 @@
 #include "common/ieee802_11_common.h"
 #include "common/wpa_ctrl.h"
 #include "common/sae.h"
+#include "common/dpp.h"
 #include "common/ocv.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
@@ -3008,6 +3009,37 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
                }
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_DPP2
+               dpp_pfs_free(sta->dpp_pfs);
+               sta->dpp_pfs = NULL;
+
+               if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
+                   hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
+                   wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
+                   elems.owe_dh) {
+                       sta->dpp_pfs = dpp_pfs_init(
+                               wpabuf_head(hapd->conf->dpp_netaccesskey),
+                               wpabuf_len(hapd->conf->dpp_netaccesskey));
+                       if (!sta->dpp_pfs) {
+                               wpa_printf(MSG_DEBUG,
+                                          "DPP: Could not initialize PFS");
+                               /* Try to continue without PFS */
+                               goto pfs_fail;
+                       }
+
+                       if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh,
+                                           elems.owe_dh_len) < 0) {
+                               dpp_pfs_free(sta->dpp_pfs);
+                               sta->dpp_pfs = NULL;
+                               return WLAN_STATUS_UNSPECIFIED_FAILURE;
+                       }
+               }
+
+               wpa_auth_set_dpp_z(sta->wpa_sm, sta->dpp_pfs ?
+                                  sta->dpp_pfs->secret : NULL);
+       pfs_fail:
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_IEEE80211N
                if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
                    wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
@@ -3278,6 +3310,10 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
        if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
                buflen += 150;
 #endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP2
+       if (sta && sta->dpp_pfs)
+               buflen += 5 + sta->dpp_pfs->curve->prime_len;
+#endif /* CONFIG_DPP2 */
        buf = os_zalloc(buflen);
        if (!buf) {
                res = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -3385,6 +3421,16 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
        }
 #endif /* CONFIG_FST */
 
+#ifdef CONFIG_DPP2
+       if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
+           sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS &&
+           wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) {
+               os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie),
+                         wpabuf_len(sta->dpp_pfs->ie));
+               p += wpabuf_len(sta->dpp_pfs->ie);
+       }
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_IEEE80211AC
        if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
                p = hostapd_eid_vendor_vht(hapd, p);
index 4a7722c28bcaca85d6f8e559a238de83af3f86f6..71f9f21da82e176bf1104b2e7d933d13bc3a6452 100644 (file)
@@ -13,6 +13,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/wpa_ctrl.h"
 #include "common/sae.h"
+#include "common/dpp.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
 #include "p2p/p2p.h"
@@ -362,6 +363,11 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
        crypto_ecdh_deinit(sta->owe_ecdh);
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_DPP2
+       dpp_pfs_free(sta->dpp_pfs);
+       sta->dpp_pfs = NULL;
+#endif /* CONFIG_DPP2 */
+
        os_free(sta->ext_capability);
 
 #ifdef CONFIG_WNM_AP
index ee3f628a41a19b087aa2e3613c9b8f00ebc4c0ea..ece0c60abd3641bdfe4d58a94d1982c0561e8618 100644 (file)
@@ -265,6 +265,10 @@ struct sta_info {
        u8 *ext_capability;
        char *ifname_wds; /* WDS ifname, if in use */
 
+#ifdef CONFIG_DPP2
+       struct dpp_pfs *dpp_pfs;
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_TESTING_OPTIONS
        enum wpa_alg last_tk_alg;
        int last_tk_key_idx;
index 71dd00bc5b54fa47c051bd1293ec4cc2a9aec774..166f4786de841366b7efff70780545a8da86db29 100644 (file)
@@ -696,6 +696,9 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
        os_free(sm->last_rx_eapol_key);
        os_free(sm->wpa_ie);
        wpa_group_put(sm->wpa_auth, sm->group);
+#ifdef CONFIG_DPP2
+       wpabuf_clear_free(sm->dpp_z);
+#endif /* CONFIG_DPP2 */
        os_free(sm);
 }
 
@@ -2153,14 +2156,24 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
                          const u8 *pmk, unsigned int pmk_len,
                          struct wpa_ptk *ptk)
 {
+       const u8 *z = NULL;
+       size_t z_len = 0;
+
 #ifdef CONFIG_IEEE80211R_AP
        if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
                return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
 #endif /* CONFIG_IEEE80211R_AP */
 
+#ifdef CONFIG_DPP2
+       if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
+               z = wpabuf_head(sm->dpp_z);
+               z_len = wpabuf_len(sm->dpp_z);
+       }
+#endif /* CONFIG_DPP2 */
+
        return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
                              sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
-                             ptk, sm->wpa_key_mgmt, sm->pairwise, NULL, 0);
+                             ptk, sm->wpa_key_mgmt, sm->pairwise, z, z_len);
 }
 
 
@@ -4829,6 +4842,17 @@ void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
 }
 
 
+#ifdef CONFIG_DPP2
+void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
+{
+       if (sm) {
+               wpabuf_clear_free(sm->dpp_z);
+               sm->dpp_z = z ? wpabuf_dup(z) : NULL;
+       }
+}
+#endif /* CONFIG_DPP2 */
+
+
 #ifdef CONFIG_TESTING_OPTIONS
 
 int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
index 50a8d1743f532f31ecae8abd79fecd828fc45728..484e1e5cb73f552169705b3f9fd3f31361d2afc7 100644 (file)
@@ -474,6 +474,7 @@ u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
                                   u8 *pos, size_t max_len,
                                   const u8 *req_ies, size_t req_ies_len);
 void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
+void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
 
 int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
                       void (*cb)(void *ctx1, void *ctx2),
index a3164d26558be0da2eb667ceb08a934b09baedfb..3dcf77aa9aec3091f60702a1a92456e372ca4e92 100644 (file)
@@ -151,6 +151,10 @@ struct wpa_state_machine {
        unsigned int fils_completed:1;
 #endif /* CONFIG_FILS */
 
+#ifdef CONFIG_DPP2
+       struct wpabuf *dpp_z;
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_TESTING_OPTIONS
        void (*eapol_status_cb)(void *ctx1, void *ctx2);
        void *eapol_status_cb_ctx1;
index ca724bd6db3f55cb36e398367f79457f9ea6fc56..58a39f9dc8ca0172b452f43c294b6543c22da89c 100644 (file)
@@ -8131,3 +8131,87 @@ fail:
        goto out;
 }
 #endif /* CONFIG_TESTING_OPTIONS */
+
+
+#ifdef CONFIG_DPP2
+
+struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
+                             size_t net_access_key_len)
+{
+       struct wpabuf *pub = NULL;
+       EVP_PKEY *own_key;
+       struct dpp_pfs *pfs;
+
+       pfs = os_zalloc(sizeof(*pfs));
+       if (!pfs)
+               return NULL;
+
+       own_key = dpp_set_keypair(&pfs->curve, net_access_key,
+                                 net_access_key_len);
+       if (!own_key) {
+               wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
+               goto fail;
+       }
+       EVP_PKEY_free(own_key);
+
+       pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
+       if (!pfs->ecdh)
+               goto fail;
+
+       pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
+       pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
+       if (!pub)
+               goto fail;
+
+       pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
+       if (!pfs->ie)
+               goto fail;
+       wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
+       wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
+       wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
+       wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
+       wpabuf_put_buf(pfs->ie, pub);
+       wpabuf_free(pub);
+       wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
+                       pfs->ie);
+
+       return pfs;
+fail:
+       wpabuf_free(pub);
+       dpp_pfs_free(pfs);
+       return NULL;
+}
+
+
+int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
+{
+       if (peer_ie_len < 2)
+               return -1;
+       if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
+               wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
+               return -1;
+       }
+
+       pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
+                                             peer_ie_len - 2);
+       pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
+       if (!pfs->secret) {
+               wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
+               return -1;
+       }
+       wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
+       return 0;
+}
+
+
+void dpp_pfs_free(struct dpp_pfs *pfs)
+{
+       if (!pfs)
+               return;
+       crypto_ecdh_deinit(pfs->ecdh);
+       wpabuf_free(pfs->ie);
+       wpabuf_clear_free(pfs->secret);
+       os_free(pfs);
+}
+
+#endif /* CONFIG_DPP2 */
index eb25de633faf1c42df128bfad1034d4d632d5529..2a6f72dda17d2611169d6b4fd06fb0bcb0a7a1f7 100644 (file)
@@ -16,6 +16,8 @@
 #include "common/wpa_common.h"
 #include "crypto/sha256.h"
 
+struct crypto_ecdh;
+
 #define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
 
 enum dpp_public_action_frame_type {
@@ -458,4 +460,17 @@ void dpp_pkex_free(struct dpp_pkex *pkex);
 
 char * dpp_corrupt_connector_signature(const char *connector);
 
+
+struct dpp_pfs {
+       struct crypto_ecdh *ecdh;
+       const struct dpp_curve_params *curve;
+       struct wpabuf *ie;
+       struct wpabuf *secret;
+};
+
+struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
+                             size_t net_access_key_len);
+int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
+void dpp_pfs_free(struct dpp_pfs *pfs);
+
 #endif /* DPP_H */
index 76f7c3faba5ee16d76fe6387e121795b8adfb797..6e43aaedfa0cb5ecd731813f463d240d2de315ee 100644 (file)
@@ -534,15 +534,25 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
 static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
                          const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
 {
+       const u8 *z = NULL;
+       size_t z_len = 0;
+
 #ifdef CONFIG_IEEE80211R
        if (wpa_key_mgmt_ft(sm->key_mgmt))
                return wpa_derive_ptk_ft(sm, src_addr, key, ptk);
 #endif /* CONFIG_IEEE80211R */
 
+#ifdef CONFIG_DPP2
+       if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
+               z = wpabuf_head(sm->dpp_z);
+               z_len = wpabuf_len(sm->dpp_z);
+       }
+#endif /* CONFIG_DPP2 */
+
        return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
                              sm->own_addr, sm->bssid, sm->snonce,
                              key->key_nonce, ptk, sm->key_mgmt,
-                             sm->pairwise_cipher, NULL, 0);
+                             sm->pairwise_cipher, z, z_len);
 }
 
 
@@ -2637,6 +2647,9 @@ void wpa_sm_deinit(struct wpa_sm *sm)
 #ifdef CONFIG_OWE
        crypto_ecdh_deinit(sm->owe_ecdh);
 #endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP2
+       wpabuf_clear_free(sm->dpp_z);
+#endif /* CONFIG_DPP2 */
        os_free(sm);
 }
 
@@ -4636,3 +4649,14 @@ void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id)
        }
 #endif /* CONFIG_FILS */
 }
+
+
+#ifdef CONFIG_DPP2
+void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z)
+{
+       if (sm) {
+               wpabuf_clear_free(sm->dpp_z);
+               sm->dpp_z = z ? wpabuf_dup(z) : NULL;
+       }
+}
+#endif /* CONFIG_DPP2 */
index 9eee383de60f38145fd2e40e2f3a5ceccac6f52a..8903f8e14c691ead13161b1a4e7dcd6de3129e1c 100644 (file)
@@ -465,5 +465,6 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid,
 
 void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set);
 void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id);
+void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z);
 
 #endif /* WPA_H */
index e1a213bd1b2bcc61a7d9dcd91cce1405ac2d6283..5dc9f2ed5e7a03180c143e252cebf274ef1b20a6 100644 (file)
@@ -168,6 +168,10 @@ struct wpa_sm {
        struct crypto_ecdh *owe_ecdh;
        u16 owe_group;
 #endif /* CONFIG_OWE */
+
+#ifdef CONFIG_DPP2
+       struct wpabuf *dpp_z;
+#endif /* CONFIG_DPP2 */
 };
 
 
index fa0c066df494f0c6df2d0ccc5b5ac2dc6aef11c4..db8699117477b97dbda68dea9c184c791c221b62 100644 (file)
@@ -2638,6 +2638,8 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
        eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
 #ifdef CONFIG_DPP2
        eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
+       dpp_pfs_free(wpa_s->dpp_pfs);
+       wpa_s->dpp_pfs = NULL;
 #endif /* CONFIG_DPP2 */
        offchannel_send_action_done(wpa_s);
        wpas_dpp_listen_stop(wpa_s);
index daca69cdbab6601a3c75ad82253dc40c61ca47e0..a46ef187cb9b3762e5414a20631955534fca450c 100644 (file)
@@ -29,6 +29,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "common/gas_server.h"
+#include "common/dpp.h"
 #include "crypto/random.h"
 #include "blacklist.h"
 #include "wpas_glue.h"
@@ -2498,6 +2499,28 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
        }
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_DPP2
+       wpa_sm_set_dpp_z(wpa_s->wpa, NULL);
+       if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->dpp_pfs) {
+               struct ieee802_11_elems elems;
+
+               if (ieee802_11_parse_elems(data->assoc_info.resp_ies,
+                                          data->assoc_info.resp_ies_len,
+                                          &elems, 0) == ParseFailed ||
+                   !elems.owe_dh)
+                       goto no_pfs;
+               if (dpp_pfs_process(wpa_s->dpp_pfs, elems.owe_dh,
+                                   elems.owe_dh_len) < 0) {
+                       wpa_supplicant_deauthenticate(wpa_s,
+                                                     WLAN_REASON_UNSPECIFIED);
+                       return -1;
+               }
+
+               wpa_sm_set_dpp_z(wpa_s->wpa, wpa_s->dpp_pfs->secret);
+       }
+no_pfs:
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_IEEE80211R
 #ifdef CONFIG_SME
        if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
index 213bf0d61a1fb2b754418efc8dc84ffd27c7d398..c435bf30557e1117ea20ac44654910c959c4d603 100644 (file)
@@ -16,6 +16,7 @@
 #include "eapol_supp/eapol_supp_sm.h"
 #include "common/wpa_common.h"
 #include "common/sae.h"
+#include "common/dpp.h"
 #include "rsn_supp/wpa.h"
 #include "rsn_supp/pmksa_cache.h"
 #include "config.h"
@@ -1571,6 +1572,36 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
        }
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_DPP2
+       if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid &&
+           wpa_s->current_ssid->dpp_netaccesskey) {
+               struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+               dpp_pfs_free(wpa_s->dpp_pfs);
+               wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
+                                             ssid->dpp_netaccesskey_len);
+               if (!wpa_s->dpp_pfs) {
+                       wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
+                       /* Try to continue without PFS */
+                       goto pfs_fail;
+               }
+               if (wpa_s->sme.assoc_req_ie_len +
+                   wpabuf_len(wpa_s->dpp_pfs->ie) >
+                   sizeof(wpa_s->sme.assoc_req_ie)) {
+                       wpa_printf(MSG_ERROR,
+                                  "DPP: Not enough buffer room for own Association Request frame elements");
+                       dpp_pfs_free(wpa_s->dpp_pfs);
+                       wpa_s->dpp_pfs = NULL;
+                       goto pfs_fail;
+               }
+               os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+                         wpabuf_head(wpa_s->dpp_pfs->ie),
+                         wpabuf_len(wpa_s->dpp_pfs->ie));
+               wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
+       }
+pfs_fail:
+#endif /* CONFIG_DPP2 */
+
        if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) {
                size_t multi_ap_ie_len;
 
index 58140bc35bb2e7f1cea652771b48e1223a4f67db..bcc0693ea2e5a457a553286a914e6ce1f371a3d7 100644 (file)
@@ -39,6 +39,7 @@
 #include "common/ieee802_11_defs.h"
 #include "common/hw_features_common.h"
 #include "common/gas_server.h"
+#include "common/dpp.h"
 #include "p2p/p2p.h"
 #include "fst/fst.h"
 #include "blacklist.h"
@@ -2832,6 +2833,28 @@ static u8 * wpas_populate_assoc_ies(
        }
 #endif /* CONFIG_OWE */
 
+#ifdef CONFIG_DPP2
+       if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
+           ssid->dpp_netaccesskey) {
+               dpp_pfs_free(wpa_s->dpp_pfs);
+               wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
+                                             ssid->dpp_netaccesskey_len);
+               if (!wpa_s->dpp_pfs) {
+                       wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
+                       /* Try to continue without PFS */
+                       goto pfs_fail;
+               }
+               if (wpabuf_len(wpa_s->dpp_pfs->ie) <=
+                   max_wpa_ie_len - wpa_ie_len) {
+                       os_memcpy(wpa_ie + wpa_ie_len,
+                                 wpabuf_head(wpa_s->dpp_pfs->ie),
+                                 wpabuf_len(wpa_s->dpp_pfs->ie));
+                       wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
+               }
+       }
+pfs_fail:
+#endif /* CONFIG_DPP2 */
+
 #ifdef CONFIG_IEEE80211R
        /*
         * Add MDIE under these conditions: the network profile allows FT,
index fa0770fa9581612da73eee7224e97d3471605f89..0db6e551d3e769788e43aa7696642f1b33e3a2aa 100644 (file)
@@ -1236,6 +1236,9 @@ struct wpa_supplicant {
        unsigned int dpp_resp_wait_time;
        unsigned int dpp_resp_max_tries;
        unsigned int dpp_resp_retry_time;
+#ifdef CONFIG_DPP2
+       struct dpp_pfs *dpp_pfs;
+#endif /* CONFIG_DPP2 */
 #ifdef CONFIG_TESTING_OPTIONS
        char *dpp_config_obj_override;
        char *dpp_discovery_override;