blob: 6772a8748a6d96ebd9d2ece3a4336ffff4be0169 [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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10#include "utils/includes.h"
11
12#include "utils/common.h"
13#include "utils/eloop.h"
14#include "common/dpp.h"
15#include "common/gas.h"
16#include "common/wpa_ctrl.h"
17#include "hostapd.h"
18#include "ap_drv_ops.h"
19#include "gas_query_ap.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070020#include "gas_serv.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070021#include "wpa_auth.h"
22#include "dpp_hostapd.h"
23
24
Roshan Pius3a1667e2018-07-03 15:17:14 -070025static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070026static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -070027static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
28static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070029#ifdef CONFIG_DPP2
30static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
31 void *timeout_ctx);
Hai Shalom899fcc72020-10-19 14:38:18 -070032static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
33 struct dpp_authentication *auth,
34 struct dpp_config_obj *conf);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070035#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070036
37static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
38
39
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070040/**
41 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
42 * @hapd: Pointer to hostapd_data
43 * @cmd: DPP URI read from a QR Code
44 * Returns: Identifier of the stored info or -1 on failure
45 */
46int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
47{
48 struct dpp_bootstrap_info *bi;
49 struct dpp_authentication *auth = hapd->dpp_auth;
50
Hai Shalom021b0b52019-04-10 11:17:58 -070051 bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070052 if (!bi)
53 return -1;
54
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070055 if (auth && auth->response_pending &&
56 dpp_notify_new_qr_code(auth, bi) == 1) {
57 wpa_printf(MSG_DEBUG,
58 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070059 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
60 " freq=%u type=%d",
61 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
62 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070063 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
64 auth->peer_mac_addr,
65 wpabuf_head(hapd->dpp_auth->resp_msg),
66 wpabuf_len(hapd->dpp_auth->resp_msg));
67 }
68
Hai Shalom899fcc72020-10-19 14:38:18 -070069#ifdef CONFIG_DPP2
70 dpp_controller_new_qr_code(hapd->iface->interfaces->dpp, bi);
71#endif /* CONFIG_DPP2 */
72
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070073 return bi->id;
74}
75
76
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080077/**
78 * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
79 * @hapd: Pointer to hostapd_data
80 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
81 * Returns: Identifier of the stored info or -1 on failure
82 */
83int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
84{
85 struct dpp_bootstrap_info *bi;
86
87 bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
88 if (!bi)
89 return -1;
90
91 return bi->id;
92}
93
94
Hai Shalomfdcde762020-04-02 11:19:20 -070095int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd)
96{
97 const char *pos;
98 struct dpp_bootstrap_info *peer_bi, *own_bi;
99
100 pos = os_strstr(cmd, " own=");
101 if (!pos)
102 return -1;
103 pos += 5;
104 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
105 if (!own_bi)
106 return -1;
107
108 pos = os_strstr(cmd, " uri=");
109 if (!pos)
110 return -1;
111 pos += 5;
112 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
113 if (!peer_bi) {
114 wpa_printf(MSG_INFO,
115 "DPP: Failed to parse URI from NFC Handover Request");
116 return -1;
117 }
118
119 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
120 return -1;
121
122 return peer_bi->id;
123}
124
125
126int hostapd_dpp_nfc_handover_sel(struct hostapd_data *hapd, const char *cmd)
127{
128 const char *pos;
129 struct dpp_bootstrap_info *peer_bi, *own_bi;
130
131 pos = os_strstr(cmd, " own=");
132 if (!pos)
133 return -1;
134 pos += 5;
135 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
136 if (!own_bi)
137 return -1;
138
139 pos = os_strstr(cmd, " uri=");
140 if (!pos)
141 return -1;
142 pos += 5;
143 peer_bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, pos);
144 if (!peer_bi) {
145 wpa_printf(MSG_INFO,
146 "DPP: Failed to parse URI from NFC Handover Select");
147 return -1;
148 }
149
150 if (peer_bi->curve != own_bi->curve) {
151 wpa_printf(MSG_INFO,
152 "DPP: Peer (NFC Handover Selector) used different curve");
153 return -1;
154 }
155
156 return peer_bi->id;
157}
158
159
Roshan Pius3a1667e2018-07-03 15:17:14 -0700160static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
161 void *timeout_ctx)
162{
163 struct hostapd_data *hapd = eloop_ctx;
164 struct dpp_authentication *auth = hapd->dpp_auth;
165
166 if (!auth || !auth->resp_msg)
167 return;
168
169 wpa_printf(MSG_DEBUG,
170 "DPP: Retry Authentication Response after timeout");
171 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
172 " freq=%u type=%d",
173 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
174 DPP_PA_AUTHENTICATION_RESP);
175 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
176 wpabuf_head(auth->resp_msg),
177 wpabuf_len(auth->resp_msg));
178}
179
180
181static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
182{
183 struct dpp_authentication *auth = hapd->dpp_auth;
184 unsigned int wait_time, max_tries;
185
186 if (!auth || !auth->resp_msg)
187 return;
188
189 if (hapd->dpp_resp_max_tries)
190 max_tries = hapd->dpp_resp_max_tries;
191 else
192 max_tries = 5;
193 auth->auth_resp_tries++;
194 if (auth->auth_resp_tries >= max_tries) {
195 wpa_printf(MSG_INFO,
196 "DPP: No confirm received from initiator - stopping exchange");
197 hostapd_drv_send_action_cancel_wait(hapd);
198 dpp_auth_deinit(hapd->dpp_auth);
199 hapd->dpp_auth = NULL;
200 return;
201 }
202
203 if (hapd->dpp_resp_retry_time)
204 wait_time = hapd->dpp_resp_retry_time;
205 else
206 wait_time = 1000;
207 wpa_printf(MSG_DEBUG,
208 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
209 wait_time);
210 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
211 eloop_register_timeout(wait_time / 1000,
212 (wait_time % 1000) * 1000,
213 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
214}
215
216
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700217void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
218 const u8 *data, size_t data_len, int ok)
219{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700220 struct dpp_authentication *auth = hapd->dpp_auth;
221
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700222 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
223 MAC2STR(dst), ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700224 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
225 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700226
227 if (!hapd->dpp_auth) {
228 wpa_printf(MSG_DEBUG,
229 "DPP: Ignore TX status since there is no ongoing authentication exchange");
230 return;
231 }
232
Hai Shalom021b0b52019-04-10 11:17:58 -0700233#ifdef CONFIG_DPP2
234 if (auth->connect_on_tx_status) {
235 wpa_printf(MSG_DEBUG,
236 "DPP: Complete exchange on configuration result");
237 dpp_auth_deinit(hapd->dpp_auth);
238 hapd->dpp_auth = NULL;
239 return;
240 }
241#endif /* CONFIG_DPP2 */
242
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700243 if (hapd->dpp_auth->remove_on_tx_status) {
244 wpa_printf(MSG_DEBUG,
245 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700246 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
247 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
248 hapd, NULL);
249 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
250 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700251#ifdef CONFIG_DPP2
252 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
253 hapd, NULL);
254#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700255 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700256 dpp_auth_deinit(hapd->dpp_auth);
257 hapd->dpp_auth = NULL;
258 return;
259 }
260
261 if (hapd->dpp_auth_ok_on_ack)
262 hostapd_dpp_auth_success(hapd, 1);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700263
264 if (!is_broadcast_ether_addr(dst) && !ok) {
265 wpa_printf(MSG_DEBUG,
266 "DPP: Unicast DPP Action frame was not ACKed");
267 if (auth->waiting_auth_resp) {
268 /* In case of DPP Authentication Request frame, move to
269 * the next channel immediately. */
270 hostapd_drv_send_action_cancel_wait(hapd);
271 hostapd_dpp_auth_init_next(hapd);
272 return;
273 }
274 if (auth->waiting_auth_conf) {
275 hostapd_dpp_auth_resp_retry(hapd);
276 return;
277 }
278 }
279
280 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
281 /* Allow timeout handling to stop iteration if no response is
282 * received from a peer that has ACKed a request. */
283 auth->auth_req_ack = 1;
284 }
285
286 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
287 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
288 wpa_printf(MSG_DEBUG,
289 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
290 hapd->dpp_auth->curr_freq,
291 hapd->dpp_auth->neg_freq);
292 hostapd_drv_send_action_cancel_wait(hapd);
293
294 if (hapd->dpp_auth->neg_freq !=
295 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
296 /* TODO: Listen operation on non-operating channel */
297 wpa_printf(MSG_INFO,
298 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
299 hapd->dpp_auth->neg_freq, hapd->iface->freq);
300 }
301 }
302
303 if (hapd->dpp_auth_ok_on_ack)
304 hapd->dpp_auth_ok_on_ack = 0;
305}
306
307
308static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
309{
310 struct hostapd_data *hapd = eloop_ctx;
311 struct dpp_authentication *auth = hapd->dpp_auth;
312 unsigned int freq;
313 struct os_reltime now, diff;
314 unsigned int wait_time, diff_ms;
315
316 if (!auth || !auth->waiting_auth_resp)
317 return;
318
319 wait_time = hapd->dpp_resp_wait_time ?
320 hapd->dpp_resp_wait_time : 2000;
321 os_get_reltime(&now);
322 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
323 diff_ms = diff.sec * 1000 + diff.usec / 1000;
324 wpa_printf(MSG_DEBUG,
325 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
326 wait_time, diff_ms);
327
328 if (auth->auth_req_ack && diff_ms >= wait_time) {
329 /* Peer ACK'ed Authentication Request frame, but did not reply
330 * with Authentication Response frame within two seconds. */
331 wpa_printf(MSG_INFO,
332 "DPP: No response received from responder - stopping initiation attempt");
333 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
334 hostapd_drv_send_action_cancel_wait(hapd);
335 hostapd_dpp_listen_stop(hapd);
336 dpp_auth_deinit(auth);
337 hapd->dpp_auth = NULL;
338 return;
339 }
340
341 if (diff_ms >= wait_time) {
342 /* Authentication Request frame was not ACK'ed and no reply
343 * was receiving within two seconds. */
344 wpa_printf(MSG_DEBUG,
345 "DPP: Continue Initiator channel iteration");
346 hostapd_drv_send_action_cancel_wait(hapd);
347 hostapd_dpp_listen_stop(hapd);
348 hostapd_dpp_auth_init_next(hapd);
349 return;
350 }
351
352 /* Driver did not support 2000 ms long wait_time with TX command, so
353 * schedule listen operation to continue waiting for the response.
354 *
355 * DPP listen operations continue until stopped, so simply schedule a
356 * new call to this function at the point when the two second reply
357 * wait has expired. */
358 wait_time -= diff_ms;
359
360 freq = auth->curr_freq;
361 if (auth->neg_freq > 0)
362 freq = auth->neg_freq;
363 wpa_printf(MSG_DEBUG,
364 "DPP: Continue reply wait on channel %u MHz for %u ms",
365 freq, wait_time);
366 hapd->dpp_in_response_listen = 1;
367
368 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
369 /* TODO: Listen operation on non-operating channel */
370 wpa_printf(MSG_INFO,
371 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
372 freq, hapd->iface->freq);
373 }
374
375 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
376 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700377}
378
379
380static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
381 struct dpp_authentication *auth)
382{
383#ifdef CONFIG_TESTING_OPTIONS
384 if (hapd->dpp_config_obj_override)
385 auth->config_obj_override =
386 os_strdup(hapd->dpp_config_obj_override);
387 if (hapd->dpp_discovery_override)
388 auth->discovery_override =
389 os_strdup(hapd->dpp_discovery_override);
390 if (hapd->dpp_groups_override)
391 auth->groups_override = os_strdup(hapd->dpp_groups_override);
392 auth->ignore_netaccesskey_mismatch =
393 hapd->dpp_ignore_netaccesskey_mismatch;
394#endif /* CONFIG_TESTING_OPTIONS */
395}
396
397
Roshan Pius3a1667e2018-07-03 15:17:14 -0700398static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
399{
400 struct hostapd_data *hapd = eloop_ctx;
401
402 if (!hapd->dpp_auth)
403 return;
404 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
405 hostapd_dpp_auth_init_next(hapd);
406}
407
408
409static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
410{
411 struct dpp_authentication *auth = hapd->dpp_auth;
412 const u8 *dst;
413 unsigned int wait_time, max_wait_time, freq, max_tries, used;
414 struct os_reltime now, diff;
415
416 if (!auth)
417 return -1;
418
419 if (auth->freq_idx == 0)
420 os_get_reltime(&hapd->dpp_init_iter_start);
421
422 if (auth->freq_idx >= auth->num_freq) {
423 auth->num_freq_iters++;
424 if (hapd->dpp_init_max_tries)
425 max_tries = hapd->dpp_init_max_tries;
426 else
427 max_tries = 5;
428 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
429 wpa_printf(MSG_INFO,
430 "DPP: No response received from responder - stopping initiation attempt");
431 wpa_msg(hapd->msg_ctx, MSG_INFO,
432 DPP_EVENT_AUTH_INIT_FAILED);
433 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
434 hapd, NULL);
435 hostapd_drv_send_action_cancel_wait(hapd);
436 dpp_auth_deinit(hapd->dpp_auth);
437 hapd->dpp_auth = NULL;
438 return -1;
439 }
440 auth->freq_idx = 0;
441 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
442 if (hapd->dpp_init_retry_time)
443 wait_time = hapd->dpp_init_retry_time;
444 else
445 wait_time = 10000;
446 os_get_reltime(&now);
447 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
448 used = diff.sec * 1000 + diff.usec / 1000;
449 if (used > wait_time)
450 wait_time = 0;
451 else
452 wait_time -= used;
453 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
454 wait_time);
455 eloop_register_timeout(wait_time / 1000,
456 (wait_time % 1000) * 1000,
457 hostapd_dpp_init_timeout, hapd,
458 NULL);
459 return 0;
460 }
461 freq = auth->freq[auth->freq_idx++];
462 auth->curr_freq = freq;
463
464 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
465 dst = broadcast;
466 else
467 dst = auth->peer_bi->mac_addr;
468 hapd->dpp_auth_ok_on_ack = 0;
469 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
470 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
471 max_wait_time = hapd->dpp_resp_wait_time ?
472 hapd->dpp_resp_wait_time : 2000;
473 if (wait_time > max_wait_time)
474 wait_time = max_wait_time;
475 wait_time += 10; /* give the driver some extra time to complete */
476 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
477 hostapd_dpp_reply_wait_timeout, hapd, NULL);
478 wait_time -= 10;
479 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
480 wpa_printf(MSG_DEBUG,
481 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
482 freq, auth->neg_freq);
483 }
484 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
485 " freq=%u type=%d",
486 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
487 auth->auth_req_ack = 0;
488 os_get_reltime(&hapd->dpp_last_init);
489 return hostapd_drv_send_action(hapd, freq, wait_time,
490 dst,
491 wpabuf_head(hapd->dpp_auth->req_msg),
492 wpabuf_len(hapd->dpp_auth->req_msg));
493}
494
495
Hai Shalom899fcc72020-10-19 14:38:18 -0700496#ifdef CONFIG_DPP2
497static int hostapd_dpp_process_conf_obj(void *ctx,
498 struct dpp_authentication *auth)
499{
500 struct hostapd_data *hapd = ctx;
501 unsigned int i;
502
503 for (i = 0; i < auth->num_conf_obj; i++)
504 hostapd_dpp_handle_config_obj(hapd, auth,
505 &auth->conf_obj[i]);
506
507 return 0;
508}
509#endif /* CONFIG_DPP2 */
510
511
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700512int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
513{
514 const char *pos;
515 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -0700516 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700517 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
518 unsigned int neg_freq = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700519 int tcp = 0;
520#ifdef CONFIG_DPP2
521 int tcp_port = DPP_TCP_PORT;
522 struct hostapd_ip_addr ipaddr;
523 char *addr;
524#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700525
526 pos = os_strstr(cmd, " peer=");
527 if (!pos)
528 return -1;
529 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700530 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700531 if (!peer_bi) {
532 wpa_printf(MSG_INFO,
533 "DPP: Could not find bootstrapping info for the identified peer");
534 return -1;
535 }
536
Hai Shalom899fcc72020-10-19 14:38:18 -0700537#ifdef CONFIG_DPP2
538 pos = os_strstr(cmd, " tcp_port=");
539 if (pos) {
540 pos += 10;
541 tcp_port = atoi(pos);
542 }
543
544 addr = get_param(cmd, " tcp_addr=");
545 if (addr) {
546 int res;
547
548 res = hostapd_parse_ip_addr(addr, &ipaddr);
549 os_free(addr);
550 if (res)
551 return -1;
552 tcp = 1;
553 }
554#endif /* CONFIG_DPP2 */
555
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700556 pos = os_strstr(cmd, " own=");
557 if (pos) {
558 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700559 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
560 atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700561 if (!own_bi) {
562 wpa_printf(MSG_INFO,
563 "DPP: Could not find bootstrapping info for the identified local entry");
564 return -1;
565 }
566
567 if (peer_bi->curve != own_bi->curve) {
568 wpa_printf(MSG_INFO,
569 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
570 peer_bi->curve->name, own_bi->curve->name);
571 return -1;
572 }
573 }
574
575 pos = os_strstr(cmd, " role=");
576 if (pos) {
577 pos += 6;
578 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700579 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700580 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700581 allowed_roles = DPP_CAPAB_ENROLLEE;
582 else if (os_strncmp(pos, "either", 6) == 0)
583 allowed_roles = DPP_CAPAB_CONFIGURATOR |
584 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700585 else
586 goto fail;
587 }
588
Roshan Pius3a1667e2018-07-03 15:17:14 -0700589 pos = os_strstr(cmd, " neg_freq=");
590 if (pos)
591 neg_freq = atoi(pos + 10);
592
Hai Shalom899fcc72020-10-19 14:38:18 -0700593 if (!tcp && hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700594 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
595 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
596 hapd, NULL);
597 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
598 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700599#ifdef CONFIG_DPP2
600 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
601 hapd, NULL);
602#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700603 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700604 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700605 }
606
Hai Shalom899fcc72020-10-19 14:38:18 -0700607 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
608 peer_bi, own_bi, allowed_roles, neg_freq,
609 hapd->iface->hw_features,
610 hapd->iface->num_hw_features);
611 if (!auth)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700612 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -0700613 hostapd_dpp_set_testing_options(hapd, auth);
614 if (dpp_set_configurator(auth, cmd) < 0) {
615 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800616 goto fail;
617 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700618
Hai Shalom899fcc72020-10-19 14:38:18 -0700619 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700620
Roshan Pius3a1667e2018-07-03 15:17:14 -0700621 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom899fcc72020-10-19 14:38:18 -0700622 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700623
Hai Shalom899fcc72020-10-19 14:38:18 -0700624#ifdef CONFIG_DPP2
625 if (tcp)
626 return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
627 &ipaddr, tcp_port, hapd->conf->dpp_name,
628 DPP_NETROLE_AP, hapd->msg_ctx, hapd,
629 hostapd_dpp_process_conf_obj);
630#endif /* CONFIG_DPP2 */
631
632 hapd->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700633 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700634fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700635 return -1;
636}
637
638
Roshan Pius3a1667e2018-07-03 15:17:14 -0700639int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
640{
641 int freq;
642
643 freq = atoi(cmd);
644 if (freq <= 0)
645 return -1;
646
647 if (os_strstr(cmd, " role=configurator"))
648 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
649 else if (os_strstr(cmd, " role=enrollee"))
650 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
651 else
652 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
653 DPP_CAPAB_ENROLLEE;
654 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
655
656 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
657 /* TODO: Listen operation on non-operating channel */
658 wpa_printf(MSG_INFO,
659 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
660 freq, hapd->iface->freq);
661 return -1;
662 }
663
664 return 0;
665}
666
667
668void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
669{
670 /* TODO: Stop listen operation on non-operating channel */
671}
672
673
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700674static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
675 const u8 *hdr, const u8 *buf, size_t len,
676 unsigned int freq)
677{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700678 const u8 *r_bootstrap, *i_bootstrap;
679 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700680 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
681
682 if (!hapd->iface->interfaces->dpp)
683 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700684
685 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
686 MAC2STR(src));
687
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700688#ifdef CONFIG_DPP2
689 hostapd_dpp_chirp_stop(hapd);
690#endif /* CONFIG_DPP2 */
691
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700692 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
693 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700694 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
695 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
696 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700697 return;
698 }
699 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
700 r_bootstrap, r_bootstrap_len);
701
702 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
703 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700704 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
705 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
706 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700707 return;
708 }
709 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
710 i_bootstrap, i_bootstrap_len);
711
712 /* Try to find own and peer bootstrapping key matches based on the
713 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -0700714 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
715 r_bootstrap, &own_bi, &peer_bi);
Hai Shalom81f62d82019-07-22 12:10:00 -0700716#ifdef CONFIG_DPP2
717 if (!own_bi) {
718 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
719 src, hdr, buf, len, freq, i_bootstrap,
720 r_bootstrap) == 0)
721 return;
722 }
723#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700724 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700725 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
726 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700727 return;
728 }
729
730 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700731 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
732 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700733 return;
734 }
735
736 hapd->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -0700737 hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp,
738 hapd->msg_ctx, hapd->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700739 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700740 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700741 if (!hapd->dpp_auth) {
742 wpa_printf(MSG_DEBUG, "DPP: No response generated");
743 return;
744 }
745 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700746 if (dpp_set_configurator(hapd->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -0700747 hapd->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800748 dpp_auth_deinit(hapd->dpp_auth);
749 hapd->dpp_auth = NULL;
750 return;
751 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700752 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
753
Roshan Pius3a1667e2018-07-03 15:17:14 -0700754 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
755 " freq=%u type=%d",
756 MAC2STR(src), hapd->dpp_auth->curr_freq,
757 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700758 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
759 src, wpabuf_head(hapd->dpp_auth->resp_msg),
760 wpabuf_len(hapd->dpp_auth->resp_msg));
761}
762
763
Roshan Pius3a1667e2018-07-03 15:17:14 -0700764static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
Hai Shalomc3565922019-10-28 11:58:20 -0700765 struct dpp_authentication *auth,
766 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700767{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700768 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700769 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700770 dpp_akm_str(conf->akm));
771 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700772 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700773 wpa_ssid_txt(conf->ssid, conf->ssid_len));
774 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700775 /* TODO: Save the Connector and consider using a command
776 * to fetch the value instead of sending an event with
777 * it. The Connector could end up being larger than what
778 * most clients are ready to receive as an event
779 * message. */
780 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -0700781 conf->connector);
Hai Shalomfdcde762020-04-02 11:19:20 -0700782 }
783 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700784 char hex[64 * 2 + 1];
785
786 wpa_snprintf_hex(hex, sizeof(hex),
Hai Shalomc3565922019-10-28 11:58:20 -0700787 (const u8 *) conf->passphrase,
788 os_strlen(conf->passphrase));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700789 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
790 hex);
Hai Shalomc3565922019-10-28 11:58:20 -0700791 } else if (conf->psk_set) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700792 char hex[PMK_LEN * 2 + 1];
793
Hai Shalomc3565922019-10-28 11:58:20 -0700794 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700795 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
796 hex);
797 }
Hai Shalomc3565922019-10-28 11:58:20 -0700798 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700799 char *hex;
800 size_t hexlen;
801
Hai Shalomc3565922019-10-28 11:58:20 -0700802 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700803 hex = os_malloc(hexlen);
804 if (hex) {
805 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -0700806 wpabuf_head(conf->c_sign_key),
807 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700808 wpa_msg(hapd->msg_ctx, MSG_INFO,
809 DPP_EVENT_C_SIGN_KEY "%s", hex);
810 os_free(hex);
811 }
812 }
813 if (auth->net_access_key) {
814 char *hex;
815 size_t hexlen;
816
817 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
818 hex = os_malloc(hexlen);
819 if (hex) {
820 wpa_snprintf_hex(hex, hexlen,
821 wpabuf_head(auth->net_access_key),
822 wpabuf_len(auth->net_access_key));
823 if (auth->net_access_key_expiry)
824 wpa_msg(hapd->msg_ctx, MSG_INFO,
825 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
826 (unsigned long)
827 auth->net_access_key_expiry);
828 else
829 wpa_msg(hapd->msg_ctx, MSG_INFO,
830 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
831 os_free(hex);
832 }
833 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700834}
835
836
Hai Shalomfdcde762020-04-02 11:19:20 -0700837static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
838 struct dpp_asymmetric_key *key)
839{
840#ifdef CONFIG_DPP2
841 int res;
842
843 if (!key)
844 return 0;
845
846 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
847 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
848
849 while (key) {
850 res = dpp_configurator_from_backup(
851 hapd->iface->interfaces->dpp, key);
852 if (res < 0)
853 return -1;
854 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
855 res);
856 key = key->next;
857 }
858#endif /* CONFIG_DPP2 */
859
860 return 0;
861}
862
863
Roshan Pius3a1667e2018-07-03 15:17:14 -0700864static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
865 enum gas_query_ap_result result,
866 const struct wpabuf *adv_proto,
867 const struct wpabuf *resp, u16 status_code)
868{
869 struct hostapd_data *hapd = ctx;
870 const u8 *pos;
871 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -0700872 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700873
874 if (!auth || !auth->auth_success) {
875 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
876 return;
877 }
878 if (!resp || status_code != WLAN_STATUS_SUCCESS) {
879 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
880 goto fail;
881 }
882
883 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
884 adv_proto);
885 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
886 resp);
887
888 if (wpabuf_len(adv_proto) != 10 ||
889 !(pos = wpabuf_head(adv_proto)) ||
890 pos[0] != WLAN_EID_ADV_PROTO ||
891 pos[1] != 8 ||
892 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
893 pos[4] != 5 ||
894 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
895 pos[8] != 0x1a ||
896 pos[9] != 1) {
897 wpa_printf(MSG_DEBUG,
898 "DPP: Not a DPP Advertisement Protocol ID");
899 goto fail;
900 }
901
902 if (dpp_conf_resp_rx(auth, resp) < 0) {
903 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
904 goto fail;
905 }
906
Hai Shalomc3565922019-10-28 11:58:20 -0700907 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Hai Shalomfdcde762020-04-02 11:19:20 -0700908 if (hostapd_dpp_handle_key_pkg(hapd, auth->conf_key_pkg) < 0)
909 goto fail;
910
Hai Shalom021b0b52019-04-10 11:17:58 -0700911 status = DPP_STATUS_OK;
912#ifdef CONFIG_TESTING_OPTIONS
913 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
914 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
915 status = DPP_STATUS_CONFIG_REJECTED;
916 }
917#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700918fail:
Hai Shalom021b0b52019-04-10 11:17:58 -0700919 if (status != DPP_STATUS_OK)
920 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
921#ifdef CONFIG_DPP2
922 if (auth->peer_version >= 2 &&
923 auth->conf_resp_status == DPP_STATUS_OK) {
924 struct wpabuf *msg;
925
926 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
927 msg = dpp_build_conf_result(auth, status);
928 if (!msg)
929 goto fail2;
930
931 wpa_msg(hapd->msg_ctx, MSG_INFO,
932 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
933 MAC2STR(addr), auth->curr_freq,
934 DPP_PA_CONFIGURATION_RESULT);
935 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
936 addr, wpabuf_head(msg),
937 wpabuf_len(msg));
938 wpabuf_free(msg);
939
940 /* This exchange will be terminated in the TX status handler */
941 auth->connect_on_tx_status = 1;
942 return;
943 }
944fail2:
945#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700946 dpp_auth_deinit(hapd->dpp_auth);
947 hapd->dpp_auth = NULL;
948}
949
950
951static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
952{
953 struct dpp_authentication *auth = hapd->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -0700954 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700955 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700956
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800957 buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
958 DPP_NETROLE_AP,
Hai Shalomc3565922019-10-28 11:58:20 -0700959 hapd->conf->dpp_mud_url, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -0700960 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700961 wpa_printf(MSG_DEBUG,
962 "DPP: No configuration request data available");
963 return;
964 }
965
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700966 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
967 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
968
969 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
970 buf, hostapd_dpp_gas_resp_cb, hapd);
971 if (res < 0) {
972 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
973 "GAS: Failed to send Query Request");
974 wpabuf_free(buf);
975 } else {
976 wpa_printf(MSG_DEBUG,
977 "DPP: GAS query started with dialog token %u", res);
978 }
979}
980
981
982static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
983{
984 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
985 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
986 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700987#ifdef CONFIG_TESTING_OPTIONS
988 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
989 wpa_printf(MSG_INFO,
990 "DPP: TESTING - stop at Authentication Confirm");
991 if (hapd->dpp_auth->configurator) {
992 /* Prevent GAS response */
993 hapd->dpp_auth->auth_success = 0;
994 }
995 return;
996 }
997#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700998
999 if (!hapd->dpp_auth->configurator)
1000 hostapd_dpp_start_gas_client(hapd);
1001}
1002
1003
1004static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001005 const u8 *hdr, const u8 *buf, size_t len,
1006 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001007{
1008 struct dpp_authentication *auth = hapd->dpp_auth;
1009 struct wpabuf *msg;
1010
1011 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
1012 MAC2STR(src));
1013
1014 if (!auth) {
1015 wpa_printf(MSG_DEBUG,
1016 "DPP: No DPP Authentication in progress - drop");
1017 return;
1018 }
1019
1020 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1021 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1022 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1023 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1024 return;
1025 }
1026
Roshan Pius3a1667e2018-07-03 15:17:14 -07001027 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1028
1029 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1030 wpa_printf(MSG_DEBUG,
1031 "DPP: Responder accepted request for different negotiation channel");
1032 auth->curr_freq = freq;
1033 }
1034
1035 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001036 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1037 if (!msg) {
1038 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1039 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
1040 return;
1041 }
1042 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1043 return;
1044 }
1045 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1046
Roshan Pius3a1667e2018-07-03 15:17:14 -07001047 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1048 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
1049 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001050 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
1051 wpabuf_head(msg), wpabuf_len(msg));
1052 wpabuf_free(msg);
1053 hapd->dpp_auth_ok_on_ack = 1;
1054}
1055
1056
1057static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1058 const u8 *hdr, const u8 *buf, size_t len)
1059{
1060 struct dpp_authentication *auth = hapd->dpp_auth;
1061
1062 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1063 MAC2STR(src));
1064
1065 if (!auth) {
1066 wpa_printf(MSG_DEBUG,
1067 "DPP: No DPP Authentication in progress - drop");
1068 return;
1069 }
1070
1071 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1072 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1073 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1074 return;
1075 }
1076
1077 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1078 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1079 return;
1080 }
1081
1082 hostapd_dpp_auth_success(hapd, 0);
1083}
1084
1085
Hai Shalom021b0b52019-04-10 11:17:58 -07001086#ifdef CONFIG_DPP2
1087
1088static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
1089 void *timeout_ctx)
1090{
1091 struct hostapd_data *hapd = eloop_ctx;
1092 struct dpp_authentication *auth = hapd->dpp_auth;
1093
1094 if (!auth || !auth->waiting_conf_result)
1095 return;
1096
1097 wpa_printf(MSG_DEBUG,
1098 "DPP: Timeout while waiting for Configuration Result");
1099 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1100 dpp_auth_deinit(auth);
1101 hapd->dpp_auth = NULL;
1102}
1103
1104
Hai Shalomc3565922019-10-28 11:58:20 -07001105static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1106 void *timeout_ctx)
1107{
1108 struct hostapd_data *hapd = eloop_ctx;
1109 struct dpp_authentication *auth = hapd->dpp_auth;
1110
1111 if (!auth || !auth->waiting_conf_result)
1112 return;
1113
1114 wpa_printf(MSG_DEBUG,
1115 "DPP: Timeout while waiting for Connection Status Result");
1116 wpa_msg(hapd->msg_ctx, MSG_INFO,
1117 DPP_EVENT_CONN_STATUS_RESULT "timeout");
1118 dpp_auth_deinit(auth);
1119 hapd->dpp_auth = NULL;
1120}
1121
1122
Hai Shalom021b0b52019-04-10 11:17:58 -07001123static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
1124 const u8 *hdr, const u8 *buf, size_t len)
1125{
1126 struct dpp_authentication *auth = hapd->dpp_auth;
1127 enum dpp_status_error status;
1128
1129 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1130 MAC2STR(src));
1131
1132 if (!auth || !auth->waiting_conf_result) {
1133 wpa_printf(MSG_DEBUG,
1134 "DPP: No DPP Configuration waiting for result - drop");
1135 return;
1136 }
1137
1138 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1139 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1140 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1141 return;
1142 }
1143
1144 status = dpp_conf_result_rx(auth, hdr, buf, len);
1145
Hai Shalomc3565922019-10-28 11:58:20 -07001146 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1147 wpa_msg(hapd->msg_ctx, MSG_INFO,
1148 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1149 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1150 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1151 hapd, NULL);
1152 eloop_cancel_timeout(
1153 hostapd_dpp_conn_status_result_wait_timeout,
1154 hapd, NULL);
1155 eloop_register_timeout(
1156 16, 0, hostapd_dpp_conn_status_result_wait_timeout,
1157 hapd, NULL);
1158 return;
1159 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001160 hostapd_drv_send_action_cancel_wait(hapd);
1161 hostapd_dpp_listen_stop(hapd);
1162 if (status == DPP_STATUS_OK)
1163 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1164 else
1165 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1166 dpp_auth_deinit(auth);
1167 hapd->dpp_auth = NULL;
1168 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1169 NULL);
1170}
1171
Hai Shalomc3565922019-10-28 11:58:20 -07001172
1173static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
1174 const u8 *src, const u8 *hdr,
1175 const u8 *buf, size_t len)
1176{
1177 struct dpp_authentication *auth = hapd->dpp_auth;
1178 enum dpp_status_error status;
1179 u8 ssid[SSID_MAX_LEN];
1180 size_t ssid_len = 0;
1181 char *channel_list = NULL;
1182
1183 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1184
1185 if (!auth || !auth->waiting_conn_status_result) {
1186 wpa_printf(MSG_DEBUG,
1187 "DPP: No DPP Configuration waiting for connection status result - drop");
1188 return;
1189 }
1190
1191 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1192 ssid, &ssid_len, &channel_list);
1193 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1194 "result=%d ssid=%s channel_list=%s",
1195 status, wpa_ssid_txt(ssid, ssid_len),
1196 channel_list ? channel_list : "N/A");
1197 os_free(channel_list);
1198 hostapd_drv_send_action_cancel_wait(hapd);
1199 hostapd_dpp_listen_stop(hapd);
1200 dpp_auth_deinit(auth);
1201 hapd->dpp_auth = NULL;
1202 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
1203 hapd, NULL);
1204}
1205
1206
Hai Shalomfdcde762020-04-02 11:19:20 -07001207static void
1208hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src,
1209 const u8 *hdr, const u8 *buf, size_t len,
1210 unsigned int freq)
1211{
1212 const u8 *r_bootstrap;
1213 u16 r_bootstrap_len;
1214 struct dpp_bootstrap_info *peer_bi;
1215 struct dpp_authentication *auth;
1216
1217 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
1218 MAC2STR(src));
1219
1220 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1221 &r_bootstrap_len);
1222 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1223 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1224 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1225 return;
1226 }
1227 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1228 r_bootstrap, r_bootstrap_len);
1229 peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp,
1230 r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07001231 dpp_notify_chirp_received(hapd->msg_ctx,
1232 peer_bi ? (int) peer_bi->id : -1,
1233 src, freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07001234 if (!peer_bi) {
1235 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1236 src, hdr, buf, len, freq, NULL,
1237 r_bootstrap) == 0)
1238 return;
1239 wpa_printf(MSG_DEBUG,
1240 "DPP: No matching bootstrapping information found");
1241 return;
1242 }
1243
1244 if (hapd->dpp_auth) {
1245 wpa_printf(MSG_DEBUG,
1246 "DPP: Ignore Presence Announcement during ongoing Authentication");
1247 return;
1248 }
1249
1250 auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1251 peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL,
1252 0);
1253 if (!auth)
1254 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07001255 hostapd_dpp_set_testing_options(hapd, auth);
1256 if (dpp_set_configurator(auth,
Hai Shalomfdcde762020-04-02 11:19:20 -07001257 hapd->dpp_configurator_params) < 0) {
1258 dpp_auth_deinit(auth);
1259 return;
1260 }
1261
1262 auth->neg_freq = freq;
1263
1264 if (!is_zero_ether_addr(peer_bi->mac_addr))
1265 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
1266
1267 hapd->dpp_auth = auth;
1268 if (hostapd_dpp_auth_init_next(hapd) < 0) {
1269 dpp_auth_deinit(hapd->dpp_auth);
1270 hapd->dpp_auth = NULL;
1271 }
1272}
1273
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001274
1275static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
1276 void *timeout_ctx)
1277{
1278 struct hostapd_data *hapd = eloop_ctx;
1279 struct dpp_authentication *auth = hapd->dpp_auth;
1280
1281 if (!auth)
1282 return;
1283
1284 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
1285 hostapd_dpp_listen_stop(hapd);
1286 dpp_auth_deinit(auth);
1287 hapd->dpp_auth = NULL;
1288}
1289
1290
1291static void
1292hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
1293 const u8 *hdr, const u8 *buf, size_t len,
1294 unsigned int freq)
1295{
Hai Shalom899fcc72020-10-19 14:38:18 -07001296 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
1297 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001298 struct dpp_configurator *conf;
1299 struct dpp_authentication *auth;
1300 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07001301 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001302
1303 if (hapd->dpp_auth) {
1304 wpa_printf(MSG_DEBUG,
1305 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1306 return;
1307 }
1308
1309 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
1310 MAC2STR(src));
1311
1312 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1313 &csign_hash_len);
1314 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
1315 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1316 "Missing or invalid required Configurator C-sign key Hash attribute");
1317 return;
1318 }
1319 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1320 csign_hash, csign_hash_len);
1321 conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp,
1322 csign_hash);
1323 if (!conf) {
1324 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1325 src, hdr, buf, len, freq, NULL,
1326 NULL) == 0)
1327 return;
1328 wpa_printf(MSG_DEBUG,
1329 "DPP: No matching Configurator information found");
1330 return;
1331 }
1332
Hai Shalom899fcc72020-10-19 14:38:18 -07001333 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
1334 &fcgroup_len);
1335 if (!fcgroup || fcgroup_len != 2) {
1336 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1337 "Missing or invalid required Finite Cyclic Group attribute");
1338 return;
1339 }
1340 group = WPA_GET_LE16(fcgroup);
1341 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
1342
1343 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
1344 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
1345
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001346 auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
Hai Shalom899fcc72020-10-19 14:38:18 -07001347 conf, freq, group, a_nonce, a_nonce_len,
1348 e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001349 if (!auth)
1350 return;
1351 hostapd_dpp_set_testing_options(hapd, auth);
1352 if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) {
1353 dpp_auth_deinit(auth);
1354 return;
1355 }
1356
1357 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1358 hapd->dpp_auth = auth;
1359
1360 hapd->dpp_in_response_listen = 0;
1361 hapd->dpp_auth_ok_on_ack = 0;
1362 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
1363 max_wait_time = hapd->dpp_resp_wait_time ?
1364 hapd->dpp_resp_wait_time : 2000;
1365 if (wait_time > max_wait_time)
1366 wait_time = max_wait_time;
1367 wait_time += 10; /* give the driver some extra time to complete */
1368 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
1369 hostapd_dpp_reconfig_reply_wait_timeout,
1370 hapd, NULL);
1371 wait_time -= 10;
1372
1373 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1374 " freq=%u type=%d",
1375 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
1376 if (hostapd_drv_send_action(hapd, freq, wait_time, src,
1377 wpabuf_head(auth->reconfig_req_msg),
1378 wpabuf_len(auth->reconfig_req_msg)) < 0) {
1379 dpp_auth_deinit(hapd->dpp_auth);
1380 hapd->dpp_auth = NULL;
1381 }
1382}
1383
1384
1385static void
1386hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src,
1387 const u8 *hdr, const u8 *buf, size_t len,
1388 unsigned int freq)
1389{
1390 struct dpp_authentication *auth = hapd->dpp_auth;
1391 struct wpabuf *conf;
1392
1393 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
1394 MACSTR, MAC2STR(src));
1395
1396 if (!auth || !auth->reconfig || !auth->configurator) {
1397 wpa_printf(MSG_DEBUG,
1398 "DPP: No DPP Reconfig Authentication in progress - drop");
1399 return;
1400 }
1401
1402 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1403 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1404 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1405 return;
1406 }
1407
1408 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
1409 if (!conf)
1410 return;
1411
1412 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1413 hapd, NULL);
1414
1415 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1416 " freq=%u type=%d",
1417 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
1418 if (hostapd_drv_send_action(hapd, freq, 500, src,
1419 wpabuf_head(conf), wpabuf_len(conf)) < 0) {
1420 wpabuf_free(conf);
1421 dpp_auth_deinit(hapd->dpp_auth);
1422 hapd->dpp_auth = NULL;
1423 return;
1424 }
1425 wpabuf_free(conf);
1426}
1427
Hai Shalom021b0b52019-04-10 11:17:58 -07001428#endif /* CONFIG_DPP2 */
1429
1430
Roshan Pius3a1667e2018-07-03 15:17:14 -07001431static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1432 const u8 *src, unsigned int freq,
1433 u8 trans_id,
1434 enum dpp_status_error status)
1435{
1436 struct wpabuf *msg;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001437 size_t len;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001438
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001439 len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector);
1440#ifdef CONFIG_DPP2
1441 len += 5;
1442#endif /* CONFIG_DPP2 */
1443 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001444 if (!msg)
1445 return;
1446
1447#ifdef CONFIG_TESTING_OPTIONS
1448 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1449 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1450 goto skip_trans_id;
1451 }
1452 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1453 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1454 trans_id ^= 0x01;
1455 }
1456#endif /* CONFIG_TESTING_OPTIONS */
1457
1458 /* Transaction ID */
1459 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1460 wpabuf_put_le16(msg, 1);
1461 wpabuf_put_u8(msg, trans_id);
1462
1463#ifdef CONFIG_TESTING_OPTIONS
1464skip_trans_id:
1465 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1466 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1467 goto skip_status;
1468 }
1469 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1470 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1471 status = 254;
1472 }
1473#endif /* CONFIG_TESTING_OPTIONS */
1474
1475 /* DPP Status */
1476 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1477 wpabuf_put_le16(msg, 1);
1478 wpabuf_put_u8(msg, status);
1479
1480#ifdef CONFIG_TESTING_OPTIONS
1481skip_status:
1482 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1483 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1484 goto skip_connector;
1485 }
1486 if (status == DPP_STATUS_OK &&
1487 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1488 char *connector;
1489
1490 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1491 connector = dpp_corrupt_connector_signature(
1492 hapd->conf->dpp_connector);
1493 if (!connector) {
1494 wpabuf_free(msg);
1495 return;
1496 }
1497 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1498 wpabuf_put_le16(msg, os_strlen(connector));
1499 wpabuf_put_str(msg, connector);
1500 os_free(connector);
1501 goto skip_connector;
1502 }
1503#endif /* CONFIG_TESTING_OPTIONS */
1504
1505 /* DPP Connector */
1506 if (status == DPP_STATUS_OK) {
1507 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1508 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1509 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1510 }
1511
1512#ifdef CONFIG_TESTING_OPTIONS
1513skip_connector:
1514#endif /* CONFIG_TESTING_OPTIONS */
1515
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001516#ifdef CONFIG_DPP2
1517 if (DPP_VERSION > 1) {
1518 /* Protocol Version */
1519 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
1520 wpabuf_put_le16(msg, 1);
1521 wpabuf_put_u8(msg, DPP_VERSION);
1522 }
1523#endif /* CONFIG_DPP2 */
1524
Roshan Pius3a1667e2018-07-03 15:17:14 -07001525 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1526 " status=%d", MAC2STR(src), status);
1527 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1528 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1529 DPP_PA_PEER_DISCOVERY_RESP, status);
1530 hostapd_drv_send_action(hapd, freq, 0, src,
1531 wpabuf_head(msg), wpabuf_len(msg));
1532 wpabuf_free(msg);
1533}
1534
1535
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001536static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1537 const u8 *src,
1538 const u8 *buf, size_t len,
1539 unsigned int freq)
1540{
1541 const u8 *connector, *trans_id;
1542 u16 connector_len, trans_id_len;
1543 struct os_time now;
1544 struct dpp_introduction intro;
1545 os_time_t expire;
1546 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001547 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001548
1549 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1550 MAC2STR(src));
1551 if (!hapd->wpa_auth ||
1552 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1553 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1554 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1555 return;
1556 }
1557
1558 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1559 !hapd->conf->dpp_csign) {
1560 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1561 return;
1562 }
1563
1564 os_get_time(&now);
1565
1566 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001567 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001568 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1569 return;
1570 }
1571
1572 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1573 &trans_id_len);
1574 if (!trans_id || trans_id_len != 1) {
1575 wpa_printf(MSG_DEBUG,
1576 "DPP: Peer did not include Transaction ID");
1577 return;
1578 }
1579
1580 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1581 if (!connector) {
1582 wpa_printf(MSG_DEBUG,
1583 "DPP: Peer did not include its Connector");
1584 return;
1585 }
1586
Roshan Pius3a1667e2018-07-03 15:17:14 -07001587 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1588 wpabuf_head(hapd->conf->dpp_netaccesskey),
1589 wpabuf_len(hapd->conf->dpp_netaccesskey),
1590 wpabuf_head(hapd->conf->dpp_csign),
1591 wpabuf_len(hapd->conf->dpp_csign),
1592 connector, connector_len, &expire);
1593 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001594 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001595 "DPP: Network Introduction protocol resulted in internal failure (peer "
1596 MACSTR ")", MAC2STR(src));
1597 return;
1598 }
1599 if (res != DPP_STATUS_OK) {
1600 wpa_printf(MSG_INFO,
1601 "DPP: Network Introduction protocol resulted in failure (peer "
1602 MACSTR " status %d)", MAC2STR(src), res);
1603 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1604 res);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001605 return;
1606 }
1607
Roshan Pius3a1667e2018-07-03 15:17:14 -07001608 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001609 expire = hapd->conf->dpp_netaccesskey_expiry;
1610 if (expire)
1611 expiration = expire - now.sec;
1612 else
1613 expiration = 0;
1614
1615 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1616 intro.pmkid, expiration,
1617 WPA_KEY_MGMT_DPP) < 0) {
1618 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
1619 return;
1620 }
1621
Roshan Pius3a1667e2018-07-03 15:17:14 -07001622 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1623 DPP_STATUS_OK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001624}
1625
1626
1627static void
1628hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
1629 const u8 *buf, size_t len,
1630 unsigned int freq)
1631{
1632 struct wpabuf *msg;
1633
1634 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1635 MAC2STR(src));
1636
1637 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1638 * values here */
1639
1640 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
1641 wpa_printf(MSG_DEBUG,
1642 "DPP: No PKEX code configured - ignore request");
1643 return;
1644 }
1645
1646 if (hapd->dpp_pkex) {
1647 /* TODO: Support parallel operations */
1648 wpa_printf(MSG_DEBUG,
1649 "DPP: Already in PKEX session - ignore new request");
1650 return;
1651 }
1652
Roshan Pius3a1667e2018-07-03 15:17:14 -07001653 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
1654 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001655 hapd->own_addr, src,
1656 hapd->dpp_pkex_identifier,
1657 hapd->dpp_pkex_code,
1658 buf, len);
1659 if (!hapd->dpp_pkex) {
1660 wpa_printf(MSG_DEBUG,
1661 "DPP: Failed to process the request - ignore it");
1662 return;
1663 }
1664
1665 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001666 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1667 " freq=%u type=%d", MAC2STR(src), freq,
1668 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001669 hostapd_drv_send_action(hapd, freq, 0, src,
1670 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001671 if (hapd->dpp_pkex->failed) {
1672 wpa_printf(MSG_DEBUG,
1673 "DPP: Terminate PKEX exchange due to an earlier error");
1674 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1675 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
1676 dpp_pkex_free(hapd->dpp_pkex);
1677 hapd->dpp_pkex = NULL;
1678 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001679}
1680
1681
1682static void
1683hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
1684 const u8 *buf, size_t len, unsigned int freq)
1685{
1686 struct wpabuf *msg;
1687
1688 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1689 MAC2STR(src));
1690
1691 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1692 * values here */
1693
1694 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
1695 hapd->dpp_pkex->exchange_done) {
1696 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1697 return;
1698 }
1699
Roshan Pius3a1667e2018-07-03 15:17:14 -07001700 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001701 if (!msg) {
1702 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1703 return;
1704 }
1705
1706 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1707 MAC2STR(src));
1708
Roshan Pius3a1667e2018-07-03 15:17:14 -07001709 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1710 " freq=%u type=%d", MAC2STR(src), freq,
1711 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001712 hostapd_drv_send_action(hapd, freq, 0, src,
1713 wpabuf_head(msg), wpabuf_len(msg));
1714 wpabuf_free(msg);
1715}
1716
1717
1718static void
1719hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
1720 const u8 *hdr, const u8 *buf, size_t len,
1721 unsigned int freq)
1722{
1723 struct wpabuf *msg;
1724 struct dpp_pkex *pkex = hapd->dpp_pkex;
1725 struct dpp_bootstrap_info *bi;
1726
1727 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1728 MAC2STR(src));
1729
1730 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1731 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1732 return;
1733 }
1734
1735 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1736 if (!msg) {
1737 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001738 if (hapd->dpp_pkex->failed) {
1739 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1740 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1741 hapd->dpp_pkex->own_bi->pkex_t =
1742 hapd->dpp_pkex->t;
1743 dpp_pkex_free(hapd->dpp_pkex);
1744 hapd->dpp_pkex = NULL;
1745 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001746 return;
1747 }
1748
1749 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1750 MACSTR, MAC2STR(src));
1751
Roshan Pius3a1667e2018-07-03 15:17:14 -07001752 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1753 " freq=%u type=%d", MAC2STR(src), freq,
1754 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001755 hostapd_drv_send_action(hapd, freq, 0, src,
1756 wpabuf_head(msg), wpabuf_len(msg));
1757 wpabuf_free(msg);
1758
Hai Shalom021b0b52019-04-10 11:17:58 -07001759 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001760 if (!bi)
1761 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001762 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001763}
1764
1765
1766static void
1767hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
1768 const u8 *hdr, const u8 *buf, size_t len,
1769 unsigned int freq)
1770{
1771 int res;
Hai Shalom021b0b52019-04-10 11:17:58 -07001772 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001773 struct dpp_pkex *pkex = hapd->dpp_pkex;
1774 char cmd[500];
1775
1776 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
1777 MAC2STR(src));
1778
1779 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1780 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1781 return;
1782 }
1783
1784 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1785 if (res < 0) {
1786 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1787 return;
1788 }
1789
Hai Shalom021b0b52019-04-10 11:17:58 -07001790 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001791 if (!bi)
1792 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001793 hapd->dpp_pkex = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001794
1795 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
1796 bi->id,
1797 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
1798 wpa_printf(MSG_DEBUG,
1799 "DPP: Start authentication after PKEX with parameters: %s",
1800 cmd);
1801 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
1802 wpa_printf(MSG_DEBUG,
1803 "DPP: Authentication initialization failed");
1804 return;
1805 }
1806}
1807
1808
1809void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
1810 const u8 *buf, size_t len, unsigned int freq)
1811{
1812 u8 crypto_suite;
1813 enum dpp_public_action_frame_type type;
1814 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001815 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001816
1817 if (len < DPP_HDR_LEN)
1818 return;
1819 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
1820 return;
1821 hdr = buf;
1822 buf += 4;
1823 len -= 4;
1824 crypto_suite = *buf++;
1825 type = *buf++;
1826 len -= 2;
1827
1828 wpa_printf(MSG_DEBUG,
1829 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
1830 MACSTR " freq=%u",
1831 crypto_suite, type, MAC2STR(src), freq);
1832 if (crypto_suite != 1) {
1833 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
1834 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001835 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1836 " freq=%u type=%d ignore=unsupported-crypto-suite",
1837 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001838 return;
1839 }
1840 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001841 if (dpp_check_attrs(buf, len) < 0) {
1842 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1843 " freq=%u type=%d ignore=invalid-attributes",
1844 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001845 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001846 }
1847 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1848 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001849
Hai Shalom81f62d82019-07-22 12:10:00 -07001850#ifdef CONFIG_DPP2
1851 if (dpp_relay_rx_action(hapd->iface->interfaces->dpp,
1852 src, hdr, buf, len, freq, NULL, NULL) == 0)
1853 return;
1854#endif /* CONFIG_DPP2 */
1855
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001856 switch (type) {
1857 case DPP_PA_AUTHENTICATION_REQ:
1858 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
1859 break;
1860 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07001861 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001862 break;
1863 case DPP_PA_AUTHENTICATION_CONF:
1864 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
1865 break;
1866 case DPP_PA_PEER_DISCOVERY_REQ:
1867 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
1868 break;
1869 case DPP_PA_PKEX_EXCHANGE_REQ:
1870 hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
1871 break;
1872 case DPP_PA_PKEX_EXCHANGE_RESP:
1873 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
1874 break;
1875 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1876 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
1877 freq);
1878 break;
1879 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1880 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
1881 freq);
1882 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07001883#ifdef CONFIG_DPP2
1884 case DPP_PA_CONFIGURATION_RESULT:
1885 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
1886 break;
Hai Shalomc3565922019-10-28 11:58:20 -07001887 case DPP_PA_CONNECTION_STATUS_RESULT:
1888 hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
1889 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07001890 case DPP_PA_PRESENCE_ANNOUNCEMENT:
1891 hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len,
1892 freq);
1893 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001894 case DPP_PA_RECONFIG_ANNOUNCEMENT:
1895 hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len,
1896 freq);
1897 break;
1898 case DPP_PA_RECONFIG_AUTH_RESP:
1899 hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len,
1900 freq);
1901 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07001902#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001903 default:
1904 wpa_printf(MSG_DEBUG,
1905 "DPP: Ignored unsupported frame subtype %d", type);
1906 break;
1907 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001908
1909 if (hapd->dpp_pkex)
1910 pkex_t = hapd->dpp_pkex->t;
1911 else if (hapd->dpp_pkex_bi)
1912 pkex_t = hapd->dpp_pkex_bi->pkex_t;
1913 else
1914 pkex_t = 0;
1915 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
1916 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
1917 hostapd_dpp_pkex_remove(hapd, "*");
1918 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001919}
1920
1921
1922struct wpabuf *
1923hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
Hai Shalom81f62d82019-07-22 12:10:00 -07001924 const u8 *query, size_t query_len,
1925 const u8 *data, size_t data_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001926{
1927 struct dpp_authentication *auth = hapd->dpp_auth;
1928 struct wpabuf *resp;
1929
1930 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001931 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001932 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07001933#ifdef CONFIG_DPP2
1934 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data,
1935 data_len) == 0) {
1936 /* Response will be forwarded once received over TCP */
1937 return NULL;
1938 }
1939#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001940 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1941 return NULL;
1942 }
1943 wpa_hexdump(MSG_DEBUG,
1944 "DPP: Received Configuration Request (GAS Query Request)",
1945 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001946 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
1947 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001948 resp = dpp_conf_req_rx(auth, query, query_len);
1949 if (!resp)
1950 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1951 return resp;
1952}
1953
1954
Roshan Pius3a1667e2018-07-03 15:17:14 -07001955void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
1956{
Hai Shalom021b0b52019-04-10 11:17:58 -07001957 struct dpp_authentication *auth = hapd->dpp_auth;
1958
1959 if (!auth)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001960 return;
1961
Hai Shalom021b0b52019-04-10 11:17:58 -07001962 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
1963 ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001964 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1965 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001966#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001967 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
1968 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07001969 if (ok && auth->peer_version >= 2 &&
1970 auth->conf_resp_status == DPP_STATUS_OK) {
1971 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
1972 auth->waiting_conf_result = 1;
1973 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1974 hapd, NULL);
1975 eloop_register_timeout(2, 0,
1976 hostapd_dpp_config_result_wait_timeout,
1977 hapd, NULL);
1978 return;
1979 }
1980#endif /* CONFIG_DPP2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001981 hostapd_drv_send_action_cancel_wait(hapd);
1982
1983 if (ok)
1984 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1985 else
1986 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1987 dpp_auth_deinit(hapd->dpp_auth);
1988 hapd->dpp_auth = NULL;
1989}
1990
1991
Roshan Pius3a1667e2018-07-03 15:17:14 -07001992int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
1993{
1994 struct dpp_authentication *auth;
1995 int ret = -1;
1996 char *curve = NULL;
1997
Hai Shalomfdcde762020-04-02 11:19:20 -07001998 auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001999 if (!auth)
2000 return -1;
2001
2002 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08002003 hostapd_dpp_set_testing_options(hapd, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07002004 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08002005 dpp_configurator_own_config(auth, curve, 1) == 0) {
Hai Shalomc3565922019-10-28 11:58:20 -07002006 hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002007 ret = 0;
2008 }
2009
2010 dpp_auth_deinit(auth);
2011 os_free(curve);
2012
2013 return ret;
2014}
2015
2016
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002017int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
2018{
2019 struct dpp_bootstrap_info *own_bi;
2020 const char *pos, *end;
2021
2022 pos = os_strstr(cmd, " own=");
2023 if (!pos)
2024 return -1;
2025 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07002026 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002027 if (!own_bi) {
2028 wpa_printf(MSG_DEBUG,
2029 "DPP: Identified bootstrap info not found");
2030 return -1;
2031 }
2032 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2033 wpa_printf(MSG_DEBUG,
2034 "DPP: Identified bootstrap info not for PKEX");
2035 return -1;
2036 }
2037 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002038 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002039
2040 os_free(hapd->dpp_pkex_identifier);
2041 hapd->dpp_pkex_identifier = NULL;
2042 pos = os_strstr(cmd, " identifier=");
2043 if (pos) {
2044 pos += 12;
2045 end = os_strchr(pos, ' ');
2046 if (!end)
2047 return -1;
2048 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
2049 if (!hapd->dpp_pkex_identifier)
2050 return -1;
2051 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
2052 hapd->dpp_pkex_identifier[end - pos] = '\0';
2053 }
2054
2055 pos = os_strstr(cmd, " code=");
2056 if (!pos)
2057 return -1;
2058 os_free(hapd->dpp_pkex_code);
2059 hapd->dpp_pkex_code = os_strdup(pos + 6);
2060 if (!hapd->dpp_pkex_code)
2061 return -1;
2062
2063 if (os_strstr(cmd, " init=1")) {
2064 struct wpabuf *msg;
2065
2066 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
2067 dpp_pkex_free(hapd->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002068 hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
2069 hapd->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002070 hapd->dpp_pkex_identifier,
2071 hapd->dpp_pkex_code);
2072 if (!hapd->dpp_pkex)
2073 return -1;
2074
2075 msg = hapd->dpp_pkex->exchange_req;
2076 /* TODO: Which channel to use? */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002077 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2078 " freq=%u type=%d", MAC2STR(broadcast), 2437,
2079 DPP_PA_PKEX_EXCHANGE_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002080 hostapd_drv_send_action(hapd, 2437, 0, broadcast,
2081 wpabuf_head(msg), wpabuf_len(msg));
2082 }
2083
2084 /* TODO: Support multiple PKEX info entries */
2085
2086 os_free(hapd->dpp_pkex_auth_cmd);
2087 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
2088
2089 return 1;
2090}
2091
2092
2093int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
2094{
2095 unsigned int id_val;
2096
2097 if (os_strcmp(id, "*") == 0) {
2098 id_val = 0;
2099 } else {
2100 id_val = atoi(id);
2101 if (id_val == 0)
2102 return -1;
2103 }
2104
2105 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
2106 return -1;
2107
2108 /* TODO: Support multiple PKEX entries */
2109 os_free(hapd->dpp_pkex_code);
2110 hapd->dpp_pkex_code = NULL;
2111 os_free(hapd->dpp_pkex_identifier);
2112 hapd->dpp_pkex_identifier = NULL;
2113 os_free(hapd->dpp_pkex_auth_cmd);
2114 hapd->dpp_pkex_auth_cmd = NULL;
2115 hapd->dpp_pkex_bi = NULL;
2116 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2117 dpp_pkex_free(hapd->dpp_pkex);
2118 hapd->dpp_pkex = NULL;
2119 return 0;
2120}
2121
2122
Roshan Pius3a1667e2018-07-03 15:17:14 -07002123void hostapd_dpp_stop(struct hostapd_data *hapd)
2124{
2125 dpp_auth_deinit(hapd->dpp_auth);
2126 hapd->dpp_auth = NULL;
2127 dpp_pkex_free(hapd->dpp_pkex);
2128 hapd->dpp_pkex = NULL;
2129}
2130
2131
Hai Shalom81f62d82019-07-22 12:10:00 -07002132#ifdef CONFIG_DPP2
2133
2134static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq,
2135 const u8 *msg, size_t len)
2136{
2137 struct hostapd_data *hapd = ctx;
2138 u8 *buf;
2139
2140 wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u",
2141 MAC2STR(addr), freq);
2142 buf = os_malloc(2 + len);
2143 if (!buf)
2144 return;
2145 buf[0] = WLAN_ACTION_PUBLIC;
2146 buf[1] = WLAN_PA_VENDOR_SPECIFIC;
2147 os_memcpy(buf + 2, msg, len);
2148 hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len);
2149 os_free(buf);
2150}
2151
2152
2153static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr,
2154 u8 dialog_token, int prot,
2155 struct wpabuf *buf)
2156{
2157 struct hostapd_data *hapd = ctx;
2158
2159 gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf);
2160}
2161
2162#endif /* CONFIG_DPP2 */
2163
2164
2165static int hostapd_dpp_add_controllers(struct hostapd_data *hapd)
2166{
2167#ifdef CONFIG_DPP2
2168 struct dpp_controller_conf *ctrl;
2169 struct dpp_relay_config config;
2170
2171 os_memset(&config, 0, sizeof(config));
2172 config.cb_ctx = hapd;
2173 config.tx = hostapd_dpp_relay_tx;
2174 config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx;
2175 for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) {
2176 config.ipaddr = &ctrl->ipaddr;
2177 config.pkhash = ctrl->pkhash;
2178 if (dpp_relay_add_controller(hapd->iface->interfaces->dpp,
2179 &config) < 0)
2180 return -1;
2181 }
2182#endif /* CONFIG_DPP2 */
2183
2184 return 0;
2185}
2186
2187
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002188int hostapd_dpp_init(struct hostapd_data *hapd)
2189{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002190 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
2191 hapd->dpp_init_done = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002192 return hostapd_dpp_add_controllers(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002193}
2194
2195
2196void hostapd_dpp_deinit(struct hostapd_data *hapd)
2197{
2198#ifdef CONFIG_TESTING_OPTIONS
2199 os_free(hapd->dpp_config_obj_override);
2200 hapd->dpp_config_obj_override = NULL;
2201 os_free(hapd->dpp_discovery_override);
2202 hapd->dpp_discovery_override = NULL;
2203 os_free(hapd->dpp_groups_override);
2204 hapd->dpp_groups_override = NULL;
2205 hapd->dpp_ignore_netaccesskey_mismatch = 0;
2206#endif /* CONFIG_TESTING_OPTIONS */
2207 if (!hapd->dpp_init_done)
2208 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002209 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
2210 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
2211 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002212#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002213 eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout,
2214 hapd, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002215 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
2216 NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07002217 eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
2218 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002219 hostapd_dpp_chirp_stop(hapd);
Hai Shalom021b0b52019-04-10 11:17:58 -07002220#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002221 dpp_auth_deinit(hapd->dpp_auth);
2222 hapd->dpp_auth = NULL;
2223 hostapd_dpp_pkex_remove(hapd, "*");
2224 hapd->dpp_pkex = NULL;
2225 os_free(hapd->dpp_configurator_params);
2226 hapd->dpp_configurator_params = NULL;
2227}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002228
2229
2230#ifdef CONFIG_DPP2
2231
Hai Shalom899fcc72020-10-19 14:38:18 -07002232int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd)
2233{
2234 struct dpp_controller_config config;
2235 const char *pos;
2236
2237 os_memset(&config, 0, sizeof(config));
2238 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
2239 config.netrole = DPP_NETROLE_AP;
2240 config.msg_ctx = hapd->msg_ctx;
2241 config.cb_ctx = hapd;
2242 config.process_conf_obj = hostapd_dpp_process_conf_obj;
2243 if (cmd) {
2244 pos = os_strstr(cmd, " tcp_port=");
2245 if (pos) {
2246 pos += 10;
2247 config.tcp_port = atoi(pos);
2248 }
2249
2250 pos = os_strstr(cmd, " role=");
2251 if (pos) {
2252 pos += 6;
2253 if (os_strncmp(pos, "configurator", 12) == 0)
2254 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
2255 else if (os_strncmp(pos, "enrollee", 8) == 0)
2256 config.allowed_roles = DPP_CAPAB_ENROLLEE;
2257 else if (os_strncmp(pos, "either", 6) == 0)
2258 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
2259 DPP_CAPAB_ENROLLEE;
2260 else
2261 return -1;
2262 }
2263
2264 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
2265 }
2266 config.configurator_params = hapd->dpp_configurator_params;
2267 return dpp_controller_start(hapd->iface->interfaces->dpp, &config);
2268}
2269
2270
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002271static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
2272
2273static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
2274{
2275 struct hostapd_data *hapd = eloop_ctx;
2276
2277 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
2278 hostapd_drv_send_action_cancel_wait(hapd);
2279 hostapd_dpp_chirp_next(hapd, NULL);
2280}
2281
2282
2283static void hostapd_dpp_chirp_start(struct hostapd_data *hapd)
2284{
2285 struct wpabuf *msg;
2286 int type;
2287
2288 msg = hapd->dpp_presence_announcement;
2289 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
2290 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq);
2291 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2292 " freq=%u type=%d",
2293 MAC2STR(broadcast), hapd->dpp_chirp_freq, type);
2294 if (hostapd_drv_send_action(
2295 hapd, hapd->dpp_chirp_freq, 2000, broadcast,
2296 wpabuf_head(msg), wpabuf_len(msg)) < 0 ||
2297 eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout,
2298 hapd, NULL) < 0)
2299 hostapd_dpp_chirp_stop(hapd);
2300}
2301
2302
2303static struct hostapd_hw_modes *
2304dpp_get_mode(struct hostapd_data *hapd,
2305 enum hostapd_hw_mode mode)
2306{
2307 struct hostapd_hw_modes *modes = hapd->iface->hw_features;
2308 u16 num_modes = hapd->iface->num_hw_features;
2309 u16 i;
2310
2311 for (i = 0; i < num_modes; i++) {
2312 if (modes[i].mode != mode ||
2313 !modes[i].num_channels || !modes[i].channels)
2314 continue;
2315 return &modes[i];
2316 }
2317
2318 return NULL;
2319}
2320
2321
2322static void
2323hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface)
2324{
2325 struct hostapd_data *hapd = iface->bss[0];
2326 struct wpa_scan_results *scan_res;
2327 struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi;
2328 unsigned int i;
2329 struct hostapd_hw_modes *mode;
2330 int c;
2331
2332 if (!bi)
2333 return;
2334
2335 hapd->dpp_chirp_scan_done = 1;
2336
2337 scan_res = hostapd_driver_get_scan_results(hapd);
2338
2339 os_free(hapd->dpp_chirp_freqs);
2340 hapd->dpp_chirp_freqs = NULL;
2341
2342 /* Channels from own bootstrapping info */
2343 if (bi) {
2344 for (i = 0; i < bi->num_freq; i++)
2345 int_array_add_unique(&hapd->dpp_chirp_freqs,
2346 bi->freq[i]);
2347 }
2348
2349 /* Preferred chirping channels */
2350 int_array_add_unique(&hapd->dpp_chirp_freqs, 2437);
2351
2352 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A);
2353 if (mode) {
2354 int chan44 = 0, chan149 = 0;
2355
2356 for (c = 0; c < mode->num_channels; c++) {
2357 struct hostapd_channel_data *chan = &mode->channels[c];
2358
2359 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2360 HOSTAPD_CHAN_RADAR))
2361 continue;
2362 if (chan->freq == 5220)
2363 chan44 = 1;
2364 if (chan->freq == 5745)
2365 chan149 = 1;
2366 }
2367 if (chan149)
2368 int_array_add_unique(&hapd->dpp_chirp_freqs, 5745);
2369 else if (chan44)
2370 int_array_add_unique(&hapd->dpp_chirp_freqs, 5220);
2371 }
2372
2373 mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD);
2374 if (mode) {
2375 for (c = 0; c < mode->num_channels; c++) {
2376 struct hostapd_channel_data *chan = &mode->channels[c];
2377
2378 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
2379 HOSTAPD_CHAN_RADAR)) ||
2380 chan->freq != 60480)
2381 continue;
2382 int_array_add_unique(&hapd->dpp_chirp_freqs, 60480);
2383 break;
2384 }
2385 }
2386
2387 /* Add channels from scan results for APs that advertise Configurator
2388 * Connectivity element */
2389 for (i = 0; scan_res && i < scan_res->num; i++) {
2390 struct wpa_scan_res *bss = scan_res->res[i];
2391 size_t ie_len = bss->ie_len;
2392
2393 if (!ie_len)
2394 ie_len = bss->beacon_ie_len;
2395 if (get_vendor_ie((const u8 *) (bss + 1), ie_len,
2396 DPP_CC_IE_VENDOR_TYPE))
2397 int_array_add_unique(&hapd->dpp_chirp_freqs,
2398 bss->freq);
2399 }
2400
2401 if (!hapd->dpp_chirp_freqs ||
2402 eloop_register_timeout(0, 0, hostapd_dpp_chirp_next,
2403 hapd, NULL) < 0)
2404 hostapd_dpp_chirp_stop(hapd);
2405
2406 wpa_scan_results_free(scan_res);
2407}
2408
2409
2410static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
2411{
2412 struct hostapd_data *hapd = eloop_ctx;
2413 int i;
2414
2415 if (hapd->dpp_chirp_listen)
2416 hostapd_dpp_listen_stop(hapd);
2417
2418 if (hapd->dpp_chirp_freq == 0) {
2419 if (hapd->dpp_chirp_round % 4 == 0 &&
2420 !hapd->dpp_chirp_scan_done) {
2421 struct wpa_driver_scan_params params;
2422 int ret;
2423
2424 wpa_printf(MSG_DEBUG,
2425 "DPP: Update channel list for chirping");
2426 os_memset(&params, 0, sizeof(params));
2427 ret = hostapd_driver_scan(hapd, &params);
2428 if (ret < 0) {
2429 wpa_printf(MSG_DEBUG,
2430 "DPP: Failed to request a scan ret=%d (%s)",
2431 ret, strerror(-ret));
2432 hostapd_dpp_chirp_scan_res_handler(hapd->iface);
2433 } else {
2434 hapd->iface->scan_cb =
2435 hostapd_dpp_chirp_scan_res_handler;
2436 }
2437 return;
2438 }
2439 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0];
2440 hapd->dpp_chirp_round++;
2441 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
2442 hapd->dpp_chirp_round);
2443 } else {
2444 for (i = 0; hapd->dpp_chirp_freqs[i]; i++)
2445 if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq)
2446 break;
2447 if (!hapd->dpp_chirp_freqs[i]) {
2448 wpa_printf(MSG_DEBUG,
2449 "DPP: Previous chirp freq %d not found",
2450 hapd->dpp_chirp_freq);
2451 return;
2452 }
2453 i++;
2454 if (hapd->dpp_chirp_freqs[i]) {
2455 hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i];
2456 } else {
2457 hapd->dpp_chirp_iter--;
2458 if (hapd->dpp_chirp_iter <= 0) {
2459 wpa_printf(MSG_DEBUG,
2460 "DPP: Chirping iterations completed");
2461 hostapd_dpp_chirp_stop(hapd);
2462 return;
2463 }
2464 hapd->dpp_chirp_freq = 0;
2465 hapd->dpp_chirp_scan_done = 0;
2466 if (eloop_register_timeout(30, 0,
2467 hostapd_dpp_chirp_next,
2468 hapd, NULL) < 0) {
2469 hostapd_dpp_chirp_stop(hapd);
2470 return;
2471 }
2472 if (hapd->dpp_chirp_listen) {
2473 wpa_printf(MSG_DEBUG,
2474 "DPP: Listen on %d MHz during chirp 30 second wait",
2475 hapd->dpp_chirp_listen);
2476 /* TODO: start listen on the channel */
2477 } else {
2478 wpa_printf(MSG_DEBUG,
2479 "DPP: Wait 30 seconds before starting the next chirping round");
2480 }
2481 return;
2482 }
2483 }
2484
2485 hostapd_dpp_chirp_start(hapd);
2486}
2487
2488
2489int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd)
2490{
2491 const char *pos;
2492 int iter = 1, listen_freq = 0;
2493 struct dpp_bootstrap_info *bi;
2494
2495 pos = os_strstr(cmd, " own=");
2496 if (!pos)
2497 return -1;
2498 pos += 5;
2499 bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
2500 if (!bi) {
2501 wpa_printf(MSG_DEBUG,
2502 "DPP: Identified bootstrap info not found");
2503 return -1;
2504 }
2505
2506 pos = os_strstr(cmd, " iter=");
2507 if (pos) {
2508 iter = atoi(pos + 6);
2509 if (iter <= 0)
2510 return -1;
2511 }
2512
2513 pos = os_strstr(cmd, " listen=");
2514 if (pos) {
2515 listen_freq = atoi(pos + 8);
2516 if (listen_freq <= 0)
2517 return -1;
2518 }
2519
2520 hostapd_dpp_chirp_stop(hapd);
2521 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
2522 hapd->dpp_qr_mutual = 0;
2523 hapd->dpp_chirp_bi = bi;
2524 hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi);
2525 if (!hapd->dpp_presence_announcement)
2526 return -1;
2527 hapd->dpp_chirp_iter = iter;
2528 hapd->dpp_chirp_round = 0;
2529 hapd->dpp_chirp_scan_done = 0;
2530 hapd->dpp_chirp_listen = listen_freq;
2531
2532 return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL);
2533}
2534
2535
2536void hostapd_dpp_chirp_stop(struct hostapd_data *hapd)
2537{
2538 if (hapd->dpp_presence_announcement) {
2539 hostapd_drv_send_action_cancel_wait(hapd);
2540 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
2541 }
2542 hapd->dpp_chirp_bi = NULL;
2543 wpabuf_free(hapd->dpp_presence_announcement);
2544 hapd->dpp_presence_announcement = NULL;
2545 if (hapd->dpp_chirp_listen)
2546 hostapd_dpp_listen_stop(hapd);
2547 hapd->dpp_chirp_listen = 0;
2548 hapd->dpp_chirp_freq = 0;
2549 os_free(hapd->dpp_chirp_freqs);
2550 hapd->dpp_chirp_freqs = NULL;
2551 eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL);
2552 eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL);
2553 if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) {
2554 /* TODO: abort ongoing scan */
2555 hapd->iface->scan_cb = NULL;
2556 }
2557}
2558
2559
2560static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx)
2561{
2562 struct dpp_bootstrap_info *bi = ctx;
2563 size_t i;
2564
2565 for (i = 0; i < iface->num_bss; i++) {
2566 struct hostapd_data *hapd = iface->bss[i];
2567
2568 if (bi == hapd->dpp_chirp_bi)
2569 hostapd_dpp_chirp_stop(hapd);
2570 }
2571
2572 return 0;
2573}
2574
2575
2576void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2577{
2578 struct hapd_interfaces *interfaces = ctx;
2579
2580 hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi);
2581}
2582
2583#endif /* CONFIG_DPP2 */