blob: 178fd126ec043dd770f7a045ff27d97a50d85f12 [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * hostapd / DPP integration
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
Hai Shalomfdcde762020-04-02 11:19:20 -07004 * Copyright (c) 2018-2020, The Linux Foundation
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10#include "utils/includes.h"
11
12#include "utils/common.h"
13#include "utils/eloop.h"
14#include "common/dpp.h"
15#include "common/gas.h"
16#include "common/wpa_ctrl.h"
17#include "hostapd.h"
18#include "ap_drv_ops.h"
19#include "gas_query_ap.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070020#include "gas_serv.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070021#include "wpa_auth.h"
22#include "dpp_hostapd.h"
23
24
Roshan Pius3a1667e2018-07-03 15:17:14 -070025static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070026static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -070027static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
28static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070029#ifdef CONFIG_DPP2
30static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
31 void *timeout_ctx);
32#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070033
34static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
35
36
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070037/**
38 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
39 * @hapd: Pointer to hostapd_data
40 * @cmd: DPP URI read from a QR Code
41 * Returns: Identifier of the stored info or -1 on failure
42 */
43int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
44{
45 struct dpp_bootstrap_info *bi;
46 struct dpp_authentication *auth = hapd->dpp_auth;
47
Hai Shalom021b0b52019-04-10 11:17:58 -070048 bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070049 if (!bi)
50 return -1;
51
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070052 if (auth && auth->response_pending &&
53 dpp_notify_new_qr_code(auth, bi) == 1) {
54 wpa_printf(MSG_DEBUG,
55 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070056 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
57 " freq=%u type=%d",
58 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
59 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070060 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
61 auth->peer_mac_addr,
62 wpabuf_head(hapd->dpp_auth->resp_msg),
63 wpabuf_len(hapd->dpp_auth->resp_msg));
64 }
65
66 return bi->id;
67}
68
69
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080070/**
71 * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
72 * @hapd: Pointer to hostapd_data
73 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
74 * Returns: Identifier of the stored info or -1 on failure
75 */
76int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
77{
78 struct dpp_bootstrap_info *bi;
79
80 bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
81 if (!bi)
82 return -1;
83
84 return bi->id;
85}
86
87
Hai Shalomfdcde762020-04-02 11:19:20 -070088int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd)
89{
90 const char *pos;
91 struct dpp_bootstrap_info *peer_bi, *own_bi;
92
93 pos = os_strstr(cmd, " own=");
94 if (!pos)
95 return -1;
96 pos += 5;
97 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
98 if (!own_bi)
99 return -1;
100
101 pos = os_strstr(cmd, " uri=");
102 if (!pos)
103 return -1;
104 pos += 5;
105 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
106 if (!peer_bi) {
107 wpa_printf(MSG_INFO,
108 "DPP: Failed to parse URI from NFC Handover Request");
109 return -1;
110 }
111
112 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
113 return -1;
114
115 return peer_bi->id;
116}
117
118
119int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd)
120{
121 const char *pos;
122 struct dpp_bootstrap_info *peer_bi, *own_bi;
123
124 pos = os_strstr(cmd, " own=");
125 if (!pos)
126 return -1;
127 pos += 5;
128 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
129 if (!own_bi)
130 return -1;
131
132 pos = os_strstr(cmd, " uri=");
133 if (!pos)
134 return -1;
135 pos += 5;
136 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
137 if (!peer_bi) {
138 wpa_printf(MSG_INFO,
139 "DPP: Failed to parse URI from NFC Handover Select");
140 return -1;
141 }
142
143 if (peer_bi->curve != own_bi->curve) {
144 wpa_printf(MSG_INFO,
145 "DPP: Peer (NFC Handover Selector) used different curve");
146 return -1;
147 }
148
149 return peer_bi->id;
150}
151
152
Roshan Pius3a1667e2018-07-03 15:17:14 -0700153static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
154 void *timeout_ctx)
155{
156 struct hostapd_data *hapd = eloop_ctx;
157 struct dpp_authentication *auth = hapd->dpp_auth;
158
159 if (!auth || !auth->resp_msg)
160 return;
161
162 wpa_printf(MSG_DEBUG,
163 "DPP: Retry Authentication Response after timeout");
164 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
165 " freq=%u type=%d",
166 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
167 DPP_PA_AUTHENTICATION_RESP);
168 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
169 wpabuf_head(auth->resp_msg),
170 wpabuf_len(auth->resp_msg));
171}
172
173
174static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
175{
176 struct dpp_authentication *auth = hapd->dpp_auth;
177 unsigned int wait_time, max_tries;
178
179 if (!auth || !auth->resp_msg)
180 return;
181
182 if (hapd->dpp_resp_max_tries)
183 max_tries = hapd->dpp_resp_max_tries;
184 else
185 max_tries = 5;
186 auth->auth_resp_tries++;
187 if (auth->auth_resp_tries >= max_tries) {
188 wpa_printf(MSG_INFO,
189 "DPP: No confirm received from initiator - stopping exchange");
190 hostapd_drv_send_action_cancel_wait(hapd);
191 dpp_auth_deinit(hapd->dpp_auth);
192 hapd->dpp_auth = NULL;
193 return;
194 }
195
196 if (hapd->dpp_resp_retry_time)
197 wait_time = hapd->dpp_resp_retry_time;
198 else
199 wait_time = 1000;
200 wpa_printf(MSG_DEBUG,
201 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
202 wait_time);
203 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
204 eloop_register_timeout(wait_time / 1000,
205 (wait_time % 1000) * 1000,
206 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
207}
208
209
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700210void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
211 const u8 *data, size_t data_len, int ok)
212{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700213 struct dpp_authentication *auth = hapd->dpp_auth;
214
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700215 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
216 MAC2STR(dst), ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700217 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
218 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700219
220 if (!hapd->dpp_auth) {
221 wpa_printf(MSG_DEBUG,
222 "DPP: Ignore TX status since there is no ongoing authentication exchange");
223 return;
224 }
225
Hai Shalom021b0b52019-04-10 11:17:58 -0700226#ifdef CONFIG_DPP2
227 if (auth->connect_on_tx_status) {
228 wpa_printf(MSG_DEBUG,
229 "DPP: Complete exchange on configuration result");
230 dpp_auth_deinit(hapd->dpp_auth);
231 hapd->dpp_auth = NULL;
232 return;
233 }
234#endif /* CONFIG_DPP2 */
235
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700236 if (hapd->dpp_auth->remove_on_tx_status) {
237 wpa_printf(MSG_DEBUG,
238 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700239 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
240 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
241 hapd, NULL);
242 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
243 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700244#ifdef CONFIG_DPP2
245 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
246 hapd, NULL);
247#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700248 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700249 dpp_auth_deinit(hapd->dpp_auth);
250 hapd->dpp_auth = NULL;
251 return;
252 }
253
254 if (hapd->dpp_auth_ok_on_ack)
255 hostapd_dpp_auth_success(hapd, 1);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700256
257 if (!is_broadcast_ether_addr(dst) && !ok) {
258 wpa_printf(MSG_DEBUG,
259 "DPP: Unicast DPP Action frame was not ACKed");
260 if (auth->waiting_auth_resp) {
261 /* In case of DPP Authentication Request frame, move to
262 * the next channel immediately. */
263 hostapd_drv_send_action_cancel_wait(hapd);
264 hostapd_dpp_auth_init_next(hapd);
265 return;
266 }
267 if (auth->waiting_auth_conf) {
268 hostapd_dpp_auth_resp_retry(hapd);
269 return;
270 }
271 }
272
273 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
274 /* Allow timeout handling to stop iteration if no response is
275 * received from a peer that has ACKed a request. */
276 auth->auth_req_ack = 1;
277 }
278
279 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
280 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
281 wpa_printf(MSG_DEBUG,
282 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
283 hapd->dpp_auth->curr_freq,
284 hapd->dpp_auth->neg_freq);
285 hostapd_drv_send_action_cancel_wait(hapd);
286
287 if (hapd->dpp_auth->neg_freq !=
288 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
289 /* TODO: Listen operation on non-operating channel */
290 wpa_printf(MSG_INFO,
291 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
292 hapd->dpp_auth->neg_freq, hapd->iface->freq);
293 }
294 }
295
296 if (hapd->dpp_auth_ok_on_ack)
297 hapd->dpp_auth_ok_on_ack = 0;
298}
299
300
301static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
302{
303 struct hostapd_data *hapd = eloop_ctx;
304 struct dpp_authentication *auth = hapd->dpp_auth;
305 unsigned int freq;
306 struct os_reltime now, diff;
307 unsigned int wait_time, diff_ms;
308
309 if (!auth || !auth->waiting_auth_resp)
310 return;
311
312 wait_time = hapd->dpp_resp_wait_time ?
313 hapd->dpp_resp_wait_time : 2000;
314 os_get_reltime(&now);
315 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
316 diff_ms = diff.sec * 1000 + diff.usec / 1000;
317 wpa_printf(MSG_DEBUG,
318 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
319 wait_time, diff_ms);
320
321 if (auth->auth_req_ack && diff_ms >= wait_time) {
322 /* Peer ACK'ed Authentication Request frame, but did not reply
323 * with Authentication Response frame within two seconds. */
324 wpa_printf(MSG_INFO,
325 "DPP: No response received from responder - stopping initiation attempt");
326 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
327 hostapd_drv_send_action_cancel_wait(hapd);
328 hostapd_dpp_listen_stop(hapd);
329 dpp_auth_deinit(auth);
330 hapd->dpp_auth = NULL;
331 return;
332 }
333
334 if (diff_ms >= wait_time) {
335 /* Authentication Request frame was not ACK'ed and no reply
336 * was receiving within two seconds. */
337 wpa_printf(MSG_DEBUG,
338 "DPP: Continue Initiator channel iteration");
339 hostapd_drv_send_action_cancel_wait(hapd);
340 hostapd_dpp_listen_stop(hapd);
341 hostapd_dpp_auth_init_next(hapd);
342 return;
343 }
344
345 /* Driver did not support 2000 ms long wait_time with TX command, so
346 * schedule listen operation to continue waiting for the response.
347 *
348 * DPP listen operations continue until stopped, so simply schedule a
349 * new call to this function at the point when the two second reply
350 * wait has expired. */
351 wait_time -= diff_ms;
352
353 freq = auth->curr_freq;
354 if (auth->neg_freq > 0)
355 freq = auth->neg_freq;
356 wpa_printf(MSG_DEBUG,
357 "DPP: Continue reply wait on channel %u MHz for %u ms",
358 freq, wait_time);
359 hapd->dpp_in_response_listen = 1;
360
361 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
362 /* TODO: Listen operation on non-operating channel */
363 wpa_printf(MSG_INFO,
364 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
365 freq, hapd->iface->freq);
366 }
367
368 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
369 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700370}
371
372
373static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
374 struct dpp_authentication *auth)
375{
376#ifdef CONFIG_TESTING_OPTIONS
377 if (hapd->dpp_config_obj_override)
378 auth->config_obj_override =
379 os_strdup(hapd->dpp_config_obj_override);
380 if (hapd->dpp_discovery_override)
381 auth->discovery_override =
382 os_strdup(hapd->dpp_discovery_override);
383 if (hapd->dpp_groups_override)
384 auth->groups_override = os_strdup(hapd->dpp_groups_override);
385 auth->ignore_netaccesskey_mismatch =
386 hapd->dpp_ignore_netaccesskey_mismatch;
387#endif /* CONFIG_TESTING_OPTIONS */
388}
389
390
Roshan Pius3a1667e2018-07-03 15:17:14 -0700391static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
392{
393 struct hostapd_data *hapd = eloop_ctx;
394
395 if (!hapd->dpp_auth)
396 return;
397 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
398 hostapd_dpp_auth_init_next(hapd);
399}
400
401
402static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
403{
404 struct dpp_authentication *auth = hapd->dpp_auth;
405 const u8 *dst;
406 unsigned int wait_time, max_wait_time, freq, max_tries, used;
407 struct os_reltime now, diff;
408
409 if (!auth)
410 return -1;
411
412 if (auth->freq_idx == 0)
413 os_get_reltime(&hapd->dpp_init_iter_start);
414
415 if (auth->freq_idx >= auth->num_freq) {
416 auth->num_freq_iters++;
417 if (hapd->dpp_init_max_tries)
418 max_tries = hapd->dpp_init_max_tries;
419 else
420 max_tries = 5;
421 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
422 wpa_printf(MSG_INFO,
423 "DPP: No response received from responder - stopping initiation attempt");
424 wpa_msg(hapd->msg_ctx, MSG_INFO,
425 DPP_EVENT_AUTH_INIT_FAILED);
426 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
427 hapd, NULL);
428 hostapd_drv_send_action_cancel_wait(hapd);
429 dpp_auth_deinit(hapd->dpp_auth);
430 hapd->dpp_auth = NULL;
431 return -1;
432 }
433 auth->freq_idx = 0;
434 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
435 if (hapd->dpp_init_retry_time)
436 wait_time = hapd->dpp_init_retry_time;
437 else
438 wait_time = 10000;
439 os_get_reltime(&now);
440 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
441 used = diff.sec * 1000 + diff.usec / 1000;
442 if (used > wait_time)
443 wait_time = 0;
444 else
445 wait_time -= used;
446 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
447 wait_time);
448 eloop_register_timeout(wait_time / 1000,
449 (wait_time % 1000) * 1000,
450 hostapd_dpp_init_timeout, hapd,
451 NULL);
452 return 0;
453 }
454 freq = auth->freq[auth->freq_idx++];
455 auth->curr_freq = freq;
456
457 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
458 dst = broadcast;
459 else
460 dst = auth->peer_bi->mac_addr;
461 hapd->dpp_auth_ok_on_ack = 0;
462 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
463 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
464 max_wait_time = hapd->dpp_resp_wait_time ?
465 hapd->dpp_resp_wait_time : 2000;
466 if (wait_time > max_wait_time)
467 wait_time = max_wait_time;
468 wait_time += 10; /* give the driver some extra time to complete */
469 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
470 hostapd_dpp_reply_wait_timeout, hapd, NULL);
471 wait_time -= 10;
472 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
473 wpa_printf(MSG_DEBUG,
474 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
475 freq, auth->neg_freq);
476 }
477 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
478 " freq=%u type=%d",
479 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
480 auth->auth_req_ack = 0;
481 os_get_reltime(&hapd->dpp_last_init);
482 return hostapd_drv_send_action(hapd, freq, wait_time,
483 dst,
484 wpabuf_head(hapd->dpp_auth->req_msg),
485 wpabuf_len(hapd->dpp_auth->req_msg));
486}
487
488
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700489int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
490{
491 const char *pos;
492 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700493 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
494 unsigned int neg_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700495
496 pos = os_strstr(cmd, " peer=");
497 if (!pos)
498 return -1;
499 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700500 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700501 if (!peer_bi) {
502 wpa_printf(MSG_INFO,
503 "DPP: Could not find bootstrapping info for the identified peer");
504 return -1;
505 }
506
507 pos = os_strstr(cmd, " own=");
508 if (pos) {
509 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700510 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
511 atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700512 if (!own_bi) {
513 wpa_printf(MSG_INFO,
514 "DPP: Could not find bootstrapping info for the identified local entry");
515 return -1;
516 }
517
518 if (peer_bi->curve != own_bi->curve) {
519 wpa_printf(MSG_INFO,
520 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
521 peer_bi->curve->name, own_bi->curve->name);
522 return -1;
523 }
524 }
525
526 pos = os_strstr(cmd, " role=");
527 if (pos) {
528 pos += 6;
529 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700530 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700531 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700532 allowed_roles = DPP_CAPAB_ENROLLEE;
533 else if (os_strncmp(pos, "either", 6) == 0)
534 allowed_roles = DPP_CAPAB_CONFIGURATOR |
535 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700536 else
537 goto fail;
538 }
539
Roshan Pius3a1667e2018-07-03 15:17:14 -0700540 pos = os_strstr(cmd, " neg_freq=");
541 if (pos)
542 neg_freq = atoi(pos + 10);
543
544 if (hapd->dpp_auth) {
545 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
546 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
547 hapd, NULL);
548 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
549 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700550#ifdef CONFIG_DPP2
551 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
552 hapd, NULL);
553#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700554 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700555 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700556 }
557
Hai Shalomfdcde762020-04-02 11:19:20 -0700558 hapd->dpp_auth = dpp_auth_init(hapd->iface->interfaces->dpp,
559 hapd->msg_ctx, peer_bi, own_bi,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700560 allowed_roles, neg_freq,
561 hapd->iface->hw_features,
562 hapd->iface->num_hw_features);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700563 if (!hapd->dpp_auth)
564 goto fail;
565 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700566 if (dpp_set_configurator(hapd->dpp_auth, cmd) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800567 dpp_auth_deinit(hapd->dpp_auth);
568 hapd->dpp_auth = NULL;
569 goto fail;
570 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700571
Roshan Pius3a1667e2018-07-03 15:17:14 -0700572 hapd->dpp_auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700573
Roshan Pius3a1667e2018-07-03 15:17:14 -0700574 if (!is_zero_ether_addr(peer_bi->mac_addr))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700575 os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
576 ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700577
Roshan Pius3a1667e2018-07-03 15:17:14 -0700578 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700579fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700580 return -1;
581}
582
583
Roshan Pius3a1667e2018-07-03 15:17:14 -0700584int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
585{
586 int freq;
587
588 freq = atoi(cmd);
589 if (freq <= 0)
590 return -1;
591
592 if (os_strstr(cmd, " role=configurator"))
593 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
594 else if (os_strstr(cmd, " role=enrollee"))
595 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
596 else
597 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
598 DPP_CAPAB_ENROLLEE;
599 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
600
601 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
602 /* TODO: Listen operation on non-operating channel */
603 wpa_printf(MSG_INFO,
604 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
605 freq, hapd->iface->freq);
606 return -1;
607 }
608
609 return 0;
610}
611
612
613void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
614{
615 /* TODO: Stop listen operation on non-operating channel */
616}
617
618
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700619static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
620 const u8 *hdr, const u8 *buf, size_t len,
621 unsigned int freq)
622{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700623 const u8 *r_bootstrap, *i_bootstrap;
624 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700625 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
626
627 if (!hapd->iface->interfaces->dpp)
628 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700629
630 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
631 MAC2STR(src));
632
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700633#ifdef CONFIG_DPP2
634 hostapd_dpp_chirp_stop(hapd);
635#endif /* CONFIG_DPP2 */
636
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700637 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
638 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700639 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
640 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
641 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700642 return;
643 }
644 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
645 r_bootstrap, r_bootstrap_len);
646
647 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
648 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700649 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
650 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
651 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700652 return;
653 }
654 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
655 i_bootstrap, i_bootstrap_len);
656
657 /* Try to find own and peer bootstrapping key matches based on the
658 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -0700659 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
660 r_bootstrap, &own_bi, &peer_bi);
Hai Shalom81f62d82019-07-22 12:10:00 -0700661#ifdef CONFIG_DPP2
662 if (!own_bi) {
663 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
664 src, hdr, buf, len, freq, i_bootstrap,
665 r_bootstrap) == 0)
666 return;
667 }
668#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700669 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700670 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
671 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700672 return;
673 }
674
675 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700676 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
677 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700678 return;
679 }
680
681 hapd->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -0700682 hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
683 hapd->msg_ctx, hapd->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700684 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700685 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700686 if (!hapd->dpp_auth) {
687 wpa_printf(MSG_DEBUG, "DPP: No response generated");
688 return;
689 }
690 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700691 if (dpp_set_configurator(hapd->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -0700692 hapd->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800693 dpp_auth_deinit(hapd->dpp_auth);
694 hapd->dpp_auth = NULL;
695 return;
696 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700697 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
698
Roshan Pius3a1667e2018-07-03 15:17:14 -0700699 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
700 " freq=%u type=%d",
701 MAC2STR(src), hapd->dpp_auth->curr_freq,
702 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700703 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
704 src, wpabuf_head(hapd->dpp_auth->resp_msg),
705 wpabuf_len(hapd->dpp_auth->resp_msg));
706}
707
708
Roshan Pius3a1667e2018-07-03 15:17:14 -0700709static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
Hai Shalomc3565922019-10-28 11:58:20 -0700710 struct dpp_authentication *auth,
711 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700712{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700713 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700714 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700715 dpp_akm_str(conf->akm));
716 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700717 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700718 wpa_ssid_txt(conf->ssid, conf->ssid_len));
719 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700720 /* TODO: Save the Connector and consider using a command
721 * to fetch the value instead of sending an event with
722 * it. The Connector could end up being larger than what
723 * most clients are ready to receive as an event
724 * message. */
725 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700726 conf->connector);
Hai Shalomfdcde762020-04-02 11:19:20 -0700727 }
728 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700729 char hex[64 * 2 + 1];
730
731 wpa_snprintf_hex(hex, sizeof(hex),
Hai Shalomc3565922019-10-28 11:58:20 -0700732 (const u8 *) conf->passphrase,
733 os_strlen(conf->passphrase));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700734 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
735 hex);
Hai Shalomc3565922019-10-28 11:58:20 -0700736 } else if (conf->psk_set) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700737 char hex[PMK_LEN * 2 + 1];
738
Hai Shalomc3565922019-10-28 11:58:20 -0700739 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700740 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
741 hex);
742 }
Hai Shalomc3565922019-10-28 11:58:20 -0700743 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700744 char *hex;
745 size_t hexlen;
746
Hai Shalomc3565922019-10-28 11:58:20 -0700747 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700748 hex = os_malloc(hexlen);
749 if (hex) {
750 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -0700751 wpabuf_head(conf->c_sign_key),
752 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700753 wpa_msg(hapd->msg_ctx, MSG_INFO,
754 DPP_EVENT_C_SIGN_KEY "%s", hex);
755 os_free(hex);
756 }
757 }
758 if (auth->net_access_key) {
759 char *hex;
760 size_t hexlen;
761
762 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
763 hex = os_malloc(hexlen);
764 if (hex) {
765 wpa_snprintf_hex(hex, hexlen,
766 wpabuf_head(auth->net_access_key),
767 wpabuf_len(auth->net_access_key));
768 if (auth->net_access_key_expiry)
769 wpa_msg(hapd->msg_ctx, MSG_INFO,
770 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
771 (unsigned long)
772 auth->net_access_key_expiry);
773 else
774 wpa_msg(hapd->msg_ctx, MSG_INFO,
775 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
776 os_free(hex);
777 }
778 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700779}
780
781
Hai Shalomfdcde762020-04-02 11:19:20 -0700782static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
783 struct dpp_asymmetric_key *key)
784{
785#ifdef CONFIG_DPP2
786 int res;
787
788 if (!key)
789 return 0;
790
791 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
792 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
793
794 while (key) {
795 res = dpp_configurator_from_backup(
796 hapd->iface->interfaces->dpp, key);
797 if (res < 0)
798 return -1;
799 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
800 res);
801 key = key->next;
802 }
803#endif /* CONFIG_DPP2 */
804
805 return 0;
806}
807
808
Roshan Pius3a1667e2018-07-03 15:17:14 -0700809static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
810 enum gas_query_ap_result result,
811 const struct wpabuf *adv_proto,
812 const struct wpabuf *resp, u16 status_code)
813{
814 struct hostapd_data *hapd = ctx;
815 const u8 *pos;
816 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -0700817 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700818
819 if (!auth || !auth->auth_success) {
820 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
821 return;
822 }
823 if (!resp || status_code != WLAN_STATUS_SUCCESS) {
824 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
825 goto fail;
826 }
827
828 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
829 adv_proto);
830 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
831 resp);
832
833 if (wpabuf_len(adv_proto) != 10 ||
834 !(pos = wpabuf_head(adv_proto)) ||
835 pos[0] != WLAN_EID_ADV_PROTO ||
836 pos[1] != 8 ||
837 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
838 pos[4] != 5 ||
839 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
840 pos[8] != 0x1a ||
841 pos[9] != 1) {
842 wpa_printf(MSG_DEBUG,
843 "DPP: Not a DPP Advertisement Protocol ID");
844 goto fail;
845 }
846
847 if (dpp_conf_resp_rx(auth, resp) < 0) {
848 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
849 goto fail;
850 }
851
Hai Shalomc3565922019-10-28 11:58:20 -0700852 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Hai Shalomfdcde762020-04-02 11:19:20 -0700853 if (hostapd_dpp_handle_key_pkg(hapd, auth->conf_key_pkg) < 0)
854 goto fail;
855
Hai Shalom021b0b52019-04-10 11:17:58 -0700856 status = DPP_STATUS_OK;
857#ifdef CONFIG_TESTING_OPTIONS
858 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
859 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
860 status = DPP_STATUS_CONFIG_REJECTED;
861 }
862#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700863fail:
Hai Shalom021b0b52019-04-10 11:17:58 -0700864 if (status != DPP_STATUS_OK)
865 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
866#ifdef CONFIG_DPP2
867 if (auth->peer_version >= 2 &&
868 auth->conf_resp_status == DPP_STATUS_OK) {
869 struct wpabuf *msg;
870
871 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
872 msg = dpp_build_conf_result(auth, status);
873 if (!msg)
874 goto fail2;
875
876 wpa_msg(hapd->msg_ctx, MSG_INFO,
877 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
878 MAC2STR(addr), auth->curr_freq,
879 DPP_PA_CONFIGURATION_RESULT);
880 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
881 addr, wpabuf_head(msg),
882 wpabuf_len(msg));
883 wpabuf_free(msg);
884
885 /* This exchange will be terminated in the TX status handler */
886 auth->connect_on_tx_status = 1;
887 return;
888 }
889fail2:
890#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700891 dpp_auth_deinit(hapd->dpp_auth);
892 hapd->dpp_auth = NULL;
893}
894
895
896static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
897{
898 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -0700899 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700900 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700901
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800902 buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
903 DPP_NETROLE_AP,
Hai Shalomc3565922019-10-28 11:58:20 -0700904 hapd->conf->dpp_mud_url, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -0700905 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700906 wpa_printf(MSG_DEBUG,
907 "DPP: No configuration request data available");
908 return;
909 }
910
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700911 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
912 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
913
914 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
915 buf, hostapd_dpp_gas_resp_cb, hapd);
916 if (res < 0) {
917 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
918 "GAS: Failed to send Query Request");
919 wpabuf_free(buf);
920 } else {
921 wpa_printf(MSG_DEBUG,
922 "DPP: GAS query started with dialog token %u", res);
923 }
924}
925
926
927static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
928{
929 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
930 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
931 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700932#ifdef CONFIG_TESTING_OPTIONS
933 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
934 wpa_printf(MSG_INFO,
935 "DPP: TESTING - stop at Authentication Confirm");
936 if (hapd->dpp_auth->configurator) {
937 /* Prevent GAS response */
938 hapd->dpp_auth->auth_success = 0;
939 }
940 return;
941 }
942#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700943
944 if (!hapd->dpp_auth->configurator)
945 hostapd_dpp_start_gas_client(hapd);
946}
947
948
949static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700950 const u8 *hdr, const u8 *buf, size_t len,
951 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700952{
953 struct dpp_authentication *auth = hapd->dpp_auth;
954 struct wpabuf *msg;
955
956 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
957 MAC2STR(src));
958
959 if (!auth) {
960 wpa_printf(MSG_DEBUG,
961 "DPP: No DPP Authentication in progress - drop");
962 return;
963 }
964
965 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
966 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
967 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
968 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
969 return;
970 }
971
Roshan Pius3a1667e2018-07-03 15:17:14 -0700972 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
973
974 if (auth->curr_freq != freq && auth->neg_freq == freq) {
975 wpa_printf(MSG_DEBUG,
976 "DPP: Responder accepted request for different negotiation channel");
977 auth->curr_freq = freq;
978 }
979
980 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700981 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
982 if (!msg) {
983 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
984 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
985 return;
986 }
987 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
988 return;
989 }
990 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
991
Roshan Pius3a1667e2018-07-03 15:17:14 -0700992 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
993 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
994 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700995 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
996 wpabuf_head(msg), wpabuf_len(msg));
997 wpabuf_free(msg);
998 hapd->dpp_auth_ok_on_ack = 1;
999}
1000
1001
1002static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1003 const u8 *hdr, const u8 *buf, size_t len)
1004{
1005 struct dpp_authentication *auth = hapd->dpp_auth;
1006
1007 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1008 MAC2STR(src));
1009
1010 if (!auth) {
1011 wpa_printf(MSG_DEBUG,
1012 "DPP: No DPP Authentication in progress - drop");
1013 return;
1014 }
1015
1016 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1017 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1018 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1019 return;
1020 }
1021
1022 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1023 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1024 return;
1025 }
1026
1027 hostapd_dpp_auth_success(hapd, 0);
1028}
1029
1030
Hai Shalom021b0b52019-04-10 11:17:58 -07001031#ifdef CONFIG_DPP2
1032
1033static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
1034 void *timeout_ctx)
1035{
1036 struct hostapd_data *hapd = eloop_ctx;
1037 struct dpp_authentication *auth = hapd->dpp_auth;
1038
1039 if (!auth || !auth->waiting_conf_result)
1040 return;
1041
1042 wpa_printf(MSG_DEBUG,
1043 "DPP: Timeout while waiting for Configuration Result");
1044 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1045 dpp_auth_deinit(auth);
1046 hapd->dpp_auth = NULL;
1047}
1048
1049
Hai Shalomc3565922019-10-28 11:58:20 -07001050static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1051 void *timeout_ctx)
1052{
1053 struct hostapd_data *hapd = eloop_ctx;
1054 struct dpp_authentication *auth = hapd->dpp_auth;
1055
1056 if (!auth || !auth->waiting_conf_result)
1057 return;
1058
1059 wpa_printf(MSG_DEBUG,
1060 "DPP: Timeout while waiting for Connection Status Result");
1061 wpa_msg(hapd->msg_ctx, MSG_INFO,
1062 DPP_EVENT_CONN_STATUS_RESULT "timeout");
1063 dpp_auth_deinit(auth);
1064 hapd->dpp_auth = NULL;
1065}
1066
1067
Hai Shalom021b0b52019-04-10 11:17:58 -07001068static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
1069 const u8 *hdr, const u8 *buf, size_t len)
1070{
1071 struct dpp_authentication *auth = hapd->dpp_auth;
1072 enum dpp_status_error status;
1073
1074 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1075 MAC2STR(src));
1076
1077 if (!auth || !auth->waiting_conf_result) {
1078 wpa_printf(MSG_DEBUG,
1079 "DPP: No DPP Configuration waiting for result - drop");
1080 return;
1081 }
1082
1083 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1084 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1085 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1086 return;
1087 }
1088
1089 status = dpp_conf_result_rx(auth, hdr, buf, len);
1090
Hai Shalomc3565922019-10-28 11:58:20 -07001091 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1092 wpa_msg(hapd->msg_ctx, MSG_INFO,
1093 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1094 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1095 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1096 hapd, NULL);
1097 eloop_cancel_timeout(
1098 hostapd_dpp_conn_status_result_wait_timeout,
1099 hapd, NULL);
1100 eloop_register_timeout(
1101 16, 0, hostapd_dpp_conn_status_result_wait_timeout,
1102 hapd, NULL);
1103 return;
1104 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001105 hostapd_drv_send_action_cancel_wait(hapd);
1106 hostapd_dpp_listen_stop(hapd);
1107 if (status == DPP_STATUS_OK)
1108 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1109 else
1110 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1111 dpp_auth_deinit(auth);
1112 hapd->dpp_auth = NULL;
1113 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1114 NULL);
1115}
1116
Hai Shalomc3565922019-10-28 11:58:20 -07001117
1118static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
1119 const u8 *src, const u8 *hdr,
1120 const u8 *buf, size_t len)
1121{
1122 struct dpp_authentication *auth = hapd->dpp_auth;
1123 enum dpp_status_error status;
1124 u8 ssid[SSID_MAX_LEN];
1125 size_t ssid_len = 0;
1126 char *channel_list = NULL;
1127
1128 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1129
1130 if (!auth || !auth->waiting_conn_status_result) {
1131 wpa_printf(MSG_DEBUG,
1132 "DPP: No DPP Configuration waiting for connection status result - drop");
1133 return;
1134 }
1135
1136 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1137 ssid, &ssid_len, &channel_list);
1138 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1139 "result=%d ssid=%s channel_list=%s",
1140 status, wpa_ssid_txt(ssid, ssid_len),
1141 channel_list ? channel_list : "N/A");
1142 os_free(channel_list);
1143 hostapd_drv_send_action_cancel_wait(hapd);
1144 hostapd_dpp_listen_stop(hapd);
1145 dpp_auth_deinit(auth);
1146 hapd->dpp_auth = NULL;
1147 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
1148 hapd, NULL);
1149}
1150
1151
Hai Shalomfdcde762020-04-02 11:19:20 -07001152static void
1153hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
1154 const u8 *hdr, const u8 *buf, size_t len,
1155 unsigned int freq)
1156{
1157 const u8 *r_bootstrap;
1158 u16 r_bootstrap_len;
1159 struct dpp_bootstrap_info *peer_bi;
1160 struct dpp_authentication *auth;
1161
1162 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
1163 MAC2STR(src));
1164
1165 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1166 &r_bootstrap_len);
1167 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1168 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1169 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1170 return;
1171 }
1172 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1173 r_bootstrap, r_bootstrap_len);
1174 peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
1175 r_bootstrap);
1176 if (!peer_bi) {
1177 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1178 src, hdr, buf, len, freq, NULL,
1179 r_bootstrap) == 0)
1180 return;
1181 wpa_printf(MSG_DEBUG,
1182 "DPP: No matching bootstrapping information found");
1183 return;
1184 }
1185
1186 if (hapd->dpp_auth) {
1187 wpa_printf(MSG_DEBUG,
1188 "DPP: Ignore Presence Announcement during ongoing Authentication");
1189 return;
1190 }
1191
1192 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1193 peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
1194 0);
1195 if (!auth)
1196 return;
1197 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
1198 if (dpp_set_configurator(hapd->dpp_auth,
1199 hapd->dpp_configurator_params) < 0) {
1200 dpp_auth_deinit(auth);
1201 return;
1202 }
1203
1204 auth->neg_freq = freq;
1205
1206 if (!is_zero_ether_addr(peer_bi->mac_addr))
1207 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
1208
1209 hapd->dpp_auth = auth;
1210 if (hostapd_dpp_auth_init_next(hapd) < 0) {
1211 dpp_auth_deinit(hapd->dpp_auth);
1212 hapd->dpp_auth = NULL;
1213 }
1214}
1215
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001216
1217static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
1218 void *timeout_ctx)
1219{
1220 struct hostapd_data *hapd = eloop_ctx;
1221 struct dpp_authentication *auth = hapd->dpp_auth;
1222
1223 if (!auth)
1224 return;
1225
1226 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
1227 hostapd_dpp_listen_stop(hapd);
1228 dpp_auth_deinit(auth);
1229 hapd->dpp_auth = NULL;
1230}
1231
1232
1233static void
1234hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
1235 const u8 *hdr, const u8 *buf, size_t len,
1236 unsigned int freq)
1237{
1238 const u8 *csign_hash;
1239 u16 csign_hash_len;
1240 struct dpp_configurator *conf;
1241 struct dpp_authentication *auth;
1242 unsigned int wait_time, max_wait_time;
1243
1244 if (hapd->dpp_auth) {
1245 wpa_printf(MSG_DEBUG,
1246 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1247 return;
1248 }
1249
1250 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
1251 MAC2STR(src));
1252
1253 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1254 &csign_hash_len);
1255 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
1256 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1257 "Missing or invalid required Configurator C-sign key Hash attribute");
1258 return;
1259 }
1260 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1261 csign_hash, csign_hash_len);
1262 conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
1263 csign_hash);
1264 if (!conf) {
1265 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1266 src, hdr, buf, len, freq, NULL,
1267 NULL) == 0)
1268 return;
1269 wpa_printf(MSG_DEBUG,
1270 "DPP: No matching Configurator information found");
1271 return;
1272 }
1273
1274 auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1275 conf, freq);
1276 if (!auth)
1277 return;
1278 hostapd_dpp_set_testing_options(hapd, auth);
1279 if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
1280 dpp_auth_deinit(auth);
1281 return;
1282 }
1283
1284 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1285 hapd->dpp_auth = auth;
1286
1287 hapd->dpp_in_response_listen = 0;
1288 hapd->dpp_auth_ok_on_ack = 0;
1289 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
1290 max_wait_time = hapd->dpp_resp_wait_time ?
1291 hapd->dpp_resp_wait_time : 2000;
1292 if (wait_time > max_wait_time)
1293 wait_time = max_wait_time;
1294 wait_time += 10; /* give the driver some extra time to complete */
1295 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
1296 hostapd_dpp_reconfig_reply_wait_timeout,
1297 hapd, NULL);
1298 wait_time -= 10;
1299
1300 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1301 " freq=%u type=%d",
1302 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
1303 if (hostapd_drv_send_action(hapd, freq, wait_time, src,
1304 wpabuf_head(auth->reconfig_req_msg),
1305 wpabuf_len(auth->reconfig_req_msg)) < 0) {
1306 dpp_auth_deinit(hapd->dpp_auth);
1307 hapd->dpp_auth = NULL;
1308 }
1309}
1310
1311
1312static void
1313hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
1314 const u8 *hdr, const u8 *buf, size_t len,
1315 unsigned int freq)
1316{
1317 struct dpp_authentication *auth = hapd->dpp_auth;
1318 struct wpabuf *conf;
1319
1320 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
1321 MACSTR, MAC2STR(src));
1322
1323 if (!auth || !auth->reconfig || !auth->configurator) {
1324 wpa_printf(MSG_DEBUG,
1325 "DPP: No DPP Reconfig Authentication in progress - drop");
1326 return;
1327 }
1328
1329 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1330 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1331 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1332 return;
1333 }
1334
1335 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
1336 if (!conf)
1337 return;
1338
1339 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1340 hapd, NULL);
1341
1342 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1343 " freq=%u type=%d",
1344 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
1345 if (hostapd_drv_send_action(hapd, freq, 500, src,
1346 wpabuf_head(conf), wpabuf_len(conf)) < 0) {
1347 wpabuf_free(conf);
1348 dpp_auth_deinit(hapd->dpp_auth);
1349 hapd->dpp_auth = NULL;
1350 return;
1351 }
1352 wpabuf_free(conf);
1353}
1354
Hai Shalom021b0b52019-04-10 11:17:58 -07001355#endif /* CONFIG_DPP2 */
1356
1357
Roshan Pius3a1667e2018-07-03 15:17:14 -07001358static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1359 const u8 *src, unsigned int freq,
1360 u8 trans_id,
1361 enum dpp_status_error status)
1362{
1363 struct wpabuf *msg;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001364 size_t len;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001365
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001366 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
1367#ifdef CONFIG_DPP2
1368 len += 5;
1369#endif /* CONFIG_DPP2 */
1370 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001371 if (!msg)
1372 return;
1373
1374#ifdef CONFIG_TESTING_OPTIONS
1375 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1376 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1377 goto skip_trans_id;
1378 }
1379 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1380 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1381 trans_id ^= 0x01;
1382 }
1383#endif /* CONFIG_TESTING_OPTIONS */
1384
1385 /* Transaction ID */
1386 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1387 wpabuf_put_le16(msg, 1);
1388 wpabuf_put_u8(msg, trans_id);
1389
1390#ifdef CONFIG_TESTING_OPTIONS
1391skip_trans_id:
1392 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1393 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1394 goto skip_status;
1395 }
1396 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1397 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1398 status = 254;
1399 }
1400#endif /* CONFIG_TESTING_OPTIONS */
1401
1402 /* DPP Status */
1403 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1404 wpabuf_put_le16(msg, 1);
1405 wpabuf_put_u8(msg, status);
1406
1407#ifdef CONFIG_TESTING_OPTIONS
1408skip_status:
1409 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1410 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1411 goto skip_connector;
1412 }
1413 if (status == DPP_STATUS_OK &&
1414 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1415 char *connector;
1416
1417 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1418 connector = dpp_corrupt_connector_signature(
1419 hapd->conf->dpp_connector);
1420 if (!connector) {
1421 wpabuf_free(msg);
1422 return;
1423 }
1424 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1425 wpabuf_put_le16(msg, os_strlen(connector));
1426 wpabuf_put_str(msg, connector);
1427 os_free(connector);
1428 goto skip_connector;
1429 }
1430#endif /* CONFIG_TESTING_OPTIONS */
1431
1432 /* DPP Connector */
1433 if (status == DPP_STATUS_OK) {
1434 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1435 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1436 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1437 }
1438
1439#ifdef CONFIG_TESTING_OPTIONS
1440skip_connector:
1441#endif /* CONFIG_TESTING_OPTIONS */
1442
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001443#ifdef CONFIG_DPP2
1444 if (DPP_VERSION > 1) {
1445 /* Protocol Version */
1446 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
1447 wpabuf_put_le16(msg, 1);
1448 wpabuf_put_u8(msg, DPP_VERSION);
1449 }
1450#endif /* CONFIG_DPP2 */
1451
Roshan Pius3a1667e2018-07-03 15:17:14 -07001452 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1453 " status=%d", MAC2STR(src), status);
1454 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1455 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1456 DPP_PA_PEER_DISCOVERY_RESP, status);
1457 hostapd_drv_send_action(hapd, freq, 0, src,
1458 wpabuf_head(msg), wpabuf_len(msg));
1459 wpabuf_free(msg);
1460}
1461
1462
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001463static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1464 const u8 *src,
1465 const u8 *buf, size_t len,
1466 unsigned int freq)
1467{
1468 const u8 *connector, *trans_id;
1469 u16 connector_len, trans_id_len;
1470 struct os_time now;
1471 struct dpp_introduction intro;
1472 os_time_t expire;
1473 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001474 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001475
1476 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1477 MAC2STR(src));
1478 if (!hapd->wpa_auth ||
1479 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1480 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1481 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1482 return;
1483 }
1484
1485 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1486 !hapd->conf->dpp_csign) {
1487 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1488 return;
1489 }
1490
1491 os_get_time(&now);
1492
1493 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001494 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001495 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1496 return;
1497 }
1498
1499 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1500 &trans_id_len);
1501 if (!trans_id || trans_id_len != 1) {
1502 wpa_printf(MSG_DEBUG,
1503 "DPP: Peer did not include Transaction ID");
1504 return;
1505 }
1506
1507 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1508 if (!connector) {
1509 wpa_printf(MSG_DEBUG,
1510 "DPP: Peer did not include its Connector");
1511 return;
1512 }
1513
Roshan Pius3a1667e2018-07-03 15:17:14 -07001514 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1515 wpabuf_head(hapd->conf->dpp_netaccesskey),
1516 wpabuf_len(hapd->conf->dpp_netaccesskey),
1517 wpabuf_head(hapd->conf->dpp_csign),
1518 wpabuf_len(hapd->conf->dpp_csign),
1519 connector, connector_len, &expire);
1520 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001521 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001522 "DPP: Network Introduction protocol resulted in internal failure (peer "
1523 MACSTR ")", MAC2STR(src));
1524 return;
1525 }
1526 if (res != DPP_STATUS_OK) {
1527 wpa_printf(MSG_INFO,
1528 "DPP: Network Introduction protocol resulted in failure (peer "
1529 MACSTR " status %d)", MAC2STR(src), res);
1530 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1531 res);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001532 return;
1533 }
1534
Roshan Pius3a1667e2018-07-03 15:17:14 -07001535 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001536 expire = hapd->conf->dpp_netaccesskey_expiry;
1537 if (expire)
1538 expiration = expire - now.sec;
1539 else
1540 expiration = 0;
1541
1542 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1543 intro.pmkid, expiration,
1544 WPA_KEY_MGMT_DPP) < 0) {
1545 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
1546 return;
1547 }
1548
Roshan Pius3a1667e2018-07-03 15:17:14 -07001549 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1550 DPP_STATUS_OK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001551}
1552
1553
1554static void
1555hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
1556 const u8 *buf, size_t len,
1557 unsigned int freq)
1558{
1559 struct wpabuf *msg;
1560
1561 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1562 MAC2STR(src));
1563
1564 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1565 * values here */
1566
1567 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
1568 wpa_printf(MSG_DEBUG,
1569 "DPP: No PKEX code configured - ignore request");
1570 return;
1571 }
1572
1573 if (hapd->dpp_pkex) {
1574 /* TODO: Support parallel operations */
1575 wpa_printf(MSG_DEBUG,
1576 "DPP: Already in PKEX session - ignore new request");
1577 return;
1578 }
1579
Roshan Pius3a1667e2018-07-03 15:17:14 -07001580 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
1581 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001582 hapd->own_addr, src,
1583 hapd->dpp_pkex_identifier,
1584 hapd->dpp_pkex_code,
1585 buf, len);
1586 if (!hapd->dpp_pkex) {
1587 wpa_printf(MSG_DEBUG,
1588 "DPP: Failed to process the request - ignore it");
1589 return;
1590 }
1591
1592 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001593 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1594 " freq=%u type=%d", MAC2STR(src), freq,
1595 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001596 hostapd_drv_send_action(hapd, freq, 0, src,
1597 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001598 if (hapd->dpp_pkex->failed) {
1599 wpa_printf(MSG_DEBUG,
1600 "DPP: Terminate PKEX exchange due to an earlier error");
1601 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1602 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
1603 dpp_pkex_free(hapd->dpp_pkex);
1604 hapd->dpp_pkex = NULL;
1605 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001606}
1607
1608
1609static void
1610hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
1611 const u8 *buf, size_t len, unsigned int freq)
1612{
1613 struct wpabuf *msg;
1614
1615 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1616 MAC2STR(src));
1617
1618 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1619 * values here */
1620
1621 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
1622 hapd->dpp_pkex->exchange_done) {
1623 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1624 return;
1625 }
1626
Roshan Pius3a1667e2018-07-03 15:17:14 -07001627 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001628 if (!msg) {
1629 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1630 return;
1631 }
1632
1633 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1634 MAC2STR(src));
1635
Roshan Pius3a1667e2018-07-03 15:17:14 -07001636 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1637 " freq=%u type=%d", MAC2STR(src), freq,
1638 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001639 hostapd_drv_send_action(hapd, freq, 0, src,
1640 wpabuf_head(msg), wpabuf_len(msg));
1641 wpabuf_free(msg);
1642}
1643
1644
1645static void
1646hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
1647 const u8 *hdr, const u8 *buf, size_t len,
1648 unsigned int freq)
1649{
1650 struct wpabuf *msg;
1651 struct dpp_pkex *pkex = hapd->dpp_pkex;
1652 struct dpp_bootstrap_info *bi;
1653
1654 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1655 MAC2STR(src));
1656
1657 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1658 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1659 return;
1660 }
1661
1662 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1663 if (!msg) {
1664 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001665 if (hapd->dpp_pkex->failed) {
1666 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1667 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1668 hapd->dpp_pkex->own_bi->pkex_t =
1669 hapd->dpp_pkex->t;
1670 dpp_pkex_free(hapd->dpp_pkex);
1671 hapd->dpp_pkex = NULL;
1672 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001673 return;
1674 }
1675
1676 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1677 MACSTR, MAC2STR(src));
1678
Roshan Pius3a1667e2018-07-03 15:17:14 -07001679 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1680 " freq=%u type=%d", MAC2STR(src), freq,
1681 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001682 hostapd_drv_send_action(hapd, freq, 0, src,
1683 wpabuf_head(msg), wpabuf_len(msg));
1684 wpabuf_free(msg);
1685
Hai Shalom021b0b52019-04-10 11:17:58 -07001686 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001687 if (!bi)
1688 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001689 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001690}
1691
1692
1693static void
1694hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
1695 const u8 *hdr, const u8 *buf, size_t len,
1696 unsigned int freq)
1697{
1698 int res;
Hai Shalom021b0b52019-04-10 11:17:58 -07001699 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001700 struct dpp_pkex *pkex = hapd->dpp_pkex;
1701 char cmd[500];
1702
1703 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
1704 MAC2STR(src));
1705
1706 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1707 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1708 return;
1709 }
1710
1711 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1712 if (res < 0) {
1713 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1714 return;
1715 }
1716
Hai Shalom021b0b52019-04-10 11:17:58 -07001717 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001718 if (!bi)
1719 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001720 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001721
1722 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
1723 bi->id,
1724 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
1725 wpa_printf(MSG_DEBUG,
1726 "DPP: Start authentication after PKEX with parameters: %s",
1727 cmd);
1728 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
1729 wpa_printf(MSG_DEBUG,
1730 "DPP: Authentication initialization failed");
1731 return;
1732 }
1733}
1734
1735
1736void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
1737 const u8 *buf, size_t len, unsigned int freq)
1738{
1739 u8 crypto_suite;
1740 enum dpp_public_action_frame_type type;
1741 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001742 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001743
1744 if (len < DPP_HDR_LEN)
1745 return;
1746 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
1747 return;
1748 hdr = buf;
1749 buf += 4;
1750 len -= 4;
1751 crypto_suite = *buf++;
1752 type = *buf++;
1753 len -= 2;
1754
1755 wpa_printf(MSG_DEBUG,
1756 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
1757 MACSTR " freq=%u",
1758 crypto_suite, type, MAC2STR(src), freq);
1759 if (crypto_suite != 1) {
1760 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
1761 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001762 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1763 " freq=%u type=%d ignore=unsupported-crypto-suite",
1764 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001765 return;
1766 }
1767 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001768 if (dpp_check_attrs(buf, len) < 0) {
1769 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1770 " freq=%u type=%d ignore=invalid-attributes",
1771 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001772 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001773 }
1774 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1775 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001776
Hai Shalom81f62d82019-07-22 12:10:00 -07001777#ifdef CONFIG_DPP2
1778 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1779 src, hdr, buf, len, freq, NULL, NULL) == 0)
1780 return;
1781#endif /* CONFIG_DPP2 */
1782
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001783 switch (type) {
1784 case DPP_PA_AUTHENTICATION_REQ:
1785 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
1786 break;
1787 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07001788 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001789 break;
1790 case DPP_PA_AUTHENTICATION_CONF:
1791 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
1792 break;
1793 case DPP_PA_PEER_DISCOVERY_REQ:
1794 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
1795 break;
1796 case DPP_PA_PKEX_EXCHANGE_REQ:
1797 hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
1798 break;
1799 case DPP_PA_PKEX_EXCHANGE_RESP:
1800 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
1801 break;
1802 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1803 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
1804 freq);
1805 break;
1806 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1807 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
1808 freq);
1809 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07001810#ifdef CONFIG_DPP2
1811 case DPP_PA_CONFIGURATION_RESULT:
1812 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
1813 break;
Hai Shalomc3565922019-10-28 11:58:20 -07001814 case DPP_PA_CONNECTION_STATUS_RESULT:
1815 hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
1816 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07001817 case DPP_PA_PRESENCE_ANNOUNCEMENT:
1818 hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
1819 freq);
1820 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001821 case DPP_PA_RECONFIG_ANNOUNCEMENT:
1822 hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
1823 freq);
1824 break;
1825 case DPP_PA_RECONFIG_AUTH_RESP:
1826 hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
1827 freq);
1828 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07001829#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001830 default:
1831 wpa_printf(MSG_DEBUG,
1832 "DPP: Ignored unsupported frame subtype %d", type);
1833 break;
1834 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001835
1836 if (hapd->dpp_pkex)
1837 pkex_t = hapd->dpp_pkex->t;
1838 else if (hapd->dpp_pkex_bi)
1839 pkex_t = hapd->dpp_pkex_bi->pkex_t;
1840 else
1841 pkex_t = 0;
1842 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
1843 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
1844 hostapd_dpp_pkex_remove(hapd, "*");
1845 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001846}
1847
1848
1849struct wpabuf *
1850hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
Hai Shalom81f62d82019-07-22 12:10:00 -07001851 const u8 *query, size_t query_len,
1852 const u8 *data, size_t data_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001853{
1854 struct dpp_authentication *auth = hapd->dpp_auth;
1855 struct wpabuf *resp;
1856
1857 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001858 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001859 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07001860#ifdef CONFIG_DPP2
1861 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
1862 data_len) == 0) {
1863 /* Response will be forwarded once received over TCP */
1864 return NULL;
1865 }
1866#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001867 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1868 return NULL;
1869 }
1870 wpa_hexdump(MSG_DEBUG,
1871 "DPP: Received Configuration Request (GAS Query Request)",
1872 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001873 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
1874 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001875 resp = dpp_conf_req_rx(auth, query, query_len);
1876 if (!resp)
1877 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1878 return resp;
1879}
1880
1881
Roshan Pius3a1667e2018-07-03 15:17:14 -07001882void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
1883{
Hai Shalom021b0b52019-04-10 11:17:58 -07001884 struct dpp_authentication *auth = hapd->dpp_auth;
1885
1886 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001887 return;
1888
Hai Shalom021b0b52019-04-10 11:17:58 -07001889 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
1890 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001891 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1892 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001893#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001894 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1895 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001896 if (ok && auth->peer_version >= 2 &&
1897 auth->conf_resp_status == DPP_STATUS_OK) {
1898 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
1899 auth->waiting_conf_result = 1;
1900 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1901 hapd, NULL);
1902 eloop_register_timeout(2, 0,
1903 hostapd_dpp_config_result_wait_timeout,
1904 hapd, NULL);
1905 return;
1906 }
1907#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001908 hostapd_drv_send_action_cancel_wait(hapd);
1909
1910 if (ok)
1911 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1912 else
1913 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1914 dpp_auth_deinit(hapd->dpp_auth);
1915 hapd->dpp_auth = NULL;
1916}
1917
1918
Roshan Pius3a1667e2018-07-03 15:17:14 -07001919int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
1920{
1921 struct dpp_authentication *auth;
1922 int ret = -1;
1923 char *curve = NULL;
1924
Hai Shalomfdcde762020-04-02 11:19:20 -07001925 auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001926 if (!auth)
1927 return -1;
1928
1929 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08001930 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001931 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001932 dpp_configurator_own_config(auth, curve, 1) == 0) {
Hai Shalomc3565922019-10-28 11:58:20 -07001933 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001934 ret = 0;
1935 }
1936
1937 dpp_auth_deinit(auth);
1938 os_free(curve);
1939
1940 return ret;
1941}
1942
1943
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001944int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
1945{
1946 struct dpp_bootstrap_info *own_bi;
1947 const char *pos, *end;
1948
1949 pos = os_strstr(cmd, " own=");
1950 if (!pos)
1951 return -1;
1952 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07001953 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001954 if (!own_bi) {
1955 wpa_printf(MSG_DEBUG,
1956 "DPP: Identified bootstrap info not found");
1957 return -1;
1958 }
1959 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
1960 wpa_printf(MSG_DEBUG,
1961 "DPP: Identified bootstrap info not for PKEX");
1962 return -1;
1963 }
1964 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001965 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001966
1967 os_free(hapd->dpp_pkex_identifier);
1968 hapd->dpp_pkex_identifier = NULL;
1969 pos = os_strstr(cmd, " identifier=");
1970 if (pos) {
1971 pos += 12;
1972 end = os_strchr(pos, ' ');
1973 if (!end)
1974 return -1;
1975 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
1976 if (!hapd->dpp_pkex_identifier)
1977 return -1;
1978 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
1979 hapd->dpp_pkex_identifier[end - pos] = '\0';
1980 }
1981
1982 pos = os_strstr(cmd, " code=");
1983 if (!pos)
1984 return -1;
1985 os_free(hapd->dpp_pkex_code);
1986 hapd->dpp_pkex_code = os_strdup(pos + 6);
1987 if (!hapd->dpp_pkex_code)
1988 return -1;
1989
1990 if (os_strstr(cmd, " init=1")) {
1991 struct wpabuf *msg;
1992
1993 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
1994 dpp_pkex_free(hapd->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001995 hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
1996 hapd->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001997 hapd->dpp_pkex_identifier,
1998 hapd->dpp_pkex_code);
1999 if (!hapd->dpp_pkex)
2000 return -1;
2001
2002 msg = hapd->dpp_pkex->exchange_req;
2003 /* TODO: Which channel to use? */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002004 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2005 " freq=%u type=%d", MAC2STR(broadcast), 2437,
2006 DPP_PA_PKEX_EXCHANGE_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002007 hostapd_drv_send_action(hapd, 2437, 0, broadcast,
2008 wpabuf_head(msg), wpabuf_len(msg));
2009 }
2010
2011 /* TODO: Support multiple PKEX info entries */
2012
2013 os_free(hapd->dpp_pkex_auth_cmd);
2014 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
2015
2016 return 1;
2017}
2018
2019
2020int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
2021{
2022 unsigned int id_val;
2023
2024 if (os_strcmp(id, "*") == 0) {
2025 id_val = 0;
2026 } else {
2027 id_val = atoi(id);
2028 if (id_val == 0)
2029 return -1;
2030 }
2031
2032 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
2033 return -1;
2034
2035 /* TODO: Support multiple PKEX entries */
2036 os_free(hapd->dpp_pkex_code);
2037 hapd->dpp_pkex_code = NULL;
2038 os_free(hapd->dpp_pkex_identifier);
2039 hapd->dpp_pkex_identifier = NULL;
2040 os_free(hapd->dpp_pkex_auth_cmd);
2041 hapd->dpp_pkex_auth_cmd = NULL;
2042 hapd->dpp_pkex_bi = NULL;
2043 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2044 dpp_pkex_free(hapd->dpp_pkex);
2045 hapd->dpp_pkex = NULL;
2046 return 0;
2047}
2048
2049
Roshan Pius3a1667e2018-07-03 15:17:14 -07002050void hostapd_dpp_stop(struct hostapd_data *hapd)
2051{
2052 dpp_auth_deinit(hapd->dpp_auth);
2053 hapd->dpp_auth = NULL;
2054 dpp_pkex_free(hapd->dpp_pkex);
2055 hapd->dpp_pkex = NULL;
2056}
2057
2058
Hai Shalom81f62d82019-07-22 12:10:00 -07002059#ifdef CONFIG_DPP2
2060
2061static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq,
2062 const u8 *msg, size_t len)
2063{
2064 struct hostapd_data *hapd = ctx;
2065 u8 *buf;
2066
2067 wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u",
2068 MAC2STR(addr), freq);
2069 buf = os_malloc(2 + len);
2070 if (!buf)
2071 return;
2072 buf[0] = WLAN_ACTION_PUBLIC;
2073 buf[1] = WLAN_PA_VENDOR_SPECIFIC;
2074 os_memcpy(buf + 2, msg, len);
2075 hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len);
2076 os_free(buf);
2077}
2078
2079
2080static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr,
2081 u8 dialog_token, int prot,
2082 struct wpabuf *buf)
2083{
2084 struct hostapd_data *hapd = ctx;
2085
2086 gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf);
2087}
2088
2089#endif /* CONFIG_DPP2 */
2090
2091
2092static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
2093{
2094#ifdef CONFIG_DPP2
2095 struct dpp_controller_conf *ctrl;
2096 struct dpp_relay_config config;
2097
2098 os_memset(&config, 0, sizeof(config));
2099 config.cb_ctx = hapd;
2100 config.tx = hostapd_dpp_relay_tx;
2101 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
2102 for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) {
2103 config.ipaddr = &ctrl->ipaddr;
2104 config.pkhash = ctrl->pkhash;
2105 if (dpp_relay_add_controller(hapd->iface->interfaces->dpp,
2106 &config) < 0)
2107 return -1;
2108 }
2109#endif /* CONFIG_DPP2 */
2110
2111 return 0;
2112}
2113
2114
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002115int hostapd_dpp_init(struct hostapd_data *hapd)
2116{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002117 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
2118 hapd->dpp_init_done = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002119 return hostapd_dpp_add_controllers(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002120}
2121
2122
2123void hostapd_dpp_deinit(struct hostapd_data *hapd)
2124{
2125#ifdef CONFIG_TESTING_OPTIONS
2126 os_free(hapd->dpp_config_obj_override);
2127 hapd->dpp_config_obj_override = NULL;
2128 os_free(hapd->dpp_discovery_override);
2129 hapd->dpp_discovery_override = NULL;
2130 os_free(hapd->dpp_groups_override);
2131 hapd->dpp_groups_override = NULL;
2132 hapd->dpp_ignore_netaccesskey_mismatch = 0;
2133#endif /* CONFIG_TESTING_OPTIONS */
2134 if (!hapd->dpp_init_done)
2135 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002136 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
2137 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
2138 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002139#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002140 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
2141 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002142 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
2143 NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07002144 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
2145 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002146 hostapd_dpp_chirp_stop(hapd);
Hai Shalom021b0b52019-04-10 11:17:58 -07002147#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002148 dpp_auth_deinit(hapd->dpp_auth);
2149 hapd->dpp_auth = NULL;
2150 hostapd_dpp_pkex_remove(hapd, "*");
2151 hapd->dpp_pkex = NULL;
2152 os_free(hapd->dpp_configurator_params);
2153 hapd->dpp_configurator_params = NULL;
2154}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002155
2156
2157#ifdef CONFIG_DPP2
2158
2159static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
2160
2161static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
2162{
2163 struct hostapd_data *hapd = eloop_ctx;
2164
2165 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
2166 hostapd_drv_send_action_cancel_wait(hapd);
2167 hostapd_dpp_chirp_next(hapd, NULL);
2168}
2169
2170
2171static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
2172{
2173 struct wpabuf *msg;
2174 int type;
2175
2176 msg = hapd->dpp_presence_announcement;
2177 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
2178 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
2179 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2180 " freq=%u type=%d",
2181 MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
2182 if (hostapd_drv_send_action(
2183 hapd, hapd->dpp_chirp_freq, 2000, broadcast,
2184 wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
2185 eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
2186 hapd, NULL) < 0)
2187 hostapd_dpp_chirp_stop(hapd);
2188}
2189
2190
2191static struct hostapd_hw_modes *
2192dpp_get_mode(struct hostapd_data *hapd,
2193 enum hostapd_hw_mode mode)
2194{
2195 struct hostapd_hw_modes *modes = hapd->iface->hw_features;
2196 u16 num_modes = hapd->iface->num_hw_features;
2197 u16 i;
2198
2199 for (i = 0; i < num_modes; i++) {
2200 if (modes[i].mode != mode ||
2201 !modes[i].num_channels || !modes[i].channels)
2202 continue;
2203 return &modes[i];
2204 }
2205
2206 return NULL;
2207}
2208
2209
2210static void
2211hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
2212{
2213 struct hostapd_data *hapd = iface->bss[0];
2214 struct wpa_scan_results *scan_res;
2215 struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
2216 unsigned int i;
2217 struct hostapd_hw_modes *mode;
2218 int c;
2219
2220 if (!bi)
2221 return;
2222
2223 hapd->dpp_chirp_scan_done = 1;
2224
2225 scan_res = hostapd_driver_get_scan_results(hapd);
2226
2227 os_free(hapd->dpp_chirp_freqs);
2228 hapd->dpp_chirp_freqs = NULL;
2229
2230 /* Channels from own bootstrapping info */
2231 if (bi) {
2232 for (i = 0; i < bi->num_freq; i++)
2233 int_array_add_unique(&hapd->dpp_chirp_freqs,
2234 bi->freq[i]);
2235 }
2236
2237 /* Preferred chirping channels */
2238 int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
2239
2240 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
2241 if (mode) {
2242 int chan44 = 0, chan149 = 0;
2243
2244 for (c = 0; c < mode->num_channels; c++) {
2245 struct hostapd_channel_data *chan = &mode->channels[c];
2246
2247 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2248 HOSTAPD_CHAN_RADAR))
2249 continue;
2250 if (chan->freq == 5220)
2251 chan44 = 1;
2252 if (chan->freq == 5745)
2253 chan149 = 1;
2254 }
2255 if (chan149)
2256 int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
2257 else if (chan44)
2258 int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
2259 }
2260
2261 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
2262 if (mode) {
2263 for (c = 0; c < mode->num_channels; c++) {
2264 struct hostapd_channel_data *chan = &mode->channels[c];
2265
2266 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
2267 HOSTAPD_CHAN_RADAR)) ||
2268 chan->freq != 60480)
2269 continue;
2270 int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
2271 break;
2272 }
2273 }
2274
2275 /* Add channels from scan results for APs that advertise Configurator
2276 * Connectivity element */
2277 for (i = 0; scan_res && i < scan_res->num; i++) {
2278 struct wpa_scan_res *bss = scan_res->res[i];
2279 size_t ie_len = bss->ie_len;
2280
2281 if (!ie_len)
2282 ie_len = bss->beacon_ie_len;
2283 if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
2284 DPP_CC_IE_VENDOR_TYPE))
2285 int_array_add_unique(&hapd->dpp_chirp_freqs,
2286 bss->freq);
2287 }
2288
2289 if (!hapd->dpp_chirp_freqs ||
2290 eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
2291 hapd, NULL) < 0)
2292 hostapd_dpp_chirp_stop(hapd);
2293
2294 wpa_scan_results_free(scan_res);
2295}
2296
2297
2298static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
2299{
2300 struct hostapd_data *hapd = eloop_ctx;
2301 int i;
2302
2303 if (hapd->dpp_chirp_listen)
2304 hostapd_dpp_listen_stop(hapd);
2305
2306 if (hapd->dpp_chirp_freq == 0) {
2307 if (hapd->dpp_chirp_round % 4 == 0 &&
2308 !hapd->dpp_chirp_scan_done) {
2309 struct wpa_driver_scan_params params;
2310 int ret;
2311
2312 wpa_printf(MSG_DEBUG,
2313 "DPP: Update channel list for chirping");
2314 os_memset(&params, 0, sizeof(params));
2315 ret = hostapd_driver_scan(hapd, &params);
2316 if (ret < 0) {
2317 wpa_printf(MSG_DEBUG,
2318 "DPP: Failed to request a scan ret=%d (%s)",
2319 ret, strerror(-ret));
2320 hostapd_dpp_chirp_scan_res_handler(hapd->iface);
2321 } else {
2322 hapd->iface->scan_cb =
2323 hostapd_dpp_chirp_scan_res_handler;
2324 }
2325 return;
2326 }
2327 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
2328 hapd->dpp_chirp_round++;
2329 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
2330 hapd->dpp_chirp_round);
2331 } else {
2332 for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
2333 if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
2334 break;
2335 if (!hapd->dpp_chirp_freqs[i]) {
2336 wpa_printf(MSG_DEBUG,
2337 "DPP: Previous chirp freq %d not found",
2338 hapd->dpp_chirp_freq);
2339 return;
2340 }
2341 i++;
2342 if (hapd->dpp_chirp_freqs[i]) {
2343 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
2344 } else {
2345 hapd->dpp_chirp_iter--;
2346 if (hapd->dpp_chirp_iter <= 0) {
2347 wpa_printf(MSG_DEBUG,
2348 "DPP: Chirping iterations completed");
2349 hostapd_dpp_chirp_stop(hapd);
2350 return;
2351 }
2352 hapd->dpp_chirp_freq = 0;
2353 hapd->dpp_chirp_scan_done = 0;
2354 if (eloop_register_timeout(30, 0,
2355 hostapd_dpp_chirp_next,
2356 hapd, NULL) < 0) {
2357 hostapd_dpp_chirp_stop(hapd);
2358 return;
2359 }
2360 if (hapd->dpp_chirp_listen) {
2361 wpa_printf(MSG_DEBUG,
2362 "DPP: Listen on %d MHz during chirp 30 second wait",
2363 hapd->dpp_chirp_listen);
2364 /* TODO: start listen on the channel */
2365 } else {
2366 wpa_printf(MSG_DEBUG,
2367 "DPP: Wait 30 seconds before starting the next chirping round");
2368 }
2369 return;
2370 }
2371 }
2372
2373 hostapd_dpp_chirp_start(hapd);
2374}
2375
2376
2377int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
2378{
2379 const char *pos;
2380 int iter = 1, listen_freq = 0;
2381 struct dpp_bootstrap_info *bi;
2382
2383 pos = os_strstr(cmd, " own=");
2384 if (!pos)
2385 return -1;
2386 pos += 5;
2387 bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
2388 if (!bi) {
2389 wpa_printf(MSG_DEBUG,
2390 "DPP: Identified bootstrap info not found");
2391 return -1;
2392 }
2393
2394 pos = os_strstr(cmd, " iter=");
2395 if (pos) {
2396 iter = atoi(pos + 6);
2397 if (iter <= 0)
2398 return -1;
2399 }
2400
2401 pos = os_strstr(cmd, " listen=");
2402 if (pos) {
2403 listen_freq = atoi(pos + 8);
2404 if (listen_freq <= 0)
2405 return -1;
2406 }
2407
2408 hostapd_dpp_chirp_stop(hapd);
2409 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
2410 hapd->dpp_qr_mutual = 0;
2411 hapd->dpp_chirp_bi = bi;
2412 hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
2413 if (!hapd->dpp_presence_announcement)
2414 return -1;
2415 hapd->dpp_chirp_iter = iter;
2416 hapd->dpp_chirp_round = 0;
2417 hapd->dpp_chirp_scan_done = 0;
2418 hapd->dpp_chirp_listen = listen_freq;
2419
2420 return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
2421}
2422
2423
2424void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
2425{
2426 if (hapd->dpp_presence_announcement) {
2427 hostapd_drv_send_action_cancel_wait(hapd);
2428 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
2429 }
2430 hapd->dpp_chirp_bi = NULL;
2431 wpabuf_free(hapd->dpp_presence_announcement);
2432 hapd->dpp_presence_announcement = NULL;
2433 if (hapd->dpp_chirp_listen)
2434 hostapd_dpp_listen_stop(hapd);
2435 hapd->dpp_chirp_listen = 0;
2436 hapd->dpp_chirp_freq = 0;
2437 os_free(hapd->dpp_chirp_freqs);
2438 hapd->dpp_chirp_freqs = NULL;
2439 eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
2440 eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
2441 if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
2442 /* TODO: abort ongoing scan */
2443 hapd->iface->scan_cb = NULL;
2444 }
2445}
2446
2447
2448static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
2449{
2450 struct dpp_bootstrap_info *bi = ctx;
2451 size_t i;
2452
2453 for (i = 0; i < iface->num_bss; i++) {
2454 struct hostapd_data *hapd = iface->bss[i];
2455
2456 if (bi == hapd->dpp_chirp_bi)
2457 hostapd_dpp_chirp_stop(hapd);
2458 }
2459
2460 return 0;
2461}
2462
2463
2464void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2465{
2466 struct hapd_interfaces *interfaces = ctx;
2467
2468 hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
2469}
2470
2471#endif /* CONFIG_DPP2 */