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