[PATCH 89/92] NAN: Support NDP establishment with PASN cipher suites

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Apr 22 05:24:20 PDT 2026


If pairing is used, PASN cipher suites (7, 8) should be used for NDP
establishment as well.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 src/common/nan_defs.h           |  8 ++++++++
 src/nan/nan_crypto.c            | 22 ++++++++++++++--------
 src/nan/nan_sec.c               | 33 +++++++++++++++------------------
 wpa_supplicant/nan_supplicant.c |  7 ++++++-
 4 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/src/common/nan_defs.h b/src/common/nan_defs.h
index b851d6219c..e9b6f21be6 100644
--- a/src/common/nan_defs.h
+++ b/src/common/nan_defs.h
@@ -496,6 +496,14 @@ enum nan_cipher_suite_id {
 	NAN_CS_MAX
 };
 
+/* Helper macros to check CSID properties */
+#define NAN_CS_IS_128(csid) \
+	((csid) == NAN_CS_SK_CCM_128 || (csid) == NAN_CS_PK_PASN_128)
+#define NAN_CS_IS_256(csid) \
+	((csid) == NAN_CS_SK_GCM_256 || (csid) == NAN_CS_PK_PASN_256)
+#define NAN_CS_IS_VALID_NDP(csid) \
+	(NAN_CS_IS_128(csid) || NAN_CS_IS_256(csid))
+
 struct nan_cipher_suite {
 	u8 csid; /* Cipher Suite ID */
 	u8 instance_id; /* Publish ID */
diff --git a/src/nan/nan_crypto.c b/src/nan/nan_crypto.c
index 7f4f50971c..b2632ea920 100644
--- a/src/nan/nan_crypto.c
+++ b/src/nan/nan_crypto.c
@@ -30,8 +30,10 @@ static size_t nan_crypto_cipher_kck_len(enum nan_cipher_suite_id cipher)
 {
 	switch (cipher) {
 	case NAN_CS_SK_CCM_128:
+	case NAN_CS_PK_PASN_128:
 		return 16;
 	case NAN_CS_SK_GCM_256:
+	case NAN_CS_PK_PASN_256:
 		return 24;
 	default:
 		return 0;
@@ -58,8 +60,10 @@ static size_t nan_cipher_key_len(enum nan_cipher_suite_id cipher)
 {
 	switch (cipher) {
 	case NAN_CS_SK_CCM_128:
+	case NAN_CS_PK_PASN_128:
 		return 16;
 	case NAN_CS_SK_GCM_256:
+	case NAN_CS_PK_PASN_256:
 		return 32;
 	default:
 		return 0;
@@ -112,7 +116,7 @@ int nan_crypto_pmk_to_ptk(const u8 *pmk, const u8 *iaddr, const u8 *raddr,
 	size_t ptk_len;
 	int ret;
 
-	if (cipher != NAN_CS_SK_CCM_128 && cipher != NAN_CS_SK_GCM_256)
+	if (!NAN_CS_IS_VALID_NDP(cipher))
 		return -1;
 
 	if (!ptk)
@@ -129,7 +133,7 @@ int nan_crypto_pmk_to_ptk(const u8 *pmk, const u8 *iaddr, const u8 *raddr,
 	ptk->tk_len = nan_cipher_key_len(cipher);
 	ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
 
-	if (cipher == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(cipher))
 		ret = sha256_prf(pmk, PMK_LEN, NAN_PTK_LABEL, data,
 				 sizeof(data), tmp, ptk_len);
 	else
@@ -183,7 +187,7 @@ int nan_crypto_calc_pmkid(const u8 *pmk, const u8 *iaddr, const u8 *raddr,
 	os_memset(data, 0, sizeof(data));
 	os_memset(digest, 0, sizeof(digest));
 
-	if (cipher != NAN_CS_SK_CCM_128 && cipher != NAN_CS_SK_GCM_256)
+	if (!NAN_CS_IS_VALID_NDP(cipher))
 		return -1;
 
 	if (!serv_id || is_zero_ether_addr(serv_id))
@@ -198,7 +202,7 @@ int nan_crypto_calc_pmkid(const u8 *pmk, const u8 *iaddr, const u8 *raddr,
 
 	wpa_hexdump_key(MSG_DEBUG, "NAN: PMKID data", data, sizeof(data));
 
-	if (cipher == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(cipher))
 		ret = hmac_sha256(pmk, PMK_LEN, data, sizeof(data), digest);
 	else
 		ret = hmac_sha384(pmk, PMK_LEN, data, sizeof(data), digest);
@@ -228,10 +232,10 @@ int nan_crypto_calc_auth_token(enum nan_cipher_suite_id cipher,
 	u8 hash[MAX_MAC_LEN];
 	int ret;
 
-	if (cipher != NAN_CS_SK_CCM_128 && cipher != NAN_CS_SK_GCM_256)
+	if (!NAN_CS_IS_VALID_NDP(cipher))
 		return -1;
 
-	if (cipher == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(cipher))
 		ret = nan_crypto_sha256(buf, len, hash);
 	else
 		ret = nan_crypto_sha384(buf, len, hash);
@@ -268,13 +272,13 @@ int nan_crypto_key_mic(const u8 *buf, size_t len, const u8 *kck,
 
 	os_memset(digest, 0, sizeof(digest));
 
-	if (cipher != NAN_CS_SK_CCM_128 && cipher != NAN_CS_SK_GCM_256)
+	if (!NAN_CS_IS_VALID_NDP(cipher))
 		return -1;
 
 	wpa_hexdump_key(MSG_DEBUG, "NAN: MIC data", buf, len);
 	wpa_hexdump_key(MSG_DEBUG, "NAN: KCK", kck, kck_len);
 
-	if (cipher == NAN_CS_SK_CCM_128) {
+	if (NAN_CS_IS_128(cipher)) {
 		mic_len = NAN_KEY_MIC_LEN;
 		ret = hmac_sha256(kck, kck_len, buf, len, digest);
 	} else {
@@ -305,8 +309,10 @@ int nan_crypto_derive_nd_pmk(const char *pwd, const u8 *service_id,
 
 	switch (csid) {
 	case NAN_CS_SK_CCM_128:
+	case NAN_CS_PK_PASN_128:
 		return pbkdf2_sha256(pwd, salt, sizeof(salt), 4096, nd_pmk, 32);
 	case NAN_CS_SK_GCM_256:
+	case NAN_CS_PK_PASN_256:
 		return pbkdf2_sha384(pwd, salt, sizeof(salt), 4096, nd_pmk, 32);
 	default:
 		return -1;
diff --git a/src/nan/nan_sec.c b/src/nan/nan_sec.c
index 995d358b77..d3d8b90d0e 100644
--- a/src/nan/nan_sec.c
+++ b/src/nan/nan_sec.c
@@ -120,8 +120,7 @@ static int nan_sec_parse_csia(const u8 *csia, size_t csia_len, u8 *instance_id,
 				return -1;
 			}
 
-			if (cs->csid != NAN_CS_SK_CCM_128 &&
-			    cs->csid != NAN_CS_SK_GCM_256) {
+			if (!NAN_CS_IS_VALID_NDP(cs->csid)) {
 				wpa_printf(MSG_DEBUG,
 					   "NAN: SEC: Unsupported cipher suite=%u",
 					   cs->csid);
@@ -206,9 +205,9 @@ static int nan_sec_key_mic_ver(struct nan_data *nan, const u8 *buf, size_t len,
 
 	os_memset(mic, 0, sizeof(mic));
 
-	if (csid == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(csid))
 		mic_len = NAN_KEY_MIC_LEN;
-	else if (csid == NAN_CS_SK_GCM_256)
+	else if (NAN_CS_IS_256(csid))
 		mic_len = NAN_KEY_MIC_24_LEN;
 	else
 		return -1;
@@ -270,7 +269,7 @@ static int nan_sec_rx_m2(struct nan_data *nan, struct nan_peer *peer,
 	 * with the MIC differently.
 	 */
 	pos = (const u8 *) (key + 1);
-	if (ndp_sec->i_csid == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(ndp_sec->i_csid))
 		pos += NAN_KEY_MIC_LEN;
 	else
 		pos += NAN_KEY_MIC_24_LEN;
@@ -338,7 +337,7 @@ static int nan_sec_rx_m3(struct nan_data *nan, struct nan_peer *peer,
 	 * with the mic differently
 	 */
 	pos = (u8 *) (key + 1);
-	if (ndp_sec->i_csid == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(ndp_sec->i_csid))
 		mic_len = NAN_KEY_MIC_LEN;
 	else
 		mic_len = NAN_KEY_MIC_24_LEN;
@@ -396,7 +395,7 @@ static int nan_sec_rx_m4(struct nan_data *nan, struct nan_peer *peer,
 	 * Due to the different MIC size, need to handle the fields starting
 	 * with the mic differently
 	 */
-	if (ndp_sec->i_csid == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(ndp_sec->i_csid))
 		pos += NAN_KEY_MIC_LEN;
 	else
 		pos += NAN_KEY_MIC_24_LEN;
@@ -490,7 +489,7 @@ int nan_sec_rx(struct nan_data *nan, struct nan_peer *peer,
 
 	total_len = sizeof(*key) + 2;
 
-	if (cipher == NAN_CS_SK_CCM_128) {
+	if (NAN_CS_IS_128(cipher)) {
 		if (shared_key_desc_len <
 		    sizeof(struct nan_shared_key) + sizeof(*key) +
 		    NAN_KEY_MIC_LEN + 2) {
@@ -655,9 +654,9 @@ static int nan_sec_add_m1_attrs(struct nan_data *nan, struct nan_peer *peer,
 	size_t key_len = sizeof(struct wpa_eapol_key) + 2;
 	int ret;
 
-	if (ndp_sec->i_csid == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(ndp_sec->i_csid))
 		key_len += NAN_KEY_MIC_LEN;
-	else if (ndp_sec->i_csid == NAN_CS_SK_GCM_256)
+	else if (NAN_CS_IS_256(ndp_sec->i_csid))
 		key_len += NAN_KEY_MIC_24_LEN;
 	else
 		return -1;
@@ -738,9 +737,9 @@ static int nan_sec_add_m2_attrs(struct nan_data *nan, struct nan_peer *peer,
 	size_t key_len;
 
 	key_len = sizeof(struct wpa_eapol_key) + 2;
-	if (ndp_sec->i_csid == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(ndp_sec->i_csid))
 		key_len += NAN_KEY_MIC_LEN;
-	else if (ndp_sec->i_csid == NAN_CS_SK_GCM_256)
+	else if (NAN_CS_IS_256(ndp_sec->i_csid))
 		key_len += NAN_KEY_MIC_24_LEN;
 	else
 		return -1;
@@ -811,9 +810,9 @@ static int nan_sec_add_key_attrs(struct nan_data *nan, struct nan_peer *peer,
 	u16 info;
 	size_t key_len = sizeof(struct wpa_eapol_key) + 2;
 
-	if (ndp_sec->i_csid == NAN_CS_SK_CCM_128)
+	if (NAN_CS_IS_128(ndp_sec->i_csid))
 		key_len += NAN_KEY_MIC_LEN;
-	else if (ndp_sec->i_csid == NAN_CS_SK_GCM_256)
+	else if (NAN_CS_IS_256(ndp_sec->i_csid))
 		key_len += NAN_KEY_MIC_24_LEN;
 	else
 		return -1;
@@ -903,8 +902,7 @@ int nan_sec_add_attrs(struct nan_data *nan, struct nan_peer *peer,
 	nan_sec_dump(nan, peer);
 
 	/* No security configuration */
-	if (peer->ndp_setup.sec.i_csid != NAN_CS_SK_CCM_128 &&
-	    peer->ndp_setup.sec.i_csid != NAN_CS_SK_GCM_256)
+	if (!NAN_CS_IS_VALID_NDP(peer->ndp_setup.sec.i_csid))
 		return 0;
 
 	switch (subtype) {
@@ -1154,8 +1152,7 @@ bool nan_sec_ndp_store_keys(struct nan_data *nan, struct nan_peer *peer,
 	    peer->ndp_setup.state != NAN_NDP_STATE_DONE)
 		return false;
 
-	if (ndp_sec->i_csid != NAN_CS_SK_CCM_128 &&
-	    ndp_sec->i_csid != NAN_CS_SK_GCM_256)
+	if (!NAN_CS_IS_VALID_NDP(ndp_sec->i_csid))
 		return false;
 
 	dl_list_for_each_safe(cur, next, &peer->info.sec,
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index ab9209e0f3..7f86567e1f 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -366,9 +366,11 @@ static int wpas_nan_set_ndi_keys(struct wpa_supplicant *wpa_s,
 	os_memset(rsc, 0, sizeof(rsc));
 	switch (csid) {
 	case NAN_CS_SK_CCM_128:
+	case NAN_CS_PK_PASN_128:
 		alg = WPA_ALG_CCMP;
 		break;
 	case NAN_CS_SK_GCM_256:
+	case NAN_CS_PK_PASN_256:
 		alg = WPA_ALG_GCMP_256;
 		break;
 	default:
@@ -1171,10 +1173,13 @@ int wpas_nan_init(struct wpa_supplicant *wpa_s)
 		!!(wpa_s->nan_capa.drv_flags &
 		   WPA_DRIVER_FLAGS_NAN_SUPPORT_USERSPACE_DE);
 
-	/* Currently support shared key suites only */
 	wpa_s->nan_supported_csids = BIT(NAN_CS_SK_CCM_128) |
 		BIT(NAN_CS_SK_GCM_256);
 
+#ifdef CONFIG_PASN
+	wpa_s->nan_supported_csids |= BIT(NAN_CS_PK_PASN_128) |
+				      BIT(NAN_CS_PK_PASN_256);
+#endif /* CONFIG_PASN */
 	return 0;
 }
 
-- 
2.53.0




More information about the Hostap mailing list