blob: 96a13fb6fb1eabc48c0bb3720669f840700c502a [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
Hai Shaloma20dcd72022-02-04 13:43:00 -08005 * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "utils/includes.h"
12
13#include "utils/common.h"
14#include "utils/eloop.h"
15#include "common/dpp.h"
16#include "common/gas.h"
17#include "common/wpa_ctrl.h"
18#include "hostapd.h"
19#include "ap_drv_ops.h"
20#include "gas_query_ap.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070021#include "gas_serv.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070022#include "wpa_auth.h"
23#include "dpp_hostapd.h"
24
25
Roshan Pius3a1667e2018-07-03 15:17:14 -070026static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom60840252021-02-19 19:02:11 -080027static void hostapd_dpp_auth_conf_wait_timeout(void *eloop_ctx,
28 void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070029static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -070030static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
31static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
Hai Shaloma20dcd72022-02-04 13:43:00 -080032static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
33 struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070034#ifdef CONFIG_DPP2
35static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
36 void *timeout_ctx);
Hai Shalom899fcc72020-10-19 14:38:18 -070037static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
38 struct dpp_authentication *auth,
39 struct dpp_config_obj *conf);
Hai Shaloma20dcd72022-02-04 13:43:00 -080040static int hostapd_dpp_process_conf_obj(void *ctx,
41 struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070042#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070043
44static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
45
46
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070047/**
48 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
49 * @hapd: Pointer to hostapd_data
50 * @cmd: DPP URI read from a QR Code
51 * Returns: Identifier of the stored info or -1 on failure
52 */
53int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
54{
55 struct dpp_bootstrap_info *bi;
56 struct dpp_authentication *auth = hapd->dpp_auth;
57
Hai Shalom021b0b52019-04-10 11:17:58 -070058 bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070059 if (!bi)
60 return -1;
61
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070062 if (auth && auth->response_pending &&
63 dpp_notify_new_qr_code(auth, bi) == 1) {
64 wpa_printf(MSG_DEBUG,
65 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070066 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
67 " freq=%u type=%d",
68 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
69 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070070 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
71 auth->peer_mac_addr,
72 wpabuf_head(hapd->dpp_auth->resp_msg),
73 wpabuf_len(hapd->dpp_auth->resp_msg));
74 }
75
Hai Shalom899fcc72020-10-19 14:38:18 -070076#ifdef CONFIG_DPP2
77 dpp_controller_new_qr_code(hapd->iface->interfaces->dpp, bi);
78#endif /* CONFIG_DPP2 */
79
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070080 return bi->id;
81}
82
83
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080084/**
85 * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
86 * @hapd: Pointer to hostapd_data
87 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
88 * Returns: Identifier of the stored info or -1 on failure
89 */
90int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
91{
92 struct dpp_bootstrap_info *bi;
93
94 bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
95 if (!bi)
96 return -1;
97
98 return bi->id;
99}
100
101
Hai Shalomfdcde762020-04-02 11:19:20 -0700102int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd)
103{
104 const char *pos;
105 struct dpp_bootstrap_info *peer_bi, *own_bi;
106
107 pos = os_strstr(cmd, " own=");
108 if (!pos)
109 return -1;
110 pos += 5;
111 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
112 if (!own_bi)
113 return -1;
114
115 pos = os_strstr(cmd, " uri=");
116 if (!pos)
117 return -1;
118 pos += 5;
119 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
120 if (!peer_bi) {
121 wpa_printf(MSG_INFO,
122 "DPP: Failed to parse URI from NFC Handover Request");
123 return -1;
124 }
125
126 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
127 return -1;
128
129 return peer_bi->id;
130}
131
132
133int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd)
134{
135 const char *pos;
136 struct dpp_bootstrap_info *peer_bi, *own_bi;
137
138 pos = os_strstr(cmd, " own=");
139 if (!pos)
140 return -1;
141 pos += 5;
142 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
143 if (!own_bi)
144 return -1;
145
146 pos = os_strstr(cmd, " uri=");
147 if (!pos)
148 return -1;
149 pos += 5;
150 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
151 if (!peer_bi) {
152 wpa_printf(MSG_INFO,
153 "DPP: Failed to parse URI from NFC Handover Select");
154 return -1;
155 }
156
157 if (peer_bi->curve != own_bi->curve) {
158 wpa_printf(MSG_INFO,
159 "DPP: Peer (NFC Handover Selector) used different curve");
160 return -1;
161 }
162
163 return peer_bi->id;
164}
165
166
Roshan Pius3a1667e2018-07-03 15:17:14 -0700167static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
168 void *timeout_ctx)
169{
170 struct hostapd_data *hapd = eloop_ctx;
171 struct dpp_authentication *auth = hapd->dpp_auth;
172
173 if (!auth || !auth->resp_msg)
174 return;
175
176 wpa_printf(MSG_DEBUG,
177 "DPP: Retry Authentication Response after timeout");
178 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
179 " freq=%u type=%d",
180 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
181 DPP_PA_AUTHENTICATION_RESP);
182 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
183 wpabuf_head(auth->resp_msg),
184 wpabuf_len(auth->resp_msg));
185}
186
187
188static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
189{
190 struct dpp_authentication *auth = hapd->dpp_auth;
191 unsigned int wait_time, max_tries;
192
193 if (!auth || !auth->resp_msg)
194 return;
195
196 if (hapd->dpp_resp_max_tries)
197 max_tries = hapd->dpp_resp_max_tries;
198 else
199 max_tries = 5;
200 auth->auth_resp_tries++;
201 if (auth->auth_resp_tries >= max_tries) {
202 wpa_printf(MSG_INFO,
203 "DPP: No confirm received from initiator - stopping exchange");
204 hostapd_drv_send_action_cancel_wait(hapd);
205 dpp_auth_deinit(hapd->dpp_auth);
206 hapd->dpp_auth = NULL;
207 return;
208 }
209
210 if (hapd->dpp_resp_retry_time)
211 wait_time = hapd->dpp_resp_retry_time;
212 else
213 wait_time = 1000;
214 wpa_printf(MSG_DEBUG,
215 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
216 wait_time);
217 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
218 eloop_register_timeout(wait_time / 1000,
219 (wait_time % 1000) * 1000,
220 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
221}
222
223
Hai Shaloma20dcd72022-02-04 13:43:00 -0800224static int hostapd_dpp_allow_ir(struct hostapd_data *hapd, unsigned int freq)
225{
226 int i, j;
227
228 if (!hapd->iface->hw_features)
229 return -1;
230
231 for (i = 0; i < hapd->iface->num_hw_features; i++) {
232 struct hostapd_hw_modes *mode = &hapd->iface->hw_features[i];
233
234 for (j = 0; j < mode->num_channels; j++) {
235 struct hostapd_channel_data *chan = &mode->channels[j];
236
237 if (chan->freq != (int) freq)
238 continue;
239
240 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
241 HOSTAPD_CHAN_NO_IR |
242 HOSTAPD_CHAN_RADAR))
243 continue;
244
245 return 1;
246 }
247 }
248
249 wpa_printf(MSG_DEBUG,
250 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
251 freq);
252
253 return 0;
254}
255
256
257static int hostapd_dpp_pkex_next_channel(struct hostapd_data *hapd,
258 struct dpp_pkex *pkex)
259{
260 if (pkex->freq == 2437)
261 pkex->freq = 5745;
262 else if (pkex->freq == 5745)
263 pkex->freq = 5220;
264 else if (pkex->freq == 5220)
265 pkex->freq = 60480;
266 else
267 return -1; /* no more channels to try */
268
269 if (hostapd_dpp_allow_ir(hapd, pkex->freq) == 1) {
270 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
271 pkex->freq);
272 return 0;
273 }
274
275 /* Could not use this channel - try the next one */
276 return hostapd_dpp_pkex_next_channel(hapd, pkex);
277}
278
279
280#ifdef CONFIG_DPP2
281static int hostapd_dpp_pkex_done(void *ctx, void *conn,
282 struct dpp_bootstrap_info *peer_bi)
283{
284 struct hostapd_data *hapd = ctx;
285 const char *cmd = hapd->dpp_pkex_auth_cmd;
286 const char *pos;
287 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
288 struct dpp_bootstrap_info *own_bi = NULL;
289 struct dpp_authentication *auth;
290
291 if (!cmd)
292 cmd = "";
293 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
294 cmd);
295
296 pos = os_strstr(cmd, " own=");
297 if (pos) {
298 pos += 5;
299 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
300 atoi(pos));
301 if (!own_bi) {
302 wpa_printf(MSG_INFO,
303 "DPP: Could not find bootstrapping info for the identified local entry");
304 return -1;
305 }
306
307 if (peer_bi->curve != own_bi->curve) {
308 wpa_printf(MSG_INFO,
309 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
310 peer_bi->curve->name, own_bi->curve->name);
311 return -1;
312 }
313 }
314
315 pos = os_strstr(cmd, " role=");
316 if (pos) {
317 pos += 6;
318 if (os_strncmp(pos, "configurator", 12) == 0)
319 allowed_roles = DPP_CAPAB_CONFIGURATOR;
320 else if (os_strncmp(pos, "enrollee", 8) == 0)
321 allowed_roles = DPP_CAPAB_ENROLLEE;
322 else if (os_strncmp(pos, "either", 6) == 0)
323 allowed_roles = DPP_CAPAB_CONFIGURATOR |
324 DPP_CAPAB_ENROLLEE;
325 else
326 return -1;
327 }
328
329 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
330 peer_bi, own_bi, allowed_roles, 0,
331 hapd->iface->hw_features,
332 hapd->iface->num_hw_features);
333 if (!auth)
334 return -1;
335
336 hostapd_dpp_set_testing_options(hapd, auth);
337 if (dpp_set_configurator(auth, cmd) < 0) {
338 dpp_auth_deinit(auth);
339 return -1;
340 }
341
342 return dpp_tcp_auth(hapd->iface->interfaces->dpp, conn, auth,
343 hapd->conf->dpp_name, DPP_NETROLE_AP,
344 hostapd_dpp_process_conf_obj, NULL);
345}
346#endif /* CONFIG_DPP2 */
347
348
349enum hostapd_dpp_pkex_ver {
350 PKEX_VER_AUTO,
351 PKEX_VER_ONLY_1,
352 PKEX_VER_ONLY_2,
353};
354
355static int hostapd_dpp_pkex_init(struct hostapd_data *hapd,
356 enum hostapd_dpp_pkex_ver ver,
357 const struct hostapd_ip_addr *ipaddr,
358 int tcp_port)
359{
360 struct dpp_pkex *pkex;
361 struct wpabuf *msg;
362 unsigned int wait_time;
363 bool v2 = ver != PKEX_VER_ONLY_1;
364
365 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
366 dpp_pkex_free(hapd->dpp_pkex);
367 hapd->dpp_pkex = NULL;
368 pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr,
369 hapd->dpp_pkex_identifier,
370 hapd->dpp_pkex_code, v2);
371 if (!pkex)
372 return -1;
373 pkex->forced_ver = ver != PKEX_VER_AUTO;
374
375 if (ipaddr) {
376#ifdef CONFIG_DPP2
377 return dpp_tcp_pkex_init(hapd->iface->interfaces->dpp, pkex,
378 ipaddr, tcp_port,
379 hapd->msg_ctx, hapd,
380 hostapd_dpp_pkex_done);
381#else /* CONFIG_DPP2 */
382 return -1;
383#endif /* CONFIG_DPP2 */
384 }
385
386 hapd->dpp_pkex = pkex;
387 msg = hapd->dpp_pkex->exchange_req;
388 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
389 pkex->freq = 2437;
390 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
391 " freq=%u type=%d", MAC2STR(broadcast), pkex->freq,
392 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
393 DPP_PA_PKEX_V1_EXCHANGE_REQ);
394 hostapd_drv_send_action(hapd, pkex->freq, 0, broadcast,
395 wpabuf_head(msg), wpabuf_len(msg));
396 pkex->exch_req_wait_time = wait_time;
397 pkex->exch_req_tries = 1;
398
399 return 0;
400}
401
402
403static void hostapd_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
404{
405 struct hostapd_data *hapd = eloop_ctx;
406 struct dpp_pkex *pkex = hapd->dpp_pkex;
407
408 if (!pkex || !pkex->exchange_req)
409 return;
410 if (pkex->exch_req_tries >= 5) {
411 if (hostapd_dpp_pkex_next_channel(hapd, pkex) < 0) {
412#ifdef CONFIG_DPP3
413 if (pkex->v2 && !pkex->forced_ver) {
414 wpa_printf(MSG_DEBUG,
415 "DPP: Fall back to PKEXv1");
416 hostapd_dpp_pkex_init(hapd, PKEX_VER_ONLY_1,
417 NULL, 0);
418 return;
419 }
420#endif /* CONFIG_DPP3 */
421 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
422 "No response from PKEX peer");
423 dpp_pkex_free(pkex);
424 hapd->dpp_pkex = NULL;
425 return;
426 }
427 pkex->exch_req_tries = 0;
428 }
429
430 pkex->exch_req_tries++;
431 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
432 pkex->exch_req_tries);
433 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
434 " freq=%u type=%d",
435 MAC2STR(broadcast), pkex->freq,
436 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
437 DPP_PA_PKEX_V1_EXCHANGE_REQ);
438 hostapd_drv_send_action(hapd, pkex->freq, pkex->exch_req_wait_time,
439 broadcast,
440 wpabuf_head(pkex->exchange_req),
441 wpabuf_len(pkex->exchange_req));
442}
443
444
445static void hostapd_dpp_pkex_tx_status(struct hostapd_data *hapd, const u8 *dst,
446 const u8 *data, size_t data_len, int ok)
447{
448 struct dpp_pkex *pkex = hapd->dpp_pkex;
449
450 if (pkex->failed) {
451 wpa_printf(MSG_DEBUG,
452 "DPP: Terminate PKEX exchange due to an earlier error");
453 if (pkex->t > pkex->own_bi->pkex_t)
454 pkex->own_bi->pkex_t = pkex->t;
455 dpp_pkex_free(pkex);
456 hapd->dpp_pkex = NULL;
457 return;
458 }
459
460 if (pkex->exch_req_wait_time && pkex->exchange_req) {
461 /* Wait for PKEX Exchange Response frame and retry request if
462 * no response is seen. */
463 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd,
464 NULL);
465 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
466 (pkex->exch_req_wait_time % 1000) * 1000,
467 hostapd_dpp_pkex_retry_timeout, hapd,
468 NULL);
469 }
470}
471
472
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700473void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
474 const u8 *data, size_t data_len, int ok)
475{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700476 struct dpp_authentication *auth = hapd->dpp_auth;
477
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700478 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
479 MAC2STR(dst), ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700480 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
481 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700482
483 if (!hapd->dpp_auth) {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800484 if (hapd->dpp_pkex) {
485 hostapd_dpp_pkex_tx_status(hapd, dst, data, data_len,
486 ok);
487 return;
488 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700489 wpa_printf(MSG_DEBUG,
490 "DPP: Ignore TX status since there is no ongoing authentication exchange");
491 return;
492 }
493
Hai Shalom021b0b52019-04-10 11:17:58 -0700494#ifdef CONFIG_DPP2
495 if (auth->connect_on_tx_status) {
496 wpa_printf(MSG_DEBUG,
497 "DPP: Complete exchange on configuration result");
498 dpp_auth_deinit(hapd->dpp_auth);
499 hapd->dpp_auth = NULL;
500 return;
501 }
502#endif /* CONFIG_DPP2 */
503
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700504 if (hapd->dpp_auth->remove_on_tx_status) {
505 wpa_printf(MSG_DEBUG,
506 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700507 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
508 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
509 hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800510 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout,
511 hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700512 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
513 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700514#ifdef CONFIG_DPP2
515 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
516 hapd, NULL);
517#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700518 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700519 dpp_auth_deinit(hapd->dpp_auth);
520 hapd->dpp_auth = NULL;
521 return;
522 }
523
524 if (hapd->dpp_auth_ok_on_ack)
525 hostapd_dpp_auth_success(hapd, 1);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700526
527 if (!is_broadcast_ether_addr(dst) && !ok) {
528 wpa_printf(MSG_DEBUG,
529 "DPP: Unicast DPP Action frame was not ACKed");
530 if (auth->waiting_auth_resp) {
531 /* In case of DPP Authentication Request frame, move to
532 * the next channel immediately. */
533 hostapd_drv_send_action_cancel_wait(hapd);
534 hostapd_dpp_auth_init_next(hapd);
535 return;
536 }
537 if (auth->waiting_auth_conf) {
538 hostapd_dpp_auth_resp_retry(hapd);
539 return;
540 }
541 }
542
Hai Shalom60840252021-02-19 19:02:11 -0800543 if (auth->waiting_auth_conf &&
544 auth->auth_resp_status == DPP_STATUS_OK) {
545 /* Make sure we do not get stuck waiting for Auth Confirm
546 * indefinitely after successfully transmitted Auth Response to
547 * allow new authentication exchanges to be started. */
548 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd,
549 NULL);
550 eloop_register_timeout(1, 0, hostapd_dpp_auth_conf_wait_timeout,
551 hapd, NULL);
552 }
553
Roshan Pius3a1667e2018-07-03 15:17:14 -0700554 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
555 /* Allow timeout handling to stop iteration if no response is
556 * received from a peer that has ACKed a request. */
557 auth->auth_req_ack = 1;
558 }
559
560 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
561 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
562 wpa_printf(MSG_DEBUG,
563 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
564 hapd->dpp_auth->curr_freq,
565 hapd->dpp_auth->neg_freq);
566 hostapd_drv_send_action_cancel_wait(hapd);
567
568 if (hapd->dpp_auth->neg_freq !=
569 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
570 /* TODO: Listen operation on non-operating channel */
571 wpa_printf(MSG_INFO,
572 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
573 hapd->dpp_auth->neg_freq, hapd->iface->freq);
574 }
575 }
576
577 if (hapd->dpp_auth_ok_on_ack)
578 hapd->dpp_auth_ok_on_ack = 0;
579}
580
581
582static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
583{
584 struct hostapd_data *hapd = eloop_ctx;
585 struct dpp_authentication *auth = hapd->dpp_auth;
586 unsigned int freq;
587 struct os_reltime now, diff;
588 unsigned int wait_time, diff_ms;
589
590 if (!auth || !auth->waiting_auth_resp)
591 return;
592
593 wait_time = hapd->dpp_resp_wait_time ?
594 hapd->dpp_resp_wait_time : 2000;
595 os_get_reltime(&now);
596 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
597 diff_ms = diff.sec * 1000 + diff.usec / 1000;
598 wpa_printf(MSG_DEBUG,
599 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
600 wait_time, diff_ms);
601
602 if (auth->auth_req_ack && diff_ms >= wait_time) {
603 /* Peer ACK'ed Authentication Request frame, but did not reply
604 * with Authentication Response frame within two seconds. */
605 wpa_printf(MSG_INFO,
606 "DPP: No response received from responder - stopping initiation attempt");
607 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
608 hostapd_drv_send_action_cancel_wait(hapd);
609 hostapd_dpp_listen_stop(hapd);
610 dpp_auth_deinit(auth);
611 hapd->dpp_auth = NULL;
612 return;
613 }
614
615 if (diff_ms >= wait_time) {
616 /* Authentication Request frame was not ACK'ed and no reply
617 * was receiving within two seconds. */
618 wpa_printf(MSG_DEBUG,
619 "DPP: Continue Initiator channel iteration");
620 hostapd_drv_send_action_cancel_wait(hapd);
621 hostapd_dpp_listen_stop(hapd);
622 hostapd_dpp_auth_init_next(hapd);
623 return;
624 }
625
626 /* Driver did not support 2000 ms long wait_time with TX command, so
627 * schedule listen operation to continue waiting for the response.
628 *
629 * DPP listen operations continue until stopped, so simply schedule a
630 * new call to this function at the point when the two second reply
631 * wait has expired. */
632 wait_time -= diff_ms;
633
634 freq = auth->curr_freq;
635 if (auth->neg_freq > 0)
636 freq = auth->neg_freq;
637 wpa_printf(MSG_DEBUG,
638 "DPP: Continue reply wait on channel %u MHz for %u ms",
639 freq, wait_time);
640 hapd->dpp_in_response_listen = 1;
641
642 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
643 /* TODO: Listen operation on non-operating channel */
644 wpa_printf(MSG_INFO,
645 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
646 freq, hapd->iface->freq);
647 }
648
649 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
650 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700651}
652
653
Hai Shalom60840252021-02-19 19:02:11 -0800654static void hostapd_dpp_auth_conf_wait_timeout(void *eloop_ctx,
655 void *timeout_ctx)
656{
657 struct hostapd_data *hapd = eloop_ctx;
658 struct dpp_authentication *auth = hapd->dpp_auth;
659
660 if (!auth || !auth->waiting_auth_conf)
661 return;
662
663 wpa_printf(MSG_DEBUG,
664 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
665 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
666 "No Auth Confirm received");
667 hostapd_drv_send_action_cancel_wait(hapd);
668 dpp_auth_deinit(auth);
669 hapd->dpp_auth = NULL;
670}
671
672
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700673static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
674 struct dpp_authentication *auth)
675{
676#ifdef CONFIG_TESTING_OPTIONS
677 if (hapd->dpp_config_obj_override)
678 auth->config_obj_override =
679 os_strdup(hapd->dpp_config_obj_override);
680 if (hapd->dpp_discovery_override)
681 auth->discovery_override =
682 os_strdup(hapd->dpp_discovery_override);
683 if (hapd->dpp_groups_override)
684 auth->groups_override = os_strdup(hapd->dpp_groups_override);
685 auth->ignore_netaccesskey_mismatch =
686 hapd->dpp_ignore_netaccesskey_mismatch;
687#endif /* CONFIG_TESTING_OPTIONS */
688}
689
690
Roshan Pius3a1667e2018-07-03 15:17:14 -0700691static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
692{
693 struct hostapd_data *hapd = eloop_ctx;
694
695 if (!hapd->dpp_auth)
696 return;
697 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
698 hostapd_dpp_auth_init_next(hapd);
699}
700
701
702static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
703{
704 struct dpp_authentication *auth = hapd->dpp_auth;
705 const u8 *dst;
706 unsigned int wait_time, max_wait_time, freq, max_tries, used;
707 struct os_reltime now, diff;
708
709 if (!auth)
710 return -1;
711
712 if (auth->freq_idx == 0)
713 os_get_reltime(&hapd->dpp_init_iter_start);
714
715 if (auth->freq_idx >= auth->num_freq) {
716 auth->num_freq_iters++;
717 if (hapd->dpp_init_max_tries)
718 max_tries = hapd->dpp_init_max_tries;
719 else
720 max_tries = 5;
721 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
722 wpa_printf(MSG_INFO,
723 "DPP: No response received from responder - stopping initiation attempt");
724 wpa_msg(hapd->msg_ctx, MSG_INFO,
725 DPP_EVENT_AUTH_INIT_FAILED);
726 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
727 hapd, NULL);
728 hostapd_drv_send_action_cancel_wait(hapd);
729 dpp_auth_deinit(hapd->dpp_auth);
730 hapd->dpp_auth = NULL;
731 return -1;
732 }
733 auth->freq_idx = 0;
734 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
735 if (hapd->dpp_init_retry_time)
736 wait_time = hapd->dpp_init_retry_time;
737 else
738 wait_time = 10000;
739 os_get_reltime(&now);
740 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
741 used = diff.sec * 1000 + diff.usec / 1000;
742 if (used > wait_time)
743 wait_time = 0;
744 else
745 wait_time -= used;
746 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
747 wait_time);
748 eloop_register_timeout(wait_time / 1000,
749 (wait_time % 1000) * 1000,
750 hostapd_dpp_init_timeout, hapd,
751 NULL);
752 return 0;
753 }
754 freq = auth->freq[auth->freq_idx++];
755 auth->curr_freq = freq;
756
Hai Shalom60840252021-02-19 19:02:11 -0800757 if (!is_zero_ether_addr(auth->peer_mac_addr))
758 dst = auth->peer_mac_addr;
759 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700760 dst = broadcast;
761 else
762 dst = auth->peer_bi->mac_addr;
763 hapd->dpp_auth_ok_on_ack = 0;
764 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
765 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
766 max_wait_time = hapd->dpp_resp_wait_time ?
767 hapd->dpp_resp_wait_time : 2000;
768 if (wait_time > max_wait_time)
769 wait_time = max_wait_time;
770 wait_time += 10; /* give the driver some extra time to complete */
771 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
772 hostapd_dpp_reply_wait_timeout, hapd, NULL);
773 wait_time -= 10;
774 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
775 wpa_printf(MSG_DEBUG,
776 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
777 freq, auth->neg_freq);
778 }
779 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
780 " freq=%u type=%d",
781 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
782 auth->auth_req_ack = 0;
783 os_get_reltime(&hapd->dpp_last_init);
784 return hostapd_drv_send_action(hapd, freq, wait_time,
785 dst,
786 wpabuf_head(hapd->dpp_auth->req_msg),
787 wpabuf_len(hapd->dpp_auth->req_msg));
788}
789
790
Hai Shalom899fcc72020-10-19 14:38:18 -0700791#ifdef CONFIG_DPP2
792static int hostapd_dpp_process_conf_obj(void *ctx,
793 struct dpp_authentication *auth)
794{
795 struct hostapd_data *hapd = ctx;
796 unsigned int i;
797
798 for (i = 0; i < auth->num_conf_obj; i++)
799 hostapd_dpp_handle_config_obj(hapd, auth,
800 &auth->conf_obj[i]);
801
802 return 0;
803}
804#endif /* CONFIG_DPP2 */
805
806
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700807int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
808{
809 const char *pos;
810 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -0700811 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700812 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
813 unsigned int neg_freq = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700814 int tcp = 0;
815#ifdef CONFIG_DPP2
816 int tcp_port = DPP_TCP_PORT;
817 struct hostapd_ip_addr ipaddr;
818 char *addr;
819#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700820
821 pos = os_strstr(cmd, " peer=");
822 if (!pos)
823 return -1;
824 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700825 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700826 if (!peer_bi) {
827 wpa_printf(MSG_INFO,
828 "DPP: Could not find bootstrapping info for the identified peer");
829 return -1;
830 }
831
Hai Shalom899fcc72020-10-19 14:38:18 -0700832#ifdef CONFIG_DPP2
833 pos = os_strstr(cmd, " tcp_port=");
834 if (pos) {
835 pos += 10;
836 tcp_port = atoi(pos);
837 }
838
839 addr = get_param(cmd, " tcp_addr=");
840 if (addr) {
841 int res;
842
843 res = hostapd_parse_ip_addr(addr, &ipaddr);
844 os_free(addr);
845 if (res)
846 return -1;
847 tcp = 1;
848 }
849#endif /* CONFIG_DPP2 */
850
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700851 pos = os_strstr(cmd, " own=");
852 if (pos) {
853 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700854 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
855 atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700856 if (!own_bi) {
857 wpa_printf(MSG_INFO,
858 "DPP: Could not find bootstrapping info for the identified local entry");
859 return -1;
860 }
861
862 if (peer_bi->curve != own_bi->curve) {
863 wpa_printf(MSG_INFO,
864 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
865 peer_bi->curve->name, own_bi->curve->name);
866 return -1;
867 }
868 }
869
870 pos = os_strstr(cmd, " role=");
871 if (pos) {
872 pos += 6;
873 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700874 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700875 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700876 allowed_roles = DPP_CAPAB_ENROLLEE;
877 else if (os_strncmp(pos, "either", 6) == 0)
878 allowed_roles = DPP_CAPAB_CONFIGURATOR |
879 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700880 else
881 goto fail;
882 }
883
Roshan Pius3a1667e2018-07-03 15:17:14 -0700884 pos = os_strstr(cmd, " neg_freq=");
885 if (pos)
886 neg_freq = atoi(pos + 10);
887
Hai Shalom899fcc72020-10-19 14:38:18 -0700888 if (!tcp && hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700889 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
890 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
891 hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800892 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout,
893 hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700894 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
895 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700896#ifdef CONFIG_DPP2
897 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
898 hapd, NULL);
899#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700900 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700901 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700902 }
903
Hai Shalom899fcc72020-10-19 14:38:18 -0700904 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
905 peer_bi, own_bi, allowed_roles, neg_freq,
906 hapd->iface->hw_features,
907 hapd->iface->num_hw_features);
908 if (!auth)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700909 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -0700910 hostapd_dpp_set_testing_options(hapd, auth);
911 if (dpp_set_configurator(auth, cmd) < 0) {
912 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800913 goto fail;
914 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700915
Hai Shalom899fcc72020-10-19 14:38:18 -0700916 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700917
Roshan Pius3a1667e2018-07-03 15:17:14 -0700918 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom899fcc72020-10-19 14:38:18 -0700919 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700920
Hai Shalom899fcc72020-10-19 14:38:18 -0700921#ifdef CONFIG_DPP2
922 if (tcp)
923 return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
924 &ipaddr, tcp_port, hapd->conf->dpp_name,
925 DPP_NETROLE_AP, hapd->msg_ctx, hapd,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800926 hostapd_dpp_process_conf_obj, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -0700927#endif /* CONFIG_DPP2 */
928
929 hapd->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700930 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700931fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700932 return -1;
933}
934
935
Roshan Pius3a1667e2018-07-03 15:17:14 -0700936int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
937{
938 int freq;
939
940 freq = atoi(cmd);
941 if (freq <= 0)
942 return -1;
943
944 if (os_strstr(cmd, " role=configurator"))
945 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
946 else if (os_strstr(cmd, " role=enrollee"))
947 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
948 else
949 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
950 DPP_CAPAB_ENROLLEE;
951 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
952
953 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
954 /* TODO: Listen operation on non-operating channel */
955 wpa_printf(MSG_INFO,
956 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
957 freq, hapd->iface->freq);
958 return -1;
959 }
960
Hai Shalom60840252021-02-19 19:02:11 -0800961 hostapd_drv_dpp_listen(hapd, true);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700962 return 0;
963}
964
965
966void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
967{
Hai Shalom60840252021-02-19 19:02:11 -0800968 hostapd_drv_dpp_listen(hapd, false);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700969 /* TODO: Stop listen operation on non-operating channel */
970}
971
972
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700973static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
974 const u8 *hdr, const u8 *buf, size_t len,
975 unsigned int freq)
976{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700977 const u8 *r_bootstrap, *i_bootstrap;
978 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700979 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
980
981 if (!hapd->iface->interfaces->dpp)
982 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700983
984 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
985 MAC2STR(src));
986
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700987#ifdef CONFIG_DPP2
988 hostapd_dpp_chirp_stop(hapd);
989#endif /* CONFIG_DPP2 */
990
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700991 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
992 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700993 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
994 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
995 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700996 return;
997 }
998 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
999 r_bootstrap, r_bootstrap_len);
1000
1001 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1002 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001003 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1004 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1005 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001006 return;
1007 }
1008 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1009 i_bootstrap, i_bootstrap_len);
1010
1011 /* Try to find own and peer bootstrapping key matches based on the
1012 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001013 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
1014 r_bootstrap, &own_bi, &peer_bi);
Hai Shalom81f62d82019-07-22 12:10:00 -07001015#ifdef CONFIG_DPP2
1016 if (!own_bi) {
1017 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1018 src, hdr, buf, len, freq, i_bootstrap,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001019 r_bootstrap, hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07001020 return;
1021 }
1022#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001023 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001024 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1025 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001026 return;
1027 }
1028
1029 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001030 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1031 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001032 return;
1033 }
1034
1035 hapd->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001036 hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
1037 hapd->msg_ctx, hapd->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001038 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001039 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001040 if (!hapd->dpp_auth) {
1041 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1042 return;
1043 }
1044 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001045 if (dpp_set_configurator(hapd->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001046 hapd->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001047 dpp_auth_deinit(hapd->dpp_auth);
1048 hapd->dpp_auth = NULL;
1049 return;
1050 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001051 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1052
Roshan Pius3a1667e2018-07-03 15:17:14 -07001053 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1054 " freq=%u type=%d",
1055 MAC2STR(src), hapd->dpp_auth->curr_freq,
1056 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001057 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
1058 src, wpabuf_head(hapd->dpp_auth->resp_msg),
1059 wpabuf_len(hapd->dpp_auth->resp_msg));
1060}
1061
1062
Roshan Pius3a1667e2018-07-03 15:17:14 -07001063static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
Hai Shalomc3565922019-10-28 11:58:20 -07001064 struct dpp_authentication *auth,
1065 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001066{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001067 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001068 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001069 dpp_akm_str(conf->akm));
1070 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001071 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001072 wpa_ssid_txt(conf->ssid, conf->ssid_len));
1073 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001074 /* TODO: Save the Connector and consider using a command
1075 * to fetch the value instead of sending an event with
1076 * it. The Connector could end up being larger than what
1077 * most clients are ready to receive as an event
1078 * message. */
1079 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001080 conf->connector);
Hai Shalomfdcde762020-04-02 11:19:20 -07001081 }
1082 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001083 char hex[64 * 2 + 1];
1084
1085 wpa_snprintf_hex(hex, sizeof(hex),
Hai Shalomc3565922019-10-28 11:58:20 -07001086 (const u8 *) conf->passphrase,
1087 os_strlen(conf->passphrase));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001088 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1089 hex);
Hai Shalomc3565922019-10-28 11:58:20 -07001090 } else if (conf->psk_set) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001091 char hex[PMK_LEN * 2 + 1];
1092
Hai Shalomc3565922019-10-28 11:58:20 -07001093 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001094 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1095 hex);
1096 }
Hai Shalomc3565922019-10-28 11:58:20 -07001097 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001098 char *hex;
1099 size_t hexlen;
1100
Hai Shalomc3565922019-10-28 11:58:20 -07001101 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001102 hex = os_malloc(hexlen);
1103 if (hex) {
1104 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001105 wpabuf_head(conf->c_sign_key),
1106 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001107 wpa_msg(hapd->msg_ctx, MSG_INFO,
1108 DPP_EVENT_C_SIGN_KEY "%s", hex);
1109 os_free(hex);
1110 }
1111 }
1112 if (auth->net_access_key) {
1113 char *hex;
1114 size_t hexlen;
1115
1116 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1117 hex = os_malloc(hexlen);
1118 if (hex) {
1119 wpa_snprintf_hex(hex, hexlen,
1120 wpabuf_head(auth->net_access_key),
1121 wpabuf_len(auth->net_access_key));
1122 if (auth->net_access_key_expiry)
1123 wpa_msg(hapd->msg_ctx, MSG_INFO,
1124 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1125 (unsigned long)
1126 auth->net_access_key_expiry);
1127 else
1128 wpa_msg(hapd->msg_ctx, MSG_INFO,
1129 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1130 os_free(hex);
1131 }
1132 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001133}
1134
1135
Hai Shalomfdcde762020-04-02 11:19:20 -07001136static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
1137 struct dpp_asymmetric_key *key)
1138{
1139#ifdef CONFIG_DPP2
1140 int res;
1141
1142 if (!key)
1143 return 0;
1144
1145 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1146 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
1147
1148 while (key) {
1149 res = dpp_configurator_from_backup(
1150 hapd->iface->interfaces->dpp, key);
1151 if (res < 0)
1152 return -1;
1153 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1154 res);
1155 key = key->next;
1156 }
1157#endif /* CONFIG_DPP2 */
1158
1159 return 0;
1160}
1161
1162
Roshan Pius3a1667e2018-07-03 15:17:14 -07001163static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1164 enum gas_query_ap_result result,
1165 const struct wpabuf *adv_proto,
1166 const struct wpabuf *resp, u16 status_code)
1167{
1168 struct hostapd_data *hapd = ctx;
1169 const u8 *pos;
1170 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001171 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001172
1173 if (!auth || !auth->auth_success) {
1174 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1175 return;
1176 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001177 if (result != GAS_QUERY_AP_SUCCESS ||
1178 !resp || status_code != WLAN_STATUS_SUCCESS) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001179 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1180 goto fail;
1181 }
1182
1183 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1184 adv_proto);
1185 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1186 resp);
1187
1188 if (wpabuf_len(adv_proto) != 10 ||
1189 !(pos = wpabuf_head(adv_proto)) ||
1190 pos[0] != WLAN_EID_ADV_PROTO ||
1191 pos[1] != 8 ||
1192 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1193 pos[4] != 5 ||
1194 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1195 pos[8] != 0x1a ||
1196 pos[9] != 1) {
1197 wpa_printf(MSG_DEBUG,
1198 "DPP: Not a DPP Advertisement Protocol ID");
1199 goto fail;
1200 }
1201
1202 if (dpp_conf_resp_rx(auth, resp) < 0) {
1203 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1204 goto fail;
1205 }
1206
Hai Shalomc3565922019-10-28 11:58:20 -07001207 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Hai Shalomfdcde762020-04-02 11:19:20 -07001208 if (hostapd_dpp_handle_key_pkg(hapd, auth->conf_key_pkg) < 0)
1209 goto fail;
1210
Hai Shalom021b0b52019-04-10 11:17:58 -07001211 status = DPP_STATUS_OK;
1212#ifdef CONFIG_TESTING_OPTIONS
1213 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1214 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1215 status = DPP_STATUS_CONFIG_REJECTED;
1216 }
1217#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001218fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001219 if (status != DPP_STATUS_OK)
1220 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1221#ifdef CONFIG_DPP2
1222 if (auth->peer_version >= 2 &&
1223 auth->conf_resp_status == DPP_STATUS_OK) {
1224 struct wpabuf *msg;
1225
1226 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1227 msg = dpp_build_conf_result(auth, status);
1228 if (!msg)
1229 goto fail2;
1230
1231 wpa_msg(hapd->msg_ctx, MSG_INFO,
1232 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1233 MAC2STR(addr), auth->curr_freq,
1234 DPP_PA_CONFIGURATION_RESULT);
1235 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
1236 addr, wpabuf_head(msg),
1237 wpabuf_len(msg));
1238 wpabuf_free(msg);
1239
1240 /* This exchange will be terminated in the TX status handler */
1241 auth->connect_on_tx_status = 1;
1242 return;
1243 }
1244fail2:
1245#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001246 dpp_auth_deinit(hapd->dpp_auth);
1247 hapd->dpp_auth = NULL;
1248}
1249
1250
1251static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
1252{
1253 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001254 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001255 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001256
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001257 buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
1258 DPP_NETROLE_AP,
Hai Shalomc3565922019-10-28 11:58:20 -07001259 hapd->conf->dpp_mud_url, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001260 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001261 wpa_printf(MSG_DEBUG,
1262 "DPP: No configuration request data available");
1263 return;
1264 }
1265
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001266 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1267 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1268
1269 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
1270 buf, hostapd_dpp_gas_resp_cb, hapd);
1271 if (res < 0) {
1272 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1273 "GAS: Failed to send Query Request");
1274 wpabuf_free(buf);
1275 } else {
1276 wpa_printf(MSG_DEBUG,
1277 "DPP: GAS query started with dialog token %u", res);
1278 }
1279}
1280
1281
1282static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
1283{
1284 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1285 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
1286 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001287#ifdef CONFIG_TESTING_OPTIONS
1288 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1289 wpa_printf(MSG_INFO,
1290 "DPP: TESTING - stop at Authentication Confirm");
1291 if (hapd->dpp_auth->configurator) {
1292 /* Prevent GAS response */
1293 hapd->dpp_auth->auth_success = 0;
1294 }
1295 return;
1296 }
1297#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001298
1299 if (!hapd->dpp_auth->configurator)
1300 hostapd_dpp_start_gas_client(hapd);
1301}
1302
1303
1304static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001305 const u8 *hdr, const u8 *buf, size_t len,
1306 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001307{
1308 struct dpp_authentication *auth = hapd->dpp_auth;
1309 struct wpabuf *msg;
1310
1311 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
1312 MAC2STR(src));
1313
1314 if (!auth) {
1315 wpa_printf(MSG_DEBUG,
1316 "DPP: No DPP Authentication in progress - drop");
1317 return;
1318 }
1319
1320 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1321 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1322 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1323 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1324 return;
1325 }
1326
Roshan Pius3a1667e2018-07-03 15:17:14 -07001327 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1328
1329 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1330 wpa_printf(MSG_DEBUG,
1331 "DPP: Responder accepted request for different negotiation channel");
1332 auth->curr_freq = freq;
1333 }
1334
1335 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001336 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1337 if (!msg) {
1338 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1339 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
1340 return;
1341 }
1342 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1343 return;
1344 }
1345 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1346
Roshan Pius3a1667e2018-07-03 15:17:14 -07001347 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1348 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
1349 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001350 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
1351 wpabuf_head(msg), wpabuf_len(msg));
1352 wpabuf_free(msg);
1353 hapd->dpp_auth_ok_on_ack = 1;
1354}
1355
1356
1357static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1358 const u8 *hdr, const u8 *buf, size_t len)
1359{
1360 struct dpp_authentication *auth = hapd->dpp_auth;
1361
1362 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1363 MAC2STR(src));
1364
1365 if (!auth) {
1366 wpa_printf(MSG_DEBUG,
1367 "DPP: No DPP Authentication in progress - drop");
1368 return;
1369 }
1370
1371 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1372 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1373 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1374 return;
1375 }
1376
1377 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1378 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1379 return;
1380 }
1381
1382 hostapd_dpp_auth_success(hapd, 0);
1383}
1384
1385
Hai Shalom021b0b52019-04-10 11:17:58 -07001386#ifdef CONFIG_DPP2
1387
1388static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
1389 void *timeout_ctx)
1390{
1391 struct hostapd_data *hapd = eloop_ctx;
1392 struct dpp_authentication *auth = hapd->dpp_auth;
1393
1394 if (!auth || !auth->waiting_conf_result)
1395 return;
1396
1397 wpa_printf(MSG_DEBUG,
1398 "DPP: Timeout while waiting for Configuration Result");
1399 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1400 dpp_auth_deinit(auth);
1401 hapd->dpp_auth = NULL;
1402}
1403
1404
Hai Shalomc3565922019-10-28 11:58:20 -07001405static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1406 void *timeout_ctx)
1407{
1408 struct hostapd_data *hapd = eloop_ctx;
1409 struct dpp_authentication *auth = hapd->dpp_auth;
1410
1411 if (!auth || !auth->waiting_conf_result)
1412 return;
1413
1414 wpa_printf(MSG_DEBUG,
1415 "DPP: Timeout while waiting for Connection Status Result");
1416 wpa_msg(hapd->msg_ctx, MSG_INFO,
1417 DPP_EVENT_CONN_STATUS_RESULT "timeout");
1418 dpp_auth_deinit(auth);
1419 hapd->dpp_auth = NULL;
1420}
1421
1422
Hai Shalom021b0b52019-04-10 11:17:58 -07001423static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
1424 const u8 *hdr, const u8 *buf, size_t len)
1425{
1426 struct dpp_authentication *auth = hapd->dpp_auth;
1427 enum dpp_status_error status;
1428
1429 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1430 MAC2STR(src));
1431
1432 if (!auth || !auth->waiting_conf_result) {
1433 wpa_printf(MSG_DEBUG,
1434 "DPP: No DPP Configuration waiting for result - drop");
1435 return;
1436 }
1437
1438 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1439 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1440 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1441 return;
1442 }
1443
1444 status = dpp_conf_result_rx(auth, hdr, buf, len);
1445
Hai Shalomc3565922019-10-28 11:58:20 -07001446 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1447 wpa_msg(hapd->msg_ctx, MSG_INFO,
1448 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1449 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1450 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1451 hapd, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001452 auth->waiting_conn_status_result = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001453 eloop_cancel_timeout(
1454 hostapd_dpp_conn_status_result_wait_timeout,
1455 hapd, NULL);
1456 eloop_register_timeout(
1457 16, 0, hostapd_dpp_conn_status_result_wait_timeout,
1458 hapd, NULL);
1459 return;
1460 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001461 hostapd_drv_send_action_cancel_wait(hapd);
1462 hostapd_dpp_listen_stop(hapd);
1463 if (status == DPP_STATUS_OK)
1464 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1465 else
1466 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1467 dpp_auth_deinit(auth);
1468 hapd->dpp_auth = NULL;
1469 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1470 NULL);
1471}
1472
Hai Shalomc3565922019-10-28 11:58:20 -07001473
1474static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
1475 const u8 *src, const u8 *hdr,
1476 const u8 *buf, size_t len)
1477{
1478 struct dpp_authentication *auth = hapd->dpp_auth;
1479 enum dpp_status_error status;
1480 u8 ssid[SSID_MAX_LEN];
1481 size_t ssid_len = 0;
1482 char *channel_list = NULL;
1483
1484 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1485
1486 if (!auth || !auth->waiting_conn_status_result) {
1487 wpa_printf(MSG_DEBUG,
1488 "DPP: No DPP Configuration waiting for connection status result - drop");
1489 return;
1490 }
1491
1492 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1493 ssid, &ssid_len, &channel_list);
1494 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1495 "result=%d ssid=%s channel_list=%s",
1496 status, wpa_ssid_txt(ssid, ssid_len),
1497 channel_list ? channel_list : "N/A");
1498 os_free(channel_list);
1499 hostapd_drv_send_action_cancel_wait(hapd);
1500 hostapd_dpp_listen_stop(hapd);
1501 dpp_auth_deinit(auth);
1502 hapd->dpp_auth = NULL;
1503 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
1504 hapd, NULL);
1505}
1506
1507
Hai Shalomfdcde762020-04-02 11:19:20 -07001508static void
1509hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
1510 const u8 *hdr, const u8 *buf, size_t len,
1511 unsigned int freq)
1512{
1513 const u8 *r_bootstrap;
1514 u16 r_bootstrap_len;
1515 struct dpp_bootstrap_info *peer_bi;
1516 struct dpp_authentication *auth;
1517
1518 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
1519 MAC2STR(src));
1520
1521 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1522 &r_bootstrap_len);
1523 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1524 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1525 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1526 return;
1527 }
1528 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1529 r_bootstrap, r_bootstrap_len);
1530 peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
1531 r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07001532 dpp_notify_chirp_received(hapd->msg_ctx,
1533 peer_bi ? (int) peer_bi->id : -1,
1534 src, freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07001535 if (!peer_bi) {
1536 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1537 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001538 r_bootstrap, hapd) == 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07001539 return;
1540 wpa_printf(MSG_DEBUG,
1541 "DPP: No matching bootstrapping information found");
1542 return;
1543 }
1544
1545 if (hapd->dpp_auth) {
1546 wpa_printf(MSG_DEBUG,
1547 "DPP: Ignore Presence Announcement during ongoing Authentication");
1548 return;
1549 }
1550
1551 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1552 peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
1553 0);
1554 if (!auth)
1555 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07001556 hostapd_dpp_set_testing_options(hapd, auth);
1557 if (dpp_set_configurator(auth,
Hai Shalomfdcde762020-04-02 11:19:20 -07001558 hapd->dpp_configurator_params) < 0) {
1559 dpp_auth_deinit(auth);
1560 return;
1561 }
1562
1563 auth->neg_freq = freq;
1564
Hai Shalom60840252021-02-19 19:02:11 -08001565 /* The source address of the Presence Announcement frame overrides any
1566 * MAC address information from the bootstrapping information. */
1567 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07001568
1569 hapd->dpp_auth = auth;
1570 if (hostapd_dpp_auth_init_next(hapd) < 0) {
1571 dpp_auth_deinit(hapd->dpp_auth);
1572 hapd->dpp_auth = NULL;
1573 }
1574}
1575
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001576
1577static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
1578 void *timeout_ctx)
1579{
1580 struct hostapd_data *hapd = eloop_ctx;
1581 struct dpp_authentication *auth = hapd->dpp_auth;
1582
1583 if (!auth)
1584 return;
1585
1586 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
1587 hostapd_dpp_listen_stop(hapd);
1588 dpp_auth_deinit(auth);
1589 hapd->dpp_auth = NULL;
1590}
1591
1592
1593static void
1594hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
1595 const u8 *hdr, const u8 *buf, size_t len,
1596 unsigned int freq)
1597{
Hai Shalom899fcc72020-10-19 14:38:18 -07001598 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
1599 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001600 struct dpp_configurator *conf;
1601 struct dpp_authentication *auth;
1602 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07001603 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001604
1605 if (hapd->dpp_auth) {
1606 wpa_printf(MSG_DEBUG,
1607 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1608 return;
1609 }
1610
1611 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
1612 MAC2STR(src));
1613
1614 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1615 &csign_hash_len);
1616 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
1617 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1618 "Missing or invalid required Configurator C-sign key Hash attribute");
1619 return;
1620 }
1621 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1622 csign_hash, csign_hash_len);
1623 conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
1624 csign_hash);
1625 if (!conf) {
1626 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1627 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001628 NULL, hapd) == 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001629 return;
1630 wpa_printf(MSG_DEBUG,
1631 "DPP: No matching Configurator information found");
1632 return;
1633 }
1634
Hai Shalom899fcc72020-10-19 14:38:18 -07001635 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
1636 &fcgroup_len);
1637 if (!fcgroup || fcgroup_len != 2) {
1638 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1639 "Missing or invalid required Finite Cyclic Group attribute");
1640 return;
1641 }
1642 group = WPA_GET_LE16(fcgroup);
1643 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
1644
1645 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
1646 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
1647
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001648 auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
Hai Shalom899fcc72020-10-19 14:38:18 -07001649 conf, freq, group, a_nonce, a_nonce_len,
1650 e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001651 if (!auth)
1652 return;
1653 hostapd_dpp_set_testing_options(hapd, auth);
1654 if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
1655 dpp_auth_deinit(auth);
1656 return;
1657 }
1658
1659 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1660 hapd->dpp_auth = auth;
1661
1662 hapd->dpp_in_response_listen = 0;
1663 hapd->dpp_auth_ok_on_ack = 0;
1664 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
1665 max_wait_time = hapd->dpp_resp_wait_time ?
1666 hapd->dpp_resp_wait_time : 2000;
1667 if (wait_time > max_wait_time)
1668 wait_time = max_wait_time;
1669 wait_time += 10; /* give the driver some extra time to complete */
1670 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
1671 hostapd_dpp_reconfig_reply_wait_timeout,
1672 hapd, NULL);
1673 wait_time -= 10;
1674
1675 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1676 " freq=%u type=%d",
1677 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
1678 if (hostapd_drv_send_action(hapd, freq, wait_time, src,
1679 wpabuf_head(auth->reconfig_req_msg),
1680 wpabuf_len(auth->reconfig_req_msg)) < 0) {
1681 dpp_auth_deinit(hapd->dpp_auth);
1682 hapd->dpp_auth = NULL;
1683 }
1684}
1685
1686
1687static void
1688hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
1689 const u8 *hdr, const u8 *buf, size_t len,
1690 unsigned int freq)
1691{
1692 struct dpp_authentication *auth = hapd->dpp_auth;
1693 struct wpabuf *conf;
1694
1695 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
1696 MACSTR, MAC2STR(src));
1697
1698 if (!auth || !auth->reconfig || !auth->configurator) {
1699 wpa_printf(MSG_DEBUG,
1700 "DPP: No DPP Reconfig Authentication in progress - drop");
1701 return;
1702 }
1703
1704 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1705 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1706 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1707 return;
1708 }
1709
1710 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
1711 if (!conf)
1712 return;
1713
1714 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1715 hapd, NULL);
1716
1717 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1718 " freq=%u type=%d",
1719 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
1720 if (hostapd_drv_send_action(hapd, freq, 500, src,
1721 wpabuf_head(conf), wpabuf_len(conf)) < 0) {
1722 wpabuf_free(conf);
1723 dpp_auth_deinit(hapd->dpp_auth);
1724 hapd->dpp_auth = NULL;
1725 return;
1726 }
1727 wpabuf_free(conf);
1728}
1729
Hai Shalom021b0b52019-04-10 11:17:58 -07001730#endif /* CONFIG_DPP2 */
1731
1732
Roshan Pius3a1667e2018-07-03 15:17:14 -07001733static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1734 const u8 *src, unsigned int freq,
1735 u8 trans_id,
1736 enum dpp_status_error status)
1737{
1738 struct wpabuf *msg;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001739 size_t len;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001740
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001741 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
1742#ifdef CONFIG_DPP2
1743 len += 5;
1744#endif /* CONFIG_DPP2 */
1745 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001746 if (!msg)
1747 return;
1748
1749#ifdef CONFIG_TESTING_OPTIONS
1750 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1751 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1752 goto skip_trans_id;
1753 }
1754 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1755 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1756 trans_id ^= 0x01;
1757 }
1758#endif /* CONFIG_TESTING_OPTIONS */
1759
1760 /* Transaction ID */
1761 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1762 wpabuf_put_le16(msg, 1);
1763 wpabuf_put_u8(msg, trans_id);
1764
1765#ifdef CONFIG_TESTING_OPTIONS
1766skip_trans_id:
1767 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1768 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1769 goto skip_status;
1770 }
1771 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1772 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1773 status = 254;
1774 }
1775#endif /* CONFIG_TESTING_OPTIONS */
1776
1777 /* DPP Status */
1778 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1779 wpabuf_put_le16(msg, 1);
1780 wpabuf_put_u8(msg, status);
1781
1782#ifdef CONFIG_TESTING_OPTIONS
1783skip_status:
1784 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1785 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1786 goto skip_connector;
1787 }
1788 if (status == DPP_STATUS_OK &&
1789 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1790 char *connector;
1791
1792 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1793 connector = dpp_corrupt_connector_signature(
1794 hapd->conf->dpp_connector);
1795 if (!connector) {
1796 wpabuf_free(msg);
1797 return;
1798 }
1799 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1800 wpabuf_put_le16(msg, os_strlen(connector));
1801 wpabuf_put_str(msg, connector);
1802 os_free(connector);
1803 goto skip_connector;
1804 }
1805#endif /* CONFIG_TESTING_OPTIONS */
1806
1807 /* DPP Connector */
1808 if (status == DPP_STATUS_OK) {
1809 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1810 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1811 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1812 }
1813
1814#ifdef CONFIG_TESTING_OPTIONS
1815skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001816 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP) {
1817 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
1818 goto skip_proto_ver;
1819 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001820#endif /* CONFIG_TESTING_OPTIONS */
1821
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001822#ifdef CONFIG_DPP2
1823 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001824 u8 ver = DPP_VERSION;
1825#ifdef CONFIG_DPP3
1826 int conn_ver;
1827
1828 conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
1829 if (conn_ver > 0 && ver != conn_ver) {
1830 wpa_printf(MSG_DEBUG,
1831 "DPP: Use Connector version %d instead of current protocol version %d",
1832 conn_ver, ver);
1833 ver = conn_ver;
1834 }
1835#endif /* CONFIG_DPP3 */
1836
1837#ifdef CONFIG_TESTING_OPTIONS
1838 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP) {
1839 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
1840 ver = 1;
1841 }
1842#endif /* CONFIG_TESTING_OPTIONS */
1843
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001844 /* Protocol Version */
1845 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
1846 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001847 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001848 }
1849#endif /* CONFIG_DPP2 */
1850
Hai Shaloma20dcd72022-02-04 13:43:00 -08001851#ifdef CONFIG_TESTING_OPTIONS
1852skip_proto_ver:
1853#endif /* CONFIG_TESTING_OPTIONS */
1854
Roshan Pius3a1667e2018-07-03 15:17:14 -07001855 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1856 " status=%d", MAC2STR(src), status);
1857 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1858 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1859 DPP_PA_PEER_DISCOVERY_RESP, status);
1860 hostapd_drv_send_action(hapd, freq, 0, src,
1861 wpabuf_head(msg), wpabuf_len(msg));
1862 wpabuf_free(msg);
1863}
1864
1865
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001866static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1867 const u8 *src,
1868 const u8 *buf, size_t len,
1869 unsigned int freq)
1870{
1871 const u8 *connector, *trans_id;
1872 u16 connector_len, trans_id_len;
1873 struct os_time now;
1874 struct dpp_introduction intro;
1875 os_time_t expire;
1876 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001877 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001878
1879 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1880 MAC2STR(src));
1881 if (!hapd->wpa_auth ||
1882 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1883 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1884 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1885 return;
1886 }
1887
1888 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1889 !hapd->conf->dpp_csign) {
1890 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1891 return;
1892 }
1893
1894 os_get_time(&now);
1895
1896 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001897 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001898 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1899 return;
1900 }
1901
1902 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1903 &trans_id_len);
1904 if (!trans_id || trans_id_len != 1) {
1905 wpa_printf(MSG_DEBUG,
1906 "DPP: Peer did not include Transaction ID");
1907 return;
1908 }
1909
1910 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1911 if (!connector) {
1912 wpa_printf(MSG_DEBUG,
1913 "DPP: Peer did not include its Connector");
1914 return;
1915 }
1916
Roshan Pius3a1667e2018-07-03 15:17:14 -07001917 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1918 wpabuf_head(hapd->conf->dpp_netaccesskey),
1919 wpabuf_len(hapd->conf->dpp_netaccesskey),
1920 wpabuf_head(hapd->conf->dpp_csign),
1921 wpabuf_len(hapd->conf->dpp_csign),
1922 connector, connector_len, &expire);
1923 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001924 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001925 "DPP: Network Introduction protocol resulted in internal failure (peer "
1926 MACSTR ")", MAC2STR(src));
1927 return;
1928 }
1929 if (res != DPP_STATUS_OK) {
1930 wpa_printf(MSG_INFO,
1931 "DPP: Network Introduction protocol resulted in failure (peer "
1932 MACSTR " status %d)", MAC2STR(src), res);
1933 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1934 res);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001935 return;
1936 }
1937
Hai Shaloma20dcd72022-02-04 13:43:00 -08001938#ifdef CONFIG_DPP3
1939 if (intro.peer_version && intro.peer_version >= 2) {
1940 const u8 *version;
1941 u16 version_len;
1942 u8 attr_version = 1;
1943
1944 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
1945 &version_len);
1946 if (version && version_len >= 1)
1947 attr_version = version[0];
1948 if (attr_version != intro.peer_version) {
1949 wpa_printf(MSG_INFO,
1950 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
1951 intro.peer_version, attr_version);
1952 hostapd_dpp_send_peer_disc_resp(hapd, src, freq,
1953 trans_id[0],
1954 DPP_STATUS_NO_MATCH);
1955 return;
1956 }
1957 }
1958#endif /* CONFIG_DPP3 */
1959
Roshan Pius3a1667e2018-07-03 15:17:14 -07001960 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001961 expire = hapd->conf->dpp_netaccesskey_expiry;
1962 if (expire)
1963 expiration = expire - now.sec;
1964 else
1965 expiration = 0;
1966
1967 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1968 intro.pmkid, expiration,
1969 WPA_KEY_MGMT_DPP) < 0) {
1970 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
1971 return;
1972 }
1973
Roshan Pius3a1667e2018-07-03 15:17:14 -07001974 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1975 DPP_STATUS_OK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001976}
1977
1978
1979static void
1980hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001981 const u8 *hdr, const u8 *buf, size_t len,
1982 unsigned int freq, bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001983{
1984 struct wpabuf *msg;
1985
1986 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1987 MAC2STR(src));
1988
1989 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1990 * values here */
1991
1992 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
1993 wpa_printf(MSG_DEBUG,
1994 "DPP: No PKEX code configured - ignore request");
Hai Shaloma20dcd72022-02-04 13:43:00 -08001995 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001996 }
1997
1998 if (hapd->dpp_pkex) {
1999 /* TODO: Support parallel operations */
2000 wpa_printf(MSG_DEBUG,
2001 "DPP: Already in PKEX session - ignore new request");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002002 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002003 }
2004
Roshan Pius3a1667e2018-07-03 15:17:14 -07002005 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
2006 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002007 hapd->own_addr, src,
2008 hapd->dpp_pkex_identifier,
2009 hapd->dpp_pkex_code,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002010 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002011 if (!hapd->dpp_pkex) {
2012 wpa_printf(MSG_DEBUG,
2013 "DPP: Failed to process the request - ignore it");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002014 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002015 }
2016
2017 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002018 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2019 " freq=%u type=%d", MAC2STR(src), freq,
2020 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002021 hostapd_drv_send_action(hapd, freq, 0, src,
2022 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002023 if (hapd->dpp_pkex->failed) {
2024 wpa_printf(MSG_DEBUG,
2025 "DPP: Terminate PKEX exchange due to an earlier error");
2026 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
2027 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
2028 dpp_pkex_free(hapd->dpp_pkex);
2029 hapd->dpp_pkex = NULL;
2030 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002031
2032 return;
2033
2034try_relay:
2035#ifdef CONFIG_DPP2
2036 if (v2)
2037 dpp_relay_rx_action(hapd->iface->interfaces->dpp,
2038 src, hdr, buf, len, freq, NULL, NULL, hapd);
2039#else /* CONFIG_DPP2 */
2040 wpa_printf(MSG_DEBUG, "DPP: No relay functionality included - skip");
2041#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002042}
2043
2044
2045static void
2046hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
2047 const u8 *buf, size_t len, unsigned int freq)
2048{
2049 struct wpabuf *msg;
2050
2051 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2052 MAC2STR(src));
2053
2054 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2055 * values here */
2056
2057 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
2058 hapd->dpp_pkex->exchange_done) {
2059 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2060 return;
2061 }
2062
Hai Shaloma20dcd72022-02-04 13:43:00 -08002063 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
2064 hapd->dpp_pkex->exch_req_wait_time = 0;
2065
Roshan Pius3a1667e2018-07-03 15:17:14 -07002066 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002067 if (!msg) {
2068 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2069 return;
2070 }
2071
2072 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
2073 MAC2STR(src));
2074
Roshan Pius3a1667e2018-07-03 15:17:14 -07002075 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2076 " freq=%u type=%d", MAC2STR(src), freq,
2077 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002078 hostapd_drv_send_action(hapd, freq, 0, src,
2079 wpabuf_head(msg), wpabuf_len(msg));
2080 wpabuf_free(msg);
2081}
2082
2083
2084static void
2085hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
2086 const u8 *hdr, const u8 *buf, size_t len,
2087 unsigned int freq)
2088{
2089 struct wpabuf *msg;
2090 struct dpp_pkex *pkex = hapd->dpp_pkex;
2091 struct dpp_bootstrap_info *bi;
2092
2093 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
2094 MAC2STR(src));
2095
2096 if (!pkex || pkex->initiator || !pkex->exchange_done) {
2097 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2098 return;
2099 }
2100
2101 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
2102 if (!msg) {
2103 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002104 if (hapd->dpp_pkex->failed) {
2105 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
2106 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
2107 hapd->dpp_pkex->own_bi->pkex_t =
2108 hapd->dpp_pkex->t;
2109 dpp_pkex_free(hapd->dpp_pkex);
2110 hapd->dpp_pkex = NULL;
2111 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002112 return;
2113 }
2114
2115 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
2116 MACSTR, MAC2STR(src));
2117
Roshan Pius3a1667e2018-07-03 15:17:14 -07002118 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2119 " freq=%u type=%d", MAC2STR(src), freq,
2120 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002121 hostapd_drv_send_action(hapd, freq, 0, src,
2122 wpabuf_head(msg), wpabuf_len(msg));
2123 wpabuf_free(msg);
2124
Hai Shalom021b0b52019-04-10 11:17:58 -07002125 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002126 if (!bi)
2127 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002128 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002129}
2130
2131
2132static void
2133hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
2134 const u8 *hdr, const u8 *buf, size_t len,
2135 unsigned int freq)
2136{
2137 int res;
Hai Shalom021b0b52019-04-10 11:17:58 -07002138 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002139 struct dpp_pkex *pkex = hapd->dpp_pkex;
2140 char cmd[500];
2141
2142 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2143 MAC2STR(src));
2144
2145 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2146 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2147 return;
2148 }
2149
2150 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2151 if (res < 0) {
2152 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2153 return;
2154 }
2155
Hai Shalom021b0b52019-04-10 11:17:58 -07002156 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002157 if (!bi)
2158 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002159 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002160
2161 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2162 bi->id,
2163 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
2164 wpa_printf(MSG_DEBUG,
2165 "DPP: Start authentication after PKEX with parameters: %s",
2166 cmd);
2167 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
2168 wpa_printf(MSG_DEBUG,
2169 "DPP: Authentication initialization failed");
2170 return;
2171 }
2172}
2173
2174
2175void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
2176 const u8 *buf, size_t len, unsigned int freq)
2177{
2178 u8 crypto_suite;
2179 enum dpp_public_action_frame_type type;
2180 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002181 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002182
2183 if (len < DPP_HDR_LEN)
2184 return;
2185 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2186 return;
2187 hdr = buf;
2188 buf += 4;
2189 len -= 4;
2190 crypto_suite = *buf++;
2191 type = *buf++;
2192 len -= 2;
2193
2194 wpa_printf(MSG_DEBUG,
2195 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2196 MACSTR " freq=%u",
2197 crypto_suite, type, MAC2STR(src), freq);
2198 if (crypto_suite != 1) {
2199 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2200 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002201 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2202 " freq=%u type=%d ignore=unsupported-crypto-suite",
2203 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002204 return;
2205 }
2206 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002207 if (dpp_check_attrs(buf, len) < 0) {
2208 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2209 " freq=%u type=%d ignore=invalid-attributes",
2210 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002211 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002212 }
2213 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2214 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002215
Hai Shalom81f62d82019-07-22 12:10:00 -07002216#ifdef CONFIG_DPP2
2217 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002218 src, hdr, buf, len, freq, NULL, NULL,
2219 hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07002220 return;
2221#endif /* CONFIG_DPP2 */
2222
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002223 switch (type) {
2224 case DPP_PA_AUTHENTICATION_REQ:
2225 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
2226 break;
2227 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002228 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002229 break;
2230 case DPP_PA_AUTHENTICATION_CONF:
2231 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
2232 break;
2233 case DPP_PA_PEER_DISCOVERY_REQ:
2234 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
2235 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002236#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002237 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002238 /* This is for PKEXv2, but for now, process only with
2239 * CONFIG_DPP3 to avoid issues with a capability that has not
2240 * been tested with other implementations. */
2241 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
2242 true);
2243 break;
2244#endif /* CONFIG_DPP3 */
2245 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
2246 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
2247 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002248 break;
2249 case DPP_PA_PKEX_EXCHANGE_RESP:
2250 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
2251 break;
2252 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2253 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
2254 freq);
2255 break;
2256 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2257 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
2258 freq);
2259 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002260#ifdef CONFIG_DPP2
2261 case DPP_PA_CONFIGURATION_RESULT:
2262 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
2263 break;
Hai Shalomc3565922019-10-28 11:58:20 -07002264 case DPP_PA_CONNECTION_STATUS_RESULT:
2265 hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
2266 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07002267 case DPP_PA_PRESENCE_ANNOUNCEMENT:
2268 hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
2269 freq);
2270 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002271 case DPP_PA_RECONFIG_ANNOUNCEMENT:
2272 hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
2273 freq);
2274 break;
2275 case DPP_PA_RECONFIG_AUTH_RESP:
2276 hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
2277 freq);
2278 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002279#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002280 default:
2281 wpa_printf(MSG_DEBUG,
2282 "DPP: Ignored unsupported frame subtype %d", type);
2283 break;
2284 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002285
2286 if (hapd->dpp_pkex)
2287 pkex_t = hapd->dpp_pkex->t;
2288 else if (hapd->dpp_pkex_bi)
2289 pkex_t = hapd->dpp_pkex_bi->pkex_t;
2290 else
2291 pkex_t = 0;
2292 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2293 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2294 hostapd_dpp_pkex_remove(hapd, "*");
2295 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002296}
2297
2298
2299struct wpabuf *
2300hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
Hai Shalom81f62d82019-07-22 12:10:00 -07002301 const u8 *query, size_t query_len,
2302 const u8 *data, size_t data_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002303{
2304 struct dpp_authentication *auth = hapd->dpp_auth;
2305 struct wpabuf *resp;
2306
2307 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002308 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002309 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002310#ifdef CONFIG_DPP2
2311 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
2312 data_len) == 0) {
2313 /* Response will be forwarded once received over TCP */
2314 return NULL;
2315 }
2316#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002317 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2318 return NULL;
2319 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002320
2321 if (hapd->dpp_auth_ok_on_ack && auth->configurator) {
2322 wpa_printf(MSG_DEBUG,
2323 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
2324 /* hostapd_dpp_auth_success() would normally have been called
2325 * from TX status handler, but since there was no such handler
2326 * call yet, simply send out the event message and proceed with
2327 * exchange. */
2328 wpa_msg(hapd->msg_ctx, MSG_INFO,
2329 DPP_EVENT_AUTH_SUCCESS "init=1");
2330 hapd->dpp_auth_ok_on_ack = 0;
2331 }
2332
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002333 wpa_hexdump(MSG_DEBUG,
2334 "DPP: Received Configuration Request (GAS Query Request)",
2335 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002336 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2337 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002338 resp = dpp_conf_req_rx(auth, query, query_len);
2339 if (!resp)
2340 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
2341 return resp;
2342}
2343
2344
Roshan Pius3a1667e2018-07-03 15:17:14 -07002345void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
2346{
Hai Shalom021b0b52019-04-10 11:17:58 -07002347 struct dpp_authentication *auth = hapd->dpp_auth;
2348
2349 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07002350 return;
2351
Hai Shalom021b0b52019-04-10 11:17:58 -07002352 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2353 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002354 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08002355 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002356 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002357#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002358 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
2359 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002360 if (ok && auth->peer_version >= 2 &&
2361 auth->conf_resp_status == DPP_STATUS_OK) {
2362 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
2363 auth->waiting_conf_result = 1;
2364 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
2365 hapd, NULL);
2366 eloop_register_timeout(2, 0,
2367 hostapd_dpp_config_result_wait_timeout,
2368 hapd, NULL);
2369 return;
2370 }
2371#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002372 hostapd_drv_send_action_cancel_wait(hapd);
2373
2374 if (ok)
2375 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
2376 else
2377 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
2378 dpp_auth_deinit(hapd->dpp_auth);
2379 hapd->dpp_auth = NULL;
2380}
2381
2382
Roshan Pius3a1667e2018-07-03 15:17:14 -07002383int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
2384{
2385 struct dpp_authentication *auth;
2386 int ret = -1;
2387 char *curve = NULL;
2388
Hai Shalomfdcde762020-04-02 11:19:20 -07002389 auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002390 if (!auth)
2391 return -1;
2392
2393 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08002394 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07002395 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08002396 dpp_configurator_own_config(auth, curve, 1) == 0) {
Hai Shalomc3565922019-10-28 11:58:20 -07002397 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002398 ret = 0;
2399 }
2400
2401 dpp_auth_deinit(auth);
2402 os_free(curve);
2403
2404 return ret;
2405}
2406
2407
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002408int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
2409{
2410 struct dpp_bootstrap_info *own_bi;
2411 const char *pos, *end;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002412 int tcp_port = DPP_TCP_PORT;
2413 struct hostapd_ip_addr *ipaddr = NULL;
2414#ifdef CONFIG_DPP2
2415 struct hostapd_ip_addr ipaddr_buf;
2416 char *addr;
2417
2418 pos = os_strstr(cmd, " tcp_port=");
2419 if (pos) {
2420 pos += 10;
2421 tcp_port = atoi(pos);
2422 }
2423
2424 addr = get_param(cmd, " tcp_addr=");
2425 if (addr) {
2426 int res;
2427
2428 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
2429 os_free(addr);
2430 if (res)
2431 return -1;
2432 ipaddr = &ipaddr_buf;
2433 }
2434#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002435
2436 pos = os_strstr(cmd, " own=");
2437 if (!pos)
2438 return -1;
2439 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07002440 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002441 if (!own_bi) {
2442 wpa_printf(MSG_DEBUG,
2443 "DPP: Identified bootstrap info not found");
2444 return -1;
2445 }
2446 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2447 wpa_printf(MSG_DEBUG,
2448 "DPP: Identified bootstrap info not for PKEX");
2449 return -1;
2450 }
2451 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002452 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002453
2454 os_free(hapd->dpp_pkex_identifier);
2455 hapd->dpp_pkex_identifier = NULL;
2456 pos = os_strstr(cmd, " identifier=");
2457 if (pos) {
2458 pos += 12;
2459 end = os_strchr(pos, ' ');
2460 if (!end)
2461 return -1;
2462 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
2463 if (!hapd->dpp_pkex_identifier)
2464 return -1;
2465 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
2466 hapd->dpp_pkex_identifier[end - pos] = '\0';
2467 }
2468
2469 pos = os_strstr(cmd, " code=");
2470 if (!pos)
2471 return -1;
2472 os_free(hapd->dpp_pkex_code);
2473 hapd->dpp_pkex_code = os_strdup(pos + 6);
2474 if (!hapd->dpp_pkex_code)
2475 return -1;
2476
2477 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002478#ifdef CONFIG_DPP3
2479 enum hostapd_dpp_pkex_ver ver = PKEX_VER_AUTO;
2480#else /* CONFIG_DPP3 */
2481 enum hostapd_dpp_pkex_ver ver = PKEX_VER_ONLY_1;
2482#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002483
Hai Shaloma20dcd72022-02-04 13:43:00 -08002484 pos = os_strstr(cmd, " ver=");
2485 if (pos) {
2486 int v;
2487
2488 pos += 5;
2489 v = atoi(pos);
2490 if (v == 1)
2491 ver = PKEX_VER_ONLY_1;
2492 else if (v == 2)
2493 ver = PKEX_VER_ONLY_2;
2494 else
2495 return -1;
2496 }
2497
2498 if (hostapd_dpp_pkex_init(hapd, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002499 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002500 } else {
2501#ifdef CONFIG_DPP2
2502 dpp_controller_pkex_add(hapd->iface->interfaces->dpp, own_bi,
2503 hapd->dpp_pkex_code,
2504 hapd->dpp_pkex_identifier);
2505#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002506 }
2507
2508 /* TODO: Support multiple PKEX info entries */
2509
2510 os_free(hapd->dpp_pkex_auth_cmd);
2511 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
2512
2513 return 1;
2514}
2515
2516
2517int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
2518{
2519 unsigned int id_val;
2520
2521 if (os_strcmp(id, "*") == 0) {
2522 id_val = 0;
2523 } else {
2524 id_val = atoi(id);
2525 if (id_val == 0)
2526 return -1;
2527 }
2528
2529 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
2530 return -1;
2531
2532 /* TODO: Support multiple PKEX entries */
2533 os_free(hapd->dpp_pkex_code);
2534 hapd->dpp_pkex_code = NULL;
2535 os_free(hapd->dpp_pkex_identifier);
2536 hapd->dpp_pkex_identifier = NULL;
2537 os_free(hapd->dpp_pkex_auth_cmd);
2538 hapd->dpp_pkex_auth_cmd = NULL;
2539 hapd->dpp_pkex_bi = NULL;
2540 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2541 dpp_pkex_free(hapd->dpp_pkex);
2542 hapd->dpp_pkex = NULL;
2543 return 0;
2544}
2545
2546
Roshan Pius3a1667e2018-07-03 15:17:14 -07002547void hostapd_dpp_stop(struct hostapd_data *hapd)
2548{
2549 dpp_auth_deinit(hapd->dpp_auth);
2550 hapd->dpp_auth = NULL;
2551 dpp_pkex_free(hapd->dpp_pkex);
2552 hapd->dpp_pkex = NULL;
2553}
2554
2555
Hai Shalom81f62d82019-07-22 12:10:00 -07002556#ifdef CONFIG_DPP2
2557
2558static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq,
2559 const u8 *msg, size_t len)
2560{
2561 struct hostapd_data *hapd = ctx;
2562 u8 *buf;
2563
2564 wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u",
2565 MAC2STR(addr), freq);
2566 buf = os_malloc(2 + len);
2567 if (!buf)
2568 return;
2569 buf[0] = WLAN_ACTION_PUBLIC;
2570 buf[1] = WLAN_PA_VENDOR_SPECIFIC;
2571 os_memcpy(buf + 2, msg, len);
2572 hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len);
2573 os_free(buf);
2574}
2575
2576
2577static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr,
2578 u8 dialog_token, int prot,
2579 struct wpabuf *buf)
2580{
2581 struct hostapd_data *hapd = ctx;
2582
2583 gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf);
2584}
2585
2586#endif /* CONFIG_DPP2 */
2587
2588
2589static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
2590{
2591#ifdef CONFIG_DPP2
2592 struct dpp_controller_conf *ctrl;
2593 struct dpp_relay_config config;
2594
2595 os_memset(&config, 0, sizeof(config));
2596 config.cb_ctx = hapd;
2597 config.tx = hostapd_dpp_relay_tx;
2598 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
2599 for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) {
2600 config.ipaddr = &ctrl->ipaddr;
2601 config.pkhash = ctrl->pkhash;
2602 if (dpp_relay_add_controller(hapd->iface->interfaces->dpp,
2603 &config) < 0)
2604 return -1;
2605 }
2606#endif /* CONFIG_DPP2 */
2607
2608 return 0;
2609}
2610
2611
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002612int hostapd_dpp_init(struct hostapd_data *hapd)
2613{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002614 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
2615 hapd->dpp_init_done = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002616 return hostapd_dpp_add_controllers(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002617}
2618
2619
2620void hostapd_dpp_deinit(struct hostapd_data *hapd)
2621{
2622#ifdef CONFIG_TESTING_OPTIONS
2623 os_free(hapd->dpp_config_obj_override);
2624 hapd->dpp_config_obj_override = NULL;
2625 os_free(hapd->dpp_discovery_override);
2626 hapd->dpp_discovery_override = NULL;
2627 os_free(hapd->dpp_groups_override);
2628 hapd->dpp_groups_override = NULL;
2629 hapd->dpp_ignore_netaccesskey_mismatch = 0;
2630#endif /* CONFIG_TESTING_OPTIONS */
2631 if (!hapd->dpp_init_done)
2632 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002633 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002634 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08002635 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002636 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
2637 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002638#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002639 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
2640 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002641 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
2642 NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07002643 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
2644 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002645 hostapd_dpp_chirp_stop(hapd);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002646 if (hapd->iface->interfaces)
2647 dpp_controller_stop_for_ctx(hapd->iface->interfaces->dpp, hapd);
Hai Shalom021b0b52019-04-10 11:17:58 -07002648#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002649 dpp_auth_deinit(hapd->dpp_auth);
2650 hapd->dpp_auth = NULL;
2651 hostapd_dpp_pkex_remove(hapd, "*");
2652 hapd->dpp_pkex = NULL;
2653 os_free(hapd->dpp_configurator_params);
2654 hapd->dpp_configurator_params = NULL;
2655}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002656
2657
2658#ifdef CONFIG_DPP2
2659
Hai Shalom899fcc72020-10-19 14:38:18 -07002660int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd)
2661{
2662 struct dpp_controller_config config;
2663 const char *pos;
2664
2665 os_memset(&config, 0, sizeof(config));
2666 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
2667 config.netrole = DPP_NETROLE_AP;
2668 config.msg_ctx = hapd->msg_ctx;
2669 config.cb_ctx = hapd;
2670 config.process_conf_obj = hostapd_dpp_process_conf_obj;
2671 if (cmd) {
2672 pos = os_strstr(cmd, " tcp_port=");
2673 if (pos) {
2674 pos += 10;
2675 config.tcp_port = atoi(pos);
2676 }
2677
2678 pos = os_strstr(cmd, " role=");
2679 if (pos) {
2680 pos += 6;
2681 if (os_strncmp(pos, "configurator", 12) == 0)
2682 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
2683 else if (os_strncmp(pos, "enrollee", 8) == 0)
2684 config.allowed_roles = DPP_CAPAB_ENROLLEE;
2685 else if (os_strncmp(pos, "either", 6) == 0)
2686 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
2687 DPP_CAPAB_ENROLLEE;
2688 else
2689 return -1;
2690 }
2691
2692 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
2693 }
2694 config.configurator_params = hapd->dpp_configurator_params;
2695 return dpp_controller_start(hapd->iface->interfaces->dpp, &config);
2696}
2697
2698
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002699static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
2700
2701static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
2702{
2703 struct hostapd_data *hapd = eloop_ctx;
2704
2705 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
2706 hostapd_drv_send_action_cancel_wait(hapd);
2707 hostapd_dpp_chirp_next(hapd, NULL);
2708}
2709
2710
2711static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
2712{
2713 struct wpabuf *msg;
2714 int type;
2715
2716 msg = hapd->dpp_presence_announcement;
2717 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
2718 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
2719 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2720 " freq=%u type=%d",
2721 MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
2722 if (hostapd_drv_send_action(
2723 hapd, hapd->dpp_chirp_freq, 2000, broadcast,
2724 wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
2725 eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
2726 hapd, NULL) < 0)
2727 hostapd_dpp_chirp_stop(hapd);
2728}
2729
2730
2731static struct hostapd_hw_modes *
2732dpp_get_mode(struct hostapd_data *hapd,
2733 enum hostapd_hw_mode mode)
2734{
2735 struct hostapd_hw_modes *modes = hapd->iface->hw_features;
2736 u16 num_modes = hapd->iface->num_hw_features;
2737 u16 i;
2738
2739 for (i = 0; i < num_modes; i++) {
2740 if (modes[i].mode != mode ||
2741 !modes[i].num_channels || !modes[i].channels)
2742 continue;
2743 return &modes[i];
2744 }
2745
2746 return NULL;
2747}
2748
2749
2750static void
2751hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
2752{
2753 struct hostapd_data *hapd = iface->bss[0];
2754 struct wpa_scan_results *scan_res;
2755 struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
2756 unsigned int i;
2757 struct hostapd_hw_modes *mode;
2758 int c;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002759 bool chan6 = hapd->iface->hw_features == NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002760
2761 if (!bi)
2762 return;
2763
2764 hapd->dpp_chirp_scan_done = 1;
2765
2766 scan_res = hostapd_driver_get_scan_results(hapd);
2767
2768 os_free(hapd->dpp_chirp_freqs);
2769 hapd->dpp_chirp_freqs = NULL;
2770
2771 /* Channels from own bootstrapping info */
2772 if (bi) {
2773 for (i = 0; i < bi->num_freq; i++)
2774 int_array_add_unique(&hapd->dpp_chirp_freqs,
2775 bi->freq[i]);
2776 }
2777
2778 /* Preferred chirping channels */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002779 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211G);
2780 if (mode) {
2781 for (c = 0; c < mode->num_channels; c++) {
2782 struct hostapd_channel_data *chan = &mode->channels[c];
2783
2784 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2785 HOSTAPD_CHAN_RADAR) ||
2786 chan->freq != 2437)
2787 continue;
2788 chan6 = true;
2789 break;
2790 }
2791 }
2792 if (chan6)
2793 int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002794
2795 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
2796 if (mode) {
2797 int chan44 = 0, chan149 = 0;
2798
2799 for (c = 0; c < mode->num_channels; c++) {
2800 struct hostapd_channel_data *chan = &mode->channels[c];
2801
2802 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2803 HOSTAPD_CHAN_RADAR))
2804 continue;
2805 if (chan->freq == 5220)
2806 chan44 = 1;
2807 if (chan->freq == 5745)
2808 chan149 = 1;
2809 }
2810 if (chan149)
2811 int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
2812 else if (chan44)
2813 int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
2814 }
2815
2816 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
2817 if (mode) {
2818 for (c = 0; c < mode->num_channels; c++) {
2819 struct hostapd_channel_data *chan = &mode->channels[c];
2820
2821 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
2822 HOSTAPD_CHAN_RADAR)) ||
2823 chan->freq != 60480)
2824 continue;
2825 int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
2826 break;
2827 }
2828 }
2829
2830 /* Add channels from scan results for APs that advertise Configurator
2831 * Connectivity element */
2832 for (i = 0; scan_res && i < scan_res->num; i++) {
2833 struct wpa_scan_res *bss = scan_res->res[i];
2834 size_t ie_len = bss->ie_len;
2835
2836 if (!ie_len)
2837 ie_len = bss->beacon_ie_len;
2838 if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
2839 DPP_CC_IE_VENDOR_TYPE))
2840 int_array_add_unique(&hapd->dpp_chirp_freqs,
2841 bss->freq);
2842 }
2843
2844 if (!hapd->dpp_chirp_freqs ||
2845 eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
2846 hapd, NULL) < 0)
2847 hostapd_dpp_chirp_stop(hapd);
2848
2849 wpa_scan_results_free(scan_res);
2850}
2851
2852
2853static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
2854{
2855 struct hostapd_data *hapd = eloop_ctx;
2856 int i;
2857
2858 if (hapd->dpp_chirp_listen)
2859 hostapd_dpp_listen_stop(hapd);
2860
2861 if (hapd->dpp_chirp_freq == 0) {
2862 if (hapd->dpp_chirp_round % 4 == 0 &&
2863 !hapd->dpp_chirp_scan_done) {
2864 struct wpa_driver_scan_params params;
2865 int ret;
2866
2867 wpa_printf(MSG_DEBUG,
2868 "DPP: Update channel list for chirping");
2869 os_memset(&params, 0, sizeof(params));
2870 ret = hostapd_driver_scan(hapd, &params);
2871 if (ret < 0) {
2872 wpa_printf(MSG_DEBUG,
2873 "DPP: Failed to request a scan ret=%d (%s)",
2874 ret, strerror(-ret));
2875 hostapd_dpp_chirp_scan_res_handler(hapd->iface);
2876 } else {
2877 hapd->iface->scan_cb =
2878 hostapd_dpp_chirp_scan_res_handler;
2879 }
2880 return;
2881 }
2882 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
2883 hapd->dpp_chirp_round++;
2884 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
2885 hapd->dpp_chirp_round);
2886 } else {
2887 for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
2888 if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
2889 break;
2890 if (!hapd->dpp_chirp_freqs[i]) {
2891 wpa_printf(MSG_DEBUG,
2892 "DPP: Previous chirp freq %d not found",
2893 hapd->dpp_chirp_freq);
2894 return;
2895 }
2896 i++;
2897 if (hapd->dpp_chirp_freqs[i]) {
2898 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
2899 } else {
2900 hapd->dpp_chirp_iter--;
2901 if (hapd->dpp_chirp_iter <= 0) {
2902 wpa_printf(MSG_DEBUG,
2903 "DPP: Chirping iterations completed");
2904 hostapd_dpp_chirp_stop(hapd);
2905 return;
2906 }
2907 hapd->dpp_chirp_freq = 0;
2908 hapd->dpp_chirp_scan_done = 0;
2909 if (eloop_register_timeout(30, 0,
2910 hostapd_dpp_chirp_next,
2911 hapd, NULL) < 0) {
2912 hostapd_dpp_chirp_stop(hapd);
2913 return;
2914 }
2915 if (hapd->dpp_chirp_listen) {
2916 wpa_printf(MSG_DEBUG,
2917 "DPP: Listen on %d MHz during chirp 30 second wait",
2918 hapd->dpp_chirp_listen);
2919 /* TODO: start listen on the channel */
2920 } else {
2921 wpa_printf(MSG_DEBUG,
2922 "DPP: Wait 30 seconds before starting the next chirping round");
2923 }
2924 return;
2925 }
2926 }
2927
2928 hostapd_dpp_chirp_start(hapd);
2929}
2930
2931
2932int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
2933{
2934 const char *pos;
2935 int iter = 1, listen_freq = 0;
2936 struct dpp_bootstrap_info *bi;
2937
2938 pos = os_strstr(cmd, " own=");
2939 if (!pos)
2940 return -1;
2941 pos += 5;
2942 bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
2943 if (!bi) {
2944 wpa_printf(MSG_DEBUG,
2945 "DPP: Identified bootstrap info not found");
2946 return -1;
2947 }
2948
2949 pos = os_strstr(cmd, " iter=");
2950 if (pos) {
2951 iter = atoi(pos + 6);
2952 if (iter <= 0)
2953 return -1;
2954 }
2955
2956 pos = os_strstr(cmd, " listen=");
2957 if (pos) {
2958 listen_freq = atoi(pos + 8);
2959 if (listen_freq <= 0)
2960 return -1;
2961 }
2962
2963 hostapd_dpp_chirp_stop(hapd);
2964 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
2965 hapd->dpp_qr_mutual = 0;
2966 hapd->dpp_chirp_bi = bi;
2967 hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
2968 if (!hapd->dpp_presence_announcement)
2969 return -1;
2970 hapd->dpp_chirp_iter = iter;
2971 hapd->dpp_chirp_round = 0;
2972 hapd->dpp_chirp_scan_done = 0;
2973 hapd->dpp_chirp_listen = listen_freq;
2974
2975 return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
2976}
2977
2978
2979void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
2980{
2981 if (hapd->dpp_presence_announcement) {
2982 hostapd_drv_send_action_cancel_wait(hapd);
2983 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
2984 }
2985 hapd->dpp_chirp_bi = NULL;
2986 wpabuf_free(hapd->dpp_presence_announcement);
2987 hapd->dpp_presence_announcement = NULL;
2988 if (hapd->dpp_chirp_listen)
2989 hostapd_dpp_listen_stop(hapd);
2990 hapd->dpp_chirp_listen = 0;
2991 hapd->dpp_chirp_freq = 0;
2992 os_free(hapd->dpp_chirp_freqs);
2993 hapd->dpp_chirp_freqs = NULL;
2994 eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
2995 eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
2996 if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
2997 /* TODO: abort ongoing scan */
2998 hapd->iface->scan_cb = NULL;
2999 }
3000}
3001
3002
3003static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
3004{
3005 struct dpp_bootstrap_info *bi = ctx;
3006 size_t i;
3007
3008 for (i = 0; i < iface->num_bss; i++) {
3009 struct hostapd_data *hapd = iface->bss[i];
3010
3011 if (bi == hapd->dpp_chirp_bi)
3012 hostapd_dpp_chirp_stop(hapd);
3013 }
3014
3015 return 0;
3016}
3017
3018
3019void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
3020{
3021 struct hapd_interfaces *interfaces = ctx;
3022
3023 hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
3024}
3025
3026#endif /* CONFIG_DPP2 */