blob: 3dc463992544f0986ccc208b9302ec85ae09ae29 [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 Ravib0ac25f2024-07-12 01:42:03 +0000542 if (hapd->dpp_auth_ok_on_ack) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700543 hostapd_dpp_auth_success(hapd, 1);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000544 if (!hapd->dpp_auth) {
545 /* The authentication session could have been removed in
546 * some error cases, e.g., when starting GAS client and
547 * failing to send the initial request. */
548 return;
549 }
550 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700551
552 if (!is_broadcast_ether_addr(dst) && !ok) {
553 wpa_printf(MSG_DEBUG,
554 "DPP: Unicast DPP Action frame was not ACKed");
555 if (auth->waiting_auth_resp) {
556 /* In case of DPP Authentication Request frame, move to
557 * the next channel immediately. */
558 hostapd_drv_send_action_cancel_wait(hapd);
559 hostapd_dpp_auth_init_next(hapd);
560 return;
561 }
562 if (auth->waiting_auth_conf) {
563 hostapd_dpp_auth_resp_retry(hapd);
564 return;
565 }
566 }
567
Hai Shalom60840252021-02-19 19:02:11 -0800568 if (auth->waiting_auth_conf &&
569 auth->auth_resp_status == DPP_STATUS_OK) {
570 /* Make sure we do not get stuck waiting for Auth Confirm
571 * indefinitely after successfully transmitted Auth Response to
572 * allow new authentication exchanges to be started. */
573 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd,
574 NULL);
575 eloop_register_timeout(1, 0, hostapd_dpp_auth_conf_wait_timeout,
576 hapd, NULL);
577 }
578
Roshan Pius3a1667e2018-07-03 15:17:14 -0700579 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
580 /* Allow timeout handling to stop iteration if no response is
581 * received from a peer that has ACKed a request. */
582 auth->auth_req_ack = 1;
583 }
584
585 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
586 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
587 wpa_printf(MSG_DEBUG,
588 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
589 hapd->dpp_auth->curr_freq,
590 hapd->dpp_auth->neg_freq);
591 hostapd_drv_send_action_cancel_wait(hapd);
592
593 if (hapd->dpp_auth->neg_freq !=
594 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
595 /* TODO: Listen operation on non-operating channel */
596 wpa_printf(MSG_INFO,
597 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
598 hapd->dpp_auth->neg_freq, hapd->iface->freq);
599 }
600 }
601
602 if (hapd->dpp_auth_ok_on_ack)
603 hapd->dpp_auth_ok_on_ack = 0;
604}
605
606
607static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
608{
609 struct hostapd_data *hapd = eloop_ctx;
610 struct dpp_authentication *auth = hapd->dpp_auth;
611 unsigned int freq;
612 struct os_reltime now, diff;
613 unsigned int wait_time, diff_ms;
614
615 if (!auth || !auth->waiting_auth_resp)
616 return;
617
618 wait_time = hapd->dpp_resp_wait_time ?
619 hapd->dpp_resp_wait_time : 2000;
620 os_get_reltime(&now);
621 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
622 diff_ms = diff.sec * 1000 + diff.usec / 1000;
623 wpa_printf(MSG_DEBUG,
624 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
625 wait_time, diff_ms);
626
627 if (auth->auth_req_ack && diff_ms >= wait_time) {
628 /* Peer ACK'ed Authentication Request frame, but did not reply
629 * with Authentication Response frame within two seconds. */
630 wpa_printf(MSG_INFO,
631 "DPP: No response received from responder - stopping initiation attempt");
632 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
633 hostapd_drv_send_action_cancel_wait(hapd);
634 hostapd_dpp_listen_stop(hapd);
635 dpp_auth_deinit(auth);
636 hapd->dpp_auth = NULL;
637 return;
638 }
639
640 if (diff_ms >= wait_time) {
641 /* Authentication Request frame was not ACK'ed and no reply
642 * was receiving within two seconds. */
643 wpa_printf(MSG_DEBUG,
644 "DPP: Continue Initiator channel iteration");
645 hostapd_drv_send_action_cancel_wait(hapd);
646 hostapd_dpp_listen_stop(hapd);
647 hostapd_dpp_auth_init_next(hapd);
648 return;
649 }
650
651 /* Driver did not support 2000 ms long wait_time with TX command, so
652 * schedule listen operation to continue waiting for the response.
653 *
654 * DPP listen operations continue until stopped, so simply schedule a
655 * new call to this function at the point when the two second reply
656 * wait has expired. */
657 wait_time -= diff_ms;
658
659 freq = auth->curr_freq;
660 if (auth->neg_freq > 0)
661 freq = auth->neg_freq;
662 wpa_printf(MSG_DEBUG,
663 "DPP: Continue reply wait on channel %u MHz for %u ms",
664 freq, wait_time);
665 hapd->dpp_in_response_listen = 1;
666
667 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
668 /* TODO: Listen operation on non-operating channel */
669 wpa_printf(MSG_INFO,
670 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
671 freq, hapd->iface->freq);
672 }
673
674 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
675 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700676}
677
678
Hai Shalom60840252021-02-19 19:02:11 -0800679static void hostapd_dpp_auth_conf_wait_timeout(void *eloop_ctx,
680 void *timeout_ctx)
681{
682 struct hostapd_data *hapd = eloop_ctx;
683 struct dpp_authentication *auth = hapd->dpp_auth;
684
685 if (!auth || !auth->waiting_auth_conf)
686 return;
687
688 wpa_printf(MSG_DEBUG,
689 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
690 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
691 "No Auth Confirm received");
692 hostapd_drv_send_action_cancel_wait(hapd);
693 dpp_auth_deinit(auth);
694 hapd->dpp_auth = NULL;
695}
696
697
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700698static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
699 struct dpp_authentication *auth)
700{
701#ifdef CONFIG_TESTING_OPTIONS
702 if (hapd->dpp_config_obj_override)
703 auth->config_obj_override =
704 os_strdup(hapd->dpp_config_obj_override);
705 if (hapd->dpp_discovery_override)
706 auth->discovery_override =
707 os_strdup(hapd->dpp_discovery_override);
708 if (hapd->dpp_groups_override)
709 auth->groups_override = os_strdup(hapd->dpp_groups_override);
710 auth->ignore_netaccesskey_mismatch =
711 hapd->dpp_ignore_netaccesskey_mismatch;
712#endif /* CONFIG_TESTING_OPTIONS */
713}
714
715
Roshan Pius3a1667e2018-07-03 15:17:14 -0700716static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
717{
718 struct hostapd_data *hapd = eloop_ctx;
719
720 if (!hapd->dpp_auth)
721 return;
722 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
723 hostapd_dpp_auth_init_next(hapd);
724}
725
726
727static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
728{
729 struct dpp_authentication *auth = hapd->dpp_auth;
730 const u8 *dst;
731 unsigned int wait_time, max_wait_time, freq, max_tries, used;
732 struct os_reltime now, diff;
733
734 if (!auth)
735 return -1;
736
737 if (auth->freq_idx == 0)
738 os_get_reltime(&hapd->dpp_init_iter_start);
739
740 if (auth->freq_idx >= auth->num_freq) {
741 auth->num_freq_iters++;
742 if (hapd->dpp_init_max_tries)
743 max_tries = hapd->dpp_init_max_tries;
744 else
745 max_tries = 5;
746 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
747 wpa_printf(MSG_INFO,
748 "DPP: No response received from responder - stopping initiation attempt");
749 wpa_msg(hapd->msg_ctx, MSG_INFO,
750 DPP_EVENT_AUTH_INIT_FAILED);
751 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
752 hapd, NULL);
753 hostapd_drv_send_action_cancel_wait(hapd);
754 dpp_auth_deinit(hapd->dpp_auth);
755 hapd->dpp_auth = NULL;
756 return -1;
757 }
758 auth->freq_idx = 0;
759 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
760 if (hapd->dpp_init_retry_time)
761 wait_time = hapd->dpp_init_retry_time;
762 else
763 wait_time = 10000;
764 os_get_reltime(&now);
765 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
766 used = diff.sec * 1000 + diff.usec / 1000;
767 if (used > wait_time)
768 wait_time = 0;
769 else
770 wait_time -= used;
771 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
772 wait_time);
773 eloop_register_timeout(wait_time / 1000,
774 (wait_time % 1000) * 1000,
775 hostapd_dpp_init_timeout, hapd,
776 NULL);
777 return 0;
778 }
779 freq = auth->freq[auth->freq_idx++];
780 auth->curr_freq = freq;
781
Hai Shalom60840252021-02-19 19:02:11 -0800782 if (!is_zero_ether_addr(auth->peer_mac_addr))
783 dst = auth->peer_mac_addr;
784 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700785 dst = broadcast;
786 else
787 dst = auth->peer_bi->mac_addr;
788 hapd->dpp_auth_ok_on_ack = 0;
789 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
790 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
791 max_wait_time = hapd->dpp_resp_wait_time ?
792 hapd->dpp_resp_wait_time : 2000;
793 if (wait_time > max_wait_time)
794 wait_time = max_wait_time;
795 wait_time += 10; /* give the driver some extra time to complete */
796 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
797 hostapd_dpp_reply_wait_timeout, hapd, NULL);
798 wait_time -= 10;
799 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
800 wpa_printf(MSG_DEBUG,
801 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
802 freq, auth->neg_freq);
803 }
804 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
805 " freq=%u type=%d",
806 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
807 auth->auth_req_ack = 0;
808 os_get_reltime(&hapd->dpp_last_init);
809 return hostapd_drv_send_action(hapd, freq, wait_time,
810 dst,
811 wpabuf_head(hapd->dpp_auth->req_msg),
812 wpabuf_len(hapd->dpp_auth->req_msg));
813}
814
815
Hai Shalom899fcc72020-10-19 14:38:18 -0700816#ifdef CONFIG_DPP2
817static int hostapd_dpp_process_conf_obj(void *ctx,
818 struct dpp_authentication *auth)
819{
820 struct hostapd_data *hapd = ctx;
821 unsigned int i;
822
823 for (i = 0; i < auth->num_conf_obj; i++)
824 hostapd_dpp_handle_config_obj(hapd, auth,
825 &auth->conf_obj[i]);
826
827 return 0;
828}
829#endif /* CONFIG_DPP2 */
830
831
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700832int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
833{
834 const char *pos;
835 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -0700836 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700837 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
838 unsigned int neg_freq = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700839 int tcp = 0;
840#ifdef CONFIG_DPP2
841 int tcp_port = DPP_TCP_PORT;
842 struct hostapd_ip_addr ipaddr;
843 char *addr;
844#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700845
846 pos = os_strstr(cmd, " peer=");
847 if (!pos)
848 return -1;
849 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700850 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700851 if (!peer_bi) {
852 wpa_printf(MSG_INFO,
853 "DPP: Could not find bootstrapping info for the identified peer");
854 return -1;
855 }
856
Hai Shalom899fcc72020-10-19 14:38:18 -0700857#ifdef CONFIG_DPP2
858 pos = os_strstr(cmd, " tcp_port=");
859 if (pos) {
860 pos += 10;
861 tcp_port = atoi(pos);
862 }
863
864 addr = get_param(cmd, " tcp_addr=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000865 if (addr && os_strcmp(addr, "from-uri") == 0) {
866 os_free(addr);
867 if (!peer_bi->host) {
868 wpa_printf(MSG_INFO,
869 "DPP: TCP address not available in peer URI");
870 return -1;
871 }
872 tcp = 1;
873 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
874 tcp_port = peer_bi->port;
875 } else if (addr) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700876 int res;
877
878 res = hostapd_parse_ip_addr(addr, &ipaddr);
879 os_free(addr);
880 if (res)
881 return -1;
882 tcp = 1;
883 }
884#endif /* CONFIG_DPP2 */
885
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700886 pos = os_strstr(cmd, " own=");
887 if (pos) {
888 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700889 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
890 atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700891 if (!own_bi) {
892 wpa_printf(MSG_INFO,
893 "DPP: Could not find bootstrapping info for the identified local entry");
894 return -1;
895 }
896
897 if (peer_bi->curve != own_bi->curve) {
898 wpa_printf(MSG_INFO,
899 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
900 peer_bi->curve->name, own_bi->curve->name);
901 return -1;
902 }
903 }
904
905 pos = os_strstr(cmd, " role=");
906 if (pos) {
907 pos += 6;
908 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700909 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700910 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700911 allowed_roles = DPP_CAPAB_ENROLLEE;
912 else if (os_strncmp(pos, "either", 6) == 0)
913 allowed_roles = DPP_CAPAB_CONFIGURATOR |
914 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700915 else
916 goto fail;
917 }
918
Roshan Pius3a1667e2018-07-03 15:17:14 -0700919 pos = os_strstr(cmd, " neg_freq=");
920 if (pos)
921 neg_freq = atoi(pos + 10);
922
Hai Shalom899fcc72020-10-19 14:38:18 -0700923 if (!tcp && hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700924 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
925 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
926 hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800927 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout,
928 hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700929 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
930 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700931#ifdef CONFIG_DPP2
932 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
933 hapd, NULL);
934#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700935 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700936 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700937 }
938
Hai Shalom899fcc72020-10-19 14:38:18 -0700939 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
940 peer_bi, own_bi, allowed_roles, neg_freq,
941 hapd->iface->hw_features,
942 hapd->iface->num_hw_features);
943 if (!auth)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700944 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -0700945 hostapd_dpp_set_testing_options(hapd, auth);
946 if (dpp_set_configurator(auth, cmd) < 0) {
947 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800948 goto fail;
949 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700950
Hai Shalom899fcc72020-10-19 14:38:18 -0700951 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700952
Roshan Pius3a1667e2018-07-03 15:17:14 -0700953 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom899fcc72020-10-19 14:38:18 -0700954 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700955
Hai Shalom899fcc72020-10-19 14:38:18 -0700956#ifdef CONFIG_DPP2
957 if (tcp)
958 return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
959 &ipaddr, tcp_port, hapd->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -0700960 DPP_NETROLE_AP, hapd->conf->dpp_mud_url,
961 hapd->conf->dpp_extra_conf_req_name,
962 hapd->conf->dpp_extra_conf_req_value,
963 hapd->msg_ctx, hapd,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800964 hostapd_dpp_process_conf_obj, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -0700965#endif /* CONFIG_DPP2 */
966
967 hapd->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700968 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700969fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700970 return -1;
971}
972
973
Roshan Pius3a1667e2018-07-03 15:17:14 -0700974int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
975{
976 int freq;
977
978 freq = atoi(cmd);
979 if (freq <= 0)
980 return -1;
981
982 if (os_strstr(cmd, " role=configurator"))
983 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
984 else if (os_strstr(cmd, " role=enrollee"))
985 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
986 else
987 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
988 DPP_CAPAB_ENROLLEE;
989 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
990
991 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
992 /* TODO: Listen operation on non-operating channel */
993 wpa_printf(MSG_INFO,
994 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
995 freq, hapd->iface->freq);
996 return -1;
997 }
998
Hai Shalom60840252021-02-19 19:02:11 -0800999 hostapd_drv_dpp_listen(hapd, true);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001000 return 0;
1001}
1002
1003
1004void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
1005{
Hai Shalom60840252021-02-19 19:02:11 -08001006 hostapd_drv_dpp_listen(hapd, false);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001007 /* TODO: Stop listen operation on non-operating channel */
1008}
1009
1010
Sunil Ravi89eba102022-09-13 21:04:37 -07001011#ifdef CONFIG_DPP2
1012static void
1013hostapd_dpp_relay_needs_controller(struct hostapd_data *hapd, const u8 *src,
1014 enum dpp_public_action_frame_type type)
1015{
1016 struct os_reltime now;
1017
1018 if (!hapd->conf->dpp_relay_port)
1019 return;
1020
1021 os_get_reltime(&now);
1022 if (hapd->dpp_relay_last_needs_ctrl.sec &&
1023 !os_reltime_expired(&now, &hapd->dpp_relay_last_needs_ctrl, 60))
1024 return;
1025 hapd->dpp_relay_last_needs_ctrl = now;
1026 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RELAY_NEEDS_CONTROLLER
1027 MACSTR " %u", MAC2STR(src), type);
1028}
1029#endif /* CONFIG_DPP2 */
1030
1031
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001032static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
1033 const u8 *hdr, const u8 *buf, size_t len,
1034 unsigned int freq)
1035{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001036 const u8 *r_bootstrap, *i_bootstrap;
1037 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001038 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1039
1040 if (!hapd->iface->interfaces->dpp)
1041 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001042
1043 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1044 MAC2STR(src));
1045
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001046#ifdef CONFIG_DPP2
1047 hostapd_dpp_chirp_stop(hapd);
1048#endif /* CONFIG_DPP2 */
1049
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001050 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1051 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001052 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1053 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1054 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001055 return;
1056 }
1057 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1058 r_bootstrap, r_bootstrap_len);
1059
1060 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1061 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001062 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1063 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1064 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001065 return;
1066 }
1067 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1068 i_bootstrap, i_bootstrap_len);
1069
1070 /* Try to find own and peer bootstrapping key matches based on the
1071 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001072 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
1073 r_bootstrap, &own_bi, &peer_bi);
Hai Shalom81f62d82019-07-22 12:10:00 -07001074#ifdef CONFIG_DPP2
1075 if (!own_bi) {
1076 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1077 src, hdr, buf, len, freq, i_bootstrap,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001078 r_bootstrap, hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07001079 return;
Sunil Ravi89eba102022-09-13 21:04:37 -07001080 hostapd_dpp_relay_needs_controller(hapd, src,
1081 DPP_PA_AUTHENTICATION_REQ);
Hai Shalom81f62d82019-07-22 12:10:00 -07001082 }
1083#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001084 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001085 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1086 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001087 return;
1088 }
1089
Sunil Ravi89eba102022-09-13 21:04:37 -07001090 if (own_bi->type == DPP_BOOTSTRAP_PKEX) {
1091 if (!peer_bi || peer_bi->type != DPP_BOOTSTRAP_PKEX) {
1092 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1093 "No matching peer bootstrapping key found for PKEX - ignore message");
1094 return;
1095 }
1096
1097 if (os_memcmp(peer_bi->pubkey_hash, own_bi->peer_pubkey_hash,
1098 SHA256_MAC_LEN) != 0) {
1099 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1100 "Mismatching peer PKEX bootstrapping key - ignore message");
1101 return;
1102 }
1103 }
1104
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001105 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001106 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1107 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001108 return;
1109 }
1110
1111 hapd->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001112 hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
1113 hapd->msg_ctx, hapd->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001114 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001115 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001116 if (!hapd->dpp_auth) {
1117 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1118 return;
1119 }
1120 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001121 if (dpp_set_configurator(hapd->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001122 hapd->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001123 dpp_auth_deinit(hapd->dpp_auth);
1124 hapd->dpp_auth = NULL;
1125 return;
1126 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001127 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1128
Roshan Pius3a1667e2018-07-03 15:17:14 -07001129 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1130 " freq=%u type=%d",
1131 MAC2STR(src), hapd->dpp_auth->curr_freq,
1132 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001133 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
1134 src, wpabuf_head(hapd->dpp_auth->resp_msg),
1135 wpabuf_len(hapd->dpp_auth->resp_msg));
1136}
1137
1138
Roshan Pius3a1667e2018-07-03 15:17:14 -07001139static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
Hai Shalomc3565922019-10-28 11:58:20 -07001140 struct dpp_authentication *auth,
1141 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001142{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001143 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001144 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001145 dpp_akm_str(conf->akm));
1146 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001147 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001148 wpa_ssid_txt(conf->ssid, conf->ssid_len));
1149 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001150 /* TODO: Save the Connector and consider using a command
1151 * to fetch the value instead of sending an event with
1152 * it. The Connector could end up being larger than what
1153 * most clients are ready to receive as an event
1154 * message. */
1155 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001156 conf->connector);
Hai Shalomfdcde762020-04-02 11:19:20 -07001157 }
1158 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001159 char hex[64 * 2 + 1];
1160
1161 wpa_snprintf_hex(hex, sizeof(hex),
Hai Shalomc3565922019-10-28 11:58:20 -07001162 (const u8 *) conf->passphrase,
1163 os_strlen(conf->passphrase));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001164 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1165 hex);
Hai Shalomc3565922019-10-28 11:58:20 -07001166 } else if (conf->psk_set) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001167 char hex[PMK_LEN * 2 + 1];
1168
Hai Shalomc3565922019-10-28 11:58:20 -07001169 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001170 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1171 hex);
1172 }
Hai Shalomc3565922019-10-28 11:58:20 -07001173 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001174 char *hex;
1175 size_t hexlen;
1176
Hai Shalomc3565922019-10-28 11:58:20 -07001177 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001178 hex = os_malloc(hexlen);
1179 if (hex) {
1180 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001181 wpabuf_head(conf->c_sign_key),
1182 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001183 wpa_msg(hapd->msg_ctx, MSG_INFO,
1184 DPP_EVENT_C_SIGN_KEY "%s", hex);
1185 os_free(hex);
1186 }
1187 }
1188 if (auth->net_access_key) {
1189 char *hex;
1190 size_t hexlen;
1191
1192 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1193 hex = os_malloc(hexlen);
1194 if (hex) {
1195 wpa_snprintf_hex(hex, hexlen,
1196 wpabuf_head(auth->net_access_key),
1197 wpabuf_len(auth->net_access_key));
1198 if (auth->net_access_key_expiry)
1199 wpa_msg(hapd->msg_ctx, MSG_INFO,
1200 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1201 (unsigned long)
1202 auth->net_access_key_expiry);
1203 else
1204 wpa_msg(hapd->msg_ctx, MSG_INFO,
1205 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1206 os_free(hex);
1207 }
1208 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001209}
1210
1211
Hai Shalomfdcde762020-04-02 11:19:20 -07001212static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
1213 struct dpp_asymmetric_key *key)
1214{
1215#ifdef CONFIG_DPP2
1216 int res;
1217
1218 if (!key)
1219 return 0;
1220
1221 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1222 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
1223
1224 while (key) {
1225 res = dpp_configurator_from_backup(
1226 hapd->iface->interfaces->dpp, key);
1227 if (res < 0)
1228 return -1;
1229 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1230 res);
1231 key = key->next;
1232 }
1233#endif /* CONFIG_DPP2 */
1234
1235 return 0;
1236}
1237
1238
Sunil Ravia04bd252022-05-02 22:54:18 -07001239#ifdef CONFIG_DPP3
1240static void hostapd_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1241{
1242 struct hostapd_data *hapd = eloop_ctx;
1243 struct dpp_authentication *auth = hapd->dpp_auth;
1244
1245 if (!auth || !auth->waiting_new_key)
1246 return;
1247
1248 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1249 hostapd_dpp_start_gas_client(hapd);
1250}
1251#endif /* CONFIG_DPP3 */
1252
1253
Roshan Pius3a1667e2018-07-03 15:17:14 -07001254static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1255 enum gas_query_ap_result result,
1256 const struct wpabuf *adv_proto,
1257 const struct wpabuf *resp, u16 status_code)
1258{
1259 struct hostapd_data *hapd = ctx;
1260 const u8 *pos;
1261 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001262 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Sunil Ravia04bd252022-05-02 22:54:18 -07001263 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001264
1265 if (!auth || !auth->auth_success) {
1266 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1267 return;
1268 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001269 if (result != GAS_QUERY_AP_SUCCESS ||
1270 !resp || status_code != WLAN_STATUS_SUCCESS) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001271 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1272 goto fail;
1273 }
1274
1275 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1276 adv_proto);
1277 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1278 resp);
1279
1280 if (wpabuf_len(adv_proto) != 10 ||
1281 !(pos = wpabuf_head(adv_proto)) ||
1282 pos[0] != WLAN_EID_ADV_PROTO ||
1283 pos[1] != 8 ||
1284 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1285 pos[4] != 5 ||
1286 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1287 pos[8] != 0x1a ||
1288 pos[9] != 1) {
1289 wpa_printf(MSG_DEBUG,
1290 "DPP: Not a DPP Advertisement Protocol ID");
1291 goto fail;
1292 }
1293
Sunil Ravia04bd252022-05-02 22:54:18 -07001294 res = dpp_conf_resp_rx(auth, resp);
1295#ifdef CONFIG_DPP3
1296 if (res == -3) {
1297 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1298 eloop_register_timeout(0, 0, hostapd_dpp_build_new_key, hapd,
1299 NULL);
1300 return;
1301 }
1302#endif /* CONFIG_DPP3 */
1303 if (res < 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001304 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1305 goto fail;
1306 }
1307
Hai Shalomc3565922019-10-28 11:58:20 -07001308 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Hai Shalomfdcde762020-04-02 11:19:20 -07001309 if (hostapd_dpp_handle_key_pkg(hapd, auth->conf_key_pkg) < 0)
1310 goto fail;
1311
Hai Shalom021b0b52019-04-10 11:17:58 -07001312 status = DPP_STATUS_OK;
1313#ifdef CONFIG_TESTING_OPTIONS
1314 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1315 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1316 status = DPP_STATUS_CONFIG_REJECTED;
1317 }
1318#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001319fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001320 if (status != DPP_STATUS_OK)
1321 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1322#ifdef CONFIG_DPP2
1323 if (auth->peer_version >= 2 &&
1324 auth->conf_resp_status == DPP_STATUS_OK) {
1325 struct wpabuf *msg;
1326
1327 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1328 msg = dpp_build_conf_result(auth, status);
1329 if (!msg)
1330 goto fail2;
1331
1332 wpa_msg(hapd->msg_ctx, MSG_INFO,
1333 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1334 MAC2STR(addr), auth->curr_freq,
1335 DPP_PA_CONFIGURATION_RESULT);
1336 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
1337 addr, wpabuf_head(msg),
1338 wpabuf_len(msg));
1339 wpabuf_free(msg);
1340
1341 /* This exchange will be terminated in the TX status handler */
1342 auth->connect_on_tx_status = 1;
1343 return;
1344 }
1345fail2:
1346#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001347 dpp_auth_deinit(hapd->dpp_auth);
1348 hapd->dpp_auth = NULL;
1349}
1350
1351
1352static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
1353{
1354 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001355 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001356 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001357
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001358 buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
1359 DPP_NETROLE_AP,
Sunil Ravi89eba102022-09-13 21:04:37 -07001360 hapd->conf->dpp_mud_url, NULL,
1361 hapd->conf->dpp_extra_conf_req_name,
1362 hapd->conf->dpp_extra_conf_req_value);
Hai Shalom021b0b52019-04-10 11:17:58 -07001363 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001364 wpa_printf(MSG_DEBUG,
1365 "DPP: No configuration request data available");
1366 return;
1367 }
1368
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001369 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1370 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1371
1372 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
1373 buf, hostapd_dpp_gas_resp_cb, hapd);
1374 if (res < 0) {
1375 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1376 "GAS: Failed to send Query Request");
1377 wpabuf_free(buf);
1378 } else {
1379 wpa_printf(MSG_DEBUG,
1380 "DPP: GAS query started with dialog token %u", res);
1381 }
1382}
1383
1384
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00001385static void hostapd_gas_req_wait(void *eloop_ctx, void *timeout_ctx)
1386{
1387 struct hostapd_data *hapd = eloop_ctx;
1388 struct dpp_authentication *auth = hapd->dpp_auth;
1389
1390 if (!auth)
1391 return;
1392
1393 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Request");
1394 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1395 dpp_auth_deinit(auth);
1396 hapd->dpp_auth = NULL;
1397}
1398
1399
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001400static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
1401{
1402 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001403 dpp_notify_auth_success(hapd->dpp_auth, initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001404#ifdef CONFIG_TESTING_OPTIONS
1405 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1406 wpa_printf(MSG_INFO,
1407 "DPP: TESTING - stop at Authentication Confirm");
1408 if (hapd->dpp_auth->configurator) {
1409 /* Prevent GAS response */
1410 hapd->dpp_auth->auth_success = 0;
1411 }
1412 return;
1413 }
1414#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001415
1416 if (!hapd->dpp_auth->configurator)
1417 hostapd_dpp_start_gas_client(hapd);
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00001418 else
1419 eloop_register_timeout(10, 0, hostapd_gas_req_wait,
1420 hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001421}
1422
1423
1424static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001425 const u8 *hdr, const u8 *buf, size_t len,
1426 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001427{
1428 struct dpp_authentication *auth = hapd->dpp_auth;
1429 struct wpabuf *msg;
1430
1431 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
1432 MAC2STR(src));
1433
1434 if (!auth) {
1435 wpa_printf(MSG_DEBUG,
1436 "DPP: No DPP Authentication in progress - drop");
1437 return;
1438 }
1439
1440 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001441 !ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001442 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1443 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1444 return;
1445 }
1446
Roshan Pius3a1667e2018-07-03 15:17:14 -07001447 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1448
1449 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1450 wpa_printf(MSG_DEBUG,
1451 "DPP: Responder accepted request for different negotiation channel");
1452 auth->curr_freq = freq;
1453 }
1454
1455 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001456 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1457 if (!msg) {
1458 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1459 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
1460 return;
1461 }
1462 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1463 return;
1464 }
1465 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1466
Roshan Pius3a1667e2018-07-03 15:17:14 -07001467 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1468 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
1469 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001470 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
1471 wpabuf_head(msg), wpabuf_len(msg));
1472 wpabuf_free(msg);
1473 hapd->dpp_auth_ok_on_ack = 1;
1474}
1475
1476
1477static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1478 const u8 *hdr, const u8 *buf, size_t len)
1479{
1480 struct dpp_authentication *auth = hapd->dpp_auth;
1481
1482 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1483 MAC2STR(src));
1484
1485 if (!auth) {
1486 wpa_printf(MSG_DEBUG,
1487 "DPP: No DPP Authentication in progress - drop");
1488 return;
1489 }
1490
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001491 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001492 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1493 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1494 return;
1495 }
1496
1497 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1498 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1499 return;
1500 }
1501
1502 hostapd_dpp_auth_success(hapd, 0);
1503}
1504
1505
Hai Shalom021b0b52019-04-10 11:17:58 -07001506#ifdef CONFIG_DPP2
1507
1508static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
1509 void *timeout_ctx)
1510{
1511 struct hostapd_data *hapd = eloop_ctx;
1512 struct dpp_authentication *auth = hapd->dpp_auth;
1513
1514 if (!auth || !auth->waiting_conf_result)
1515 return;
1516
1517 wpa_printf(MSG_DEBUG,
1518 "DPP: Timeout while waiting for Configuration Result");
1519 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1520 dpp_auth_deinit(auth);
1521 hapd->dpp_auth = NULL;
1522}
1523
1524
Hai Shalomc3565922019-10-28 11:58:20 -07001525static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1526 void *timeout_ctx)
1527{
1528 struct hostapd_data *hapd = eloop_ctx;
1529 struct dpp_authentication *auth = hapd->dpp_auth;
1530
1531 if (!auth || !auth->waiting_conf_result)
1532 return;
1533
1534 wpa_printf(MSG_DEBUG,
1535 "DPP: Timeout while waiting for Connection Status Result");
1536 wpa_msg(hapd->msg_ctx, MSG_INFO,
1537 DPP_EVENT_CONN_STATUS_RESULT "timeout");
1538 dpp_auth_deinit(auth);
1539 hapd->dpp_auth = NULL;
1540}
1541
1542
Sunil Ravi89eba102022-09-13 21:04:37 -07001543#ifdef CONFIG_DPP3
1544
1545static bool hostapd_dpp_pb_active(struct hostapd_data *hapd)
1546{
1547 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1548
1549 return ifaces && (ifaces->dpp_pb_time.sec ||
1550 ifaces->dpp_pb_time.usec);
1551}
1552
1553
1554static void hostapd_dpp_remove_pb_hash(struct hostapd_data *hapd)
1555{
1556 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1557 int i;
1558
1559 if (!ifaces->dpp_pb_bi)
1560 return;
1561 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
1562 struct dpp_pb_info *info = &ifaces->dpp_pb[i];
1563
1564 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
1565 continue;
1566 if (os_memcmp(info->hash, ifaces->dpp_pb_resp_hash,
1567 SHA256_MAC_LEN) == 0) {
1568 /* Allow a new push button session to be established
1569 * immediately without the successfully completed
1570 * session triggering session overlap. */
1571 info->rx_time.sec = 0;
1572 info->rx_time.usec = 0;
1573 wpa_printf(MSG_DEBUG,
1574 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
1575 }
1576 }
1577}
1578
1579#endif /* CONFIG_DPP3 */
1580
1581
Hai Shalom021b0b52019-04-10 11:17:58 -07001582static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
1583 const u8 *hdr, const u8 *buf, size_t len)
1584{
1585 struct dpp_authentication *auth = hapd->dpp_auth;
1586 enum dpp_status_error status;
Sunil Ravi89eba102022-09-13 21:04:37 -07001587#ifdef CONFIG_DPP3
1588 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
1589#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001590
1591 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1592 MAC2STR(src));
1593
1594 if (!auth || !auth->waiting_conf_result) {
1595 wpa_printf(MSG_DEBUG,
1596 "DPP: No DPP Configuration waiting for result - drop");
1597 return;
1598 }
1599
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001600 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001601 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1602 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1603 return;
1604 }
1605
1606 status = dpp_conf_result_rx(auth, hdr, buf, len);
1607
Hai Shalomc3565922019-10-28 11:58:20 -07001608 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1609 wpa_msg(hapd->msg_ctx, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07001610 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
1611 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07001612 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1613 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1614 hapd, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001615 auth->waiting_conn_status_result = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001616 eloop_cancel_timeout(
1617 hostapd_dpp_conn_status_result_wait_timeout,
1618 hapd, NULL);
1619 eloop_register_timeout(
1620 16, 0, hostapd_dpp_conn_status_result_wait_timeout,
1621 hapd, NULL);
1622 return;
1623 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001624 hostapd_drv_send_action_cancel_wait(hapd);
1625 hostapd_dpp_listen_stop(hapd);
1626 if (status == DPP_STATUS_OK)
Sunil Ravi89eba102022-09-13 21:04:37 -07001627 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
1628 "conf_status=%d", auth->conf_resp_status);
Hai Shalom021b0b52019-04-10 11:17:58 -07001629 else
1630 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1631 dpp_auth_deinit(auth);
1632 hapd->dpp_auth = NULL;
1633 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1634 NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07001635#ifdef CONFIG_DPP3
1636 if (!ifaces->dpp_pb_result_indicated && hostapd_dpp_pb_active(hapd)) {
1637 if (status == DPP_STATUS_OK)
1638 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
1639 "success");
1640 else
1641 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
1642 "no-configuration-available");
1643 ifaces->dpp_pb_result_indicated = true;
1644 if (status == DPP_STATUS_OK)
1645 hostapd_dpp_remove_pb_hash(hapd);
1646 hostapd_dpp_push_button_stop(hapd);
1647 }
1648#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07001649}
1650
Hai Shalomc3565922019-10-28 11:58:20 -07001651
1652static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
1653 const u8 *src, const u8 *hdr,
1654 const u8 *buf, size_t len)
1655{
1656 struct dpp_authentication *auth = hapd->dpp_auth;
1657 enum dpp_status_error status;
1658 u8 ssid[SSID_MAX_LEN];
1659 size_t ssid_len = 0;
1660 char *channel_list = NULL;
1661
1662 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1663
1664 if (!auth || !auth->waiting_conn_status_result) {
1665 wpa_printf(MSG_DEBUG,
1666 "DPP: No DPP Configuration waiting for connection status result - drop");
1667 return;
1668 }
1669
1670 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1671 ssid, &ssid_len, &channel_list);
1672 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1673 "result=%d ssid=%s channel_list=%s",
1674 status, wpa_ssid_txt(ssid, ssid_len),
1675 channel_list ? channel_list : "N/A");
1676 os_free(channel_list);
1677 hostapd_drv_send_action_cancel_wait(hapd);
1678 hostapd_dpp_listen_stop(hapd);
1679 dpp_auth_deinit(auth);
1680 hapd->dpp_auth = NULL;
1681 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
1682 hapd, NULL);
1683}
1684
1685
Hai Shalomfdcde762020-04-02 11:19:20 -07001686static void
1687hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
1688 const u8 *hdr, const u8 *buf, size_t len,
1689 unsigned int freq)
1690{
1691 const u8 *r_bootstrap;
1692 u16 r_bootstrap_len;
1693 struct dpp_bootstrap_info *peer_bi;
1694 struct dpp_authentication *auth;
1695
1696 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
1697 MAC2STR(src));
1698
1699 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1700 &r_bootstrap_len);
1701 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1702 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1703 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1704 return;
1705 }
1706 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1707 r_bootstrap, r_bootstrap_len);
1708 peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
1709 r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07001710 dpp_notify_chirp_received(hapd->msg_ctx,
1711 peer_bi ? (int) peer_bi->id : -1,
1712 src, freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07001713 if (!peer_bi) {
1714 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1715 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001716 r_bootstrap, hapd) == 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07001717 return;
1718 wpa_printf(MSG_DEBUG,
1719 "DPP: No matching bootstrapping information found");
Sunil Ravi89eba102022-09-13 21:04:37 -07001720 hostapd_dpp_relay_needs_controller(
1721 hapd, src, DPP_PA_PRESENCE_ANNOUNCEMENT);
Hai Shalomfdcde762020-04-02 11:19:20 -07001722 return;
1723 }
1724
1725 if (hapd->dpp_auth) {
1726 wpa_printf(MSG_DEBUG,
1727 "DPP: Ignore Presence Announcement during ongoing Authentication");
1728 return;
1729 }
1730
1731 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1732 peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
1733 0);
1734 if (!auth)
1735 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07001736 hostapd_dpp_set_testing_options(hapd, auth);
1737 if (dpp_set_configurator(auth,
Hai Shalomfdcde762020-04-02 11:19:20 -07001738 hapd->dpp_configurator_params) < 0) {
1739 dpp_auth_deinit(auth);
1740 return;
1741 }
1742
1743 auth->neg_freq = freq;
1744
Hai Shalom60840252021-02-19 19:02:11 -08001745 /* The source address of the Presence Announcement frame overrides any
1746 * MAC address information from the bootstrapping information. */
1747 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07001748
1749 hapd->dpp_auth = auth;
1750 if (hostapd_dpp_auth_init_next(hapd) < 0) {
1751 dpp_auth_deinit(hapd->dpp_auth);
1752 hapd->dpp_auth = NULL;
1753 }
1754}
1755
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001756
1757static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
1758 void *timeout_ctx)
1759{
1760 struct hostapd_data *hapd = eloop_ctx;
1761 struct dpp_authentication *auth = hapd->dpp_auth;
1762
1763 if (!auth)
1764 return;
1765
1766 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
1767 hostapd_dpp_listen_stop(hapd);
1768 dpp_auth_deinit(auth);
1769 hapd->dpp_auth = NULL;
1770}
1771
1772
1773static void
1774hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
1775 const u8 *hdr, const u8 *buf, size_t len,
1776 unsigned int freq)
1777{
Hai Shalom899fcc72020-10-19 14:38:18 -07001778 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
1779 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001780 struct dpp_configurator *conf;
1781 struct dpp_authentication *auth;
1782 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07001783 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001784
1785 if (hapd->dpp_auth) {
1786 wpa_printf(MSG_DEBUG,
1787 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1788 return;
1789 }
1790
1791 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
1792 MAC2STR(src));
1793
1794 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1795 &csign_hash_len);
1796 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
1797 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1798 "Missing or invalid required Configurator C-sign key Hash attribute");
1799 return;
1800 }
1801 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1802 csign_hash, csign_hash_len);
1803 conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
1804 csign_hash);
1805 if (!conf) {
1806 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1807 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001808 NULL, hapd) == 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001809 return;
1810 wpa_printf(MSG_DEBUG,
1811 "DPP: No matching Configurator information found");
Sunil Ravi89eba102022-09-13 21:04:37 -07001812 hostapd_dpp_relay_needs_controller(
1813 hapd, src, DPP_PA_RECONFIG_ANNOUNCEMENT);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001814 return;
1815 }
1816
Hai Shalom899fcc72020-10-19 14:38:18 -07001817 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
1818 &fcgroup_len);
1819 if (!fcgroup || fcgroup_len != 2) {
1820 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1821 "Missing or invalid required Finite Cyclic Group attribute");
1822 return;
1823 }
1824 group = WPA_GET_LE16(fcgroup);
1825 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
1826
1827 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
1828 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
1829
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001830 auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
Hai Shalom899fcc72020-10-19 14:38:18 -07001831 conf, freq, group, a_nonce, a_nonce_len,
1832 e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001833 if (!auth)
1834 return;
1835 hostapd_dpp_set_testing_options(hapd, auth);
1836 if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
1837 dpp_auth_deinit(auth);
1838 return;
1839 }
1840
1841 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1842 hapd->dpp_auth = auth;
1843
1844 hapd->dpp_in_response_listen = 0;
1845 hapd->dpp_auth_ok_on_ack = 0;
1846 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
1847 max_wait_time = hapd->dpp_resp_wait_time ?
1848 hapd->dpp_resp_wait_time : 2000;
1849 if (wait_time > max_wait_time)
1850 wait_time = max_wait_time;
1851 wait_time += 10; /* give the driver some extra time to complete */
1852 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
1853 hostapd_dpp_reconfig_reply_wait_timeout,
1854 hapd, NULL);
1855 wait_time -= 10;
1856
1857 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1858 " freq=%u type=%d",
1859 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
1860 if (hostapd_drv_send_action(hapd, freq, wait_time, src,
1861 wpabuf_head(auth->reconfig_req_msg),
1862 wpabuf_len(auth->reconfig_req_msg)) < 0) {
1863 dpp_auth_deinit(hapd->dpp_auth);
1864 hapd->dpp_auth = NULL;
1865 }
1866}
1867
1868
1869static void
1870hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
1871 const u8 *hdr, const u8 *buf, size_t len,
1872 unsigned int freq)
1873{
1874 struct dpp_authentication *auth = hapd->dpp_auth;
1875 struct wpabuf *conf;
1876
1877 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
1878 MACSTR, MAC2STR(src));
1879
1880 if (!auth || !auth->reconfig || !auth->configurator) {
1881 wpa_printf(MSG_DEBUG,
1882 "DPP: No DPP Reconfig Authentication in progress - drop");
1883 return;
1884 }
1885
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001886 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001887 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1888 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1889 return;
1890 }
1891
1892 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
1893 if (!conf)
1894 return;
1895
1896 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1897 hapd, NULL);
1898
1899 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1900 " freq=%u type=%d",
1901 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
1902 if (hostapd_drv_send_action(hapd, freq, 500, src,
1903 wpabuf_head(conf), wpabuf_len(conf)) < 0) {
1904 wpabuf_free(conf);
1905 dpp_auth_deinit(hapd->dpp_auth);
1906 hapd->dpp_auth = NULL;
1907 return;
1908 }
1909 wpabuf_free(conf);
1910}
1911
Hai Shalom021b0b52019-04-10 11:17:58 -07001912#endif /* CONFIG_DPP2 */
1913
1914
Roshan Pius3a1667e2018-07-03 15:17:14 -07001915static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1916 const u8 *src, unsigned int freq,
1917 u8 trans_id,
1918 enum dpp_status_error status)
1919{
1920 struct wpabuf *msg;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001921 size_t len;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001922
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001923 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
1924#ifdef CONFIG_DPP2
1925 len += 5;
1926#endif /* CONFIG_DPP2 */
1927 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001928 if (!msg)
1929 return;
1930
1931#ifdef CONFIG_TESTING_OPTIONS
1932 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1933 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1934 goto skip_trans_id;
1935 }
1936 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1937 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1938 trans_id ^= 0x01;
1939 }
1940#endif /* CONFIG_TESTING_OPTIONS */
1941
1942 /* Transaction ID */
1943 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1944 wpabuf_put_le16(msg, 1);
1945 wpabuf_put_u8(msg, trans_id);
1946
1947#ifdef CONFIG_TESTING_OPTIONS
1948skip_trans_id:
1949 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1950 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1951 goto skip_status;
1952 }
1953 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1954 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1955 status = 254;
1956 }
1957#endif /* CONFIG_TESTING_OPTIONS */
1958
1959 /* DPP Status */
1960 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1961 wpabuf_put_le16(msg, 1);
1962 wpabuf_put_u8(msg, status);
1963
1964#ifdef CONFIG_TESTING_OPTIONS
1965skip_status:
1966 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1967 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1968 goto skip_connector;
1969 }
1970 if (status == DPP_STATUS_OK &&
1971 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1972 char *connector;
1973
1974 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1975 connector = dpp_corrupt_connector_signature(
1976 hapd->conf->dpp_connector);
1977 if (!connector) {
1978 wpabuf_free(msg);
1979 return;
1980 }
1981 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1982 wpabuf_put_le16(msg, os_strlen(connector));
1983 wpabuf_put_str(msg, connector);
1984 os_free(connector);
1985 goto skip_connector;
1986 }
1987#endif /* CONFIG_TESTING_OPTIONS */
1988
1989 /* DPP Connector */
1990 if (status == DPP_STATUS_OK) {
1991 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1992 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1993 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1994 }
1995
1996#ifdef CONFIG_TESTING_OPTIONS
1997skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001998 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP) {
1999 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
2000 goto skip_proto_ver;
2001 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002002#endif /* CONFIG_TESTING_OPTIONS */
2003
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002004#ifdef CONFIG_DPP2
2005 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002006 u8 ver = DPP_VERSION;
2007#ifdef CONFIG_DPP3
2008 int conn_ver;
2009
2010 conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
2011 if (conn_ver > 0 && ver != conn_ver) {
2012 wpa_printf(MSG_DEBUG,
2013 "DPP: Use Connector version %d instead of current protocol version %d",
2014 conn_ver, ver);
2015 ver = conn_ver;
2016 }
2017#endif /* CONFIG_DPP3 */
2018
2019#ifdef CONFIG_TESTING_OPTIONS
2020 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP) {
2021 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
2022 ver = 1;
2023 }
2024#endif /* CONFIG_TESTING_OPTIONS */
2025
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002026 /* Protocol Version */
2027 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
2028 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002029 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002030 }
2031#endif /* CONFIG_DPP2 */
2032
Hai Shaloma20dcd72022-02-04 13:43:00 -08002033#ifdef CONFIG_TESTING_OPTIONS
2034skip_proto_ver:
2035#endif /* CONFIG_TESTING_OPTIONS */
2036
Roshan Pius3a1667e2018-07-03 15:17:14 -07002037 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
2038 " status=%d", MAC2STR(src), status);
2039 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2040 " freq=%u type=%d status=%d", MAC2STR(src), freq,
2041 DPP_PA_PEER_DISCOVERY_RESP, status);
2042 hostapd_drv_send_action(hapd, freq, 0, src,
2043 wpabuf_head(msg), wpabuf_len(msg));
2044 wpabuf_free(msg);
2045}
2046
2047
Sunil Ravi89eba102022-09-13 21:04:37 -07002048static bool hapd_dpp_connector_available(struct hostapd_data *hapd)
2049{
2050 if (!hapd->wpa_auth ||
2051 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
2052 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
2053 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
2054 return false;
2055 }
2056
2057 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
2058 !hapd->conf->dpp_csign) {
2059 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
2060 return false;
2061 }
2062
2063 return true;
2064}
2065
2066
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002067static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
2068 const u8 *src,
2069 const u8 *buf, size_t len,
2070 unsigned int freq)
2071{
2072 const u8 *connector, *trans_id;
2073 u16 connector_len, trans_id_len;
2074 struct os_time now;
2075 struct dpp_introduction intro;
2076 os_time_t expire;
2077 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002078 enum dpp_status_error res;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002079 u8 pkhash[SHA256_MAC_LEN];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002080
Sunil Ravi89eba102022-09-13 21:04:37 -07002081 os_memset(&intro, 0, sizeof(intro));
2082
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002083 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
2084 MAC2STR(src));
Sunil Ravi89eba102022-09-13 21:04:37 -07002085 if (!hapd_dpp_connector_available(hapd))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002086 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002087
2088 os_get_time(&now);
2089
2090 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002091 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002092 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
2093 return;
2094 }
2095
2096 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2097 &trans_id_len);
2098 if (!trans_id || trans_id_len != 1) {
2099 wpa_printf(MSG_DEBUG,
2100 "DPP: Peer did not include Transaction ID");
2101 return;
2102 }
2103
2104 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2105 if (!connector) {
2106 wpa_printf(MSG_DEBUG,
2107 "DPP: Peer did not include its Connector");
2108 return;
2109 }
2110
Roshan Pius3a1667e2018-07-03 15:17:14 -07002111 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
2112 wpabuf_head(hapd->conf->dpp_netaccesskey),
2113 wpabuf_len(hapd->conf->dpp_netaccesskey),
2114 wpabuf_head(hapd->conf->dpp_csign),
2115 wpabuf_len(hapd->conf->dpp_csign),
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002116 connector, connector_len, &expire, pkhash);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002117 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002118 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002119 "DPP: Network Introduction protocol resulted in internal failure (peer "
2120 MACSTR ")", MAC2STR(src));
Sunil Ravi89eba102022-09-13 21:04:37 -07002121 goto done;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002122 }
2123 if (res != DPP_STATUS_OK) {
2124 wpa_printf(MSG_INFO,
2125 "DPP: Network Introduction protocol resulted in failure (peer "
2126 MACSTR " status %d)", MAC2STR(src), res);
2127 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
2128 res);
Sunil Ravi89eba102022-09-13 21:04:37 -07002129 goto done;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002130 }
2131
Hai Shaloma20dcd72022-02-04 13:43:00 -08002132#ifdef CONFIG_DPP3
2133 if (intro.peer_version && intro.peer_version >= 2) {
2134 const u8 *version;
2135 u16 version_len;
2136 u8 attr_version = 1;
2137
2138 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2139 &version_len);
2140 if (version && version_len >= 1)
2141 attr_version = version[0];
2142 if (attr_version != intro.peer_version) {
2143 wpa_printf(MSG_INFO,
2144 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2145 intro.peer_version, attr_version);
2146 hostapd_dpp_send_peer_disc_resp(hapd, src, freq,
2147 trans_id[0],
2148 DPP_STATUS_NO_MATCH);
Sunil Ravi89eba102022-09-13 21:04:37 -07002149 goto done;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002150 }
2151 }
2152#endif /* CONFIG_DPP3 */
2153
Roshan Pius3a1667e2018-07-03 15:17:14 -07002154 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002155 expire = hapd->conf->dpp_netaccesskey_expiry;
2156 if (expire)
2157 expiration = expire - now.sec;
2158 else
2159 expiration = 0;
2160
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002161 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002162 intro.pmkid, expiration,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002163 WPA_KEY_MGMT_DPP, pkhash) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002164 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
Sunil Ravi89eba102022-09-13 21:04:37 -07002165 goto done;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002166 }
2167
Roshan Pius3a1667e2018-07-03 15:17:14 -07002168 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
2169 DPP_STATUS_OK);
Sunil Ravi89eba102022-09-13 21:04:37 -07002170done:
2171 dpp_peer_intro_deinit(&intro);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002172}
2173
2174
2175static void
2176hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002177 const u8 *hdr, const u8 *buf, size_t len,
2178 unsigned int freq, bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002179{
2180 struct wpabuf *msg;
2181
2182 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
2183 MAC2STR(src));
2184
Sunil Ravia04bd252022-05-02 22:54:18 -07002185 if (hapd->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
2186 wpa_printf(MSG_DEBUG,
2187 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
2188 return;
2189 }
2190 if (hapd->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
2191 wpa_printf(MSG_DEBUG,
2192 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
2193 return;
2194 }
2195
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002196 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2197 * values here */
2198
2199 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
2200 wpa_printf(MSG_DEBUG,
2201 "DPP: No PKEX code configured - ignore request");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002202 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002203 }
2204
Sunil Ravi89eba102022-09-13 21:04:37 -07002205#ifdef CONFIG_DPP2
2206 if (dpp_controller_is_own_pkex_req(hapd->iface->interfaces->dpp,
2207 buf, len)) {
2208 wpa_printf(MSG_DEBUG,
2209 "DPP: PKEX Exchange Request is from local Controller - ignore request");
2210 return;
2211 }
2212#endif /* CONFIG_DPP2 */
2213
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002214 if (hapd->dpp_pkex) {
2215 /* TODO: Support parallel operations */
2216 wpa_printf(MSG_DEBUG,
2217 "DPP: Already in PKEX session - ignore new request");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002218 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002219 }
2220
Roshan Pius3a1667e2018-07-03 15:17:14 -07002221 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
2222 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002223 hapd->own_addr, src,
2224 hapd->dpp_pkex_identifier,
2225 hapd->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07002226 hapd->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002227 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002228 if (!hapd->dpp_pkex) {
2229 wpa_printf(MSG_DEBUG,
2230 "DPP: Failed to process the request - ignore it");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002231 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002232 }
2233
2234 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002235 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2236 " freq=%u type=%d", MAC2STR(src), freq,
2237 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002238 hostapd_drv_send_action(hapd, freq, 0, src,
2239 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002240 if (hapd->dpp_pkex->failed) {
2241 wpa_printf(MSG_DEBUG,
2242 "DPP: Terminate PKEX exchange due to an earlier error");
2243 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
2244 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
2245 dpp_pkex_free(hapd->dpp_pkex);
2246 hapd->dpp_pkex = NULL;
2247 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002248
2249 return;
2250
2251try_relay:
2252#ifdef CONFIG_DPP2
Sunil8cd6f4d2022-06-28 18:40:46 +00002253 if (v2 && dpp_relay_rx_action(hapd->iface->interfaces->dpp,
2254 src, hdr, buf, len, freq, NULL, NULL,
Sunil Ravi89eba102022-09-13 21:04:37 -07002255 hapd) != 0) {
Sunil8cd6f4d2022-06-28 18:40:46 +00002256 wpa_printf(MSG_DEBUG,
2257 "DPP: No Relay available for the message");
Sunil Ravi89eba102022-09-13 21:04:37 -07002258 hostapd_dpp_relay_needs_controller(hapd, src,
2259 DPP_PA_PKEX_EXCHANGE_REQ);
2260 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002261#else /* CONFIG_DPP2 */
2262 wpa_printf(MSG_DEBUG, "DPP: No relay functionality included - skip");
2263#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002264}
2265
2266
2267static void
2268hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
2269 const u8 *buf, size_t len, unsigned int freq)
2270{
2271 struct wpabuf *msg;
2272
2273 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2274 MAC2STR(src));
2275
2276 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2277 * values here */
2278
2279 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
2280 hapd->dpp_pkex->exchange_done) {
2281 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2282 return;
2283 }
2284
Hai Shaloma20dcd72022-02-04 13:43:00 -08002285 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
2286 hapd->dpp_pkex->exch_req_wait_time = 0;
2287
Roshan Pius3a1667e2018-07-03 15:17:14 -07002288 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002289 if (!msg) {
2290 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2291 return;
2292 }
2293
2294 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
2295 MAC2STR(src));
2296
Roshan Pius3a1667e2018-07-03 15:17:14 -07002297 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2298 " freq=%u type=%d", MAC2STR(src), freq,
2299 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002300 hostapd_drv_send_action(hapd, freq, 0, src,
2301 wpabuf_head(msg), wpabuf_len(msg));
2302 wpabuf_free(msg);
2303}
2304
2305
2306static void
2307hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
2308 const u8 *hdr, const u8 *buf, size_t len,
2309 unsigned int freq)
2310{
2311 struct wpabuf *msg;
2312 struct dpp_pkex *pkex = hapd->dpp_pkex;
2313 struct dpp_bootstrap_info *bi;
2314
2315 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
2316 MAC2STR(src));
2317
2318 if (!pkex || pkex->initiator || !pkex->exchange_done) {
2319 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2320 return;
2321 }
2322
2323 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
2324 if (!msg) {
2325 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002326 if (hapd->dpp_pkex->failed) {
2327 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
2328 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
2329 hapd->dpp_pkex->own_bi->pkex_t =
2330 hapd->dpp_pkex->t;
2331 dpp_pkex_free(hapd->dpp_pkex);
2332 hapd->dpp_pkex = NULL;
2333 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002334 return;
2335 }
2336
2337 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
2338 MACSTR, MAC2STR(src));
2339
Roshan Pius3a1667e2018-07-03 15:17:14 -07002340 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2341 " freq=%u type=%d", MAC2STR(src), freq,
2342 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002343 hostapd_drv_send_action(hapd, freq, 0, src,
2344 wpabuf_head(msg), wpabuf_len(msg));
2345 wpabuf_free(msg);
2346
Sunil Ravi89eba102022-09-13 21:04:37 -07002347 hostapd_dpp_pkex_clear_code(hapd);
Hai Shalom021b0b52019-04-10 11:17:58 -07002348 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002349 if (!bi)
2350 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002351 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002352}
2353
2354
2355static void
2356hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
2357 const u8 *hdr, const u8 *buf, size_t len,
2358 unsigned int freq)
2359{
Sunil Ravi89eba102022-09-13 21:04:37 -07002360 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002361 int res;
Hai Shalom021b0b52019-04-10 11:17:58 -07002362 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002363 struct dpp_pkex *pkex = hapd->dpp_pkex;
2364 char cmd[500];
2365
2366 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2367 MAC2STR(src));
2368
2369 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2370 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2371 return;
2372 }
2373
2374 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2375 if (res < 0) {
2376 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2377 return;
2378 }
2379
Sunil Ravi89eba102022-09-13 21:04:37 -07002380 hostapd_dpp_pkex_clear_code(hapd);
2381 bi = dpp_pkex_finish(ifaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002382 if (!bi)
2383 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002384 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002385
Sunil Ravi89eba102022-09-13 21:04:37 -07002386#ifdef CONFIG_DPP3
2387 if (ifaces->dpp_pb_bi &&
2388 os_memcmp(bi->pubkey_hash_chirp, ifaces->dpp_pb_resp_hash,
2389 SHA256_MAC_LEN) != 0) {
2390 char id[20];
2391
2392 wpa_printf(MSG_INFO,
2393 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
2394 wpa_hexdump(MSG_DEBUG,
2395 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
2396 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
2397 wpa_hexdump(MSG_DEBUG,
2398 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
2399 ifaces->dpp_pb_resp_hash, SHA256_MAC_LEN);
2400
2401 os_snprintf(id, sizeof(id), "%u", bi->id);
2402 dpp_bootstrap_remove(ifaces->dpp, id);
2403 hostapd_dpp_push_button_stop(hapd);
2404 return;
2405 }
2406#endif /* CONFIG_DPP3 */
2407
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002408 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2409 bi->id,
2410 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
2411 wpa_printf(MSG_DEBUG,
2412 "DPP: Start authentication after PKEX with parameters: %s",
2413 cmd);
2414 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
2415 wpa_printf(MSG_DEBUG,
2416 "DPP: Authentication initialization failed");
2417 return;
2418 }
2419}
2420
2421
Sunil Ravi89eba102022-09-13 21:04:37 -07002422#ifdef CONFIG_DPP3
2423
2424static void hostapd_dpp_pb_pkex_init(struct hostapd_data *hapd,
2425 unsigned int freq, const u8 *src,
2426 const u8 *r_hash)
2427{
2428 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
2429 struct dpp_pkex *pkex;
2430 struct wpabuf *msg;
2431 char ssid_hex[2 * SSID_MAX_LEN + 1], *pass_hex = NULL;
2432 char cmd[300];
2433 const char *password = NULL;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002434#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -07002435 struct sae_password_entry *e;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002436#endif /* CONFIG_SAE */
Sunil Ravi89eba102022-09-13 21:04:37 -07002437 int conf_id = -1;
2438 bool sae = false, psk = false;
2439 size_t len;
2440
2441 if (hapd->dpp_pkex) {
2442 wpa_printf(MSG_DEBUG,
2443 "PDP: Sending previously generated PKEX Exchange Request to "
2444 MACSTR, MAC2STR(src));
2445 msg = hapd->dpp_pkex->exchange_req;
2446 hostapd_drv_send_action(hapd, freq, 0, src,
2447 wpabuf_head(msg), wpabuf_len(msg));
2448 return;
2449 }
2450
2451 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
2452 MACSTR, MAC2STR(src));
2453
2454 hapd->dpp_pkex_bi = ifaces->dpp_pb_bi;
2455 os_memcpy(ifaces->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
2456
2457 pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr,
2458 "PBPKEX", (const char *) ifaces->dpp_pb_c_nonce,
2459 ifaces->dpp_pb_bi->curve->nonce_len,
2460 true);
2461 if (!pkex) {
2462 hostapd_dpp_push_button_stop(hapd);
2463 return;
2464 }
2465 pkex->freq = freq;
2466
2467 hapd->dpp_pkex = pkex;
2468 msg = hapd->dpp_pkex->exchange_req;
2469
2470 if (ifaces->dpp_pb_cmd) {
2471 /* Use the externally provided configuration */
2472 os_free(hapd->dpp_pkex_auth_cmd);
2473 len = 30 + os_strlen(ifaces->dpp_pb_cmd);
2474 hapd->dpp_pkex_auth_cmd = os_malloc(len);
2475 if (!hapd->dpp_pkex_auth_cmd) {
2476 hostapd_dpp_push_button_stop(hapd);
2477 return;
2478 }
2479 os_snprintf(hapd->dpp_pkex_auth_cmd, len, " own=%d %s",
2480 hapd->dpp_pkex_bi->id, ifaces->dpp_pb_cmd);
2481 goto send_frame;
2482 }
2483
2484 /* Build config based on the current AP configuration */
2485 wpa_snprintf_hex(ssid_hex, sizeof(ssid_hex),
2486 (const u8 *) hapd->conf->ssid.ssid,
2487 hapd->conf->ssid.ssid_len);
2488
2489 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
2490 /* TODO: If a local Configurator has been enabled, allow a
2491 * DPP AKM credential to be provisioned by setting conf_id. */
2492 }
2493
2494 if (hapd->conf->wpa & WPA_PROTO_RSN) {
2495 psk = hapd->conf->wpa_key_mgmt & (WPA_KEY_MGMT_PSK |
2496 WPA_KEY_MGMT_PSK_SHA256);
2497#ifdef CONFIG_SAE
2498 sae = hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE;
2499#endif /* CONFIG_SAE */
2500 }
2501
2502#ifdef CONFIG_SAE
2503 for (e = hapd->conf->sae_passwords; sae && e && !password;
2504 e = e->next) {
2505 if (e->identifier || !is_broadcast_ether_addr(e->peer_addr))
2506 continue;
2507 password = e->password;
2508 }
2509#endif /* CONFIG_SAE */
2510 if (!password && hapd->conf->ssid.wpa_passphrase_set &&
2511 hapd->conf->ssid.wpa_passphrase)
2512 password = hapd->conf->ssid.wpa_passphrase;
2513 if (password) {
2514 len = 2 * os_strlen(password) + 1;
2515 pass_hex = os_malloc(len);
2516 if (!pass_hex) {
2517 hostapd_dpp_push_button_stop(hapd);
2518 return;
2519 }
2520 wpa_snprintf_hex(pass_hex, len, (const u8 *) password,
2521 os_strlen(password));
2522 }
2523
2524 if (conf_id > 0 && sae && psk && pass_hex) {
2525 os_snprintf(cmd, sizeof(cmd),
2526 "conf=sta-dpp+psk+sae configurator=%d ssid=%s pass=%s",
2527 conf_id, ssid_hex, pass_hex);
2528 } else if (conf_id > 0 && sae && pass_hex) {
2529 os_snprintf(cmd, sizeof(cmd),
2530 "conf=sta-dpp+sae configurator=%d ssid=%s pass=%s",
2531 conf_id, ssid_hex, pass_hex);
2532 } else if (conf_id > 0) {
2533 os_snprintf(cmd, sizeof(cmd),
2534 "conf=sta-dpp configurator=%d ssid=%s",
2535 conf_id, ssid_hex);
2536 } if (sae && psk && pass_hex) {
2537 os_snprintf(cmd, sizeof(cmd),
2538 "conf=sta-psk+sae ssid=%s pass=%s",
2539 ssid_hex, pass_hex);
2540 } else if (sae && pass_hex) {
2541 os_snprintf(cmd, sizeof(cmd),
2542 "conf=sta-sae ssid=%s pass=%s",
2543 ssid_hex, pass_hex);
2544 } else if (psk && pass_hex) {
2545 os_snprintf(cmd, sizeof(cmd),
2546 "conf=sta-psk ssid=%s pass=%s",
2547 ssid_hex, pass_hex);
2548 } else {
2549 wpa_printf(MSG_INFO,
2550 "DPP: Unsupported AP configuration for push button");
2551 str_clear_free(pass_hex);
2552 hostapd_dpp_push_button_stop(hapd);
2553 return;
2554 }
2555 str_clear_free(pass_hex);
2556
2557 os_free(hapd->dpp_pkex_auth_cmd);
2558 len = 30 + os_strlen(cmd);
2559 hapd->dpp_pkex_auth_cmd = os_malloc(len);
2560 if (hapd->dpp_pkex_auth_cmd)
2561 os_snprintf(hapd->dpp_pkex_auth_cmd, len, " own=%d %s",
2562 hapd->dpp_pkex_bi->id, cmd);
2563 forced_memzero(cmd, sizeof(cmd));
2564 if (!hapd->dpp_pkex_auth_cmd) {
2565 hostapd_dpp_push_button_stop(hapd);
2566 return;
2567 }
2568
2569send_frame:
2570 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2571 " freq=%u type=%d", MAC2STR(src), freq,
2572 DPP_PA_PKEX_EXCHANGE_REQ);
2573 hostapd_drv_send_action(hapd, pkex->freq, 0, src,
2574 wpabuf_head(msg), wpabuf_len(msg));
2575 pkex->exch_req_wait_time = 2000;
2576 pkex->exch_req_tries = 1;
2577}
2578
2579
2580static void
2581hostapd_dpp_rx_pb_presence_announcement(struct hostapd_data *hapd,
2582 const u8 *src, const u8 *hdr,
2583 const u8 *buf, size_t len,
2584 unsigned int freq)
2585{
2586 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
2587 const u8 *r_hash;
2588 u16 r_hash_len;
2589 unsigned int i;
2590 bool found = false;
2591 struct dpp_pb_info *info, *tmp;
2592 struct os_reltime now, age;
2593 struct wpabuf *msg;
2594
2595 if (!ifaces)
2596 return;
2597
2598 os_get_reltime(&now);
2599 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
2600 MACSTR, MAC2STR(src));
2601
2602 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2603 &r_hash_len);
2604 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
2605 wpa_printf(MSG_DEBUG,
2606 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
2607 return;
2608 }
2609 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2610 r_hash, r_hash_len);
2611
2612 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2613 info = &ifaces->dpp_pb[i];
2614 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
2615 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
2616 continue;
2617 wpa_printf(MSG_DEBUG,
2618 "DPP: Active push button Enrollee already known");
2619 found = true;
2620 info->rx_time = now;
2621 }
2622
2623 if (!found) {
2624 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2625 tmp = &ifaces->dpp_pb[i];
2626 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
2627 continue;
2628
2629 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
2630 wpa_hexdump(MSG_DEBUG,
2631 "DPP: Push button Enrollee hash expired",
2632 tmp->hash, SHA256_MAC_LEN);
2633 tmp->rx_time.sec = 0;
2634 tmp->rx_time.usec = 0;
2635 continue;
2636 }
2637
2638 wpa_hexdump(MSG_DEBUG,
2639 "DPP: Push button session overlap with hash",
2640 tmp->hash, SHA256_MAC_LEN);
2641 if (!ifaces->dpp_pb_result_indicated &&
2642 hostapd_dpp_pb_active(hapd)) {
2643 wpa_msg(hapd->msg_ctx, MSG_INFO,
2644 DPP_EVENT_PB_RESULT "session-overlap");
2645 ifaces->dpp_pb_result_indicated = true;
2646 }
2647 hostapd_dpp_push_button_stop(hapd);
2648 return;
2649 }
2650
2651 /* Replace the oldest entry */
2652 info = &ifaces->dpp_pb[0];
2653 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
2654 tmp = &ifaces->dpp_pb[i];
2655 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
2656 info = tmp;
2657 }
2658 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
2659 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
2660 info->rx_time = now;
2661 }
2662
2663 if (!hostapd_dpp_pb_active(hapd)) {
2664 wpa_printf(MSG_DEBUG,
2665 "DPP: Discard message since own push button has not been pressed");
2666 return;
2667 }
2668
2669 if (ifaces->dpp_pb_announce_time.sec == 0 &&
2670 ifaces->dpp_pb_announce_time.usec == 0) {
2671 /* Start a wait before allowing PKEX to be initiated */
2672 ifaces->dpp_pb_announce_time = now;
2673 }
2674
2675 if (!ifaces->dpp_pb_bi) {
2676 int res;
2677
2678 res = dpp_bootstrap_gen(ifaces->dpp, "type=pkex");
2679 if (res < 0)
2680 return;
2681 ifaces->dpp_pb_bi = dpp_bootstrap_get_id(ifaces->dpp, res);
2682 if (!ifaces->dpp_pb_bi)
2683 return;
2684
2685 if (random_get_bytes(ifaces->dpp_pb_c_nonce,
2686 ifaces->dpp_pb_bi->curve->nonce_len)) {
2687 wpa_printf(MSG_ERROR,
2688 "DPP: Failed to generate C-nonce");
2689 hostapd_dpp_push_button_stop(hapd);
2690 return;
2691 }
2692 }
2693
2694 /* Skip the response if one was sent within last 50 ms since the
2695 * Enrollee is going to send out at least three announcement messages.
2696 */
2697 os_reltime_sub(&now, &ifaces->dpp_pb_last_resp, &age);
2698 if (age.sec == 0 && age.usec < 50000) {
2699 wpa_printf(MSG_DEBUG,
2700 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
2701 return;
2702 }
2703
2704 msg = dpp_build_pb_announcement_resp(
2705 ifaces->dpp_pb_bi, r_hash, ifaces->dpp_pb_c_nonce,
2706 ifaces->dpp_pb_bi->curve->nonce_len);
2707 if (!msg) {
2708 hostapd_dpp_push_button_stop(hapd);
2709 return;
2710 }
2711
2712 wpa_printf(MSG_DEBUG,
2713 "DPP: Send Push Button Presence Announcement Response to "
2714 MACSTR, MAC2STR(src));
2715 ifaces->dpp_pb_last_resp = now;
2716
2717 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2718 " freq=%u type=%d", MAC2STR(src), freq,
2719 DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
2720 hostapd_drv_send_action(hapd, freq, 0, src,
2721 wpabuf_head(msg), wpabuf_len(msg));
2722 wpabuf_free(msg);
2723
2724 if (os_reltime_expired(&now, &ifaces->dpp_pb_announce_time, 15))
2725 hostapd_dpp_pb_pkex_init(hapd, freq, src, r_hash);
2726}
2727
2728
2729static void
2730hostapd_dpp_rx_priv_peer_intro_query(struct hostapd_data *hapd, const u8 *src,
2731 const u8 *hdr, const u8 *buf, size_t len,
2732 unsigned int freq)
2733{
2734 const u8 *trans_id, *version;
2735 u16 trans_id_len, version_len;
2736 struct wpabuf *msg;
2737 u8 ver = DPP_VERSION;
2738 int conn_ver;
2739
2740 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Query from "
2741 MACSTR, MAC2STR(src));
2742
2743 if (!hapd_dpp_connector_available(hapd))
2744 return;
2745
2746 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2747 &trans_id_len);
2748 if (!trans_id || trans_id_len != 1) {
2749 wpa_printf(MSG_DEBUG,
2750 "DPP: Peer did not include Transaction ID");
2751 return;
2752 }
2753
2754 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2755 &version_len);
2756 if (!version || version_len != 1) {
2757 wpa_printf(MSG_DEBUG,
2758 "DPP: Peer did not include Protocol Version");
2759 return;
2760 }
2761
2762 wpa_printf(MSG_DEBUG, "DPP: Transaction ID %u, Version %u",
2763 trans_id[0], version[0]);
2764
2765 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
2766 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_NOTIFY, len);
2767 if (!msg)
2768 return;
2769
2770 /* Transaction ID */
2771 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2772 wpabuf_put_le16(msg, 1);
2773 wpabuf_put_u8(msg, trans_id[0]);
2774
2775 /* Protocol Version */
2776 conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
2777 if (conn_ver > 0 && ver != conn_ver) {
2778 wpa_printf(MSG_DEBUG,
2779 "DPP: Use Connector version %d instead of current protocol version %d",
2780 conn_ver, ver);
2781 ver = conn_ver;
2782 }
2783 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
2784 wpabuf_put_le16(msg, 1);
2785 wpabuf_put_u8(msg, ver);
2786
2787 /* DPP Connector */
2788 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2789 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
2790 wpabuf_put_str(msg, hapd->conf->dpp_connector);
2791
2792 wpa_printf(MSG_DEBUG, "DPP: Send Private Peer Introduction Notify to "
2793 MACSTR, MAC2STR(src));
2794 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2795 " freq=%u type=%d", MAC2STR(src), freq,
2796 DPP_PA_PRIV_PEER_INTRO_NOTIFY);
2797 hostapd_drv_send_action(hapd, freq, 0, src,
2798 wpabuf_head(msg), wpabuf_len(msg));
2799 wpabuf_free(msg);
2800}
2801
2802
2803static void
2804hostapd_dpp_rx_priv_peer_intro_update(struct hostapd_data *hapd, const u8 *src,
2805 const u8 *hdr, const u8 *buf, size_t len,
2806 unsigned int freq)
2807{
2808 struct crypto_ec_key *own_key;
2809 const struct dpp_curve_params *curve;
2810 enum hpke_kem_id kem_id;
2811 enum hpke_kdf_id kdf_id;
2812 enum hpke_aead_id aead_id;
2813 const u8 *aad = hdr;
2814 size_t aad_len = DPP_HDR_LEN;
2815 struct wpabuf *pt;
2816 const u8 *trans_id, *wrapped, *version, *connector;
2817 u16 trans_id_len, wrapped_len, version_len, connector_len;
2818 struct os_time now;
2819 struct dpp_introduction intro;
2820 os_time_t expire;
2821 int expiration;
2822 enum dpp_status_error res;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002823 u8 pkhash[SHA256_MAC_LEN];
Sunil Ravi89eba102022-09-13 21:04:37 -07002824
2825 os_memset(&intro, 0, sizeof(intro));
2826
2827 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Update from "
2828 MACSTR, MAC2STR(src));
2829
2830 if (!hapd_dpp_connector_available(hapd))
2831 return;
2832
2833 os_get_time(&now);
2834
2835 if (hapd->conf->dpp_netaccesskey_expiry &&
2836 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
2837 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
2838 return;
2839 }
2840
2841 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2842 &trans_id_len);
2843 if (!trans_id || trans_id_len != 1) {
2844 wpa_printf(MSG_DEBUG,
2845 "DPP: Peer did not include Transaction ID");
2846 return;
2847 }
2848
2849 wrapped = dpp_get_attr(buf, len, DPP_ATTR_WRAPPED_DATA,
2850 &wrapped_len);
2851 if (!wrapped) {
2852 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Wrapped Data");
2853 return;
2854 }
2855
2856 own_key = dpp_set_keypair(&curve,
2857 wpabuf_head(hapd->conf->dpp_netaccesskey),
2858 wpabuf_len(hapd->conf->dpp_netaccesskey));
2859 if (!own_key) {
2860 wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
2861 return;
2862 }
2863
2864 if (dpp_hpke_suite(curve->ike_group, &kem_id, &kdf_id, &aead_id) < 0) {
2865 wpa_printf(MSG_ERROR, "DPP: Unsupported curve %d",
2866 curve->ike_group);
2867 crypto_ec_key_deinit(own_key);
2868 return;
2869 }
2870
2871 pt = hpke_base_open(kem_id, kdf_id, aead_id, own_key, NULL, 0,
2872 aad, aad_len, wrapped, wrapped_len);
2873 crypto_ec_key_deinit(own_key);
2874 if (!pt) {
2875 wpa_printf(MSG_INFO, "DPP: Failed to decrypt Connector");
2876 return;
2877 }
2878 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE-Decrypted Wrapped Data", pt);
2879
2880 connector = dpp_get_attr(wpabuf_head(pt), wpabuf_len(pt),
2881 DPP_ATTR_CONNECTOR, &connector_len);
2882 if (!connector) {
2883 wpa_printf(MSG_DEBUG,
2884 "DPP: Peer did not include its Connector");
2885 goto done;
2886 }
2887
2888 version = dpp_get_attr(wpabuf_head(pt), wpabuf_len(pt),
2889 DPP_ATTR_PROTOCOL_VERSION, &version_len);
2890 if (!version || version_len < 1) {
2891 wpa_printf(MSG_DEBUG,
2892 "DPP: Peer did not include Protocol Version");
2893 goto done;
2894 }
2895
2896 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
2897 wpabuf_head(hapd->conf->dpp_netaccesskey),
2898 wpabuf_len(hapd->conf->dpp_netaccesskey),
2899 wpabuf_head(hapd->conf->dpp_csign),
2900 wpabuf_len(hapd->conf->dpp_csign),
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002901 connector, connector_len, &expire, pkhash);
Sunil Ravi89eba102022-09-13 21:04:37 -07002902 if (res == 255) {
2903 wpa_printf(MSG_INFO,
2904 "DPP: Network Introduction protocol resulted in internal failure (peer "
2905 MACSTR ")", MAC2STR(src));
2906 goto done;
2907 }
2908 if (res != DPP_STATUS_OK) {
2909 wpa_printf(MSG_INFO,
2910 "DPP: Network Introduction protocol resulted in failure (peer "
2911 MACSTR " status %d)", MAC2STR(src), res);
2912 goto done;
2913 }
2914
2915 if (intro.peer_version && intro.peer_version >= 2) {
2916 u8 attr_version = 1;
2917
2918 if (version && version_len >= 1)
2919 attr_version = version[0];
2920 if (attr_version != intro.peer_version) {
2921 wpa_printf(MSG_INFO,
2922 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2923 intro.peer_version, attr_version);
2924 goto done;
2925 }
2926 }
2927
2928 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
2929 expire = hapd->conf->dpp_netaccesskey_expiry;
2930 if (expire)
2931 expiration = expire - now.sec;
2932 else
2933 expiration = 0;
2934
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002935 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
Sunil Ravi89eba102022-09-13 21:04:37 -07002936 intro.pmkid, expiration,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002937 WPA_KEY_MGMT_DPP, pkhash) < 0) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002938 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
2939 goto done;
2940 }
2941
2942 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction completed with "
2943 MACSTR, MAC2STR(src));
2944
2945done:
2946 dpp_peer_intro_deinit(&intro);
2947 wpabuf_free(pt);
2948}
2949
2950#endif /* CONFIG_DPP3 */
2951
2952
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002953void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
2954 const u8 *buf, size_t len, unsigned int freq)
2955{
2956 u8 crypto_suite;
2957 enum dpp_public_action_frame_type type;
2958 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002959 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002960
2961 if (len < DPP_HDR_LEN)
2962 return;
2963 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2964 return;
2965 hdr = buf;
2966 buf += 4;
2967 len -= 4;
2968 crypto_suite = *buf++;
2969 type = *buf++;
2970 len -= 2;
2971
2972 wpa_printf(MSG_DEBUG,
2973 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2974 MACSTR " freq=%u",
2975 crypto_suite, type, MAC2STR(src), freq);
2976 if (crypto_suite != 1) {
2977 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2978 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002979 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2980 " freq=%u type=%d ignore=unsupported-crypto-suite",
2981 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002982 return;
2983 }
2984 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002985 if (dpp_check_attrs(buf, len) < 0) {
2986 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2987 " freq=%u type=%d ignore=invalid-attributes",
2988 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002989 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002990 }
2991 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2992 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002993
Hai Shalom81f62d82019-07-22 12:10:00 -07002994#ifdef CONFIG_DPP2
2995 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002996 src, hdr, buf, len, freq, NULL, NULL,
2997 hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07002998 return;
2999#endif /* CONFIG_DPP2 */
3000
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003001 switch (type) {
3002 case DPP_PA_AUTHENTICATION_REQ:
3003 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
3004 break;
3005 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07003006 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003007 break;
3008 case DPP_PA_AUTHENTICATION_CONF:
3009 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
3010 break;
3011 case DPP_PA_PEER_DISCOVERY_REQ:
3012 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
3013 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003014#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003015 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003016 /* This is for PKEXv2, but for now, process only with
3017 * CONFIG_DPP3 to avoid issues with a capability that has not
3018 * been tested with other implementations. */
3019 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
3020 true);
3021 break;
3022#endif /* CONFIG_DPP3 */
3023 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
3024 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
3025 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003026 break;
3027 case DPP_PA_PKEX_EXCHANGE_RESP:
3028 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
3029 break;
3030 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
3031 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
3032 freq);
3033 break;
3034 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
3035 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
3036 freq);
3037 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003038#ifdef CONFIG_DPP2
3039 case DPP_PA_CONFIGURATION_RESULT:
3040 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
3041 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003042 case DPP_PA_CONNECTION_STATUS_RESULT:
3043 hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
3044 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07003045 case DPP_PA_PRESENCE_ANNOUNCEMENT:
3046 hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
3047 freq);
3048 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003049 case DPP_PA_RECONFIG_ANNOUNCEMENT:
3050 hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
3051 freq);
3052 break;
3053 case DPP_PA_RECONFIG_AUTH_RESP:
3054 hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
3055 freq);
3056 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003057#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07003058#ifdef CONFIG_DPP3
3059 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
3060 hostapd_dpp_rx_pb_presence_announcement(hapd, src, hdr,
3061 buf, len, freq);
3062 break;
3063 case DPP_PA_PRIV_PEER_INTRO_QUERY:
3064 hostapd_dpp_rx_priv_peer_intro_query(hapd, src, hdr,
3065 buf, len, freq);
3066 break;
3067 case DPP_PA_PRIV_PEER_INTRO_UPDATE:
3068 hostapd_dpp_rx_priv_peer_intro_update(hapd, src, hdr,
3069 buf, len, freq);
3070 break;
3071#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003072 default:
3073 wpa_printf(MSG_DEBUG,
3074 "DPP: Ignored unsupported frame subtype %d", type);
3075 break;
3076 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003077
3078 if (hapd->dpp_pkex)
3079 pkex_t = hapd->dpp_pkex->t;
3080 else if (hapd->dpp_pkex_bi)
3081 pkex_t = hapd->dpp_pkex_bi->pkex_t;
3082 else
3083 pkex_t = 0;
3084 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
3085 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
3086 hostapd_dpp_pkex_remove(hapd, "*");
3087 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003088}
3089
3090
3091struct wpabuf *
3092hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
Hai Shalom81f62d82019-07-22 12:10:00 -07003093 const u8 *query, size_t query_len,
3094 const u8 *data, size_t data_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003095{
3096 struct dpp_authentication *auth = hapd->dpp_auth;
3097 struct wpabuf *resp;
3098
3099 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00003100 eloop_cancel_timeout(hostapd_gas_req_wait, hapd, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003101 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003102 !ether_addr_equal(sa, auth->peer_mac_addr)) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003103#ifdef CONFIG_DPP2
3104 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
3105 data_len) == 0) {
3106 /* Response will be forwarded once received over TCP */
3107 return NULL;
3108 }
3109#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003110 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
3111 return NULL;
3112 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08003113
3114 if (hapd->dpp_auth_ok_on_ack && auth->configurator) {
3115 wpa_printf(MSG_DEBUG,
3116 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
3117 /* hostapd_dpp_auth_success() would normally have been called
3118 * from TX status handler, but since there was no such handler
3119 * call yet, simply send out the event message and proceed with
3120 * exchange. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003121 dpp_notify_auth_success(hapd->dpp_auth, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003122 hapd->dpp_auth_ok_on_ack = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003123#ifdef CONFIG_TESTING_OPTIONS
3124 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
3125 wpa_printf(MSG_INFO,
3126 "DPP: TESTING - stop at Authentication Confirm");
3127 return NULL;
3128 }
3129#endif /* CONFIG_TESTING_OPTIONS */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003130 }
3131
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003132 wpa_hexdump(MSG_DEBUG,
3133 "DPP: Received Configuration Request (GAS Query Request)",
3134 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003135 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
3136 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003137 resp = dpp_conf_req_rx(auth, query, query_len);
3138 if (!resp)
3139 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
3140 return resp;
3141}
3142
3143
Roshan Pius3a1667e2018-07-03 15:17:14 -07003144void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
3145{
Hai Shalom021b0b52019-04-10 11:17:58 -07003146 struct dpp_authentication *auth = hapd->dpp_auth;
Sunil Ravi89eba102022-09-13 21:04:37 -07003147#ifdef CONFIG_DPP3
3148 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3149#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07003150
3151 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07003152 return;
3153
Sunil Ravia04bd252022-05-02 22:54:18 -07003154#ifdef CONFIG_DPP3
3155 if (auth->waiting_new_key && ok) {
3156 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
3157 return;
3158 }
3159#endif /* CONFIG_DPP3 */
3160
Hai Shalom021b0b52019-04-10 11:17:58 -07003161 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
3162 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003163 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003164 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003165 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003166#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003167 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
3168 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003169 if (ok && auth->peer_version >= 2 &&
3170 auth->conf_resp_status == DPP_STATUS_OK) {
3171 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
3172 auth->waiting_conf_result = 1;
3173 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
3174 hapd, NULL);
3175 eloop_register_timeout(2, 0,
3176 hostapd_dpp_config_result_wait_timeout,
3177 hapd, NULL);
3178 return;
3179 }
3180#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003181 hostapd_drv_send_action_cancel_wait(hapd);
3182
3183 if (ok)
Sunil Ravi89eba102022-09-13 21:04:37 -07003184 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
3185 "conf_status=%d", auth->conf_resp_status);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003186 else
3187 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
3188 dpp_auth_deinit(hapd->dpp_auth);
3189 hapd->dpp_auth = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003190#ifdef CONFIG_DPP3
3191 if (!ifaces->dpp_pb_result_indicated && hostapd_dpp_pb_active(hapd)) {
3192 if (ok)
3193 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
3194 "success");
3195 else
3196 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_RESULT
3197 "could-not-connect");
3198 ifaces->dpp_pb_result_indicated = true;
3199 if (ok)
3200 hostapd_dpp_remove_pb_hash(hapd);
3201 hostapd_dpp_push_button_stop(hapd);
3202 }
3203#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003204}
3205
3206
Roshan Pius3a1667e2018-07-03 15:17:14 -07003207int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
3208{
3209 struct dpp_authentication *auth;
3210 int ret = -1;
3211 char *curve = NULL;
3212
Hai Shalomfdcde762020-04-02 11:19:20 -07003213 auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003214 if (!auth)
3215 return -1;
3216
3217 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08003218 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07003219 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08003220 dpp_configurator_own_config(auth, curve, 1) == 0) {
Hai Shalomc3565922019-10-28 11:58:20 -07003221 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003222 ret = 0;
3223 }
3224
3225 dpp_auth_deinit(auth);
3226 os_free(curve);
3227
3228 return ret;
3229}
3230
3231
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003232int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
3233{
3234 struct dpp_bootstrap_info *own_bi;
3235 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07003236#ifdef CONFIG_DPP3
3237 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
3238#else /* CONFIG_DPP3 */
3239 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
3240#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003241 int tcp_port = DPP_TCP_PORT;
3242 struct hostapd_ip_addr *ipaddr = NULL;
3243#ifdef CONFIG_DPP2
3244 struct hostapd_ip_addr ipaddr_buf;
3245 char *addr;
3246
3247 pos = os_strstr(cmd, " tcp_port=");
3248 if (pos) {
3249 pos += 10;
3250 tcp_port = atoi(pos);
3251 }
3252
3253 addr = get_param(cmd, " tcp_addr=");
3254 if (addr) {
3255 int res;
3256
3257 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
3258 os_free(addr);
3259 if (res)
3260 return -1;
3261 ipaddr = &ipaddr_buf;
3262 }
3263#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003264
3265 pos = os_strstr(cmd, " own=");
3266 if (!pos)
3267 return -1;
3268 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07003269 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003270 if (!own_bi) {
3271 wpa_printf(MSG_DEBUG,
3272 "DPP: Identified bootstrap info not found");
3273 return -1;
3274 }
3275 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
3276 wpa_printf(MSG_DEBUG,
3277 "DPP: Identified bootstrap info not for PKEX");
3278 return -1;
3279 }
3280 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003281 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003282
3283 os_free(hapd->dpp_pkex_identifier);
3284 hapd->dpp_pkex_identifier = NULL;
3285 pos = os_strstr(cmd, " identifier=");
3286 if (pos) {
3287 pos += 12;
3288 end = os_strchr(pos, ' ');
3289 if (!end)
3290 return -1;
3291 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
3292 if (!hapd->dpp_pkex_identifier)
3293 return -1;
3294 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
3295 hapd->dpp_pkex_identifier[end - pos] = '\0';
3296 }
3297
3298 pos = os_strstr(cmd, " code=");
3299 if (!pos)
3300 return -1;
3301 os_free(hapd->dpp_pkex_code);
3302 hapd->dpp_pkex_code = os_strdup(pos + 6);
3303 if (!hapd->dpp_pkex_code)
3304 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07003305 hapd->dpp_pkex_code_len = os_strlen(hapd->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003306
Sunil Ravia04bd252022-05-02 22:54:18 -07003307 pos = os_strstr(cmd, " ver=");
3308 if (pos) {
3309 int v;
3310
3311 pos += 5;
3312 v = atoi(pos);
3313 if (v == 1)
3314 ver = PKEX_VER_ONLY_1;
3315 else if (v == 2)
3316 ver = PKEX_VER_ONLY_2;
3317 else
3318 return -1;
3319 }
3320 hapd->dpp_pkex_ver = ver;
3321
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003322 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003323 if (hostapd_dpp_pkex_init(hapd, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003324 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003325 } else {
3326#ifdef CONFIG_DPP2
3327 dpp_controller_pkex_add(hapd->iface->interfaces->dpp, own_bi,
3328 hapd->dpp_pkex_code,
3329 hapd->dpp_pkex_identifier);
3330#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003331 }
3332
3333 /* TODO: Support multiple PKEX info entries */
3334
3335 os_free(hapd->dpp_pkex_auth_cmd);
3336 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
3337
3338 return 1;
3339}
3340
3341
3342int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
3343{
3344 unsigned int id_val;
3345
3346 if (os_strcmp(id, "*") == 0) {
3347 id_val = 0;
3348 } else {
3349 id_val = atoi(id);
3350 if (id_val == 0)
3351 return -1;
3352 }
3353
Sunil Ravi89eba102022-09-13 21:04:37 -07003354 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003355 return -1;
3356
3357 /* TODO: Support multiple PKEX entries */
3358 os_free(hapd->dpp_pkex_code);
3359 hapd->dpp_pkex_code = NULL;
3360 os_free(hapd->dpp_pkex_identifier);
3361 hapd->dpp_pkex_identifier = NULL;
3362 os_free(hapd->dpp_pkex_auth_cmd);
3363 hapd->dpp_pkex_auth_cmd = NULL;
3364 hapd->dpp_pkex_bi = NULL;
3365 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
3366 dpp_pkex_free(hapd->dpp_pkex);
3367 hapd->dpp_pkex = NULL;
3368 return 0;
3369}
3370
3371
Roshan Pius3a1667e2018-07-03 15:17:14 -07003372void hostapd_dpp_stop(struct hostapd_data *hapd)
3373{
3374 dpp_auth_deinit(hapd->dpp_auth);
3375 hapd->dpp_auth = NULL;
3376 dpp_pkex_free(hapd->dpp_pkex);
3377 hapd->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003378#ifdef CONFIG_DPP3
3379 hostapd_dpp_push_button_stop(hapd);
3380#endif /* CONFIG_DPP3 */
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00003381 eloop_cancel_timeout(hostapd_gas_req_wait, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003382}
3383
3384
Hai Shalom81f62d82019-07-22 12:10:00 -07003385#ifdef CONFIG_DPP2
3386
3387static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq,
3388 const u8 *msg, size_t len)
3389{
3390 struct hostapd_data *hapd = ctx;
3391 u8 *buf;
3392
Sunil Ravi89eba102022-09-13 21:04:37 -07003393 if (freq == 0)
3394 freq = hapd->iface->freq;
3395
Hai Shalom81f62d82019-07-22 12:10:00 -07003396 wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u",
3397 MAC2STR(addr), freq);
3398 buf = os_malloc(2 + len);
3399 if (!buf)
3400 return;
3401 buf[0] = WLAN_ACTION_PUBLIC;
3402 buf[1] = WLAN_PA_VENDOR_SPECIFIC;
3403 os_memcpy(buf + 2, msg, len);
3404 hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len);
3405 os_free(buf);
3406}
3407
3408
3409static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr,
3410 u8 dialog_token, int prot,
3411 struct wpabuf *buf)
3412{
3413 struct hostapd_data *hapd = ctx;
3414
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003415 gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf, 0);
Hai Shalom81f62d82019-07-22 12:10:00 -07003416}
3417
3418#endif /* CONFIG_DPP2 */
3419
3420
3421static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
3422{
3423#ifdef CONFIG_DPP2
3424 struct dpp_controller_conf *ctrl;
3425 struct dpp_relay_config config;
3426
3427 os_memset(&config, 0, sizeof(config));
Sunil Ravi89eba102022-09-13 21:04:37 -07003428 config.msg_ctx = hapd->msg_ctx;
Hai Shalom81f62d82019-07-22 12:10:00 -07003429 config.cb_ctx = hapd;
3430 config.tx = hostapd_dpp_relay_tx;
3431 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
3432 for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) {
3433 config.ipaddr = &ctrl->ipaddr;
3434 config.pkhash = ctrl->pkhash;
3435 if (dpp_relay_add_controller(hapd->iface->interfaces->dpp,
3436 &config) < 0)
3437 return -1;
3438 }
Sunil Ravi89eba102022-09-13 21:04:37 -07003439
3440 if (hapd->conf->dpp_relay_port)
3441 dpp_relay_listen(hapd->iface->interfaces->dpp,
3442 hapd->conf->dpp_relay_port,
3443 &config);
Hai Shalom81f62d82019-07-22 12:10:00 -07003444#endif /* CONFIG_DPP2 */
3445
3446 return 0;
3447}
3448
3449
Sunil Ravi89eba102022-09-13 21:04:37 -07003450#ifdef CONFIG_DPP2
3451
3452int hostapd_dpp_add_controller(struct hostapd_data *hapd, const char *cmd)
3453{
3454 struct dpp_relay_config config;
3455 struct hostapd_ip_addr addr;
3456 u8 pkhash[SHA256_MAC_LEN];
3457 char *pos, *tmp;
3458 int ret = -1;
3459 bool prev_state, new_state;
3460 struct dpp_global *dpp = hapd->iface->interfaces->dpp;
3461
3462 tmp = os_strdup(cmd);
3463 if (!tmp)
3464 goto fail;
3465 pos = os_strchr(tmp, ' ');
3466 if (!pos)
3467 goto fail;
3468 *pos++ = '\0';
3469 if (hostapd_parse_ip_addr(tmp, &addr) < 0 ||
3470 hexstr2bin(pos, pkhash, SHA256_MAC_LEN) < 0)
3471 goto fail;
3472
3473 os_memset(&config, 0, sizeof(config));
3474 config.msg_ctx = hapd->msg_ctx;
3475 config.cb_ctx = hapd;
3476 config.tx = hostapd_dpp_relay_tx;
3477 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
3478 config.ipaddr = &addr;
3479 config.pkhash = pkhash;
3480 prev_state = dpp_relay_controller_available(dpp);
3481 ret = dpp_relay_add_controller(dpp, &config);
3482 new_state = dpp_relay_controller_available(dpp);
3483 if (new_state != prev_state)
3484 ieee802_11_update_beacons(hapd->iface);
3485fail:
3486 os_free(tmp);
3487 return ret;
3488}
3489
3490
3491void hostapd_dpp_remove_controller(struct hostapd_data *hapd, const char *cmd)
3492{
3493 struct hostapd_ip_addr addr;
3494 bool prev_state, new_state;
3495 struct dpp_global *dpp = hapd->iface->interfaces->dpp;
3496
3497 if (hostapd_parse_ip_addr(cmd, &addr) < 0)
3498 return;
3499 prev_state = dpp_relay_controller_available(dpp);
3500 dpp_relay_remove_controller(dpp, &addr);
3501 new_state = dpp_relay_controller_available(dpp);
3502 if (new_state != prev_state)
3503 ieee802_11_update_beacons(hapd->iface);
3504}
3505
3506#endif /* CONFIG_DPP2 */
3507
3508
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003509int hostapd_dpp_init(struct hostapd_data *hapd)
3510{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003511 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
3512 hapd->dpp_init_done = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07003513 return hostapd_dpp_add_controllers(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003514}
3515
3516
3517void hostapd_dpp_deinit(struct hostapd_data *hapd)
3518{
3519#ifdef CONFIG_TESTING_OPTIONS
3520 os_free(hapd->dpp_config_obj_override);
3521 hapd->dpp_config_obj_override = NULL;
3522 os_free(hapd->dpp_discovery_override);
3523 hapd->dpp_discovery_override = NULL;
3524 os_free(hapd->dpp_groups_override);
3525 hapd->dpp_groups_override = NULL;
3526 hapd->dpp_ignore_netaccesskey_mismatch = 0;
3527#endif /* CONFIG_TESTING_OPTIONS */
3528 if (!hapd->dpp_init_done)
3529 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003530 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003531 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003532 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003533 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
3534 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00003535 eloop_cancel_timeout(hostapd_gas_req_wait, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003536#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003537 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
3538 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003539 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
3540 NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07003541 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
3542 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003543 hostapd_dpp_chirp_stop(hapd);
Sunil Ravi89eba102022-09-13 21:04:37 -07003544 if (hapd->iface->interfaces) {
3545 dpp_relay_stop_listen(hapd->iface->interfaces->dpp);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003546 dpp_controller_stop_for_ctx(hapd->iface->interfaces->dpp, hapd);
Sunil Ravi89eba102022-09-13 21:04:37 -07003547 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003548#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003549#ifdef CONFIG_DPP3
3550 eloop_cancel_timeout(hostapd_dpp_build_new_key, hapd, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07003551 hostapd_dpp_push_button_stop(hapd);
Sunil Ravia04bd252022-05-02 22:54:18 -07003552#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003553 dpp_auth_deinit(hapd->dpp_auth);
3554 hapd->dpp_auth = NULL;
3555 hostapd_dpp_pkex_remove(hapd, "*");
3556 hapd->dpp_pkex = NULL;
3557 os_free(hapd->dpp_configurator_params);
3558 hapd->dpp_configurator_params = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003559 os_free(hapd->dpp_pkex_auth_cmd);
3560 hapd->dpp_pkex_auth_cmd = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003561}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003562
3563
3564#ifdef CONFIG_DPP2
3565
Hai Shalom899fcc72020-10-19 14:38:18 -07003566int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd)
3567{
3568 struct dpp_controller_config config;
3569 const char *pos;
3570
3571 os_memset(&config, 0, sizeof(config));
3572 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
3573 config.netrole = DPP_NETROLE_AP;
3574 config.msg_ctx = hapd->msg_ctx;
3575 config.cb_ctx = hapd;
3576 config.process_conf_obj = hostapd_dpp_process_conf_obj;
3577 if (cmd) {
3578 pos = os_strstr(cmd, " tcp_port=");
3579 if (pos) {
3580 pos += 10;
3581 config.tcp_port = atoi(pos);
3582 }
3583
3584 pos = os_strstr(cmd, " role=");
3585 if (pos) {
3586 pos += 6;
3587 if (os_strncmp(pos, "configurator", 12) == 0)
3588 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
3589 else if (os_strncmp(pos, "enrollee", 8) == 0)
3590 config.allowed_roles = DPP_CAPAB_ENROLLEE;
3591 else if (os_strncmp(pos, "either", 6) == 0)
3592 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
3593 DPP_CAPAB_ENROLLEE;
3594 else
3595 return -1;
3596 }
3597
3598 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
3599 }
3600 config.configurator_params = hapd->dpp_configurator_params;
3601 return dpp_controller_start(hapd->iface->interfaces->dpp, &config);
3602}
3603
3604
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003605static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
3606
3607static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
3608{
3609 struct hostapd_data *hapd = eloop_ctx;
3610
3611 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
3612 hostapd_drv_send_action_cancel_wait(hapd);
3613 hostapd_dpp_chirp_next(hapd, NULL);
3614}
3615
3616
3617static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
3618{
3619 struct wpabuf *msg;
3620 int type;
3621
3622 msg = hapd->dpp_presence_announcement;
3623 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
3624 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
3625 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3626 " freq=%u type=%d",
3627 MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
3628 if (hostapd_drv_send_action(
3629 hapd, hapd->dpp_chirp_freq, 2000, broadcast,
3630 wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
3631 eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
3632 hapd, NULL) < 0)
3633 hostapd_dpp_chirp_stop(hapd);
3634}
3635
3636
3637static struct hostapd_hw_modes *
3638dpp_get_mode(struct hostapd_data *hapd,
3639 enum hostapd_hw_mode mode)
3640{
3641 struct hostapd_hw_modes *modes = hapd->iface->hw_features;
3642 u16 num_modes = hapd->iface->num_hw_features;
3643 u16 i;
3644
3645 for (i = 0; i < num_modes; i++) {
3646 if (modes[i].mode != mode ||
3647 !modes[i].num_channels || !modes[i].channels)
3648 continue;
3649 return &modes[i];
3650 }
3651
3652 return NULL;
3653}
3654
3655
3656static void
3657hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
3658{
3659 struct hostapd_data *hapd = iface->bss[0];
3660 struct wpa_scan_results *scan_res;
3661 struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
3662 unsigned int i;
3663 struct hostapd_hw_modes *mode;
3664 int c;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003665 bool chan6 = hapd->iface->hw_features == NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003666
3667 if (!bi)
3668 return;
3669
3670 hapd->dpp_chirp_scan_done = 1;
3671
3672 scan_res = hostapd_driver_get_scan_results(hapd);
3673
3674 os_free(hapd->dpp_chirp_freqs);
3675 hapd->dpp_chirp_freqs = NULL;
3676
3677 /* Channels from own bootstrapping info */
3678 if (bi) {
3679 for (i = 0; i < bi->num_freq; i++)
3680 int_array_add_unique(&hapd->dpp_chirp_freqs,
3681 bi->freq[i]);
3682 }
3683
3684 /* Preferred chirping channels */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003685 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211G);
3686 if (mode) {
3687 for (c = 0; c < mode->num_channels; c++) {
3688 struct hostapd_channel_data *chan = &mode->channels[c];
3689
3690 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3691 HOSTAPD_CHAN_RADAR) ||
3692 chan->freq != 2437)
3693 continue;
3694 chan6 = true;
3695 break;
3696 }
3697 }
3698 if (chan6)
3699 int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003700
3701 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
3702 if (mode) {
3703 int chan44 = 0, chan149 = 0;
3704
3705 for (c = 0; c < mode->num_channels; c++) {
3706 struct hostapd_channel_data *chan = &mode->channels[c];
3707
3708 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3709 HOSTAPD_CHAN_RADAR))
3710 continue;
3711 if (chan->freq == 5220)
3712 chan44 = 1;
3713 if (chan->freq == 5745)
3714 chan149 = 1;
3715 }
3716 if (chan149)
3717 int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
3718 else if (chan44)
3719 int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
3720 }
3721
3722 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
3723 if (mode) {
3724 for (c = 0; c < mode->num_channels; c++) {
3725 struct hostapd_channel_data *chan = &mode->channels[c];
3726
3727 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
3728 HOSTAPD_CHAN_RADAR)) ||
3729 chan->freq != 60480)
3730 continue;
3731 int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
3732 break;
3733 }
3734 }
3735
3736 /* Add channels from scan results for APs that advertise Configurator
3737 * Connectivity element */
3738 for (i = 0; scan_res && i < scan_res->num; i++) {
3739 struct wpa_scan_res *bss = scan_res->res[i];
3740 size_t ie_len = bss->ie_len;
3741
3742 if (!ie_len)
3743 ie_len = bss->beacon_ie_len;
3744 if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
3745 DPP_CC_IE_VENDOR_TYPE))
3746 int_array_add_unique(&hapd->dpp_chirp_freqs,
3747 bss->freq);
3748 }
3749
3750 if (!hapd->dpp_chirp_freqs ||
3751 eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
3752 hapd, NULL) < 0)
3753 hostapd_dpp_chirp_stop(hapd);
3754
3755 wpa_scan_results_free(scan_res);
3756}
3757
3758
3759static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
3760{
3761 struct hostapd_data *hapd = eloop_ctx;
3762 int i;
3763
3764 if (hapd->dpp_chirp_listen)
3765 hostapd_dpp_listen_stop(hapd);
3766
3767 if (hapd->dpp_chirp_freq == 0) {
3768 if (hapd->dpp_chirp_round % 4 == 0 &&
3769 !hapd->dpp_chirp_scan_done) {
3770 struct wpa_driver_scan_params params;
3771 int ret;
3772
3773 wpa_printf(MSG_DEBUG,
3774 "DPP: Update channel list for chirping");
3775 os_memset(&params, 0, sizeof(params));
3776 ret = hostapd_driver_scan(hapd, &params);
3777 if (ret < 0) {
3778 wpa_printf(MSG_DEBUG,
3779 "DPP: Failed to request a scan ret=%d (%s)",
3780 ret, strerror(-ret));
3781 hostapd_dpp_chirp_scan_res_handler(hapd->iface);
3782 } else {
3783 hapd->iface->scan_cb =
3784 hostapd_dpp_chirp_scan_res_handler;
3785 }
3786 return;
3787 }
3788 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
3789 hapd->dpp_chirp_round++;
3790 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
3791 hapd->dpp_chirp_round);
3792 } else {
3793 for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
3794 if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
3795 break;
3796 if (!hapd->dpp_chirp_freqs[i]) {
3797 wpa_printf(MSG_DEBUG,
3798 "DPP: Previous chirp freq %d not found",
3799 hapd->dpp_chirp_freq);
3800 return;
3801 }
3802 i++;
3803 if (hapd->dpp_chirp_freqs[i]) {
3804 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
3805 } else {
3806 hapd->dpp_chirp_iter--;
3807 if (hapd->dpp_chirp_iter <= 0) {
3808 wpa_printf(MSG_DEBUG,
3809 "DPP: Chirping iterations completed");
3810 hostapd_dpp_chirp_stop(hapd);
3811 return;
3812 }
3813 hapd->dpp_chirp_freq = 0;
3814 hapd->dpp_chirp_scan_done = 0;
3815 if (eloop_register_timeout(30, 0,
3816 hostapd_dpp_chirp_next,
3817 hapd, NULL) < 0) {
3818 hostapd_dpp_chirp_stop(hapd);
3819 return;
3820 }
3821 if (hapd->dpp_chirp_listen) {
3822 wpa_printf(MSG_DEBUG,
3823 "DPP: Listen on %d MHz during chirp 30 second wait",
3824 hapd->dpp_chirp_listen);
3825 /* TODO: start listen on the channel */
3826 } else {
3827 wpa_printf(MSG_DEBUG,
3828 "DPP: Wait 30 seconds before starting the next chirping round");
3829 }
3830 return;
3831 }
3832 }
3833
3834 hostapd_dpp_chirp_start(hapd);
3835}
3836
3837
3838int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
3839{
3840 const char *pos;
3841 int iter = 1, listen_freq = 0;
3842 struct dpp_bootstrap_info *bi;
3843
3844 pos = os_strstr(cmd, " own=");
3845 if (!pos)
3846 return -1;
3847 pos += 5;
3848 bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
3849 if (!bi) {
3850 wpa_printf(MSG_DEBUG,
3851 "DPP: Identified bootstrap info not found");
3852 return -1;
3853 }
3854
3855 pos = os_strstr(cmd, " iter=");
3856 if (pos) {
3857 iter = atoi(pos + 6);
3858 if (iter <= 0)
3859 return -1;
3860 }
3861
3862 pos = os_strstr(cmd, " listen=");
3863 if (pos) {
3864 listen_freq = atoi(pos + 8);
3865 if (listen_freq <= 0)
3866 return -1;
3867 }
3868
3869 hostapd_dpp_chirp_stop(hapd);
3870 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
3871 hapd->dpp_qr_mutual = 0;
3872 hapd->dpp_chirp_bi = bi;
3873 hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
3874 if (!hapd->dpp_presence_announcement)
3875 return -1;
3876 hapd->dpp_chirp_iter = iter;
3877 hapd->dpp_chirp_round = 0;
3878 hapd->dpp_chirp_scan_done = 0;
3879 hapd->dpp_chirp_listen = listen_freq;
3880
3881 return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
3882}
3883
3884
3885void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
3886{
3887 if (hapd->dpp_presence_announcement) {
3888 hostapd_drv_send_action_cancel_wait(hapd);
3889 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
3890 }
3891 hapd->dpp_chirp_bi = NULL;
3892 wpabuf_free(hapd->dpp_presence_announcement);
3893 hapd->dpp_presence_announcement = NULL;
3894 if (hapd->dpp_chirp_listen)
3895 hostapd_dpp_listen_stop(hapd);
3896 hapd->dpp_chirp_listen = 0;
3897 hapd->dpp_chirp_freq = 0;
3898 os_free(hapd->dpp_chirp_freqs);
3899 hapd->dpp_chirp_freqs = NULL;
3900 eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
3901 eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
3902 if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
3903 /* TODO: abort ongoing scan */
3904 hapd->iface->scan_cb = NULL;
3905 }
3906}
3907
3908
3909static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
3910{
3911 struct dpp_bootstrap_info *bi = ctx;
3912 size_t i;
3913
3914 for (i = 0; i < iface->num_bss; i++) {
3915 struct hostapd_data *hapd = iface->bss[i];
3916
3917 if (bi == hapd->dpp_chirp_bi)
3918 hostapd_dpp_chirp_stop(hapd);
3919 }
3920
3921 return 0;
3922}
3923
3924
3925void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
3926{
3927 struct hapd_interfaces *interfaces = ctx;
3928
3929 hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
3930}
3931
3932#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07003933
3934
3935#ifdef CONFIG_DPP3
3936
3937static void hostapd_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
3938{
3939 struct hostapd_data *hapd = eloop_ctx;
3940
3941 wpa_printf(MSG_DEBUG, "DPP: Active push button mode expired");
3942 hostapd_dpp_push_button_stop(hapd);
3943}
3944
3945
3946int hostapd_dpp_push_button(struct hostapd_data *hapd, const char *cmd)
3947{
3948 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3949
3950 if (!ifaces || !ifaces->dpp)
3951 return -1;
3952 os_get_reltime(&ifaces->dpp_pb_time);
3953 ifaces->dpp_pb_announce_time.sec = 0;
3954 ifaces->dpp_pb_announce_time.usec = 0;
3955 str_clear_free(ifaces->dpp_pb_cmd);
3956 ifaces->dpp_pb_cmd = NULL;
3957 if (cmd) {
3958 ifaces->dpp_pb_cmd = os_strdup(cmd);
3959 if (!ifaces->dpp_pb_cmd)
3960 return -1;
3961 }
3962 eloop_register_timeout(100, 0, hostapd_dpp_push_button_expire,
3963 hapd, NULL);
3964
Sunil Ravi99c035e2024-07-12 01:42:03 +00003965 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PB_STATUS "started");
Sunil Ravi89eba102022-09-13 21:04:37 -07003966 return 0;
3967}
3968
3969
3970void hostapd_dpp_push_button_stop(struct hostapd_data *hapd)
3971{
3972 struct hapd_interfaces *ifaces = hapd->iface->interfaces;
3973
3974 if (!ifaces || !ifaces->dpp)
3975 return;
3976 eloop_cancel_timeout(hostapd_dpp_push_button_expire, hapd, NULL);
3977 if (hostapd_dpp_pb_active(hapd)) {
3978 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
3979 if (!ifaces->dpp_pb_result_indicated)
3980 wpa_msg(hapd->msg_ctx, MSG_INFO,
3981 DPP_EVENT_PB_RESULT "failed");
3982 }
3983 ifaces->dpp_pb_time.sec = 0;
3984 ifaces->dpp_pb_time.usec = 0;
3985 dpp_pkex_free(hapd->dpp_pkex);
3986 hapd->dpp_pkex = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003987 hapd->dpp_pkex_bi = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003988 os_free(hapd->dpp_pkex_auth_cmd);
3989 hapd->dpp_pkex_auth_cmd = NULL;
3990
3991 if (ifaces->dpp_pb_bi) {
3992 char id[20];
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003993 size_t i;
3994
3995 for (i = 0; i < ifaces->count; i++) {
3996 struct hostapd_iface *iface = ifaces->iface[i];
3997 size_t j;
3998
3999 for (j = 0; iface && j < iface->num_bss; j++) {
4000 struct hostapd_data *h = iface->bss[j];
4001
4002 if (h->dpp_pkex_bi == ifaces->dpp_pb_bi)
4003 h->dpp_pkex_bi = NULL;
4004 }
4005 }
Sunil Ravi89eba102022-09-13 21:04:37 -07004006
4007 os_snprintf(id, sizeof(id), "%u", ifaces->dpp_pb_bi->id);
4008 dpp_bootstrap_remove(ifaces->dpp, id);
4009 ifaces->dpp_pb_bi = NULL;
4010 }
4011
4012 ifaces->dpp_pb_result_indicated = false;
4013
4014 str_clear_free(ifaces->dpp_pb_cmd);
4015 ifaces->dpp_pb_cmd = NULL;
4016}
4017
4018#endif /* CONFIG_DPP3 */
4019
4020
4021#ifdef CONFIG_DPP2
4022bool hostapd_dpp_configurator_connectivity(struct hostapd_data *hapd)
4023{
4024 return hapd->conf->dpp_configurator_connectivity ||
4025 (hapd->iface->interfaces &&
4026 dpp_relay_controller_available(hapd->iface->interfaces->dpp));
4027}
4028#endif /* CONFIG_DPP2 */