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

Message ID 20200224091437.15212-12-ilan.peer@intel.com
State Changes Requested
Headers show
Series
  • Preparations for Pre association Security Negotiation(PASN) Support
Related show

Commit Message

Peer, Ilan Feb. 24, 2020, 9:14 a.m. UTC
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 <ilan.peer@intel.com>
---
 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(-)

Comments

Jouni Malinen Feb. 29, 2020, 10:09 p.m. UTC | #1
On Mon, Feb 24, 2020 at 11:14:36AM +0200, Ilan Peer wrote:
> Extend the wpa_pmk_r1_to_ptk() to also derive High Level
> Transient Key (HLTK), which can later be used for secure
> LTF measurements.

There is still ongoing discussion on how HLTK derivation should be done
and this may change based on where similar PTK extension designs
in P802.11ax, P802.11ba, and REVmd go. As such, I'm not sure this (and
same for patch 12/12) is ready to go in based on the current
P802.11az/D2.0.

Patch
diff mbox series

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");