[PATCH 11/12] FT: Extend the wpa_pmk_r1_to_ptk() function to also derive HLTK

Ilan Peer <[email protected]>
Newsgroups gmane.linux.drivers.hostap
Message-ID <[email protected]>
Extend the wpa_pmk_r1_to_ptk() to also derive High Level
Transient Key (HLTK), which can later be used for secure
LTF measurements.

Signed-off-by: Ilan Peer <[email protected]>
---
 src/ap/wpa_auth.c       |  4 +++-
 src/ap/wpa_auth_ft.c    |  7 +++++--
 src/common/wpa_common.c | 23 ++++++++++++++++++++---
 src/common/wpa_common.h |  3 ++-
 src/rsn_supp/wpa_ft.c   |  6 ++++--
 wlantest/rx_eapol.c     |  2 +-
 wlantest/rx_mgmt.c      |  4 ++--
 7 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 88c3c5aede..d77c0b02f6 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -2271,7 +2271,9 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
 						 sm->pmk_r1_name,
 						 ptk, ptk_name,
 						 sm->wpa_key_mgmt,
-						 sm->pairwise);
+						 sm->pairwise,
+						 sm->wpa_auth->conf.hltk ?
+						 WPA_HLTK_MAX_LEN : 0);
 		}
 		return wpa_auth_derive_ptk_ft(sm, ptk);
 	}
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index c0b462558f..fd654ecd0f 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -2151,7 +2151,8 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
 
 	return wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
 				 sm->addr, sm->wpa_auth->addr, sm->pmk_r1_name,
-				 ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise);
+				 ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise,
+				 0);
 }
 
 
@@ -3090,7 +3091,9 @@ pmk_r1_derived:
 	if (wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
 			      sm->addr, sm->wpa_auth->addr, pmk_r1_name,
 			      &sm->PTK, ptk_name, sm->wpa_key_mgmt,
-			      pairwise) < 0)
+			      pairwise,
+			      sm->wpa_auth->conf.hltk ?
+			      WPA_HLTK_MAX_LEN : 0) < 0)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
 	sm->pairwise = pairwise;
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 844bb343eb..24cfcaba50 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1740,16 +1740,25 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
 		      const u8 *snonce, const u8 *anonce,
 		      const u8 *sta_addr, const u8 *bssid,
 		      const u8 *pmk_r1_name,
-		      struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
+		      struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher,
+		      size_t hltk_len)
 {
 	u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
 	u8 *pos, hash[32];
 	const u8 *addr[6];
 	size_t len[6];
-	u8 tmp[2 * WPA_KCK_MAX_LEN + 2 * WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
+	u8 tmp[2 * WPA_KCK_MAX_LEN + 2 * WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN +
+	       WPA_HLTK_MAX_LEN];
 	size_t ptk_len, offset;
 	int use_sha384 = wpa_key_mgmt_sha384(akmp);
 
+	if (hltk_len > WPA_HLTK_MAX_LEN) {
+		wpa_printf(MSG_ERROR,
+			   "FT: HLTK len=%zu exceeds max supported len",
+			   hltk_len);
+		return -1;
+	}
+
 	/*
 	 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
 	 *                  BSSID || STA-ADDR)
@@ -1776,8 +1785,9 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
 	ptk->kek_len = wpa_kek_len(akmp, PMK_LEN);
 	ptk->kek2_len = wpa_kek2_len(akmp);
 	ptk->tk_len = wpa_cipher_key_len(cipher);
+	ptk->hltk_len = hltk_len;
 	ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len +
-		ptk->kck2_len + ptk->kek2_len;
+		ptk->kck2_len + ptk->kek2_len + ptk->hltk_len;
 
 #ifdef CONFIG_SHA384
 	if (use_sha384) {
@@ -1836,6 +1846,9 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
 	os_memcpy(ptk->kck2, tmp + offset, ptk->kck2_len);
 	offset += ptk->kck2_len;
 	os_memcpy(ptk->kek2, tmp + offset, ptk->kek2_len);
+	offset += ptk->kek2_len;
+	os_memcpy(ptk->hltk, tmp + offset, ptk->hltk_len);
+	offset += ptk->hltk_len;
 
 	wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
 	wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
@@ -1845,6 +1858,10 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
 	if (ptk->kek2_len)
 		wpa_hexdump_key(MSG_DEBUG, "FT: KEK2",
 				ptk->kek2, ptk->kek2_len);
+	if (ptk->hltk_len)
+		wpa_hexdump_key(MSG_DEBUG, "FT: HLTK",
+				ptk->hltk, ptk->hltk_len);
+
 	wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
 	wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
 
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 99ec57bb38..3815584964 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -400,7 +400,8 @@ int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
 int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len, const u8 *snonce,
 		      const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
 		      const u8 *pmk_r1_name,
-		      struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher);
+		      struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher,
+		      size_t hltk_len);
 #endif /* CONFIG_IEEE80211R */
 
 struct wpa_ie_data {
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 046bdfd169..42b85147df 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -63,7 +63,8 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
 		    WPA_PMK_NAME_LEN);
 	return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, anonce,
 				 sm->own_addr, sm->bssid, sm->pmk_r1_name, ptk,
-				 ptk_name, sm->key_mgmt, sm->pairwise_cipher);
+				 ptk_name, sm->key_mgmt, sm->pairwise_cipher,
+				 sm->hltk ? WPA_HLTK_MAX_LEN : 0);
 }
 
 
@@ -633,7 +634,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
 	if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce,
 			      anonce, sm->own_addr, bssid,
 			      sm->pmk_r1_name, &sm->ptk, ptk_name, sm->key_mgmt,
-			      sm->pairwise_cipher) < 0)
+			      sm->pairwise_cipher,
+			      sm->hltk ? WPA_HLTK_MAX_LEN : 0) < 0)
 		return -1;
 
 	if (wpa_key_mgmt_fils(sm->key_mgmt)) {
diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c
index 0a75a89dbc..3f85c14333 100644
--- a/wlantest/rx_eapol.c
+++ b/wlantest/rx_eapol.c
@@ -124,7 +124,7 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
 				      sta->addr,
 				      bss->bssid, pmk_r1_name, &ptk, ptk_name,
 				      sta->key_mgmt,
-				      sta->pairwise_cipher) < 0 ||
+				      sta->pairwise_cipher, 0) < 0 ||
 		    check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data,
 			      len) < 0)
 			return -1;
diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c
index 92762b8f04..6729371508 100644
--- a/wlantest/rx_mgmt.c
+++ b/wlantest/rx_mgmt.c
@@ -290,7 +290,7 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss,
 	    wpa_pmk_r1_to_ptk(pmk_r1, PMK_LEN, parse.fte_snonce,
 			      parse.fte_anonce, sta->addr, bss->bssid,
 			      pmk_r1_name, &ptk, ptk_name, sta->key_mgmt,
-			      sta->pairwise_cipher) < 0)
+			      sta->pairwise_cipher, 0) < 0)
 		return;
 
 	add_note(wt, MSG_DEBUG, "Derived new PTK");
@@ -1173,7 +1173,7 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt,
 	    wpa_pmk_r1_to_ptk(pmk_r1, PMK_LEN, parse.fte_snonce,
 			      parse.fte_anonce, new_sta->addr, bss->bssid,
 			      pmk_r1_name, &ptk, ptk_name, new_sta->key_mgmt,
-			      new_sta->pairwise_cipher) < 0)
+			      new_sta->pairwise_cipher, 0) < 0)
 		return;
 
 	add_note(wt, MSG_DEBUG, "Derived new PTK");
-- 
2.17.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.