blob: 7a8ea4e6010c858065f7fc4af3e2a354eea36d6f [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
Sunil Ravieb83e2a2024-06-28 17:34:56 +0000542 if (hapd->dpp_auth_ok_on_ack)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700543 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");
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001381 dpp_notify_auth_success(hapd->dpp_auth, initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001382#ifdef CONFIG_TESTING_OPTIONS
1383 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1384 wpa_printf(MSG_INFO,
1385 "DPP: TESTING - stop at Authentication Confirm");
1386 if (hapd->dpp_auth->configurator) {
1387 /* Prevent GAS response */
1388 hapd->dpp_auth->auth_success = 0;
1389 }
1390 return;
1391 }
1392#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001393
1394 if (!hapd->dpp_auth->configurator)
1395 hostapd_dpp_start_gas_client(hapd);
1396}
1397
1398
1399static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001400 const u8 *hdr, const u8 *buf, size_t len,
1401 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001402{
1403 struct dpp_authentication *auth = hapd->dpp_auth;
1404 struct wpabuf *msg;
1405
1406 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
1407 MAC2STR(src));
1408
1409 if (!auth) {
1410 wpa_printf(MSG_DEBUG,
1411 "DPP: No DPP Authentication in progress - drop");
1412 return;
1413 }
1414
1415 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
Sunil Ravieb83e2a2024-06-28 17:34:56 +00001416 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001417 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1418 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1419 return;
1420 }
1421
Roshan Pius3a1667e2018-07-03 15:17:14 -07001422 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1423
1424 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1425 wpa_printf(MSG_DEBUG,
1426 "DPP: Responder accepted request for different negotiation channel");
1427 auth->curr_freq = freq;
1428 }
1429
1430 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001431 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1432 if (!msg) {
1433 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1434 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
1435 return;
1436 }
1437 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1438 return;
1439 }
1440 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1441
Roshan Pius3a1667e2018-07-03 15:17:14 -07001442 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1443 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
1444 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001445 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
1446 wpabuf_head(msg), wpabuf_len(msg));
1447 wpabuf_free(msg);
1448 hapd->dpp_auth_ok_on_ack = 1;
1449}
1450
1451
1452static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1453 const u8 *hdr, const u8 *buf, size_t len)
1454{
1455 struct dpp_authentication *auth = hapd->dpp_auth;
1456
1457 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1458 MAC2STR(src));
1459
1460 if (!auth) {
1461 wpa_printf(MSG_DEBUG,
1462 "DPP: No DPP Authentication in progress - drop");
1463 return;
1464 }
1465
Sunil Ravieb83e2a2024-06-28 17:34:56 +00001466 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001467 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1468 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1469 return;
1470 }
1471
1472 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1473 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1474 return;
1475 }
1476
1477 hostapd_dpp_auth_success(hapd, 0);
1478}
1479
1480
Hai Shalom021b0b52019-04-10 11:17:58 -07001481#ifdef CONFIG_DPP2
1482
1483static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
1484 void *timeout_ctx)
1485{
1486 struct hostapd_data *hapd = eloop_ctx;
1487 struct dpp_authentication *auth = hapd->dpp_auth;
1488
1489 if (!auth || !auth->waiting_conf_result)
1490 return;
1491
1492 wpa_printf(MSG_DEBUG,
1493 "DPP: Timeout while waiting for Configuration Result");
1494 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1495 dpp_auth_deinit(auth);
1496 hapd->dpp_auth = NULL;
1497}
1498
1499
Hai Shalomc3565922019-10-28 11:58:20 -07001500static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1501 void *timeout_ctx)
1502{
1503 struct hostapd_data *hapd = eloop_ctx;
1504 struct dpp_authentication *auth = hapd->dpp_auth;
1505
1506 if (!auth || !auth->waiting_conf_result)
1507 return;
1508
1509 wpa_printf(MSG_DEBUG,
1510 "DPP: Timeout while waiting for Connection Status Result");
1511 wpa_msg(hapd->msg_ctx, MSG_INFO,
1512 DPP_EVENT_CONN_STATUS_RESULT "timeout");
1513 dpp_auth_deinit(auth);
1514 hapd->dpp_auth = NULL;
1515}
1516
1517
Sunil Ravi89eba102022-09-13 21:04:37 -07001518#ifdef CONFIG_DPP3
1519
1520static bool hostapd_dpp_pb_active(struct hostapd_data *hapd)
1521{
1522 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1523
1524 return ifaces && (ifaces->dpp_pb_time.sec ||
1525 ifaces->dpp_pb_time.usec);
1526}
1527
1528
1529static void hostapd_dpp_remove_pb_hash(struct hostapd_data *hapd)
1530{
1531 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1532 int i;
1533
1534 if (!ifaces->dpp_pb_bi)
1535 return;
1536 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
1537 struct dpp_pb_info *info = &ifaces->dpp_pb[i];
1538
1539 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
1540 continue;
1541 if (os_memcmp(info->hash, ifaces->dpp_pb_resp_hash,
1542 SHA256_MAC_LEN) == 0) {
1543 /* Allow a new push button session to be established
1544 * immediately without the successfully completed
1545 * session triggering session overlap. */
1546 info->rx_time.sec = 0;
1547 info->rx_time.usec = 0;
1548 wpa_printf(MSG_DEBUG,
1549 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
1550 }
1551 }
1552}
1553
1554#endif /* CONFIG_DPP3 */
1555
1556
Hai Shalom021b0b52019-04-10 11:17:58 -07001557static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
1558 const u8 *hdr, const u8 *buf, size_t len)
1559{
1560 struct dpp_authentication *auth = hapd->dpp_auth;
1561 enum dpp_status_error status;
Sunil Ravi89eba102022-09-13 21:04:37 -07001562#ifdef CONFIG_DPP3
1563 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1564#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001565
1566 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1567 MAC2STR(src));
1568
1569 if (!auth || !auth->waiting_conf_result) {
1570 wpa_printf(MSG_DEBUG,
1571 "DPP: No DPP Configuration waiting for result - drop");
1572 return;
1573 }
1574
Sunil Ravieb83e2a2024-06-28 17:34:56 +00001575 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001576 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1577 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1578 return;
1579 }
1580
1581 status = dpp_conf_result_rx(auth, hdr, buf, len);
1582
Hai Shalomc3565922019-10-28 11:58:20 -07001583 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1584 wpa_msg(hapd->msg_ctx, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07001585 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
1586 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07001587 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1588 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1589 hapd, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001590 auth->waiting_conn_status_result = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001591 eloop_cancel_timeout(
1592 hostapd_dpp_conn_status_result_wait_timeout,
1593 hapd, NULL);
1594 eloop_register_timeout(
1595 16, 0, hostapd_dpp_conn_status_result_wait_timeout,
1596 hapd, NULL);
1597 return;
1598 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001599 hostapd_drv_send_action_cancel_wait(hapd);
1600 hostapd_dpp_listen_stop(hapd);
1601 if (status == DPP_STATUS_OK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001602 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
1603 "conf_status=%d", auth->conf_resp_status);
Hai Shalom021b0b52019-04-10 11:17:58 -07001604 else
1605 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1606 dpp_auth_deinit(auth);
1607 hapd->dpp_auth = NULL;
1608 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1609 NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07001610#ifdef CONFIG_DPP3
1611 if (!ifaces->dpp_pb_result_indicated && hostapd_dpp_pb_active(hapd)) {
1612 if (status == DPP_STATUS_OK)
1613 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
1614 "success");
1615 else
1616 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
1617 "no-configuration-available");
1618 ifaces->dpp_pb_result_indicated = true;
1619 if (status == DPP_STATUS_OK)
1620 hostapd_dpp_remove_pb_hash(hapd);
1621 hostapd_dpp_push_button_stop(hapd);
1622 }
1623#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001624}
1625
Hai Shalomc3565922019-10-28 11:58:20 -07001626
1627static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
1628 const u8 *src, const u8 *hdr,
1629 const u8 *buf, size_t len)
1630{
1631 struct dpp_authentication *auth = hapd->dpp_auth;
1632 enum dpp_status_error status;
1633 u8 ssid[SSID_MAX_LEN];
1634 size_t ssid_len = 0;
1635 char *channel_list = NULL;
1636
1637 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1638
1639 if (!auth || !auth->waiting_conn_status_result) {
1640 wpa_printf(MSG_DEBUG,
1641 "DPP: No DPP Configuration waiting for connection status result - drop");
1642 return;
1643 }
1644
1645 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1646 ssid, &ssid_len, &channel_list);
1647 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1648 "result=%d ssid=%s channel_list=%s",
1649 status, wpa_ssid_txt(ssid, ssid_len),
1650 channel_list ? channel_list : "N/A");
1651 os_free(channel_list);
1652 hostapd_drv_send_action_cancel_wait(hapd);
1653 hostapd_dpp_listen_stop(hapd);
1654 dpp_auth_deinit(auth);
1655 hapd->dpp_auth = NULL;
1656 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
1657 hapd, NULL);
1658}
1659
1660
Hai Shalomfdcde762020-04-02 11:19:20 -07001661static void
1662hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
1663 const u8 *hdr, const u8 *buf, size_t len,
1664 unsigned int freq)
1665{
1666 const u8 *r_bootstrap;
1667 u16 r_bootstrap_len;
1668 struct dpp_bootstrap_info *peer_bi;
1669 struct dpp_authentication *auth;
1670
1671 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
1672 MAC2STR(src));
1673
1674 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1675 &r_bootstrap_len);
1676 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1677 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1678 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1679 return;
1680 }
1681 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1682 r_bootstrap, r_bootstrap_len);
1683 peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
1684 r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07001685 dpp_notify_chirp_received(hapd->msg_ctx,
1686 peer_bi ? (int) peer_bi->id : -1,
1687 src, freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07001688 if (!peer_bi) {
1689 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1690 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001691 r_bootstrap, hapd) == 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07001692 return;
1693 wpa_printf(MSG_DEBUG,
1694 "DPP: No matching bootstrapping information found");
Sunil Ravi89eba102022-09-13 21:04:37 -07001695 hostapd_dpp_relay_needs_controller(
1696 hapd, src, DPP_PA_PRESENCE_ANNOUNCEMENT);
Hai Shalomfdcde762020-04-02 11:19:20 -07001697 return;
1698 }
1699
1700 if (hapd->dpp_auth) {
1701 wpa_printf(MSG_DEBUG,
1702 "DPP: Ignore Presence Announcement during ongoing Authentication");
1703 return;
1704 }
1705
1706 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1707 peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
1708 0);
1709 if (!auth)
1710 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07001711 hostapd_dpp_set_testing_options(hapd, auth);
1712 if (dpp_set_configurator(auth,
Hai Shalomfdcde762020-04-02 11:19:20 -07001713 hapd->dpp_configurator_params) < 0) {
1714 dpp_auth_deinit(auth);
1715 return;
1716 }
1717
1718 auth->neg_freq = freq;
1719
Hai Shalom60840252021-02-19 19:02:11 -08001720 /* The source address of the Presence Announcement frame overrides any
1721 * MAC address information from the bootstrapping information. */
1722 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07001723
1724 hapd->dpp_auth = auth;
1725 if (hostapd_dpp_auth_init_next(hapd) < 0) {
1726 dpp_auth_deinit(hapd->dpp_auth);
1727 hapd->dpp_auth = NULL;
1728 }
1729}
1730
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001731
1732static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
1733 void *timeout_ctx)
1734{
1735 struct hostapd_data *hapd = eloop_ctx;
1736 struct dpp_authentication *auth = hapd->dpp_auth;
1737
1738 if (!auth)
1739 return;
1740
1741 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
1742 hostapd_dpp_listen_stop(hapd);
1743 dpp_auth_deinit(auth);
1744 hapd->dpp_auth = NULL;
1745}
1746
1747
1748static void
1749hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
1750 const u8 *hdr, const u8 *buf, size_t len,
1751 unsigned int freq)
1752{
Hai Shalom899fcc72020-10-19 14:38:18 -07001753 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
1754 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001755 struct dpp_configurator *conf;
1756 struct dpp_authentication *auth;
1757 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07001758 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001759
1760 if (hapd->dpp_auth) {
1761 wpa_printf(MSG_DEBUG,
1762 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1763 return;
1764 }
1765
1766 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
1767 MAC2STR(src));
1768
1769 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1770 &csign_hash_len);
1771 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
1772 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1773 "Missing or invalid required Configurator C-sign key Hash attribute");
1774 return;
1775 }
1776 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1777 csign_hash, csign_hash_len);
1778 conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
1779 csign_hash);
1780 if (!conf) {
1781 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1782 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001783 NULL, hapd) == 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001784 return;
1785 wpa_printf(MSG_DEBUG,
1786 "DPP: No matching Configurator information found");
Sunil Ravi89eba102022-09-13 21:04:37 -07001787 hostapd_dpp_relay_needs_controller(
1788 hapd, src, DPP_PA_RECONFIG_ANNOUNCEMENT);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001789 return;
1790 }
1791
Hai Shalom899fcc72020-10-19 14:38:18 -07001792 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
1793 &fcgroup_len);
1794 if (!fcgroup || fcgroup_len != 2) {
1795 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1796 "Missing or invalid required Finite Cyclic Group attribute");
1797 return;
1798 }
1799 group = WPA_GET_LE16(fcgroup);
1800 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
1801
1802 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
1803 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
1804
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001805 auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
Hai Shalom899fcc72020-10-19 14:38:18 -07001806 conf, freq, group, a_nonce, a_nonce_len,
1807 e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001808 if (!auth)
1809 return;
1810 hostapd_dpp_set_testing_options(hapd, auth);
1811 if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
1812 dpp_auth_deinit(auth);
1813 return;
1814 }
1815
1816 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1817 hapd->dpp_auth = auth;
1818
1819 hapd->dpp_in_response_listen = 0;
1820 hapd->dpp_auth_ok_on_ack = 0;
1821 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
1822 max_wait_time = hapd->dpp_resp_wait_time ?
1823 hapd->dpp_resp_wait_time : 2000;
1824 if (wait_time > max_wait_time)
1825 wait_time = max_wait_time;
1826 wait_time += 10; /* give the driver some extra time to complete */
1827 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
1828 hostapd_dpp_reconfig_reply_wait_timeout,
1829 hapd, NULL);
1830 wait_time -= 10;
1831
1832 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1833 " freq=%u type=%d",
1834 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
1835 if (hostapd_drv_send_action(hapd, freq, wait_time, src,
1836 wpabuf_head(auth->reconfig_req_msg),
1837 wpabuf_len(auth->reconfig_req_msg)) < 0) {
1838 dpp_auth_deinit(hapd->dpp_auth);
1839 hapd->dpp_auth = NULL;
1840 }
1841}
1842
1843
1844static void
1845hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
1846 const u8 *hdr, const u8 *buf, size_t len,
1847 unsigned int freq)
1848{
1849 struct dpp_authentication *auth = hapd->dpp_auth;
1850 struct wpabuf *conf;
1851
1852 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
1853 MACSTR, MAC2STR(src));
1854
1855 if (!auth || !auth->reconfig || !auth->configurator) {
1856 wpa_printf(MSG_DEBUG,
1857 "DPP: No DPP Reconfig Authentication in progress - drop");
1858 return;
1859 }
1860
Sunil Ravieb83e2a2024-06-28 17:34:56 +00001861 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001862 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1863 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1864 return;
1865 }
1866
1867 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
1868 if (!conf)
1869 return;
1870
1871 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1872 hapd, NULL);
1873
1874 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1875 " freq=%u type=%d",
1876 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
1877 if (hostapd_drv_send_action(hapd, freq, 500, src,
1878 wpabuf_head(conf), wpabuf_len(conf)) < 0) {
1879 wpabuf_free(conf);
1880 dpp_auth_deinit(hapd->dpp_auth);
1881 hapd->dpp_auth = NULL;
1882 return;
1883 }
1884 wpabuf_free(conf);
1885}
1886
Hai Shalom021b0b52019-04-10 11:17:58 -07001887#endif /* CONFIG_DPP2 */
1888
1889
Roshan Pius3a1667e2018-07-03 15:17:14 -07001890static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1891 const u8 *src, unsigned int freq,
1892 u8 trans_id,
1893 enum dpp_status_error status)
1894{
1895 struct wpabuf *msg;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001896 size_t len;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001897
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001898 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
1899#ifdef CONFIG_DPP2
1900 len += 5;
1901#endif /* CONFIG_DPP2 */
1902 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001903 if (!msg)
1904 return;
1905
1906#ifdef CONFIG_TESTING_OPTIONS
1907 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1908 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1909 goto skip_trans_id;
1910 }
1911 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1912 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1913 trans_id ^= 0x01;
1914 }
1915#endif /* CONFIG_TESTING_OPTIONS */
1916
1917 /* Transaction ID */
1918 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1919 wpabuf_put_le16(msg, 1);
1920 wpabuf_put_u8(msg, trans_id);
1921
1922#ifdef CONFIG_TESTING_OPTIONS
1923skip_trans_id:
1924 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1925 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1926 goto skip_status;
1927 }
1928 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1929 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1930 status = 254;
1931 }
1932#endif /* CONFIG_TESTING_OPTIONS */
1933
1934 /* DPP Status */
1935 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1936 wpabuf_put_le16(msg, 1);
1937 wpabuf_put_u8(msg, status);
1938
1939#ifdef CONFIG_TESTING_OPTIONS
1940skip_status:
1941 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1942 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1943 goto skip_connector;
1944 }
1945 if (status == DPP_STATUS_OK &&
1946 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1947 char *connector;
1948
1949 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1950 connector = dpp_corrupt_connector_signature(
1951 hapd->conf->dpp_connector);
1952 if (!connector) {
1953 wpabuf_free(msg);
1954 return;
1955 }
1956 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1957 wpabuf_put_le16(msg, os_strlen(connector));
1958 wpabuf_put_str(msg, connector);
1959 os_free(connector);
1960 goto skip_connector;
1961 }
1962#endif /* CONFIG_TESTING_OPTIONS */
1963
1964 /* DPP Connector */
1965 if (status == DPP_STATUS_OK) {
1966 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1967 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1968 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1969 }
1970
1971#ifdef CONFIG_TESTING_OPTIONS
1972skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001973 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP) {
1974 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
1975 goto skip_proto_ver;
1976 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001977#endif /* CONFIG_TESTING_OPTIONS */
1978
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001979#ifdef CONFIG_DPP2
1980 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001981 u8 ver = DPP_VERSION;
1982#ifdef CONFIG_DPP3
1983 int conn_ver;
1984
1985 conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
1986 if (conn_ver > 0 && ver != conn_ver) {
1987 wpa_printf(MSG_DEBUG,
1988 "DPP: Use Connector version %d instead of current protocol version %d",
1989 conn_ver, ver);
1990 ver = conn_ver;
1991 }
1992#endif /* CONFIG_DPP3 */
1993
1994#ifdef CONFIG_TESTING_OPTIONS
1995 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP) {
1996 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
1997 ver = 1;
1998 }
1999#endif /* CONFIG_TESTING_OPTIONS */
2000
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002001 /* Protocol Version */
2002 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
2003 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002004 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002005 }
2006#endif /* CONFIG_DPP2 */
2007
Hai Shaloma20dcd72022-02-04 13:43:00 -08002008#ifdef CONFIG_TESTING_OPTIONS
2009skip_proto_ver:
2010#endif /* CONFIG_TESTING_OPTIONS */
2011
Roshan Pius3a1667e2018-07-03 15:17:14 -07002012 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
2013 " status=%d", MAC2STR(src), status);
2014 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2015 " freq=%u type=%d status=%d", MAC2STR(src), freq,
2016 DPP_PA_PEER_DISCOVERY_RESP, status);
2017 hostapd_drv_send_action(hapd, freq, 0, src,
2018 wpabuf_head(msg), wpabuf_len(msg));
2019 wpabuf_free(msg);
2020}
2021
2022
Sunil Ravi89eba102022-09-13 21:04:37 -07002023static bool hapd_dpp_connector_available(struct hostapd_data *hapd)
2024{
2025 if (!hapd->wpa_auth ||
2026 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
2027 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
2028 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
2029 return false;
2030 }
2031
2032 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
2033 !hapd->conf->dpp_csign) {
2034 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
2035 return false;
2036 }
2037
2038 return true;
2039}
2040
2041
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002042static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
2043 const u8 *src,
2044 const u8 *buf, size_t len,
2045 unsigned int freq)
2046{
2047 const u8 *connector, *trans_id;
2048 u16 connector_len, trans_id_len;
2049 struct os_time now;
2050 struct dpp_introduction intro;
2051 os_time_t expire;
2052 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002053 enum dpp_status_error res;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002054 u8 pkhash[SHA256_MAC_LEN];
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),
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002091 connector, connector_len, &expire, pkhash);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002092 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
Sunil Ravieb83e2a2024-06-28 17:34:56 +00002136 if (wpa_auth_pmksa_add3(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002137 intro.pmkid, expiration,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002138 WPA_KEY_MGMT_DPP, pkhash) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002139 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;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002409#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07002410 struct sae_password_entry *e;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002411#endif /* CONFIG_SAE */
Sunil Ravi89eba102022-09-13 21:04:37 -07002412 int conf_id = -1;
2413 bool sae = false, psk = false;
2414 size_t len;
2415
2416 if (hapd->dpp_pkex) {
2417 wpa_printf(MSG_DEBUG,
2418 "PDP: Sending previously generated PKEX Exchange Request to "
2419 MACSTR, MAC2STR(src));
2420 msg = hapd->dpp_pkex->exchange_req;
2421 hostapd_drv_send_action(hapd, freq, 0, src,
2422 wpabuf_head(msg), wpabuf_len(msg));
2423 return;
2424 }
2425
2426 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
2427 MACSTR, MAC2STR(src));
2428
2429 hapd->dpp_pkex_bi = ifaces->dpp_pb_bi;
2430 os_memcpy(ifaces->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
2431
2432 pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr,
2433 "PBPKEX", (const char *) ifaces->dpp_pb_c_nonce,
2434 ifaces->dpp_pb_bi->curve->nonce_len,
2435 true);
2436 if (!pkex) {
2437 hostapd_dpp_push_button_stop(hapd);
2438 return;
2439 }
2440 pkex->freq = freq;
2441
2442 hapd->dpp_pkex = pkex;
2443 msg = hapd->dpp_pkex->exchange_req;
2444
2445 if (ifaces->dpp_pb_cmd) {
2446 /* Use the externally provided configuration */
2447 os_free(hapd->dpp_pkex_auth_cmd);
2448 len = 30 + os_strlen(ifaces->dpp_pb_cmd);
2449 hapd->dpp_pkex_auth_cmd = os_malloc(len);
2450 if (!hapd->dpp_pkex_auth_cmd) {
2451 hostapd_dpp_push_button_stop(hapd);
2452 return;
2453 }
2454 os_snprintf(hapd->dpp_pkex_auth_cmd, len, " own=%d %s",
2455 hapd->dpp_pkex_bi->id, ifaces->dpp_pb_cmd);
2456 goto send_frame;
2457 }
2458
2459 /* Build config based on the current AP configuration */
2460 wpa_snprintf_hex(ssid_hex, sizeof(ssid_hex),
2461 (const u8 *) hapd->conf->ssid.ssid,
2462 hapd->conf->ssid.ssid_len);
2463
2464 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
2465 /* TODO: If a local Configurator has been enabled, allow a
2466 * DPP AKM credential to be provisioned by setting conf_id. */
2467 }
2468
2469 if (hapd->conf->wpa & WPA_PROTO_RSN) {
2470 psk = hapd->conf->wpa_key_mgmt & (WPA_KEY_MGMT_PSK |
2471 WPA_KEY_MGMT_PSK_SHA256);
2472#ifdef CONFIG_SAE
2473 sae = hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE;
2474#endif /* CONFIG_SAE */
2475 }
2476
2477#ifdef CONFIG_SAE
2478 for (e = hapd->conf->sae_passwords; sae && e && !password;
2479 e = e->next) {
2480 if (e->identifier || !is_broadcast_ether_addr(e->peer_addr))
2481 continue;
2482 password = e->password;
2483 }
2484#endif /* CONFIG_SAE */
2485 if (!password && hapd->conf->ssid.wpa_passphrase_set &&
2486 hapd->conf->ssid.wpa_passphrase)
2487 password = hapd->conf->ssid.wpa_passphrase;
2488 if (password) {
2489 len = 2 * os_strlen(password) + 1;
2490 pass_hex = os_malloc(len);
2491 if (!pass_hex) {
2492 hostapd_dpp_push_button_stop(hapd);
2493 return;
2494 }
2495 wpa_snprintf_hex(pass_hex, len, (const u8 *) password,
2496 os_strlen(password));
2497 }
2498
2499 if (conf_id > 0 && sae && psk && pass_hex) {
2500 os_snprintf(cmd, sizeof(cmd),
2501 "conf=sta-dpp+psk+sae configurator=%d ssid=%s pass=%s",
2502 conf_id, ssid_hex, pass_hex);
2503 } else if (conf_id > 0 && sae && pass_hex) {
2504 os_snprintf(cmd, sizeof(cmd),
2505 "conf=sta-dpp+sae configurator=%d ssid=%s pass=%s",
2506 conf_id, ssid_hex, pass_hex);
2507 } else if (conf_id > 0) {
2508 os_snprintf(cmd, sizeof(cmd),
2509 "conf=sta-dpp configurator=%d ssid=%s",
2510 conf_id, ssid_hex);
2511 } if (sae && psk && pass_hex) {
2512 os_snprintf(cmd, sizeof(cmd),
2513 "conf=sta-psk+sae ssid=%s pass=%s",
2514 ssid_hex, pass_hex);
2515 } else if (sae && pass_hex) {
2516 os_snprintf(cmd, sizeof(cmd),
2517 "conf=sta-sae ssid=%s pass=%s",
2518 ssid_hex, pass_hex);
2519 } else if (psk && pass_hex) {
2520 os_snprintf(cmd, sizeof(cmd),
2521 "conf=sta-psk ssid=%s pass=%s",
2522 ssid_hex, pass_hex);
2523 } else {
2524 wpa_printf(MSG_INFO,
2525 "DPP: Unsupported AP configuration for push button");
2526 str_clear_free(pass_hex);
2527 hostapd_dpp_push_button_stop(hapd);
2528 return;
2529 }
2530 str_clear_free(pass_hex);
2531
2532 os_free(hapd->dpp_pkex_auth_cmd);
2533 len = 30 + os_strlen(cmd);
2534 hapd->dpp_pkex_auth_cmd = os_malloc(len);
2535 if (hapd->dpp_pkex_auth_cmd)
2536 os_snprintf(hapd->dpp_pkex_auth_cmd, len, " own=%d %s",
2537 hapd->dpp_pkex_bi->id, cmd);
2538 forced_memzero(cmd, sizeof(cmd));
2539 if (!hapd->dpp_pkex_auth_cmd) {
2540 hostapd_dpp_push_button_stop(hapd);
2541 return;
2542 }
2543
2544send_frame:
2545 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2546 " freq=%u type=%d", MAC2STR(src), freq,
2547 DPP_PA_PKEX_EXCHANGE_REQ);
2548 hostapd_drv_send_action(hapd, pkex->freq, 0, src,
2549 wpabuf_head(msg), wpabuf_len(msg));
2550 pkex->exch_req_wait_time = 2000;
2551 pkex->exch_req_tries = 1;
2552}
2553
2554
2555static void
2556hostapd_dpp_rx_pb_presence_announcement(struct hostapd_data *hapd,
2557 const u8 *src, const u8 *hdr,
2558 const u8 *buf, size_t len,
2559 unsigned int freq)
2560{
2561 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
2562 const u8 *r_hash;
2563 u16 r_hash_len;
2564 unsigned int i;
2565 bool found = false;
2566 struct dpp_pb_info *info, *tmp;
2567 struct os_reltime now, age;
2568 struct wpabuf *msg;
2569
2570 if (!ifaces)
2571 return;
2572
2573 os_get_reltime(&now);
2574 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
2575 MACSTR, MAC2STR(src));
2576
2577 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2578 &r_hash_len);
2579 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
2580 wpa_printf(MSG_DEBUG,
2581 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
2582 return;
2583 }
2584 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2585 r_hash, r_hash_len);
2586
2587 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2588 info = &ifaces->dpp_pb[i];
2589 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
2590 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
2591 continue;
2592 wpa_printf(MSG_DEBUG,
2593 "DPP: Active push button Enrollee already known");
2594 found = true;
2595 info->rx_time = now;
2596 }
2597
2598 if (!found) {
2599 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2600 tmp = &ifaces->dpp_pb[i];
2601 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
2602 continue;
2603
2604 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
2605 wpa_hexdump(MSG_DEBUG,
2606 "DPP: Push button Enrollee hash expired",
2607 tmp->hash, SHA256_MAC_LEN);
2608 tmp->rx_time.sec = 0;
2609 tmp->rx_time.usec = 0;
2610 continue;
2611 }
2612
2613 wpa_hexdump(MSG_DEBUG,
2614 "DPP: Push button session overlap with hash",
2615 tmp->hash, SHA256_MAC_LEN);
2616 if (!ifaces->dpp_pb_result_indicated &&
2617 hostapd_dpp_pb_active(hapd)) {
2618 wpa_msg(hapd->msg_ctx, MSG_INFO,
2619 DPP_EVENT_PB_RESULT "session-overlap");
2620 ifaces->dpp_pb_result_indicated = true;
2621 }
2622 hostapd_dpp_push_button_stop(hapd);
2623 return;
2624 }
2625
2626 /* Replace the oldest entry */
2627 info = &ifaces->dpp_pb[0];
2628 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
2629 tmp = &ifaces->dpp_pb[i];
2630 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
2631 info = tmp;
2632 }
2633 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
2634 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
2635 info->rx_time = now;
2636 }
2637
2638 if (!hostapd_dpp_pb_active(hapd)) {
2639 wpa_printf(MSG_DEBUG,
2640 "DPP: Discard message since own push button has not been pressed");
2641 return;
2642 }
2643
2644 if (ifaces->dpp_pb_announce_time.sec == 0 &&
2645 ifaces->dpp_pb_announce_time.usec == 0) {
2646 /* Start a wait before allowing PKEX to be initiated */
2647 ifaces->dpp_pb_announce_time = now;
2648 }
2649
2650 if (!ifaces->dpp_pb_bi) {
2651 int res;
2652
2653 res = dpp_bootstrap_gen(ifaces->dpp, "type=pkex");
2654 if (res < 0)
2655 return;
2656 ifaces->dpp_pb_bi = dpp_bootstrap_get_id(ifaces->dpp, res);
2657 if (!ifaces->dpp_pb_bi)
2658 return;
2659
2660 if (random_get_bytes(ifaces->dpp_pb_c_nonce,
2661 ifaces->dpp_pb_bi->curve->nonce_len)) {
2662 wpa_printf(MSG_ERROR,
2663 "DPP: Failed to generate C-nonce");
2664 hostapd_dpp_push_button_stop(hapd);
2665 return;
2666 }
2667 }
2668
2669 /* Skip the response if one was sent within last 50 ms since the
2670 * Enrollee is going to send out at least three announcement messages.
2671 */
2672 os_reltime_sub(&now, &ifaces->dpp_pb_last_resp, &age);
2673 if (age.sec == 0 && age.usec < 50000) {
2674 wpa_printf(MSG_DEBUG,
2675 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
2676 return;
2677 }
2678
2679 msg = dpp_build_pb_announcement_resp(
2680 ifaces->dpp_pb_bi, r_hash, ifaces->dpp_pb_c_nonce,
2681 ifaces->dpp_pb_bi->curve->nonce_len);
2682 if (!msg) {
2683 hostapd_dpp_push_button_stop(hapd);
2684 return;
2685 }
2686
2687 wpa_printf(MSG_DEBUG,
2688 "DPP: Send Push Button Presence Announcement Response to "
2689 MACSTR, MAC2STR(src));
2690 ifaces->dpp_pb_last_resp = now;
2691
2692 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2693 " freq=%u type=%d", MAC2STR(src), freq,
2694 DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
2695 hostapd_drv_send_action(hapd, freq, 0, src,
2696 wpabuf_head(msg), wpabuf_len(msg));
2697 wpabuf_free(msg);
2698
2699 if (os_reltime_expired(&now, &ifaces->dpp_pb_announce_time, 15))
2700 hostapd_dpp_pb_pkex_init(hapd, freq, src, r_hash);
2701}
2702
2703
2704static void
2705hostapd_dpp_rx_priv_peer_intro_query(struct hostapd_data *hapd, const u8 *src,
2706 const u8 *hdr, const u8 *buf, size_t len,
2707 unsigned int freq)
2708{
2709 const u8 *trans_id, *version;
2710 u16 trans_id_len, version_len;
2711 struct wpabuf *msg;
2712 u8 ver = DPP_VERSION;
2713 int conn_ver;
2714
2715 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Query from "
2716 MACSTR, MAC2STR(src));
2717
2718 if (!hapd_dpp_connector_available(hapd))
2719 return;
2720
2721 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2722 &trans_id_len);
2723 if (!trans_id || trans_id_len != 1) {
2724 wpa_printf(MSG_DEBUG,
2725 "DPP: Peer did not include Transaction ID");
2726 return;
2727 }
2728
2729 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2730 &version_len);
2731 if (!version || version_len != 1) {
2732 wpa_printf(MSG_DEBUG,
2733 "DPP: Peer did not include Protocol Version");
2734 return;
2735 }
2736
2737 wpa_printf(MSG_DEBUG, "DPP: Transaction ID %u, Version %u",
2738 trans_id[0], version[0]);
2739
2740 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
2741 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_NOTIFY, len);
2742 if (!msg)
2743 return;
2744
2745 /* Transaction ID */
2746 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2747 wpabuf_put_le16(msg, 1);
2748 wpabuf_put_u8(msg, trans_id[0]);
2749
2750 /* Protocol Version */
2751 conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
2752 if (conn_ver > 0 && ver != conn_ver) {
2753 wpa_printf(MSG_DEBUG,
2754 "DPP: Use Connector version %d instead of current protocol version %d",
2755 conn_ver, ver);
2756 ver = conn_ver;
2757 }
2758 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
2759 wpabuf_put_le16(msg, 1);
2760 wpabuf_put_u8(msg, ver);
2761
2762 /* DPP Connector */
2763 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2764 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
2765 wpabuf_put_str(msg, hapd->conf->dpp_connector);
2766
2767 wpa_printf(MSG_DEBUG, "DPP: Send Private Peer Introduction Notify to "
2768 MACSTR, MAC2STR(src));
2769 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2770 " freq=%u type=%d", MAC2STR(src), freq,
2771 DPP_PA_PRIV_PEER_INTRO_NOTIFY);
2772 hostapd_drv_send_action(hapd, freq, 0, src,
2773 wpabuf_head(msg), wpabuf_len(msg));
2774 wpabuf_free(msg);
2775}
2776
2777
2778static void
2779hostapd_dpp_rx_priv_peer_intro_update(struct hostapd_data *hapd, const u8 *src,
2780 const u8 *hdr, const u8 *buf, size_t len,
2781 unsigned int freq)
2782{
2783 struct crypto_ec_key *own_key;
2784 const struct dpp_curve_params *curve;
2785 enum hpke_kem_id kem_id;
2786 enum hpke_kdf_id kdf_id;
2787 enum hpke_aead_id aead_id;
2788 const u8 *aad = hdr;
2789 size_t aad_len = DPP_HDR_LEN;
2790 struct wpabuf *pt;
2791 const u8 *trans_id, *wrapped, *version, *connector;
2792 u16 trans_id_len, wrapped_len, version_len, connector_len;
2793 struct os_time now;
2794 struct dpp_introduction intro;
2795 os_time_t expire;
2796 int expiration;
2797 enum dpp_status_error res;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002798 u8 pkhash[SHA256_MAC_LEN];
Sunil Ravi89eba102022-09-13 21:04:37 -07002799
2800 os_memset(&intro, 0, sizeof(intro));
2801
2802 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Update from "
2803 MACSTR, MAC2STR(src));
2804
2805 if (!hapd_dpp_connector_available(hapd))
2806 return;
2807
2808 os_get_time(&now);
2809
2810 if (hapd->conf->dpp_netaccesskey_expiry &&
2811 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
2812 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
2813 return;
2814 }
2815
2816 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2817 &trans_id_len);
2818 if (!trans_id || trans_id_len != 1) {
2819 wpa_printf(MSG_DEBUG,
2820 "DPP: Peer did not include Transaction ID");
2821 return;
2822 }
2823
2824 wrapped = dpp_get_attr(buf, len, DPP_ATTR_WRAPPED_DATA,
2825 &wrapped_len);
2826 if (!wrapped) {
2827 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Wrapped Data");
2828 return;
2829 }
2830
2831 own_key = dpp_set_keypair(&curve,
2832 wpabuf_head(hapd->conf->dpp_netaccesskey),
2833 wpabuf_len(hapd->conf->dpp_netaccesskey));
2834 if (!own_key) {
2835 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
2836 return;
2837 }
2838
2839 if (dpp_hpke_suite(curve->ike_group, &kem_id, &kdf_id, &aead_id) < 0) {
2840 wpa_printf(MSG_ERROR, "DPP: Unsupported curve %d",
2841 curve->ike_group);
2842 crypto_ec_key_deinit(own_key);
2843 return;
2844 }
2845
2846 pt = hpke_base_open(kem_id, kdf_id, aead_id, own_key, NULL, 0,
2847 aad, aad_len, wrapped, wrapped_len);
2848 crypto_ec_key_deinit(own_key);
2849 if (!pt) {
2850 wpa_printf(MSG_INFO, "DPP: Failed to decrypt Connector");
2851 return;
2852 }
2853 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE-Decrypted Wrapped Data", pt);
2854
2855 connector = dpp_get_attr(wpabuf_head(pt), wpabuf_len(pt),
2856 DPP_ATTR_CONNECTOR, &connector_len);
2857 if (!connector) {
2858 wpa_printf(MSG_DEBUG,
2859 "DPP: Peer did not include its Connector");
2860 goto done;
2861 }
2862
2863 version = dpp_get_attr(wpabuf_head(pt), wpabuf_len(pt),
2864 DPP_ATTR_PROTOCOL_VERSION, &version_len);
2865 if (!version || version_len < 1) {
2866 wpa_printf(MSG_DEBUG,
2867 "DPP: Peer did not include Protocol Version");
2868 goto done;
2869 }
2870
2871 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
2872 wpabuf_head(hapd->conf->dpp_netaccesskey),
2873 wpabuf_len(hapd->conf->dpp_netaccesskey),
2874 wpabuf_head(hapd->conf->dpp_csign),
2875 wpabuf_len(hapd->conf->dpp_csign),
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002876 connector, connector_len, &expire, pkhash);
Sunil Ravi89eba102022-09-13 21:04:37 -07002877 if (res == 255) {
2878 wpa_printf(MSG_INFO,
2879 "DPP: Network Introduction protocol resulted in internal failure (peer "
2880 MACSTR ")", MAC2STR(src));
2881 goto done;
2882 }
2883 if (res != DPP_STATUS_OK) {
2884 wpa_printf(MSG_INFO,
2885 "DPP: Network Introduction protocol resulted in failure (peer "
2886 MACSTR " status %d)", MAC2STR(src), res);
2887 goto done;
2888 }
2889
2890 if (intro.peer_version && intro.peer_version >= 2) {
2891 u8 attr_version = 1;
2892
2893 if (version && version_len >= 1)
2894 attr_version = version[0];
2895 if (attr_version != intro.peer_version) {
2896 wpa_printf(MSG_INFO,
2897 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2898 intro.peer_version, attr_version);
2899 goto done;
2900 }
2901 }
2902
2903 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
2904 expire = hapd->conf->dpp_netaccesskey_expiry;
2905 if (expire)
2906 expiration = expire - now.sec;
2907 else
2908 expiration = 0;
2909
Sunil Ravieb83e2a2024-06-28 17:34:56 +00002910 if (wpa_auth_pmksa_add3(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
Sunil Ravi89eba102022-09-13 21:04:37 -07002911 intro.pmkid, expiration,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002912 WPA_KEY_MGMT_DPP, pkhash) < 0) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002913 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
2914 goto done;
2915 }
2916
2917 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction completed with "
2918 MACSTR, MAC2STR(src));
2919
2920done:
2921 dpp_peer_intro_deinit(&intro);
2922 wpabuf_free(pt);
2923}
2924
2925#endif /* CONFIG_DPP3 */
2926
2927
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002928void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
2929 const u8 *buf, size_t len, unsigned int freq)
2930{
2931 u8 crypto_suite;
2932 enum dpp_public_action_frame_type type;
2933 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002934 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002935
2936 if (len < DPP_HDR_LEN)
2937 return;
2938 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2939 return;
2940 hdr = buf;
2941 buf += 4;
2942 len -= 4;
2943 crypto_suite = *buf++;
2944 type = *buf++;
2945 len -= 2;
2946
2947 wpa_printf(MSG_DEBUG,
2948 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2949 MACSTR " freq=%u",
2950 crypto_suite, type, MAC2STR(src), freq);
2951 if (crypto_suite != 1) {
2952 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2953 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002954 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2955 " freq=%u type=%d ignore=unsupported-crypto-suite",
2956 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002957 return;
2958 }
2959 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002960 if (dpp_check_attrs(buf, len) < 0) {
2961 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2962 " freq=%u type=%d ignore=invalid-attributes",
2963 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002964 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002965 }
2966 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2967 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002968
Hai Shalom81f62d82019-07-22 12:10:00 -07002969#ifdef CONFIG_DPP2
2970 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002971 src, hdr, buf, len, freq, NULL, NULL,
2972 hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07002973 return;
2974#endif /* CONFIG_DPP2 */
2975
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002976 switch (type) {
2977 case DPP_PA_AUTHENTICATION_REQ:
2978 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
2979 break;
2980 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002981 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002982 break;
2983 case DPP_PA_AUTHENTICATION_CONF:
2984 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
2985 break;
2986 case DPP_PA_PEER_DISCOVERY_REQ:
2987 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
2988 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002989#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002990 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002991 /* This is for PKEXv2, but for now, process only with
2992 * CONFIG_DPP3 to avoid issues with a capability that has not
2993 * been tested with other implementations. */
2994 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
2995 true);
2996 break;
2997#endif /* CONFIG_DPP3 */
2998 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
2999 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
3000 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003001 break;
3002 case DPP_PA_PKEX_EXCHANGE_RESP:
3003 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
3004 break;
3005 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
3006 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
3007 freq);
3008 break;
3009 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
3010 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
3011 freq);
3012 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003013#ifdef CONFIG_DPP2
3014 case DPP_PA_CONFIGURATION_RESULT:
3015 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
3016 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003017 case DPP_PA_CONNECTION_STATUS_RESULT:
3018 hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
3019 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07003020 case DPP_PA_PRESENCE_ANNOUNCEMENT:
3021 hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
3022 freq);
3023 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003024 case DPP_PA_RECONFIG_ANNOUNCEMENT:
3025 hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
3026 freq);
3027 break;
3028 case DPP_PA_RECONFIG_AUTH_RESP:
3029 hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
3030 freq);
3031 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003032#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07003033#ifdef CONFIG_DPP3
3034 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
3035 hostapd_dpp_rx_pb_presence_announcement(hapd, src, hdr,
3036 buf, len, freq);
3037 break;
3038 case DPP_PA_PRIV_PEER_INTRO_QUERY:
3039 hostapd_dpp_rx_priv_peer_intro_query(hapd, src, hdr,
3040 buf, len, freq);
3041 break;
3042 case DPP_PA_PRIV_PEER_INTRO_UPDATE:
3043 hostapd_dpp_rx_priv_peer_intro_update(hapd, src, hdr,
3044 buf, len, freq);
3045 break;
3046#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003047 default:
3048 wpa_printf(MSG_DEBUG,
3049 "DPP: Ignored unsupported frame subtype %d", type);
3050 break;
3051 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003052
3053 if (hapd->dpp_pkex)
3054 pkex_t = hapd->dpp_pkex->t;
3055 else if (hapd->dpp_pkex_bi)
3056 pkex_t = hapd->dpp_pkex_bi->pkex_t;
3057 else
3058 pkex_t = 0;
3059 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
3060 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
3061 hostapd_dpp_pkex_remove(hapd, "*");
3062 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003063}
3064
3065
3066struct wpabuf *
3067hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
Hai Shalom81f62d82019-07-22 12:10:00 -07003068 const u8 *query, size_t query_len,
3069 const u8 *data, size_t data_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003070{
3071 struct dpp_authentication *auth = hapd->dpp_auth;
3072 struct wpabuf *resp;
3073
3074 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003075 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravieb83e2a2024-06-28 17:34:56 +00003076 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003077#ifdef CONFIG_DPP2
3078 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
3079 data_len) == 0) {
3080 /* Response will be forwarded once received over TCP */
3081 return NULL;
3082 }
3083#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003084 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
3085 return NULL;
3086 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08003087
3088 if (hapd->dpp_auth_ok_on_ack && auth->configurator) {
3089 wpa_printf(MSG_DEBUG,
3090 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
3091 /* hostapd_dpp_auth_success() would normally have been called
3092 * from TX status handler, but since there was no such handler
3093 * call yet, simply send out the event message and proceed with
3094 * exchange. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003095 dpp_notify_auth_success(hapd->dpp_auth, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003096 hapd->dpp_auth_ok_on_ack = 0;
3097 }
3098
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003099 wpa_hexdump(MSG_DEBUG,
3100 "DPP: Received Configuration Request (GAS Query Request)",
3101 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003102 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
3103 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003104 resp = dpp_conf_req_rx(auth, query, query_len);
3105 if (!resp)
3106 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
3107 return resp;
3108}
3109
3110
Roshan Pius3a1667e2018-07-03 15:17:14 -07003111void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
3112{
Hai Shalom021b0b52019-04-10 11:17:58 -07003113 struct dpp_authentication *auth = hapd->dpp_auth;
Sunil Ravi89eba102022-09-13 21:04:37 -07003114#ifdef CONFIG_DPP3
3115 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3116#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07003117
3118 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07003119 return;
3120
Sunil Ravia04bd252022-05-02 22:54:18 -07003121#ifdef CONFIG_DPP3
3122 if (auth->waiting_new_key && ok) {
3123 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
3124 return;
3125 }
3126#endif /* CONFIG_DPP3 */
3127
Hai Shalom021b0b52019-04-10 11:17:58 -07003128 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
3129 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003130 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003131 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003132 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003133#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003134 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
3135 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003136 if (ok && auth->peer_version >= 2 &&
3137 auth->conf_resp_status == DPP_STATUS_OK) {
3138 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
3139 auth->waiting_conf_result = 1;
3140 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
3141 hapd, NULL);
3142 eloop_register_timeout(2, 0,
3143 hostapd_dpp_config_result_wait_timeout,
3144 hapd, NULL);
3145 return;
3146 }
3147#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003148 hostapd_drv_send_action_cancel_wait(hapd);
3149
3150 if (ok)
Sunil Ravi89eba102022-09-13 21:04:37 -07003151 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
3152 "conf_status=%d", auth->conf_resp_status);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003153 else
3154 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
3155 dpp_auth_deinit(hapd->dpp_auth);
3156 hapd->dpp_auth = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003157#ifdef CONFIG_DPP3
3158 if (!ifaces->dpp_pb_result_indicated && hostapd_dpp_pb_active(hapd)) {
3159 if (ok)
3160 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
3161 "success");
3162 else
3163 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
3164 "could-not-connect");
3165 ifaces->dpp_pb_result_indicated = true;
3166 if (ok)
3167 hostapd_dpp_remove_pb_hash(hapd);
3168 hostapd_dpp_push_button_stop(hapd);
3169 }
3170#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003171}
3172
3173
Roshan Pius3a1667e2018-07-03 15:17:14 -07003174int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
3175{
3176 struct dpp_authentication *auth;
3177 int ret = -1;
3178 char *curve = NULL;
3179
Hai Shalomfdcde762020-04-02 11:19:20 -07003180 auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003181 if (!auth)
3182 return -1;
3183
3184 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08003185 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07003186 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08003187 dpp_configurator_own_config(auth, curve, 1) == 0) {
Hai Shalomc3565922019-10-28 11:58:20 -07003188 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003189 ret = 0;
3190 }
3191
3192 dpp_auth_deinit(auth);
3193 os_free(curve);
3194
3195 return ret;
3196}
3197
3198
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003199int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
3200{
3201 struct dpp_bootstrap_info *own_bi;
3202 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07003203#ifdef CONFIG_DPP3
3204 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
3205#else /* CONFIG_DPP3 */
3206 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
3207#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003208 int tcp_port = DPP_TCP_PORT;
3209 struct hostapd_ip_addr *ipaddr = NULL;
3210#ifdef CONFIG_DPP2
3211 struct hostapd_ip_addr ipaddr_buf;
3212 char *addr;
3213
3214 pos = os_strstr(cmd, " tcp_port=");
3215 if (pos) {
3216 pos += 10;
3217 tcp_port = atoi(pos);
3218 }
3219
3220 addr = get_param(cmd, " tcp_addr=");
3221 if (addr) {
3222 int res;
3223
3224 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
3225 os_free(addr);
3226 if (res)
3227 return -1;
3228 ipaddr = &ipaddr_buf;
3229 }
3230#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003231
3232 pos = os_strstr(cmd, " own=");
3233 if (!pos)
3234 return -1;
3235 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07003236 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003237 if (!own_bi) {
3238 wpa_printf(MSG_DEBUG,
3239 "DPP: Identified bootstrap info not found");
3240 return -1;
3241 }
3242 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
3243 wpa_printf(MSG_DEBUG,
3244 "DPP: Identified bootstrap info not for PKEX");
3245 return -1;
3246 }
3247 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003248 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003249
3250 os_free(hapd->dpp_pkex_identifier);
3251 hapd->dpp_pkex_identifier = NULL;
3252 pos = os_strstr(cmd, " identifier=");
3253 if (pos) {
3254 pos += 12;
3255 end = os_strchr(pos, ' ');
3256 if (!end)
3257 return -1;
3258 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
3259 if (!hapd->dpp_pkex_identifier)
3260 return -1;
3261 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
3262 hapd->dpp_pkex_identifier[end - pos] = '\0';
3263 }
3264
3265 pos = os_strstr(cmd, " code=");
3266 if (!pos)
3267 return -1;
3268 os_free(hapd->dpp_pkex_code);
3269 hapd->dpp_pkex_code = os_strdup(pos + 6);
3270 if (!hapd->dpp_pkex_code)
3271 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07003272 hapd->dpp_pkex_code_len = os_strlen(hapd->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003273
Sunil Ravia04bd252022-05-02 22:54:18 -07003274 pos = os_strstr(cmd, " ver=");
3275 if (pos) {
3276 int v;
3277
3278 pos += 5;
3279 v = atoi(pos);
3280 if (v == 1)
3281 ver = PKEX_VER_ONLY_1;
3282 else if (v == 2)
3283 ver = PKEX_VER_ONLY_2;
3284 else
3285 return -1;
3286 }
3287 hapd->dpp_pkex_ver = ver;
3288
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003289 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003290 if (hostapd_dpp_pkex_init(hapd, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003291 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003292 } else {
3293#ifdef CONFIG_DPP2
3294 dpp_controller_pkex_add(hapd->iface->interfaces->dpp, own_bi,
3295 hapd->dpp_pkex_code,
3296 hapd->dpp_pkex_identifier);
3297#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003298 }
3299
3300 /* TODO: Support multiple PKEX info entries */
3301
3302 os_free(hapd->dpp_pkex_auth_cmd);
3303 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
3304
3305 return 1;
3306}
3307
3308
3309int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
3310{
3311 unsigned int id_val;
3312
3313 if (os_strcmp(id, "*") == 0) {
3314 id_val = 0;
3315 } else {
3316 id_val = atoi(id);
3317 if (id_val == 0)
3318 return -1;
3319 }
3320
Sunil Ravi89eba102022-09-13 21:04:37 -07003321 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003322 return -1;
3323
3324 /* TODO: Support multiple PKEX entries */
3325 os_free(hapd->dpp_pkex_code);
3326 hapd->dpp_pkex_code = NULL;
3327 os_free(hapd->dpp_pkex_identifier);
3328 hapd->dpp_pkex_identifier = NULL;
3329 os_free(hapd->dpp_pkex_auth_cmd);
3330 hapd->dpp_pkex_auth_cmd = NULL;
3331 hapd->dpp_pkex_bi = NULL;
3332 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
3333 dpp_pkex_free(hapd->dpp_pkex);
3334 hapd->dpp_pkex = NULL;
3335 return 0;
3336}
3337
3338
Roshan Pius3a1667e2018-07-03 15:17:14 -07003339void hostapd_dpp_stop(struct hostapd_data *hapd)
3340{
3341 dpp_auth_deinit(hapd->dpp_auth);
3342 hapd->dpp_auth = NULL;
3343 dpp_pkex_free(hapd->dpp_pkex);
3344 hapd->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003345#ifdef CONFIG_DPP3
3346 hostapd_dpp_push_button_stop(hapd);
3347#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003348}
3349
3350
Hai Shalom81f62d82019-07-22 12:10:00 -07003351#ifdef CONFIG_DPP2
3352
3353static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq,
3354 const u8 *msg, size_t len)
3355{
3356 struct hostapd_data *hapd = ctx;
3357 u8 *buf;
3358
Sunil Ravi89eba102022-09-13 21:04:37 -07003359 if (freq == 0)
3360 freq = hapd->iface->freq;
3361
Hai Shalom81f62d82019-07-22 12:10:00 -07003362 wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u",
3363 MAC2STR(addr), freq);
3364 buf = os_malloc(2 + len);
3365 if (!buf)
3366 return;
3367 buf[0] = WLAN_ACTION_PUBLIC;
3368 buf[1] = WLAN_PA_VENDOR_SPECIFIC;
3369 os_memcpy(buf + 2, msg, len);
3370 hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len);
3371 os_free(buf);
3372}
3373
3374
3375static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr,
3376 u8 dialog_token, int prot,
3377 struct wpabuf *buf)
3378{
3379 struct hostapd_data *hapd = ctx;
3380
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003381 gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf, 0);
Hai Shalom81f62d82019-07-22 12:10:00 -07003382}
3383
3384#endif /* CONFIG_DPP2 */
3385
3386
3387static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
3388{
3389#ifdef CONFIG_DPP2
3390 struct dpp_controller_conf *ctrl;
3391 struct dpp_relay_config config;
3392
3393 os_memset(&config, 0, sizeof(config));
Sunil Ravi89eba102022-09-13 21:04:37 -07003394 config.msg_ctx = hapd->msg_ctx;
Hai Shalom81f62d82019-07-22 12:10:00 -07003395 config.cb_ctx = hapd;
3396 config.tx = hostapd_dpp_relay_tx;
3397 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
3398 for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) {
3399 config.ipaddr = &ctrl->ipaddr;
3400 config.pkhash = ctrl->pkhash;
3401 if (dpp_relay_add_controller(hapd->iface->interfaces->dpp,
3402 &config) < 0)
3403 return -1;
3404 }
Sunil Ravi89eba102022-09-13 21:04:37 -07003405
3406 if (hapd->conf->dpp_relay_port)
3407 dpp_relay_listen(hapd->iface->interfaces->dpp,
3408 hapd->conf->dpp_relay_port,
3409 &config);
Hai Shalom81f62d82019-07-22 12:10:00 -07003410#endif /* CONFIG_DPP2 */
3411
3412 return 0;
3413}
3414
3415
Sunil Ravi89eba102022-09-13 21:04:37 -07003416#ifdef CONFIG_DPP2
3417
3418int hostapd_dpp_add_controller(struct hostapd_data *hapd, const char *cmd)
3419{
3420 struct dpp_relay_config config;
3421 struct hostapd_ip_addr addr;
3422 u8 pkhash[SHA256_MAC_LEN];
3423 char *pos, *tmp;
3424 int ret = -1;
3425 bool prev_state, new_state;
3426 struct dpp_global *dpp = hapd->iface->interfaces->dpp;
3427
3428 tmp = os_strdup(cmd);
3429 if (!tmp)
3430 goto fail;
3431 pos = os_strchr(tmp, ' ');
3432 if (!pos)
3433 goto fail;
3434 *pos++ = '\0';
3435 if (hostapd_parse_ip_addr(tmp, &addr) < 0 ||
3436 hexstr2bin(pos, pkhash, SHA256_MAC_LEN) < 0)
3437 goto fail;
3438
3439 os_memset(&config, 0, sizeof(config));
3440 config.msg_ctx = hapd->msg_ctx;
3441 config.cb_ctx = hapd;
3442 config.tx = hostapd_dpp_relay_tx;
3443 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
3444 config.ipaddr = &addr;
3445 config.pkhash = pkhash;
3446 prev_state = dpp_relay_controller_available(dpp);
3447 ret = dpp_relay_add_controller(dpp, &config);
3448 new_state = dpp_relay_controller_available(dpp);
3449 if (new_state != prev_state)
3450 ieee802_11_update_beacons(hapd->iface);
3451fail:
3452 os_free(tmp);
3453 return ret;
3454}
3455
3456
3457void hostapd_dpp_remove_controller(struct hostapd_data *hapd, const char *cmd)
3458{
3459 struct hostapd_ip_addr addr;
3460 bool prev_state, new_state;
3461 struct dpp_global *dpp = hapd->iface->interfaces->dpp;
3462
3463 if (hostapd_parse_ip_addr(cmd, &addr) < 0)
3464 return;
3465 prev_state = dpp_relay_controller_available(dpp);
3466 dpp_relay_remove_controller(dpp, &addr);
3467 new_state = dpp_relay_controller_available(dpp);
3468 if (new_state != prev_state)
3469 ieee802_11_update_beacons(hapd->iface);
3470}
3471
3472#endif /* CONFIG_DPP2 */
3473
3474
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003475int hostapd_dpp_init(struct hostapd_data *hapd)
3476{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003477 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
3478 hapd->dpp_init_done = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07003479 return hostapd_dpp_add_controllers(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003480}
3481
3482
3483void hostapd_dpp_deinit(struct hostapd_data *hapd)
3484{
3485#ifdef CONFIG_TESTING_OPTIONS
3486 os_free(hapd->dpp_config_obj_override);
3487 hapd->dpp_config_obj_override = NULL;
3488 os_free(hapd->dpp_discovery_override);
3489 hapd->dpp_discovery_override = NULL;
3490 os_free(hapd->dpp_groups_override);
3491 hapd->dpp_groups_override = NULL;
3492 hapd->dpp_ignore_netaccesskey_mismatch = 0;
3493#endif /* CONFIG_TESTING_OPTIONS */
3494 if (!hapd->dpp_init_done)
3495 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003496 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003497 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003498 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003499 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
3500 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003501#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003502 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
3503 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003504 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
3505 NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07003506 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
3507 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003508 hostapd_dpp_chirp_stop(hapd);
Sunil Ravi89eba102022-09-13 21:04:37 -07003509 if (hapd->iface->interfaces) {
3510 dpp_relay_stop_listen(hapd->iface->interfaces->dpp);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003511 dpp_controller_stop_for_ctx(hapd->iface->interfaces->dpp, hapd);
Sunil Ravi89eba102022-09-13 21:04:37 -07003512 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003513#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003514#ifdef CONFIG_DPP3
3515 eloop_cancel_timeout(hostapd_dpp_build_new_key, hapd, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07003516 hostapd_dpp_push_button_stop(hapd);
Sunil Ravia04bd252022-05-02 22:54:18 -07003517#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003518 dpp_auth_deinit(hapd->dpp_auth);
3519 hapd->dpp_auth = NULL;
3520 hostapd_dpp_pkex_remove(hapd, "*");
3521 hapd->dpp_pkex = NULL;
3522 os_free(hapd->dpp_configurator_params);
3523 hapd->dpp_configurator_params = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003524 os_free(hapd->dpp_pkex_auth_cmd);
3525 hapd->dpp_pkex_auth_cmd = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003526}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003527
3528
3529#ifdef CONFIG_DPP2
3530
Hai Shalom899fcc72020-10-19 14:38:18 -07003531int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd)
3532{
3533 struct dpp_controller_config config;
3534 const char *pos;
3535
3536 os_memset(&config, 0, sizeof(config));
3537 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
3538 config.netrole = DPP_NETROLE_AP;
3539 config.msg_ctx = hapd->msg_ctx;
3540 config.cb_ctx = hapd;
3541 config.process_conf_obj = hostapd_dpp_process_conf_obj;
3542 if (cmd) {
3543 pos = os_strstr(cmd, " tcp_port=");
3544 if (pos) {
3545 pos += 10;
3546 config.tcp_port = atoi(pos);
3547 }
3548
3549 pos = os_strstr(cmd, " role=");
3550 if (pos) {
3551 pos += 6;
3552 if (os_strncmp(pos, "configurator", 12) == 0)
3553 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
3554 else if (os_strncmp(pos, "enrollee", 8) == 0)
3555 config.allowed_roles = DPP_CAPAB_ENROLLEE;
3556 else if (os_strncmp(pos, "either", 6) == 0)
3557 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
3558 DPP_CAPAB_ENROLLEE;
3559 else
3560 return -1;
3561 }
3562
3563 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
3564 }
3565 config.configurator_params = hapd->dpp_configurator_params;
3566 return dpp_controller_start(hapd->iface->interfaces->dpp, &config);
3567}
3568
3569
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003570static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
3571
3572static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
3573{
3574 struct hostapd_data *hapd = eloop_ctx;
3575
3576 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
3577 hostapd_drv_send_action_cancel_wait(hapd);
3578 hostapd_dpp_chirp_next(hapd, NULL);
3579}
3580
3581
3582static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
3583{
3584 struct wpabuf *msg;
3585 int type;
3586
3587 msg = hapd->dpp_presence_announcement;
3588 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
3589 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
3590 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3591 " freq=%u type=%d",
3592 MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
3593 if (hostapd_drv_send_action(
3594 hapd, hapd->dpp_chirp_freq, 2000, broadcast,
3595 wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
3596 eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
3597 hapd, NULL) < 0)
3598 hostapd_dpp_chirp_stop(hapd);
3599}
3600
3601
3602static struct hostapd_hw_modes *
3603dpp_get_mode(struct hostapd_data *hapd,
3604 enum hostapd_hw_mode mode)
3605{
3606 struct hostapd_hw_modes *modes = hapd->iface->hw_features;
3607 u16 num_modes = hapd->iface->num_hw_features;
3608 u16 i;
3609
3610 for (i = 0; i < num_modes; i++) {
3611 if (modes[i].mode != mode ||
3612 !modes[i].num_channels || !modes[i].channels)
3613 continue;
3614 return &modes[i];
3615 }
3616
3617 return NULL;
3618}
3619
3620
3621static void
3622hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
3623{
3624 struct hostapd_data *hapd = iface->bss[0];
3625 struct wpa_scan_results *scan_res;
3626 struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
3627 unsigned int i;
3628 struct hostapd_hw_modes *mode;
3629 int c;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003630 bool chan6 = hapd->iface->hw_features == NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003631
3632 if (!bi)
3633 return;
3634
3635 hapd->dpp_chirp_scan_done = 1;
3636
3637 scan_res = hostapd_driver_get_scan_results(hapd);
3638
3639 os_free(hapd->dpp_chirp_freqs);
3640 hapd->dpp_chirp_freqs = NULL;
3641
3642 /* Channels from own bootstrapping info */
3643 if (bi) {
3644 for (i = 0; i < bi->num_freq; i++)
3645 int_array_add_unique(&hapd->dpp_chirp_freqs,
3646 bi->freq[i]);
3647 }
3648
3649 /* Preferred chirping channels */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003650 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211G);
3651 if (mode) {
3652 for (c = 0; c < mode->num_channels; c++) {
3653 struct hostapd_channel_data *chan = &mode->channels[c];
3654
3655 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3656 HOSTAPD_CHAN_RADAR) ||
3657 chan->freq != 2437)
3658 continue;
3659 chan6 = true;
3660 break;
3661 }
3662 }
3663 if (chan6)
3664 int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003665
3666 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
3667 if (mode) {
3668 int chan44 = 0, chan149 = 0;
3669
3670 for (c = 0; c < mode->num_channels; c++) {
3671 struct hostapd_channel_data *chan = &mode->channels[c];
3672
3673 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3674 HOSTAPD_CHAN_RADAR))
3675 continue;
3676 if (chan->freq == 5220)
3677 chan44 = 1;
3678 if (chan->freq == 5745)
3679 chan149 = 1;
3680 }
3681 if (chan149)
3682 int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
3683 else if (chan44)
3684 int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
3685 }
3686
3687 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
3688 if (mode) {
3689 for (c = 0; c < mode->num_channels; c++) {
3690 struct hostapd_channel_data *chan = &mode->channels[c];
3691
3692 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
3693 HOSTAPD_CHAN_RADAR)) ||
3694 chan->freq != 60480)
3695 continue;
3696 int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
3697 break;
3698 }
3699 }
3700
3701 /* Add channels from scan results for APs that advertise Configurator
3702 * Connectivity element */
3703 for (i = 0; scan_res && i < scan_res->num; i++) {
3704 struct wpa_scan_res *bss = scan_res->res[i];
3705 size_t ie_len = bss->ie_len;
3706
3707 if (!ie_len)
3708 ie_len = bss->beacon_ie_len;
3709 if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
3710 DPP_CC_IE_VENDOR_TYPE))
3711 int_array_add_unique(&hapd->dpp_chirp_freqs,
3712 bss->freq);
3713 }
3714
3715 if (!hapd->dpp_chirp_freqs ||
3716 eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
3717 hapd, NULL) < 0)
3718 hostapd_dpp_chirp_stop(hapd);
3719
3720 wpa_scan_results_free(scan_res);
3721}
3722
3723
3724static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
3725{
3726 struct hostapd_data *hapd = eloop_ctx;
3727 int i;
3728
3729 if (hapd->dpp_chirp_listen)
3730 hostapd_dpp_listen_stop(hapd);
3731
3732 if (hapd->dpp_chirp_freq == 0) {
3733 if (hapd->dpp_chirp_round % 4 == 0 &&
3734 !hapd->dpp_chirp_scan_done) {
3735 struct wpa_driver_scan_params params;
3736 int ret;
3737
3738 wpa_printf(MSG_DEBUG,
3739 "DPP: Update channel list for chirping");
3740 os_memset(&params, 0, sizeof(params));
3741 ret = hostapd_driver_scan(hapd, &params);
3742 if (ret < 0) {
3743 wpa_printf(MSG_DEBUG,
3744 "DPP: Failed to request a scan ret=%d (%s)",
3745 ret, strerror(-ret));
3746 hostapd_dpp_chirp_scan_res_handler(hapd->iface);
3747 } else {
3748 hapd->iface->scan_cb =
3749 hostapd_dpp_chirp_scan_res_handler;
3750 }
3751 return;
3752 }
3753 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
3754 hapd->dpp_chirp_round++;
3755 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
3756 hapd->dpp_chirp_round);
3757 } else {
3758 for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
3759 if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
3760 break;
3761 if (!hapd->dpp_chirp_freqs[i]) {
3762 wpa_printf(MSG_DEBUG,
3763 "DPP: Previous chirp freq %d not found",
3764 hapd->dpp_chirp_freq);
3765 return;
3766 }
3767 i++;
3768 if (hapd->dpp_chirp_freqs[i]) {
3769 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
3770 } else {
3771 hapd->dpp_chirp_iter--;
3772 if (hapd->dpp_chirp_iter <= 0) {
3773 wpa_printf(MSG_DEBUG,
3774 "DPP: Chirping iterations completed");
3775 hostapd_dpp_chirp_stop(hapd);
3776 return;
3777 }
3778 hapd->dpp_chirp_freq = 0;
3779 hapd->dpp_chirp_scan_done = 0;
3780 if (eloop_register_timeout(30, 0,
3781 hostapd_dpp_chirp_next,
3782 hapd, NULL) < 0) {
3783 hostapd_dpp_chirp_stop(hapd);
3784 return;
3785 }
3786 if (hapd->dpp_chirp_listen) {
3787 wpa_printf(MSG_DEBUG,
3788 "DPP: Listen on %d MHz during chirp 30 second wait",
3789 hapd->dpp_chirp_listen);
3790 /* TODO: start listen on the channel */
3791 } else {
3792 wpa_printf(MSG_DEBUG,
3793 "DPP: Wait 30 seconds before starting the next chirping round");
3794 }
3795 return;
3796 }
3797 }
3798
3799 hostapd_dpp_chirp_start(hapd);
3800}
3801
3802
3803int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
3804{
3805 const char *pos;
3806 int iter = 1, listen_freq = 0;
3807 struct dpp_bootstrap_info *bi;
3808
3809 pos = os_strstr(cmd, " own=");
3810 if (!pos)
3811 return -1;
3812 pos += 5;
3813 bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
3814 if (!bi) {
3815 wpa_printf(MSG_DEBUG,
3816 "DPP: Identified bootstrap info not found");
3817 return -1;
3818 }
3819
3820 pos = os_strstr(cmd, " iter=");
3821 if (pos) {
3822 iter = atoi(pos + 6);
3823 if (iter <= 0)
3824 return -1;
3825 }
3826
3827 pos = os_strstr(cmd, " listen=");
3828 if (pos) {
3829 listen_freq = atoi(pos + 8);
3830 if (listen_freq <= 0)
3831 return -1;
3832 }
3833
3834 hostapd_dpp_chirp_stop(hapd);
3835 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
3836 hapd->dpp_qr_mutual = 0;
3837 hapd->dpp_chirp_bi = bi;
3838 hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
3839 if (!hapd->dpp_presence_announcement)
3840 return -1;
3841 hapd->dpp_chirp_iter = iter;
3842 hapd->dpp_chirp_round = 0;
3843 hapd->dpp_chirp_scan_done = 0;
3844 hapd->dpp_chirp_listen = listen_freq;
3845
3846 return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
3847}
3848
3849
3850void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
3851{
3852 if (hapd->dpp_presence_announcement) {
3853 hostapd_drv_send_action_cancel_wait(hapd);
3854 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
3855 }
3856 hapd->dpp_chirp_bi = NULL;
3857 wpabuf_free(hapd->dpp_presence_announcement);
3858 hapd->dpp_presence_announcement = NULL;
3859 if (hapd->dpp_chirp_listen)
3860 hostapd_dpp_listen_stop(hapd);
3861 hapd->dpp_chirp_listen = 0;
3862 hapd->dpp_chirp_freq = 0;
3863 os_free(hapd->dpp_chirp_freqs);
3864 hapd->dpp_chirp_freqs = NULL;
3865 eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
3866 eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
3867 if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
3868 /* TODO: abort ongoing scan */
3869 hapd->iface->scan_cb = NULL;
3870 }
3871}
3872
3873
3874static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
3875{
3876 struct dpp_bootstrap_info *bi = ctx;
3877 size_t i;
3878
3879 for (i = 0; i < iface->num_bss; i++) {
3880 struct hostapd_data *hapd = iface->bss[i];
3881
3882 if (bi == hapd->dpp_chirp_bi)
3883 hostapd_dpp_chirp_stop(hapd);
3884 }
3885
3886 return 0;
3887}
3888
3889
3890void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
3891{
3892 struct hapd_interfaces *interfaces = ctx;
3893
3894 hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
3895}
3896
3897#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07003898
3899
3900#ifdef CONFIG_DPP3
3901
3902static void hostapd_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
3903{
3904 struct hostapd_data *hapd = eloop_ctx;
3905
3906 wpa_printf(MSG_DEBUG, "DPP: Active push button mode expired");
3907 hostapd_dpp_push_button_stop(hapd);
3908}
3909
3910
3911int hostapd_dpp_push_button(struct hostapd_data *hapd, const char *cmd)
3912{
3913 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3914
3915 if (!ifaces || !ifaces->dpp)
3916 return -1;
3917 os_get_reltime(&ifaces->dpp_pb_time);
3918 ifaces->dpp_pb_announce_time.sec = 0;
3919 ifaces->dpp_pb_announce_time.usec = 0;
3920 str_clear_free(ifaces->dpp_pb_cmd);
3921 ifaces->dpp_pb_cmd = NULL;
3922 if (cmd) {
3923 ifaces->dpp_pb_cmd = os_strdup(cmd);
3924 if (!ifaces->dpp_pb_cmd)
3925 return -1;
3926 }
3927 eloop_register_timeout(100, 0, hostapd_dpp_push_button_expire,
3928 hapd, NULL);
3929
3930 return 0;
3931}
3932
3933
3934void hostapd_dpp_push_button_stop(struct hostapd_data *hapd)
3935{
3936 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3937
3938 if (!ifaces || !ifaces->dpp)
3939 return;
3940 eloop_cancel_timeout(hostapd_dpp_push_button_expire, hapd, NULL);
3941 if (hostapd_dpp_pb_active(hapd)) {
3942 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
3943 if (!ifaces->dpp_pb_result_indicated)
3944 wpa_msg(hapd->msg_ctx, MSG_INFO,
3945 DPP_EVENT_PB_RESULT "failed");
3946 }
3947 ifaces->dpp_pb_time.sec = 0;
3948 ifaces->dpp_pb_time.usec = 0;
3949 dpp_pkex_free(hapd->dpp_pkex);
3950 hapd->dpp_pkex = NULL;
3951 os_free(hapd->dpp_pkex_auth_cmd);
3952 hapd->dpp_pkex_auth_cmd = NULL;
3953
3954 if (ifaces->dpp_pb_bi) {
3955 char id[20];
3956
3957 os_snprintf(id, sizeof(id), "%u", ifaces->dpp_pb_bi->id);
3958 dpp_bootstrap_remove(ifaces->dpp, id);
3959 ifaces->dpp_pb_bi = NULL;
3960 }
3961
3962 ifaces->dpp_pb_result_indicated = false;
3963
3964 str_clear_free(ifaces->dpp_pb_cmd);
3965 ifaces->dpp_pb_cmd = NULL;
3966}
3967
3968#endif /* CONFIG_DPP3 */
3969
3970
3971#ifdef CONFIG_DPP2
3972bool hostapd_dpp_configurator_connectivity(struct hostapd_data *hapd)
3973{
3974 return hapd->conf->dpp_configurator_connectivity ||
3975 (hapd->iface->interfaces &&
3976 dpp_relay_controller_available(hapd->iface->interfaces->dpp));
3977}
3978#endif /* CONFIG_DPP2 */