blob: 32ddb3b21a7f8e133de1b83d2986b83fe3044508 [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"
Sunil Ravi89eba102022-09-13 21:04:37 -070018#include "crypto/random.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070019#include "hostapd.h"
20#include "ap_drv_ops.h"
21#include "gas_query_ap.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070022#include "gas_serv.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070023#include "wpa_auth.h"
Sunil Ravi89eba102022-09-13 21:04:37 -070024#include "beacon.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070025#include "dpp_hostapd.h"
26
27
Roshan Pius3a1667e2018-07-03 15:17:14 -070028static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom60840252021-02-19 19:02:11 -080029static void hostapd_dpp_auth_conf_wait_timeout(void *eloop_ctx,
30 void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070031static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -070032static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
33static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
Hai Shaloma20dcd72022-02-04 13:43:00 -080034static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
35 struct dpp_authentication *auth);
Sunil Ravia04bd252022-05-02 22:54:18 -070036static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070037#ifdef CONFIG_DPP2
38static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
39 void *timeout_ctx);
Hai Shalom899fcc72020-10-19 14:38:18 -070040static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
41 struct dpp_authentication *auth,
42 struct dpp_config_obj *conf);
Hai Shaloma20dcd72022-02-04 13:43:00 -080043static int hostapd_dpp_process_conf_obj(void *ctx,
44 struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070045#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070046
47static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
48
49
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070050/**
51 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
52 * @hapd: Pointer to hostapd_data
53 * @cmd: DPP URI read from a QR Code
54 * Returns: Identifier of the stored info or -1 on failure
55 */
56int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
57{
58 struct dpp_bootstrap_info *bi;
59 struct dpp_authentication *auth = hapd->dpp_auth;
60
Hai Shalom021b0b52019-04-10 11:17:58 -070061 bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070062 if (!bi)
63 return -1;
64
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070065 if (auth && auth->response_pending &&
66 dpp_notify_new_qr_code(auth, bi) == 1) {
67 wpa_printf(MSG_DEBUG,
68 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070069 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
70 " freq=%u type=%d",
71 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
72 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070073 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
74 auth->peer_mac_addr,
75 wpabuf_head(hapd->dpp_auth->resp_msg),
76 wpabuf_len(hapd->dpp_auth->resp_msg));
77 }
78
Hai Shalom899fcc72020-10-19 14:38:18 -070079#ifdef CONFIG_DPP2
80 dpp_controller_new_qr_code(hapd->iface->interfaces->dpp, bi);
81#endif /* CONFIG_DPP2 */
82
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070083 return bi->id;
84}
85
86
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080087/**
88 * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
89 * @hapd: Pointer to hostapd_data
90 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
91 * Returns: Identifier of the stored info or -1 on failure
92 */
93int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
94{
95 struct dpp_bootstrap_info *bi;
96
97 bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
98 if (!bi)
99 return -1;
100
101 return bi->id;
102}
103
104
Hai Shalomfdcde762020-04-02 11:19:20 -0700105int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd)
106{
107 const char *pos;
108 struct dpp_bootstrap_info *peer_bi, *own_bi;
109
110 pos = os_strstr(cmd, " own=");
111 if (!pos)
112 return -1;
113 pos += 5;
114 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
115 if (!own_bi)
116 return -1;
117
118 pos = os_strstr(cmd, " uri=");
119 if (!pos)
120 return -1;
121 pos += 5;
122 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
123 if (!peer_bi) {
124 wpa_printf(MSG_INFO,
125 "DPP: Failed to parse URI from NFC Handover Request");
126 return -1;
127 }
128
129 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
130 return -1;
131
132 return peer_bi->id;
133}
134
135
136int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd)
137{
138 const char *pos;
139 struct dpp_bootstrap_info *peer_bi, *own_bi;
140
141 pos = os_strstr(cmd, " own=");
142 if (!pos)
143 return -1;
144 pos += 5;
145 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
146 if (!own_bi)
147 return -1;
148
149 pos = os_strstr(cmd, " uri=");
150 if (!pos)
151 return -1;
152 pos += 5;
153 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
154 if (!peer_bi) {
155 wpa_printf(MSG_INFO,
156 "DPP: Failed to parse URI from NFC Handover Select");
157 return -1;
158 }
159
160 if (peer_bi->curve != own_bi->curve) {
161 wpa_printf(MSG_INFO,
162 "DPP: Peer (NFC Handover Selector) used different curve");
163 return -1;
164 }
165
166 return peer_bi->id;
167}
168
169
Roshan Pius3a1667e2018-07-03 15:17:14 -0700170static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
171 void *timeout_ctx)
172{
173 struct hostapd_data *hapd = eloop_ctx;
174 struct dpp_authentication *auth = hapd->dpp_auth;
175
176 if (!auth || !auth->resp_msg)
177 return;
178
179 wpa_printf(MSG_DEBUG,
180 "DPP: Retry Authentication Response after timeout");
181 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
182 " freq=%u type=%d",
183 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
184 DPP_PA_AUTHENTICATION_RESP);
185 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
186 wpabuf_head(auth->resp_msg),
187 wpabuf_len(auth->resp_msg));
188}
189
190
191static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
192{
193 struct dpp_authentication *auth = hapd->dpp_auth;
194 unsigned int wait_time, max_tries;
195
196 if (!auth || !auth->resp_msg)
197 return;
198
199 if (hapd->dpp_resp_max_tries)
200 max_tries = hapd->dpp_resp_max_tries;
201 else
202 max_tries = 5;
203 auth->auth_resp_tries++;
204 if (auth->auth_resp_tries >= max_tries) {
205 wpa_printf(MSG_INFO,
206 "DPP: No confirm received from initiator - stopping exchange");
207 hostapd_drv_send_action_cancel_wait(hapd);
208 dpp_auth_deinit(hapd->dpp_auth);
209 hapd->dpp_auth = NULL;
210 return;
211 }
212
213 if (hapd->dpp_resp_retry_time)
214 wait_time = hapd->dpp_resp_retry_time;
215 else
216 wait_time = 1000;
217 wpa_printf(MSG_DEBUG,
218 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
219 wait_time);
220 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
221 eloop_register_timeout(wait_time / 1000,
222 (wait_time % 1000) * 1000,
223 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
224}
225
226
Hai Shaloma20dcd72022-02-04 13:43:00 -0800227static int hostapd_dpp_allow_ir(struct hostapd_data *hapd, unsigned int freq)
228{
229 int i, j;
230
231 if (!hapd->iface->hw_features)
232 return -1;
233
234 for (i = 0; i < hapd->iface->num_hw_features; i++) {
235 struct hostapd_hw_modes *mode = &hapd->iface->hw_features[i];
236
237 for (j = 0; j < mode->num_channels; j++) {
238 struct hostapd_channel_data *chan = &mode->channels[j];
239
240 if (chan->freq != (int) freq)
241 continue;
242
243 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
244 HOSTAPD_CHAN_NO_IR |
245 HOSTAPD_CHAN_RADAR))
246 continue;
247
248 return 1;
249 }
250 }
251
252 wpa_printf(MSG_DEBUG,
253 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
254 freq);
255
256 return 0;
257}
258
259
260static int hostapd_dpp_pkex_next_channel(struct hostapd_data *hapd,
261 struct dpp_pkex *pkex)
262{
263 if (pkex->freq == 2437)
264 pkex->freq = 5745;
265 else if (pkex->freq == 5745)
266 pkex->freq = 5220;
267 else if (pkex->freq == 5220)
268 pkex->freq = 60480;
269 else
270 return -1; /* no more channels to try */
271
272 if (hostapd_dpp_allow_ir(hapd, pkex->freq) == 1) {
273 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
274 pkex->freq);
275 return 0;
276 }
277
278 /* Could not use this channel - try the next one */
279 return hostapd_dpp_pkex_next_channel(hapd, pkex);
280}
281
282
Sunil Ravi89eba102022-09-13 21:04:37 -0700283static void hostapd_dpp_pkex_clear_code(struct hostapd_data *hapd)
284{
285 if (!hapd->dpp_pkex_code && !hapd->dpp_pkex_identifier)
286 return;
287
288 /* Delete PKEX code and identifier on successful completion of
289 * PKEX. We are not supposed to reuse these without being
290 * explicitly requested to perform PKEX again. */
291 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
292 os_free(hapd->dpp_pkex_code);
293 hapd->dpp_pkex_code = NULL;
294 os_free(hapd->dpp_pkex_identifier);
295 hapd->dpp_pkex_identifier = NULL;
296}
297
298
Hai Shaloma20dcd72022-02-04 13:43:00 -0800299#ifdef CONFIG_DPP2
300static int hostapd_dpp_pkex_done(void *ctx, void *conn,
301 struct dpp_bootstrap_info *peer_bi)
302{
303 struct hostapd_data *hapd = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -0700304 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -0800305 const char *pos;
306 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
307 struct dpp_bootstrap_info *own_bi = NULL;
308 struct dpp_authentication *auth;
309
Sunil Ravi89eba102022-09-13 21:04:37 -0700310 hostapd_dpp_pkex_clear_code(hapd);
311
312 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
313 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -0800314 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
315 cmd);
316
317 pos = os_strstr(cmd, " own=");
318 if (pos) {
319 pos += 5;
320 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
321 atoi(pos));
322 if (!own_bi) {
323 wpa_printf(MSG_INFO,
324 "DPP: Could not find bootstrapping info for the identified local entry");
325 return -1;
326 }
327
328 if (peer_bi->curve != own_bi->curve) {
329 wpa_printf(MSG_INFO,
330 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
331 peer_bi->curve->name, own_bi->curve->name);
332 return -1;
333 }
334 }
335
336 pos = os_strstr(cmd, " role=");
337 if (pos) {
338 pos += 6;
339 if (os_strncmp(pos, "configurator", 12) == 0)
340 allowed_roles = DPP_CAPAB_CONFIGURATOR;
341 else if (os_strncmp(pos, "enrollee", 8) == 0)
342 allowed_roles = DPP_CAPAB_ENROLLEE;
343 else if (os_strncmp(pos, "either", 6) == 0)
344 allowed_roles = DPP_CAPAB_CONFIGURATOR |
345 DPP_CAPAB_ENROLLEE;
346 else
347 return -1;
348 }
349
350 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
351 peer_bi, own_bi, allowed_roles, 0,
352 hapd->iface->hw_features,
353 hapd->iface->num_hw_features);
354 if (!auth)
355 return -1;
356
357 hostapd_dpp_set_testing_options(hapd, auth);
358 if (dpp_set_configurator(auth, cmd) < 0) {
359 dpp_auth_deinit(auth);
360 return -1;
361 }
362
363 return dpp_tcp_auth(hapd->iface->interfaces->dpp, conn, auth,
364 hapd->conf->dpp_name, DPP_NETROLE_AP,
Sunil Ravi89eba102022-09-13 21:04:37 -0700365 hapd->conf->dpp_mud_url,
366 hapd->conf->dpp_extra_conf_req_name,
367 hapd->conf->dpp_extra_conf_req_value,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800368 hostapd_dpp_process_conf_obj, NULL);
369}
370#endif /* CONFIG_DPP2 */
371
372
Hai Shaloma20dcd72022-02-04 13:43:00 -0800373static int hostapd_dpp_pkex_init(struct hostapd_data *hapd,
Sunil Ravia04bd252022-05-02 22:54:18 -0700374 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800375 const struct hostapd_ip_addr *ipaddr,
376 int tcp_port)
377{
378 struct dpp_pkex *pkex;
379 struct wpabuf *msg;
380 unsigned int wait_time;
381 bool v2 = ver != PKEX_VER_ONLY_1;
382
383 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
384 dpp_pkex_free(hapd->dpp_pkex);
385 hapd->dpp_pkex = NULL;
386 pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr,
387 hapd->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -0700388 hapd->dpp_pkex_code, hapd->dpp_pkex_code_len, v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800389 if (!pkex)
390 return -1;
391 pkex->forced_ver = ver != PKEX_VER_AUTO;
392
393 if (ipaddr) {
394#ifdef CONFIG_DPP2
395 return dpp_tcp_pkex_init(hapd->iface->interfaces->dpp, pkex,
396 ipaddr, tcp_port,
397 hapd->msg_ctx, hapd,
398 hostapd_dpp_pkex_done);
399#else /* CONFIG_DPP2 */
400 return -1;
401#endif /* CONFIG_DPP2 */
402 }
403
404 hapd->dpp_pkex = pkex;
405 msg = hapd->dpp_pkex->exchange_req;
406 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
407 pkex->freq = 2437;
408 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
409 " freq=%u type=%d", MAC2STR(broadcast), pkex->freq,
410 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
411 DPP_PA_PKEX_V1_EXCHANGE_REQ);
412 hostapd_drv_send_action(hapd, pkex->freq, 0, broadcast,
413 wpabuf_head(msg), wpabuf_len(msg));
414 pkex->exch_req_wait_time = wait_time;
415 pkex->exch_req_tries = 1;
416
417 return 0;
418}
419
420
421static void hostapd_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
422{
423 struct hostapd_data *hapd = eloop_ctx;
424 struct dpp_pkex *pkex = hapd->dpp_pkex;
425
426 if (!pkex || !pkex->exchange_req)
427 return;
428 if (pkex->exch_req_tries >= 5) {
429 if (hostapd_dpp_pkex_next_channel(hapd, pkex) < 0) {
430#ifdef CONFIG_DPP3
431 if (pkex->v2 && !pkex->forced_ver) {
432 wpa_printf(MSG_DEBUG,
433 "DPP: Fall back to PKEXv1");
434 hostapd_dpp_pkex_init(hapd, PKEX_VER_ONLY_1,
435 NULL, 0);
436 return;
437 }
438#endif /* CONFIG_DPP3 */
439 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
440 "No response from PKEX peer");
441 dpp_pkex_free(pkex);
442 hapd->dpp_pkex = NULL;
443 return;
444 }
445 pkex->exch_req_tries = 0;
446 }
447
448 pkex->exch_req_tries++;
449 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
450 pkex->exch_req_tries);
451 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
452 " freq=%u type=%d",
453 MAC2STR(broadcast), pkex->freq,
454 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
455 DPP_PA_PKEX_V1_EXCHANGE_REQ);
456 hostapd_drv_send_action(hapd, pkex->freq, pkex->exch_req_wait_time,
457 broadcast,
458 wpabuf_head(pkex->exchange_req),
459 wpabuf_len(pkex->exchange_req));
460}
461
462
463static void hostapd_dpp_pkex_tx_status(struct hostapd_data *hapd, const u8 *dst,
464 const u8 *data, size_t data_len, int ok)
465{
466 struct dpp_pkex *pkex = hapd->dpp_pkex;
467
468 if (pkex->failed) {
469 wpa_printf(MSG_DEBUG,
470 "DPP: Terminate PKEX exchange due to an earlier error");
471 if (pkex->t > pkex->own_bi->pkex_t)
472 pkex->own_bi->pkex_t = pkex->t;
473 dpp_pkex_free(pkex);
474 hapd->dpp_pkex = NULL;
475 return;
476 }
477
478 if (pkex->exch_req_wait_time && pkex->exchange_req) {
479 /* Wait for PKEX Exchange Response frame and retry request if
480 * no response is seen. */
481 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd,
482 NULL);
483 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
484 (pkex->exch_req_wait_time % 1000) * 1000,
485 hostapd_dpp_pkex_retry_timeout, hapd,
486 NULL);
487 }
488}
489
490
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700491void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
492 const u8 *data, size_t data_len, int ok)
493{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700494 struct dpp_authentication *auth = hapd->dpp_auth;
495
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700496 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
497 MAC2STR(dst), ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700498 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
499 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700500
501 if (!hapd->dpp_auth) {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800502 if (hapd->dpp_pkex) {
503 hostapd_dpp_pkex_tx_status(hapd, dst, data, data_len,
504 ok);
505 return;
506 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700507 wpa_printf(MSG_DEBUG,
508 "DPP: Ignore TX status since there is no ongoing authentication exchange");
509 return;
510 }
511
Hai Shalom021b0b52019-04-10 11:17:58 -0700512#ifdef CONFIG_DPP2
513 if (auth->connect_on_tx_status) {
514 wpa_printf(MSG_DEBUG,
515 "DPP: Complete exchange on configuration result");
516 dpp_auth_deinit(hapd->dpp_auth);
517 hapd->dpp_auth = NULL;
518 return;
519 }
520#endif /* CONFIG_DPP2 */
521
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700522 if (hapd->dpp_auth->remove_on_tx_status) {
523 wpa_printf(MSG_DEBUG,
524 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700525 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
526 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
527 hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800528 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout,
529 hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700530 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
531 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700532#ifdef CONFIG_DPP2
533 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
534 hapd, NULL);
535#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700536 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700537 dpp_auth_deinit(hapd->dpp_auth);
538 hapd->dpp_auth = NULL;
539 return;
540 }
541
542 if (hapd->dpp_auth_ok_on_ack)
543 hostapd_dpp_auth_success(hapd, 1);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700544
545 if (!is_broadcast_ether_addr(dst) && !ok) {
546 wpa_printf(MSG_DEBUG,
547 "DPP: Unicast DPP Action frame was not ACKed");
548 if (auth->waiting_auth_resp) {
549 /* In case of DPP Authentication Request frame, move to
550 * the next channel immediately. */
551 hostapd_drv_send_action_cancel_wait(hapd);
552 hostapd_dpp_auth_init_next(hapd);
553 return;
554 }
555 if (auth->waiting_auth_conf) {
556 hostapd_dpp_auth_resp_retry(hapd);
557 return;
558 }
559 }
560
Hai Shalom60840252021-02-19 19:02:11 -0800561 if (auth->waiting_auth_conf &&
562 auth->auth_resp_status == DPP_STATUS_OK) {
563 /* Make sure we do not get stuck waiting for Auth Confirm
564 * indefinitely after successfully transmitted Auth Response to
565 * allow new authentication exchanges to be started. */
566 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd,
567 NULL);
568 eloop_register_timeout(1, 0, hostapd_dpp_auth_conf_wait_timeout,
569 hapd, NULL);
570 }
571
Roshan Pius3a1667e2018-07-03 15:17:14 -0700572 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
573 /* Allow timeout handling to stop iteration if no response is
574 * received from a peer that has ACKed a request. */
575 auth->auth_req_ack = 1;
576 }
577
578 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
579 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
580 wpa_printf(MSG_DEBUG,
581 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
582 hapd->dpp_auth->curr_freq,
583 hapd->dpp_auth->neg_freq);
584 hostapd_drv_send_action_cancel_wait(hapd);
585
586 if (hapd->dpp_auth->neg_freq !=
587 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
588 /* TODO: Listen operation on non-operating channel */
589 wpa_printf(MSG_INFO,
590 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
591 hapd->dpp_auth->neg_freq, hapd->iface->freq);
592 }
593 }
594
595 if (hapd->dpp_auth_ok_on_ack)
596 hapd->dpp_auth_ok_on_ack = 0;
597}
598
599
600static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
601{
602 struct hostapd_data *hapd = eloop_ctx;
603 struct dpp_authentication *auth = hapd->dpp_auth;
604 unsigned int freq;
605 struct os_reltime now, diff;
606 unsigned int wait_time, diff_ms;
607
608 if (!auth || !auth->waiting_auth_resp)
609 return;
610
611 wait_time = hapd->dpp_resp_wait_time ?
612 hapd->dpp_resp_wait_time : 2000;
613 os_get_reltime(&now);
614 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
615 diff_ms = diff.sec * 1000 + diff.usec / 1000;
616 wpa_printf(MSG_DEBUG,
617 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
618 wait_time, diff_ms);
619
620 if (auth->auth_req_ack && diff_ms >= wait_time) {
621 /* Peer ACK'ed Authentication Request frame, but did not reply
622 * with Authentication Response frame within two seconds. */
623 wpa_printf(MSG_INFO,
624 "DPP: No response received from responder - stopping initiation attempt");
625 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
626 hostapd_drv_send_action_cancel_wait(hapd);
627 hostapd_dpp_listen_stop(hapd);
628 dpp_auth_deinit(auth);
629 hapd->dpp_auth = NULL;
630 return;
631 }
632
633 if (diff_ms >= wait_time) {
634 /* Authentication Request frame was not ACK'ed and no reply
635 * was receiving within two seconds. */
636 wpa_printf(MSG_DEBUG,
637 "DPP: Continue Initiator channel iteration");
638 hostapd_drv_send_action_cancel_wait(hapd);
639 hostapd_dpp_listen_stop(hapd);
640 hostapd_dpp_auth_init_next(hapd);
641 return;
642 }
643
644 /* Driver did not support 2000 ms long wait_time with TX command, so
645 * schedule listen operation to continue waiting for the response.
646 *
647 * DPP listen operations continue until stopped, so simply schedule a
648 * new call to this function at the point when the two second reply
649 * wait has expired. */
650 wait_time -= diff_ms;
651
652 freq = auth->curr_freq;
653 if (auth->neg_freq > 0)
654 freq = auth->neg_freq;
655 wpa_printf(MSG_DEBUG,
656 "DPP: Continue reply wait on channel %u MHz for %u ms",
657 freq, wait_time);
658 hapd->dpp_in_response_listen = 1;
659
660 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
661 /* TODO: Listen operation on non-operating channel */
662 wpa_printf(MSG_INFO,
663 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
664 freq, hapd->iface->freq);
665 }
666
667 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
668 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700669}
670
671
Hai Shalom60840252021-02-19 19:02:11 -0800672static void hostapd_dpp_auth_conf_wait_timeout(void *eloop_ctx,
673 void *timeout_ctx)
674{
675 struct hostapd_data *hapd = eloop_ctx;
676 struct dpp_authentication *auth = hapd->dpp_auth;
677
678 if (!auth || !auth->waiting_auth_conf)
679 return;
680
681 wpa_printf(MSG_DEBUG,
682 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
683 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
684 "No Auth Confirm received");
685 hostapd_drv_send_action_cancel_wait(hapd);
686 dpp_auth_deinit(auth);
687 hapd->dpp_auth = NULL;
688}
689
690
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700691static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
692 struct dpp_authentication *auth)
693{
694#ifdef CONFIG_TESTING_OPTIONS
695 if (hapd->dpp_config_obj_override)
696 auth->config_obj_override =
697 os_strdup(hapd->dpp_config_obj_override);
698 if (hapd->dpp_discovery_override)
699 auth->discovery_override =
700 os_strdup(hapd->dpp_discovery_override);
701 if (hapd->dpp_groups_override)
702 auth->groups_override = os_strdup(hapd->dpp_groups_override);
703 auth->ignore_netaccesskey_mismatch =
704 hapd->dpp_ignore_netaccesskey_mismatch;
705#endif /* CONFIG_TESTING_OPTIONS */
706}
707
708
Roshan Pius3a1667e2018-07-03 15:17:14 -0700709static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
710{
711 struct hostapd_data *hapd = eloop_ctx;
712
713 if (!hapd->dpp_auth)
714 return;
715 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
716 hostapd_dpp_auth_init_next(hapd);
717}
718
719
720static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
721{
722 struct dpp_authentication *auth = hapd->dpp_auth;
723 const u8 *dst;
724 unsigned int wait_time, max_wait_time, freq, max_tries, used;
725 struct os_reltime now, diff;
726
727 if (!auth)
728 return -1;
729
730 if (auth->freq_idx == 0)
731 os_get_reltime(&hapd->dpp_init_iter_start);
732
733 if (auth->freq_idx >= auth->num_freq) {
734 auth->num_freq_iters++;
735 if (hapd->dpp_init_max_tries)
736 max_tries = hapd->dpp_init_max_tries;
737 else
738 max_tries = 5;
739 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
740 wpa_printf(MSG_INFO,
741 "DPP: No response received from responder - stopping initiation attempt");
742 wpa_msg(hapd->msg_ctx, MSG_INFO,
743 DPP_EVENT_AUTH_INIT_FAILED);
744 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
745 hapd, NULL);
746 hostapd_drv_send_action_cancel_wait(hapd);
747 dpp_auth_deinit(hapd->dpp_auth);
748 hapd->dpp_auth = NULL;
749 return -1;
750 }
751 auth->freq_idx = 0;
752 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
753 if (hapd->dpp_init_retry_time)
754 wait_time = hapd->dpp_init_retry_time;
755 else
756 wait_time = 10000;
757 os_get_reltime(&now);
758 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
759 used = diff.sec * 1000 + diff.usec / 1000;
760 if (used > wait_time)
761 wait_time = 0;
762 else
763 wait_time -= used;
764 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
765 wait_time);
766 eloop_register_timeout(wait_time / 1000,
767 (wait_time % 1000) * 1000,
768 hostapd_dpp_init_timeout, hapd,
769 NULL);
770 return 0;
771 }
772 freq = auth->freq[auth->freq_idx++];
773 auth->curr_freq = freq;
774
Hai Shalom60840252021-02-19 19:02:11 -0800775 if (!is_zero_ether_addr(auth->peer_mac_addr))
776 dst = auth->peer_mac_addr;
777 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700778 dst = broadcast;
779 else
780 dst = auth->peer_bi->mac_addr;
781 hapd->dpp_auth_ok_on_ack = 0;
782 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
783 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
784 max_wait_time = hapd->dpp_resp_wait_time ?
785 hapd->dpp_resp_wait_time : 2000;
786 if (wait_time > max_wait_time)
787 wait_time = max_wait_time;
788 wait_time += 10; /* give the driver some extra time to complete */
789 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
790 hostapd_dpp_reply_wait_timeout, hapd, NULL);
791 wait_time -= 10;
792 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
793 wpa_printf(MSG_DEBUG,
794 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
795 freq, auth->neg_freq);
796 }
797 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
798 " freq=%u type=%d",
799 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
800 auth->auth_req_ack = 0;
801 os_get_reltime(&hapd->dpp_last_init);
802 return hostapd_drv_send_action(hapd, freq, wait_time,
803 dst,
804 wpabuf_head(hapd->dpp_auth->req_msg),
805 wpabuf_len(hapd->dpp_auth->req_msg));
806}
807
808
Hai Shalom899fcc72020-10-19 14:38:18 -0700809#ifdef CONFIG_DPP2
810static int hostapd_dpp_process_conf_obj(void *ctx,
811 struct dpp_authentication *auth)
812{
813 struct hostapd_data *hapd = ctx;
814 unsigned int i;
815
816 for (i = 0; i < auth->num_conf_obj; i++)
817 hostapd_dpp_handle_config_obj(hapd, auth,
818 &auth->conf_obj[i]);
819
820 return 0;
821}
822#endif /* CONFIG_DPP2 */
823
824
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700825int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
826{
827 const char *pos;
828 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -0700829 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700830 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
831 unsigned int neg_freq = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700832 int tcp = 0;
833#ifdef CONFIG_DPP2
834 int tcp_port = DPP_TCP_PORT;
835 struct hostapd_ip_addr ipaddr;
836 char *addr;
837#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700838
839 pos = os_strstr(cmd, " peer=");
840 if (!pos)
841 return -1;
842 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700843 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700844 if (!peer_bi) {
845 wpa_printf(MSG_INFO,
846 "DPP: Could not find bootstrapping info for the identified peer");
847 return -1;
848 }
849
Hai Shalom899fcc72020-10-19 14:38:18 -0700850#ifdef CONFIG_DPP2
851 pos = os_strstr(cmd, " tcp_port=");
852 if (pos) {
853 pos += 10;
854 tcp_port = atoi(pos);
855 }
856
857 addr = get_param(cmd, " tcp_addr=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000858 if (addr && os_strcmp(addr, "from-uri") == 0) {
859 os_free(addr);
860 if (!peer_bi->host) {
861 wpa_printf(MSG_INFO,
862 "DPP: TCP address not available in peer URI");
863 return -1;
864 }
865 tcp = 1;
866 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
867 tcp_port = peer_bi->port;
868 } else if (addr) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700869 int res;
870
871 res = hostapd_parse_ip_addr(addr, &ipaddr);
872 os_free(addr);
873 if (res)
874 return -1;
875 tcp = 1;
876 }
877#endif /* CONFIG_DPP2 */
878
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700879 pos = os_strstr(cmd, " own=");
880 if (pos) {
881 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700882 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
883 atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700884 if (!own_bi) {
885 wpa_printf(MSG_INFO,
886 "DPP: Could not find bootstrapping info for the identified local entry");
887 return -1;
888 }
889
890 if (peer_bi->curve != own_bi->curve) {
891 wpa_printf(MSG_INFO,
892 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
893 peer_bi->curve->name, own_bi->curve->name);
894 return -1;
895 }
896 }
897
898 pos = os_strstr(cmd, " role=");
899 if (pos) {
900 pos += 6;
901 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700902 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700903 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700904 allowed_roles = DPP_CAPAB_ENROLLEE;
905 else if (os_strncmp(pos, "either", 6) == 0)
906 allowed_roles = DPP_CAPAB_CONFIGURATOR |
907 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700908 else
909 goto fail;
910 }
911
Roshan Pius3a1667e2018-07-03 15:17:14 -0700912 pos = os_strstr(cmd, " neg_freq=");
913 if (pos)
914 neg_freq = atoi(pos + 10);
915
Hai Shalom899fcc72020-10-19 14:38:18 -0700916 if (!tcp && hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700917 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
918 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
919 hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800920 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout,
921 hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700922 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
923 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700924#ifdef CONFIG_DPP2
925 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
926 hapd, NULL);
927#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700928 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700929 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700930 }
931
Hai Shalom899fcc72020-10-19 14:38:18 -0700932 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
933 peer_bi, own_bi, allowed_roles, neg_freq,
934 hapd->iface->hw_features,
935 hapd->iface->num_hw_features);
936 if (!auth)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700937 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -0700938 hostapd_dpp_set_testing_options(hapd, auth);
939 if (dpp_set_configurator(auth, cmd) < 0) {
940 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800941 goto fail;
942 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700943
Hai Shalom899fcc72020-10-19 14:38:18 -0700944 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700945
Roshan Pius3a1667e2018-07-03 15:17:14 -0700946 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom899fcc72020-10-19 14:38:18 -0700947 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700948
Hai Shalom899fcc72020-10-19 14:38:18 -0700949#ifdef CONFIG_DPP2
950 if (tcp)
951 return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
952 &ipaddr, tcp_port, hapd->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -0700953 DPP_NETROLE_AP, hapd->conf->dpp_mud_url,
954 hapd->conf->dpp_extra_conf_req_name,
955 hapd->conf->dpp_extra_conf_req_value,
956 hapd->msg_ctx, hapd,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800957 hostapd_dpp_process_conf_obj, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -0700958#endif /* CONFIG_DPP2 */
959
960 hapd->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700961 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700962fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700963 return -1;
964}
965
966
Roshan Pius3a1667e2018-07-03 15:17:14 -0700967int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
968{
969 int freq;
970
971 freq = atoi(cmd);
972 if (freq <= 0)
973 return -1;
974
975 if (os_strstr(cmd, " role=configurator"))
976 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
977 else if (os_strstr(cmd, " role=enrollee"))
978 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
979 else
980 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
981 DPP_CAPAB_ENROLLEE;
982 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
983
984 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
985 /* TODO: Listen operation on non-operating channel */
986 wpa_printf(MSG_INFO,
987 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
988 freq, hapd->iface->freq);
989 return -1;
990 }
991
Hai Shalom60840252021-02-19 19:02:11 -0800992 hostapd_drv_dpp_listen(hapd, true);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700993 return 0;
994}
995
996
997void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
998{
Hai Shalom60840252021-02-19 19:02:11 -0800999 hostapd_drv_dpp_listen(hapd, false);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001000 /* TODO: Stop listen operation on non-operating channel */
1001}
1002
1003
Sunil Ravi89eba102022-09-13 21:04:37 -07001004#ifdef CONFIG_DPP2
1005static void
1006hostapd_dpp_relay_needs_controller(struct hostapd_data *hapd, const u8 *src,
1007 enum dpp_public_action_frame_type type)
1008{
1009 struct os_reltime now;
1010
1011 if (!hapd->conf->dpp_relay_port)
1012 return;
1013
1014 os_get_reltime(&now);
1015 if (hapd->dpp_relay_last_needs_ctrl.sec &&
1016 !os_reltime_expired(&now, &hapd->dpp_relay_last_needs_ctrl, 60))
1017 return;
1018 hapd->dpp_relay_last_needs_ctrl = now;
1019 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RELAY_NEEDS_CONTROLLER
1020 MACSTR " %u", MAC2STR(src), type);
1021}
1022#endif /* CONFIG_DPP2 */
1023
1024
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001025static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
1026 const u8 *hdr, const u8 *buf, size_t len,
1027 unsigned int freq)
1028{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001029 const u8 *r_bootstrap, *i_bootstrap;
1030 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001031 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1032
1033 if (!hapd->iface->interfaces->dpp)
1034 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001035
1036 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1037 MAC2STR(src));
1038
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001039#ifdef CONFIG_DPP2
1040 hostapd_dpp_chirp_stop(hapd);
1041#endif /* CONFIG_DPP2 */
1042
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001043 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1044 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001045 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1046 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1047 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001048 return;
1049 }
1050 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1051 r_bootstrap, r_bootstrap_len);
1052
1053 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1054 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001055 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1056 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1057 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001058 return;
1059 }
1060 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1061 i_bootstrap, i_bootstrap_len);
1062
1063 /* Try to find own and peer bootstrapping key matches based on the
1064 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001065 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
1066 r_bootstrap, &own_bi, &peer_bi);
Hai Shalom81f62d82019-07-22 12:10:00 -07001067#ifdef CONFIG_DPP2
1068 if (!own_bi) {
1069 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1070 src, hdr, buf, len, freq, i_bootstrap,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001071 r_bootstrap, hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07001072 return;
Sunil Ravi89eba102022-09-13 21:04:37 -07001073 hostapd_dpp_relay_needs_controller(hapd, src,
1074 DPP_PA_AUTHENTICATION_REQ);
Hai Shalom81f62d82019-07-22 12:10:00 -07001075 }
1076#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001077 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001078 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1079 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001080 return;
1081 }
1082
Sunil Ravi89eba102022-09-13 21:04:37 -07001083 if (own_bi->type == DPP_BOOTSTRAP_PKEX) {
1084 if (!peer_bi || peer_bi->type != DPP_BOOTSTRAP_PKEX) {
1085 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1086 "No matching peer bootstrapping key found for PKEX - ignore message");
1087 return;
1088 }
1089
1090 if (os_memcmp(peer_bi->pubkey_hash, own_bi->peer_pubkey_hash,
1091 SHA256_MAC_LEN) != 0) {
1092 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1093 "Mismatching peer PKEX bootstrapping key - ignore message");
1094 return;
1095 }
1096 }
1097
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001098 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001099 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1100 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001101 return;
1102 }
1103
1104 hapd->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001105 hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
1106 hapd->msg_ctx, hapd->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001107 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001108 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001109 if (!hapd->dpp_auth) {
1110 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1111 return;
1112 }
1113 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001114 if (dpp_set_configurator(hapd->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001115 hapd->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001116 dpp_auth_deinit(hapd->dpp_auth);
1117 hapd->dpp_auth = NULL;
1118 return;
1119 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001120 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1121
Roshan Pius3a1667e2018-07-03 15:17:14 -07001122 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1123 " freq=%u type=%d",
1124 MAC2STR(src), hapd->dpp_auth->curr_freq,
1125 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001126 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
1127 src, wpabuf_head(hapd->dpp_auth->resp_msg),
1128 wpabuf_len(hapd->dpp_auth->resp_msg));
1129}
1130
1131
Roshan Pius3a1667e2018-07-03 15:17:14 -07001132static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
Hai Shalomc3565922019-10-28 11:58:20 -07001133 struct dpp_authentication *auth,
1134 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001135{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001136 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001137 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001138 dpp_akm_str(conf->akm));
1139 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001140 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001141 wpa_ssid_txt(conf->ssid, conf->ssid_len));
1142 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001143 /* TODO: Save the Connector and consider using a command
1144 * to fetch the value instead of sending an event with
1145 * it. The Connector could end up being larger than what
1146 * most clients are ready to receive as an event
1147 * message. */
1148 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001149 conf->connector);
Hai Shalomfdcde762020-04-02 11:19:20 -07001150 }
1151 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001152 char hex[64 * 2 + 1];
1153
1154 wpa_snprintf_hex(hex, sizeof(hex),
Hai Shalomc3565922019-10-28 11:58:20 -07001155 (const u8 *) conf->passphrase,
1156 os_strlen(conf->passphrase));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001157 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1158 hex);
Hai Shalomc3565922019-10-28 11:58:20 -07001159 } else if (conf->psk_set) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001160 char hex[PMK_LEN * 2 + 1];
1161
Hai Shalomc3565922019-10-28 11:58:20 -07001162 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001163 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1164 hex);
1165 }
Hai Shalomc3565922019-10-28 11:58:20 -07001166 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001167 char *hex;
1168 size_t hexlen;
1169
Hai Shalomc3565922019-10-28 11:58:20 -07001170 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001171 hex = os_malloc(hexlen);
1172 if (hex) {
1173 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001174 wpabuf_head(conf->c_sign_key),
1175 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001176 wpa_msg(hapd->msg_ctx, MSG_INFO,
1177 DPP_EVENT_C_SIGN_KEY "%s", hex);
1178 os_free(hex);
1179 }
1180 }
1181 if (auth->net_access_key) {
1182 char *hex;
1183 size_t hexlen;
1184
1185 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1186 hex = os_malloc(hexlen);
1187 if (hex) {
1188 wpa_snprintf_hex(hex, hexlen,
1189 wpabuf_head(auth->net_access_key),
1190 wpabuf_len(auth->net_access_key));
1191 if (auth->net_access_key_expiry)
1192 wpa_msg(hapd->msg_ctx, MSG_INFO,
1193 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1194 (unsigned long)
1195 auth->net_access_key_expiry);
1196 else
1197 wpa_msg(hapd->msg_ctx, MSG_INFO,
1198 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1199 os_free(hex);
1200 }
1201 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001202}
1203
1204
Hai Shalomfdcde762020-04-02 11:19:20 -07001205static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
1206 struct dpp_asymmetric_key *key)
1207{
1208#ifdef CONFIG_DPP2
1209 int res;
1210
1211 if (!key)
1212 return 0;
1213
1214 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1215 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
1216
1217 while (key) {
1218 res = dpp_configurator_from_backup(
1219 hapd->iface->interfaces->dpp, key);
1220 if (res < 0)
1221 return -1;
1222 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1223 res);
1224 key = key->next;
1225 }
1226#endif /* CONFIG_DPP2 */
1227
1228 return 0;
1229}
1230
1231
Sunil Ravia04bd252022-05-02 22:54:18 -07001232#ifdef CONFIG_DPP3
1233static void hostapd_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1234{
1235 struct hostapd_data *hapd = eloop_ctx;
1236 struct dpp_authentication *auth = hapd->dpp_auth;
1237
1238 if (!auth || !auth->waiting_new_key)
1239 return;
1240
1241 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1242 hostapd_dpp_start_gas_client(hapd);
1243}
1244#endif /* CONFIG_DPP3 */
1245
1246
Roshan Pius3a1667e2018-07-03 15:17:14 -07001247static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1248 enum gas_query_ap_result result,
1249 const struct wpabuf *adv_proto,
1250 const struct wpabuf *resp, u16 status_code)
1251{
1252 struct hostapd_data *hapd = ctx;
1253 const u8 *pos;
1254 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001255 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Sunil Ravia04bd252022-05-02 22:54:18 -07001256 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001257
1258 if (!auth || !auth->auth_success) {
1259 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1260 return;
1261 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001262 if (result != GAS_QUERY_AP_SUCCESS ||
1263 !resp || status_code != WLAN_STATUS_SUCCESS) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001264 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1265 goto fail;
1266 }
1267
1268 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1269 adv_proto);
1270 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1271 resp);
1272
1273 if (wpabuf_len(adv_proto) != 10 ||
1274 !(pos = wpabuf_head(adv_proto)) ||
1275 pos[0] != WLAN_EID_ADV_PROTO ||
1276 pos[1] != 8 ||
1277 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1278 pos[4] != 5 ||
1279 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1280 pos[8] != 0x1a ||
1281 pos[9] != 1) {
1282 wpa_printf(MSG_DEBUG,
1283 "DPP: Not a DPP Advertisement Protocol ID");
1284 goto fail;
1285 }
1286
Sunil Ravia04bd252022-05-02 22:54:18 -07001287 res = dpp_conf_resp_rx(auth, resp);
1288#ifdef CONFIG_DPP3
1289 if (res == -3) {
1290 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1291 eloop_register_timeout(0, 0, hostapd_dpp_build_new_key, hapd,
1292 NULL);
1293 return;
1294 }
1295#endif /* CONFIG_DPP3 */
1296 if (res < 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001297 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1298 goto fail;
1299 }
1300
Hai Shalomc3565922019-10-28 11:58:20 -07001301 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Hai Shalomfdcde762020-04-02 11:19:20 -07001302 if (hostapd_dpp_handle_key_pkg(hapd, auth->conf_key_pkg) < 0)
1303 goto fail;
1304
Hai Shalom021b0b52019-04-10 11:17:58 -07001305 status = DPP_STATUS_OK;
1306#ifdef CONFIG_TESTING_OPTIONS
1307 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1308 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1309 status = DPP_STATUS_CONFIG_REJECTED;
1310 }
1311#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001312fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001313 if (status != DPP_STATUS_OK)
1314 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1315#ifdef CONFIG_DPP2
1316 if (auth->peer_version >= 2 &&
1317 auth->conf_resp_status == DPP_STATUS_OK) {
1318 struct wpabuf *msg;
1319
1320 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1321 msg = dpp_build_conf_result(auth, status);
1322 if (!msg)
1323 goto fail2;
1324
1325 wpa_msg(hapd->msg_ctx, MSG_INFO,
1326 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1327 MAC2STR(addr), auth->curr_freq,
1328 DPP_PA_CONFIGURATION_RESULT);
1329 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
1330 addr, wpabuf_head(msg),
1331 wpabuf_len(msg));
1332 wpabuf_free(msg);
1333
1334 /* This exchange will be terminated in the TX status handler */
1335 auth->connect_on_tx_status = 1;
1336 return;
1337 }
1338fail2:
1339#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001340 dpp_auth_deinit(hapd->dpp_auth);
1341 hapd->dpp_auth = NULL;
1342}
1343
1344
1345static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
1346{
1347 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001348 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001349 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001350
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001351 buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
1352 DPP_NETROLE_AP,
Sunil Ravi89eba102022-09-13 21:04:37 -07001353 hapd->conf->dpp_mud_url, NULL,
1354 hapd->conf->dpp_extra_conf_req_name,
1355 hapd->conf->dpp_extra_conf_req_value);
Hai Shalom021b0b52019-04-10 11:17:58 -07001356 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001357 wpa_printf(MSG_DEBUG,
1358 "DPP: No configuration request data available");
1359 return;
1360 }
1361
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001362 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1363 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1364
1365 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
1366 buf, hostapd_dpp_gas_resp_cb, hapd);
1367 if (res < 0) {
1368 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1369 "GAS: Failed to send Query Request");
1370 wpabuf_free(buf);
1371 } else {
1372 wpa_printf(MSG_DEBUG,
1373 "DPP: GAS query started with dialog token %u", res);
1374 }
1375}
1376
1377
1378static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
1379{
1380 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1381 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
1382 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001383#ifdef CONFIG_TESTING_OPTIONS
1384 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1385 wpa_printf(MSG_INFO,
1386 "DPP: TESTING - stop at Authentication Confirm");
1387 if (hapd->dpp_auth->configurator) {
1388 /* Prevent GAS response */
1389 hapd->dpp_auth->auth_success = 0;
1390 }
1391 return;
1392 }
1393#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001394
1395 if (!hapd->dpp_auth->configurator)
1396 hostapd_dpp_start_gas_client(hapd);
1397}
1398
1399
1400static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001401 const u8 *hdr, const u8 *buf, size_t len,
1402 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001403{
1404 struct dpp_authentication *auth = hapd->dpp_auth;
1405 struct wpabuf *msg;
1406
1407 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
1408 MAC2STR(src));
1409
1410 if (!auth) {
1411 wpa_printf(MSG_DEBUG,
1412 "DPP: No DPP Authentication in progress - drop");
1413 return;
1414 }
1415
1416 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1417 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1418 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1419 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1420 return;
1421 }
1422
Roshan Pius3a1667e2018-07-03 15:17:14 -07001423 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1424
1425 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1426 wpa_printf(MSG_DEBUG,
1427 "DPP: Responder accepted request for different negotiation channel");
1428 auth->curr_freq = freq;
1429 }
1430
1431 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001432 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1433 if (!msg) {
1434 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1435 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
1436 return;
1437 }
1438 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1439 return;
1440 }
1441 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1442
Roshan Pius3a1667e2018-07-03 15:17:14 -07001443 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1444 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
1445 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001446 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
1447 wpabuf_head(msg), wpabuf_len(msg));
1448 wpabuf_free(msg);
1449 hapd->dpp_auth_ok_on_ack = 1;
1450}
1451
1452
1453static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1454 const u8 *hdr, const u8 *buf, size_t len)
1455{
1456 struct dpp_authentication *auth = hapd->dpp_auth;
1457
1458 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1459 MAC2STR(src));
1460
1461 if (!auth) {
1462 wpa_printf(MSG_DEBUG,
1463 "DPP: No DPP Authentication in progress - drop");
1464 return;
1465 }
1466
1467 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1468 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1469 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1470 return;
1471 }
1472
1473 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1474 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1475 return;
1476 }
1477
1478 hostapd_dpp_auth_success(hapd, 0);
1479}
1480
1481
Hai Shalom021b0b52019-04-10 11:17:58 -07001482#ifdef CONFIG_DPP2
1483
1484static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
1485 void *timeout_ctx)
1486{
1487 struct hostapd_data *hapd = eloop_ctx;
1488 struct dpp_authentication *auth = hapd->dpp_auth;
1489
1490 if (!auth || !auth->waiting_conf_result)
1491 return;
1492
1493 wpa_printf(MSG_DEBUG,
1494 "DPP: Timeout while waiting for Configuration Result");
1495 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1496 dpp_auth_deinit(auth);
1497 hapd->dpp_auth = NULL;
1498}
1499
1500
Hai Shalomc3565922019-10-28 11:58:20 -07001501static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1502 void *timeout_ctx)
1503{
1504 struct hostapd_data *hapd = eloop_ctx;
1505 struct dpp_authentication *auth = hapd->dpp_auth;
1506
1507 if (!auth || !auth->waiting_conf_result)
1508 return;
1509
1510 wpa_printf(MSG_DEBUG,
1511 "DPP: Timeout while waiting for Connection Status Result");
1512 wpa_msg(hapd->msg_ctx, MSG_INFO,
1513 DPP_EVENT_CONN_STATUS_RESULT "timeout");
1514 dpp_auth_deinit(auth);
1515 hapd->dpp_auth = NULL;
1516}
1517
1518
Sunil Ravi89eba102022-09-13 21:04:37 -07001519#ifdef CONFIG_DPP3
1520
1521static bool hostapd_dpp_pb_active(struct hostapd_data *hapd)
1522{
1523 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1524
1525 return ifaces && (ifaces->dpp_pb_time.sec ||
1526 ifaces->dpp_pb_time.usec);
1527}
1528
1529
1530static void hostapd_dpp_remove_pb_hash(struct hostapd_data *hapd)
1531{
1532 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1533 int i;
1534
1535 if (!ifaces->dpp_pb_bi)
1536 return;
1537 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
1538 struct dpp_pb_info *info = &ifaces->dpp_pb[i];
1539
1540 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
1541 continue;
1542 if (os_memcmp(info->hash, ifaces->dpp_pb_resp_hash,
1543 SHA256_MAC_LEN) == 0) {
1544 /* Allow a new push button session to be established
1545 * immediately without the successfully completed
1546 * session triggering session overlap. */
1547 info->rx_time.sec = 0;
1548 info->rx_time.usec = 0;
1549 wpa_printf(MSG_DEBUG,
1550 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
1551 }
1552 }
1553}
1554
1555#endif /* CONFIG_DPP3 */
1556
1557
Hai Shalom021b0b52019-04-10 11:17:58 -07001558static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
1559 const u8 *hdr, const u8 *buf, size_t len)
1560{
1561 struct dpp_authentication *auth = hapd->dpp_auth;
1562 enum dpp_status_error status;
Sunil Ravi89eba102022-09-13 21:04:37 -07001563#ifdef CONFIG_DPP3
1564 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1565#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001566
1567 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1568 MAC2STR(src));
1569
1570 if (!auth || !auth->waiting_conf_result) {
1571 wpa_printf(MSG_DEBUG,
1572 "DPP: No DPP Configuration waiting for result - drop");
1573 return;
1574 }
1575
1576 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1577 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1578 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1579 return;
1580 }
1581
1582 status = dpp_conf_result_rx(auth, hdr, buf, len);
1583
Hai Shalomc3565922019-10-28 11:58:20 -07001584 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1585 wpa_msg(hapd->msg_ctx, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07001586 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
1587 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07001588 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1589 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1590 hapd, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001591 auth->waiting_conn_status_result = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001592 eloop_cancel_timeout(
1593 hostapd_dpp_conn_status_result_wait_timeout,
1594 hapd, NULL);
1595 eloop_register_timeout(
1596 16, 0, hostapd_dpp_conn_status_result_wait_timeout,
1597 hapd, NULL);
1598 return;
1599 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001600 hostapd_drv_send_action_cancel_wait(hapd);
1601 hostapd_dpp_listen_stop(hapd);
1602 if (status == DPP_STATUS_OK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001603 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
1604 "conf_status=%d", auth->conf_resp_status);
Hai Shalom021b0b52019-04-10 11:17:58 -07001605 else
1606 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1607 dpp_auth_deinit(auth);
1608 hapd->dpp_auth = NULL;
1609 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1610 NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07001611#ifdef CONFIG_DPP3
1612 if (!ifaces->dpp_pb_result_indicated && hostapd_dpp_pb_active(hapd)) {
1613 if (status == DPP_STATUS_OK)
1614 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
1615 "success");
1616 else
1617 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
1618 "no-configuration-available");
1619 ifaces->dpp_pb_result_indicated = true;
1620 if (status == DPP_STATUS_OK)
1621 hostapd_dpp_remove_pb_hash(hapd);
1622 hostapd_dpp_push_button_stop(hapd);
1623 }
1624#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001625}
1626
Hai Shalomc3565922019-10-28 11:58:20 -07001627
1628static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
1629 const u8 *src, const u8 *hdr,
1630 const u8 *buf, size_t len)
1631{
1632 struct dpp_authentication *auth = hapd->dpp_auth;
1633 enum dpp_status_error status;
1634 u8 ssid[SSID_MAX_LEN];
1635 size_t ssid_len = 0;
1636 char *channel_list = NULL;
1637
1638 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1639
1640 if (!auth || !auth->waiting_conn_status_result) {
1641 wpa_printf(MSG_DEBUG,
1642 "DPP: No DPP Configuration waiting for connection status result - drop");
1643 return;
1644 }
1645
1646 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1647 ssid, &ssid_len, &channel_list);
1648 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1649 "result=%d ssid=%s channel_list=%s",
1650 status, wpa_ssid_txt(ssid, ssid_len),
1651 channel_list ? channel_list : "N/A");
1652 os_free(channel_list);
1653 hostapd_drv_send_action_cancel_wait(hapd);
1654 hostapd_dpp_listen_stop(hapd);
1655 dpp_auth_deinit(auth);
1656 hapd->dpp_auth = NULL;
1657 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
1658 hapd, NULL);
1659}
1660
1661
Hai Shalomfdcde762020-04-02 11:19:20 -07001662static void
1663hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
1664 const u8 *hdr, const u8 *buf, size_t len,
1665 unsigned int freq)
1666{
1667 const u8 *r_bootstrap;
1668 u16 r_bootstrap_len;
1669 struct dpp_bootstrap_info *peer_bi;
1670 struct dpp_authentication *auth;
1671
1672 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
1673 MAC2STR(src));
1674
1675 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1676 &r_bootstrap_len);
1677 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1678 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1679 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1680 return;
1681 }
1682 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1683 r_bootstrap, r_bootstrap_len);
1684 peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
1685 r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07001686 dpp_notify_chirp_received(hapd->msg_ctx,
1687 peer_bi ? (int) peer_bi->id : -1,
1688 src, freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07001689 if (!peer_bi) {
1690 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1691 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001692 r_bootstrap, hapd) == 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07001693 return;
1694 wpa_printf(MSG_DEBUG,
1695 "DPP: No matching bootstrapping information found");
Sunil Ravi89eba102022-09-13 21:04:37 -07001696 hostapd_dpp_relay_needs_controller(
1697 hapd, src, DPP_PA_PRESENCE_ANNOUNCEMENT);
Hai Shalomfdcde762020-04-02 11:19:20 -07001698 return;
1699 }
1700
1701 if (hapd->dpp_auth) {
1702 wpa_printf(MSG_DEBUG,
1703 "DPP: Ignore Presence Announcement during ongoing Authentication");
1704 return;
1705 }
1706
1707 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1708 peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
1709 0);
1710 if (!auth)
1711 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07001712 hostapd_dpp_set_testing_options(hapd, auth);
1713 if (dpp_set_configurator(auth,
Hai Shalomfdcde762020-04-02 11:19:20 -07001714 hapd->dpp_configurator_params) < 0) {
1715 dpp_auth_deinit(auth);
1716 return;
1717 }
1718
1719 auth->neg_freq = freq;
1720
Hai Shalom60840252021-02-19 19:02:11 -08001721 /* The source address of the Presence Announcement frame overrides any
1722 * MAC address information from the bootstrapping information. */
1723 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07001724
1725 hapd->dpp_auth = auth;
1726 if (hostapd_dpp_auth_init_next(hapd) < 0) {
1727 dpp_auth_deinit(hapd->dpp_auth);
1728 hapd->dpp_auth = NULL;
1729 }
1730}
1731
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001732
1733static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
1734 void *timeout_ctx)
1735{
1736 struct hostapd_data *hapd = eloop_ctx;
1737 struct dpp_authentication *auth = hapd->dpp_auth;
1738
1739 if (!auth)
1740 return;
1741
1742 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
1743 hostapd_dpp_listen_stop(hapd);
1744 dpp_auth_deinit(auth);
1745 hapd->dpp_auth = NULL;
1746}
1747
1748
1749static void
1750hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
1751 const u8 *hdr, const u8 *buf, size_t len,
1752 unsigned int freq)
1753{
Hai Shalom899fcc72020-10-19 14:38:18 -07001754 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
1755 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001756 struct dpp_configurator *conf;
1757 struct dpp_authentication *auth;
1758 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07001759 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001760
1761 if (hapd->dpp_auth) {
1762 wpa_printf(MSG_DEBUG,
1763 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1764 return;
1765 }
1766
1767 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
1768 MAC2STR(src));
1769
1770 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1771 &csign_hash_len);
1772 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
1773 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1774 "Missing or invalid required Configurator C-sign key Hash attribute");
1775 return;
1776 }
1777 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1778 csign_hash, csign_hash_len);
1779 conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
1780 csign_hash);
1781 if (!conf) {
1782 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1783 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001784 NULL, hapd) == 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001785 return;
1786 wpa_printf(MSG_DEBUG,
1787 "DPP: No matching Configurator information found");
Sunil Ravi89eba102022-09-13 21:04:37 -07001788 hostapd_dpp_relay_needs_controller(
1789 hapd, src, DPP_PA_RECONFIG_ANNOUNCEMENT);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001790 return;
1791 }
1792
Hai Shalom899fcc72020-10-19 14:38:18 -07001793 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
1794 &fcgroup_len);
1795 if (!fcgroup || fcgroup_len != 2) {
1796 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1797 "Missing or invalid required Finite Cyclic Group attribute");
1798 return;
1799 }
1800 group = WPA_GET_LE16(fcgroup);
1801 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
1802
1803 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
1804 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
1805
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001806 auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
Hai Shalom899fcc72020-10-19 14:38:18 -07001807 conf, freq, group, a_nonce, a_nonce_len,
1808 e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001809 if (!auth)
1810 return;
1811 hostapd_dpp_set_testing_options(hapd, auth);
1812 if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
1813 dpp_auth_deinit(auth);
1814 return;
1815 }
1816
1817 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1818 hapd->dpp_auth = auth;
1819
1820 hapd->dpp_in_response_listen = 0;
1821 hapd->dpp_auth_ok_on_ack = 0;
1822 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
1823 max_wait_time = hapd->dpp_resp_wait_time ?
1824 hapd->dpp_resp_wait_time : 2000;
1825 if (wait_time > max_wait_time)
1826 wait_time = max_wait_time;
1827 wait_time += 10; /* give the driver some extra time to complete */
1828 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
1829 hostapd_dpp_reconfig_reply_wait_timeout,
1830 hapd, NULL);
1831 wait_time -= 10;
1832
1833 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1834 " freq=%u type=%d",
1835 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
1836 if (hostapd_drv_send_action(hapd, freq, wait_time, src,
1837 wpabuf_head(auth->reconfig_req_msg),
1838 wpabuf_len(auth->reconfig_req_msg)) < 0) {
1839 dpp_auth_deinit(hapd->dpp_auth);
1840 hapd->dpp_auth = NULL;
1841 }
1842}
1843
1844
1845static void
1846hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
1847 const u8 *hdr, const u8 *buf, size_t len,
1848 unsigned int freq)
1849{
1850 struct dpp_authentication *auth = hapd->dpp_auth;
1851 struct wpabuf *conf;
1852
1853 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
1854 MACSTR, MAC2STR(src));
1855
1856 if (!auth || !auth->reconfig || !auth->configurator) {
1857 wpa_printf(MSG_DEBUG,
1858 "DPP: No DPP Reconfig Authentication in progress - drop");
1859 return;
1860 }
1861
1862 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1863 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1864 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1865 return;
1866 }
1867
1868 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
1869 if (!conf)
1870 return;
1871
1872 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1873 hapd, NULL);
1874
1875 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1876 " freq=%u type=%d",
1877 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
1878 if (hostapd_drv_send_action(hapd, freq, 500, src,
1879 wpabuf_head(conf), wpabuf_len(conf)) < 0) {
1880 wpabuf_free(conf);
1881 dpp_auth_deinit(hapd->dpp_auth);
1882 hapd->dpp_auth = NULL;
1883 return;
1884 }
1885 wpabuf_free(conf);
1886}
1887
Hai Shalom021b0b52019-04-10 11:17:58 -07001888#endif /* CONFIG_DPP2 */
1889
1890
Roshan Pius3a1667e2018-07-03 15:17:14 -07001891static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1892 const u8 *src, unsigned int freq,
1893 u8 trans_id,
1894 enum dpp_status_error status)
1895{
1896 struct wpabuf *msg;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001897 size_t len;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001898
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001899 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
1900#ifdef CONFIG_DPP2
1901 len += 5;
1902#endif /* CONFIG_DPP2 */
1903 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001904 if (!msg)
1905 return;
1906
1907#ifdef CONFIG_TESTING_OPTIONS
1908 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1909 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1910 goto skip_trans_id;
1911 }
1912 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1913 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1914 trans_id ^= 0x01;
1915 }
1916#endif /* CONFIG_TESTING_OPTIONS */
1917
1918 /* Transaction ID */
1919 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1920 wpabuf_put_le16(msg, 1);
1921 wpabuf_put_u8(msg, trans_id);
1922
1923#ifdef CONFIG_TESTING_OPTIONS
1924skip_trans_id:
1925 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1926 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1927 goto skip_status;
1928 }
1929 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1930 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1931 status = 254;
1932 }
1933#endif /* CONFIG_TESTING_OPTIONS */
1934
1935 /* DPP Status */
1936 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1937 wpabuf_put_le16(msg, 1);
1938 wpabuf_put_u8(msg, status);
1939
1940#ifdef CONFIG_TESTING_OPTIONS
1941skip_status:
1942 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1943 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1944 goto skip_connector;
1945 }
1946 if (status == DPP_STATUS_OK &&
1947 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1948 char *connector;
1949
1950 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1951 connector = dpp_corrupt_connector_signature(
1952 hapd->conf->dpp_connector);
1953 if (!connector) {
1954 wpabuf_free(msg);
1955 return;
1956 }
1957 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1958 wpabuf_put_le16(msg, os_strlen(connector));
1959 wpabuf_put_str(msg, connector);
1960 os_free(connector);
1961 goto skip_connector;
1962 }
1963#endif /* CONFIG_TESTING_OPTIONS */
1964
1965 /* DPP Connector */
1966 if (status == DPP_STATUS_OK) {
1967 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1968 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1969 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1970 }
1971
1972#ifdef CONFIG_TESTING_OPTIONS
1973skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001974 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP) {
1975 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
1976 goto skip_proto_ver;
1977 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001978#endif /* CONFIG_TESTING_OPTIONS */
1979
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001980#ifdef CONFIG_DPP2
1981 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001982 u8 ver = DPP_VERSION;
1983#ifdef CONFIG_DPP3
1984 int conn_ver;
1985
1986 conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
1987 if (conn_ver > 0 && ver != conn_ver) {
1988 wpa_printf(MSG_DEBUG,
1989 "DPP: Use Connector version %d instead of current protocol version %d",
1990 conn_ver, ver);
1991 ver = conn_ver;
1992 }
1993#endif /* CONFIG_DPP3 */
1994
1995#ifdef CONFIG_TESTING_OPTIONS
1996 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP) {
1997 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
1998 ver = 1;
1999 }
2000#endif /* CONFIG_TESTING_OPTIONS */
2001
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002002 /* Protocol Version */
2003 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
2004 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002005 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002006 }
2007#endif /* CONFIG_DPP2 */
2008
Hai Shaloma20dcd72022-02-04 13:43:00 -08002009#ifdef CONFIG_TESTING_OPTIONS
2010skip_proto_ver:
2011#endif /* CONFIG_TESTING_OPTIONS */
2012
Roshan Pius3a1667e2018-07-03 15:17:14 -07002013 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
2014 " status=%d", MAC2STR(src), status);
2015 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2016 " freq=%u type=%d status=%d", MAC2STR(src), freq,
2017 DPP_PA_PEER_DISCOVERY_RESP, status);
2018 hostapd_drv_send_action(hapd, freq, 0, src,
2019 wpabuf_head(msg), wpabuf_len(msg));
2020 wpabuf_free(msg);
2021}
2022
2023
Sunil Ravi89eba102022-09-13 21:04:37 -07002024static bool hapd_dpp_connector_available(struct hostapd_data *hapd)
2025{
2026 if (!hapd->wpa_auth ||
2027 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
2028 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
2029 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
2030 return false;
2031 }
2032
2033 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
2034 !hapd->conf->dpp_csign) {
2035 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
2036 return false;
2037 }
2038
2039 return true;
2040}
2041
2042
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002043static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
2044 const u8 *src,
2045 const u8 *buf, size_t len,
2046 unsigned int freq)
2047{
2048 const u8 *connector, *trans_id;
2049 u16 connector_len, trans_id_len;
2050 struct os_time now;
2051 struct dpp_introduction intro;
2052 os_time_t expire;
2053 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002054 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002055
Sunil Ravi89eba102022-09-13 21:04:37 -07002056 os_memset(&intro, 0, sizeof(intro));
2057
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002058 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
2059 MAC2STR(src));
Sunil Ravi89eba102022-09-13 21:04:37 -07002060 if (!hapd_dpp_connector_available(hapd))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002061 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002062
2063 os_get_time(&now);
2064
2065 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002066 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002067 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
2068 return;
2069 }
2070
2071 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2072 &trans_id_len);
2073 if (!trans_id || trans_id_len != 1) {
2074 wpa_printf(MSG_DEBUG,
2075 "DPP: Peer did not include Transaction ID");
2076 return;
2077 }
2078
2079 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2080 if (!connector) {
2081 wpa_printf(MSG_DEBUG,
2082 "DPP: Peer did not include its Connector");
2083 return;
2084 }
2085
Roshan Pius3a1667e2018-07-03 15:17:14 -07002086 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
2087 wpabuf_head(hapd->conf->dpp_netaccesskey),
2088 wpabuf_len(hapd->conf->dpp_netaccesskey),
2089 wpabuf_head(hapd->conf->dpp_csign),
2090 wpabuf_len(hapd->conf->dpp_csign),
2091 connector, connector_len, &expire);
2092 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002093 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002094 "DPP: Network Introduction protocol resulted in internal failure (peer "
2095 MACSTR ")", MAC2STR(src));
Sunil Ravi89eba102022-09-13 21:04:37 -07002096 goto done;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002097 }
2098 if (res != DPP_STATUS_OK) {
2099 wpa_printf(MSG_INFO,
2100 "DPP: Network Introduction protocol resulted in failure (peer "
2101 MACSTR " status %d)", MAC2STR(src), res);
2102 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
2103 res);
Sunil Ravi89eba102022-09-13 21:04:37 -07002104 goto done;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002105 }
2106
Hai Shaloma20dcd72022-02-04 13:43:00 -08002107#ifdef CONFIG_DPP3
2108 if (intro.peer_version && intro.peer_version >= 2) {
2109 const u8 *version;
2110 u16 version_len;
2111 u8 attr_version = 1;
2112
2113 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2114 &version_len);
2115 if (version && version_len >= 1)
2116 attr_version = version[0];
2117 if (attr_version != intro.peer_version) {
2118 wpa_printf(MSG_INFO,
2119 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2120 intro.peer_version, attr_version);
2121 hostapd_dpp_send_peer_disc_resp(hapd, src, freq,
2122 trans_id[0],
2123 DPP_STATUS_NO_MATCH);
Sunil Ravi89eba102022-09-13 21:04:37 -07002124 goto done;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002125 }
2126 }
2127#endif /* CONFIG_DPP3 */
2128
Roshan Pius3a1667e2018-07-03 15:17:14 -07002129 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002130 expire = hapd->conf->dpp_netaccesskey_expiry;
2131 if (expire)
2132 expiration = expire - now.sec;
2133 else
2134 expiration = 0;
2135
2136 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
2137 intro.pmkid, expiration,
2138 WPA_KEY_MGMT_DPP) < 0) {
2139 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
Sunil Ravi89eba102022-09-13 21:04:37 -07002140 goto done;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002141 }
2142
Roshan Pius3a1667e2018-07-03 15:17:14 -07002143 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
2144 DPP_STATUS_OK);
Sunil Ravi89eba102022-09-13 21:04:37 -07002145done:
2146 dpp_peer_intro_deinit(&intro);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002147}
2148
2149
2150static void
2151hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002152 const u8 *hdr, const u8 *buf, size_t len,
2153 unsigned int freq, bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002154{
2155 struct wpabuf *msg;
2156
2157 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
2158 MAC2STR(src));
2159
Sunil Ravia04bd252022-05-02 22:54:18 -07002160 if (hapd->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
2161 wpa_printf(MSG_DEBUG,
2162 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
2163 return;
2164 }
2165 if (hapd->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
2166 wpa_printf(MSG_DEBUG,
2167 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
2168 return;
2169 }
2170
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002171 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2172 * values here */
2173
2174 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
2175 wpa_printf(MSG_DEBUG,
2176 "DPP: No PKEX code configured - ignore request");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002177 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002178 }
2179
Sunil Ravi89eba102022-09-13 21:04:37 -07002180#ifdef CONFIG_DPP2
2181 if (dpp_controller_is_own_pkex_req(hapd->iface->interfaces->dpp,
2182 buf, len)) {
2183 wpa_printf(MSG_DEBUG,
2184 "DPP: PKEX Exchange Request is from local Controller - ignore request");
2185 return;
2186 }
2187#endif /* CONFIG_DPP2 */
2188
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002189 if (hapd->dpp_pkex) {
2190 /* TODO: Support parallel operations */
2191 wpa_printf(MSG_DEBUG,
2192 "DPP: Already in PKEX session - ignore new request");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002193 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002194 }
2195
Roshan Pius3a1667e2018-07-03 15:17:14 -07002196 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
2197 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002198 hapd->own_addr, src,
2199 hapd->dpp_pkex_identifier,
2200 hapd->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07002201 hapd->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002202 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002203 if (!hapd->dpp_pkex) {
2204 wpa_printf(MSG_DEBUG,
2205 "DPP: Failed to process the request - ignore it");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002206 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002207 }
2208
2209 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002210 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2211 " freq=%u type=%d", MAC2STR(src), freq,
2212 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002213 hostapd_drv_send_action(hapd, freq, 0, src,
2214 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002215 if (hapd->dpp_pkex->failed) {
2216 wpa_printf(MSG_DEBUG,
2217 "DPP: Terminate PKEX exchange due to an earlier error");
2218 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
2219 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
2220 dpp_pkex_free(hapd->dpp_pkex);
2221 hapd->dpp_pkex = NULL;
2222 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002223
2224 return;
2225
2226try_relay:
2227#ifdef CONFIG_DPP2
Sunil8cd6f4d2022-06-28 18:40:46 +00002228 if (v2 && dpp_relay_rx_action(hapd->iface->interfaces->dpp,
2229 src, hdr, buf, len, freq, NULL, NULL,
Sunil Ravi89eba102022-09-13 21:04:37 -07002230 hapd) != 0) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002231 wpa_printf(MSG_DEBUG,
2232 "DPP: No Relay available for the message");
Sunil Ravi89eba102022-09-13 21:04:37 -07002233 hostapd_dpp_relay_needs_controller(hapd, src,
2234 DPP_PA_PKEX_EXCHANGE_REQ);
2235 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002236#else /* CONFIG_DPP2 */
2237 wpa_printf(MSG_DEBUG, "DPP: No relay functionality included - skip");
2238#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002239}
2240
2241
2242static void
2243hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
2244 const u8 *buf, size_t len, unsigned int freq)
2245{
2246 struct wpabuf *msg;
2247
2248 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2249 MAC2STR(src));
2250
2251 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2252 * values here */
2253
2254 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
2255 hapd->dpp_pkex->exchange_done) {
2256 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2257 return;
2258 }
2259
Hai Shaloma20dcd72022-02-04 13:43:00 -08002260 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
2261 hapd->dpp_pkex->exch_req_wait_time = 0;
2262
Roshan Pius3a1667e2018-07-03 15:17:14 -07002263 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002264 if (!msg) {
2265 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2266 return;
2267 }
2268
2269 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
2270 MAC2STR(src));
2271
Roshan Pius3a1667e2018-07-03 15:17:14 -07002272 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2273 " freq=%u type=%d", MAC2STR(src), freq,
2274 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002275 hostapd_drv_send_action(hapd, freq, 0, src,
2276 wpabuf_head(msg), wpabuf_len(msg));
2277 wpabuf_free(msg);
2278}
2279
2280
2281static void
2282hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
2283 const u8 *hdr, const u8 *buf, size_t len,
2284 unsigned int freq)
2285{
2286 struct wpabuf *msg;
2287 struct dpp_pkex *pkex = hapd->dpp_pkex;
2288 struct dpp_bootstrap_info *bi;
2289
2290 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
2291 MAC2STR(src));
2292
2293 if (!pkex || pkex->initiator || !pkex->exchange_done) {
2294 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2295 return;
2296 }
2297
2298 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
2299 if (!msg) {
2300 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002301 if (hapd->dpp_pkex->failed) {
2302 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
2303 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
2304 hapd->dpp_pkex->own_bi->pkex_t =
2305 hapd->dpp_pkex->t;
2306 dpp_pkex_free(hapd->dpp_pkex);
2307 hapd->dpp_pkex = NULL;
2308 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002309 return;
2310 }
2311
2312 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
2313 MACSTR, MAC2STR(src));
2314
Roshan Pius3a1667e2018-07-03 15:17:14 -07002315 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2316 " freq=%u type=%d", MAC2STR(src), freq,
2317 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002318 hostapd_drv_send_action(hapd, freq, 0, src,
2319 wpabuf_head(msg), wpabuf_len(msg));
2320 wpabuf_free(msg);
2321
Sunil Ravi89eba102022-09-13 21:04:37 -07002322 hostapd_dpp_pkex_clear_code(hapd);
Hai Shalom021b0b52019-04-10 11:17:58 -07002323 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002324 if (!bi)
2325 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002326 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002327}
2328
2329
2330static void
2331hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
2332 const u8 *hdr, const u8 *buf, size_t len,
2333 unsigned int freq)
2334{
Sunil Ravi89eba102022-09-13 21:04:37 -07002335 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002336 int res;
Hai Shalom021b0b52019-04-10 11:17:58 -07002337 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002338 struct dpp_pkex *pkex = hapd->dpp_pkex;
2339 char cmd[500];
2340
2341 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2342 MAC2STR(src));
2343
2344 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2345 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2346 return;
2347 }
2348
2349 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2350 if (res < 0) {
2351 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2352 return;
2353 }
2354
Sunil Ravi89eba102022-09-13 21:04:37 -07002355 hostapd_dpp_pkex_clear_code(hapd);
2356 bi = dpp_pkex_finish(ifaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002357 if (!bi)
2358 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002359 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002360
Sunil Ravi89eba102022-09-13 21:04:37 -07002361#ifdef CONFIG_DPP3
2362 if (ifaces->dpp_pb_bi &&
2363 os_memcmp(bi->pubkey_hash_chirp, ifaces->dpp_pb_resp_hash,
2364 SHA256_MAC_LEN) != 0) {
2365 char id[20];
2366
2367 wpa_printf(MSG_INFO,
2368 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
2369 wpa_hexdump(MSG_DEBUG,
2370 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
2371 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
2372 wpa_hexdump(MSG_DEBUG,
2373 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
2374 ifaces->dpp_pb_resp_hash, SHA256_MAC_LEN);
2375
2376 os_snprintf(id, sizeof(id), "%u", bi->id);
2377 dpp_bootstrap_remove(ifaces->dpp, id);
2378 hostapd_dpp_push_button_stop(hapd);
2379 return;
2380 }
2381#endif /* CONFIG_DPP3 */
2382
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002383 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2384 bi->id,
2385 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
2386 wpa_printf(MSG_DEBUG,
2387 "DPP: Start authentication after PKEX with parameters: %s",
2388 cmd);
2389 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
2390 wpa_printf(MSG_DEBUG,
2391 "DPP: Authentication initialization failed");
2392 return;
2393 }
2394}
2395
2396
Sunil Ravi89eba102022-09-13 21:04:37 -07002397#ifdef CONFIG_DPP3
2398
2399static void hostapd_dpp_pb_pkex_init(struct hostapd_data *hapd,
2400 unsigned int freq, const u8 *src,
2401 const u8 *r_hash)
2402{
2403 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
2404 struct dpp_pkex *pkex;
2405 struct wpabuf *msg;
2406 char ssid_hex[2 * SSID_MAX_LEN + 1], *pass_hex = NULL;
2407 char cmd[300];
2408 const char *password = NULL;
2409 struct sae_password_entry *e;
2410 int conf_id = -1;
2411 bool sae = false, psk = false;
2412 size_t len;
2413
2414 if (hapd->dpp_pkex) {
2415 wpa_printf(MSG_DEBUG,
2416 "PDP: Sending previously generated PKEX Exchange Request to "
2417 MACSTR, MAC2STR(src));
2418 msg = hapd->dpp_pkex->exchange_req;
2419 hostapd_drv_send_action(hapd, freq, 0, src,
2420 wpabuf_head(msg), wpabuf_len(msg));
2421 return;
2422 }
2423
2424 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
2425 MACSTR, MAC2STR(src));
2426
2427 hapd->dpp_pkex_bi = ifaces->dpp_pb_bi;
2428 os_memcpy(ifaces->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
2429
2430 pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr,
2431 "PBPKEX", (const char *) ifaces->dpp_pb_c_nonce,
2432 ifaces->dpp_pb_bi->curve->nonce_len,
2433 true);
2434 if (!pkex) {
2435 hostapd_dpp_push_button_stop(hapd);
2436 return;
2437 }
2438 pkex->freq = freq;
2439
2440 hapd->dpp_pkex = pkex;
2441 msg = hapd->dpp_pkex->exchange_req;
2442
2443 if (ifaces->dpp_pb_cmd) {
2444 /* Use the externally provided configuration */
2445 os_free(hapd->dpp_pkex_auth_cmd);
2446 len = 30 + os_strlen(ifaces->dpp_pb_cmd);
2447 hapd->dpp_pkex_auth_cmd = os_malloc(len);
2448 if (!hapd->dpp_pkex_auth_cmd) {
2449 hostapd_dpp_push_button_stop(hapd);
2450 return;
2451 }
2452 os_snprintf(hapd->dpp_pkex_auth_cmd, len, " own=%d %s",
2453 hapd->dpp_pkex_bi->id, ifaces->dpp_pb_cmd);
2454 goto send_frame;
2455 }
2456
2457 /* Build config based on the current AP configuration */
2458 wpa_snprintf_hex(ssid_hex, sizeof(ssid_hex),
2459 (const u8 *) hapd->conf->ssid.ssid,
2460 hapd->conf->ssid.ssid_len);
2461
2462 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
2463 /* TODO: If a local Configurator has been enabled, allow a
2464 * DPP AKM credential to be provisioned by setting conf_id. */
2465 }
2466
2467 if (hapd->conf->wpa & WPA_PROTO_RSN) {
2468 psk = hapd->conf->wpa_key_mgmt & (WPA_KEY_MGMT_PSK |
2469 WPA_KEY_MGMT_PSK_SHA256);
2470#ifdef CONFIG_SAE
2471 sae = hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE;
2472#endif /* CONFIG_SAE */
2473 }
2474
2475#ifdef CONFIG_SAE
2476 for (e = hapd->conf->sae_passwords; sae && e && !password;
2477 e = e->next) {
2478 if (e->identifier || !is_broadcast_ether_addr(e->peer_addr))
2479 continue;
2480 password = e->password;
2481 }
2482#endif /* CONFIG_SAE */
2483 if (!password && hapd->conf->ssid.wpa_passphrase_set &&
2484 hapd->conf->ssid.wpa_passphrase)
2485 password = hapd->conf->ssid.wpa_passphrase;
2486 if (password) {
2487 len = 2 * os_strlen(password) + 1;
2488 pass_hex = os_malloc(len);
2489 if (!pass_hex) {
2490 hostapd_dpp_push_button_stop(hapd);
2491 return;
2492 }
2493 wpa_snprintf_hex(pass_hex, len, (const u8 *) password,
2494 os_strlen(password));
2495 }
2496
2497 if (conf_id > 0 && sae && psk && pass_hex) {
2498 os_snprintf(cmd, sizeof(cmd),
2499 "conf=sta-dpp+psk+sae configurator=%d ssid=%s pass=%s",
2500 conf_id, ssid_hex, pass_hex);
2501 } else if (conf_id > 0 && sae && pass_hex) {
2502 os_snprintf(cmd, sizeof(cmd),
2503 "conf=sta-dpp+sae configurator=%d ssid=%s pass=%s",
2504 conf_id, ssid_hex, pass_hex);
2505 } else if (conf_id > 0) {
2506 os_snprintf(cmd, sizeof(cmd),
2507 "conf=sta-dpp configurator=%d ssid=%s",
2508 conf_id, ssid_hex);
2509 } if (sae && psk && pass_hex) {
2510 os_snprintf(cmd, sizeof(cmd),
2511 "conf=sta-psk+sae ssid=%s pass=%s",
2512 ssid_hex, pass_hex);
2513 } else if (sae && pass_hex) {
2514 os_snprintf(cmd, sizeof(cmd),
2515 "conf=sta-sae ssid=%s pass=%s",
2516 ssid_hex, pass_hex);
2517 } else if (psk && pass_hex) {
2518 os_snprintf(cmd, sizeof(cmd),
2519 "conf=sta-psk ssid=%s pass=%s",
2520 ssid_hex, pass_hex);
2521 } else {
2522 wpa_printf(MSG_INFO,
2523 "DPP: Unsupported AP configuration for push button");
2524 str_clear_free(pass_hex);
2525 hostapd_dpp_push_button_stop(hapd);
2526 return;
2527 }
2528 str_clear_free(pass_hex);
2529
2530 os_free(hapd->dpp_pkex_auth_cmd);
2531 len = 30 + os_strlen(cmd);
2532 hapd->dpp_pkex_auth_cmd = os_malloc(len);
2533 if (hapd->dpp_pkex_auth_cmd)
2534 os_snprintf(hapd->dpp_pkex_auth_cmd, len, " own=%d %s",
2535 hapd->dpp_pkex_bi->id, cmd);
2536 forced_memzero(cmd, sizeof(cmd));
2537 if (!hapd->dpp_pkex_auth_cmd) {
2538 hostapd_dpp_push_button_stop(hapd);
2539 return;
2540 }
2541
2542send_frame:
2543 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2544 " freq=%u type=%d", MAC2STR(src), freq,
2545 DPP_PA_PKEX_EXCHANGE_REQ);
2546 hostapd_drv_send_action(hapd, pkex->freq, 0, src,
2547 wpabuf_head(msg), wpabuf_len(msg));
2548 pkex->exch_req_wait_time = 2000;
2549 pkex->exch_req_tries = 1;
2550}
2551
2552
2553static void
2554hostapd_dpp_rx_pb_presence_announcement(struct hostapd_data *hapd,
2555 const u8 *src, const u8 *hdr,
2556 const u8 *buf, size_t len,
2557 unsigned int freq)
2558{
2559 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
2560 const u8 *r_hash;
2561 u16 r_hash_len;
2562 unsigned int i;
2563 bool found = false;
2564 struct dpp_pb_info *info, *tmp;
2565 struct os_reltime now, age;
2566 struct wpabuf *msg;
2567
2568 if (!ifaces)
2569 return;
2570
2571 os_get_reltime(&now);
2572 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
2573 MACSTR, MAC2STR(src));
2574
2575 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2576 &r_hash_len);
2577 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
2578 wpa_printf(MSG_DEBUG,
2579 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
2580 return;
2581 }
2582 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2583 r_hash, r_hash_len);
2584
2585 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2586 info = &ifaces->dpp_pb[i];
2587 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
2588 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
2589 continue;
2590 wpa_printf(MSG_DEBUG,
2591 "DPP: Active push button Enrollee already known");
2592 found = true;
2593 info->rx_time = now;
2594 }
2595
2596 if (!found) {
2597 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2598 tmp = &ifaces->dpp_pb[i];
2599 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
2600 continue;
2601
2602 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
2603 wpa_hexdump(MSG_DEBUG,
2604 "DPP: Push button Enrollee hash expired",
2605 tmp->hash, SHA256_MAC_LEN);
2606 tmp->rx_time.sec = 0;
2607 tmp->rx_time.usec = 0;
2608 continue;
2609 }
2610
2611 wpa_hexdump(MSG_DEBUG,
2612 "DPP: Push button session overlap with hash",
2613 tmp->hash, SHA256_MAC_LEN);
2614 if (!ifaces->dpp_pb_result_indicated &&
2615 hostapd_dpp_pb_active(hapd)) {
2616 wpa_msg(hapd->msg_ctx, MSG_INFO,
2617 DPP_EVENT_PB_RESULT "session-overlap");
2618 ifaces->dpp_pb_result_indicated = true;
2619 }
2620 hostapd_dpp_push_button_stop(hapd);
2621 return;
2622 }
2623
2624 /* Replace the oldest entry */
2625 info = &ifaces->dpp_pb[0];
2626 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
2627 tmp = &ifaces->dpp_pb[i];
2628 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
2629 info = tmp;
2630 }
2631 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
2632 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
2633 info->rx_time = now;
2634 }
2635
2636 if (!hostapd_dpp_pb_active(hapd)) {
2637 wpa_printf(MSG_DEBUG,
2638 "DPP: Discard message since own push button has not been pressed");
2639 return;
2640 }
2641
2642 if (ifaces->dpp_pb_announce_time.sec == 0 &&
2643 ifaces->dpp_pb_announce_time.usec == 0) {
2644 /* Start a wait before allowing PKEX to be initiated */
2645 ifaces->dpp_pb_announce_time = now;
2646 }
2647
2648 if (!ifaces->dpp_pb_bi) {
2649 int res;
2650
2651 res = dpp_bootstrap_gen(ifaces->dpp, "type=pkex");
2652 if (res < 0)
2653 return;
2654 ifaces->dpp_pb_bi = dpp_bootstrap_get_id(ifaces->dpp, res);
2655 if (!ifaces->dpp_pb_bi)
2656 return;
2657
2658 if (random_get_bytes(ifaces->dpp_pb_c_nonce,
2659 ifaces->dpp_pb_bi->curve->nonce_len)) {
2660 wpa_printf(MSG_ERROR,
2661 "DPP: Failed to generate C-nonce");
2662 hostapd_dpp_push_button_stop(hapd);
2663 return;
2664 }
2665 }
2666
2667 /* Skip the response if one was sent within last 50 ms since the
2668 * Enrollee is going to send out at least three announcement messages.
2669 */
2670 os_reltime_sub(&now, &ifaces->dpp_pb_last_resp, &age);
2671 if (age.sec == 0 && age.usec < 50000) {
2672 wpa_printf(MSG_DEBUG,
2673 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
2674 return;
2675 }
2676
2677 msg = dpp_build_pb_announcement_resp(
2678 ifaces->dpp_pb_bi, r_hash, ifaces->dpp_pb_c_nonce,
2679 ifaces->dpp_pb_bi->curve->nonce_len);
2680 if (!msg) {
2681 hostapd_dpp_push_button_stop(hapd);
2682 return;
2683 }
2684
2685 wpa_printf(MSG_DEBUG,
2686 "DPP: Send Push Button Presence Announcement Response to "
2687 MACSTR, MAC2STR(src));
2688 ifaces->dpp_pb_last_resp = now;
2689
2690 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2691 " freq=%u type=%d", MAC2STR(src), freq,
2692 DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
2693 hostapd_drv_send_action(hapd, freq, 0, src,
2694 wpabuf_head(msg), wpabuf_len(msg));
2695 wpabuf_free(msg);
2696
2697 if (os_reltime_expired(&now, &ifaces->dpp_pb_announce_time, 15))
2698 hostapd_dpp_pb_pkex_init(hapd, freq, src, r_hash);
2699}
2700
2701
2702static void
2703hostapd_dpp_rx_priv_peer_intro_query(struct hostapd_data *hapd, const u8 *src,
2704 const u8 *hdr, const u8 *buf, size_t len,
2705 unsigned int freq)
2706{
2707 const u8 *trans_id, *version;
2708 u16 trans_id_len, version_len;
2709 struct wpabuf *msg;
2710 u8 ver = DPP_VERSION;
2711 int conn_ver;
2712
2713 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Query from "
2714 MACSTR, MAC2STR(src));
2715
2716 if (!hapd_dpp_connector_available(hapd))
2717 return;
2718
2719 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2720 &trans_id_len);
2721 if (!trans_id || trans_id_len != 1) {
2722 wpa_printf(MSG_DEBUG,
2723 "DPP: Peer did not include Transaction ID");
2724 return;
2725 }
2726
2727 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2728 &version_len);
2729 if (!version || version_len != 1) {
2730 wpa_printf(MSG_DEBUG,
2731 "DPP: Peer did not include Protocol Version");
2732 return;
2733 }
2734
2735 wpa_printf(MSG_DEBUG, "DPP: Transaction ID %u, Version %u",
2736 trans_id[0], version[0]);
2737
2738 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
2739 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_NOTIFY, len);
2740 if (!msg)
2741 return;
2742
2743 /* Transaction ID */
2744 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2745 wpabuf_put_le16(msg, 1);
2746 wpabuf_put_u8(msg, trans_id[0]);
2747
2748 /* Protocol Version */
2749 conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
2750 if (conn_ver > 0 && ver != conn_ver) {
2751 wpa_printf(MSG_DEBUG,
2752 "DPP: Use Connector version %d instead of current protocol version %d",
2753 conn_ver, ver);
2754 ver = conn_ver;
2755 }
2756 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
2757 wpabuf_put_le16(msg, 1);
2758 wpabuf_put_u8(msg, ver);
2759
2760 /* DPP Connector */
2761 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2762 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
2763 wpabuf_put_str(msg, hapd->conf->dpp_connector);
2764
2765 wpa_printf(MSG_DEBUG, "DPP: Send Private Peer Introduction Notify to "
2766 MACSTR, MAC2STR(src));
2767 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2768 " freq=%u type=%d", MAC2STR(src), freq,
2769 DPP_PA_PRIV_PEER_INTRO_NOTIFY);
2770 hostapd_drv_send_action(hapd, freq, 0, src,
2771 wpabuf_head(msg), wpabuf_len(msg));
2772 wpabuf_free(msg);
2773}
2774
2775
2776static void
2777hostapd_dpp_rx_priv_peer_intro_update(struct hostapd_data *hapd, const u8 *src,
2778 const u8 *hdr, const u8 *buf, size_t len,
2779 unsigned int freq)
2780{
2781 struct crypto_ec_key *own_key;
2782 const struct dpp_curve_params *curve;
2783 enum hpke_kem_id kem_id;
2784 enum hpke_kdf_id kdf_id;
2785 enum hpke_aead_id aead_id;
2786 const u8 *aad = hdr;
2787 size_t aad_len = DPP_HDR_LEN;
2788 struct wpabuf *pt;
2789 const u8 *trans_id, *wrapped, *version, *connector;
2790 u16 trans_id_len, wrapped_len, version_len, connector_len;
2791 struct os_time now;
2792 struct dpp_introduction intro;
2793 os_time_t expire;
2794 int expiration;
2795 enum dpp_status_error res;
2796
2797 os_memset(&intro, 0, sizeof(intro));
2798
2799 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Update from "
2800 MACSTR, MAC2STR(src));
2801
2802 if (!hapd_dpp_connector_available(hapd))
2803 return;
2804
2805 os_get_time(&now);
2806
2807 if (hapd->conf->dpp_netaccesskey_expiry &&
2808 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
2809 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
2810 return;
2811 }
2812
2813 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2814 &trans_id_len);
2815 if (!trans_id || trans_id_len != 1) {
2816 wpa_printf(MSG_DEBUG,
2817 "DPP: Peer did not include Transaction ID");
2818 return;
2819 }
2820
2821 wrapped = dpp_get_attr(buf, len, DPP_ATTR_WRAPPED_DATA,
2822 &wrapped_len);
2823 if (!wrapped) {
2824 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Wrapped Data");
2825 return;
2826 }
2827
2828 own_key = dpp_set_keypair(&curve,
2829 wpabuf_head(hapd->conf->dpp_netaccesskey),
2830 wpabuf_len(hapd->conf->dpp_netaccesskey));
2831 if (!own_key) {
2832 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
2833 return;
2834 }
2835
2836 if (dpp_hpke_suite(curve->ike_group, &kem_id, &kdf_id, &aead_id) < 0) {
2837 wpa_printf(MSG_ERROR, "DPP: Unsupported curve %d",
2838 curve->ike_group);
2839 crypto_ec_key_deinit(own_key);
2840 return;
2841 }
2842
2843 pt = hpke_base_open(kem_id, kdf_id, aead_id, own_key, NULL, 0,
2844 aad, aad_len, wrapped, wrapped_len);
2845 crypto_ec_key_deinit(own_key);
2846 if (!pt) {
2847 wpa_printf(MSG_INFO, "DPP: Failed to decrypt Connector");
2848 return;
2849 }
2850 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE-Decrypted Wrapped Data", pt);
2851
2852 connector = dpp_get_attr(wpabuf_head(pt), wpabuf_len(pt),
2853 DPP_ATTR_CONNECTOR, &connector_len);
2854 if (!connector) {
2855 wpa_printf(MSG_DEBUG,
2856 "DPP: Peer did not include its Connector");
2857 goto done;
2858 }
2859
2860 version = dpp_get_attr(wpabuf_head(pt), wpabuf_len(pt),
2861 DPP_ATTR_PROTOCOL_VERSION, &version_len);
2862 if (!version || version_len < 1) {
2863 wpa_printf(MSG_DEBUG,
2864 "DPP: Peer did not include Protocol Version");
2865 goto done;
2866 }
2867
2868 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
2869 wpabuf_head(hapd->conf->dpp_netaccesskey),
2870 wpabuf_len(hapd->conf->dpp_netaccesskey),
2871 wpabuf_head(hapd->conf->dpp_csign),
2872 wpabuf_len(hapd->conf->dpp_csign),
2873 connector, connector_len, &expire);
2874 if (res == 255) {
2875 wpa_printf(MSG_INFO,
2876 "DPP: Network Introduction protocol resulted in internal failure (peer "
2877 MACSTR ")", MAC2STR(src));
2878 goto done;
2879 }
2880 if (res != DPP_STATUS_OK) {
2881 wpa_printf(MSG_INFO,
2882 "DPP: Network Introduction protocol resulted in failure (peer "
2883 MACSTR " status %d)", MAC2STR(src), res);
2884 goto done;
2885 }
2886
2887 if (intro.peer_version && intro.peer_version >= 2) {
2888 u8 attr_version = 1;
2889
2890 if (version && version_len >= 1)
2891 attr_version = version[0];
2892 if (attr_version != intro.peer_version) {
2893 wpa_printf(MSG_INFO,
2894 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2895 intro.peer_version, attr_version);
2896 goto done;
2897 }
2898 }
2899
2900 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
2901 expire = hapd->conf->dpp_netaccesskey_expiry;
2902 if (expire)
2903 expiration = expire - now.sec;
2904 else
2905 expiration = 0;
2906
2907 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
2908 intro.pmkid, expiration,
2909 WPA_KEY_MGMT_DPP) < 0) {
2910 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
2911 goto done;
2912 }
2913
2914 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction completed with "
2915 MACSTR, MAC2STR(src));
2916
2917done:
2918 dpp_peer_intro_deinit(&intro);
2919 wpabuf_free(pt);
2920}
2921
2922#endif /* CONFIG_DPP3 */
2923
2924
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002925void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
2926 const u8 *buf, size_t len, unsigned int freq)
2927{
2928 u8 crypto_suite;
2929 enum dpp_public_action_frame_type type;
2930 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002931 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002932
2933 if (len < DPP_HDR_LEN)
2934 return;
2935 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2936 return;
2937 hdr = buf;
2938 buf += 4;
2939 len -= 4;
2940 crypto_suite = *buf++;
2941 type = *buf++;
2942 len -= 2;
2943
2944 wpa_printf(MSG_DEBUG,
2945 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2946 MACSTR " freq=%u",
2947 crypto_suite, type, MAC2STR(src), freq);
2948 if (crypto_suite != 1) {
2949 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2950 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002951 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2952 " freq=%u type=%d ignore=unsupported-crypto-suite",
2953 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002954 return;
2955 }
2956 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002957 if (dpp_check_attrs(buf, len) < 0) {
2958 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2959 " freq=%u type=%d ignore=invalid-attributes",
2960 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002961 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002962 }
2963 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2964 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002965
Hai Shalom81f62d82019-07-22 12:10:00 -07002966#ifdef CONFIG_DPP2
2967 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002968 src, hdr, buf, len, freq, NULL, NULL,
2969 hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07002970 return;
2971#endif /* CONFIG_DPP2 */
2972
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002973 switch (type) {
2974 case DPP_PA_AUTHENTICATION_REQ:
2975 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
2976 break;
2977 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002978 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002979 break;
2980 case DPP_PA_AUTHENTICATION_CONF:
2981 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
2982 break;
2983 case DPP_PA_PEER_DISCOVERY_REQ:
2984 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
2985 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002986#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002987 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002988 /* This is for PKEXv2, but for now, process only with
2989 * CONFIG_DPP3 to avoid issues with a capability that has not
2990 * been tested with other implementations. */
2991 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
2992 true);
2993 break;
2994#endif /* CONFIG_DPP3 */
2995 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
2996 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
2997 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002998 break;
2999 case DPP_PA_PKEX_EXCHANGE_RESP:
3000 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
3001 break;
3002 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
3003 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
3004 freq);
3005 break;
3006 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
3007 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
3008 freq);
3009 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003010#ifdef CONFIG_DPP2
3011 case DPP_PA_CONFIGURATION_RESULT:
3012 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
3013 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003014 case DPP_PA_CONNECTION_STATUS_RESULT:
3015 hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
3016 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07003017 case DPP_PA_PRESENCE_ANNOUNCEMENT:
3018 hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
3019 freq);
3020 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003021 case DPP_PA_RECONFIG_ANNOUNCEMENT:
3022 hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
3023 freq);
3024 break;
3025 case DPP_PA_RECONFIG_AUTH_RESP:
3026 hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
3027 freq);
3028 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003029#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07003030#ifdef CONFIG_DPP3
3031 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
3032 hostapd_dpp_rx_pb_presence_announcement(hapd, src, hdr,
3033 buf, len, freq);
3034 break;
3035 case DPP_PA_PRIV_PEER_INTRO_QUERY:
3036 hostapd_dpp_rx_priv_peer_intro_query(hapd, src, hdr,
3037 buf, len, freq);
3038 break;
3039 case DPP_PA_PRIV_PEER_INTRO_UPDATE:
3040 hostapd_dpp_rx_priv_peer_intro_update(hapd, src, hdr,
3041 buf, len, freq);
3042 break;
3043#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003044 default:
3045 wpa_printf(MSG_DEBUG,
3046 "DPP: Ignored unsupported frame subtype %d", type);
3047 break;
3048 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003049
3050 if (hapd->dpp_pkex)
3051 pkex_t = hapd->dpp_pkex->t;
3052 else if (hapd->dpp_pkex_bi)
3053 pkex_t = hapd->dpp_pkex_bi->pkex_t;
3054 else
3055 pkex_t = 0;
3056 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
3057 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
3058 hostapd_dpp_pkex_remove(hapd, "*");
3059 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003060}
3061
3062
3063struct wpabuf *
3064hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
Hai Shalom81f62d82019-07-22 12:10:00 -07003065 const u8 *query, size_t query_len,
3066 const u8 *data, size_t data_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003067{
3068 struct dpp_authentication *auth = hapd->dpp_auth;
3069 struct wpabuf *resp;
3070
3071 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003072 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003073 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003074#ifdef CONFIG_DPP2
3075 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
3076 data_len) == 0) {
3077 /* Response will be forwarded once received over TCP */
3078 return NULL;
3079 }
3080#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003081 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
3082 return NULL;
3083 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08003084
3085 if (hapd->dpp_auth_ok_on_ack && auth->configurator) {
3086 wpa_printf(MSG_DEBUG,
3087 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
3088 /* hostapd_dpp_auth_success() would normally have been called
3089 * from TX status handler, but since there was no such handler
3090 * call yet, simply send out the event message and proceed with
3091 * exchange. */
3092 wpa_msg(hapd->msg_ctx, MSG_INFO,
3093 DPP_EVENT_AUTH_SUCCESS "init=1");
3094 hapd->dpp_auth_ok_on_ack = 0;
3095 }
3096
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003097 wpa_hexdump(MSG_DEBUG,
3098 "DPP: Received Configuration Request (GAS Query Request)",
3099 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003100 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
3101 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003102 resp = dpp_conf_req_rx(auth, query, query_len);
3103 if (!resp)
3104 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
3105 return resp;
3106}
3107
3108
Roshan Pius3a1667e2018-07-03 15:17:14 -07003109void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
3110{
Hai Shalom021b0b52019-04-10 11:17:58 -07003111 struct dpp_authentication *auth = hapd->dpp_auth;
Sunil Ravi89eba102022-09-13 21:04:37 -07003112#ifdef CONFIG_DPP3
3113 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3114#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07003115
3116 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07003117 return;
3118
Sunil Ravia04bd252022-05-02 22:54:18 -07003119#ifdef CONFIG_DPP3
3120 if (auth->waiting_new_key && ok) {
3121 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
3122 return;
3123 }
3124#endif /* CONFIG_DPP3 */
3125
Hai Shalom021b0b52019-04-10 11:17:58 -07003126 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
3127 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003128 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003129 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003130 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003131#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003132 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
3133 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003134 if (ok && auth->peer_version >= 2 &&
3135 auth->conf_resp_status == DPP_STATUS_OK) {
3136 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
3137 auth->waiting_conf_result = 1;
3138 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
3139 hapd, NULL);
3140 eloop_register_timeout(2, 0,
3141 hostapd_dpp_config_result_wait_timeout,
3142 hapd, NULL);
3143 return;
3144 }
3145#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003146 hostapd_drv_send_action_cancel_wait(hapd);
3147
3148 if (ok)
Sunil Ravi89eba102022-09-13 21:04:37 -07003149 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
3150 "conf_status=%d", auth->conf_resp_status);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003151 else
3152 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
3153 dpp_auth_deinit(hapd->dpp_auth);
3154 hapd->dpp_auth = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003155#ifdef CONFIG_DPP3
3156 if (!ifaces->dpp_pb_result_indicated && hostapd_dpp_pb_active(hapd)) {
3157 if (ok)
3158 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
3159 "success");
3160 else
3161 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
3162 "could-not-connect");
3163 ifaces->dpp_pb_result_indicated = true;
3164 if (ok)
3165 hostapd_dpp_remove_pb_hash(hapd);
3166 hostapd_dpp_push_button_stop(hapd);
3167 }
3168#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003169}
3170
3171
Roshan Pius3a1667e2018-07-03 15:17:14 -07003172int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
3173{
3174 struct dpp_authentication *auth;
3175 int ret = -1;
3176 char *curve = NULL;
3177
Hai Shalomfdcde762020-04-02 11:19:20 -07003178 auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003179 if (!auth)
3180 return -1;
3181
3182 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08003183 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07003184 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08003185 dpp_configurator_own_config(auth, curve, 1) == 0) {
Hai Shalomc3565922019-10-28 11:58:20 -07003186 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003187 ret = 0;
3188 }
3189
3190 dpp_auth_deinit(auth);
3191 os_free(curve);
3192
3193 return ret;
3194}
3195
3196
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003197int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
3198{
3199 struct dpp_bootstrap_info *own_bi;
3200 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07003201#ifdef CONFIG_DPP3
3202 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
3203#else /* CONFIG_DPP3 */
3204 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
3205#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003206 int tcp_port = DPP_TCP_PORT;
3207 struct hostapd_ip_addr *ipaddr = NULL;
3208#ifdef CONFIG_DPP2
3209 struct hostapd_ip_addr ipaddr_buf;
3210 char *addr;
3211
3212 pos = os_strstr(cmd, " tcp_port=");
3213 if (pos) {
3214 pos += 10;
3215 tcp_port = atoi(pos);
3216 }
3217
3218 addr = get_param(cmd, " tcp_addr=");
3219 if (addr) {
3220 int res;
3221
3222 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
3223 os_free(addr);
3224 if (res)
3225 return -1;
3226 ipaddr = &ipaddr_buf;
3227 }
3228#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003229
3230 pos = os_strstr(cmd, " own=");
3231 if (!pos)
3232 return -1;
3233 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07003234 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003235 if (!own_bi) {
3236 wpa_printf(MSG_DEBUG,
3237 "DPP: Identified bootstrap info not found");
3238 return -1;
3239 }
3240 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
3241 wpa_printf(MSG_DEBUG,
3242 "DPP: Identified bootstrap info not for PKEX");
3243 return -1;
3244 }
3245 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003246 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003247
3248 os_free(hapd->dpp_pkex_identifier);
3249 hapd->dpp_pkex_identifier = NULL;
3250 pos = os_strstr(cmd, " identifier=");
3251 if (pos) {
3252 pos += 12;
3253 end = os_strchr(pos, ' ');
3254 if (!end)
3255 return -1;
3256 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
3257 if (!hapd->dpp_pkex_identifier)
3258 return -1;
3259 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
3260 hapd->dpp_pkex_identifier[end - pos] = '\0';
3261 }
3262
3263 pos = os_strstr(cmd, " code=");
3264 if (!pos)
3265 return -1;
3266 os_free(hapd->dpp_pkex_code);
3267 hapd->dpp_pkex_code = os_strdup(pos + 6);
3268 if (!hapd->dpp_pkex_code)
3269 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07003270 hapd->dpp_pkex_code_len = os_strlen(hapd->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003271
Sunil Ravia04bd252022-05-02 22:54:18 -07003272 pos = os_strstr(cmd, " ver=");
3273 if (pos) {
3274 int v;
3275
3276 pos += 5;
3277 v = atoi(pos);
3278 if (v == 1)
3279 ver = PKEX_VER_ONLY_1;
3280 else if (v == 2)
3281 ver = PKEX_VER_ONLY_2;
3282 else
3283 return -1;
3284 }
3285 hapd->dpp_pkex_ver = ver;
3286
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003287 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003288 if (hostapd_dpp_pkex_init(hapd, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003289 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003290 } else {
3291#ifdef CONFIG_DPP2
3292 dpp_controller_pkex_add(hapd->iface->interfaces->dpp, own_bi,
3293 hapd->dpp_pkex_code,
3294 hapd->dpp_pkex_identifier);
3295#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003296 }
3297
3298 /* TODO: Support multiple PKEX info entries */
3299
3300 os_free(hapd->dpp_pkex_auth_cmd);
3301 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
3302
3303 return 1;
3304}
3305
3306
3307int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
3308{
3309 unsigned int id_val;
3310
3311 if (os_strcmp(id, "*") == 0) {
3312 id_val = 0;
3313 } else {
3314 id_val = atoi(id);
3315 if (id_val == 0)
3316 return -1;
3317 }
3318
Sunil Ravi89eba102022-09-13 21:04:37 -07003319 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003320 return -1;
3321
3322 /* TODO: Support multiple PKEX entries */
3323 os_free(hapd->dpp_pkex_code);
3324 hapd->dpp_pkex_code = NULL;
3325 os_free(hapd->dpp_pkex_identifier);
3326 hapd->dpp_pkex_identifier = NULL;
3327 os_free(hapd->dpp_pkex_auth_cmd);
3328 hapd->dpp_pkex_auth_cmd = NULL;
3329 hapd->dpp_pkex_bi = NULL;
3330 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
3331 dpp_pkex_free(hapd->dpp_pkex);
3332 hapd->dpp_pkex = NULL;
3333 return 0;
3334}
3335
3336
Roshan Pius3a1667e2018-07-03 15:17:14 -07003337void hostapd_dpp_stop(struct hostapd_data *hapd)
3338{
3339 dpp_auth_deinit(hapd->dpp_auth);
3340 hapd->dpp_auth = NULL;
3341 dpp_pkex_free(hapd->dpp_pkex);
3342 hapd->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003343#ifdef CONFIG_DPP3
3344 hostapd_dpp_push_button_stop(hapd);
3345#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003346}
3347
3348
Hai Shalom81f62d82019-07-22 12:10:00 -07003349#ifdef CONFIG_DPP2
3350
3351static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq,
3352 const u8 *msg, size_t len)
3353{
3354 struct hostapd_data *hapd = ctx;
3355 u8 *buf;
3356
Sunil Ravi89eba102022-09-13 21:04:37 -07003357 if (freq == 0)
3358 freq = hapd->iface->freq;
3359
Hai Shalom81f62d82019-07-22 12:10:00 -07003360 wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u",
3361 MAC2STR(addr), freq);
3362 buf = os_malloc(2 + len);
3363 if (!buf)
3364 return;
3365 buf[0] = WLAN_ACTION_PUBLIC;
3366 buf[1] = WLAN_PA_VENDOR_SPECIFIC;
3367 os_memcpy(buf + 2, msg, len);
3368 hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len);
3369 os_free(buf);
3370}
3371
3372
3373static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr,
3374 u8 dialog_token, int prot,
3375 struct wpabuf *buf)
3376{
3377 struct hostapd_data *hapd = ctx;
3378
3379 gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf);
3380}
3381
3382#endif /* CONFIG_DPP2 */
3383
3384
3385static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
3386{
3387#ifdef CONFIG_DPP2
3388 struct dpp_controller_conf *ctrl;
3389 struct dpp_relay_config config;
3390
3391 os_memset(&config, 0, sizeof(config));
Sunil Ravi89eba102022-09-13 21:04:37 -07003392 config.msg_ctx = hapd->msg_ctx;
Hai Shalom81f62d82019-07-22 12:10:00 -07003393 config.cb_ctx = hapd;
3394 config.tx = hostapd_dpp_relay_tx;
3395 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
3396 for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) {
3397 config.ipaddr = &ctrl->ipaddr;
3398 config.pkhash = ctrl->pkhash;
3399 if (dpp_relay_add_controller(hapd->iface->interfaces->dpp,
3400 &config) < 0)
3401 return -1;
3402 }
Sunil Ravi89eba102022-09-13 21:04:37 -07003403
3404 if (hapd->conf->dpp_relay_port)
3405 dpp_relay_listen(hapd->iface->interfaces->dpp,
3406 hapd->conf->dpp_relay_port,
3407 &config);
Hai Shalom81f62d82019-07-22 12:10:00 -07003408#endif /* CONFIG_DPP2 */
3409
3410 return 0;
3411}
3412
3413
Sunil Ravi89eba102022-09-13 21:04:37 -07003414#ifdef CONFIG_DPP2
3415
3416int hostapd_dpp_add_controller(struct hostapd_data *hapd, const char *cmd)
3417{
3418 struct dpp_relay_config config;
3419 struct hostapd_ip_addr addr;
3420 u8 pkhash[SHA256_MAC_LEN];
3421 char *pos, *tmp;
3422 int ret = -1;
3423 bool prev_state, new_state;
3424 struct dpp_global *dpp = hapd->iface->interfaces->dpp;
3425
3426 tmp = os_strdup(cmd);
3427 if (!tmp)
3428 goto fail;
3429 pos = os_strchr(tmp, ' ');
3430 if (!pos)
3431 goto fail;
3432 *pos++ = '\0';
3433 if (hostapd_parse_ip_addr(tmp, &addr) < 0 ||
3434 hexstr2bin(pos, pkhash, SHA256_MAC_LEN) < 0)
3435 goto fail;
3436
3437 os_memset(&config, 0, sizeof(config));
3438 config.msg_ctx = hapd->msg_ctx;
3439 config.cb_ctx = hapd;
3440 config.tx = hostapd_dpp_relay_tx;
3441 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
3442 config.ipaddr = &addr;
3443 config.pkhash = pkhash;
3444 prev_state = dpp_relay_controller_available(dpp);
3445 ret = dpp_relay_add_controller(dpp, &config);
3446 new_state = dpp_relay_controller_available(dpp);
3447 if (new_state != prev_state)
3448 ieee802_11_update_beacons(hapd->iface);
3449fail:
3450 os_free(tmp);
3451 return ret;
3452}
3453
3454
3455void hostapd_dpp_remove_controller(struct hostapd_data *hapd, const char *cmd)
3456{
3457 struct hostapd_ip_addr addr;
3458 bool prev_state, new_state;
3459 struct dpp_global *dpp = hapd->iface->interfaces->dpp;
3460
3461 if (hostapd_parse_ip_addr(cmd, &addr) < 0)
3462 return;
3463 prev_state = dpp_relay_controller_available(dpp);
3464 dpp_relay_remove_controller(dpp, &addr);
3465 new_state = dpp_relay_controller_available(dpp);
3466 if (new_state != prev_state)
3467 ieee802_11_update_beacons(hapd->iface);
3468}
3469
3470#endif /* CONFIG_DPP2 */
3471
3472
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003473int hostapd_dpp_init(struct hostapd_data *hapd)
3474{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003475 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
3476 hapd->dpp_init_done = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07003477 return hostapd_dpp_add_controllers(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003478}
3479
3480
3481void hostapd_dpp_deinit(struct hostapd_data *hapd)
3482{
3483#ifdef CONFIG_TESTING_OPTIONS
3484 os_free(hapd->dpp_config_obj_override);
3485 hapd->dpp_config_obj_override = NULL;
3486 os_free(hapd->dpp_discovery_override);
3487 hapd->dpp_discovery_override = NULL;
3488 os_free(hapd->dpp_groups_override);
3489 hapd->dpp_groups_override = NULL;
3490 hapd->dpp_ignore_netaccesskey_mismatch = 0;
3491#endif /* CONFIG_TESTING_OPTIONS */
3492 if (!hapd->dpp_init_done)
3493 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003494 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003495 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003496 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003497 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
3498 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003499#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003500 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
3501 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003502 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
3503 NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07003504 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
3505 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003506 hostapd_dpp_chirp_stop(hapd);
Sunil Ravi89eba102022-09-13 21:04:37 -07003507 if (hapd->iface->interfaces) {
3508 dpp_relay_stop_listen(hapd->iface->interfaces->dpp);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003509 dpp_controller_stop_for_ctx(hapd->iface->interfaces->dpp, hapd);
Sunil Ravi89eba102022-09-13 21:04:37 -07003510 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003511#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003512#ifdef CONFIG_DPP3
3513 eloop_cancel_timeout(hostapd_dpp_build_new_key, hapd, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07003514 hostapd_dpp_push_button_stop(hapd);
Sunil Ravia04bd252022-05-02 22:54:18 -07003515#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003516 dpp_auth_deinit(hapd->dpp_auth);
3517 hapd->dpp_auth = NULL;
3518 hostapd_dpp_pkex_remove(hapd, "*");
3519 hapd->dpp_pkex = NULL;
3520 os_free(hapd->dpp_configurator_params);
3521 hapd->dpp_configurator_params = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003522 os_free(hapd->dpp_pkex_auth_cmd);
3523 hapd->dpp_pkex_auth_cmd = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003524}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003525
3526
3527#ifdef CONFIG_DPP2
3528
Hai Shalom899fcc72020-10-19 14:38:18 -07003529int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd)
3530{
3531 struct dpp_controller_config config;
3532 const char *pos;
3533
3534 os_memset(&config, 0, sizeof(config));
3535 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
3536 config.netrole = DPP_NETROLE_AP;
3537 config.msg_ctx = hapd->msg_ctx;
3538 config.cb_ctx = hapd;
3539 config.process_conf_obj = hostapd_dpp_process_conf_obj;
3540 if (cmd) {
3541 pos = os_strstr(cmd, " tcp_port=");
3542 if (pos) {
3543 pos += 10;
3544 config.tcp_port = atoi(pos);
3545 }
3546
3547 pos = os_strstr(cmd, " role=");
3548 if (pos) {
3549 pos += 6;
3550 if (os_strncmp(pos, "configurator", 12) == 0)
3551 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
3552 else if (os_strncmp(pos, "enrollee", 8) == 0)
3553 config.allowed_roles = DPP_CAPAB_ENROLLEE;
3554 else if (os_strncmp(pos, "either", 6) == 0)
3555 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
3556 DPP_CAPAB_ENROLLEE;
3557 else
3558 return -1;
3559 }
3560
3561 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
3562 }
3563 config.configurator_params = hapd->dpp_configurator_params;
3564 return dpp_controller_start(hapd->iface->interfaces->dpp, &config);
3565}
3566
3567
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003568static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
3569
3570static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
3571{
3572 struct hostapd_data *hapd = eloop_ctx;
3573
3574 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
3575 hostapd_drv_send_action_cancel_wait(hapd);
3576 hostapd_dpp_chirp_next(hapd, NULL);
3577}
3578
3579
3580static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
3581{
3582 struct wpabuf *msg;
3583 int type;
3584
3585 msg = hapd->dpp_presence_announcement;
3586 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
3587 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
3588 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3589 " freq=%u type=%d",
3590 MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
3591 if (hostapd_drv_send_action(
3592 hapd, hapd->dpp_chirp_freq, 2000, broadcast,
3593 wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
3594 eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
3595 hapd, NULL) < 0)
3596 hostapd_dpp_chirp_stop(hapd);
3597}
3598
3599
3600static struct hostapd_hw_modes *
3601dpp_get_mode(struct hostapd_data *hapd,
3602 enum hostapd_hw_mode mode)
3603{
3604 struct hostapd_hw_modes *modes = hapd->iface->hw_features;
3605 u16 num_modes = hapd->iface->num_hw_features;
3606 u16 i;
3607
3608 for (i = 0; i < num_modes; i++) {
3609 if (modes[i].mode != mode ||
3610 !modes[i].num_channels || !modes[i].channels)
3611 continue;
3612 return &modes[i];
3613 }
3614
3615 return NULL;
3616}
3617
3618
3619static void
3620hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
3621{
3622 struct hostapd_data *hapd = iface->bss[0];
3623 struct wpa_scan_results *scan_res;
3624 struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
3625 unsigned int i;
3626 struct hostapd_hw_modes *mode;
3627 int c;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003628 bool chan6 = hapd->iface->hw_features == NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003629
3630 if (!bi)
3631 return;
3632
3633 hapd->dpp_chirp_scan_done = 1;
3634
3635 scan_res = hostapd_driver_get_scan_results(hapd);
3636
3637 os_free(hapd->dpp_chirp_freqs);
3638 hapd->dpp_chirp_freqs = NULL;
3639
3640 /* Channels from own bootstrapping info */
3641 if (bi) {
3642 for (i = 0; i < bi->num_freq; i++)
3643 int_array_add_unique(&hapd->dpp_chirp_freqs,
3644 bi->freq[i]);
3645 }
3646
3647 /* Preferred chirping channels */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003648 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211G);
3649 if (mode) {
3650 for (c = 0; c < mode->num_channels; c++) {
3651 struct hostapd_channel_data *chan = &mode->channels[c];
3652
3653 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3654 HOSTAPD_CHAN_RADAR) ||
3655 chan->freq != 2437)
3656 continue;
3657 chan6 = true;
3658 break;
3659 }
3660 }
3661 if (chan6)
3662 int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003663
3664 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
3665 if (mode) {
3666 int chan44 = 0, chan149 = 0;
3667
3668 for (c = 0; c < mode->num_channels; c++) {
3669 struct hostapd_channel_data *chan = &mode->channels[c];
3670
3671 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3672 HOSTAPD_CHAN_RADAR))
3673 continue;
3674 if (chan->freq == 5220)
3675 chan44 = 1;
3676 if (chan->freq == 5745)
3677 chan149 = 1;
3678 }
3679 if (chan149)
3680 int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
3681 else if (chan44)
3682 int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
3683 }
3684
3685 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
3686 if (mode) {
3687 for (c = 0; c < mode->num_channels; c++) {
3688 struct hostapd_channel_data *chan = &mode->channels[c];
3689
3690 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
3691 HOSTAPD_CHAN_RADAR)) ||
3692 chan->freq != 60480)
3693 continue;
3694 int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
3695 break;
3696 }
3697 }
3698
3699 /* Add channels from scan results for APs that advertise Configurator
3700 * Connectivity element */
3701 for (i = 0; scan_res && i < scan_res->num; i++) {
3702 struct wpa_scan_res *bss = scan_res->res[i];
3703 size_t ie_len = bss->ie_len;
3704
3705 if (!ie_len)
3706 ie_len = bss->beacon_ie_len;
3707 if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
3708 DPP_CC_IE_VENDOR_TYPE))
3709 int_array_add_unique(&hapd->dpp_chirp_freqs,
3710 bss->freq);
3711 }
3712
3713 if (!hapd->dpp_chirp_freqs ||
3714 eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
3715 hapd, NULL) < 0)
3716 hostapd_dpp_chirp_stop(hapd);
3717
3718 wpa_scan_results_free(scan_res);
3719}
3720
3721
3722static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
3723{
3724 struct hostapd_data *hapd = eloop_ctx;
3725 int i;
3726
3727 if (hapd->dpp_chirp_listen)
3728 hostapd_dpp_listen_stop(hapd);
3729
3730 if (hapd->dpp_chirp_freq == 0) {
3731 if (hapd->dpp_chirp_round % 4 == 0 &&
3732 !hapd->dpp_chirp_scan_done) {
3733 struct wpa_driver_scan_params params;
3734 int ret;
3735
3736 wpa_printf(MSG_DEBUG,
3737 "DPP: Update channel list for chirping");
3738 os_memset(&params, 0, sizeof(params));
3739 ret = hostapd_driver_scan(hapd, &params);
3740 if (ret < 0) {
3741 wpa_printf(MSG_DEBUG,
3742 "DPP: Failed to request a scan ret=%d (%s)",
3743 ret, strerror(-ret));
3744 hostapd_dpp_chirp_scan_res_handler(hapd->iface);
3745 } else {
3746 hapd->iface->scan_cb =
3747 hostapd_dpp_chirp_scan_res_handler;
3748 }
3749 return;
3750 }
3751 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
3752 hapd->dpp_chirp_round++;
3753 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
3754 hapd->dpp_chirp_round);
3755 } else {
3756 for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
3757 if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
3758 break;
3759 if (!hapd->dpp_chirp_freqs[i]) {
3760 wpa_printf(MSG_DEBUG,
3761 "DPP: Previous chirp freq %d not found",
3762 hapd->dpp_chirp_freq);
3763 return;
3764 }
3765 i++;
3766 if (hapd->dpp_chirp_freqs[i]) {
3767 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
3768 } else {
3769 hapd->dpp_chirp_iter--;
3770 if (hapd->dpp_chirp_iter <= 0) {
3771 wpa_printf(MSG_DEBUG,
3772 "DPP: Chirping iterations completed");
3773 hostapd_dpp_chirp_stop(hapd);
3774 return;
3775 }
3776 hapd->dpp_chirp_freq = 0;
3777 hapd->dpp_chirp_scan_done = 0;
3778 if (eloop_register_timeout(30, 0,
3779 hostapd_dpp_chirp_next,
3780 hapd, NULL) < 0) {
3781 hostapd_dpp_chirp_stop(hapd);
3782 return;
3783 }
3784 if (hapd->dpp_chirp_listen) {
3785 wpa_printf(MSG_DEBUG,
3786 "DPP: Listen on %d MHz during chirp 30 second wait",
3787 hapd->dpp_chirp_listen);
3788 /* TODO: start listen on the channel */
3789 } else {
3790 wpa_printf(MSG_DEBUG,
3791 "DPP: Wait 30 seconds before starting the next chirping round");
3792 }
3793 return;
3794 }
3795 }
3796
3797 hostapd_dpp_chirp_start(hapd);
3798}
3799
3800
3801int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
3802{
3803 const char *pos;
3804 int iter = 1, listen_freq = 0;
3805 struct dpp_bootstrap_info *bi;
3806
3807 pos = os_strstr(cmd, " own=");
3808 if (!pos)
3809 return -1;
3810 pos += 5;
3811 bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
3812 if (!bi) {
3813 wpa_printf(MSG_DEBUG,
3814 "DPP: Identified bootstrap info not found");
3815 return -1;
3816 }
3817
3818 pos = os_strstr(cmd, " iter=");
3819 if (pos) {
3820 iter = atoi(pos + 6);
3821 if (iter <= 0)
3822 return -1;
3823 }
3824
3825 pos = os_strstr(cmd, " listen=");
3826 if (pos) {
3827 listen_freq = atoi(pos + 8);
3828 if (listen_freq <= 0)
3829 return -1;
3830 }
3831
3832 hostapd_dpp_chirp_stop(hapd);
3833 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
3834 hapd->dpp_qr_mutual = 0;
3835 hapd->dpp_chirp_bi = bi;
3836 hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
3837 if (!hapd->dpp_presence_announcement)
3838 return -1;
3839 hapd->dpp_chirp_iter = iter;
3840 hapd->dpp_chirp_round = 0;
3841 hapd->dpp_chirp_scan_done = 0;
3842 hapd->dpp_chirp_listen = listen_freq;
3843
3844 return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
3845}
3846
3847
3848void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
3849{
3850 if (hapd->dpp_presence_announcement) {
3851 hostapd_drv_send_action_cancel_wait(hapd);
3852 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
3853 }
3854 hapd->dpp_chirp_bi = NULL;
3855 wpabuf_free(hapd->dpp_presence_announcement);
3856 hapd->dpp_presence_announcement = NULL;
3857 if (hapd->dpp_chirp_listen)
3858 hostapd_dpp_listen_stop(hapd);
3859 hapd->dpp_chirp_listen = 0;
3860 hapd->dpp_chirp_freq = 0;
3861 os_free(hapd->dpp_chirp_freqs);
3862 hapd->dpp_chirp_freqs = NULL;
3863 eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
3864 eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
3865 if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
3866 /* TODO: abort ongoing scan */
3867 hapd->iface->scan_cb = NULL;
3868 }
3869}
3870
3871
3872static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
3873{
3874 struct dpp_bootstrap_info *bi = ctx;
3875 size_t i;
3876
3877 for (i = 0; i < iface->num_bss; i++) {
3878 struct hostapd_data *hapd = iface->bss[i];
3879
3880 if (bi == hapd->dpp_chirp_bi)
3881 hostapd_dpp_chirp_stop(hapd);
3882 }
3883
3884 return 0;
3885}
3886
3887
3888void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
3889{
3890 struct hapd_interfaces *interfaces = ctx;
3891
3892 hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
3893}
3894
3895#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07003896
3897
3898#ifdef CONFIG_DPP3
3899
3900static void hostapd_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
3901{
3902 struct hostapd_data *hapd = eloop_ctx;
3903
3904 wpa_printf(MSG_DEBUG, "DPP: Active push button mode expired");
3905 hostapd_dpp_push_button_stop(hapd);
3906}
3907
3908
3909int hostapd_dpp_push_button(struct hostapd_data *hapd, const char *cmd)
3910{
3911 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3912
3913 if (!ifaces || !ifaces->dpp)
3914 return -1;
3915 os_get_reltime(&ifaces->dpp_pb_time);
3916 ifaces->dpp_pb_announce_time.sec = 0;
3917 ifaces->dpp_pb_announce_time.usec = 0;
3918 str_clear_free(ifaces->dpp_pb_cmd);
3919 ifaces->dpp_pb_cmd = NULL;
3920 if (cmd) {
3921 ifaces->dpp_pb_cmd = os_strdup(cmd);
3922 if (!ifaces->dpp_pb_cmd)
3923 return -1;
3924 }
3925 eloop_register_timeout(100, 0, hostapd_dpp_push_button_expire,
3926 hapd, NULL);
3927
3928 return 0;
3929}
3930
3931
3932void hostapd_dpp_push_button_stop(struct hostapd_data *hapd)
3933{
3934 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3935
3936 if (!ifaces || !ifaces->dpp)
3937 return;
3938 eloop_cancel_timeout(hostapd_dpp_push_button_expire, hapd, NULL);
3939 if (hostapd_dpp_pb_active(hapd)) {
3940 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
3941 if (!ifaces->dpp_pb_result_indicated)
3942 wpa_msg(hapd->msg_ctx, MSG_INFO,
3943 DPP_EVENT_PB_RESULT "failed");
3944 }
3945 ifaces->dpp_pb_time.sec = 0;
3946 ifaces->dpp_pb_time.usec = 0;
3947 dpp_pkex_free(hapd->dpp_pkex);
3948 hapd->dpp_pkex = NULL;
3949 os_free(hapd->dpp_pkex_auth_cmd);
3950 hapd->dpp_pkex_auth_cmd = NULL;
3951
3952 if (ifaces->dpp_pb_bi) {
3953 char id[20];
3954
3955 os_snprintf(id, sizeof(id), "%u", ifaces->dpp_pb_bi->id);
3956 dpp_bootstrap_remove(ifaces->dpp, id);
3957 ifaces->dpp_pb_bi = NULL;
3958 }
3959
3960 ifaces->dpp_pb_result_indicated = false;
3961
3962 str_clear_free(ifaces->dpp_pb_cmd);
3963 ifaces->dpp_pb_cmd = NULL;
3964}
3965
3966#endif /* CONFIG_DPP3 */
3967
3968
3969#ifdef CONFIG_DPP2
3970bool hostapd_dpp_configurator_connectivity(struct hostapd_data *hapd)
3971{
3972 return hapd->conf->dpp_configurator_connectivity ||
3973 (hapd->iface->interfaces &&
3974 dpp_relay_controller_available(hapd->iface->interfaces->dpp));
3975}
3976#endif /* CONFIG_DPP2 */