[PATCH 34/92] NAN: Add function for decrypting the Key Data field

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Apr 22 05:23:25 PDT 2026


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

The Key Data field in the NAN Shared Key Descriptor attribute sent
in a followup SDF after NAN pairing is encrypted with the KEK. Add
a function for decrypting this field.

Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
 src/nan/nan_crypto.c | 69 ++++++++++++++++++++++++++++++++++++++++++++
 src/nan/nan_i.h      |  4 +++
 2 files changed, 73 insertions(+)

diff --git a/src/nan/nan_crypto.c b/src/nan/nan_crypto.c
index 256ff23840..31702f5e9e 100644
--- a/src/nan/nan_crypto.c
+++ b/src/nan/nan_crypto.c
@@ -603,3 +603,72 @@ fail:
 	os_free(padded_key_data);
 	return encrypted_key_data;
 }
+
+
+/*
+ * nan_crypto_decrypt_key_data - Decrypt NAN key data using AES-UNWRAP
+ *
+ * @kek: Key Encryption Key
+ * @kek_len: KEK length in bytes
+ * @encrypted_data: Encrypted key data to decrypt
+ * @encrypted_len: Length of encrypted data in bytes
+ * Returns: wpabuf containing decrypted data or %NULL on failure
+ *
+ * This function decrypts NAN key data that was encrypted using AES-WRAP.
+ * The encrypted data must be at least 16 bytes and a multiple of 8 bytes
+ * (AES-WRAP requirement). The caller is responsible for freeing the returned
+ * wpabuf using wpabuf_free().
+ */
+struct wpabuf *nan_crypto_decrypt_key_data(const u8 *kek, size_t kek_len,
+					   const u8 *encrypted_data,
+					   size_t encrypted_len)
+{
+	struct wpabuf *decrypted;
+	size_t plain_len;
+	u8 *buf;
+
+	if (!encrypted_data || !encrypted_len) {
+		wpa_printf(MSG_ERROR, "NAN: Invalid encrypted key data");
+		return NULL;
+	}
+
+	wpa_hexdump_key(MSG_DEBUG, "NAN: Encrypted key data",
+			encrypted_data, encrypted_len);
+
+	if (!kek || !kek_len) {
+		wpa_printf(MSG_ERROR,
+			   "NAN: No KEK available for key data decryption");
+		return NULL;
+	}
+
+	wpa_hexdump_key(MSG_DEBUG, "NAN: KEK for decryption", kek, kek_len);
+
+	/* AES-WRAP adds 8 bytes overhead */
+	if (encrypted_len < 16 || encrypted_len % 8 != 0) {
+		wpa_printf(MSG_ERROR,
+			   "NAN: Invalid encrypted key data length %zu",
+			   encrypted_len);
+		return NULL;
+	}
+
+	plain_len = encrypted_len - 8;
+	decrypted = wpabuf_alloc(plain_len);
+	if (!decrypted) {
+		wpa_printf(MSG_ERROR,
+			   "NAN: Failed to allocate decryption buffer");
+		return NULL;
+	}
+
+	buf = wpabuf_put(decrypted, plain_len);
+	if (aes_unwrap(kek, kek_len, plain_len / 8, encrypted_data, buf)) {
+		wpa_printf(MSG_ERROR,
+			   "NAN: AES unwrap failed - could not decrypt key data");
+		wpabuf_free(decrypted);
+		return NULL;
+	}
+
+	wpa_hexdump_key(MSG_DEBUG, "NAN: Decrypted key data",
+			wpabuf_head(decrypted), wpabuf_len(decrypted));
+
+	return decrypted;
+}
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index edfe28358a..6762e3e83c 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -729,6 +729,10 @@ int nan_crypto_derive_kek(const u8 *kdk, size_t kdk_len,
 			  struct wpa_ptk *ptk);
 struct wpabuf *nan_crypto_encrypt_key_data(const struct wpabuf *key_data,
 					   const u8 *kek, size_t kek_len);
+struct wpabuf *nan_crypto_decrypt_key_data(const u8 *kek, size_t kek_len,
+					   const u8 *encrypted_data,
+					   size_t encrypted_len);
+
 
 void nan_sec_reset(struct nan_data *nan, struct nan_ndp_sec *ndp_sec);
 int nan_sec_rx(struct nan_data *nan, struct nan_peer *peer,
-- 
2.53.0




More information about the Hostap mailing list