From 10ec6a5f38f1dfee75aeb7a0358271dc4d56834f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 Mar 2019 23:51:53 +0200 Subject: [PATCH] DPP2: PFS for PTK derivation 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 --- src/ap/drv_callbacks.c | 33 ++++++++++++ src/ap/ieee802_11.c | 46 +++++++++++++++++ src/ap/sta_info.c | 6 +++ src/ap/sta_info.h | 4 ++ src/ap/wpa_auth.c | 26 +++++++++- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_i.h | 4 ++ src/common/dpp.c | 84 +++++++++++++++++++++++++++++++ src/common/dpp.h | 15 ++++++ src/rsn_supp/wpa.c | 26 +++++++++- src/rsn_supp/wpa.h | 1 + src/rsn_supp/wpa_i.h | 4 ++ wpa_supplicant/dpp_supplicant.c | 2 + wpa_supplicant/events.c | 23 +++++++++ wpa_supplicant/sme.c | 31 ++++++++++++ wpa_supplicant/wpa_supplicant.c | 23 +++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 ++ 17 files changed, 330 insertions(+), 2 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index cf01854e1..8ddf754f6 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -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); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index df80b58dc..bb05f1aed 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -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); diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 4a7722c28..71f9f21da 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -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 diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index ee3f628a4..ece0c60ab 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -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; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 71dd00bc5..166f4786d 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -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, diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 50a8d1743..484e1e5cb 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -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), diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index a3164d265..3dcf77aa9 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -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; diff --git a/src/common/dpp.c b/src/common/dpp.c index ca724bd6d..58a39f9dc 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -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 */ diff --git a/src/common/dpp.h b/src/common/dpp.h index eb25de633..2a6f72dda 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -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 */ diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 76f7c3fab..6e43aaedf 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -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 */ diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 9eee383de..8903f8e14 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -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 */ diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index e1a213bd1..5dc9f2ed5 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -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 */ }; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index fa0c066df..db8699117 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -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); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index daca69cdb..a46ef187c 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -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) { diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 213bf0d61..c435bf305 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -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; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 58140bc35..bcc0693ea 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -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, diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index fa0770fa9..0db6e551d 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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; -- 2.39.2