From ecacd9ccd45682949f5136ea4f18e131a159846c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 Mar 2019 22:02:06 +0200 Subject: [PATCH] DPP2: Extend wpa_pmk_to_ptk() to support extra Z.x component in context DPP allows Diffie-Hellman exchange to be used for PFS in PTK derivation. This requires an additional Z.x (x coordinate of the DH shared secret) to be passed to wpa_pmk_to_ptk(). This commit adds that to the function and updates all the callers to pass NULL,0 for that part in preparation of the DPP specific changes to start using this. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 2 +- src/common/wpa_common.c | 36 +++++++++++++++++++++++++++--------- src/common/wpa_common.h | 3 ++- src/rsn_supp/wpa.c | 2 +- wlantest/rx_eapol.c | 2 +- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 1cb8113d0..71dd00bc5 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2160,7 +2160,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, 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); + ptk, sm->wpa_key_mgmt, sm->pairwise, NULL, 0); } diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 613d5d05b..2c5b2eba2 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -340,14 +340,21 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", * Min(AA, SA) || Max(AA, SA) || - * Min(ANonce, SNonce) || Max(ANonce, SNonce)) + * Min(ANonce, SNonce) || Max(ANonce, SNonce) + * [ || Z.x ]) + * + * The optional Z.x component is used only with DPP and that part is not defined + * in IEEE 802.11. */ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, - struct wpa_ptk *ptk, int akmp, int cipher) + struct wpa_ptk *ptk, int akmp, int cipher, + const u8 *z, size_t z_len) { - u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; +#define MAX_Z_LEN 66 /* with NIST P-521 */ + u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN + MAX_Z_LEN]; + size_t data_len = 2 * ETH_ALEN + 2 * WPA_NONCE_LEN; u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; size_t ptk_len; @@ -356,6 +363,9 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, return -1; } + if (z_len > MAX_Z_LEN) + return -1; + if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { os_memcpy(data, addr1, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); @@ -374,6 +384,11 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, WPA_NONCE_LEN); } + if (z && z_len) { + os_memcpy(data + 2 * ETH_ALEN + 2 * WPA_NONCE_LEN, z, z_len); + data_len += z_len; + } + ptk->kck_len = wpa_kck_len(akmp, pmk_len); ptk->kek_len = wpa_kek_len(akmp, pmk_len); ptk->tk_len = wpa_cipher_key_len(cipher); @@ -388,7 +403,7 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, if (wpa_key_mgmt_sha384(akmp)) { #if defined(CONFIG_SUITEB192) || defined(CONFIG_FILS) wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)"); - if (sha384_prf(pmk, pmk_len, label, data, sizeof(data), + if (sha384_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) return -1; #else /* CONFIG_SUITEB192 || CONFIG_FILS */ @@ -397,7 +412,7 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, } else if (wpa_key_mgmt_sha256(akmp) || akmp == WPA_KEY_MGMT_OWE) { #if defined(CONFIG_IEEE80211W) || defined(CONFIG_SAE) || defined(CONFIG_FILS) wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)"); - if (sha256_prf(pmk, pmk_len, label, data, sizeof(data), + if (sha256_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) return -1; #else /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */ @@ -406,17 +421,17 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, #ifdef CONFIG_DPP } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 32) { wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)"); - if (sha256_prf(pmk, pmk_len, label, data, sizeof(data), + if (sha256_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) return -1; } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 48) { wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)"); - if (sha384_prf(pmk, pmk_len, label, data, sizeof(data), + if (sha384_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) return -1; } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 64) { wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA512)"); - if (sha512_prf(pmk, pmk_len, label, data, sizeof(data), + if (sha512_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) return -1; } else if (akmp == WPA_KEY_MGMT_DPP) { @@ -426,7 +441,7 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, #endif /* CONFIG_DPP */ } else { wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA1)"); - if (sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, + if (sha1_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) return -1; } @@ -435,6 +450,8 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, MAC2STR(addr1), MAC2STR(addr2)); wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); + if (z && z_len) + wpa_hexdump_key(MSG_DEBUG, "WPA: Z.x", z, z_len); wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len); @@ -451,6 +468,7 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, ptk->kck2_len = 0; os_memset(tmp, 0, sizeof(tmp)); + os_memset(data, 0, data_len); return 0; } diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 2d9a71564..e83d6887a 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -347,7 +347,8 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, - struct wpa_ptk *ptk, int akmp, int cipher); + struct wpa_ptk *ptk, int akmp, int cipher, + const u8 *z, size_t z_len); int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len, const u8 *snonce, const u8 *anonce, const u8 *dh_ss, size_t dh_ss_len, u8 *pmk, size_t *pmk_len); diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 4b42f89b5..76f7c3fab 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -542,7 +542,7 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, 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); + sm->pairwise_cipher, NULL, 0); } diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 9c52fbac4..1af48ec8f 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -130,7 +130,7 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss, "Pairwise key expansion", bss->bssid, sta->addr, sta->anonce, sta->snonce, &ptk, sta->key_mgmt, - sta->pairwise_cipher) < 0 || + sta->pairwise_cipher, NULL, 0) < 0 || check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data, len) < 0) { return -1;