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 <jouni@codeaurora.org>
This commit is contained in:
parent
ecacd9ccd4
commit
10ec6a5f38
17 changed files with 330 additions and 2 deletions
|
@ -15,6 +15,7 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/ieee802_11_common.h"
|
#include "common/ieee802_11_common.h"
|
||||||
#include "common/wpa_ctrl.h"
|
#include "common/wpa_ctrl.h"
|
||||||
|
#include "common/dpp.h"
|
||||||
#include "crypto/random.h"
|
#include "crypto/random.h"
|
||||||
#include "p2p/p2p.h"
|
#include "p2p/p2p.h"
|
||||||
#include "wps/wps.h"
|
#include "wps/wps.h"
|
||||||
|
@ -565,6 +566,38 @@ skip_wpa_check:
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OWE */
|
#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)
|
#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE)
|
||||||
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "common/ieee802_11_common.h"
|
#include "common/ieee802_11_common.h"
|
||||||
#include "common/wpa_ctrl.h"
|
#include "common/wpa_ctrl.h"
|
||||||
#include "common/sae.h"
|
#include "common/sae.h"
|
||||||
|
#include "common/dpp.h"
|
||||||
#include "common/ocv.h"
|
#include "common/ocv.h"
|
||||||
#include "radius/radius.h"
|
#include "radius/radius.h"
|
||||||
#include "radius/radius_client.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 */
|
#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
|
#ifdef CONFIG_IEEE80211N
|
||||||
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
|
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
|
||||||
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
|
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))
|
if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
|
||||||
buflen += 150;
|
buflen += 150;
|
||||||
#endif /* CONFIG_OWE */
|
#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);
|
buf = os_zalloc(buflen);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
res = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
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 */
|
#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
|
#ifdef CONFIG_IEEE80211AC
|
||||||
if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
|
if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
|
||||||
p = hostapd_eid_vendor_vht(hapd, p);
|
p = hostapd_eid_vendor_vht(hapd, p);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/wpa_ctrl.h"
|
#include "common/wpa_ctrl.h"
|
||||||
#include "common/sae.h"
|
#include "common/sae.h"
|
||||||
|
#include "common/dpp.h"
|
||||||
#include "radius/radius.h"
|
#include "radius/radius.h"
|
||||||
#include "radius/radius_client.h"
|
#include "radius/radius_client.h"
|
||||||
#include "p2p/p2p.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);
|
crypto_ecdh_deinit(sta->owe_ecdh);
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
dpp_pfs_free(sta->dpp_pfs);
|
||||||
|
sta->dpp_pfs = NULL;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
os_free(sta->ext_capability);
|
os_free(sta->ext_capability);
|
||||||
|
|
||||||
#ifdef CONFIG_WNM_AP
|
#ifdef CONFIG_WNM_AP
|
||||||
|
|
|
@ -265,6 +265,10 @@ struct sta_info {
|
||||||
u8 *ext_capability;
|
u8 *ext_capability;
|
||||||
char *ifname_wds; /* WDS ifname, if in use */
|
char *ifname_wds; /* WDS ifname, if in use */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
struct dpp_pfs *dpp_pfs;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
enum wpa_alg last_tk_alg;
|
enum wpa_alg last_tk_alg;
|
||||||
int last_tk_key_idx;
|
int last_tk_key_idx;
|
||||||
|
|
|
@ -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->last_rx_eapol_key);
|
||||||
os_free(sm->wpa_ie);
|
os_free(sm->wpa_ie);
|
||||||
wpa_group_put(sm->wpa_auth, sm->group);
|
wpa_group_put(sm->wpa_auth, sm->group);
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
wpabuf_clear_free(sm->dpp_z);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
os_free(sm);
|
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,
|
const u8 *pmk, unsigned int pmk_len,
|
||||||
struct wpa_ptk *ptk)
|
struct wpa_ptk *ptk)
|
||||||
{
|
{
|
||||||
|
const u8 *z = NULL;
|
||||||
|
size_t z_len = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
|
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
|
||||||
return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
|
return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#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",
|
return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
|
||||||
sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
|
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
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
|
||||||
int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
|
int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
|
||||||
|
|
|
@ -474,6 +474,7 @@ u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
|
||||||
u8 *pos, size_t max_len,
|
u8 *pos, size_t max_len,
|
||||||
const u8 *req_ies, size_t req_ies_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_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,
|
int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
|
||||||
void (*cb)(void *ctx1, void *ctx2),
|
void (*cb)(void *ctx1, void *ctx2),
|
||||||
|
|
|
@ -151,6 +151,10 @@ struct wpa_state_machine {
|
||||||
unsigned int fils_completed:1;
|
unsigned int fils_completed:1;
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
struct wpabuf *dpp_z;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
void (*eapol_status_cb)(void *ctx1, void *ctx2);
|
void (*eapol_status_cb)(void *ctx1, void *ctx2);
|
||||||
void *eapol_status_cb_ctx1;
|
void *eapol_status_cb_ctx1;
|
||||||
|
|
|
@ -8131,3 +8131,87 @@ fail:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#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 */
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "common/wpa_common.h"
|
#include "common/wpa_common.h"
|
||||||
#include "crypto/sha256.h"
|
#include "crypto/sha256.h"
|
||||||
|
|
||||||
|
struct crypto_ecdh;
|
||||||
|
|
||||||
#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
|
#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
|
||||||
|
|
||||||
enum dpp_public_action_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);
|
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 */
|
#endif /* DPP_H */
|
||||||
|
|
|
@ -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,
|
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 struct wpa_eapol_key *key, struct wpa_ptk *ptk)
|
||||||
{
|
{
|
||||||
|
const u8 *z = NULL;
|
||||||
|
size_t z_len = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (wpa_key_mgmt_ft(sm->key_mgmt))
|
if (wpa_key_mgmt_ft(sm->key_mgmt))
|
||||||
return wpa_derive_ptk_ft(sm, src_addr, key, ptk);
|
return wpa_derive_ptk_ft(sm, src_addr, key, ptk);
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#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",
|
return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
|
||||||
sm->own_addr, sm->bssid, sm->snonce,
|
sm->own_addr, sm->bssid, sm->snonce,
|
||||||
key->key_nonce, ptk, sm->key_mgmt,
|
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
|
#ifdef CONFIG_OWE
|
||||||
crypto_ecdh_deinit(sm->owe_ecdh);
|
crypto_ecdh_deinit(sm->owe_ecdh);
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
wpabuf_clear_free(sm->dpp_z);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
os_free(sm);
|
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 */
|
#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 */
|
||||||
|
|
|
@ -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_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_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 */
|
#endif /* WPA_H */
|
||||||
|
|
|
@ -168,6 +168,10 @@ struct wpa_sm {
|
||||||
struct crypto_ecdh *owe_ecdh;
|
struct crypto_ecdh *owe_ecdh;
|
||||||
u16 owe_group;
|
u16 owe_group;
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
struct wpabuf *dpp_z;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
|
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 */
|
#endif /* CONFIG_DPP2 */
|
||||||
offchannel_send_action_done(wpa_s);
|
offchannel_send_action_done(wpa_s);
|
||||||
wpas_dpp_listen_stop(wpa_s);
|
wpas_dpp_listen_stop(wpa_s);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/ieee802_11_common.h"
|
#include "common/ieee802_11_common.h"
|
||||||
#include "common/gas_server.h"
|
#include "common/gas_server.h"
|
||||||
|
#include "common/dpp.h"
|
||||||
#include "crypto/random.h"
|
#include "crypto/random.h"
|
||||||
#include "blacklist.h"
|
#include "blacklist.h"
|
||||||
#include "wpas_glue.h"
|
#include "wpas_glue.h"
|
||||||
|
@ -2498,6 +2499,28 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OWE */
|
#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_IEEE80211R
|
||||||
#ifdef CONFIG_SME
|
#ifdef CONFIG_SME
|
||||||
if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
|
if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "eapol_supp/eapol_supp_sm.h"
|
#include "eapol_supp/eapol_supp_sm.h"
|
||||||
#include "common/wpa_common.h"
|
#include "common/wpa_common.h"
|
||||||
#include "common/sae.h"
|
#include "common/sae.h"
|
||||||
|
#include "common/dpp.h"
|
||||||
#include "rsn_supp/wpa.h"
|
#include "rsn_supp/wpa.h"
|
||||||
#include "rsn_supp/pmksa_cache.h"
|
#include "rsn_supp/pmksa_cache.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -1571,6 +1572,36 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OWE */
|
#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) {
|
if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) {
|
||||||
size_t multi_ap_ie_len;
|
size_t multi_ap_ie_len;
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/hw_features_common.h"
|
#include "common/hw_features_common.h"
|
||||||
#include "common/gas_server.h"
|
#include "common/gas_server.h"
|
||||||
|
#include "common/dpp.h"
|
||||||
#include "p2p/p2p.h"
|
#include "p2p/p2p.h"
|
||||||
#include "fst/fst.h"
|
#include "fst/fst.h"
|
||||||
#include "blacklist.h"
|
#include "blacklist.h"
|
||||||
|
@ -2832,6 +2833,28 @@ static u8 * wpas_populate_assoc_ies(
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OWE */
|
#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
|
#ifdef CONFIG_IEEE80211R
|
||||||
/*
|
/*
|
||||||
* Add MDIE under these conditions: the network profile allows FT,
|
* Add MDIE under these conditions: the network profile allows FT,
|
||||||
|
|
|
@ -1236,6 +1236,9 @@ struct wpa_supplicant {
|
||||||
unsigned int dpp_resp_wait_time;
|
unsigned int dpp_resp_wait_time;
|
||||||
unsigned int dpp_resp_max_tries;
|
unsigned int dpp_resp_max_tries;
|
||||||
unsigned int dpp_resp_retry_time;
|
unsigned int dpp_resp_retry_time;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
struct dpp_pfs *dpp_pfs;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
char *dpp_config_obj_override;
|
char *dpp_config_obj_override;
|
||||||
char *dpp_discovery_override;
|
char *dpp_discovery_override;
|
||||||
|
|
Loading…
Reference in a new issue