1 /*
2 * NAN NDP/NDL state machine testing
3 * Copyright (C) 2025 Intel Corporation
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10 #include "utils/common.h"
11 #include "common/nan_defs.h"
12 #include "drivers/driver.h"
13 #include "nan_i.h"
14 #include "nan_module_tests.h"
15 #include "crypto/sha256.h"
16 #include "crypto/sha384.h"
17 #include "crypto/crypto.h"
18
19 #define NAN_TEST_MAX_NAF_LEN 1024
20 #define NAN_TEST_MAX_PEERS 20
21 #define NAN_TEST_MAX_ACTIONS 30
22 #define NAN_TEST_MIN_SLOTS 12
23 #define NAN_TEST_MAX_LATENCY 3
24 #define NAN_TEST_PUBLISH_INST_ID 12
25
26 static const u8 g_pub_nmi[] = { 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA };
27 static const u8 g_pub_ndi[] = { 0x00, 0xAA, 0xAA, 0x00, 0x00, 0x00 };
28 static const u8 g_sub_nmi[] = { 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB };
29 static const u8 g_sub_ndi[] = { 0x00, 0xBB, 0xBB, 0xBB, 0x00, 0x00 };
30
31 /**
32 * struct nan_test_action - NAN test action context
33 * @list: Used for global actions list
34 * @dev: NAN device for which the action is intended
35 * @cb: Callback to be called for the action
36 * @ctx: Parameter for the callback function
37 *
38 * The test utility uses actions to handle asynchronous events between the
39 * devices and internally to the local device. When an event is triggered
40 * outside of the NAN module context, the event is wrapped by an action item and
41 * is processed asynchronously. Examples:
42 *
43 * NAF transmission: when a NAF is transmitted by a device, it is translated to
44 * 2 asynchronous actions: one action to indicate Tx status to the transmitting
45 * device and one to indicate an Rx frame to the peer device.
46 *
47 * NDP event: when an NDP event is fired by the NAN module, it is translated to
48 * an asynchronous action to the local device.
49 */
50 struct nan_test_action {
51 struct dl_list list;
52 struct nan_device *dev;
53 int (*cb)(struct nan_device *dev, void *ctx);
54 void *ctx;
55 };
56
57 /**
58 * nan_test_tx_status_action - NAN test Tx status action context
59 * @data: Copy of the original NAF
60 * @acked: True iff the NAF was acked
61 * @dst: Destination of the NAF
62 */
63 struct nan_test_tx_status_action {
64 const struct wpabuf *data;
65 bool acked;
66 u8 dst[ETH_ALEN];
67 };
68
69 /**
70 * nan_test_ndp_notify - NAN test NDP notification handling
71 * @type: Notification type
72 * @ndp_id: NDP identifier
73 * @ssi: Service specific information
74 * @ssi_len: Length of service specific information
75 */
76 struct nan_test_ndp_notify {
77 enum nan_test_ndp_notify_type type;
78 struct nan_ndp_id ndp_id;
79 const u8 *ssi;
80 size_t ssi_len;
81 };
82
83 /**
84 * nan_test_global - Global context for the NAN testing
85 * @devs: List of devices. See &struct nan_device.
86 * @actions: tracks the NAN actions
87 * @elems: Default HT/VHT/HE capabilities elements
88 */
89 struct nan_test_global {
90 struct dl_list devs;
91 struct dl_list actions;
92 struct wpabuf *elems;
93 };
94
95 #define DEV_NOT_INIT_ERR(_dev) \
96 do { \
97 if (!(_dev) || !(_dev)->nan) { \
98 wpa_printf(MSG_ERROR, \
99 "NAN: %s: device not initialized", \
100 __func__); \
101 return -1; \
102 } \
103 } while (0)
104
105 #define DEV_NOT_INIT_ERR_VOID(_dev) \
106 do { \
107 if (!(_dev) || !(_dev)->nan) { \
108 wpa_printf(MSG_ERROR, \
109 "NAN: %s: device not initialized", \
110 __func__); \
111 return; \
112 } \
113 } while (0)
114
115
116 /**
117 * nan_test_global_init - Initialize NAN test global data structures
118 * @global: NAN test global data structure
119 */
nan_test_global_init(struct nan_test_global * global)120 static void nan_test_global_init(struct nan_test_global *global)
121 {
122 u8 elems[] = {
123 /* HT capabilities */
124 0x2d, 0x1a, 0x7e, 0x10, 0x1b, 0xff, 0xff, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00,
128
129 /* VHT capabilities */
130 0xbf, 0x0c, 0xfa, 0x04, 0x80, 0x03, 0xaa, 0xaa,
131 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
132
133 /* HE capabilities */
134 0xff, 0x1e, 0x23, 0x01, 0x78, 0xc8, 0x1a, 0x40,
135 0x00, 0x1c, 0xbf, 0xce, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xfa, 0xff,
137 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff,
138 };
139
140 wpa_printf(MSG_INFO, "%s: Enter", __func__);
141 os_memset(global, 0, sizeof(struct nan_test_global));
142 dl_list_init(&global->devs);
143 dl_list_init(&global->actions);
144
145 global->elems = wpabuf_alloc_copy(elems, sizeof(elems));
146
147 wpa_printf(MSG_INFO, "%s: Done\n", __func__);
148 }
149
150
151 /**
152 * nan_test_dev_deinit - De-initialize NAN device
153 * @dev: NAN device
154 */
nan_test_dev_deinit(struct nan_device * dev)155 static void nan_test_dev_deinit(struct nan_device *dev)
156 {
157 DEV_NOT_INIT_ERR_VOID(dev);
158
159 os_free(dev->pot_avail);
160 nan_stop(dev->nan);
161 nan_deinit(dev->nan);
162 os_memset(dev, 0, sizeof(struct nan_device));
163 }
164
165
166 /**
167 * nan_test_global_deinit - De-initialize NAN test global data structures
168 * @global: NAN test global data structure
169 */
nan_test_global_deinit(struct nan_test_global * global)170 static void nan_test_global_deinit(struct nan_test_global *global)
171 {
172 struct nan_device *dev, *next;
173 struct nan_test_action *action, *action_next;
174
175 wpa_printf(MSG_INFO, "%s: Enter", __func__);
176
177 dl_list_for_each_safe(dev, next, &global->devs, struct nan_device,
178 list) {
179 dl_list_del(&dev->list);
180 nan_test_dev_deinit(dev);
181 os_free(dev);
182 }
183
184 dl_list_for_each_safe(action, action_next, &global->actions,
185 struct nan_test_action, list) {
186 dl_list_del(&dev->list);
187 os_free(action->ctx);
188 os_free(action);
189 }
190
191 wpabuf_free(global->elems);
192 }
193
194
195 /**
196 * nan_test_add_action - Add a NAN test action to the list of actions
197 * @global: NAN test global data structure
198 * @dev: NAN device for which the action is intended
199 * @cb: Callback to be called for the action
200 * @ctx: Parameter for the callback function
201 * Returns: A pointer to the newly added action, or NULL on failure
202 */
203 static struct nan_test_action *
nan_test_add_action(struct nan_test_global * global,struct nan_device * dev,int (* cb)(struct nan_device * dev,void * ctx),void * ctx)204 nan_test_add_action(struct nan_test_global *global,
205 struct nan_device *dev,
206 int (*cb)(struct nan_device *dev, void *ctx),
207 void *ctx)
208 {
209 struct nan_test_action *action;
210
211 action = os_malloc(sizeof(struct nan_test_action));
212 if (!action) {
213 wpa_printf(MSG_ERROR, "NAN Test: Failed to allocate action");
214 return NULL;
215 }
216
217 action->dev = dev;
218 action->cb = cb;
219 action->ctx = ctx;
220
221 dl_list_add_tail(&global->actions, &action->list);
222 return action;
223 }
224
225
226 /**
227 * nan_test_run_actions - Iterate over all NAN test actions and execute them
228 * @global: NAN test global data structure
229 * Returns: 0 in success, -1 on error
230 *
231 * Runs as longs as there are actions to run. Exists where there are no more
232 * action to perform or on error.
233 */
nan_test_run_actions(struct nan_test_global * global)234 static int nan_test_run_actions(struct nan_test_global *global)
235 {
236 u32 n_actions = 0;
237
238 wpa_printf(MSG_INFO, "%s: Running actions", __func__);
239
240 while (!dl_list_empty(&global->actions)) {
241 struct nan_test_action *action =
242 dl_list_first(&global->actions, struct nan_test_action,
243 list);
244 int ret;
245
246 dl_list_del(&action->list);
247
248 if (++n_actions > NAN_TEST_MAX_ACTIONS) {
249 wpa_printf(MSG_ERROR,
250 "NAN Test action: Too many actions executed");
251 return -1;
252 }
253
254 if (!action->cb || !action->dev) {
255 wpa_printf(MSG_ERROR,
256 "NAN Test action: Invalid action");
257 return -1;
258 }
259
260 wpa_printf(MSG_INFO, "%s: ===> NAN Test action <===",
261 action->dev->name);
262 ret = action->cb(action->dev, action->ctx);
263
264 /*
265 * The action context should be freed by the callback function
266 * that understands the content of the context and can properly
267 * handle it.
268 */
269 os_free(action);
270
271 if (ret) {
272 wpa_printf(MSG_ERROR, "NAN Test action: FAILED");
273 return ret;
274 }
275 }
276
277 wpa_printf(MSG_INFO, "%s: Running actions done", __func__);
278 return 0;
279 }
280
281
nan_test_start_cb(void * ctx,const struct nan_cluster_config * config)282 static int nan_test_start_cb(void *ctx, const struct nan_cluster_config *config)
283 {
284 struct nan_device *dev = ctx;
285
286 DEV_NOT_INIT_ERR(dev);
287
288 return 0;
289 }
290
291
292 /*
293 * nan_test_stop_cb - Stop the NAN device.
294 * @ctx: Pointer to the &struct nan_device
295 */
nan_test_stop_cb(void * ctx)296 static void nan_test_stop_cb(void *ctx)
297 {
298 struct nan_device *dev = ctx;
299
300 DEV_NOT_INIT_ERR_VOID(dev);
301
302 wpa_printf(MSG_INFO, "%s: %s: Done", __func__, dev->name);
303 }
304
305
nan_test_nan_ndp_action(struct nan_device * dev,void * ctx)306 static int nan_test_nan_ndp_action(struct nan_device *dev, void *ctx)
307 {
308 struct nan_ndp_params *params = ctx;
309 int ret;
310
311 wpa_printf(MSG_INFO, "%s: %s: type=%u, peer_nmi=" MACSTR,
312 dev->name, __func__, params->type,
313 MAC2STR(params->ndp_id.peer_nmi));
314
315 ret = nan_handle_ndp_setup(dev->nan, params);
316
317 os_free(params);
318
319 return ret;
320 }
321
322
323 /*
324 * nan_ndp_notify_action - Default NAN NDP notification handling
325 * @dev: NAN device
326 * @ctx: Pointer to &struct nan_test_ndp_notify
327 */
nan_ndp_notify_action(struct nan_device * dev,void * ctx)328 static int nan_ndp_notify_action(struct nan_device *dev, void *ctx)
329 {
330 struct nan_test_ndp_notify *notify = ctx;
331 struct nan_test_action *action;
332 int ret;
333
334 wpa_printf(MSG_INFO, "%s: %s: type=%u, peer_nmi=" MACSTR,
335 dev->name, __func__, notify->type,
336 MAC2STR(notify->ndp_id.peer_nmi));
337
338 ret = -1;
339 if (notify->type == NAN_TEST_NDP_NOTIFY_REQUEST) {
340 struct nan_ndp_params *params;
341 struct nan_device *curd;
342 bool found = false;
343
344 dl_list_for_each(curd, &dev->global->devs, struct nan_device,
345 list) {
346 if (ether_addr_equal(curd->nmi,
347 notify->ndp_id.peer_nmi)) {
348 found = true;
349 break;
350 }
351 }
352
353 if (!found) {
354 wpa_printf(MSG_ERROR, "Peer device not found");
355 ret = -1;
356 goto out;
357 }
358
359 params = os_zalloc(sizeof(struct nan_ndp_params));
360 if (!params) {
361 ret = -1;
362 goto out;
363 }
364
365 params->type = NAN_NDP_ACTION_RESP;
366 os_memcpy(params->ndp_id.peer_nmi, notify->ndp_id.peer_nmi,
367 ETH_ALEN);
368 os_memcpy(params->ndp_id.init_ndi, notify->ndp_id.init_ndi,
369 ETH_ALEN);
370 params->ndp_id.id = notify->ndp_id.id;
371 params->qos.min_slots = NAN_TEST_MIN_SLOTS;
372 params->qos.max_latency = NAN_TEST_MAX_LATENCY;
373
374 if (dev->conf->ndp_confs[dev->n_ndps].accept_request) {
375 wpa_printf(MSG_INFO, "%s: Accepting request",
376 dev->name);
377
378 os_memcpy(params->u.resp.resp_ndi, dev->ndi, ETH_ALEN);
379 params->u.resp.status = NAN_NDP_STATUS_ACCEPTED;
380 dev->conf->schedule_cb(¶ms->sched);
381 params->sched.elems = dev->global->elems;
382 params->sched_valid = 1;
383
384 params->sec.csid =
385 dev->conf->ndp_confs[dev->n_ndps].csid;
386 os_memcpy(params->sec.pmk, dev->conf->pmk, PMK_LEN);
387 } else {
388 wpa_printf(MSG_INFO, "%s: Rejecting request",
389 dev->name);
390
391 params->u.resp.status = NAN_NDP_STATUS_REJECTED;
392 params->u.resp.reason_code =
393 dev->conf->ndp_confs[dev->n_ndps].reason;
394 }
395
396 action = nan_test_add_action(dev->global, dev,
397 nan_test_nan_ndp_action,
398 params);
399 if (action)
400 ret = 0;
401 } else if (notify->type == NAN_TEST_NDP_NOTIFY_RESPONSE) {
402 struct nan_ndp_params *params;
403
404 params = os_zalloc(sizeof(struct nan_ndp_params));
405 if (!params) {
406 ret = -1;
407 goto out;
408 }
409
410 params->type = NAN_NDP_ACTION_CONF;
411 os_memcpy(params->ndp_id.peer_nmi, notify->ndp_id.peer_nmi,
412 ETH_ALEN);
413 os_memcpy(params->ndp_id.init_ndi, notify->ndp_id.init_ndi,
414 ETH_ALEN);
415 params->ndp_id.id = notify->ndp_id.id;
416
417 params->qos.min_slots = NAN_TEST_MIN_SLOTS;
418 params->qos.max_latency = NAN_TEST_MAX_LATENCY;
419
420 if (dev->conf->ndp_confs[dev->n_ndps].accept_request) {
421 wpa_printf(MSG_INFO, "%s: Accepting response",
422 dev->name);
423
424 os_memcpy(params->u.resp.resp_ndi, dev->ndi, ETH_ALEN);
425 params->u.resp.status = NAN_NDP_STATUS_ACCEPTED;
426
427 if (!dev->conf->schedule_conf_cb) {
428 wpa_printf(MSG_ERROR,
429 "%s: No schedule conf cb defined",
430 dev->name);
431 os_free(params);
432 ret = -1;
433 goto out;
434 }
435
436 dev->conf->schedule_conf_cb(¶ms->sched);
437 params->sched.elems = dev->global->elems;
438 params->sched_valid = 1;
439
440 params->sec.csid =
441 dev->conf->ndp_confs[dev->n_ndps].csid;
442 os_memcpy(params->sec.pmk, dev->conf->pmk, PMK_LEN);
443 } else {
444 wpa_printf(MSG_INFO, "%s: Rejecting response",
445 dev->name);
446
447 params->u.resp.status = NAN_NDP_STATUS_REJECTED;
448 params->u.resp.reason_code =
449 dev->conf->ndp_confs[dev->n_ndps].reason;
450 }
451
452 action = nan_test_add_action(dev->global, dev,
453 nan_test_nan_ndp_action,
454 params);
455 if (action)
456 ret = 0;
457 } else if (notify->type ==
458 dev->conf->ndp_confs[dev->n_ndps].expected_result) {
459 ret = 0;
460 if (notify->type == NAN_TEST_NDP_NOTIFY_CONNECTED) {
461 if (dev->conf->ndp_confs[dev->n_ndps].
462 term_once_connected) {
463 struct nan_ndp_params *params;
464
465 wpa_printf(MSG_INFO,
466 "%s: Connected successfully. Now term",
467 dev->name);
468
469 params = os_zalloc(sizeof(*params));
470 if (!params) {
471 ret = -1;
472 goto out;
473 }
474
475 params->type = NAN_NDP_ACTION_TERM;
476 os_memcpy(params->ndp_id.peer_nmi,
477 notify->ndp_id.peer_nmi,
478 ETH_ALEN);
479 os_memcpy(params->ndp_id.init_ndi,
480 notify->ndp_id.init_ndi,
481 ETH_ALEN);
482 params->ndp_id.id = notify->ndp_id.id;
483
484 action = nan_test_add_action(
485 dev->global, dev,
486 nan_test_nan_ndp_action, params);
487 if (action)
488 ret = 0;
489 }
490 }
491 } else if (notify->type == NAN_TEST_NDP_NOTIFY_DISCONNECTED &&
492 dev->connected_notify_received) {
493 wpa_printf(MSG_INFO,
494 "%s: Disconnected after connected as expected. Test case done",
495 dev->name);
496 ret = 0;
497 } else {
498 wpa_printf(MSG_ERROR,
499 "%s: Unexpected notify: type=%u expected=%u",
500 dev->name, notify->type,
501 dev->conf->ndp_confs[dev->n_ndps].expected_result);
502 ret = -1;
503 }
504
505 out:
506 os_free((void *) notify->ssi);
507 os_free(notify);
508 return ret;
509 }
510
511
nan_test_ndp_action(struct nan_device * dev,enum nan_test_ndp_notify_type type,struct nan_ndp_id * ndp_id,u8 publish_inst_id,const u8 * ssi,size_t ssi_len,enum nan_cipher_suite_id csid,const u8 * pmkid)512 static void nan_test_ndp_action(struct nan_device *dev, enum
513 nan_test_ndp_notify_type type,
514 struct nan_ndp_id *ndp_id,
515 u8 publish_inst_id,
516 const u8 *ssi, size_t ssi_len,
517 enum nan_cipher_suite_id csid,
518 const u8 *pmkid)
519 {
520 struct nan_test_ndp_notify *notify;
521
522 DEV_NOT_INIT_ERR_VOID(dev);
523
524 wpa_printf(MSG_INFO, "%s: %s: Enter: type=%u",
525 dev->name, __func__, type);
526
527 notify = os_zalloc(sizeof(struct nan_test_ndp_notify));
528 if (!notify) {
529 wpa_printf(MSG_ERROR,
530 "Failed allocation: nan_test_ndp_notify");
531 return;
532 }
533
534 notify->type = type;
535 os_memcpy(¬ify->ndp_id, ndp_id, sizeof(notify->ndp_id));
536
537 if (ssi && ssi_len) {
538 notify->ssi = os_memdup(ssi, ssi_len);
539 if (!notify->ssi) {
540 wpa_printf(MSG_ERROR, "Failed allocation: ssi");
541 os_free(notify);
542 return;
543 }
544 notify->ssi_len = ssi_len;
545 }
546
547 if (nan_test_add_action(dev->global, dev, nan_ndp_notify_action,
548 notify))
549 return;
550
551 os_free((void *) notify->ssi);
552 os_free(notify);
553 }
554
555
556 /**
557 * nan_test_ndp_action_notfi_cb - Callback for NDP request
558 * @ctx: Pointer to &struct nan_device
559 * @params: NDP action notification parameters
560 *
561 * The handling of the event is done asynchronously through the NAN test actions
562 * processing.
563 */
564 static void
nan_test_ndp_action_notfi_cb(void * ctx,struct nan_ndp_action_notif_params * params)565 nan_test_ndp_action_notfi_cb(void *ctx,
566 struct nan_ndp_action_notif_params *params)
567 {
568 struct nan_device *dev = ctx;
569 enum nan_test_ndp_notify_type type;
570
571 DEV_NOT_INIT_ERR_VOID(dev);
572
573 if (params->is_request)
574 type = NAN_TEST_NDP_NOTIFY_REQUEST;
575 else
576 type = NAN_TEST_NDP_NOTIFY_RESPONSE;
577
578 nan_test_ndp_action(dev, type, ¶ms->ndp_id,
579 params->publish_inst_id, params->ssi,
580 params->ssi_len, params->csid, params->pmkid);
581 }
582
583
584 /**
585 * nan_test_ndp_connected_cb - Callback for NDP connected
586 * @ctx: Pointer to &struct nan_device
587 * @params: NDP action notification parameters
588 * Returns: 0 on success, -1 on failure
589 *
590 * The handling of the event is done asynchronously through the NAN test actions
591 * processing.
592 */
nan_test_ndp_connected_cb(void * ctx,struct nan_ndp_connection_params * params)593 static int nan_test_ndp_connected_cb(void *ctx,
594 struct nan_ndp_connection_params *params)
595 {
596 struct nan_device *dev = ctx;
597 struct nan_peer_schedule sched;
598 struct nan_peer_potential_avail pot;
599
600 DEV_NOT_INIT_ERR(dev);
601
602 wpa_printf(MSG_INFO,
603 "%s: %s: Enter. local_ndi=" MACSTR " peer_ndi=" MACSTR,
604 dev->name, __func__,
605 MAC2STR(params->local_ndi), MAC2STR(params->peer_ndi));
606
607 nan_peer_get_schedule_info(dev->nan, params->ndp_id.peer_nmi, &sched);
608 nan_peer_get_pot_avail(dev->nan, params->ndp_id.peer_nmi, &pot);
609
610 if (nan_peer_get_tk(dev->nan, params->ndp_id.peer_nmi,
611 params->peer_ndi, params->local_ndi,
612 dev->tk, &dev->tk_len, &dev->csid) == 0) {
613 wpa_hexdump(MSG_DEBUG, "NAN Test: TK", dev->tk, dev->tk_len);
614
615 if (dev->csid !=
616 dev->conf->ndp_confs[dev->n_ndps].expected_csid) {
617 wpa_printf(MSG_ERROR,
618 "%s: Unexpected CSID: got %u expected %u",
619 dev->name, dev->csid,
620 dev->conf->ndp_confs[dev->n_ndps].
621 expected_csid);
622 return -1;
623 }
624 }
625
626 nan_test_ndp_action(dev, NAN_TEST_NDP_NOTIFY_CONNECTED, ¶ms->ndp_id,
627 0, params->ssi, params->ssi_len, NAN_CS_NONE, NULL);
628
629 dev->connected_notify_received = true;
630
631 return 0;
632 }
633
634
635 /**
636 * nan_test_ndp_disconnected_cb - Callback for NDP disconnected
637 * @ctx: Pointer to &struct nan_device
638 * @ndp_id: NDP identifier
639 * @local_ndi: Local NDI address
640 * @peer_ndi: Peer NDI address
641 * @reason: Reason for disconnection
642 * @locally_generated: true if locally generated, false if triggered by peer
643 * @remove_sta: true if the NDI station should be removed
644 * @failure: true if NDP setup failed, false if graceful disconnection
645 * @gtk_id: GTK key ID used for the NDP; 0 if no GTK was used
646 *
647 * The handling of the event is done asynchronously through the NAN test actions
648 * processing.
649 */
nan_test_ndp_disconnected_cb(void * ctx,struct nan_ndp_id * ndp_id,const u8 * local_ndi,const u8 * peer_ndi,enum nan_reason reason,bool locally_generated,bool remove_sta,bool failure,u8 gtk_id)650 static void nan_test_ndp_disconnected_cb(void *ctx, struct nan_ndp_id *ndp_id,
651 const u8 *local_ndi,
652 const u8 *peer_ndi,
653 enum nan_reason reason,
654 bool locally_generated,
655 bool remove_sta,
656 bool failure,
657 u8 gtk_id)
658 {
659 struct nan_device *dev = ctx;
660
661 DEV_NOT_INIT_ERR_VOID(dev);
662
663 wpa_printf(MSG_INFO, "%s: %s: Enter", dev->name, __func__);
664
665 nan_test_ndp_action(dev, NAN_TEST_NDP_NOTIFY_DISCONNECTED,
666 ndp_id, 0, NULL, 0, NAN_CS_NONE, NULL);
667
668 dev->disconnected_notify_received = true;
669 }
670
671
672 /**
673 * nan_test_send_naf_cb_action - NAN test action to send a NAN to a device
674 * @dev: NAN device
675 * @ctx: Pointer to a buffer holding the NAF to be sent
676 */
nan_test_send_naf_cb_action(struct nan_device * dev,void * ctx)677 static int nan_test_send_naf_cb_action(struct nan_device *dev, void *ctx)
678 {
679 struct wpabuf *data = ctx;
680 int ret;
681
682 DEV_NOT_INIT_ERR(dev);
683
684 wpa_printf(MSG_INFO, "%s: %s: Enter", dev->name, __func__);
685 wpa_hexdump(MSG_DEBUG, "NAN Test: NAF:", wpabuf_head(data),
686 wpabuf_len(data));
687
688 ret = nan_action_rx(dev->nan, wpabuf_head(data), wpabuf_len(data));
689 wpabuf_free(data);
690 return ret;
691 }
692
693
694 /**
695 * nan_test_tx_status_action - NAN test action to send Tx status to a device
696 * @dev: NAN device
697 * @ctx: Pointer to &struct nan_test_tx_status_action
698 */
nan_test_tx_status_action(struct nan_device * dev,void * ctx)699 static int nan_test_tx_status_action(struct nan_device *dev, void *ctx)
700 {
701 struct nan_test_tx_status_action *tx_status = ctx;
702 int ret;
703
704 DEV_NOT_INIT_ERR(dev);
705
706 wpa_printf(MSG_INFO, "%s: %s: enter", dev->name, __func__);
707
708 ret = nan_tx_status(dev->nan, tx_status->dst,
709 wpabuf_head(tx_status->data),
710 wpabuf_len(tx_status->data), tx_status->acked);
711
712 wpabuf_free((struct wpabuf *)tx_status->data);
713 os_free(tx_status);
714 return ret;
715 }
716
717
718 /**
719 * nan_test_send_naf_cb - NAN send NAF callback function
720 * @ctx: Pointer to &struct nan_device
721 * @dst: Destination NAN Management Interface address
722 * @src: Source NAN Management Interface address
723 * @cluster_id: NAN Cluster ID
724 *
725 * The callback builds the management frame and creates the following NAN test
726 * actions:
727 * - NAN test tx status action: to be sent to the transmitting device
728 * - NAN test send NAF action: to be sent to the destination device.
729 */
nan_test_send_naf_cb(void * ctx,const u8 * dst,const u8 * src,const u8 * cluster_id,struct wpabuf * buf)730 static int nan_test_send_naf_cb(void *ctx, const u8 *dst, const u8 *src,
731 const u8 *cluster_id, struct wpabuf *buf)
732 {
733 struct nan_device *dev = ctx;
734 struct nan_device *curd;
735 struct ieee80211_hdr *hdr;
736 struct wpabuf *data = NULL;
737 struct nan_test_tx_status_action *tx_status = NULL;
738 struct nan_test_action *dev_action, *cur_action;
739 bool found = false;
740
741 DEV_NOT_INIT_ERR(dev);
742
743 if (!dst)
744 return -1;
745
746 wpa_printf(MSG_INFO, "%s: %s: Enter " MACSTR, __func__, dev->name,
747 MAC2STR(dst));
748
749 dl_list_for_each(curd, &dev->global->devs, struct nan_device, list) {
750 if (ether_addr_equal(curd->nmi, dst) ||
751 ether_addr_equal(curd->ndi, dst)) {
752 found = true;
753 break;
754 }
755 }
756
757 if (!found) {
758 wpa_printf(MSG_ERROR, "%s: Destination device not found",
759 __func__);
760 return -1;
761 }
762
763 /* Prepare action to send the frame to the peer */
764 data = wpabuf_alloc(sizeof(struct ieee80211_hdr) + wpabuf_len(buf));
765 if (!data) {
766 wpa_printf(MSG_ERROR, "%s: Failed to allocate NAF", __func__);
767 return -1;
768 }
769
770 hdr = wpabuf_put(data, sizeof(struct ieee80211_hdr));
771 hdr->frame_control =
772 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);
773
774 os_memcpy(hdr->addr1, dst, ETH_ALEN);
775 if (!src)
776 os_memcpy(hdr->addr2, dev->nmi, ETH_ALEN);
777 else
778 os_memcpy(hdr->addr2, src, ETH_ALEN);
779 if (cluster_id)
780 os_memcpy(hdr->addr3, cluster_id, ETH_ALEN);
781
782 wpabuf_put_data(data, wpabuf_head(buf), wpabuf_len(buf));
783
784 /* Prepare action to send Tx status */
785 tx_status = os_malloc(sizeof(struct nan_test_tx_status_action));
786 if (!tx_status) {
787 wpa_printf(MSG_ERROR, "%s: Failed to allocate Tx status",
788 __func__);
789 goto fail;
790 }
791
792 tx_status->data = wpabuf_dup(data);
793 if (!tx_status->data) {
794 wpa_printf(MSG_ERROR, "%s: Failed to allocate Tx status data",
795 __func__);
796 goto fail;
797 }
798
799 os_memcpy(tx_status->dst, dst, ETH_ALEN);
800 tx_status->acked = 1;
801
802 /* First send the TX status */
803 dev_action = nan_test_add_action(dev->global, dev,
804 nan_test_tx_status_action, tx_status);
805 if (!dev_action)
806 goto fail;
807
808 /* And then deliver the frame */
809 cur_action = nan_test_add_action(curd->global, curd,
810 nan_test_send_naf_cb_action, data);
811 if (!cur_action)
812 goto fail;
813
814 return 0;
815
816 fail:
817 wpabuf_free(data);
818 if (tx_status)
819 wpabuf_free((struct wpabuf *) tx_status->data);
820
821 os_free(tx_status);
822
823 return -1;
824 }
825
826
827 /**
828 * nan_test_get_chans_cb - Get NAN supported channels callback
829 * @ctx: Pointer to &struct nan_device
830 * @map_id: Channel map identifier
831 * @chans: Pointer to &struct nan_channels to be filled with supported channels
832 */
nan_test_get_chans_cb(void * ctx,u8 map_id,struct nan_channels * chans)833 static int nan_test_get_chans_cb(void *ctx, u8 map_id,
834 struct nan_channels *chans)
835 {
836 struct nan_device *dev = ctx;
837
838 DEV_NOT_INIT_ERR(dev);
839
840 wpa_printf(MSG_INFO, "%s: %s: Enter", dev->name, __func__);
841
842 return dev->conf->get_chans_cb(chans);
843 }
844
845
846 /**
847 * nan_test_is_valid_publish_id_cb - Check if the publish instance ID is valid
848 * @ctx: Pointer to &struct nan_device
849 * @instance_id: Publish instance ID
850 * @service_id: Buffer to be filled with the service ID
851 * Returns true if the instance ID is valid, false otherwise
852 */
nan_test_is_valid_publish_id_cb(void * ctx,u8 instance_id,u8 * service_id)853 static bool nan_test_is_valid_publish_id_cb(void *ctx, u8 instance_id,
854 u8 *service_id)
855 {
856 if (instance_id != NAN_TEST_PUBLISH_INST_ID)
857 return false;
858
859 os_memset(service_id, 0xaa, NAN_SERVICE_ID_LEN);
860 return true;
861 }
862
863
864 /*
865 * nan_test_set_peer_schedule_cb - Set peer schedule callback
866 *
867 * @ctx: Pointer to &struct nan_device
868 * @sched: Pointer to &struct nan_peer_schedule to be filled
869 */
870 static int
nan_test_set_peer_schedule_cb(void * ctx,const u8 * nmi_addr,bool new_sta,u16 cdw,u8 sequence_id,u16 max_channel_switch_time,const struct nan_peer_schedule * sched,const struct wpabuf * ulw_elems)871 nan_test_set_peer_schedule_cb(void *ctx, const u8 *nmi_addr, bool new_sta,
872 u16 cdw, u8 sequence_id,
873 u16 max_channel_switch_time,
874 const struct nan_peer_schedule *sched,
875 const struct wpabuf *ulw_elems)
876 {
877 struct nan_device *dev = (struct nan_device *)ctx;
878
879 DEV_NOT_INIT_ERR(dev);
880
881 wpa_printf(MSG_INFO, "%s: %s: Enter", dev->name, __func__);
882 wpa_printf(MSG_INFO, "%s: nmi_addr=" MACSTR
883 " new_sta=%d cdw=%u sequence_id=%u max_channel_switch_time=%u",
884 dev->name, MAC2STR(nmi_addr), new_sta, cdw, sequence_id,
885 max_channel_switch_time);
886
887 return 0;
888 }
889
890
891 /**
892 * nan_test_dev_init - Initialize a test device instance
893 * @dev: the instance of the device to initialize
894 */
nan_test_dev_init(struct nan_device * dev)895 static int nan_test_dev_init(struct nan_device *dev)
896 {
897 struct nan_config nan;
898
899 os_memset(&nan, 0, sizeof(nan));
900 os_memcpy(nan.nmi_addr, dev->nmi, ETH_ALEN);
901 nan.cb_ctx = dev;
902
903 nan.start = nan_test_start_cb;
904 nan.stop = nan_test_stop_cb;
905 nan.ndp_action_notif = nan_test_ndp_action_notfi_cb;
906 nan.ndp_connected = nan_test_ndp_connected_cb;
907 nan.ndp_disconnected = nan_test_ndp_disconnected_cb;
908 nan.send_naf = nan_test_send_naf_cb;
909 nan.get_chans = nan_test_get_chans_cb;
910 nan.is_valid_publish_id = nan_test_is_valid_publish_id_cb;
911 nan.set_peer_schedule = nan_test_set_peer_schedule_cb;
912
913 /* Awake on every DW on 2 GHz and 5 GHz */
914 nan.dev_capa.cdw_info = 0x9;
915 nan.dev_capa.supported_bands = NAN_DEV_CAPA_SBAND_2G |
916 NAN_DEV_CAPA_SBAND_5G |
917 NAN_DEV_CAPA_SBAND_6G;
918
919 nan.dev_capa.op_mode = NAN_DEV_CAPA_OP_MODE_PHY_MODE;
920 nan.dev_capa.n_antennas = 0x22;
921 nan.dev_capa.channel_switch_time = 10;
922 nan.dev_capa.capa = 0;
923
924 nan.dev_capa_ext_reg_info = 0;
925 nan.pairing_cfg.npk_caching = true;
926 nan.pairing_cfg.pairing_setup = true;
927
928 dev->nan = nan_init(&nan);
929 if (!dev->nan) {
930 wpa_printf(MSG_DEBUG, "NAN: Failed to init");
931 return -1;
932 }
933
934 return 0;
935 }
936
937
938 /**
939 * nan_test_start_dev - Start a NAN test device
940 * @global: NAN test global data structure
941 * @name: Name of the device
942 * @nmi: NAN Management interface address
943 * @ndi: NAN Data interface address
944 * @cconf: NAN cluster configuration
945 * @dconf: Test device configuration
946 */
947 static struct nan_device *
nan_test_start_dev(struct nan_test_global * global,const char * name,const u8 * nmi,const u8 * ndi,struct nan_cluster_config * conf,const struct nan_test_dev_conf * dconf)948 nan_test_start_dev(struct nan_test_global *global,
949 const char *name, const u8 *nmi,
950 const u8 *ndi,
951 struct nan_cluster_config *conf,
952 const struct nan_test_dev_conf *dconf)
953 {
954 struct nan_device *dev;
955 int ret;
956 size_t nlen;
957
958 dev = os_zalloc(sizeof(struct nan_device));
959 if (!dev)
960 return NULL;
961
962 nlen = os_strlen(name);
963 if (nlen >= sizeof(dev->name))
964 nlen = sizeof(dev->name) - 1;
965 os_memcpy(dev->name, name, nlen);
966 os_memcpy(dev->nmi, nmi, sizeof(dev->nmi));
967 os_memcpy(dev->ndi, ndi, sizeof(dev->ndi));
968 dl_list_init(&dev->list);
969 dev->global = global;
970
971 if (dconf->pot_avail_len) {
972 dev->pot_avail = os_memdup(dconf->pot_avail,
973 dconf->pot_avail_len);
974 if (!dev->pot_avail)
975 goto fail;
976 dev->pot_avail_len = dconf->pot_avail_len;
977 }
978
979 ret = nan_test_dev_init(dev);
980 if (ret)
981 goto fail;
982
983 dev->conf = dconf;
984 ret = nan_start(dev->nan, conf);
985 if (ret)
986 goto fail;
987
988 dl_list_add(&global->devs, &dev->list);
989 return dev;
990
991 fail:
992 nan_test_dev_deinit(dev);
993 os_free(dev);
994 return NULL;
995 }
996
997
998 /**
999 * nan_test_setup_devices - Setup the test devices
1000 * @global: NAN test global data structure
1001 * @pub_conf: Publisher test configuration
1002 * @sub_conf: Subscriber test configuration
1003 */
1004 static struct nan_device *
nan_test_setup_devices(struct nan_test_global * global,const struct nan_test_dev_conf * pub_conf,const struct nan_test_dev_conf * sub_conf)1005 nan_test_setup_devices(struct nan_test_global *global,
1006 const struct nan_test_dev_conf *pub_conf,
1007 const struct nan_test_dev_conf *sub_conf)
1008 {
1009 struct nan_cluster_config cconf = {
1010 .master_pref = 2,
1011 .dual_band = 1,
1012 };
1013 /*
1014 * Device attributes containing:
1015 * 1. Device capability attribute (ID=0x0F, len=10):
1016 * - map_id=0
1017 * - cdw_info=0x0009 (awake on every DW on 2G and 5G)
1018 * - supported_bands=0x07 (2G, 5G, 6G)
1019 * - op_mode=0x01
1020 * - n_antennas=0x22
1021 * - channel_switch_time=0x000a (10)
1022 * - capa=0x00
1023 * 2. Availability attribute (ID=0x12, len=12)
1024 */
1025 const u8 attrs[] = {
1026 /* Device capability attribute */
1027 0x0f, 0x09, 0x00, 0x00, 0x09, 0x00, 0x07, 0x01,
1028 0x22, 0x0a, 0x00, 0x00,
1029 /* Availability attribute */
1030 0x12, 0x0c, 0x00, 0x01, 0x20, 0x00, 0x07, 0x00,
1031 0x1a, 0x00, 0x11, 0x51, 0xff, 0x07, 0x00,
1032 };
1033
1034 struct nan_device *pub, *sub;
1035
1036 wpa_printf(MSG_INFO, "%s: Enter\n", __func__);
1037
1038 pub = nan_test_start_dev(global, "publisher", g_pub_nmi, g_pub_ndi,
1039 &cconf, pub_conf);
1040 if (!pub)
1041 goto fail;
1042
1043 sub = nan_test_start_dev(global, "subscriber", g_sub_nmi, g_sub_ndi,
1044 &cconf, sub_conf);
1045 if (!sub)
1046 goto fail;
1047
1048 nan_add_peer(pub->nan, g_sub_nmi, attrs, sizeof(attrs));
1049 nan_add_peer(sub->nan, g_pub_nmi, attrs, sizeof(attrs));
1050
1051 wpa_printf(MSG_INFO, "\n%s: Done\n", __func__);
1052 return sub;
1053
1054 fail:
1055 wpa_printf(MSG_INFO, "\n%s: Fail\n", __func__);
1056 return NULL;
1057 }
1058
1059
nan_test_ndp_request(struct nan_device * sub,const u8 * pub_nmi)1060 static int nan_test_ndp_request(struct nan_device *sub, const u8 *pub_nmi)
1061 {
1062 struct nan_ndp_params *params;
1063 struct nan_test_action *action;
1064
1065 DEV_NOT_INIT_ERR(sub);
1066
1067 params = os_zalloc(sizeof(struct nan_ndp_params));
1068 if (!params) {
1069 wpa_printf(MSG_ERROR, "Failed allocation: nan_ndp_params");
1070 return -1;
1071 }
1072
1073 params->type = NAN_NDP_ACTION_REQ;
1074 os_memcpy(params->ndp_id.peer_nmi, pub_nmi, ETH_ALEN);
1075 os_memcpy(params->ndp_id.init_ndi, sub->ndi, ETH_ALEN);
1076 params->ndp_id.id = ++sub->counter;
1077 params->qos.min_slots = NAN_TEST_MIN_SLOTS;
1078 params->qos.max_latency = NAN_TEST_MAX_LATENCY;
1079 params->sec.csid = sub->conf->ndp_confs[sub->n_ndps].csid;
1080 os_memcpy(params->sec.pmk, sub->conf->pmk, PMK_LEN);
1081
1082 /* Use the device specific schedule callback */
1083 sub->conf->schedule_cb(¶ms->sched);
1084 params->sched_valid = 1;
1085 params->sched.elems = sub->global->elems;
1086
1087 params->u.req.publish_inst_id = NAN_TEST_PUBLISH_INST_ID;
1088 os_memset(params->u.req.service_id, 0xaa, NAN_SERVICE_ID_LEN);
1089
1090 action = nan_test_add_action(sub->global, sub, nan_test_nan_ndp_action,
1091 params);
1092 if (action)
1093 return 0;
1094
1095 wpa_printf(MSG_ERROR, "Failed adding NDP request action");
1096 os_free(params);
1097
1098 return -1;
1099 }
1100
1101
1102 /**
1103 * nan_test_ndp_setup - test NDP setup
1104 * @global: NAN test global data structure
1105 * @pub_conf: Publisher test configuration
1106 * @sub_conf: Subscriber test configuration
1107 *
1108 * Create the test devices, perform the basic publish/subscribe/match to allow
1109 * NDP establishment and trigger an NDP request flow based on the actions
1110 * mechanism.
1111 */
1112 static struct nan_device *
nan_test_ndp_setup(struct nan_test_global * global,const struct nan_test_dev_conf * pub_conf,const struct nan_test_dev_conf * sub_conf)1113 nan_test_ndp_setup(struct nan_test_global *global,
1114 const struct nan_test_dev_conf *pub_conf,
1115 const struct nan_test_dev_conf *sub_conf)
1116 {
1117 if (pub_conf->n_ndps != sub_conf->n_ndps || !pub_conf->n_ndps ||
1118 pub_conf->n_ndps >= NAN_MAX_NUM_NDPS) {
1119 wpa_printf(MSG_DEBUG,
1120 "NAN Test: Publisher and Subscriber n_ndps mismatch or invalid");
1121 return NULL;
1122 }
1123
1124 return nan_test_setup_devices(global, pub_conf, sub_conf);
1125 }
1126
1127
nan_test_verify_expected_result(struct nan_device * dev)1128 static int nan_test_verify_expected_result(struct nan_device *dev)
1129 {
1130 DEV_NOT_INIT_ERR(dev);
1131
1132 if (dev->conf->ndp_confs[dev->n_ndps].expected_result ==
1133 NAN_TEST_NDP_NOTIFY_CONNECTED &&
1134 !dev->connected_notify_received) {
1135 wpa_printf(MSG_ERROR,
1136 "%s: Expected connected notify not received",
1137 dev->name);
1138 return -1;
1139 }
1140
1141 if (dev->conf->ndp_confs[dev->n_ndps].expected_result ==
1142 NAN_TEST_NDP_NOTIFY_DISCONNECTED &&
1143 !dev->disconnected_notify_received) {
1144 wpa_printf(MSG_ERROR,
1145 "%s: Expected disconnected notify not received",
1146 dev->name);
1147 return -1;
1148 }
1149
1150 return 0;
1151 }
1152
1153
nan_test_iteration_done(struct nan_test_global * global)1154 static int nan_test_iteration_done(struct nan_test_global *global)
1155 {
1156 struct nan_device *dev;
1157 u8 tk[NAN_TK_MAX_LEN];
1158 size_t tk_len = 0;
1159 enum nan_cipher_suite_id csid;
1160 int ret;
1161
1162 os_memset(tk, 0, sizeof(tk));
1163
1164 dl_list_for_each(dev, &global->devs, struct nan_device, list) {
1165 ret = nan_test_verify_expected_result(dev);
1166
1167 if (ret)
1168 return ret;
1169
1170 if (tk_len == 0 && dev->tk_len > 0) {
1171 os_memcpy(tk, dev->tk, dev->tk_len);
1172 tk_len = dev->tk_len;
1173 csid = dev->csid;
1174 } else if (dev->tk_len > 0) {
1175 if (tk_len != dev->tk_len ||
1176 csid != dev->csid ||
1177 os_memcmp(tk, dev->tk, tk_len) != 0) {
1178 wpa_printf(MSG_ERROR,
1179 "%s: TK mismatch with other device",
1180 dev->name);
1181 return -1;
1182 }
1183
1184 wpa_printf(MSG_INFO, "%s: TK matches with other device",
1185 dev->name);
1186 }
1187
1188 dev->connected_notify_received = false;
1189 dev->disconnected_notify_received = false;
1190
1191 os_memset(dev->tk, 0, sizeof(dev->tk));
1192 dev->tk_len = 0;
1193
1194 dev->n_ndps++;
1195 }
1196
1197 return 0;
1198 }
1199
1200
1201 /**
1202 * nan_test_run - Run the NAN tests
1203 * Iterates over all tests cases and for each test case initializes the global
1204 * context, creates the NAN devices and perform the test case.
1205 */
nan_test_run(void)1206 static int nan_test_run(void)
1207 {
1208 struct nan_test_global global;
1209 const struct nan_test_case *curr_tc;
1210 bool all_failed = false;
1211
1212 while ((curr_tc = nan_test_case_get_next())) {
1213 struct nan_device *sub;
1214 bool failed = false;
1215 size_t i;
1216
1217 wpa_printf(MSG_INFO,
1218 "\n======> NAN TEST CASE: %s <======\n",
1219 curr_tc->name);
1220
1221 nan_test_global_init(&global);
1222 sub = nan_test_ndp_setup(&global,
1223 &curr_tc->pub_conf,
1224 &curr_tc->sub_conf);
1225 if (!sub) {
1226 wpa_printf(MSG_ERROR,
1227 "NAN Test: Failed to setup devices");
1228 nan_test_global_deinit(&global);
1229 failed = true;
1230 continue;
1231 }
1232
1233 for (i = 0; i < sub->conf->n_ndps; i++) {
1234 int ret = nan_test_ndp_request(sub, g_pub_nmi);
1235
1236 if (!ret)
1237 ret = nan_test_run_actions(&global);
1238
1239 if (!ret)
1240 ret = nan_test_iteration_done(&global);
1241
1242 wpa_printf(MSG_INFO,
1243 "\n======> NAN TEST CASE: %s: iter=%zu: result=%s <======\n",
1244 curr_tc->name, i,
1245 ret ? "FAILED" : "SUCCESS");
1246
1247 if (ret) {
1248 failed = true;
1249 break;
1250 }
1251 }
1252
1253 wpa_printf(MSG_INFO,
1254 "\n======> NAN TEST CASE: %s: Done. Result=%s <======\n",
1255 curr_tc->name, failed ? "FAILED" : "SUCCESS");
1256
1257 all_failed |= failed;
1258
1259 nan_test_global_deinit(&global);
1260 }
1261
1262 return all_failed ? -1 : 0;
1263 }
1264
1265
1266 static const u8 nan_key[32] = {
1267 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1268 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1269 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1270 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1271 };
1272
1273 static u8 nan_addrs[][ETH_ALEN] = {
1274 {
1275 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
1276 },
1277 {
1278 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
1279 },
1280 };
1281
1282 static u8 nan_nonce[][WPA_NONCE_LEN] = {
1283 {
1284 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1285 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1286 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1287 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1288 },
1289 {
1290 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1291 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1292 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1293 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
1294 },
1295 };
1296
1297 static struct nan_ptk nan_ptk_128 = {
1298 .kck = {
1299 0x67, 0x40, 0x47, 0x6f, 0x9c, 0xb4, 0xcd, 0xee,
1300 0xfb, 0xc7, 0xad, 0x25, 0x78, 0xd5, 0x5e, 0xb2,
1301 },
1302 .kek = {
1303 0xe5, 0xc7, 0x55, 0xbb, 0x4e, 0x4f, 0xd7, 0xbb,
1304 0xdb, 0x19, 0xa5, 0xb3, 0x6c, 0xcc, 0x77, 0xe3,
1305 },
1306 .tk = {
1307 0xe2, 0x7f, 0xfc, 0x7b, 0xa2, 0xd6, 0xb2, 0x44,
1308 0x63, 0x4a, 0x0c, 0xf2, 0x09, 0xf8, 0x06, 0x9a,
1309 },
1310 .kck_len = 16,
1311 .kek_len = 16,
1312 .tk_len = 16,
1313 };
1314
1315 static struct nan_ptk nan_ptk_256 = {
1316 .kck = {
1317 0x72, 0x70, 0xd5, 0xdc, 0x05, 0x44, 0x8a, 0xb4,
1318 0x1a, 0x73, 0xe5, 0x51, 0x56, 0xa0, 0x78, 0x3a,
1319 0x33, 0x74, 0x62, 0x4e, 0x81, 0xe0, 0x39, 0xf8,
1320 },
1321 .kek = {
1322 0x55, 0x3e, 0x2c, 0x8a, 0x0b, 0xab, 0xfc, 0xe1,
1323 0xf9, 0x45, 0xfb, 0xa7, 0xa6, 0xc9, 0x0c, 0x77,
1324 0x76, 0x64, 0x6b, 0xaa, 0xc0, 0x59, 0x7c, 0xd6,
1325 0xa4, 0x99, 0x31, 0xf2, 0x6e, 0xbf, 0x0e, 0x49,
1326 },
1327 .tk = {
1328 0x44, 0x61, 0x12, 0xba, 0x4c, 0x25, 0x8b, 0xe5,
1329 0x29, 0x33, 0x8f, 0x77, 0x45, 0x55, 0x13, 0x87,
1330 0x69, 0x61, 0xf4, 0x33, 0xad, 0x87, 0x47, 0xbb,
1331 0xa1, 0xd6, 0x5b, 0x4d, 0xaf, 0x0a, 0x37, 0x5a
1332 },
1333 .kck_len = 24,
1334 .kek_len = 32,
1335 .tk_len = 32,
1336 };
1337
1338 static const u8 nan_service_id[NAN_SERVICE_ID_LEN] = {
1339 0x48, 0xda, 0x63, 0xdc, 0xde, 0x19,
1340 };
1341
1342 static u8 nan_pmkid_128[PMKID_LEN] = {
1343 0xcf, 0x4f, 0x64, 0x44, 0xd8, 0xe2, 0xc4, 0xef,
1344 0xa4, 0xf3, 0xa6, 0x51, 0xf3, 0x0f, 0x63, 0x4f,
1345 };
1346
1347 static u8 nan_pmkid_256[PMKID_LEN] = {
1348 0x08, 0x11, 0x23, 0xc8, 0x57, 0x52, 0x6a, 0x09,
1349 0x6d, 0x46, 0x48, 0x2b, 0xa8, 0x02, 0xfc, 0x28,
1350 };
1351
1352 static u8 nan_crypto_sha256_digest[SHA256_MAC_LEN] = {
1353 0xde, 0x7a, 0xa9, 0x34, 0x0d, 0x1d, 0xbb, 0x73,
1354 0x4d, 0x4d, 0x5a, 0xcb, 0x6b, 0xe4, 0xed, 0xc9,
1355 0x0a, 0x16, 0x37, 0xaa, 0x1e, 0x5a, 0x34, 0x2e,
1356 0x58, 0xdd, 0x0b, 0x30, 0x4b, 0xa4, 0x8c, 0x32,
1357 };
1358
1359 static u8 nan_crypto_sha384_digest[SHA384_MAC_LEN] = {
1360 0xb1, 0xf9, 0x75, 0xbd, 0x80, 0x84, 0x21, 0x35,
1361 0xc2, 0x38, 0xf7, 0x0d, 0x03, 0x32, 0x38, 0xe7,
1362 0xbb, 0x55, 0x39, 0x21, 0xf5, 0xb3, 0xbd, 0x5c,
1363 0x93, 0x78, 0x52, 0x61, 0x6f, 0x83, 0x58, 0x2d,
1364 0xdc, 0x0d, 0xe2, 0x25, 0x5e, 0x72, 0x6c, 0x95,
1365 0xd0, 0xcb, 0x09, 0xef, 0x2a, 0x8f, 0x08, 0x17,
1366 };
1367
1368 static const char sha_data[] =
1369 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
1370
1371 static u8 sha256_digest[] = {
1372 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
1373 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
1374 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
1375 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
1376 };
1377
1378 static u8 sha384_digest[] = {
1379 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39,
1380 0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39,
1381 0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab,
1382 0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6,
1383 0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f,
1384 0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b,
1385 };
1386
1387 #define NAN_CRYPTO_FAIL(_ret) \
1388 if (_ret) { \
1389 wpa_printf(MSG_ERROR, \
1390 "NAN Crypto test fail: %s:%d", \
1391 __func__, __LINE__); \
1392 return -1; \
1393 }
1394
1395
nan_test_crypto_key_mic(void)1396 static int nan_test_crypto_key_mic(void)
1397 {
1398 u8 digest[SHA384_MAC_LEN];
1399 u8 *data = nan_nonce[0];
1400 size_t data_len = sizeof(nan_nonce[0]);
1401
1402 NAN_CRYPTO_FAIL(nan_crypto_key_mic(data, data_len, nan_key,
1403 sizeof(nan_key), NAN_CS_SK_CCM_128,
1404 digest));
1405
1406 NAN_CRYPTO_FAIL(os_memcmp(digest, nan_crypto_sha256_digest,
1407 NAN_KEY_MIC_LEN));
1408
1409 os_memset(digest, 0, sizeof(digest));
1410
1411 NAN_CRYPTO_FAIL(nan_crypto_key_mic(data, data_len, nan_key,
1412 sizeof(nan_key), NAN_CS_SK_GCM_256,
1413 digest));
1414 NAN_CRYPTO_FAIL(os_memcmp(digest, nan_crypto_sha384_digest,
1415 NAN_KEY_MIC_24_LEN));
1416
1417 return 0;
1418 }
1419
1420
nan_test_crypto_pmkid(void)1421 static int nan_test_crypto_pmkid(void)
1422 {
1423 u8 pmkid[PMKID_LEN];
1424
1425 NAN_CRYPTO_FAIL(nan_crypto_calc_pmkid(nan_key, nan_addrs[0],
1426 nan_addrs[1], nan_service_id,
1427 NAN_CS_SK_CCM_128, pmkid));
1428
1429 NAN_CRYPTO_FAIL(os_memcmp(pmkid, nan_pmkid_128, sizeof(pmkid)));
1430
1431 NAN_CRYPTO_FAIL(nan_crypto_calc_pmkid(nan_key, nan_addrs[0],
1432 nan_addrs[1], nan_service_id,
1433 NAN_CS_SK_GCM_256, pmkid));
1434
1435 NAN_CRYPTO_FAIL(os_memcmp(pmkid, nan_pmkid_256, sizeof(pmkid)));
1436
1437 return 0;
1438 }
1439
1440
nan_test_ptk(void)1441 static int nan_test_ptk(void)
1442 {
1443 struct nan_ptk tptk;
1444
1445 os_memset(&tptk, 0, sizeof(tptk));
1446
1447 NAN_CRYPTO_FAIL(nan_crypto_pmk_to_ptk(nan_key,
1448 nan_addrs[0], nan_addrs[1],
1449 nan_nonce[0], nan_nonce[1],
1450 &tptk, NAN_CS_SK_CCM_128));
1451
1452 NAN_CRYPTO_FAIL(os_memcmp(&tptk, &nan_ptk_128, sizeof(tptk)));
1453
1454 os_memset(&tptk, 0, sizeof(tptk));
1455
1456 NAN_CRYPTO_FAIL(nan_crypto_pmk_to_ptk(nan_key,
1457 nan_addrs[0], nan_addrs[1],
1458 nan_nonce[0], nan_nonce[1],
1459 &tptk, NAN_CS_SK_GCM_256));
1460
1461 NAN_CRYPTO_FAIL(os_memcmp(&tptk, &nan_ptk_256, sizeof(tptk)));
1462
1463 return 0;
1464 }
1465
1466
nan_test_crypto_auth_token(void)1467 static int nan_test_crypto_auth_token(void)
1468 {
1469 u8 digest[SHA384_MAC_LEN];
1470 const u8 *data = (const u8 *) sha_data;
1471 size_t len = os_strlen(sha_data);
1472
1473 NAN_CRYPTO_FAIL(nan_crypto_calc_auth_token(NAN_CS_SK_CCM_128, data,
1474 len, digest));
1475 NAN_CRYPTO_FAIL(os_memcmp(digest, sha256_digest, NAN_AUTH_TOKEN_LEN));
1476
1477 os_memset(digest, 0, sizeof(digest));
1478
1479 NAN_CRYPTO_FAIL(nan_crypto_calc_auth_token(NAN_CS_SK_GCM_256, data, len,
1480 digest));
1481 NAN_CRYPTO_FAIL(os_memcmp(digest, sha384_digest, NAN_AUTH_TOKEN_LEN));
1482
1483 return 0;
1484 }
1485
1486
nan_test_derive_nd_pmk(void)1487 static int nan_test_derive_nd_pmk(void)
1488 {
1489 u8 pmk[PMK_LEN];
1490 /* Wi-Fi Aware spec v4.0, Appendix M.1 - Test Vector 1 */
1491 const char *pwd = "NAN";
1492 const u8 service_id[NAN_SERVICE_ID_LEN] = {
1493 0x2b, 0x9c, 0x45, 0x0f, 0x66, 0x71,
1494 };
1495 const u8 nmi[ETH_ALEN] = {
1496 0x02, 0x90, 0x4c, 0x12, 0xd0, 0x01,
1497 };
1498 const u8 expected_pmk_ccm128[PMK_LEN] = {
1499 0xee, 0x35, 0x85, 0x06, 0x30, 0x56, 0xd1, 0x64,
1500 0xd1, 0x54, 0x54, 0xad, 0x39, 0x01, 0x0d, 0x4e,
1501 0x26, 0x40, 0xb0, 0xd8, 0x2f, 0xb2, 0x4a, 0x2d,
1502 0x68, 0x99, 0x86, 0x2d, 0x27, 0x3c, 0x68, 0xbf,
1503 };
1504
1505 NAN_CRYPTO_FAIL(nan_crypto_derive_nd_pmk(pwd, service_id,
1506 NAN_CS_SK_CCM_128, nmi, pmk));
1507 NAN_CRYPTO_FAIL(os_memcmp(pmk, expected_pmk_ccm128, PMK_LEN));
1508
1509 return 0;
1510 }
1511
nan_test_crypto(void)1512 int nan_test_crypto(void)
1513 {
1514 NAN_CRYPTO_FAIL(nan_test_crypto_key_mic());
1515 NAN_CRYPTO_FAIL(nan_test_crypto_pmkid());
1516 NAN_CRYPTO_FAIL(nan_test_ptk());
1517 NAN_CRYPTO_FAIL(nan_test_crypto_auth_token());
1518 NAN_CRYPTO_FAIL(nan_test_derive_nd_pmk());
1519
1520 return 0;
1521 }
1522
1523
nan_module_tests(void)1524 int nan_module_tests(void)
1525 {
1526 if (nan_test_crypto())
1527 return -1;
1528
1529 return nan_test_run();
1530 }
1531