[PATCH 37/97] NAN: Add the GTK KDE to key data field when GTK is required

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Apr 28 13:05:38 PDT 2026


From: Avraham Stern <avraham.stern at intel.com>

When the NDP requires a GTK, add the GTK KDE to the key data field
and set the key RSC field to the GTK RSC.

Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
 src/common/wpa_common.h |  7 ++++++
 src/nan/nan_sec.c       | 54 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 71df9db86e..98a1c7213a 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -359,6 +359,13 @@ struct rsn_error_kde {
 	be16 error_type;
 } STRUCT_PACKED;
 
+#define WPA_GTK_KDE_PREFIX_LEN 2
+struct wpa_gtk_kde {
+	u8 keyid;
+	u8 reserved;
+	u8 gtk[WPA_GTK_MAX_LEN];
+} STRUCT_PACKED;
+
 #define WPA_IGTK_KDE_PREFIX_LEN (2 + RSN_PN_LEN)
 struct wpa_igtk_kde {
 	u8 keyid[2];
diff --git a/src/nan/nan_sec.c b/src/nan/nan_sec.c
index 964b6a01a3..68310c94f1 100644
--- a/src/nan/nan_sec.c
+++ b/src/nan/nan_sec.c
@@ -966,7 +966,8 @@ static int nan_sec_igtk_kde(struct nan_data *nan, struct wpabuf *buf)
 
 #define NAN_KDES_MAX_LEN                                           \
 	(KDE_HDR_LEN + sizeof(struct wpa_igtk_kde) + KDE_HDR_LEN + \
-	 sizeof(struct wpa_bigtk_kde))
+	 sizeof(struct wpa_bigtk_kde) + KDE_HDR_LEN +              \
+	 sizeof(struct wpa_gtk_kde))
 
 static int nan_sec_bigtk_kde(struct nan_data *nan, struct nan_ndp_sec *ndp_sec,
 			     struct wpabuf *buf)
@@ -1002,6 +1003,30 @@ static int nan_sec_bigtk_kde(struct nan_data *nan, struct nan_ndp_sec *ndp_sec,
 }
 
 
+static int nan_sec_gtk_kde(struct nan_data *nan, struct wpabuf *buf,
+			   struct nan_ndp_sec *ndp_sec)
+{
+	if (!ndp_sec->local_gtk.gtk.gtk_len)
+		return 0;
+
+	if (ndp_sec->local_gtk.id > 3) {
+		wpa_printf(MSG_DEBUG, "NAN: Invalid GTK Key ID %u",
+			   ndp_sec->local_gtk.id);
+		return -1;
+	}
+
+	nan_add_kde_hdr(buf, RSN_KEY_DATA_GROUPKEY,
+			WPA_GTK_KDE_PREFIX_LEN +
+				ndp_sec->local_gtk.gtk.gtk_len);
+	wpabuf_put_u8(buf, ndp_sec->local_gtk.id);
+	wpabuf_put_u8(buf, 0);
+	wpabuf_put_data(buf, ndp_sec->local_gtk.gtk.gtk,
+			ndp_sec->local_gtk.gtk.gtk_len);
+
+	return 0;
+}
+
+
 static bool nan_sec_igtk_supported(struct nan_ndp_sec *ndp_sec)
 {
 	return ((ndp_sec->i_capab & NAN_CS_INFO_CAPA_GTK_SUPP_MASK) >>
@@ -1021,9 +1046,10 @@ static int nan_sec_add_kdes(struct nan_data *nan,
 	struct wpabuf *enc_kde;
 	int ret = -1;
 
-	if (!nan_sec_igtk_supported(ndp_sec)) {
+	if (!nan_sec_igtk_supported(ndp_sec) &&
+	    ndp_sec->local_gtk.gtk.gtk_len == 0) {
 		wpa_printf(MSG_DEBUG,
-			   "NAN: IGTK not supported for this NDP");
+			   "NAN: GTK/IGTK not supported for this NDP");
 		return 0;
 	}
 
@@ -1046,6 +1072,9 @@ static int nan_sec_add_kdes(struct nan_data *nan,
 	if (nan_sec_bigtk_kde(nan, ndp_sec, kde_buf) < 0)
 		goto fail;
 
+	if (nan_sec_gtk_kde(nan, kde_buf, ndp_sec) < 0)
+		goto fail;
+
 	enc_kde = nan_crypto_encrypt_key_data(kde_buf, ndp_sec->ptk.kek,
 					      ndp_sec->ptk.kek_len);
 	if (!enc_kde) {
@@ -1121,6 +1150,25 @@ static int nan_sec_add_key_attrs(struct nan_data *nan, struct nan_peer *peer,
 		return -1;
 	}
 
+	/* When GTK is present, the key RSC field is set to the GTK RSC */
+	if (ndp_sec->local_gtk.gtk.gtk_len) {
+		u8 *local_ndi;
+		struct nan_ndp *pndp = peer->ndp_setup.ndp;
+
+		if (pndp->initiator)
+			local_ndi = pndp->init_ndi;
+		else
+			local_ndi = pndp->resp_ndi;
+
+		if (nan->cfg->get_seqnum(nan->cfg->cb_ctx,
+					 ndp_sec->local_gtk.id, key->key_rsc,
+					 local_ndi) < 0) {
+			wpa_printf(MSG_DEBUG,
+				   "NAN: SEC: Failed to get GTK seqnum");
+			return -1;
+		}
+	}
+
 	info = WPA_KEY_INFO_TYPE_AKM_DEFINED | WPA_KEY_INFO_KEY_TYPE |
 	       WPA_KEY_INFO_MIC | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SECURE;
 	if (is_ack)
-- 
2.53.0




More information about the Hostap mailing list