blob: 2613c0cbbc86fede18a567fd1f3932faaefbd3d9 [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * hostapd / DPP integration
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
Hai Shalomfdcde762020-04-02 11:19:20 -07004 * Copyright (c) 2018-2020, The Linux Foundation
Hai Shaloma20dcd72022-02-04 13:43:00 -08005 * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "utils/includes.h"
12
13#include "utils/common.h"
14#include "utils/eloop.h"
15#include "common/dpp.h"
16#include "common/gas.h"
17#include "common/wpa_ctrl.h"
18#include "hostapd.h"
19#include "ap_drv_ops.h"
20#include "gas_query_ap.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070021#include "gas_serv.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070022#include "wpa_auth.h"
23#include "dpp_hostapd.h"
24
25
Roshan Pius3a1667e2018-07-03 15:17:14 -070026static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom60840252021-02-19 19:02:11 -080027static void hostapd_dpp_auth_conf_wait_timeout(void *eloop_ctx,
28 void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070029static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -070030static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
31static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
Hai Shaloma20dcd72022-02-04 13:43:00 -080032static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
33 struct dpp_authentication *auth);
Sunil Ravia04bd252022-05-02 22:54:18 -070034static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070035#ifdef CONFIG_DPP2
36static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
37 void *timeout_ctx);
Hai Shalom899fcc72020-10-19 14:38:18 -070038static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
39 struct dpp_authentication *auth,
40 struct dpp_config_obj *conf);
Hai Shaloma20dcd72022-02-04 13:43:00 -080041static int hostapd_dpp_process_conf_obj(void *ctx,
42 struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070043#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070044
45static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
46
47
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070048/**
49 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
50 * @hapd: Pointer to hostapd_data
51 * @cmd: DPP URI read from a QR Code
52 * Returns: Identifier of the stored info or -1 on failure
53 */
54int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
55{
56 struct dpp_bootstrap_info *bi;
57 struct dpp_authentication *auth = hapd->dpp_auth;
58
Hai Shalom021b0b52019-04-10 11:17:58 -070059 bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070060 if (!bi)
61 return -1;
62
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070063 if (auth && auth->response_pending &&
64 dpp_notify_new_qr_code(auth, bi) == 1) {
65 wpa_printf(MSG_DEBUG,
66 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070067 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
68 " freq=%u type=%d",
69 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
70 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070071 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
72 auth->peer_mac_addr,
73 wpabuf_head(hapd->dpp_auth->resp_msg),
74 wpabuf_len(hapd->dpp_auth->resp_msg));
75 }
76
Hai Shalom899fcc72020-10-19 14:38:18 -070077#ifdef CONFIG_DPP2
78 dpp_controller_new_qr_code(hapd->iface->interfaces->dpp, bi);
79#endif /* CONFIG_DPP2 */
80
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070081 return bi->id;
82}
83
84
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080085/**
86 * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
87 * @hapd: Pointer to hostapd_data
88 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
89 * Returns: Identifier of the stored info or -1 on failure
90 */
91int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
92{
93 struct dpp_bootstrap_info *bi;
94
95 bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
96 if (!bi)
97 return -1;
98
99 return bi->id;
100}
101
102
Hai Shalomfdcde762020-04-02 11:19:20 -0700103int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd)
104{
105 const char *pos;
106 struct dpp_bootstrap_info *peer_bi, *own_bi;
107
108 pos = os_strstr(cmd, " own=");
109 if (!pos)
110 return -1;
111 pos += 5;
112 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
113 if (!own_bi)
114 return -1;
115
116 pos = os_strstr(cmd, " uri=");
117 if (!pos)
118 return -1;
119 pos += 5;
120 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
121 if (!peer_bi) {
122 wpa_printf(MSG_INFO,
123 "DPP: Failed to parse URI from NFC Handover Request");
124 return -1;
125 }
126
127 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
128 return -1;
129
130 return peer_bi->id;
131}
132
133
134int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd)
135{
136 const char *pos;
137 struct dpp_bootstrap_info *peer_bi, *own_bi;
138
139 pos = os_strstr(cmd, " own=");
140 if (!pos)
141 return -1;
142 pos += 5;
143 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
144 if (!own_bi)
145 return -1;
146
147 pos = os_strstr(cmd, " uri=");
148 if (!pos)
149 return -1;
150 pos += 5;
151 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
152 if (!peer_bi) {
153 wpa_printf(MSG_INFO,
154 "DPP: Failed to parse URI from NFC Handover Select");
155 return -1;
156 }
157
158 if (peer_bi->curve != own_bi->curve) {
159 wpa_printf(MSG_INFO,
160 "DPP: Peer (NFC Handover Selector) used different curve");
161 return -1;
162 }
163
164 return peer_bi->id;
165}
166
167
Roshan Pius3a1667e2018-07-03 15:17:14 -0700168static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
169 void *timeout_ctx)
170{
171 struct hostapd_data *hapd = eloop_ctx;
172 struct dpp_authentication *auth = hapd->dpp_auth;
173
174 if (!auth || !auth->resp_msg)
175 return;
176
177 wpa_printf(MSG_DEBUG,
178 "DPP: Retry Authentication Response after timeout");
179 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
180 " freq=%u type=%d",
181 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
182 DPP_PA_AUTHENTICATION_RESP);
183 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
184 wpabuf_head(auth->resp_msg),
185 wpabuf_len(auth->resp_msg));
186}
187
188
189static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
190{
191 struct dpp_authentication *auth = hapd->dpp_auth;
192 unsigned int wait_time, max_tries;
193
194 if (!auth || !auth->resp_msg)
195 return;
196
197 if (hapd->dpp_resp_max_tries)
198 max_tries = hapd->dpp_resp_max_tries;
199 else
200 max_tries = 5;
201 auth->auth_resp_tries++;
202 if (auth->auth_resp_tries >= max_tries) {
203 wpa_printf(MSG_INFO,
204 "DPP: No confirm received from initiator - stopping exchange");
205 hostapd_drv_send_action_cancel_wait(hapd);
206 dpp_auth_deinit(hapd->dpp_auth);
207 hapd->dpp_auth = NULL;
208 return;
209 }
210
211 if (hapd->dpp_resp_retry_time)
212 wait_time = hapd->dpp_resp_retry_time;
213 else
214 wait_time = 1000;
215 wpa_printf(MSG_DEBUG,
216 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
217 wait_time);
218 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
219 eloop_register_timeout(wait_time / 1000,
220 (wait_time % 1000) * 1000,
221 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
222}
223
224
Hai Shaloma20dcd72022-02-04 13:43:00 -0800225static int hostapd_dpp_allow_ir(struct hostapd_data *hapd, unsigned int freq)
226{
227 int i, j;
228
229 if (!hapd->iface->hw_features)
230 return -1;
231
232 for (i = 0; i < hapd->iface->num_hw_features; i++) {
233 struct hostapd_hw_modes *mode = &hapd->iface->hw_features[i];
234
235 for (j = 0; j < mode->num_channels; j++) {
236 struct hostapd_channel_data *chan = &mode->channels[j];
237
238 if (chan->freq != (int) freq)
239 continue;
240
241 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
242 HOSTAPD_CHAN_NO_IR |
243 HOSTAPD_CHAN_RADAR))
244 continue;
245
246 return 1;
247 }
248 }
249
250 wpa_printf(MSG_DEBUG,
251 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
252 freq);
253
254 return 0;
255}
256
257
258static int hostapd_dpp_pkex_next_channel(struct hostapd_data *hapd,
259 struct dpp_pkex *pkex)
260{
261 if (pkex->freq == 2437)
262 pkex->freq = 5745;
263 else if (pkex->freq == 5745)
264 pkex->freq = 5220;
265 else if (pkex->freq == 5220)
266 pkex->freq = 60480;
267 else
268 return -1; /* no more channels to try */
269
270 if (hostapd_dpp_allow_ir(hapd, pkex->freq) == 1) {
271 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
272 pkex->freq);
273 return 0;
274 }
275
276 /* Could not use this channel - try the next one */
277 return hostapd_dpp_pkex_next_channel(hapd, pkex);
278}
279
280
281#ifdef CONFIG_DPP2
282static int hostapd_dpp_pkex_done(void *ctx, void *conn,
283 struct dpp_bootstrap_info *peer_bi)
284{
285 struct hostapd_data *hapd = ctx;
286 const char *cmd = hapd->dpp_pkex_auth_cmd;
287 const char *pos;
288 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
289 struct dpp_bootstrap_info *own_bi = NULL;
290 struct dpp_authentication *auth;
291
292 if (!cmd)
293 cmd = "";
294 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
295 cmd);
296
297 pos = os_strstr(cmd, " own=");
298 if (pos) {
299 pos += 5;
300 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
301 atoi(pos));
302 if (!own_bi) {
303 wpa_printf(MSG_INFO,
304 "DPP: Could not find bootstrapping info for the identified local entry");
305 return -1;
306 }
307
308 if (peer_bi->curve != own_bi->curve) {
309 wpa_printf(MSG_INFO,
310 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
311 peer_bi->curve->name, own_bi->curve->name);
312 return -1;
313 }
314 }
315
316 pos = os_strstr(cmd, " role=");
317 if (pos) {
318 pos += 6;
319 if (os_strncmp(pos, "configurator", 12) == 0)
320 allowed_roles = DPP_CAPAB_CONFIGURATOR;
321 else if (os_strncmp(pos, "enrollee", 8) == 0)
322 allowed_roles = DPP_CAPAB_ENROLLEE;
323 else if (os_strncmp(pos, "either", 6) == 0)
324 allowed_roles = DPP_CAPAB_CONFIGURATOR |
325 DPP_CAPAB_ENROLLEE;
326 else
327 return -1;
328 }
329
330 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
331 peer_bi, own_bi, allowed_roles, 0,
332 hapd->iface->hw_features,
333 hapd->iface->num_hw_features);
334 if (!auth)
335 return -1;
336
337 hostapd_dpp_set_testing_options(hapd, auth);
338 if (dpp_set_configurator(auth, cmd) < 0) {
339 dpp_auth_deinit(auth);
340 return -1;
341 }
342
343 return dpp_tcp_auth(hapd->iface->interfaces->dpp, conn, auth,
344 hapd->conf->dpp_name, DPP_NETROLE_AP,
345 hostapd_dpp_process_conf_obj, NULL);
346}
347#endif /* CONFIG_DPP2 */
348
349
Hai Shaloma20dcd72022-02-04 13:43:00 -0800350static int hostapd_dpp_pkex_init(struct hostapd_data *hapd,
Sunil Ravia04bd252022-05-02 22:54:18 -0700351 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800352 const struct hostapd_ip_addr *ipaddr,
353 int tcp_port)
354{
355 struct dpp_pkex *pkex;
356 struct wpabuf *msg;
357 unsigned int wait_time;
358 bool v2 = ver != PKEX_VER_ONLY_1;
359
360 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
361 dpp_pkex_free(hapd->dpp_pkex);
362 hapd->dpp_pkex = NULL;
363 pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr,
364 hapd->dpp_pkex_identifier,
365 hapd->dpp_pkex_code, v2);
366 if (!pkex)
367 return -1;
368 pkex->forced_ver = ver != PKEX_VER_AUTO;
369
370 if (ipaddr) {
371#ifdef CONFIG_DPP2
372 return dpp_tcp_pkex_init(hapd->iface->interfaces->dpp, pkex,
373 ipaddr, tcp_port,
374 hapd->msg_ctx, hapd,
375 hostapd_dpp_pkex_done);
376#else /* CONFIG_DPP2 */
377 return -1;
378#endif /* CONFIG_DPP2 */
379 }
380
381 hapd->dpp_pkex = pkex;
382 msg = hapd->dpp_pkex->exchange_req;
383 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
384 pkex->freq = 2437;
385 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
386 " freq=%u type=%d", MAC2STR(broadcast), pkex->freq,
387 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
388 DPP_PA_PKEX_V1_EXCHANGE_REQ);
389 hostapd_drv_send_action(hapd, pkex->freq, 0, broadcast,
390 wpabuf_head(msg), wpabuf_len(msg));
391 pkex->exch_req_wait_time = wait_time;
392 pkex->exch_req_tries = 1;
393
394 return 0;
395}
396
397
398static void hostapd_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
399{
400 struct hostapd_data *hapd = eloop_ctx;
401 struct dpp_pkex *pkex = hapd->dpp_pkex;
402
403 if (!pkex || !pkex->exchange_req)
404 return;
405 if (pkex->exch_req_tries >= 5) {
406 if (hostapd_dpp_pkex_next_channel(hapd, pkex) < 0) {
407#ifdef CONFIG_DPP3
408 if (pkex->v2 && !pkex->forced_ver) {
409 wpa_printf(MSG_DEBUG,
410 "DPP: Fall back to PKEXv1");
411 hostapd_dpp_pkex_init(hapd, PKEX_VER_ONLY_1,
412 NULL, 0);
413 return;
414 }
415#endif /* CONFIG_DPP3 */
416 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
417 "No response from PKEX peer");
418 dpp_pkex_free(pkex);
419 hapd->dpp_pkex = NULL;
420 return;
421 }
422 pkex->exch_req_tries = 0;
423 }
424
425 pkex->exch_req_tries++;
426 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
427 pkex->exch_req_tries);
428 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
429 " freq=%u type=%d",
430 MAC2STR(broadcast), pkex->freq,
431 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
432 DPP_PA_PKEX_V1_EXCHANGE_REQ);
433 hostapd_drv_send_action(hapd, pkex->freq, pkex->exch_req_wait_time,
434 broadcast,
435 wpabuf_head(pkex->exchange_req),
436 wpabuf_len(pkex->exchange_req));
437}
438
439
440static void hostapd_dpp_pkex_tx_status(struct hostapd_data *hapd, const u8 *dst,
441 const u8 *data, size_t data_len, int ok)
442{
443 struct dpp_pkex *pkex = hapd->dpp_pkex;
444
445 if (pkex->failed) {
446 wpa_printf(MSG_DEBUG,
447 "DPP: Terminate PKEX exchange due to an earlier error");
448 if (pkex->t > pkex->own_bi->pkex_t)
449 pkex->own_bi->pkex_t = pkex->t;
450 dpp_pkex_free(pkex);
451 hapd->dpp_pkex = NULL;
452 return;
453 }
454
455 if (pkex->exch_req_wait_time && pkex->exchange_req) {
456 /* Wait for PKEX Exchange Response frame and retry request if
457 * no response is seen. */
458 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd,
459 NULL);
460 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
461 (pkex->exch_req_wait_time % 1000) * 1000,
462 hostapd_dpp_pkex_retry_timeout, hapd,
463 NULL);
464 }
465}
466
467
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700468void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
469 const u8 *data, size_t data_len, int ok)
470{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700471 struct dpp_authentication *auth = hapd->dpp_auth;
472
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700473 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
474 MAC2STR(dst), ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700475 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
476 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700477
478 if (!hapd->dpp_auth) {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800479 if (hapd->dpp_pkex) {
480 hostapd_dpp_pkex_tx_status(hapd, dst, data, data_len,
481 ok);
482 return;
483 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700484 wpa_printf(MSG_DEBUG,
485 "DPP: Ignore TX status since there is no ongoing authentication exchange");
486 return;
487 }
488
Hai Shalom021b0b52019-04-10 11:17:58 -0700489#ifdef CONFIG_DPP2
490 if (auth->connect_on_tx_status) {
491 wpa_printf(MSG_DEBUG,
492 "DPP: Complete exchange on configuration result");
493 dpp_auth_deinit(hapd->dpp_auth);
494 hapd->dpp_auth = NULL;
495 return;
496 }
497#endif /* CONFIG_DPP2 */
498
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700499 if (hapd->dpp_auth->remove_on_tx_status) {
500 wpa_printf(MSG_DEBUG,
501 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700502 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
503 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
504 hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800505 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout,
506 hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700507 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
508 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700509#ifdef CONFIG_DPP2
510 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
511 hapd, NULL);
512#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700513 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700514 dpp_auth_deinit(hapd->dpp_auth);
515 hapd->dpp_auth = NULL;
516 return;
517 }
518
519 if (hapd->dpp_auth_ok_on_ack)
520 hostapd_dpp_auth_success(hapd, 1);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700521
522 if (!is_broadcast_ether_addr(dst) && !ok) {
523 wpa_printf(MSG_DEBUG,
524 "DPP: Unicast DPP Action frame was not ACKed");
525 if (auth->waiting_auth_resp) {
526 /* In case of DPP Authentication Request frame, move to
527 * the next channel immediately. */
528 hostapd_drv_send_action_cancel_wait(hapd);
529 hostapd_dpp_auth_init_next(hapd);
530 return;
531 }
532 if (auth->waiting_auth_conf) {
533 hostapd_dpp_auth_resp_retry(hapd);
534 return;
535 }
536 }
537
Hai Shalom60840252021-02-19 19:02:11 -0800538 if (auth->waiting_auth_conf &&
539 auth->auth_resp_status == DPP_STATUS_OK) {
540 /* Make sure we do not get stuck waiting for Auth Confirm
541 * indefinitely after successfully transmitted Auth Response to
542 * allow new authentication exchanges to be started. */
543 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd,
544 NULL);
545 eloop_register_timeout(1, 0, hostapd_dpp_auth_conf_wait_timeout,
546 hapd, NULL);
547 }
548
Roshan Pius3a1667e2018-07-03 15:17:14 -0700549 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
550 /* Allow timeout handling to stop iteration if no response is
551 * received from a peer that has ACKed a request. */
552 auth->auth_req_ack = 1;
553 }
554
555 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
556 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
557 wpa_printf(MSG_DEBUG,
558 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
559 hapd->dpp_auth->curr_freq,
560 hapd->dpp_auth->neg_freq);
561 hostapd_drv_send_action_cancel_wait(hapd);
562
563 if (hapd->dpp_auth->neg_freq !=
564 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
565 /* TODO: Listen operation on non-operating channel */
566 wpa_printf(MSG_INFO,
567 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
568 hapd->dpp_auth->neg_freq, hapd->iface->freq);
569 }
570 }
571
572 if (hapd->dpp_auth_ok_on_ack)
573 hapd->dpp_auth_ok_on_ack = 0;
574}
575
576
577static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
578{
579 struct hostapd_data *hapd = eloop_ctx;
580 struct dpp_authentication *auth = hapd->dpp_auth;
581 unsigned int freq;
582 struct os_reltime now, diff;
583 unsigned int wait_time, diff_ms;
584
585 if (!auth || !auth->waiting_auth_resp)
586 return;
587
588 wait_time = hapd->dpp_resp_wait_time ?
589 hapd->dpp_resp_wait_time : 2000;
590 os_get_reltime(&now);
591 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
592 diff_ms = diff.sec * 1000 + diff.usec / 1000;
593 wpa_printf(MSG_DEBUG,
594 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
595 wait_time, diff_ms);
596
597 if (auth->auth_req_ack && diff_ms >= wait_time) {
598 /* Peer ACK'ed Authentication Request frame, but did not reply
599 * with Authentication Response frame within two seconds. */
600 wpa_printf(MSG_INFO,
601 "DPP: No response received from responder - stopping initiation attempt");
602 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
603 hostapd_drv_send_action_cancel_wait(hapd);
604 hostapd_dpp_listen_stop(hapd);
605 dpp_auth_deinit(auth);
606 hapd->dpp_auth = NULL;
607 return;
608 }
609
610 if (diff_ms >= wait_time) {
611 /* Authentication Request frame was not ACK'ed and no reply
612 * was receiving within two seconds. */
613 wpa_printf(MSG_DEBUG,
614 "DPP: Continue Initiator channel iteration");
615 hostapd_drv_send_action_cancel_wait(hapd);
616 hostapd_dpp_listen_stop(hapd);
617 hostapd_dpp_auth_init_next(hapd);
618 return;
619 }
620
621 /* Driver did not support 2000 ms long wait_time with TX command, so
622 * schedule listen operation to continue waiting for the response.
623 *
624 * DPP listen operations continue until stopped, so simply schedule a
625 * new call to this function at the point when the two second reply
626 * wait has expired. */
627 wait_time -= diff_ms;
628
629 freq = auth->curr_freq;
630 if (auth->neg_freq > 0)
631 freq = auth->neg_freq;
632 wpa_printf(MSG_DEBUG,
633 "DPP: Continue reply wait on channel %u MHz for %u ms",
634 freq, wait_time);
635 hapd->dpp_in_response_listen = 1;
636
637 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
638 /* TODO: Listen operation on non-operating channel */
639 wpa_printf(MSG_INFO,
640 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
641 freq, hapd->iface->freq);
642 }
643
644 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
645 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700646}
647
648
Hai Shalom60840252021-02-19 19:02:11 -0800649static void hostapd_dpp_auth_conf_wait_timeout(void *eloop_ctx,
650 void *timeout_ctx)
651{
652 struct hostapd_data *hapd = eloop_ctx;
653 struct dpp_authentication *auth = hapd->dpp_auth;
654
655 if (!auth || !auth->waiting_auth_conf)
656 return;
657
658 wpa_printf(MSG_DEBUG,
659 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
660 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
661 "No Auth Confirm received");
662 hostapd_drv_send_action_cancel_wait(hapd);
663 dpp_auth_deinit(auth);
664 hapd->dpp_auth = NULL;
665}
666
667
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700668static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
669 struct dpp_authentication *auth)
670{
671#ifdef CONFIG_TESTING_OPTIONS
672 if (hapd->dpp_config_obj_override)
673 auth->config_obj_override =
674 os_strdup(hapd->dpp_config_obj_override);
675 if (hapd->dpp_discovery_override)
676 auth->discovery_override =
677 os_strdup(hapd->dpp_discovery_override);
678 if (hapd->dpp_groups_override)
679 auth->groups_override = os_strdup(hapd->dpp_groups_override);
680 auth->ignore_netaccesskey_mismatch =
681 hapd->dpp_ignore_netaccesskey_mismatch;
682#endif /* CONFIG_TESTING_OPTIONS */
683}
684
685
Roshan Pius3a1667e2018-07-03 15:17:14 -0700686static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
687{
688 struct hostapd_data *hapd = eloop_ctx;
689
690 if (!hapd->dpp_auth)
691 return;
692 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
693 hostapd_dpp_auth_init_next(hapd);
694}
695
696
697static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
698{
699 struct dpp_authentication *auth = hapd->dpp_auth;
700 const u8 *dst;
701 unsigned int wait_time, max_wait_time, freq, max_tries, used;
702 struct os_reltime now, diff;
703
704 if (!auth)
705 return -1;
706
707 if (auth->freq_idx == 0)
708 os_get_reltime(&hapd->dpp_init_iter_start);
709
710 if (auth->freq_idx >= auth->num_freq) {
711 auth->num_freq_iters++;
712 if (hapd->dpp_init_max_tries)
713 max_tries = hapd->dpp_init_max_tries;
714 else
715 max_tries = 5;
716 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
717 wpa_printf(MSG_INFO,
718 "DPP: No response received from responder - stopping initiation attempt");
719 wpa_msg(hapd->msg_ctx, MSG_INFO,
720 DPP_EVENT_AUTH_INIT_FAILED);
721 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
722 hapd, NULL);
723 hostapd_drv_send_action_cancel_wait(hapd);
724 dpp_auth_deinit(hapd->dpp_auth);
725 hapd->dpp_auth = NULL;
726 return -1;
727 }
728 auth->freq_idx = 0;
729 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
730 if (hapd->dpp_init_retry_time)
731 wait_time = hapd->dpp_init_retry_time;
732 else
733 wait_time = 10000;
734 os_get_reltime(&now);
735 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
736 used = diff.sec * 1000 + diff.usec / 1000;
737 if (used > wait_time)
738 wait_time = 0;
739 else
740 wait_time -= used;
741 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
742 wait_time);
743 eloop_register_timeout(wait_time / 1000,
744 (wait_time % 1000) * 1000,
745 hostapd_dpp_init_timeout, hapd,
746 NULL);
747 return 0;
748 }
749 freq = auth->freq[auth->freq_idx++];
750 auth->curr_freq = freq;
751
Hai Shalom60840252021-02-19 19:02:11 -0800752 if (!is_zero_ether_addr(auth->peer_mac_addr))
753 dst = auth->peer_mac_addr;
754 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700755 dst = broadcast;
756 else
757 dst = auth->peer_bi->mac_addr;
758 hapd->dpp_auth_ok_on_ack = 0;
759 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
760 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
761 max_wait_time = hapd->dpp_resp_wait_time ?
762 hapd->dpp_resp_wait_time : 2000;
763 if (wait_time > max_wait_time)
764 wait_time = max_wait_time;
765 wait_time += 10; /* give the driver some extra time to complete */
766 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
767 hostapd_dpp_reply_wait_timeout, hapd, NULL);
768 wait_time -= 10;
769 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
770 wpa_printf(MSG_DEBUG,
771 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
772 freq, auth->neg_freq);
773 }
774 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
775 " freq=%u type=%d",
776 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
777 auth->auth_req_ack = 0;
778 os_get_reltime(&hapd->dpp_last_init);
779 return hostapd_drv_send_action(hapd, freq, wait_time,
780 dst,
781 wpabuf_head(hapd->dpp_auth->req_msg),
782 wpabuf_len(hapd->dpp_auth->req_msg));
783}
784
785
Hai Shalom899fcc72020-10-19 14:38:18 -0700786#ifdef CONFIG_DPP2
787static int hostapd_dpp_process_conf_obj(void *ctx,
788 struct dpp_authentication *auth)
789{
790 struct hostapd_data *hapd = ctx;
791 unsigned int i;
792
793 for (i = 0; i < auth->num_conf_obj; i++)
794 hostapd_dpp_handle_config_obj(hapd, auth,
795 &auth->conf_obj[i]);
796
797 return 0;
798}
799#endif /* CONFIG_DPP2 */
800
801
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700802int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
803{
804 const char *pos;
805 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -0700806 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700807 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
808 unsigned int neg_freq = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700809 int tcp = 0;
810#ifdef CONFIG_DPP2
811 int tcp_port = DPP_TCP_PORT;
812 struct hostapd_ip_addr ipaddr;
813 char *addr;
814#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700815
816 pos = os_strstr(cmd, " peer=");
817 if (!pos)
818 return -1;
819 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700820 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700821 if (!peer_bi) {
822 wpa_printf(MSG_INFO,
823 "DPP: Could not find bootstrapping info for the identified peer");
824 return -1;
825 }
826
Hai Shalom899fcc72020-10-19 14:38:18 -0700827#ifdef CONFIG_DPP2
828 pos = os_strstr(cmd, " tcp_port=");
829 if (pos) {
830 pos += 10;
831 tcp_port = atoi(pos);
832 }
833
834 addr = get_param(cmd, " tcp_addr=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000835 if (addr && os_strcmp(addr, "from-uri") == 0) {
836 os_free(addr);
837 if (!peer_bi->host) {
838 wpa_printf(MSG_INFO,
839 "DPP: TCP address not available in peer URI");
840 return -1;
841 }
842 tcp = 1;
843 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
844 tcp_port = peer_bi->port;
845 } else if (addr) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700846 int res;
847
848 res = hostapd_parse_ip_addr(addr, &ipaddr);
849 os_free(addr);
850 if (res)
851 return -1;
852 tcp = 1;
853 }
854#endif /* CONFIG_DPP2 */
855
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700856 pos = os_strstr(cmd, " own=");
857 if (pos) {
858 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700859 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
860 atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700861 if (!own_bi) {
862 wpa_printf(MSG_INFO,
863 "DPP: Could not find bootstrapping info for the identified local entry");
864 return -1;
865 }
866
867 if (peer_bi->curve != own_bi->curve) {
868 wpa_printf(MSG_INFO,
869 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
870 peer_bi->curve->name, own_bi->curve->name);
871 return -1;
872 }
873 }
874
875 pos = os_strstr(cmd, " role=");
876 if (pos) {
877 pos += 6;
878 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700879 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700880 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700881 allowed_roles = DPP_CAPAB_ENROLLEE;
882 else if (os_strncmp(pos, "either", 6) == 0)
883 allowed_roles = DPP_CAPAB_CONFIGURATOR |
884 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700885 else
886 goto fail;
887 }
888
Roshan Pius3a1667e2018-07-03 15:17:14 -0700889 pos = os_strstr(cmd, " neg_freq=");
890 if (pos)
891 neg_freq = atoi(pos + 10);
892
Hai Shalom899fcc72020-10-19 14:38:18 -0700893 if (!tcp && hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700894 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
895 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
896 hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800897 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout,
898 hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700899 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
900 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700901#ifdef CONFIG_DPP2
902 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
903 hapd, NULL);
904#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700905 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700906 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700907 }
908
Hai Shalom899fcc72020-10-19 14:38:18 -0700909 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
910 peer_bi, own_bi, allowed_roles, neg_freq,
911 hapd->iface->hw_features,
912 hapd->iface->num_hw_features);
913 if (!auth)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700914 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -0700915 hostapd_dpp_set_testing_options(hapd, auth);
916 if (dpp_set_configurator(auth, cmd) < 0) {
917 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800918 goto fail;
919 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700920
Hai Shalom899fcc72020-10-19 14:38:18 -0700921 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700922
Roshan Pius3a1667e2018-07-03 15:17:14 -0700923 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom899fcc72020-10-19 14:38:18 -0700924 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700925
Hai Shalom899fcc72020-10-19 14:38:18 -0700926#ifdef CONFIG_DPP2
927 if (tcp)
928 return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
929 &ipaddr, tcp_port, hapd->conf->dpp_name,
930 DPP_NETROLE_AP, hapd->msg_ctx, hapd,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800931 hostapd_dpp_process_conf_obj, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -0700932#endif /* CONFIG_DPP2 */
933
934 hapd->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700935 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700936fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700937 return -1;
938}
939
940
Roshan Pius3a1667e2018-07-03 15:17:14 -0700941int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
942{
943 int freq;
944
945 freq = atoi(cmd);
946 if (freq <= 0)
947 return -1;
948
949 if (os_strstr(cmd, " role=configurator"))
950 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
951 else if (os_strstr(cmd, " role=enrollee"))
952 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
953 else
954 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
955 DPP_CAPAB_ENROLLEE;
956 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
957
958 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
959 /* TODO: Listen operation on non-operating channel */
960 wpa_printf(MSG_INFO,
961 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
962 freq, hapd->iface->freq);
963 return -1;
964 }
965
Hai Shalom60840252021-02-19 19:02:11 -0800966 hostapd_drv_dpp_listen(hapd, true);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700967 return 0;
968}
969
970
971void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
972{
Hai Shalom60840252021-02-19 19:02:11 -0800973 hostapd_drv_dpp_listen(hapd, false);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700974 /* TODO: Stop listen operation on non-operating channel */
975}
976
977
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700978static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
979 const u8 *hdr, const u8 *buf, size_t len,
980 unsigned int freq)
981{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700982 const u8 *r_bootstrap, *i_bootstrap;
983 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700984 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
985
986 if (!hapd->iface->interfaces->dpp)
987 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700988
989 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
990 MAC2STR(src));
991
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700992#ifdef CONFIG_DPP2
993 hostapd_dpp_chirp_stop(hapd);
994#endif /* CONFIG_DPP2 */
995
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700996 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
997 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700998 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
999 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1000 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001001 return;
1002 }
1003 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1004 r_bootstrap, r_bootstrap_len);
1005
1006 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1007 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001008 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1009 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1010 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001011 return;
1012 }
1013 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1014 i_bootstrap, i_bootstrap_len);
1015
1016 /* Try to find own and peer bootstrapping key matches based on the
1017 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001018 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
1019 r_bootstrap, &own_bi, &peer_bi);
Hai Shalom81f62d82019-07-22 12:10:00 -07001020#ifdef CONFIG_DPP2
1021 if (!own_bi) {
1022 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1023 src, hdr, buf, len, freq, i_bootstrap,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001024 r_bootstrap, hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07001025 return;
1026 }
1027#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001028 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001029 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1030 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001031 return;
1032 }
1033
1034 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001035 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1036 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001037 return;
1038 }
1039
1040 hapd->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001041 hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
1042 hapd->msg_ctx, hapd->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001043 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001044 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001045 if (!hapd->dpp_auth) {
1046 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1047 return;
1048 }
1049 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001050 if (dpp_set_configurator(hapd->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001051 hapd->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001052 dpp_auth_deinit(hapd->dpp_auth);
1053 hapd->dpp_auth = NULL;
1054 return;
1055 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001056 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1057
Roshan Pius3a1667e2018-07-03 15:17:14 -07001058 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1059 " freq=%u type=%d",
1060 MAC2STR(src), hapd->dpp_auth->curr_freq,
1061 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001062 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
1063 src, wpabuf_head(hapd->dpp_auth->resp_msg),
1064 wpabuf_len(hapd->dpp_auth->resp_msg));
1065}
1066
1067
Roshan Pius3a1667e2018-07-03 15:17:14 -07001068static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
Hai Shalomc3565922019-10-28 11:58:20 -07001069 struct dpp_authentication *auth,
1070 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001071{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001072 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001073 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001074 dpp_akm_str(conf->akm));
1075 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001076 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001077 wpa_ssid_txt(conf->ssid, conf->ssid_len));
1078 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001079 /* TODO: Save the Connector and consider using a command
1080 * to fetch the value instead of sending an event with
1081 * it. The Connector could end up being larger than what
1082 * most clients are ready to receive as an event
1083 * message. */
1084 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001085 conf->connector);
Hai Shalomfdcde762020-04-02 11:19:20 -07001086 }
1087 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001088 char hex[64 * 2 + 1];
1089
1090 wpa_snprintf_hex(hex, sizeof(hex),
Hai Shalomc3565922019-10-28 11:58:20 -07001091 (const u8 *) conf->passphrase,
1092 os_strlen(conf->passphrase));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001093 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1094 hex);
Hai Shalomc3565922019-10-28 11:58:20 -07001095 } else if (conf->psk_set) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001096 char hex[PMK_LEN * 2 + 1];
1097
Hai Shalomc3565922019-10-28 11:58:20 -07001098 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001099 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1100 hex);
1101 }
Hai Shalomc3565922019-10-28 11:58:20 -07001102 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001103 char *hex;
1104 size_t hexlen;
1105
Hai Shalomc3565922019-10-28 11:58:20 -07001106 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001107 hex = os_malloc(hexlen);
1108 if (hex) {
1109 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001110 wpabuf_head(conf->c_sign_key),
1111 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001112 wpa_msg(hapd->msg_ctx, MSG_INFO,
1113 DPP_EVENT_C_SIGN_KEY "%s", hex);
1114 os_free(hex);
1115 }
1116 }
1117 if (auth->net_access_key) {
1118 char *hex;
1119 size_t hexlen;
1120
1121 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1122 hex = os_malloc(hexlen);
1123 if (hex) {
1124 wpa_snprintf_hex(hex, hexlen,
1125 wpabuf_head(auth->net_access_key),
1126 wpabuf_len(auth->net_access_key));
1127 if (auth->net_access_key_expiry)
1128 wpa_msg(hapd->msg_ctx, MSG_INFO,
1129 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1130 (unsigned long)
1131 auth->net_access_key_expiry);
1132 else
1133 wpa_msg(hapd->msg_ctx, MSG_INFO,
1134 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1135 os_free(hex);
1136 }
1137 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001138}
1139
1140
Hai Shalomfdcde762020-04-02 11:19:20 -07001141static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
1142 struct dpp_asymmetric_key *key)
1143{
1144#ifdef CONFIG_DPP2
1145 int res;
1146
1147 if (!key)
1148 return 0;
1149
1150 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1151 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
1152
1153 while (key) {
1154 res = dpp_configurator_from_backup(
1155 hapd->iface->interfaces->dpp, key);
1156 if (res < 0)
1157 return -1;
1158 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1159 res);
1160 key = key->next;
1161 }
1162#endif /* CONFIG_DPP2 */
1163
1164 return 0;
1165}
1166
1167
Sunil Ravia04bd252022-05-02 22:54:18 -07001168#ifdef CONFIG_DPP3
1169static void hostapd_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1170{
1171 struct hostapd_data *hapd = eloop_ctx;
1172 struct dpp_authentication *auth = hapd->dpp_auth;
1173
1174 if (!auth || !auth->waiting_new_key)
1175 return;
1176
1177 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1178 hostapd_dpp_start_gas_client(hapd);
1179}
1180#endif /* CONFIG_DPP3 */
1181
1182
Roshan Pius3a1667e2018-07-03 15:17:14 -07001183static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1184 enum gas_query_ap_result result,
1185 const struct wpabuf *adv_proto,
1186 const struct wpabuf *resp, u16 status_code)
1187{
1188 struct hostapd_data *hapd = ctx;
1189 const u8 *pos;
1190 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001191 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Sunil Ravia04bd252022-05-02 22:54:18 -07001192 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001193
1194 if (!auth || !auth->auth_success) {
1195 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1196 return;
1197 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001198 if (result != GAS_QUERY_AP_SUCCESS ||
1199 !resp || status_code != WLAN_STATUS_SUCCESS) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001200 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1201 goto fail;
1202 }
1203
1204 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1205 adv_proto);
1206 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1207 resp);
1208
1209 if (wpabuf_len(adv_proto) != 10 ||
1210 !(pos = wpabuf_head(adv_proto)) ||
1211 pos[0] != WLAN_EID_ADV_PROTO ||
1212 pos[1] != 8 ||
1213 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1214 pos[4] != 5 ||
1215 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1216 pos[8] != 0x1a ||
1217 pos[9] != 1) {
1218 wpa_printf(MSG_DEBUG,
1219 "DPP: Not a DPP Advertisement Protocol ID");
1220 goto fail;
1221 }
1222
Sunil Ravia04bd252022-05-02 22:54:18 -07001223 res = dpp_conf_resp_rx(auth, resp);
1224#ifdef CONFIG_DPP3
1225 if (res == -3) {
1226 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1227 eloop_register_timeout(0, 0, hostapd_dpp_build_new_key, hapd,
1228 NULL);
1229 return;
1230 }
1231#endif /* CONFIG_DPP3 */
1232 if (res < 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001233 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1234 goto fail;
1235 }
1236
Hai Shalomc3565922019-10-28 11:58:20 -07001237 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Hai Shalomfdcde762020-04-02 11:19:20 -07001238 if (hostapd_dpp_handle_key_pkg(hapd, auth->conf_key_pkg) < 0)
1239 goto fail;
1240
Hai Shalom021b0b52019-04-10 11:17:58 -07001241 status = DPP_STATUS_OK;
1242#ifdef CONFIG_TESTING_OPTIONS
1243 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1244 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1245 status = DPP_STATUS_CONFIG_REJECTED;
1246 }
1247#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001248fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001249 if (status != DPP_STATUS_OK)
1250 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1251#ifdef CONFIG_DPP2
1252 if (auth->peer_version >= 2 &&
1253 auth->conf_resp_status == DPP_STATUS_OK) {
1254 struct wpabuf *msg;
1255
1256 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1257 msg = dpp_build_conf_result(auth, status);
1258 if (!msg)
1259 goto fail2;
1260
1261 wpa_msg(hapd->msg_ctx, MSG_INFO,
1262 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1263 MAC2STR(addr), auth->curr_freq,
1264 DPP_PA_CONFIGURATION_RESULT);
1265 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
1266 addr, wpabuf_head(msg),
1267 wpabuf_len(msg));
1268 wpabuf_free(msg);
1269
1270 /* This exchange will be terminated in the TX status handler */
1271 auth->connect_on_tx_status = 1;
1272 return;
1273 }
1274fail2:
1275#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001276 dpp_auth_deinit(hapd->dpp_auth);
1277 hapd->dpp_auth = NULL;
1278}
1279
1280
1281static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
1282{
1283 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001284 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001285 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001286
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001287 buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
1288 DPP_NETROLE_AP,
Hai Shalomc3565922019-10-28 11:58:20 -07001289 hapd->conf->dpp_mud_url, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001290 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001291 wpa_printf(MSG_DEBUG,
1292 "DPP: No configuration request data available");
1293 return;
1294 }
1295
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001296 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1297 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1298
1299 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
1300 buf, hostapd_dpp_gas_resp_cb, hapd);
1301 if (res < 0) {
1302 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1303 "GAS: Failed to send Query Request");
1304 wpabuf_free(buf);
1305 } else {
1306 wpa_printf(MSG_DEBUG,
1307 "DPP: GAS query started with dialog token %u", res);
1308 }
1309}
1310
1311
1312static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
1313{
1314 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1315 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
1316 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001317#ifdef CONFIG_TESTING_OPTIONS
1318 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1319 wpa_printf(MSG_INFO,
1320 "DPP: TESTING - stop at Authentication Confirm");
1321 if (hapd->dpp_auth->configurator) {
1322 /* Prevent GAS response */
1323 hapd->dpp_auth->auth_success = 0;
1324 }
1325 return;
1326 }
1327#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001328
1329 if (!hapd->dpp_auth->configurator)
1330 hostapd_dpp_start_gas_client(hapd);
1331}
1332
1333
1334static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001335 const u8 *hdr, const u8 *buf, size_t len,
1336 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001337{
1338 struct dpp_authentication *auth = hapd->dpp_auth;
1339 struct wpabuf *msg;
1340
1341 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
1342 MAC2STR(src));
1343
1344 if (!auth) {
1345 wpa_printf(MSG_DEBUG,
1346 "DPP: No DPP Authentication in progress - drop");
1347 return;
1348 }
1349
1350 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1351 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1352 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1353 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1354 return;
1355 }
1356
Roshan Pius3a1667e2018-07-03 15:17:14 -07001357 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1358
1359 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1360 wpa_printf(MSG_DEBUG,
1361 "DPP: Responder accepted request for different negotiation channel");
1362 auth->curr_freq = freq;
1363 }
1364
1365 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001366 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1367 if (!msg) {
1368 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1369 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
1370 return;
1371 }
1372 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1373 return;
1374 }
1375 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1376
Roshan Pius3a1667e2018-07-03 15:17:14 -07001377 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1378 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
1379 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001380 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
1381 wpabuf_head(msg), wpabuf_len(msg));
1382 wpabuf_free(msg);
1383 hapd->dpp_auth_ok_on_ack = 1;
1384}
1385
1386
1387static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1388 const u8 *hdr, const u8 *buf, size_t len)
1389{
1390 struct dpp_authentication *auth = hapd->dpp_auth;
1391
1392 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1393 MAC2STR(src));
1394
1395 if (!auth) {
1396 wpa_printf(MSG_DEBUG,
1397 "DPP: No DPP Authentication in progress - drop");
1398 return;
1399 }
1400
1401 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1402 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1403 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1404 return;
1405 }
1406
1407 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1408 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1409 return;
1410 }
1411
1412 hostapd_dpp_auth_success(hapd, 0);
1413}
1414
1415
Hai Shalom021b0b52019-04-10 11:17:58 -07001416#ifdef CONFIG_DPP2
1417
1418static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
1419 void *timeout_ctx)
1420{
1421 struct hostapd_data *hapd = eloop_ctx;
1422 struct dpp_authentication *auth = hapd->dpp_auth;
1423
1424 if (!auth || !auth->waiting_conf_result)
1425 return;
1426
1427 wpa_printf(MSG_DEBUG,
1428 "DPP: Timeout while waiting for Configuration Result");
1429 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1430 dpp_auth_deinit(auth);
1431 hapd->dpp_auth = NULL;
1432}
1433
1434
Hai Shalomc3565922019-10-28 11:58:20 -07001435static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1436 void *timeout_ctx)
1437{
1438 struct hostapd_data *hapd = eloop_ctx;
1439 struct dpp_authentication *auth = hapd->dpp_auth;
1440
1441 if (!auth || !auth->waiting_conf_result)
1442 return;
1443
1444 wpa_printf(MSG_DEBUG,
1445 "DPP: Timeout while waiting for Connection Status Result");
1446 wpa_msg(hapd->msg_ctx, MSG_INFO,
1447 DPP_EVENT_CONN_STATUS_RESULT "timeout");
1448 dpp_auth_deinit(auth);
1449 hapd->dpp_auth = NULL;
1450}
1451
1452
Hai Shalom021b0b52019-04-10 11:17:58 -07001453static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
1454 const u8 *hdr, const u8 *buf, size_t len)
1455{
1456 struct dpp_authentication *auth = hapd->dpp_auth;
1457 enum dpp_status_error status;
1458
1459 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1460 MAC2STR(src));
1461
1462 if (!auth || !auth->waiting_conf_result) {
1463 wpa_printf(MSG_DEBUG,
1464 "DPP: No DPP Configuration waiting for result - drop");
1465 return;
1466 }
1467
1468 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1469 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1470 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1471 return;
1472 }
1473
1474 status = dpp_conf_result_rx(auth, hdr, buf, len);
1475
Hai Shalomc3565922019-10-28 11:58:20 -07001476 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1477 wpa_msg(hapd->msg_ctx, MSG_INFO,
1478 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1479 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1480 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1481 hapd, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001482 auth->waiting_conn_status_result = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001483 eloop_cancel_timeout(
1484 hostapd_dpp_conn_status_result_wait_timeout,
1485 hapd, NULL);
1486 eloop_register_timeout(
1487 16, 0, hostapd_dpp_conn_status_result_wait_timeout,
1488 hapd, NULL);
1489 return;
1490 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001491 hostapd_drv_send_action_cancel_wait(hapd);
1492 hostapd_dpp_listen_stop(hapd);
1493 if (status == DPP_STATUS_OK)
1494 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1495 else
1496 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1497 dpp_auth_deinit(auth);
1498 hapd->dpp_auth = NULL;
1499 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1500 NULL);
1501}
1502
Hai Shalomc3565922019-10-28 11:58:20 -07001503
1504static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
1505 const u8 *src, const u8 *hdr,
1506 const u8 *buf, size_t len)
1507{
1508 struct dpp_authentication *auth = hapd->dpp_auth;
1509 enum dpp_status_error status;
1510 u8 ssid[SSID_MAX_LEN];
1511 size_t ssid_len = 0;
1512 char *channel_list = NULL;
1513
1514 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1515
1516 if (!auth || !auth->waiting_conn_status_result) {
1517 wpa_printf(MSG_DEBUG,
1518 "DPP: No DPP Configuration waiting for connection status result - drop");
1519 return;
1520 }
1521
1522 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1523 ssid, &ssid_len, &channel_list);
1524 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1525 "result=%d ssid=%s channel_list=%s",
1526 status, wpa_ssid_txt(ssid, ssid_len),
1527 channel_list ? channel_list : "N/A");
1528 os_free(channel_list);
1529 hostapd_drv_send_action_cancel_wait(hapd);
1530 hostapd_dpp_listen_stop(hapd);
1531 dpp_auth_deinit(auth);
1532 hapd->dpp_auth = NULL;
1533 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
1534 hapd, NULL);
1535}
1536
1537
Hai Shalomfdcde762020-04-02 11:19:20 -07001538static void
1539hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
1540 const u8 *hdr, const u8 *buf, size_t len,
1541 unsigned int freq)
1542{
1543 const u8 *r_bootstrap;
1544 u16 r_bootstrap_len;
1545 struct dpp_bootstrap_info *peer_bi;
1546 struct dpp_authentication *auth;
1547
1548 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
1549 MAC2STR(src));
1550
1551 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1552 &r_bootstrap_len);
1553 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1554 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1555 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1556 return;
1557 }
1558 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1559 r_bootstrap, r_bootstrap_len);
1560 peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
1561 r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07001562 dpp_notify_chirp_received(hapd->msg_ctx,
1563 peer_bi ? (int) peer_bi->id : -1,
1564 src, freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07001565 if (!peer_bi) {
1566 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1567 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001568 r_bootstrap, hapd) == 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07001569 return;
1570 wpa_printf(MSG_DEBUG,
1571 "DPP: No matching bootstrapping information found");
1572 return;
1573 }
1574
1575 if (hapd->dpp_auth) {
1576 wpa_printf(MSG_DEBUG,
1577 "DPP: Ignore Presence Announcement during ongoing Authentication");
1578 return;
1579 }
1580
1581 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1582 peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
1583 0);
1584 if (!auth)
1585 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07001586 hostapd_dpp_set_testing_options(hapd, auth);
1587 if (dpp_set_configurator(auth,
Hai Shalomfdcde762020-04-02 11:19:20 -07001588 hapd->dpp_configurator_params) < 0) {
1589 dpp_auth_deinit(auth);
1590 return;
1591 }
1592
1593 auth->neg_freq = freq;
1594
Hai Shalom60840252021-02-19 19:02:11 -08001595 /* The source address of the Presence Announcement frame overrides any
1596 * MAC address information from the bootstrapping information. */
1597 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07001598
1599 hapd->dpp_auth = auth;
1600 if (hostapd_dpp_auth_init_next(hapd) < 0) {
1601 dpp_auth_deinit(hapd->dpp_auth);
1602 hapd->dpp_auth = NULL;
1603 }
1604}
1605
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001606
1607static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
1608 void *timeout_ctx)
1609{
1610 struct hostapd_data *hapd = eloop_ctx;
1611 struct dpp_authentication *auth = hapd->dpp_auth;
1612
1613 if (!auth)
1614 return;
1615
1616 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
1617 hostapd_dpp_listen_stop(hapd);
1618 dpp_auth_deinit(auth);
1619 hapd->dpp_auth = NULL;
1620}
1621
1622
1623static void
1624hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
1625 const u8 *hdr, const u8 *buf, size_t len,
1626 unsigned int freq)
1627{
Hai Shalom899fcc72020-10-19 14:38:18 -07001628 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
1629 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001630 struct dpp_configurator *conf;
1631 struct dpp_authentication *auth;
1632 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07001633 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001634
1635 if (hapd->dpp_auth) {
1636 wpa_printf(MSG_DEBUG,
1637 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1638 return;
1639 }
1640
1641 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
1642 MAC2STR(src));
1643
1644 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1645 &csign_hash_len);
1646 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
1647 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1648 "Missing or invalid required Configurator C-sign key Hash attribute");
1649 return;
1650 }
1651 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1652 csign_hash, csign_hash_len);
1653 conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
1654 csign_hash);
1655 if (!conf) {
1656 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1657 src, hdr, buf, len, freq, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001658 NULL, hapd) == 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001659 return;
1660 wpa_printf(MSG_DEBUG,
1661 "DPP: No matching Configurator information found");
1662 return;
1663 }
1664
Hai Shalom899fcc72020-10-19 14:38:18 -07001665 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
1666 &fcgroup_len);
1667 if (!fcgroup || fcgroup_len != 2) {
1668 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1669 "Missing or invalid required Finite Cyclic Group attribute");
1670 return;
1671 }
1672 group = WPA_GET_LE16(fcgroup);
1673 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
1674
1675 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
1676 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
1677
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001678 auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
Hai Shalom899fcc72020-10-19 14:38:18 -07001679 conf, freq, group, a_nonce, a_nonce_len,
1680 e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001681 if (!auth)
1682 return;
1683 hostapd_dpp_set_testing_options(hapd, auth);
1684 if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
1685 dpp_auth_deinit(auth);
1686 return;
1687 }
1688
1689 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1690 hapd->dpp_auth = auth;
1691
1692 hapd->dpp_in_response_listen = 0;
1693 hapd->dpp_auth_ok_on_ack = 0;
1694 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
1695 max_wait_time = hapd->dpp_resp_wait_time ?
1696 hapd->dpp_resp_wait_time : 2000;
1697 if (wait_time > max_wait_time)
1698 wait_time = max_wait_time;
1699 wait_time += 10; /* give the driver some extra time to complete */
1700 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
1701 hostapd_dpp_reconfig_reply_wait_timeout,
1702 hapd, NULL);
1703 wait_time -= 10;
1704
1705 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1706 " freq=%u type=%d",
1707 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
1708 if (hostapd_drv_send_action(hapd, freq, wait_time, src,
1709 wpabuf_head(auth->reconfig_req_msg),
1710 wpabuf_len(auth->reconfig_req_msg)) < 0) {
1711 dpp_auth_deinit(hapd->dpp_auth);
1712 hapd->dpp_auth = NULL;
1713 }
1714}
1715
1716
1717static void
1718hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
1719 const u8 *hdr, const u8 *buf, size_t len,
1720 unsigned int freq)
1721{
1722 struct dpp_authentication *auth = hapd->dpp_auth;
1723 struct wpabuf *conf;
1724
1725 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
1726 MACSTR, MAC2STR(src));
1727
1728 if (!auth || !auth->reconfig || !auth->configurator) {
1729 wpa_printf(MSG_DEBUG,
1730 "DPP: No DPP Reconfig Authentication in progress - drop");
1731 return;
1732 }
1733
1734 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1735 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1736 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1737 return;
1738 }
1739
1740 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
1741 if (!conf)
1742 return;
1743
1744 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1745 hapd, NULL);
1746
1747 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1748 " freq=%u type=%d",
1749 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
1750 if (hostapd_drv_send_action(hapd, freq, 500, src,
1751 wpabuf_head(conf), wpabuf_len(conf)) < 0) {
1752 wpabuf_free(conf);
1753 dpp_auth_deinit(hapd->dpp_auth);
1754 hapd->dpp_auth = NULL;
1755 return;
1756 }
1757 wpabuf_free(conf);
1758}
1759
Hai Shalom021b0b52019-04-10 11:17:58 -07001760#endif /* CONFIG_DPP2 */
1761
1762
Roshan Pius3a1667e2018-07-03 15:17:14 -07001763static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1764 const u8 *src, unsigned int freq,
1765 u8 trans_id,
1766 enum dpp_status_error status)
1767{
1768 struct wpabuf *msg;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001769 size_t len;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001770
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001771 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
1772#ifdef CONFIG_DPP2
1773 len += 5;
1774#endif /* CONFIG_DPP2 */
1775 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001776 if (!msg)
1777 return;
1778
1779#ifdef CONFIG_TESTING_OPTIONS
1780 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1781 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1782 goto skip_trans_id;
1783 }
1784 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1785 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1786 trans_id ^= 0x01;
1787 }
1788#endif /* CONFIG_TESTING_OPTIONS */
1789
1790 /* Transaction ID */
1791 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1792 wpabuf_put_le16(msg, 1);
1793 wpabuf_put_u8(msg, trans_id);
1794
1795#ifdef CONFIG_TESTING_OPTIONS
1796skip_trans_id:
1797 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1798 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1799 goto skip_status;
1800 }
1801 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1802 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1803 status = 254;
1804 }
1805#endif /* CONFIG_TESTING_OPTIONS */
1806
1807 /* DPP Status */
1808 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1809 wpabuf_put_le16(msg, 1);
1810 wpabuf_put_u8(msg, status);
1811
1812#ifdef CONFIG_TESTING_OPTIONS
1813skip_status:
1814 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1815 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1816 goto skip_connector;
1817 }
1818 if (status == DPP_STATUS_OK &&
1819 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1820 char *connector;
1821
1822 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1823 connector = dpp_corrupt_connector_signature(
1824 hapd->conf->dpp_connector);
1825 if (!connector) {
1826 wpabuf_free(msg);
1827 return;
1828 }
1829 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1830 wpabuf_put_le16(msg, os_strlen(connector));
1831 wpabuf_put_str(msg, connector);
1832 os_free(connector);
1833 goto skip_connector;
1834 }
1835#endif /* CONFIG_TESTING_OPTIONS */
1836
1837 /* DPP Connector */
1838 if (status == DPP_STATUS_OK) {
1839 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1840 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1841 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1842 }
1843
1844#ifdef CONFIG_TESTING_OPTIONS
1845skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001846 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP) {
1847 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
1848 goto skip_proto_ver;
1849 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001850#endif /* CONFIG_TESTING_OPTIONS */
1851
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001852#ifdef CONFIG_DPP2
1853 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001854 u8 ver = DPP_VERSION;
1855#ifdef CONFIG_DPP3
1856 int conn_ver;
1857
1858 conn_ver = dpp_get_connector_version(hapd->conf->dpp_connector);
1859 if (conn_ver > 0 && ver != conn_ver) {
1860 wpa_printf(MSG_DEBUG,
1861 "DPP: Use Connector version %d instead of current protocol version %d",
1862 conn_ver, ver);
1863 ver = conn_ver;
1864 }
1865#endif /* CONFIG_DPP3 */
1866
1867#ifdef CONFIG_TESTING_OPTIONS
1868 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP) {
1869 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
1870 ver = 1;
1871 }
1872#endif /* CONFIG_TESTING_OPTIONS */
1873
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001874 /* Protocol Version */
1875 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
1876 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001877 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001878 }
1879#endif /* CONFIG_DPP2 */
1880
Hai Shaloma20dcd72022-02-04 13:43:00 -08001881#ifdef CONFIG_TESTING_OPTIONS
1882skip_proto_ver:
1883#endif /* CONFIG_TESTING_OPTIONS */
1884
Roshan Pius3a1667e2018-07-03 15:17:14 -07001885 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1886 " status=%d", MAC2STR(src), status);
1887 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1888 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1889 DPP_PA_PEER_DISCOVERY_RESP, status);
1890 hostapd_drv_send_action(hapd, freq, 0, src,
1891 wpabuf_head(msg), wpabuf_len(msg));
1892 wpabuf_free(msg);
1893}
1894
1895
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001896static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1897 const u8 *src,
1898 const u8 *buf, size_t len,
1899 unsigned int freq)
1900{
1901 const u8 *connector, *trans_id;
1902 u16 connector_len, trans_id_len;
1903 struct os_time now;
1904 struct dpp_introduction intro;
1905 os_time_t expire;
1906 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001907 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001908
1909 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1910 MAC2STR(src));
1911 if (!hapd->wpa_auth ||
1912 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1913 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1914 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1915 return;
1916 }
1917
1918 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1919 !hapd->conf->dpp_csign) {
1920 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1921 return;
1922 }
1923
1924 os_get_time(&now);
1925
1926 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001927 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001928 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1929 return;
1930 }
1931
1932 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1933 &trans_id_len);
1934 if (!trans_id || trans_id_len != 1) {
1935 wpa_printf(MSG_DEBUG,
1936 "DPP: Peer did not include Transaction ID");
1937 return;
1938 }
1939
1940 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1941 if (!connector) {
1942 wpa_printf(MSG_DEBUG,
1943 "DPP: Peer did not include its Connector");
1944 return;
1945 }
1946
Roshan Pius3a1667e2018-07-03 15:17:14 -07001947 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1948 wpabuf_head(hapd->conf->dpp_netaccesskey),
1949 wpabuf_len(hapd->conf->dpp_netaccesskey),
1950 wpabuf_head(hapd->conf->dpp_csign),
1951 wpabuf_len(hapd->conf->dpp_csign),
1952 connector, connector_len, &expire);
1953 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001954 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001955 "DPP: Network Introduction protocol resulted in internal failure (peer "
1956 MACSTR ")", MAC2STR(src));
1957 return;
1958 }
1959 if (res != DPP_STATUS_OK) {
1960 wpa_printf(MSG_INFO,
1961 "DPP: Network Introduction protocol resulted in failure (peer "
1962 MACSTR " status %d)", MAC2STR(src), res);
1963 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1964 res);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001965 return;
1966 }
1967
Hai Shaloma20dcd72022-02-04 13:43:00 -08001968#ifdef CONFIG_DPP3
1969 if (intro.peer_version && intro.peer_version >= 2) {
1970 const u8 *version;
1971 u16 version_len;
1972 u8 attr_version = 1;
1973
1974 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
1975 &version_len);
1976 if (version && version_len >= 1)
1977 attr_version = version[0];
1978 if (attr_version != intro.peer_version) {
1979 wpa_printf(MSG_INFO,
1980 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
1981 intro.peer_version, attr_version);
1982 hostapd_dpp_send_peer_disc_resp(hapd, src, freq,
1983 trans_id[0],
1984 DPP_STATUS_NO_MATCH);
1985 return;
1986 }
1987 }
1988#endif /* CONFIG_DPP3 */
1989
Roshan Pius3a1667e2018-07-03 15:17:14 -07001990 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001991 expire = hapd->conf->dpp_netaccesskey_expiry;
1992 if (expire)
1993 expiration = expire - now.sec;
1994 else
1995 expiration = 0;
1996
1997 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1998 intro.pmkid, expiration,
1999 WPA_KEY_MGMT_DPP) < 0) {
2000 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
2001 return;
2002 }
2003
Roshan Pius3a1667e2018-07-03 15:17:14 -07002004 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
2005 DPP_STATUS_OK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002006}
2007
2008
2009static void
2010hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002011 const u8 *hdr, const u8 *buf, size_t len,
2012 unsigned int freq, bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002013{
2014 struct wpabuf *msg;
2015
2016 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
2017 MAC2STR(src));
2018
Sunil Ravia04bd252022-05-02 22:54:18 -07002019 if (hapd->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
2020 wpa_printf(MSG_DEBUG,
2021 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
2022 return;
2023 }
2024 if (hapd->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
2025 wpa_printf(MSG_DEBUG,
2026 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
2027 return;
2028 }
2029
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002030 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2031 * values here */
2032
2033 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
2034 wpa_printf(MSG_DEBUG,
2035 "DPP: No PKEX code configured - ignore request");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002036 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002037 }
2038
2039 if (hapd->dpp_pkex) {
2040 /* TODO: Support parallel operations */
2041 wpa_printf(MSG_DEBUG,
2042 "DPP: Already in PKEX session - ignore new request");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002043 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002044 }
2045
Roshan Pius3a1667e2018-07-03 15:17:14 -07002046 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
2047 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002048 hapd->own_addr, src,
2049 hapd->dpp_pkex_identifier,
2050 hapd->dpp_pkex_code,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002051 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002052 if (!hapd->dpp_pkex) {
2053 wpa_printf(MSG_DEBUG,
2054 "DPP: Failed to process the request - ignore it");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002055 goto try_relay;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002056 }
2057
2058 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002059 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2060 " freq=%u type=%d", MAC2STR(src), freq,
2061 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002062 hostapd_drv_send_action(hapd, freq, 0, src,
2063 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002064 if (hapd->dpp_pkex->failed) {
2065 wpa_printf(MSG_DEBUG,
2066 "DPP: Terminate PKEX exchange due to an earlier error");
2067 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
2068 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
2069 dpp_pkex_free(hapd->dpp_pkex);
2070 hapd->dpp_pkex = NULL;
2071 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002072
2073 return;
2074
2075try_relay:
2076#ifdef CONFIG_DPP2
Sunil8cd6f4d2022-06-28 18:40:46 +00002077 if (v2 && dpp_relay_rx_action(hapd->iface->interfaces->dpp,
2078 src, hdr, buf, len, freq, NULL, NULL,
2079 hapd) != 0)
2080 wpa_printf(MSG_DEBUG,
2081 "DPP: No Relay available for the message");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002082#else /* CONFIG_DPP2 */
2083 wpa_printf(MSG_DEBUG, "DPP: No relay functionality included - skip");
2084#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002085}
2086
2087
2088static void
2089hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
2090 const u8 *buf, size_t len, unsigned int freq)
2091{
2092 struct wpabuf *msg;
2093
2094 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2095 MAC2STR(src));
2096
2097 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2098 * values here */
2099
2100 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
2101 hapd->dpp_pkex->exchange_done) {
2102 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2103 return;
2104 }
2105
Hai Shaloma20dcd72022-02-04 13:43:00 -08002106 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
2107 hapd->dpp_pkex->exch_req_wait_time = 0;
2108
Roshan Pius3a1667e2018-07-03 15:17:14 -07002109 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002110 if (!msg) {
2111 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2112 return;
2113 }
2114
2115 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
2116 MAC2STR(src));
2117
Roshan Pius3a1667e2018-07-03 15:17:14 -07002118 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2119 " freq=%u type=%d", MAC2STR(src), freq,
2120 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002121 hostapd_drv_send_action(hapd, freq, 0, src,
2122 wpabuf_head(msg), wpabuf_len(msg));
2123 wpabuf_free(msg);
2124}
2125
2126
2127static void
2128hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
2129 const u8 *hdr, const u8 *buf, size_t len,
2130 unsigned int freq)
2131{
2132 struct wpabuf *msg;
2133 struct dpp_pkex *pkex = hapd->dpp_pkex;
2134 struct dpp_bootstrap_info *bi;
2135
2136 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
2137 MAC2STR(src));
2138
2139 if (!pkex || pkex->initiator || !pkex->exchange_done) {
2140 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2141 return;
2142 }
2143
2144 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
2145 if (!msg) {
2146 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002147 if (hapd->dpp_pkex->failed) {
2148 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
2149 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
2150 hapd->dpp_pkex->own_bi->pkex_t =
2151 hapd->dpp_pkex->t;
2152 dpp_pkex_free(hapd->dpp_pkex);
2153 hapd->dpp_pkex = NULL;
2154 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002155 return;
2156 }
2157
2158 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
2159 MACSTR, MAC2STR(src));
2160
Roshan Pius3a1667e2018-07-03 15:17:14 -07002161 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2162 " freq=%u type=%d", MAC2STR(src), freq,
2163 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002164 hostapd_drv_send_action(hapd, freq, 0, src,
2165 wpabuf_head(msg), wpabuf_len(msg));
2166 wpabuf_free(msg);
2167
Hai Shalom021b0b52019-04-10 11:17:58 -07002168 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002169 if (!bi)
2170 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002171 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002172}
2173
2174
2175static void
2176hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
2177 const u8 *hdr, const u8 *buf, size_t len,
2178 unsigned int freq)
2179{
2180 int res;
Hai Shalom021b0b52019-04-10 11:17:58 -07002181 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002182 struct dpp_pkex *pkex = hapd->dpp_pkex;
2183 char cmd[500];
2184
2185 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2186 MAC2STR(src));
2187
2188 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2189 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2190 return;
2191 }
2192
2193 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2194 if (res < 0) {
2195 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2196 return;
2197 }
2198
Hai Shalom021b0b52019-04-10 11:17:58 -07002199 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002200 if (!bi)
2201 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002202 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002203
2204 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2205 bi->id,
2206 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
2207 wpa_printf(MSG_DEBUG,
2208 "DPP: Start authentication after PKEX with parameters: %s",
2209 cmd);
2210 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
2211 wpa_printf(MSG_DEBUG,
2212 "DPP: Authentication initialization failed");
2213 return;
2214 }
2215}
2216
2217
2218void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
2219 const u8 *buf, size_t len, unsigned int freq)
2220{
2221 u8 crypto_suite;
2222 enum dpp_public_action_frame_type type;
2223 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002224 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002225
2226 if (len < DPP_HDR_LEN)
2227 return;
2228 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2229 return;
2230 hdr = buf;
2231 buf += 4;
2232 len -= 4;
2233 crypto_suite = *buf++;
2234 type = *buf++;
2235 len -= 2;
2236
2237 wpa_printf(MSG_DEBUG,
2238 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2239 MACSTR " freq=%u",
2240 crypto_suite, type, MAC2STR(src), freq);
2241 if (crypto_suite != 1) {
2242 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2243 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002244 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2245 " freq=%u type=%d ignore=unsupported-crypto-suite",
2246 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002247 return;
2248 }
2249 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002250 if (dpp_check_attrs(buf, len) < 0) {
2251 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2252 " freq=%u type=%d ignore=invalid-attributes",
2253 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002254 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002255 }
2256 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2257 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002258
Hai Shalom81f62d82019-07-22 12:10:00 -07002259#ifdef CONFIG_DPP2
2260 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002261 src, hdr, buf, len, freq, NULL, NULL,
2262 hapd) == 0)
Hai Shalom81f62d82019-07-22 12:10:00 -07002263 return;
2264#endif /* CONFIG_DPP2 */
2265
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002266 switch (type) {
2267 case DPP_PA_AUTHENTICATION_REQ:
2268 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
2269 break;
2270 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002271 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002272 break;
2273 case DPP_PA_AUTHENTICATION_CONF:
2274 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
2275 break;
2276 case DPP_PA_PEER_DISCOVERY_REQ:
2277 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
2278 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002279#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002280 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08002281 /* This is for PKEXv2, but for now, process only with
2282 * CONFIG_DPP3 to avoid issues with a capability that has not
2283 * been tested with other implementations. */
2284 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
2285 true);
2286 break;
2287#endif /* CONFIG_DPP3 */
2288 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
2289 hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq,
2290 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002291 break;
2292 case DPP_PA_PKEX_EXCHANGE_RESP:
2293 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
2294 break;
2295 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2296 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
2297 freq);
2298 break;
2299 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2300 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
2301 freq);
2302 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002303#ifdef CONFIG_DPP2
2304 case DPP_PA_CONFIGURATION_RESULT:
2305 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
2306 break;
Hai Shalomc3565922019-10-28 11:58:20 -07002307 case DPP_PA_CONNECTION_STATUS_RESULT:
2308 hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
2309 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07002310 case DPP_PA_PRESENCE_ANNOUNCEMENT:
2311 hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
2312 freq);
2313 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002314 case DPP_PA_RECONFIG_ANNOUNCEMENT:
2315 hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
2316 freq);
2317 break;
2318 case DPP_PA_RECONFIG_AUTH_RESP:
2319 hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
2320 freq);
2321 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002322#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002323 default:
2324 wpa_printf(MSG_DEBUG,
2325 "DPP: Ignored unsupported frame subtype %d", type);
2326 break;
2327 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002328
2329 if (hapd->dpp_pkex)
2330 pkex_t = hapd->dpp_pkex->t;
2331 else if (hapd->dpp_pkex_bi)
2332 pkex_t = hapd->dpp_pkex_bi->pkex_t;
2333 else
2334 pkex_t = 0;
2335 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2336 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2337 hostapd_dpp_pkex_remove(hapd, "*");
2338 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002339}
2340
2341
2342struct wpabuf *
2343hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
Hai Shalom81f62d82019-07-22 12:10:00 -07002344 const u8 *query, size_t query_len,
2345 const u8 *data, size_t data_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002346{
2347 struct dpp_authentication *auth = hapd->dpp_auth;
2348 struct wpabuf *resp;
2349
2350 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002351 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002352 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002353#ifdef CONFIG_DPP2
2354 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
2355 data_len) == 0) {
2356 /* Response will be forwarded once received over TCP */
2357 return NULL;
2358 }
2359#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002360 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2361 return NULL;
2362 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002363
2364 if (hapd->dpp_auth_ok_on_ack && auth->configurator) {
2365 wpa_printf(MSG_DEBUG,
2366 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
2367 /* hostapd_dpp_auth_success() would normally have been called
2368 * from TX status handler, but since there was no such handler
2369 * call yet, simply send out the event message and proceed with
2370 * exchange. */
2371 wpa_msg(hapd->msg_ctx, MSG_INFO,
2372 DPP_EVENT_AUTH_SUCCESS "init=1");
2373 hapd->dpp_auth_ok_on_ack = 0;
2374 }
2375
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002376 wpa_hexdump(MSG_DEBUG,
2377 "DPP: Received Configuration Request (GAS Query Request)",
2378 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002379 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2380 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002381 resp = dpp_conf_req_rx(auth, query, query_len);
2382 if (!resp)
2383 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
2384 return resp;
2385}
2386
2387
Roshan Pius3a1667e2018-07-03 15:17:14 -07002388void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
2389{
Hai Shalom021b0b52019-04-10 11:17:58 -07002390 struct dpp_authentication *auth = hapd->dpp_auth;
2391
2392 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07002393 return;
2394
Sunil Ravia04bd252022-05-02 22:54:18 -07002395#ifdef CONFIG_DPP3
2396 if (auth->waiting_new_key && ok) {
2397 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
2398 return;
2399 }
2400#endif /* CONFIG_DPP3 */
2401
Hai Shalom021b0b52019-04-10 11:17:58 -07002402 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2403 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002404 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08002405 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002406 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002407#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002408 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
2409 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002410 if (ok && auth->peer_version >= 2 &&
2411 auth->conf_resp_status == DPP_STATUS_OK) {
2412 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
2413 auth->waiting_conf_result = 1;
2414 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
2415 hapd, NULL);
2416 eloop_register_timeout(2, 0,
2417 hostapd_dpp_config_result_wait_timeout,
2418 hapd, NULL);
2419 return;
2420 }
2421#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002422 hostapd_drv_send_action_cancel_wait(hapd);
2423
2424 if (ok)
2425 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
2426 else
2427 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
2428 dpp_auth_deinit(hapd->dpp_auth);
2429 hapd->dpp_auth = NULL;
2430}
2431
2432
Roshan Pius3a1667e2018-07-03 15:17:14 -07002433int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
2434{
2435 struct dpp_authentication *auth;
2436 int ret = -1;
2437 char *curve = NULL;
2438
Hai Shalomfdcde762020-04-02 11:19:20 -07002439 auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002440 if (!auth)
2441 return -1;
2442
2443 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08002444 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07002445 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08002446 dpp_configurator_own_config(auth, curve, 1) == 0) {
Hai Shalomc3565922019-10-28 11:58:20 -07002447 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002448 ret = 0;
2449 }
2450
2451 dpp_auth_deinit(auth);
2452 os_free(curve);
2453
2454 return ret;
2455}
2456
2457
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002458int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
2459{
2460 struct dpp_bootstrap_info *own_bi;
2461 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07002462#ifdef CONFIG_DPP3
2463 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
2464#else /* CONFIG_DPP3 */
2465 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
2466#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002467 int tcp_port = DPP_TCP_PORT;
2468 struct hostapd_ip_addr *ipaddr = NULL;
2469#ifdef CONFIG_DPP2
2470 struct hostapd_ip_addr ipaddr_buf;
2471 char *addr;
2472
2473 pos = os_strstr(cmd, " tcp_port=");
2474 if (pos) {
2475 pos += 10;
2476 tcp_port = atoi(pos);
2477 }
2478
2479 addr = get_param(cmd, " tcp_addr=");
2480 if (addr) {
2481 int res;
2482
2483 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
2484 os_free(addr);
2485 if (res)
2486 return -1;
2487 ipaddr = &ipaddr_buf;
2488 }
2489#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002490
2491 pos = os_strstr(cmd, " own=");
2492 if (!pos)
2493 return -1;
2494 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07002495 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002496 if (!own_bi) {
2497 wpa_printf(MSG_DEBUG,
2498 "DPP: Identified bootstrap info not found");
2499 return -1;
2500 }
2501 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2502 wpa_printf(MSG_DEBUG,
2503 "DPP: Identified bootstrap info not for PKEX");
2504 return -1;
2505 }
2506 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002507 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002508
2509 os_free(hapd->dpp_pkex_identifier);
2510 hapd->dpp_pkex_identifier = NULL;
2511 pos = os_strstr(cmd, " identifier=");
2512 if (pos) {
2513 pos += 12;
2514 end = os_strchr(pos, ' ');
2515 if (!end)
2516 return -1;
2517 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
2518 if (!hapd->dpp_pkex_identifier)
2519 return -1;
2520 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
2521 hapd->dpp_pkex_identifier[end - pos] = '\0';
2522 }
2523
2524 pos = os_strstr(cmd, " code=");
2525 if (!pos)
2526 return -1;
2527 os_free(hapd->dpp_pkex_code);
2528 hapd->dpp_pkex_code = os_strdup(pos + 6);
2529 if (!hapd->dpp_pkex_code)
2530 return -1;
2531
Sunil Ravia04bd252022-05-02 22:54:18 -07002532 pos = os_strstr(cmd, " ver=");
2533 if (pos) {
2534 int v;
2535
2536 pos += 5;
2537 v = atoi(pos);
2538 if (v == 1)
2539 ver = PKEX_VER_ONLY_1;
2540 else if (v == 2)
2541 ver = PKEX_VER_ONLY_2;
2542 else
2543 return -1;
2544 }
2545 hapd->dpp_pkex_ver = ver;
2546
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002547 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002548 if (hostapd_dpp_pkex_init(hapd, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002549 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002550 } else {
2551#ifdef CONFIG_DPP2
2552 dpp_controller_pkex_add(hapd->iface->interfaces->dpp, own_bi,
2553 hapd->dpp_pkex_code,
2554 hapd->dpp_pkex_identifier);
2555#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002556 }
2557
2558 /* TODO: Support multiple PKEX info entries */
2559
2560 os_free(hapd->dpp_pkex_auth_cmd);
2561 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
2562
2563 return 1;
2564}
2565
2566
2567int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
2568{
2569 unsigned int id_val;
2570
2571 if (os_strcmp(id, "*") == 0) {
2572 id_val = 0;
2573 } else {
2574 id_val = atoi(id);
2575 if (id_val == 0)
2576 return -1;
2577 }
2578
2579 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
2580 return -1;
2581
2582 /* TODO: Support multiple PKEX entries */
2583 os_free(hapd->dpp_pkex_code);
2584 hapd->dpp_pkex_code = NULL;
2585 os_free(hapd->dpp_pkex_identifier);
2586 hapd->dpp_pkex_identifier = NULL;
2587 os_free(hapd->dpp_pkex_auth_cmd);
2588 hapd->dpp_pkex_auth_cmd = NULL;
2589 hapd->dpp_pkex_bi = NULL;
2590 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2591 dpp_pkex_free(hapd->dpp_pkex);
2592 hapd->dpp_pkex = NULL;
2593 return 0;
2594}
2595
2596
Roshan Pius3a1667e2018-07-03 15:17:14 -07002597void hostapd_dpp_stop(struct hostapd_data *hapd)
2598{
2599 dpp_auth_deinit(hapd->dpp_auth);
2600 hapd->dpp_auth = NULL;
2601 dpp_pkex_free(hapd->dpp_pkex);
2602 hapd->dpp_pkex = NULL;
2603}
2604
2605
Hai Shalom81f62d82019-07-22 12:10:00 -07002606#ifdef CONFIG_DPP2
2607
2608static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq,
2609 const u8 *msg, size_t len)
2610{
2611 struct hostapd_data *hapd = ctx;
2612 u8 *buf;
2613
2614 wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u",
2615 MAC2STR(addr), freq);
2616 buf = os_malloc(2 + len);
2617 if (!buf)
2618 return;
2619 buf[0] = WLAN_ACTION_PUBLIC;
2620 buf[1] = WLAN_PA_VENDOR_SPECIFIC;
2621 os_memcpy(buf + 2, msg, len);
2622 hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len);
2623 os_free(buf);
2624}
2625
2626
2627static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr,
2628 u8 dialog_token, int prot,
2629 struct wpabuf *buf)
2630{
2631 struct hostapd_data *hapd = ctx;
2632
2633 gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf);
2634}
2635
2636#endif /* CONFIG_DPP2 */
2637
2638
2639static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
2640{
2641#ifdef CONFIG_DPP2
2642 struct dpp_controller_conf *ctrl;
2643 struct dpp_relay_config config;
2644
2645 os_memset(&config, 0, sizeof(config));
2646 config.cb_ctx = hapd;
2647 config.tx = hostapd_dpp_relay_tx;
2648 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
2649 for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) {
2650 config.ipaddr = &ctrl->ipaddr;
2651 config.pkhash = ctrl->pkhash;
2652 if (dpp_relay_add_controller(hapd->iface->interfaces->dpp,
2653 &config) < 0)
2654 return -1;
2655 }
2656#endif /* CONFIG_DPP2 */
2657
2658 return 0;
2659}
2660
2661
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002662int hostapd_dpp_init(struct hostapd_data *hapd)
2663{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002664 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
2665 hapd->dpp_init_done = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002666 return hostapd_dpp_add_controllers(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002667}
2668
2669
2670void hostapd_dpp_deinit(struct hostapd_data *hapd)
2671{
2672#ifdef CONFIG_TESTING_OPTIONS
2673 os_free(hapd->dpp_config_obj_override);
2674 hapd->dpp_config_obj_override = NULL;
2675 os_free(hapd->dpp_discovery_override);
2676 hapd->dpp_discovery_override = NULL;
2677 os_free(hapd->dpp_groups_override);
2678 hapd->dpp_groups_override = NULL;
2679 hapd->dpp_ignore_netaccesskey_mismatch = 0;
2680#endif /* CONFIG_TESTING_OPTIONS */
2681 if (!hapd->dpp_init_done)
2682 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002683 eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002684 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08002685 eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002686 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
2687 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002688#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002689 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
2690 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002691 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
2692 NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07002693 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
2694 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002695 hostapd_dpp_chirp_stop(hapd);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002696 if (hapd->iface->interfaces)
2697 dpp_controller_stop_for_ctx(hapd->iface->interfaces->dpp, hapd);
Hai Shalom021b0b52019-04-10 11:17:58 -07002698#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07002699#ifdef CONFIG_DPP3
2700 eloop_cancel_timeout(hostapd_dpp_build_new_key, hapd, NULL);
2701#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002702 dpp_auth_deinit(hapd->dpp_auth);
2703 hapd->dpp_auth = NULL;
2704 hostapd_dpp_pkex_remove(hapd, "*");
2705 hapd->dpp_pkex = NULL;
2706 os_free(hapd->dpp_configurator_params);
2707 hapd->dpp_configurator_params = NULL;
2708}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002709
2710
2711#ifdef CONFIG_DPP2
2712
Hai Shalom899fcc72020-10-19 14:38:18 -07002713int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd)
2714{
2715 struct dpp_controller_config config;
2716 const char *pos;
2717
2718 os_memset(&config, 0, sizeof(config));
2719 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
2720 config.netrole = DPP_NETROLE_AP;
2721 config.msg_ctx = hapd->msg_ctx;
2722 config.cb_ctx = hapd;
2723 config.process_conf_obj = hostapd_dpp_process_conf_obj;
2724 if (cmd) {
2725 pos = os_strstr(cmd, " tcp_port=");
2726 if (pos) {
2727 pos += 10;
2728 config.tcp_port = atoi(pos);
2729 }
2730
2731 pos = os_strstr(cmd, " role=");
2732 if (pos) {
2733 pos += 6;
2734 if (os_strncmp(pos, "configurator", 12) == 0)
2735 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
2736 else if (os_strncmp(pos, "enrollee", 8) == 0)
2737 config.allowed_roles = DPP_CAPAB_ENROLLEE;
2738 else if (os_strncmp(pos, "either", 6) == 0)
2739 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
2740 DPP_CAPAB_ENROLLEE;
2741 else
2742 return -1;
2743 }
2744
2745 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
2746 }
2747 config.configurator_params = hapd->dpp_configurator_params;
2748 return dpp_controller_start(hapd->iface->interfaces->dpp, &config);
2749}
2750
2751
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002752static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
2753
2754static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
2755{
2756 struct hostapd_data *hapd = eloop_ctx;
2757
2758 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
2759 hostapd_drv_send_action_cancel_wait(hapd);
2760 hostapd_dpp_chirp_next(hapd, NULL);
2761}
2762
2763
2764static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
2765{
2766 struct wpabuf *msg;
2767 int type;
2768
2769 msg = hapd->dpp_presence_announcement;
2770 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
2771 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
2772 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2773 " freq=%u type=%d",
2774 MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
2775 if (hostapd_drv_send_action(
2776 hapd, hapd->dpp_chirp_freq, 2000, broadcast,
2777 wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
2778 eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
2779 hapd, NULL) < 0)
2780 hostapd_dpp_chirp_stop(hapd);
2781}
2782
2783
2784static struct hostapd_hw_modes *
2785dpp_get_mode(struct hostapd_data *hapd,
2786 enum hostapd_hw_mode mode)
2787{
2788 struct hostapd_hw_modes *modes = hapd->iface->hw_features;
2789 u16 num_modes = hapd->iface->num_hw_features;
2790 u16 i;
2791
2792 for (i = 0; i < num_modes; i++) {
2793 if (modes[i].mode != mode ||
2794 !modes[i].num_channels || !modes[i].channels)
2795 continue;
2796 return &modes[i];
2797 }
2798
2799 return NULL;
2800}
2801
2802
2803static void
2804hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
2805{
2806 struct hostapd_data *hapd = iface->bss[0];
2807 struct wpa_scan_results *scan_res;
2808 struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
2809 unsigned int i;
2810 struct hostapd_hw_modes *mode;
2811 int c;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002812 bool chan6 = hapd->iface->hw_features == NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002813
2814 if (!bi)
2815 return;
2816
2817 hapd->dpp_chirp_scan_done = 1;
2818
2819 scan_res = hostapd_driver_get_scan_results(hapd);
2820
2821 os_free(hapd->dpp_chirp_freqs);
2822 hapd->dpp_chirp_freqs = NULL;
2823
2824 /* Channels from own bootstrapping info */
2825 if (bi) {
2826 for (i = 0; i < bi->num_freq; i++)
2827 int_array_add_unique(&hapd->dpp_chirp_freqs,
2828 bi->freq[i]);
2829 }
2830
2831 /* Preferred chirping channels */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002832 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211G);
2833 if (mode) {
2834 for (c = 0; c < mode->num_channels; c++) {
2835 struct hostapd_channel_data *chan = &mode->channels[c];
2836
2837 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2838 HOSTAPD_CHAN_RADAR) ||
2839 chan->freq != 2437)
2840 continue;
2841 chan6 = true;
2842 break;
2843 }
2844 }
2845 if (chan6)
2846 int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002847
2848 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
2849 if (mode) {
2850 int chan44 = 0, chan149 = 0;
2851
2852 for (c = 0; c < mode->num_channels; c++) {
2853 struct hostapd_channel_data *chan = &mode->channels[c];
2854
2855 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2856 HOSTAPD_CHAN_RADAR))
2857 continue;
2858 if (chan->freq == 5220)
2859 chan44 = 1;
2860 if (chan->freq == 5745)
2861 chan149 = 1;
2862 }
2863 if (chan149)
2864 int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
2865 else if (chan44)
2866 int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
2867 }
2868
2869 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
2870 if (mode) {
2871 for (c = 0; c < mode->num_channels; c++) {
2872 struct hostapd_channel_data *chan = &mode->channels[c];
2873
2874 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
2875 HOSTAPD_CHAN_RADAR)) ||
2876 chan->freq != 60480)
2877 continue;
2878 int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
2879 break;
2880 }
2881 }
2882
2883 /* Add channels from scan results for APs that advertise Configurator
2884 * Connectivity element */
2885 for (i = 0; scan_res && i < scan_res->num; i++) {
2886 struct wpa_scan_res *bss = scan_res->res[i];
2887 size_t ie_len = bss->ie_len;
2888
2889 if (!ie_len)
2890 ie_len = bss->beacon_ie_len;
2891 if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
2892 DPP_CC_IE_VENDOR_TYPE))
2893 int_array_add_unique(&hapd->dpp_chirp_freqs,
2894 bss->freq);
2895 }
2896
2897 if (!hapd->dpp_chirp_freqs ||
2898 eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
2899 hapd, NULL) < 0)
2900 hostapd_dpp_chirp_stop(hapd);
2901
2902 wpa_scan_results_free(scan_res);
2903}
2904
2905
2906static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
2907{
2908 struct hostapd_data *hapd = eloop_ctx;
2909 int i;
2910
2911 if (hapd->dpp_chirp_listen)
2912 hostapd_dpp_listen_stop(hapd);
2913
2914 if (hapd->dpp_chirp_freq == 0) {
2915 if (hapd->dpp_chirp_round % 4 == 0 &&
2916 !hapd->dpp_chirp_scan_done) {
2917 struct wpa_driver_scan_params params;
2918 int ret;
2919
2920 wpa_printf(MSG_DEBUG,
2921 "DPP: Update channel list for chirping");
2922 os_memset(&params, 0, sizeof(params));
2923 ret = hostapd_driver_scan(hapd, &params);
2924 if (ret < 0) {
2925 wpa_printf(MSG_DEBUG,
2926 "DPP: Failed to request a scan ret=%d (%s)",
2927 ret, strerror(-ret));
2928 hostapd_dpp_chirp_scan_res_handler(hapd->iface);
2929 } else {
2930 hapd->iface->scan_cb =
2931 hostapd_dpp_chirp_scan_res_handler;
2932 }
2933 return;
2934 }
2935 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
2936 hapd->dpp_chirp_round++;
2937 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
2938 hapd->dpp_chirp_round);
2939 } else {
2940 for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
2941 if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
2942 break;
2943 if (!hapd->dpp_chirp_freqs[i]) {
2944 wpa_printf(MSG_DEBUG,
2945 "DPP: Previous chirp freq %d not found",
2946 hapd->dpp_chirp_freq);
2947 return;
2948 }
2949 i++;
2950 if (hapd->dpp_chirp_freqs[i]) {
2951 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
2952 } else {
2953 hapd->dpp_chirp_iter--;
2954 if (hapd->dpp_chirp_iter <= 0) {
2955 wpa_printf(MSG_DEBUG,
2956 "DPP: Chirping iterations completed");
2957 hostapd_dpp_chirp_stop(hapd);
2958 return;
2959 }
2960 hapd->dpp_chirp_freq = 0;
2961 hapd->dpp_chirp_scan_done = 0;
2962 if (eloop_register_timeout(30, 0,
2963 hostapd_dpp_chirp_next,
2964 hapd, NULL) < 0) {
2965 hostapd_dpp_chirp_stop(hapd);
2966 return;
2967 }
2968 if (hapd->dpp_chirp_listen) {
2969 wpa_printf(MSG_DEBUG,
2970 "DPP: Listen on %d MHz during chirp 30 second wait",
2971 hapd->dpp_chirp_listen);
2972 /* TODO: start listen on the channel */
2973 } else {
2974 wpa_printf(MSG_DEBUG,
2975 "DPP: Wait 30 seconds before starting the next chirping round");
2976 }
2977 return;
2978 }
2979 }
2980
2981 hostapd_dpp_chirp_start(hapd);
2982}
2983
2984
2985int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
2986{
2987 const char *pos;
2988 int iter = 1, listen_freq = 0;
2989 struct dpp_bootstrap_info *bi;
2990
2991 pos = os_strstr(cmd, " own=");
2992 if (!pos)
2993 return -1;
2994 pos += 5;
2995 bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
2996 if (!bi) {
2997 wpa_printf(MSG_DEBUG,
2998 "DPP: Identified bootstrap info not found");
2999 return -1;
3000 }
3001
3002 pos = os_strstr(cmd, " iter=");
3003 if (pos) {
3004 iter = atoi(pos + 6);
3005 if (iter <= 0)
3006 return -1;
3007 }
3008
3009 pos = os_strstr(cmd, " listen=");
3010 if (pos) {
3011 listen_freq = atoi(pos + 8);
3012 if (listen_freq <= 0)
3013 return -1;
3014 }
3015
3016 hostapd_dpp_chirp_stop(hapd);
3017 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
3018 hapd->dpp_qr_mutual = 0;
3019 hapd->dpp_chirp_bi = bi;
3020 hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
3021 if (!hapd->dpp_presence_announcement)
3022 return -1;
3023 hapd->dpp_chirp_iter = iter;
3024 hapd->dpp_chirp_round = 0;
3025 hapd->dpp_chirp_scan_done = 0;
3026 hapd->dpp_chirp_listen = listen_freq;
3027
3028 return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
3029}
3030
3031
3032void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
3033{
3034 if (hapd->dpp_presence_announcement) {
3035 hostapd_drv_send_action_cancel_wait(hapd);
3036 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
3037 }
3038 hapd->dpp_chirp_bi = NULL;
3039 wpabuf_free(hapd->dpp_presence_announcement);
3040 hapd->dpp_presence_announcement = NULL;
3041 if (hapd->dpp_chirp_listen)
3042 hostapd_dpp_listen_stop(hapd);
3043 hapd->dpp_chirp_listen = 0;
3044 hapd->dpp_chirp_freq = 0;
3045 os_free(hapd->dpp_chirp_freqs);
3046 hapd->dpp_chirp_freqs = NULL;
3047 eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
3048 eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
3049 if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
3050 /* TODO: abort ongoing scan */
3051 hapd->iface->scan_cb = NULL;
3052 }
3053}
3054
3055
3056static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
3057{
3058 struct dpp_bootstrap_info *bi = ctx;
3059 size_t i;
3060
3061 for (i = 0; i < iface->num_bss; i++) {
3062 struct hostapd_data *hapd = iface->bss[i];
3063
3064 if (bi == hapd->dpp_chirp_bi)
3065 hostapd_dpp_chirp_stop(hapd);
3066 }
3067
3068 return 0;
3069}
3070
3071
3072void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
3073{
3074 struct hapd_interfaces *interfaces = ctx;
3075
3076 hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
3077}
3078
3079#endif /* CONFIG_DPP2 */