[PATCH 34/97] NAN: Implement spec-compliant security strength comparison
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Tue Apr 28 13:05:35 PDT 2026
Per Wi-Fi Aware Specification v4.0 section 7.4, implement proper security
strength ordering for NDP security upgrade scenarios. The spec defines
the following strength ordering (highest to lowest):
- NCS-PK-PASN-256 using a password (SAE)
- NCS-PK-PASN-128 using a password (SAE)
- NCS-SK-256 using a PSK/Passphrase
- NCS-SK-128 using a PSK/Passphrase
- NCS-PK-PASN-256 using opportunistic bootstrapping (PASN)
- NCS-PK-PASN-128 using opportunistic bootstrapping (PASN)
- No security
To distinguish between password and opportunistic pairing, store the
AKMP which was used for pairing.
Add nan_sec_get_strength() to compute numeric strength levels considering
both the cipher suite ID and the authentication method (SAE vs PASN).
Update nan_sec_ndp_store_keys() to use this strength comparison when
deciding whether to update security keys.
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
src/nan/nan_i.h | 5 +++
src/nan/nan_pairing.c | 1 +
src/nan/nan_sec.c | 72 ++++++++++++++++++++++++++++++++++++++-----
3 files changed, 70 insertions(+), 8 deletions(-)
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index 748120aa25..1d6956986b 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -302,6 +302,8 @@ struct nan_elem_container_entry {
* @pmk: PMK shared with the peer
* @pmkid: PMKID shared with the peer
* @ptk: PTK shared with the peer
+ * @pairing_akmp: AKMP used for the pairing (see See WPA_KEY_MGMT_*) or
+ * zero if PASN pairing was not used for NDP establishment.
*/
struct nan_peer_sec_info_entry {
struct dl_list list;
@@ -313,6 +315,7 @@ struct nan_peer_sec_info_entry {
u8 pmk[PMK_LEN];
u8 pmkid[PMKID_LEN];
struct nan_ptk ptk;
+ int pairing_akmp;
};
/**
@@ -503,6 +506,7 @@ enum nan_pairing_role {
* @flags: Bitmap of pairing flags. See NAN_PAIRING_FLAG_*
* @pending_auth1: Pending PASN Authentication frame 1 to be processed
* @pairing_csid: Cipher suite ID used for the pairing
+ * @pairing_akmp: AKMP used for the pairing. See WPA_KEY_MGMT_*.
*/
struct nan_pairing_peer_data {
struct nan_pairing_cfg pairing_cfg;
@@ -516,6 +520,7 @@ struct nan_pairing_peer_data {
u32 flags;
struct wpabuf *pending_auth1;
enum nan_cipher_suite_id pairing_csid;
+ int pairing_akmp;
};
/**
diff --git a/src/nan/nan_pairing.c b/src/nan/nan_pairing.c
index 938925eacf..00df9d5b96 100644
--- a/src/nan/nan_pairing.c
+++ b/src/nan/nan_pairing.c
@@ -602,6 +602,7 @@ static void nan_pairing_done(struct nan_data *nan_data, struct nan_peer *peer)
peer->pairing.pairing_csid = cipher == WPA_CIPHER_GCMP_256 ?
NAN_CS_PK_PASN_256 : NAN_CS_PK_PASN_128;
+ peer->pairing.pairing_akmp = pasn_get_akmp(pasn);
if (!nan_data->cfg->pairing_cfg.npk_caching ||
!peer->pairing.pairing_cfg.npk_caching ||
diff --git a/src/nan/nan_sec.c b/src/nan/nan_sec.c
index 768a8268b0..7c509b672c 100644
--- a/src/nan/nan_sec.c
+++ b/src/nan/nan_sec.c
@@ -1416,6 +1416,44 @@ int nan_sec_pre_tx(struct nan_data *nan, struct nan_peer *peer,
}
+/*
+ * nan_sec_get_strength - Get security strength level for a cipher suite
+ *
+ * Per Wi-Fi Aware Specification v4.0 section 7.4, security strength ordering
+ * (from highest to lowest):
+ * - CSID 8 (NCS-PK-PASN-256) using a password (SAE)
+ * - CSID 7 (NCS-PK-PASN-128) using a password (SAE)
+ * - CSID 2 (NCS-SK-256) using a PSK/Passphrase
+ * - CSID 1 (NCS-SK-128) using a PSK/Passphrase
+ * - CSID 8 (NCS-PK-PASN-256) using opportunistic bootstrapping (PASN)
+ * - CSID 7 (NCS-PK-PASN-128) using opportunistic bootstrapping (PASN)
+ * - No security
+ *
+ * @csid: Cipher suite ID
+ * @pairing_akmp: AKMP used for pairing (to distinguish SAE vs opportunistic)
+ *
+ * Returns: Security strength level (higher = stronger), 0 for no security
+ */
+static int nan_sec_get_strength(enum nan_cipher_suite_id csid, int pairing_akmp)
+{
+ bool is_opportunistic = pairing_akmp == WPA_KEY_MGMT_PASN;
+
+ switch (csid) {
+ case NAN_CS_PK_PASN_256:
+ return is_opportunistic ? 2 : 6;
+ case NAN_CS_PK_PASN_128:
+ return is_opportunistic ? 1 : 5;
+ case NAN_CS_SK_GCM_256:
+ return 4;
+ case NAN_CS_SK_CCM_128:
+ return 3;
+ case NAN_CS_NONE:
+ default:
+ return 0;
+ }
+}
+
+
/*
* nan_sec_ndp_store_keys - Store the NDP keys after successful NDP
* establishment
@@ -1433,6 +1471,8 @@ bool nan_sec_ndp_store_keys(struct nan_data *nan, struct nan_peer *peer,
struct nan_ndp *ndp = peer->ndp_setup.ndp;
struct nan_ndp_sec *ndp_sec = &peer->ndp_setup.sec;
struct nan_peer_sec_info_entry *cur, *next;
+ int new_strength, cur_strength;
+ int new_akmp = 0;
if (!ndp || !ndp_sec->valid || !ndp_sec->i_csid ||
peer->ndp_setup.state != NAN_NDP_STATE_DONE)
@@ -1441,6 +1481,12 @@ bool nan_sec_ndp_store_keys(struct nan_data *nan, struct nan_peer *peer,
if (!NAN_CS_IS_VALID_NDP(ndp_sec->i_csid))
return false;
+ /* Get AKMP for the new security association */
+ if (peer->pairing.flags & NAN_PAIRING_FLAG_PAIRED)
+ new_akmp = peer->pairing.pairing_akmp;
+
+ new_strength = nan_sec_get_strength(ndp_sec->i_csid, new_akmp);
+
dl_list_for_each_safe(cur, next, &peer->info.sec,
struct nan_peer_sec_info_entry, list) {
if (!ether_addr_equal(peer_ndi, cur->peer_ndi) ||
@@ -1448,16 +1494,24 @@ bool nan_sec_ndp_store_keys(struct nan_data *nan, struct nan_peer *peer,
continue;
/*
- * The security configuration should be updated if it is
- * stronger than the existing one or equal in strength. Since
- * GCM-256 is considered stronger than CCM-128, always update if
- * it is the current one. Otherwise, update only if the previous
- * one was CCMP-128.
+ * Per Wi-Fi Aware Specification v4.0 section 7.4:
+ * The security configuration should be updated if the new
+ * security strength is same or greater than the existing SA.
+ * Otherwise, the existing higher-strength SA continues to be
+ * used and any key material derived shall be discarded.
*/
- if (ndp_sec->i_csid == NAN_CS_SK_GCM_256 ||
- cur->csid == NAN_CS_SK_CCM_128)
+ cur_strength = nan_sec_get_strength(cur->csid, cur->pairing_akmp);
+
+ wpa_printf(MSG_DEBUG,
+ "NAN: SEC: Comparing strength: new=%d (csid=%u, akmp=0x%x) vs cur=%d (csid=%u, akmp=0x%x)",
+ new_strength, ndp_sec->i_csid, new_akmp,
+ cur_strength, cur->csid, cur->pairing_akmp);
+
+ if (new_strength >= cur_strength)
goto store;
+ wpa_printf(MSG_DEBUG,
+ "NAN: SEC: New security weaker than existing, discarding keys");
return false;
}
@@ -1476,10 +1530,12 @@ store:
wpa_printf(MSG_DEBUG, "NAN: SEC: Store security information");
cur->csid = ndp_sec->i_csid;
+ if (peer->pairing.flags & NAN_PAIRING_FLAG_PAIRED)
+ cur->pairing_akmp = peer->pairing.pairing_akmp;
+
os_memcpy(cur->pmkid, ndp_sec->i_pmkid, PMKID_LEN);
os_memcpy(cur->pmk, ndp_sec->pmk, PMK_LEN);
os_memcpy(&cur->ptk, &ndp_sec->ptk, sizeof(cur->ptk));
-
return true;
}
--
2.53.0
More information about the Hostap
mailing list