[RFC v2 55/99] NAN: Add NAN module testing for secure state machine
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Tue Dec 23 03:51:59 PST 2025
From: Ilan Peer <ilan.peer at intel.com>
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
src/nan/nan_module_test_cases.c | 153 ++++++++++++++++++++++++++++++++
src/nan/nan_module_tests.c | 52 +++++++++++
src/nan/nan_module_tests.h | 16 ++++
3 files changed, 221 insertions(+)
diff --git a/src/nan/nan_module_test_cases.c b/src/nan/nan_module_test_cases.c
index 43e08d34b4..8a38f2f747 100644
--- a/src/nan/nan_module_test_cases.c
+++ b/src/nan/nan_module_test_cases.c
@@ -375,6 +375,156 @@ static struct nan_test_case three_way_ndp_two_way_ndl_reject = {
};
+static struct nan_test_case four_way_ndp_two_way_ndl_chan_149_ccm_128 = {
+ .name = "Four way NDP and two way NDL channel 149 with CCMP 128",
+ .pub_conf = {
+ .schedule_cb = nan_test_schedule_cb_all_ndc,
+ .get_chans_cb = nan_test_get_chans_default,
+ .n_ndps = 1,
+ .ndp_confs = {
+ {
+ .accept_request = 1,
+ .expected_result =
+ NAN_TEST_NDP_NOTIFY_CONNECTED,
+ .csid = NAN_CS_SK_CCM_128,
+ .expected_csid = NAN_CS_SK_CCM_128,
+ },
+ },
+ .pot_avail = {
+ 0x12, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00,
+ 0xba, 0x02, 0x20, 0x02, 0x04
+ },
+ .pot_avail_len = 13,
+ .pmk = {
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ },
+ },
+ .sub_conf = {
+ .schedule_cb = nan_test_schedule_cb_all_no_ndc,
+ .get_chans_cb = nan_test_get_chans_default,
+ .n_ndps = 1,
+ .ndp_confs = {
+ {
+ .accept_request = 1,
+ .expected_result =
+ NAN_TEST_NDP_NOTIFY_CONNECTED,
+ .csid = NAN_CS_SK_CCM_128,
+ .expected_csid = NAN_CS_SK_CCM_128,
+ .term_once_connected = 1,
+ },
+ },
+ .pmk = {
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ },
+ }
+};
+
+static struct nan_test_case four_way_ndp_two_way_ndl_chan_149_gcm_256 = {
+ .name = "Four way NDP and three way NDL with GCMP 256",
+ .pub_conf = {
+ .schedule_cb = nan_test_schedule_cb_all_ndc,
+ .get_chans_cb = nan_test_get_chans_default,
+ .n_ndps = 1,
+ .ndp_confs = {
+ {
+ .accept_request = 1,
+ .expected_result =
+ NAN_TEST_NDP_NOTIFY_CONNECTED,
+ .csid = NAN_CS_SK_GCM_256,
+ .expected_csid = NAN_CS_SK_GCM_256,
+ },
+ },
+ .pot_avail = {
+ 0x12, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00,
+ 0xba, 0x02, 0x20, 0x02, 0x04
+ },
+ .pot_avail_len = 13,
+ .pmk = {
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ },
+ },
+ .sub_conf = {
+ .schedule_cb = nan_test_schedule_cb_2ghz_no_ndc,
+ .schedule_conf_cb = nan_test_schedule_cb_all_ndc,
+ .get_chans_cb = nan_test_get_chans_default_reverse,
+ .n_ndps = 1,
+ .ndp_confs = {
+ {
+ .accept_request = 1,
+ .expected_result =
+ NAN_TEST_NDP_NOTIFY_CONNECTED,
+ .csid = NAN_CS_SK_GCM_256,
+ .expected_csid = NAN_CS_SK_GCM_256,
+ .term_once_connected = 1,
+ },
+ },
+ .pmk = {
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ },
+ }
+};
+
+
+static struct nan_test_case pmk_mismatch = {
+ .name = "PMK mismatch test case",
+ .pub_conf = {
+ .schedule_cb = nan_test_schedule_cb_all_ndc,
+ .get_chans_cb = nan_test_get_chans_default,
+ .n_ndps = 1,
+ .ndp_confs = {
+ {
+ .accept_request = 1,
+ .expected_result =
+ NAN_TEST_NDP_NOTIFY_DISCONNECTED,
+ .csid = NAN_CS_SK_GCM_256,
+ },
+ },
+ .pot_avail = {
+ 0x12, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00,
+ 0xba, 0x02, 0x20, 0x02, 0x04
+ },
+ .pot_avail_len = 13,
+ .pmk = {
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ },
+ },
+ .sub_conf = {
+ .schedule_cb = nan_test_schedule_cb_all_no_ndc,
+ .get_chans_cb = nan_test_get_chans_default,
+ .n_ndps = 1,
+ .ndp_confs = {
+ {
+ .accept_request = 1,
+ .expected_result =
+ NAN_TEST_NDP_NOTIFY_DISCONNECTED,
+ .csid = NAN_CS_SK_GCM_256,
+ },
+ },
+ .pmk = {
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x0,
+ },
+ }
+};
+
+
static struct nan_test_case *g_nan_test_cases[] = {
&three_way_ndp_two_way_ndl_chan_149,
&three_way_ndp_two_way_ndl_diff_period,
@@ -382,6 +532,9 @@ static struct nan_test_case *g_nan_test_cases[] = {
&three_way_ndp_two_way_ndl_chan_mis,
&three_way_ndp_two_way_ndl_reject,
&three_way_ndp_three_way_ndl,
+ &four_way_ndp_two_way_ndl_chan_149_ccm_128,
+ &four_way_ndp_two_way_ndl_chan_149_gcm_256,
+ &pmk_mismatch,
NULL,
};
diff --git a/src/nan/nan_module_tests.c b/src/nan/nan_module_tests.c
index dedec5b612..3ccce9243d 100644
--- a/src/nan/nan_module_tests.c
+++ b/src/nan/nan_module_tests.c
@@ -78,6 +78,8 @@ struct nan_test_ndp_notify {
size_t ssi_len;
};
+#define NAN_TEST_MAX_TKS 2
+
/*
* nan_test_global - Global context for the NAN testing
*
@@ -384,6 +386,10 @@ static int nan_ndp_notify_action(struct nan_device *dev, void *ctx)
dev->conf->schedule_cb(¶ms->sched);
params->sched.elems = dev->global->elems;
params->sched_valid = 1;
+
+ params->sec.csid =
+ dev->conf->ndp_confs[dev->n_ndps].csid;
+ os_memcpy(params->sec.pmk, dev->conf->pmk, PMK_LEN);
} else {
wpa_printf(MSG_INFO, "%s: Rejecting request",
dev->name);
@@ -437,6 +443,9 @@ static int nan_ndp_notify_action(struct nan_device *dev, void *ctx)
params->sched.elems = dev->global->elems;
params->sched_valid = 1;
+ params->sec.csid =
+ dev->conf->ndp_confs[dev->n_ndps].csid;
+ os_memcpy(params->sec.pmk, dev->conf->pmk, PMK_LEN);
} else {
wpa_printf(MSG_INFO, "%s: Rejecting response",
dev->name);
@@ -606,6 +615,19 @@ static void nan_test_ndp_connected_cb(void *ctx,
nan_peer_get_pot_avail(dev->nan, params->ndp_id.peer_nmi,
&pot);
+ if (nan_peer_get_tk(dev->nan, params->ndp_id.peer_nmi,
+ params->peer_ndi, params->local_ndi,
+ dev->tk, &dev->tk_len, &dev->csid) == 0) {
+ wpa_hexdump(MSG_DEBUG, "NAN Test: TK", dev->tk, dev->tk_len);
+
+ if (dev->csid != dev->conf->ndp_confs[dev->n_ndps].expected_csid) {
+ wpa_printf(MSG_ERROR,
+ "%s: Unexpected CSID: got %u expected %u",
+ dev->name, dev->csid,
+ dev->conf->ndp_confs[dev->n_ndps].expected_csid);
+ }
+ }
+
nan_test_ndp_action(dev, NAN_TEST_NDP_NOTIFY_CONNECTED,
¶ms->ndp_id, 0,
params->ssi, params->ssi_len,
@@ -849,6 +871,7 @@ static int nan_test_dev_init(struct nan_device *dev)
struct nan_config nan;
os_memset(&nan, 0, sizeof(nan));
+ os_memcpy(nan.nmi_addr, dev->nmi, ETH_ALEN);
nan.cb_ctx = dev;
nan.start = nan_test_start_cb;
@@ -1005,6 +1028,8 @@ static int nan_test_ndp_request(struct nan_device *sub)
params->ndp_id.id = ++sub->counter;
params->qos.min_slots = NAN_TEST_MIN_SLOTS;
params->qos.max_latency = NAN_TEST_MAX_LATENCY;
+ params->sec.csid = sub->conf->ndp_confs[sub->n_ndps].csid;
+ os_memcpy(params->sec.pmk, sub->conf->pmk, PMK_LEN);
/* Use the device specific schedule callback */
sub->conf->schedule_cb(¶ms->sched);
@@ -1079,16 +1104,43 @@ static int nan_test_verify_expected_result(struct nan_device *dev)
static int nan_test_iteration_done(struct nan_test_global *global)
{
struct nan_device *dev;
+ u8 tk[NAN_TK_MAX_LEN];
+ size_t tk_len = 0;
+ enum nan_cipher_suite_id csid;
int ret;
+ os_memset(tk, 0, sizeof(tk));
+
dl_list_for_each(dev, &global->devs, struct nan_device, list) {
ret = nan_test_verify_expected_result(dev);
if (ret)
return ret;
+ if (tk_len == 0 && dev->tk_len > 0) {
+ os_memcpy(tk, dev->tk, dev->tk_len);
+ tk_len = dev->tk_len;
+ csid = dev->csid;
+ } else if (dev->tk_len > 0) {
+ if (tk_len != dev->tk_len ||
+ csid != dev->csid ||
+ os_memcmp(tk, dev->tk, tk_len) != 0) {
+ wpa_printf(MSG_ERROR,
+ "%s: TK mismatch with other device",
+ dev->name);
+ return -1;
+ }
+
+ wpa_printf(MSG_INFO, "%s: TK matches with other device",
+ dev->name);
+ }
+
dev->connected_notify_received = false;
dev->disconnected_notify_received = false;
+
+ os_memset(dev->tk, 0, sizeof(dev->tk));
+ dev->tk_len = 0;
+
dev->n_ndps++;
}
diff --git a/src/nan/nan_module_tests.h b/src/nan/nan_module_tests.h
index f50eb76953..18eab97f9e 100644
--- a/src/nan/nan_module_tests.h
+++ b/src/nan/nan_module_tests.h
@@ -57,6 +57,11 @@ enum nan_test_ndp_notify_type {
* @term_once_connected: Terminate once connected.
* @expected_result: Expected NDP establishment result
* @reason: For publisher device, indicates the reject reason
+ * @pot_avail: Device potential availability
+ * @pot_avail_len: Length of the device potential availability
+ * @csid: Cipher suite ID
+ * @expected_csid: Expected Cipher suite ID in case of a successful connection
+ * @pmk: Pairwise Master Key
*/
struct nan_test_dev_conf {
int (*schedule_cb)(struct nan_schedule *sched);
@@ -72,7 +77,11 @@ struct nan_test_dev_conf {
bool term_once_connected;
enum nan_test_ndp_notify_type expected_result;
u8 reason;
+ enum nan_cipher_suite_id csid;
+ enum nan_cipher_suite_id expected_csid;
} ndp_confs[NAN_MAX_NUM_NDPS];
+
+ u8 pmk[PMK_LEN];
};
/*
@@ -92,6 +101,9 @@ struct nan_test_dev_conf {
* was received
* @disconnected_notify_received: Indicates whether a disconnected notification
* was received
+ * @tk: NAN TK
+ * @tk_len: Length of the NAN TK
+ * @csid: Cipher suite ID
*/
struct nan_device {
struct dl_list list;
@@ -111,6 +123,10 @@ struct nan_device {
bool connected_notify_received;
bool disconnected_notify_received;
+
+ u8 tk[NAN_TK_MAX_LEN];
+ size_t tk_len;
+ enum nan_cipher_suite_id csid;
};
/*
--
2.49.0
More information about the Hostap
mailing list