]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/dpp_supplicant.c
tests: OCE association in open network
[thirdparty/hostap.git] / wpa_supplicant / dpp_supplicant.c
CommitLineData
be27e185
JM
1/*
2 * wpa_supplicant - DPP
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
18015fc8 4 * Copyright (c) 2018-2019, The Linux Foundation
be27e185
JM
5 *
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"
30d27b04 13#include "utils/eloop.h"
c02dd10d 14#include "utils/ip_addr.h"
be27e185 15#include "common/dpp.h"
461d39af
JM
16#include "common/gas.h"
17#include "common/gas_server.h"
a0d5c56f
JM
18#include "rsn_supp/wpa.h"
19#include "rsn_supp/pmksa_cache.h"
be27e185 20#include "wpa_supplicant_i.h"
a0d5c56f 21#include "config.h"
30d27b04
JM
22#include "driver_i.h"
23#include "offchannel.h"
461d39af 24#include "gas_query.h"
a0d5c56f
JM
25#include "bss.h"
26#include "scan.h"
8528994e 27#include "notify.h"
be27e185
JM
28#include "dpp_supplicant.h"
29
30
30d27b04
JM
31static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
32 unsigned int freq);
461d39af
JM
33static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
34static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
30d27b04
JM
35static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
36 unsigned int freq, const u8 *dst,
37 const u8 *src, const u8 *bssid,
38 const u8 *data, size_t data_len,
39 enum offchannel_send_action_result result);
f97ace34
JM
40static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
41static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
00d2d13d
JM
42static void
43wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
44 unsigned int freq, const u8 *dst,
45 const u8 *src, const u8 *bssid,
46 const u8 *data, size_t data_len,
47 enum offchannel_send_action_result result);
30d27b04
JM
48
49static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
50
85fd8263
JM
51/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
52 * a single transaction in progress at any point in time. */
53static const u8 TRANSACTION_ID = 1;
54
30d27b04 55
be27e185
JM
56/**
57 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
58 * @wpa_s: Pointer to wpa_supplicant data
59 * @cmd: DPP URI read from a QR Code
60 * Returns: Identifier of the stored info or -1 on failure
61 */
62int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
63{
64 struct dpp_bootstrap_info *bi;
30d27b04 65 struct dpp_authentication *auth = wpa_s->dpp_auth;
be27e185 66
87d8435c 67 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
be27e185
JM
68 if (!bi)
69 return -1;
70
30d27b04
JM
71 if (auth && auth->response_pending &&
72 dpp_notify_new_qr_code(auth, bi) == 1) {
30d27b04
JM
73 wpa_printf(MSG_DEBUG,
74 "DPP: Sending out pending authentication response");
af48810b
JM
75 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
76 " freq=%u type=%d",
77 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
78 DPP_PA_AUTHENTICATION_RESP);
30d27b04
JM
79 offchannel_send_action(wpa_s, auth->curr_freq,
80 auth->peer_mac_addr, wpa_s->own_addr,
81 broadcast,
dc4d271c
JM
82 wpabuf_head(auth->resp_msg),
83 wpabuf_len(auth->resp_msg),
30d27b04 84 500, wpas_dpp_tx_status, 0);
30d27b04
JM
85 }
86
be27e185
JM
87 return bi->id;
88}
89
90
e780b4bf
JM
91/**
92 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
93 * @wpa_s: Pointer to wpa_supplicant data
94 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
95 * Returns: Identifier of the stored info or -1 on failure
96 */
97int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
98{
99 struct dpp_bootstrap_info *bi;
100
101 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
102 if (!bi)
103 return -1;
104
105 return bi->id;
106}
107
108
95b0104a
JM
109static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
110{
111 struct wpa_supplicant *wpa_s = eloop_ctx;
112 struct dpp_authentication *auth = wpa_s->dpp_auth;
113
114 if (!auth || !auth->resp_msg)
115 return;
116
117 wpa_printf(MSG_DEBUG,
118 "DPP: Retry Authentication Response after timeout");
119 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
120 " freq=%u type=%d",
121 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
122 DPP_PA_AUTHENTICATION_RESP);
123 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
124 wpa_s->own_addr, broadcast,
125 wpabuf_head(auth->resp_msg),
126 wpabuf_len(auth->resp_msg),
127 500, wpas_dpp_tx_status, 0);
128}
129
130
131static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
132{
133 struct dpp_authentication *auth = wpa_s->dpp_auth;
134 unsigned int wait_time, max_tries;
135
136 if (!auth || !auth->resp_msg)
137 return;
138
139 if (wpa_s->dpp_resp_max_tries)
140 max_tries = wpa_s->dpp_resp_max_tries;
141 else
142 max_tries = 5;
143 auth->auth_resp_tries++;
144 if (auth->auth_resp_tries >= max_tries) {
145 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
146 offchannel_send_action_done(wpa_s);
147 dpp_auth_deinit(wpa_s->dpp_auth);
148 wpa_s->dpp_auth = NULL;
149 return;
150 }
151
152 if (wpa_s->dpp_resp_retry_time)
153 wait_time = wpa_s->dpp_resp_retry_time;
154 else
ed2c493e 155 wait_time = 1000;
95b0104a
JM
156 wpa_printf(MSG_DEBUG,
157 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
158 wait_time);
159 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
160 eloop_register_timeout(wait_time / 1000,
161 (wait_time % 1000) * 1000,
162 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
163}
164
165
22f90b32
JM
166static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
167{
168 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
16ef233b
JM
169 wpa_s->suitable_network = 0;
170 wpa_s->no_suitable_network = 0;
22f90b32
JM
171 wpa_s->disconnected = 0;
172 wpa_s->reassociate = 1;
173 wpa_s->scan_runs = 0;
174 wpa_s->normal_scans = 0;
175 wpa_supplicant_cancel_sched_scan(wpa_s);
176 wpa_supplicant_req_scan(wpa_s, 0, 0);
177}
178
179
16ef233b
JM
180#ifdef CONFIG_DPP2
181
182static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
183 void *timeout_ctx)
184{
185 struct wpa_supplicant *wpa_s = eloop_ctx;
186 struct dpp_authentication *auth = wpa_s->dpp_auth;
187 enum dpp_status_error result;
188
189 if (!auth || !auth->conn_status_requested)
190 return;
191
192 wpa_printf(MSG_DEBUG,
193 "DPP: Connection timeout - report Connection Status Result");
194 if (wpa_s->suitable_network)
195 result = DPP_STATUS_AUTH_FAILURE;
196 else if (wpa_s->no_suitable_network)
197 result = DPP_STATUS_NO_AP;
198 else
199 result = 255; /* What to report here for unexpected state? */
200 wpas_dpp_send_conn_status_result(wpa_s, result);
201}
202
203
204static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
205{
206 char *str, *end, *pos;
207 size_t len;
208 unsigned int i;
209 u8 last_op_class = 0;
210 int res;
211
212 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
213 return NULL;
214
215 len = wpa_s->num_last_scan_freqs * 8;
216 str = os_zalloc(len);
217 if (!str)
218 return NULL;
219 end = str + len;
220 pos = str;
221
222 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
223 enum hostapd_hw_mode mode;
224 u8 op_class, channel;
225
226 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
227 0, 0, &op_class, &channel);
228 if (mode == NUM_HOSTAPD_MODES)
229 continue;
230 if (op_class == last_op_class)
231 res = os_snprintf(pos, end - pos, ",%d", channel);
232 else
233 res = os_snprintf(pos, end - pos, "%s%d/%d",
234 pos == str ? "" : ",",
235 op_class, channel);
236 if (os_snprintf_error(end - pos, res)) {
237 *pos = '\0';
238 break;
239 }
240 pos += res;
241 last_op_class = op_class;
242 }
243
244 if (pos == str) {
245 os_free(str);
246 str = NULL;
247 }
248 return str;
249}
250
251
252void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
253 enum dpp_status_error result)
254{
255 struct wpabuf *msg;
256 const char *channel_list = NULL;
257 char *channel_list_buf = NULL;
258 struct wpa_ssid *ssid = wpa_s->current_ssid;
259 struct dpp_authentication *auth = wpa_s->dpp_auth;
260
261 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
262
263 if (!auth || !auth->conn_status_requested)
264 return;
265 auth->conn_status_requested = 0;
266 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
267 result);
268
269 if (result == DPP_STATUS_NO_AP) {
270 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
271 channel_list = channel_list_buf;
272 }
273
274 msg = dpp_build_conn_status_result(auth, result,
275 ssid ? ssid->ssid :
276 wpa_s->dpp_last_ssid,
277 ssid ? ssid->ssid_len :
278 wpa_s->dpp_last_ssid_len,
279 channel_list);
280 os_free(channel_list_buf);
281 if (!msg) {
282 dpp_auth_deinit(wpa_s->dpp_auth);
283 wpa_s->dpp_auth = NULL;
284 return;
285 }
286
287 wpa_msg(wpa_s, MSG_INFO,
288 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
289 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
290 DPP_PA_CONNECTION_STATUS_RESULT);
291 offchannel_send_action(wpa_s, auth->curr_freq,
292 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
293 wpabuf_head(msg), wpabuf_len(msg),
294 500, wpas_dpp_tx_status, 0);
295 wpabuf_free(msg);
296
297 /* This exchange will be terminated in the TX status handler */
298 auth->remove_on_tx_status = 1;
299
300 return;
301}
302
303
304void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
305{
306 struct dpp_authentication *auth = wpa_s->dpp_auth;
307
308 if (auth && auth->conn_status_requested)
309 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
310}
311
312#endif /* CONFIG_DPP2 */
313
314
30d27b04
JM
315static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
316 unsigned int freq, const u8 *dst,
317 const u8 *src, const u8 *bssid,
318 const u8 *data, size_t data_len,
319 enum offchannel_send_action_result result)
320{
af48810b 321 const char *res_txt;
f97ace34 322 struct dpp_authentication *auth = wpa_s->dpp_auth;
af48810b
JM
323
324 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
325 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
326 "FAILED");
30d27b04 327 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
af48810b
JM
328 " result=%s", freq, MAC2STR(dst), res_txt);
329 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
330 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
30d27b04
JM
331
332 if (!wpa_s->dpp_auth) {
333 wpa_printf(MSG_DEBUG,
334 "DPP: Ignore TX status since there is no ongoing authentication exchange");
335 return;
336 }
337
22f90b32
JM
338#ifdef CONFIG_DPP2
339 if (auth->connect_on_tx_status) {
16ef233b 340 auth->connect_on_tx_status = 0;
22f90b32
JM
341 wpa_printf(MSG_DEBUG,
342 "DPP: Try to connect after completed configuration result");
343 wpas_dpp_try_to_connect(wpa_s);
16ef233b
JM
344 if (auth->conn_status_requested) {
345 wpa_printf(MSG_DEBUG,
346 "DPP: Start 15 second timeout for reporting connection status result");
347 eloop_cancel_timeout(
348 wpas_dpp_conn_status_result_timeout,
349 wpa_s, NULL);
350 eloop_register_timeout(
351 15, 0, wpas_dpp_conn_status_result_timeout,
352 wpa_s, NULL);
353 } else {
354 dpp_auth_deinit(wpa_s->dpp_auth);
355 wpa_s->dpp_auth = NULL;
356 }
22f90b32
JM
357 return;
358 }
359#endif /* CONFIG_DPP2 */
360
30d27b04
JM
361 if (wpa_s->dpp_auth->remove_on_tx_status) {
362 wpa_printf(MSG_DEBUG,
16ef233b 363 "DPP: Terminate authentication exchange due to a request to do so on TX status");
f97ace34 364 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
461d39af 365 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
95b0104a
JM
366 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
367 NULL);
461d39af 368 offchannel_send_action_done(wpa_s);
30d27b04
JM
369 dpp_auth_deinit(wpa_s->dpp_auth);
370 wpa_s->dpp_auth = NULL;
371 return;
372 }
373
461d39af
JM
374 if (wpa_s->dpp_auth_ok_on_ack)
375 wpas_dpp_auth_success(wpa_s, 1);
376
30d27b04
JM
377 if (!is_broadcast_ether_addr(dst) &&
378 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
379 wpa_printf(MSG_DEBUG,
380 "DPP: Unicast DPP Action frame was not ACKed");
f97ace34
JM
381 if (auth->waiting_auth_resp) {
382 /* In case of DPP Authentication Request frame, move to
383 * the next channel immediately. */
384 offchannel_send_action_done(wpa_s);
385 wpas_dpp_auth_init_next(wpa_s);
386 return;
387 }
95b0104a
JM
388 if (auth->waiting_auth_conf) {
389 wpas_dpp_auth_resp_retry(wpa_s);
390 return;
391 }
30d27b04 392 }
d2709206 393
248264c6
JM
394 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
395 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
396 /* Allow timeout handling to stop iteration if no response is
397 * received from a peer that has ACKed a request. */
398 auth->auth_req_ack = 1;
399 }
400
d2709206
JM
401 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
402 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
403 wpa_printf(MSG_DEBUG,
404 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
405 wpa_s->dpp_auth->curr_freq,
406 wpa_s->dpp_auth->neg_freq);
407 offchannel_send_action_done(wpa_s);
408 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
409 }
d3cb7ebe
JM
410
411 if (wpa_s->dpp_auth_ok_on_ack)
412 wpa_s->dpp_auth_ok_on_ack = 0;
30d27b04
JM
413}
414
415
416static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
417{
418 struct wpa_supplicant *wpa_s = eloop_ctx;
248264c6 419 struct dpp_authentication *auth = wpa_s->dpp_auth;
d2709206 420 unsigned int freq;
0db637ca
JM
421 struct os_reltime now, diff;
422 unsigned int wait_time, diff_ms;
30d27b04 423
0db637ca 424 if (!auth || !auth->waiting_auth_resp)
30d27b04 425 return;
f97ace34 426
0db637ca
JM
427 wait_time = wpa_s->dpp_resp_wait_time ?
428 wpa_s->dpp_resp_wait_time : 2000;
429 os_get_reltime(&now);
430 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
431 diff_ms = diff.sec * 1000 + diff.usec / 1000;
432 wpa_printf(MSG_DEBUG,
433 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
434 wait_time, diff_ms);
435
436 if (auth->auth_req_ack && diff_ms >= wait_time) {
437 /* Peer ACK'ed Authentication Request frame, but did not reply
438 * with Authentication Response frame within two seconds. */
248264c6
JM
439 wpa_printf(MSG_INFO,
440 "DPP: No response received from responder - stopping initiation attempt");
441 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
442 offchannel_send_action_done(wpa_s);
0db637ca 443 wpas_dpp_listen_stop(wpa_s);
248264c6
JM
444 dpp_auth_deinit(auth);
445 wpa_s->dpp_auth = NULL;
446 return;
447 }
448
0db637ca
JM
449 if (diff_ms >= wait_time) {
450 /* Authentication Request frame was not ACK'ed and no reply
451 * was receiving within two seconds. */
452 wpa_printf(MSG_DEBUG,
453 "DPP: Continue Initiator channel iteration");
454 offchannel_send_action_done(wpa_s);
455 wpas_dpp_listen_stop(wpa_s);
456 wpas_dpp_auth_init_next(wpa_s);
457 return;
f97ace34
JM
458 }
459
0db637ca
JM
460 /* Driver did not support 2000 ms long wait_time with TX command, so
461 * schedule listen operation to continue waiting for the response.
462 *
463 * DPP listen operations continue until stopped, so simply schedule a
464 * new call to this function at the point when the two second reply
465 * wait has expired. */
466 wait_time -= diff_ms;
467
248264c6
JM
468 freq = auth->curr_freq;
469 if (auth->neg_freq > 0)
470 freq = auth->neg_freq;
0db637ca
JM
471 wpa_printf(MSG_DEBUG,
472 "DPP: Continue reply wait on channel %u MHz for %u ms",
473 freq, wait_time);
474 wpa_s->dpp_in_response_listen = 1;
d2709206 475 wpas_dpp_listen_start(wpa_s, freq);
0db637ca
JM
476
477 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
478 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
30d27b04
JM
479}
480
481
461d39af
JM
482static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
483 struct dpp_authentication *auth)
484{
485#ifdef CONFIG_TESTING_OPTIONS
486 if (wpa_s->dpp_config_obj_override)
487 auth->config_obj_override =
488 os_strdup(wpa_s->dpp_config_obj_override);
489 if (wpa_s->dpp_discovery_override)
490 auth->discovery_override =
491 os_strdup(wpa_s->dpp_discovery_override);
492 if (wpa_s->dpp_groups_override)
493 auth->groups_override =
494 os_strdup(wpa_s->dpp_groups_override);
461d39af
JM
495 auth->ignore_netaccesskey_mismatch =
496 wpa_s->dpp_ignore_netaccesskey_mismatch;
497#endif /* CONFIG_TESTING_OPTIONS */
498}
499
500
f97ace34
JM
501static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
502{
503 struct wpa_supplicant *wpa_s = eloop_ctx;
504
505 if (!wpa_s->dpp_auth)
506 return;
507 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
508 wpas_dpp_auth_init_next(wpa_s);
509}
510
511
512static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
513{
514 struct dpp_authentication *auth = wpa_s->dpp_auth;
515 const u8 *dst;
0db637ca 516 unsigned int wait_time, max_wait_time, freq, max_tries, used;
921f5acd 517 struct os_reltime now, diff;
f97ace34 518
0db637ca 519 wpa_s->dpp_in_response_listen = 0;
f97ace34
JM
520 if (!auth)
521 return -1;
0db637ca
JM
522
523 if (auth->freq_idx == 0)
524 os_get_reltime(&wpa_s->dpp_init_iter_start);
525
f97ace34
JM
526 if (auth->freq_idx >= auth->num_freq) {
527 auth->num_freq_iters++;
528 if (wpa_s->dpp_init_max_tries)
529 max_tries = wpa_s->dpp_init_max_tries;
530 else
531 max_tries = 5;
248264c6 532 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
f97ace34
JM
533 wpa_printf(MSG_INFO,
534 "DPP: No response received from responder - stopping initiation attempt");
535 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
536 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
537 wpa_s, NULL);
538 offchannel_send_action_done(wpa_s);
539 dpp_auth_deinit(wpa_s->dpp_auth);
540 wpa_s->dpp_auth = NULL;
541 return -1;
542 }
543 auth->freq_idx = 0;
544 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
545 if (wpa_s->dpp_init_retry_time)
546 wait_time = wpa_s->dpp_init_retry_time;
547 else
548 wait_time = 10000;
921f5acd 549 os_get_reltime(&now);
0db637ca 550 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
921f5acd
JM
551 used = diff.sec * 1000 + diff.usec / 1000;
552 if (used > wait_time)
553 wait_time = 0;
554 else
555 wait_time -= used;
556 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
557 wait_time);
f97ace34
JM
558 eloop_register_timeout(wait_time / 1000,
559 (wait_time % 1000) * 1000,
560 wpas_dpp_init_timeout, wpa_s,
561 NULL);
562 return 0;
563 }
564 freq = auth->freq[auth->freq_idx++];
565 auth->curr_freq = freq;
566
567 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
568 dst = broadcast;
569 else
570 dst = auth->peer_bi->mac_addr;
571 wpa_s->dpp_auth_ok_on_ack = 0;
572 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
573 wait_time = wpa_s->max_remain_on_chan;
0db637ca
JM
574 max_wait_time = wpa_s->dpp_resp_wait_time ?
575 wpa_s->dpp_resp_wait_time : 2000;
576 if (wait_time > max_wait_time)
577 wait_time = max_wait_time;
578 wait_time += 10; /* give the driver some extra time to complete */
f97ace34
JM
579 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
580 wpas_dpp_reply_wait_timeout,
581 wpa_s, NULL);
0db637ca 582 wait_time -= 10;
f97ace34
JM
583 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
584 wpa_printf(MSG_DEBUG,
585 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
586 freq, auth->neg_freq);
587 }
588 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
589 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
248264c6 590 auth->auth_req_ack = 0;
f97ace34
JM
591 os_get_reltime(&wpa_s->dpp_last_init);
592 return offchannel_send_action(wpa_s, freq, dst,
593 wpa_s->own_addr, broadcast,
594 wpabuf_head(auth->req_msg),
595 wpabuf_len(auth->req_msg),
596 wait_time, wpas_dpp_tx_status, 0);
597}
598
599
b65b22d6
JM
600int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
601{
602 const char *pos;
603 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
2a5a0680 604 struct dpp_authentication *auth;
d1f08264 605 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
d2709206 606 unsigned int neg_freq = 0;
2a5a0680
JM
607 int tcp = 0;
608#ifdef CONFIG_DPP2
609 int tcp_port = DPP_TCP_PORT;
610 struct hostapd_ip_addr ipaddr;
611 char *addr;
612#endif /* CONFIG_DPP2 */
b65b22d6
JM
613
614 wpa_s->dpp_gas_client = 0;
615
616 pos = os_strstr(cmd, " peer=");
617 if (!pos)
618 return -1;
619 pos += 6;
87d8435c 620 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
b65b22d6
JM
621 if (!peer_bi) {
622 wpa_printf(MSG_INFO,
623 "DPP: Could not find bootstrapping info for the identified peer");
624 return -1;
625 }
626
2a5a0680
JM
627#ifdef CONFIG_DPP2
628 pos = os_strstr(cmd, " tcp_port=");
629 if (pos) {
630 pos += 10;
631 tcp_port = atoi(pos);
632 }
633
634 addr = get_param(cmd, " tcp_addr=");
635 if (addr) {
636 int res;
637
638 res = hostapd_parse_ip_addr(addr, &ipaddr);
639 os_free(addr);
640 if (res)
641 return -1;
642 tcp = 1;
643 }
644#endif /* CONFIG_DPP2 */
645
b65b22d6
JM
646 pos = os_strstr(cmd, " own=");
647 if (pos) {
648 pos += 5;
87d8435c 649 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
b65b22d6
JM
650 if (!own_bi) {
651 wpa_printf(MSG_INFO,
652 "DPP: Could not find bootstrapping info for the identified local entry");
653 return -1;
654 }
655
656 if (peer_bi->curve != own_bi->curve) {
657 wpa_printf(MSG_INFO,
658 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
659 peer_bi->curve->name, own_bi->curve->name);
660 return -1;
661 }
662 }
663
664 pos = os_strstr(cmd, " role=");
665 if (pos) {
666 pos += 6;
667 if (os_strncmp(pos, "configurator", 12) == 0)
d1f08264 668 allowed_roles = DPP_CAPAB_CONFIGURATOR;
b65b22d6 669 else if (os_strncmp(pos, "enrollee", 8) == 0)
d1f08264
JM
670 allowed_roles = DPP_CAPAB_ENROLLEE;
671 else if (os_strncmp(pos, "either", 6) == 0)
672 allowed_roles = DPP_CAPAB_CONFIGURATOR |
673 DPP_CAPAB_ENROLLEE;
b65b22d6
JM
674 else
675 goto fail;
676 }
677
678 pos = os_strstr(cmd, " netrole=");
679 if (pos) {
680 pos += 9;
681 wpa_s->dpp_netrole_ap = os_strncmp(pos, "ap", 2) == 0;
682 }
30d27b04 683
d2709206
JM
684 pos = os_strstr(cmd, " neg_freq=");
685 if (pos)
686 neg_freq = atoi(pos + 10);
687
2a5a0680 688 if (!tcp && wpa_s->dpp_auth) {
f97ace34 689 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
30d27b04 690 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
95b0104a
JM
691 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
692 NULL);
30d27b04
JM
693 offchannel_send_action_done(wpa_s);
694 dpp_auth_deinit(wpa_s->dpp_auth);
2a5a0680 695 wpa_s->dpp_auth = NULL;
30d27b04 696 }
2a5a0680
JM
697
698 auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles, neg_freq,
699 wpa_s->hw.modes, wpa_s->hw.num_modes);
700 if (!auth)
461d39af 701 goto fail;
2a5a0680
JM
702 wpas_dpp_set_testing_options(wpa_s, auth);
703 if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) < 0) {
704 dpp_auth_deinit(auth);
a00d65e7
JM
705 goto fail;
706 }
30d27b04 707
2a5a0680 708 auth->neg_freq = neg_freq;
30d27b04 709
f97ace34 710 if (!is_zero_ether_addr(peer_bi->mac_addr))
2a5a0680
JM
711 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
712
713#ifdef CONFIG_DPP2
714 if (tcp)
715 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port);
716#endif /* CONFIG_DPP2 */
f97ace34 717
2a5a0680 718 wpa_s->dpp_auth = auth;
f97ace34 719 return wpas_dpp_auth_init_next(wpa_s);
461d39af 720fail:
461d39af 721 return -1;
30d27b04
JM
722}
723
724
725struct wpas_dpp_listen_work {
726 unsigned int freq;
727 unsigned int duration;
728 struct wpabuf *probe_resp_ie;
729};
730
731
732static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
733{
734 if (!lwork)
735 return;
736 os_free(lwork);
737}
738
739
740static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
741{
742 struct wpas_dpp_listen_work *lwork;
743
744 if (!wpa_s->dpp_listen_work)
745 return;
746
747 lwork = wpa_s->dpp_listen_work->ctx;
748 wpas_dpp_listen_work_free(lwork);
749 radio_work_done(wpa_s->dpp_listen_work);
750 wpa_s->dpp_listen_work = NULL;
751}
752
753
754static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
755{
756 struct wpa_supplicant *wpa_s = work->wpa_s;
757 struct wpas_dpp_listen_work *lwork = work->ctx;
758
759 if (deinit) {
760 if (work->started) {
761 wpa_s->dpp_listen_work = NULL;
762 wpas_dpp_listen_stop(wpa_s);
763 }
764 wpas_dpp_listen_work_free(lwork);
765 return;
766 }
767
768 wpa_s->dpp_listen_work = work;
769
770 wpa_s->dpp_pending_listen_freq = lwork->freq;
771
772 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
773 wpa_s->max_remain_on_chan) < 0) {
774 wpa_printf(MSG_DEBUG,
775 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
776 lwork->freq);
d8c20ec5 777 wpa_s->dpp_listen_freq = 0;
30d27b04
JM
778 wpas_dpp_listen_work_done(wpa_s);
779 wpa_s->dpp_pending_listen_freq = 0;
780 return;
781 }
782 wpa_s->off_channel_freq = 0;
783 wpa_s->roc_waiting_drv_freq = lwork->freq;
784}
785
786
787static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
788 unsigned int freq)
789{
790 struct wpas_dpp_listen_work *lwork;
791
792 if (wpa_s->dpp_listen_work) {
793 wpa_printf(MSG_DEBUG,
794 "DPP: Reject start_listen since dpp_listen_work already exists");
795 return -1;
796 }
797
798 if (wpa_s->dpp_listen_freq)
799 wpas_dpp_listen_stop(wpa_s);
800 wpa_s->dpp_listen_freq = freq;
801
802 lwork = os_zalloc(sizeof(*lwork));
803 if (!lwork)
804 return -1;
805 lwork->freq = freq;
806
807 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
808 lwork) < 0) {
809 wpas_dpp_listen_work_free(lwork);
810 return -1;
811 }
812
813 return 0;
814}
815
816
817int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
818{
819 int freq;
820
821 freq = atoi(cmd);
822 if (freq <= 0)
823 return -1;
824
825 if (os_strstr(cmd, " role=configurator"))
826 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
827 else if (os_strstr(cmd, " role=enrollee"))
828 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
829 else
830 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
831 DPP_CAPAB_ENROLLEE;
832 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
461d39af 833 wpa_s->dpp_netrole_ap = os_strstr(cmd, " netrole=ap") != NULL;
30d27b04
JM
834 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
835 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
836 freq);
837 return 0;
838 }
839
840 return wpas_dpp_listen_start(wpa_s, freq);
841}
842
843
844void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
845{
0db637ca 846 wpa_s->dpp_in_response_listen = 0;
30d27b04
JM
847 if (!wpa_s->dpp_listen_freq)
848 return;
849
850 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
851 wpa_s->dpp_listen_freq);
852 wpa_drv_cancel_remain_on_channel(wpa_s);
853 wpa_s->dpp_listen_freq = 0;
854 wpas_dpp_listen_work_done(wpa_s);
855}
856
857
30d27b04
JM
858void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
859 unsigned int freq)
860{
861 wpas_dpp_listen_work_done(wpa_s);
862
0db637ca
JM
863 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
864 unsigned int new_freq;
865
30d27b04 866 /* Continue listen with a new remain-on-channel */
0db637ca
JM
867 if (wpa_s->dpp_auth->neg_freq > 0)
868 new_freq = wpa_s->dpp_auth->neg_freq;
869 else
870 new_freq = wpa_s->dpp_auth->curr_freq;
30d27b04
JM
871 wpa_printf(MSG_DEBUG,
872 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
0db637ca
JM
873 new_freq);
874 wpas_dpp_listen_start(wpa_s, new_freq);
30d27b04
JM
875 return;
876 }
877
878 if (wpa_s->dpp_listen_freq) {
879 /* Continue listen with a new remain-on-channel */
880 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
881 }
882}
883
884
885static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
dc4d271c
JM
886 const u8 *hdr, const u8 *buf, size_t len,
887 unsigned int freq)
30d27b04 888{
27fefbbb
JM
889 const u8 *r_bootstrap, *i_bootstrap;
890 u16 r_bootstrap_len, i_bootstrap_len;
87d8435c
JM
891 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
892
893 if (!wpa_s->dpp)
894 return;
30d27b04
JM
895
896 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
897 MAC2STR(src));
898
30d27b04
JM
899 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
900 &r_bootstrap_len);
27fefbbb 901 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
26806abe
JM
902 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
903 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
30d27b04
JM
904 return;
905 }
906 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
907 r_bootstrap, r_bootstrap_len);
908
909 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
910 &i_bootstrap_len);
27fefbbb 911 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
26806abe
JM
912 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
913 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
30d27b04
JM
914 return;
915 }
916 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
917 i_bootstrap, i_bootstrap_len);
918
919 /* Try to find own and peer bootstrapping key matches based on the
920 * received hash values */
87d8435c
JM
921 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
922 &own_bi, &peer_bi);
30d27b04 923 if (!own_bi) {
26806abe
JM
924 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
925 "No matching own bootstrapping key found - ignore message");
30d27b04
JM
926 return;
927 }
928
929 if (wpa_s->dpp_auth) {
26806abe
JM
930 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
931 "Already in DPP authentication exchange - ignore new one");
30d27b04
JM
932 return;
933 }
934
461d39af
JM
935 wpa_s->dpp_gas_client = 0;
936 wpa_s->dpp_auth_ok_on_ack = 0;
30d27b04
JM
937 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles,
938 wpa_s->dpp_qr_mutual,
27fefbbb 939 peer_bi, own_bi, freq, hdr, buf, len);
30d27b04
JM
940 if (!wpa_s->dpp_auth) {
941 wpa_printf(MSG_DEBUG, "DPP: No response generated");
942 return;
943 }
461d39af 944 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
87d8435c
JM
945 if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth,
946 wpa_s->dpp_configurator_params) < 0) {
a00d65e7
JM
947 dpp_auth_deinit(wpa_s->dpp_auth);
948 wpa_s->dpp_auth = NULL;
949 return;
950 }
30d27b04
JM
951 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
952
d2709206
JM
953 if (wpa_s->dpp_listen_freq &&
954 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
955 wpa_printf(MSG_DEBUG,
956 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
957 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
958 wpas_dpp_listen_stop(wpa_s);
959 }
960
af48810b
JM
961 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
962 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
963 DPP_PA_AUTHENTICATION_RESP);
30d27b04
JM
964 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
965 src, wpa_s->own_addr, broadcast,
dc4d271c
JM
966 wpabuf_head(wpa_s->dpp_auth->resp_msg),
967 wpabuf_len(wpa_s->dpp_auth->resp_msg),
30d27b04 968 500, wpas_dpp_tx_status, 0);
30d27b04
JM
969}
970
971
461d39af
JM
972static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
973{
974 /* TODO: stop wait and start ROC */
975}
976
977
8528994e 978static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
52d469de
JM
979 struct dpp_authentication *auth,
980 struct dpp_config_obj *conf)
8528994e
JM
981{
982 struct wpa_ssid *ssid;
983
22f90b32 984#ifdef CONFIG_DPP2
52d469de 985 if (conf->akm == DPP_AKM_SAE) {
22f90b32
JM
986#ifdef CONFIG_SAE
987 struct wpa_driver_capa capa;
988 int res;
989
990 res = wpa_drv_get_capa(wpa_s, &capa);
991 if (res == 0 &&
992 !(capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
993 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
994 wpa_printf(MSG_DEBUG,
995 "DPP: SAE not supported by the driver");
996 return NULL;
997 }
998#else /* CONFIG_SAE */
999 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1000 return NULL;
1001#endif /* CONFIG_SAE */
1002 }
1003#endif /* CONFIG_DPP2 */
1004
8528994e
JM
1005 ssid = wpa_config_add_network(wpa_s->conf);
1006 if (!ssid)
1007 return NULL;
1008 wpas_notify_network_added(wpa_s, ssid);
1009 wpa_config_set_network_defaults(ssid);
1010 ssid->disabled = 1;
1011
52d469de 1012 ssid->ssid = os_malloc(conf->ssid_len);
8528994e
JM
1013 if (!ssid->ssid)
1014 goto fail;
52d469de
JM
1015 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1016 ssid->ssid_len = conf->ssid_len;
8528994e 1017
52d469de 1018 if (conf->connector) {
8528994e 1019 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
70e19013 1020 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
52d469de 1021 ssid->dpp_connector = os_strdup(conf->connector);
8528994e
JM
1022 if (!ssid->dpp_connector)
1023 goto fail;
1024 }
1025
52d469de
JM
1026 if (conf->c_sign_key) {
1027 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
8528994e
JM
1028 if (!ssid->dpp_csign)
1029 goto fail;
52d469de
JM
1030 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1031 wpabuf_len(conf->c_sign_key));
1032 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
8528994e
JM
1033 }
1034
1035 if (auth->net_access_key) {
1036 ssid->dpp_netaccesskey =
1037 os_malloc(wpabuf_len(auth->net_access_key));
1038 if (!ssid->dpp_netaccesskey)
1039 goto fail;
1040 os_memcpy(ssid->dpp_netaccesskey,
1041 wpabuf_head(auth->net_access_key),
1042 wpabuf_len(auth->net_access_key));
1043 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1044 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1045 }
1046
52d469de
JM
1047 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1048 dpp_akm_sae(conf->akm)) {
1049 if (!conf->connector)
18015fc8 1050 ssid->key_mgmt = 0;
52d469de 1051 if (dpp_akm_psk(conf->akm))
5dd745b7
JM
1052 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1053 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
52d469de 1054 if (dpp_akm_sae(conf->akm))
5dd745b7
JM
1055 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1056 WPA_KEY_MGMT_FT_SAE;
70e19013 1057 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
52d469de 1058 if (conf->passphrase[0]) {
8528994e 1059 if (wpa_config_set_quoted(ssid, "psk",
52d469de 1060 conf->passphrase) < 0)
8528994e
JM
1061 goto fail;
1062 wpa_config_update_psk(ssid);
1063 ssid->export_keys = 1;
1064 } else {
52d469de
JM
1065 ssid->psk_set = conf->psk_set;
1066 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
8528994e
JM
1067 }
1068 }
1069
52d469de
JM
1070 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1071 wpa_s->dpp_last_ssid_len = conf->ssid_len;
16ef233b 1072
8528994e
JM
1073 return ssid;
1074fail:
1075 wpas_notify_network_removed(wpa_s, ssid);
1076 wpa_config_remove_network(wpa_s->conf, ssid->id);
1077 return NULL;
1078}
1079
1080
22f90b32 1081static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
52d469de
JM
1082 struct dpp_authentication *auth,
1083 struct dpp_config_obj *conf)
8528994e
JM
1084{
1085 struct wpa_ssid *ssid;
1086
1087 if (wpa_s->conf->dpp_config_processing < 1)
22f90b32 1088 return 0;
8528994e 1089
52d469de 1090 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
8528994e 1091 if (!ssid)
22f90b32 1092 return -1;
8528994e
JM
1093
1094 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
954c535a
JM
1095 if (wpa_s->conf->dpp_config_processing == 2)
1096 ssid->disabled = 0;
1097
1098#ifndef CONFIG_NO_CONFIG_WRITE
1099 if (wpa_s->conf->update_config &&
1100 wpa_config_write(wpa_s->confname, wpa_s->conf))
1101 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1102#endif /* CONFIG_NO_CONFIG_WRITE */
1103
52d469de
JM
1104 return 0;
1105}
1106
1107
1108static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1109 struct dpp_authentication *auth)
1110{
8528994e 1111 if (wpa_s->conf->dpp_config_processing < 2)
52d469de 1112 return;
8528994e 1113
22f90b32
JM
1114#ifdef CONFIG_DPP2
1115 if (auth->peer_version >= 2) {
1116 wpa_printf(MSG_DEBUG,
1117 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1118 auth->connect_on_tx_status = 1;
52d469de 1119 return;
22f90b32
JM
1120 }
1121#endif /* CONFIG_DPP2 */
1122
1123 wpas_dpp_try_to_connect(wpa_s);
8528994e
JM
1124}
1125
1126
22f90b32 1127static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
52d469de
JM
1128 struct dpp_authentication *auth,
1129 struct dpp_config_obj *conf)
461d39af 1130{
461d39af 1131 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
52d469de 1132 if (conf->ssid_len)
461d39af 1133 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
52d469de 1134 wpa_ssid_txt(conf->ssid, conf->ssid_len));
181bf933
JM
1135 if (conf->ssid_charset)
1136 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1137 conf->ssid_charset);
52d469de 1138 if (conf->connector) {
461d39af
JM
1139 /* TODO: Save the Connector and consider using a command
1140 * to fetch the value instead of sending an event with
1141 * it. The Connector could end up being larger than what
1142 * most clients are ready to receive as an event
1143 * message. */
1144 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
52d469de 1145 conf->connector);
461d39af 1146 }
52d469de 1147 if (conf->c_sign_key) {
461d39af
JM
1148 char *hex;
1149 size_t hexlen;
1150
52d469de 1151 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
461d39af
JM
1152 hex = os_malloc(hexlen);
1153 if (hex) {
1154 wpa_snprintf_hex(hex, hexlen,
52d469de
JM
1155 wpabuf_head(conf->c_sign_key),
1156 wpabuf_len(conf->c_sign_key));
c77e2ff0
JM
1157 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1158 hex);
461d39af
JM
1159 os_free(hex);
1160 }
1161 }
1162 if (auth->net_access_key) {
1163 char *hex;
1164 size_t hexlen;
1165
1166 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1167 hex = os_malloc(hexlen);
1168 if (hex) {
1169 wpa_snprintf_hex(hex, hexlen,
1170 wpabuf_head(auth->net_access_key),
1171 wpabuf_len(auth->net_access_key));
1172 if (auth->net_access_key_expiry)
1173 wpa_msg(wpa_s, MSG_INFO,
1174 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1175 (long unsigned)
1176 auth->net_access_key_expiry);
1177 else
1178 wpa_msg(wpa_s, MSG_INFO,
1179 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1180 os_free(hex);
1181 }
1182 }
8528994e 1183
52d469de 1184 return wpas_dpp_process_config(wpa_s, auth, conf);
f522bb23
JM
1185}
1186
1187
1188static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1189 enum gas_query_result result,
1190 const struct wpabuf *adv_proto,
1191 const struct wpabuf *resp, u16 status_code)
1192{
1193 struct wpa_supplicant *wpa_s = ctx;
1194 const u8 *pos;
1195 struct dpp_authentication *auth = wpa_s->dpp_auth;
22f90b32
JM
1196 int res;
1197 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
52d469de 1198 unsigned int i;
f522bb23 1199
1866dfb5
JM
1200 wpa_s->dpp_gas_dialog_token = -1;
1201
f522bb23
JM
1202 if (!auth || !auth->auth_success) {
1203 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1204 return;
1205 }
931f7ff6
JM
1206 if (result != GAS_QUERY_SUCCESS ||
1207 !resp || status_code != WLAN_STATUS_SUCCESS) {
f522bb23
JM
1208 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1209 goto fail;
1210 }
1211
1212 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1213 adv_proto);
1214 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1215 resp);
1216
1217 if (wpabuf_len(adv_proto) != 10 ||
1218 !(pos = wpabuf_head(adv_proto)) ||
1219 pos[0] != WLAN_EID_ADV_PROTO ||
1220 pos[1] != 8 ||
1221 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1222 pos[4] != 5 ||
1223 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1224 pos[8] != 0x1a ||
1225 pos[9] != 1) {
1226 wpa_printf(MSG_DEBUG,
1227 "DPP: Not a DPP Advertisement Protocol ID");
1228 goto fail;
1229 }
8528994e 1230
f522bb23
JM
1231 if (dpp_conf_resp_rx(auth, resp) < 0) {
1232 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1233 goto fail;
1234 }
1235
52d469de
JM
1236 for (i = 0; i < auth->num_conf_obj; i++) {
1237 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1238 &auth->conf_obj[i]);
1239 if (res < 0)
1240 goto fail;
1241 }
1242 if (auth->num_conf_obj)
1243 wpas_dpp_post_process_config(wpa_s, auth);
461d39af 1244
22f90b32 1245 status = DPP_STATUS_OK;
67b3bcc9
JM
1246#ifdef CONFIG_TESTING_OPTIONS
1247 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1248 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1249 status = DPP_STATUS_CONFIG_REJECTED;
1250 }
1251#endif /* CONFIG_TESTING_OPTIONS */
461d39af 1252fail:
22f90b32
JM
1253 if (status != DPP_STATUS_OK)
1254 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1255#ifdef CONFIG_DPP2
1256 if (auth->peer_version >= 2 &&
1257 auth->conf_resp_status == DPP_STATUS_OK) {
1258 struct wpabuf *msg;
1259
1260 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1261 msg = dpp_build_conf_result(auth, status);
1262 if (!msg)
1263 goto fail2;
1264
1265 wpa_msg(wpa_s, MSG_INFO,
1266 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1267 MAC2STR(addr), auth->curr_freq,
1268 DPP_PA_CONFIGURATION_RESULT);
1269 offchannel_send_action(wpa_s, auth->curr_freq,
1270 addr, wpa_s->own_addr, broadcast,
1271 wpabuf_head(msg),
1272 wpabuf_len(msg),
1273 500, wpas_dpp_tx_status, 0);
1274 wpabuf_free(msg);
1275
1276 /* This exchange will be terminated in the TX status handler */
1277 return;
1278 }
1279fail2:
1280#endif /* CONFIG_DPP2 */
461d39af
JM
1281 dpp_auth_deinit(wpa_s->dpp_auth);
1282 wpa_s->dpp_auth = NULL;
1283}
1284
1285
1286static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1287{
1288 struct dpp_authentication *auth = wpa_s->dpp_auth;
bd23daa8 1289 struct wpabuf *buf;
461d39af 1290 int res;
8f8c423a 1291 int *supp_op_classes;
461d39af
JM
1292
1293 wpa_s->dpp_gas_client = 1;
461d39af
JM
1294 offchannel_send_action_done(wpa_s);
1295 wpas_dpp_listen_stop(wpa_s);
1296
8f8c423a 1297 supp_op_classes = wpas_supp_op_classes(wpa_s);
5a5639b0
JM
1298 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
1299 wpa_s->dpp_netrole_ap,
8f8c423a
JM
1300 wpa_s->conf->dpp_mud_url,
1301 supp_op_classes);
1302 os_free(supp_op_classes);
bd23daa8 1303 if (!buf) {
461d39af
JM
1304 wpa_printf(MSG_DEBUG,
1305 "DPP: No configuration request data available");
1306 return;
1307 }
1308
461d39af
JM
1309 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1310 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1311
1312 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
aca4d84e 1313 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
461d39af
JM
1314 if (res < 0) {
1315 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1316 wpabuf_free(buf);
1317 } else {
1318 wpa_printf(MSG_DEBUG,
1319 "DPP: GAS query started with dialog token %u", res);
1866dfb5 1320 wpa_s->dpp_gas_dialog_token = res;
461d39af
JM
1321 }
1322}
1323
1324
1325static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1326{
1327 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1328 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
d74963d4
SD
1329#ifdef CONFIG_TESTING_OPTIONS
1330 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1331 wpa_printf(MSG_INFO,
1332 "DPP: TESTING - stop at Authentication Confirm");
1333 if (wpa_s->dpp_auth->configurator) {
1334 /* Prevent GAS response */
1335 wpa_s->dpp_auth->auth_success = 0;
1336 }
1337 return;
1338 }
1339#endif /* CONFIG_TESTING_OPTIONS */
461d39af
JM
1340
1341 if (wpa_s->dpp_auth->configurator)
1342 wpas_dpp_start_gas_server(wpa_s);
1343 else
1344 wpas_dpp_start_gas_client(wpa_s);
1345}
1346
1347
30d27b04 1348static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
d2709206
JM
1349 const u8 *hdr, const u8 *buf, size_t len,
1350 unsigned int freq)
30d27b04
JM
1351{
1352 struct dpp_authentication *auth = wpa_s->dpp_auth;
dc4d271c 1353 struct wpabuf *msg;
30d27b04 1354
d2709206
JM
1355 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1356 " (freq %u MHz)", MAC2STR(src), freq);
30d27b04
JM
1357
1358 if (!auth) {
1359 wpa_printf(MSG_DEBUG,
1360 "DPP: No DPP Authentication in progress - drop");
1361 return;
1362 }
1363
1364 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1365 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1366 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1367 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1368 return;
1369 }
1370
1371 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1372
d2709206
JM
1373 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1374 wpa_printf(MSG_DEBUG,
1375 "DPP: Responder accepted request for different negotiation channel");
1376 auth->curr_freq = freq;
1377 }
1378
f97ace34 1379 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
dc4d271c
JM
1380 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1381 if (!msg) {
30d27b04
JM
1382 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1383 wpa_printf(MSG_DEBUG,
1384 "DPP: Start wait for full response");
1385 offchannel_send_action_done(wpa_s);
1386 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1387 return;
1388 }
1389 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1390 return;
1391 }
1392 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1393
af48810b
JM
1394 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1395 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
30d27b04
JM
1396 offchannel_send_action(wpa_s, auth->curr_freq,
1397 src, wpa_s->own_addr, broadcast,
1398 wpabuf_head(msg), wpabuf_len(msg),
1399 500, wpas_dpp_tx_status, 0);
1400 wpabuf_free(msg);
461d39af 1401 wpa_s->dpp_auth_ok_on_ack = 1;
30d27b04
JM
1402}
1403
1404
1405static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
dc4d271c 1406 const u8 *hdr, const u8 *buf, size_t len)
30d27b04
JM
1407{
1408 struct dpp_authentication *auth = wpa_s->dpp_auth;
1409
1410 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1411 MAC2STR(src));
1412
1413 if (!auth) {
1414 wpa_printf(MSG_DEBUG,
1415 "DPP: No DPP Authentication in progress - drop");
1416 return;
1417 }
1418
1419 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1420 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1421 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1422 return;
1423 }
1424
dc4d271c 1425 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
30d27b04
JM
1426 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1427 return;
1428 }
1429
461d39af 1430 wpas_dpp_auth_success(wpa_s, 0);
30d27b04
JM
1431}
1432
1433
22f90b32
JM
1434#ifdef CONFIG_DPP2
1435
1436static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
1437 void *timeout_ctx)
1438{
1439 struct wpa_supplicant *wpa_s = eloop_ctx;
1440 struct dpp_authentication *auth = wpa_s->dpp_auth;
1441
1442 if (!auth || !auth->waiting_conf_result)
1443 return;
1444
1445 wpa_printf(MSG_DEBUG,
1446 "DPP: Timeout while waiting for Configuration Result");
1447 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1448 dpp_auth_deinit(auth);
1449 wpa_s->dpp_auth = NULL;
1450}
1451
1452
b10e01a7
JM
1453static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1454 void *timeout_ctx)
1455{
1456 struct wpa_supplicant *wpa_s = eloop_ctx;
1457 struct dpp_authentication *auth = wpa_s->dpp_auth;
1458
1459 if (!auth || !auth->waiting_conn_status_result)
1460 return;
1461
1462 wpa_printf(MSG_DEBUG,
1463 "DPP: Timeout while waiting for Connection Status Result");
1464 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
1465 wpas_dpp_listen_stop(wpa_s);
1466 dpp_auth_deinit(auth);
1467 wpa_s->dpp_auth = NULL;
1468}
1469
1470
22f90b32
JM
1471static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
1472 const u8 *hdr, const u8 *buf, size_t len)
1473{
1474 struct dpp_authentication *auth = wpa_s->dpp_auth;
1475 enum dpp_status_error status;
1476
1477 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1478 MAC2STR(src));
1479
1480 if (!auth || !auth->waiting_conf_result) {
1481 wpa_printf(MSG_DEBUG,
1482 "DPP: No DPP Configuration waiting for result - drop");
1483 return;
1484 }
1485
1486 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1487 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1488 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1489 return;
1490 }
1491
1492 status = dpp_conf_result_rx(auth, hdr, buf, len);
1493
b10e01a7
JM
1494 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1495 wpa_msg(wpa_s, MSG_INFO,
1496 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1497 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1498 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
1499 wpa_s, NULL);
1500 auth->waiting_conn_status_result = 1;
1501 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1502 wpa_s, NULL);
1503 eloop_register_timeout(16, 0,
1504 wpas_dpp_conn_status_result_wait_timeout,
1505 wpa_s, NULL);
1506 offchannel_send_action_done(wpa_s);
1507 wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq :
1508 auth->curr_freq);
1509 return;
1510 }
22f90b32
JM
1511 offchannel_send_action_done(wpa_s);
1512 wpas_dpp_listen_stop(wpa_s);
1513 if (status == DPP_STATUS_OK)
1514 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
1515 else
1516 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1517 dpp_auth_deinit(auth);
1518 wpa_s->dpp_auth = NULL;
1519 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
1520}
1521
2a5a0680 1522
b10e01a7
JM
1523static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
1524 const u8 *src, const u8 *hdr,
1525 const u8 *buf, size_t len)
1526{
1527 struct dpp_authentication *auth = wpa_s->dpp_auth;
1528 enum dpp_status_error status;
1529 u8 ssid[SSID_MAX_LEN];
1530 size_t ssid_len = 0;
1531 char *channel_list = NULL;
1532
1533 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1534
1535 if (!auth || !auth->waiting_conn_status_result) {
1536 wpa_printf(MSG_DEBUG,
1537 "DPP: No DPP Configuration waiting for connection status result - drop");
1538 return;
1539 }
1540
1541 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1542 ssid, &ssid_len, &channel_list);
1543 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1544 "result=%d ssid=%s channel_list=%s",
1545 status, wpa_ssid_txt(ssid, ssid_len),
1546 channel_list ? channel_list : "N/A");
1547 os_free(channel_list);
1548 offchannel_send_action_done(wpa_s);
1549 wpas_dpp_listen_stop(wpa_s);
1550 dpp_auth_deinit(auth);
1551 wpa_s->dpp_auth = NULL;
1552 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1553 wpa_s, NULL);
1554}
1555
1556
2a5a0680
JM
1557static int wpas_dpp_process_conf_obj(void *ctx,
1558 struct dpp_authentication *auth)
1559{
1560 struct wpa_supplicant *wpa_s = ctx;
52d469de
JM
1561 unsigned int i;
1562 int res = -1;
1563
1564 for (i = 0; i < auth->num_conf_obj; i++) {
1565 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1566 &auth->conf_obj[i]);
1567 if (res)
1568 break;
1569 }
1570 if (!res)
1571 wpas_dpp_post_process_config(wpa_s, auth);
2a5a0680 1572
52d469de 1573 return res;
2a5a0680
JM
1574}
1575
22f90b32
JM
1576#endif /* CONFIG_DPP2 */
1577
1578
a0d5c56f
JM
1579static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
1580 const u8 *src,
1581 const u8 *buf, size_t len)
1582{
1583 struct wpa_ssid *ssid;
e85b6601
JM
1584 const u8 *connector, *trans_id, *status;
1585 u16 connector_len, trans_id_len, status_len;
a0d5c56f
JM
1586 struct dpp_introduction intro;
1587 struct rsn_pmksa_cache_entry *entry;
787615b3
JM
1588 struct os_time now;
1589 struct os_reltime rnow;
1590 os_time_t expiry;
1591 unsigned int seconds;
e85b6601 1592 enum dpp_status_error res;
a0d5c56f
JM
1593
1594 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
1595 MAC2STR(src));
1596 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
1597 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
1598 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
1599 MACSTR " - drop", MAC2STR(src));
1600 return;
1601 }
1602 offchannel_send_action_done(wpa_s);
1603
1604 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1605 if (ssid == wpa_s->dpp_intro_network)
1606 break;
1607 }
1608 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
1609 !ssid->dpp_csign) {
1610 wpa_printf(MSG_DEBUG,
1611 "DPP: Profile not found for network introduction");
1612 return;
1613 }
1614
85fd8263
JM
1615 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1616 &trans_id_len);
1617 if (!trans_id || trans_id_len != 1) {
1618 wpa_printf(MSG_DEBUG,
1619 "DPP: Peer did not include Transaction ID");
e85b6601
JM
1620 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1621 " fail=missing_transaction_id", MAC2STR(src));
85fd8263
JM
1622 goto fail;
1623 }
1624 if (trans_id[0] != TRANSACTION_ID) {
1625 wpa_printf(MSG_DEBUG,
1626 "DPP: Ignore frame with unexpected Transaction ID %u",
1627 trans_id[0]);
e85b6601
JM
1628 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1629 " fail=transaction_id_mismatch", MAC2STR(src));
1630 goto fail;
1631 }
1632
1633 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
1634 if (!status || status_len != 1) {
1635 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
1636 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1637 " fail=missing_status", MAC2STR(src));
1638 goto fail;
1639 }
1640 if (status[0] != DPP_STATUS_OK) {
1641 wpa_printf(MSG_DEBUG,
1642 "DPP: Peer rejected network introduction: Status %u",
1643 status[0]);
1644 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1645 " status=%u", MAC2STR(src), status[0]);
16ef233b
JM
1646#ifdef CONFIG_DPP2
1647 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
1648#endif /* CONFIG_DPP2 */
85fd8263
JM
1649 goto fail;
1650 }
1651
a0d5c56f
JM
1652 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1653 if (!connector) {
1654 wpa_printf(MSG_DEBUG,
1655 "DPP: Peer did not include its Connector");
e85b6601
JM
1656 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1657 " fail=missing_connector", MAC2STR(src));
1658 goto fail;
a0d5c56f
JM
1659 }
1660
e85b6601
JM
1661 res = dpp_peer_intro(&intro, ssid->dpp_connector,
1662 ssid->dpp_netaccesskey,
1663 ssid->dpp_netaccesskey_len,
1664 ssid->dpp_csign,
1665 ssid->dpp_csign_len,
1666 connector, connector_len, &expiry);
1667 if (res != DPP_STATUS_OK) {
a0d5c56f
JM
1668 wpa_printf(MSG_INFO,
1669 "DPP: Network Introduction protocol resulted in failure");
e85b6601
JM
1670 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1671 " fail=peer_connector_validation_failed", MAC2STR(src));
16ef233b
JM
1672#ifdef CONFIG_DPP2
1673 wpas_dpp_send_conn_status_result(wpa_s, res);
1674#endif /* CONFIG_DPP2 */
a0d5c56f
JM
1675 goto fail;
1676 }
1677
a0d5c56f
JM
1678 entry = os_zalloc(sizeof(*entry));
1679 if (!entry)
1680 goto fail;
1681 os_memcpy(entry->aa, src, ETH_ALEN);
1682 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
1683 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
1684 entry->pmk_len = intro.pmk_len;
1685 entry->akmp = WPA_KEY_MGMT_DPP;
787615b3
JM
1686 if (expiry) {
1687 os_get_time(&now);
1688 seconds = expiry - now.sec;
1689 } else {
1690 seconds = 86400 * 7;
1691 }
1692 os_get_reltime(&rnow);
1693 entry->expiration = rnow.sec + seconds;
1694 entry->reauth_time = rnow.sec + seconds;
a0d5c56f
JM
1695 entry->network_ctx = ssid;
1696 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
1697
e85b6601
JM
1698 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1699 " status=%u", MAC2STR(src), status[0]);
1700
a0d5c56f
JM
1701 wpa_printf(MSG_DEBUG,
1702 "DPP: Try connection again after successful network introduction");
1703 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
1704 wpa_supplicant_cancel_sched_scan(wpa_s);
1705 wpa_supplicant_req_scan(wpa_s, 0, 0);
1706 }
1707fail:
1708 os_memset(&intro, 0, sizeof(intro));
1709}
1710
1711
3b50f8a4
JM
1712static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
1713{
1714 int i, j;
1715
1716 if (!wpa_s->hw.modes)
1717 return -1;
1718
1719 for (i = 0; i < wpa_s->hw.num_modes; i++) {
1720 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
1721
1722 for (j = 0; j < mode->num_channels; j++) {
1723 struct hostapd_channel_data *chan = &mode->channels[j];
1724
1725 if (chan->freq != (int) freq)
1726 continue;
1727
1728 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
1729 HOSTAPD_CHAN_NO_IR |
1730 HOSTAPD_CHAN_RADAR))
1731 continue;
1732
1733 return 1;
1734 }
1735 }
1736
1737 wpa_printf(MSG_DEBUG,
1738 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
1739 freq);
1740
1741 return 0;
1742}
1743
1744
1745static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
1746 struct dpp_pkex *pkex)
1747{
1748 if (pkex->freq == 2437)
1749 pkex->freq = 5745;
1750 else if (pkex->freq == 5745)
1751 pkex->freq = 5220;
1752 else if (pkex->freq == 5220)
1753 pkex->freq = 60480;
1754 else
1755 return -1; /* no more channels to try */
1756
1757 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
1758 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
1759 pkex->freq);
1760 return 0;
1761 }
1762
1763 /* Could not use this channel - try the next one */
1764 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
1765}
1766
1767
00d2d13d
JM
1768static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
1769{
1770 struct wpa_supplicant *wpa_s = eloop_ctx;
1771 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1772
1773 if (!pkex || !pkex->exchange_req)
1774 return;
1775 if (pkex->exch_req_tries >= 5) {
3b50f8a4
JM
1776 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
1777 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1778 "No response from PKEX peer");
1779 dpp_pkex_free(pkex);
1780 wpa_s->dpp_pkex = NULL;
1781 return;
1782 }
1783 pkex->exch_req_tries = 0;
00d2d13d
JM
1784 }
1785
1786 pkex->exch_req_tries++;
1787 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
1788 pkex->exch_req_tries);
1789 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1790 MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
1791 offchannel_send_action(wpa_s, pkex->freq, broadcast,
1792 wpa_s->own_addr, broadcast,
1793 wpabuf_head(pkex->exchange_req),
1794 wpabuf_len(pkex->exchange_req),
1795 pkex->exch_req_wait_time,
1796 wpas_dpp_tx_pkex_status, 0);
1797}
1798
1799
500ed7f0
JM
1800static void
1801wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
1802 unsigned int freq, const u8 *dst,
1803 const u8 *src, const u8 *bssid,
1804 const u8 *data, size_t data_len,
1805 enum offchannel_send_action_result result)
1806{
af48810b 1807 const char *res_txt;
00d2d13d 1808 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
af48810b
JM
1809
1810 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
1811 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
1812 "FAILED");
500ed7f0
JM
1813 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
1814 " result=%s (PKEX)",
af48810b
JM
1815 freq, MAC2STR(dst), res_txt);
1816 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
1817 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
e0247e79 1818
00d2d13d 1819 if (!pkex) {
e0247e79
JM
1820 wpa_printf(MSG_DEBUG,
1821 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
1822 return;
1823 }
1824
00d2d13d 1825 if (pkex->failed) {
e0247e79
JM
1826 wpa_printf(MSG_DEBUG,
1827 "DPP: Terminate PKEX exchange due to an earlier error");
00d2d13d
JM
1828 if (pkex->t > pkex->own_bi->pkex_t)
1829 pkex->own_bi->pkex_t = pkex->t;
1830 dpp_pkex_free(pkex);
e0247e79 1831 wpa_s->dpp_pkex = NULL;
00d2d13d
JM
1832 return;
1833 }
1834
1835 if (pkex->exch_req_wait_time && pkex->exchange_req) {
1836 /* Wait for PKEX Exchange Response frame and retry request if
1837 * no response is seen. */
1838 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1839 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
1840 (pkex->exch_req_wait_time % 1000) * 1000,
1841 wpas_dpp_pkex_retry_timeout, wpa_s,
1842 NULL);
e0247e79 1843 }
500ed7f0
JM
1844}
1845
1846
1847static void
1848wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
1849 const u8 *buf, size_t len, unsigned int freq)
1850{
1851 struct wpabuf *msg;
1852 unsigned int wait_time;
1853
1854 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1855 MAC2STR(src));
1856
1857 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1858 * values here */
1859
1860 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
1861 wpa_printf(MSG_DEBUG,
1862 "DPP: No PKEX code configured - ignore request");
1863 return;
1864 }
1865
1866 if (wpa_s->dpp_pkex) {
1867 /* TODO: Support parallel operations */
1868 wpa_printf(MSG_DEBUG,
1869 "DPP: Already in PKEX session - ignore new request");
1870 return;
1871 }
1872
219d4c9f 1873 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
500ed7f0
JM
1874 wpa_s->own_addr, src,
1875 wpa_s->dpp_pkex_identifier,
1876 wpa_s->dpp_pkex_code,
1877 buf, len);
1878 if (!wpa_s->dpp_pkex) {
1879 wpa_printf(MSG_DEBUG,
1880 "DPP: Failed to process the request - ignore it");
1881 return;
1882 }
1883
1884 msg = wpa_s->dpp_pkex->exchange_resp;
1885 wait_time = wpa_s->max_remain_on_chan;
1886 if (wait_time > 2000)
1887 wait_time = 2000;
af48810b
JM
1888 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1889 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
500ed7f0
JM
1890 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1891 broadcast,
1892 wpabuf_head(msg), wpabuf_len(msg),
1893 wait_time, wpas_dpp_tx_pkex_status, 0);
1894}
1895
1896
1897static void
1898wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
1899 const u8 *buf, size_t len, unsigned int freq)
1900{
1901 struct wpabuf *msg;
1902 unsigned int wait_time;
1903
1904 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1905 MAC2STR(src));
1906
1907 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1908 * values here */
1909
1910 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
1911 wpa_s->dpp_pkex->exchange_done) {
1912 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1913 return;
1914 }
1915
00d2d13d
JM
1916 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1917 wpa_s->dpp_pkex->exch_req_wait_time = 0;
1918
af4103e5 1919 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
500ed7f0
JM
1920 if (!msg) {
1921 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1922 return;
1923 }
1924
1925 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1926 MAC2STR(src));
1927
1928 wait_time = wpa_s->max_remain_on_chan;
1929 if (wait_time > 2000)
1930 wait_time = 2000;
af48810b
JM
1931 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1932 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
500ed7f0
JM
1933 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1934 broadcast,
1935 wpabuf_head(msg), wpabuf_len(msg),
1936 wait_time, wpas_dpp_tx_pkex_status, 0);
1937 wpabuf_free(msg);
1938}
1939
1940
de029861
JM
1941static struct dpp_bootstrap_info *
1942wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
1943 unsigned int freq)
1944{
de029861
JM
1945 struct dpp_bootstrap_info *bi;
1946
87d8435c 1947 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
de029861
JM
1948 if (!bi)
1949 return NULL;
de029861 1950 wpa_s->dpp_pkex = NULL;
de029861
JM
1951 return bi;
1952}
1953
1954
500ed7f0
JM
1955static void
1956wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
4be5bc98
JM
1957 const u8 *hdr, const u8 *buf, size_t len,
1958 unsigned int freq)
500ed7f0
JM
1959{
1960 struct wpabuf *msg;
1961 unsigned int wait_time;
1962 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
500ed7f0
JM
1963
1964 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1965 MAC2STR(src));
1966
1967 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1968 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1969 return;
1970 }
1971
4be5bc98 1972 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
500ed7f0
JM
1973 if (!msg) {
1974 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
039b8e73
JM
1975 if (pkex->failed) {
1976 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
29ab69e4
JM
1977 if (pkex->t > pkex->own_bi->pkex_t)
1978 pkex->own_bi->pkex_t = pkex->t;
039b8e73
JM
1979 dpp_pkex_free(wpa_s->dpp_pkex);
1980 wpa_s->dpp_pkex = NULL;
1981 }
500ed7f0
JM
1982 return;
1983 }
1984
1985 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1986 MACSTR, MAC2STR(src));
1987
1988 wait_time = wpa_s->max_remain_on_chan;
1989 if (wait_time > 2000)
1990 wait_time = 2000;
af48810b
JM
1991 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1992 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
500ed7f0
JM
1993 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1994 broadcast,
1995 wpabuf_head(msg), wpabuf_len(msg),
1996 wait_time, wpas_dpp_tx_pkex_status, 0);
1997 wpabuf_free(msg);
1998
de029861 1999 wpas_dpp_pkex_finish(wpa_s, src, freq);
500ed7f0
JM
2000}
2001
2002
2003static void
2004wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
4be5bc98 2005 const u8 *hdr, const u8 *buf, size_t len,
500ed7f0
JM
2006 unsigned int freq)
2007{
2008 int res;
de029861 2009 struct dpp_bootstrap_info *bi;
500ed7f0
JM
2010 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2011 char cmd[500];
2012
2013 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2014 MAC2STR(src));
2015
2016 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2017 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2018 return;
2019 }
2020
4be5bc98 2021 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
500ed7f0
JM
2022 if (res < 0) {
2023 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2024 return;
2025 }
2026
de029861 2027 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
500ed7f0
JM
2028 if (!bi)
2029 return;
500ed7f0
JM
2030
2031 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2032 bi->id,
2033 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
2034 wpa_printf(MSG_DEBUG,
2035 "DPP: Start authentication after PKEX with parameters: %s",
2036 cmd);
2037 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
2038 wpa_printf(MSG_DEBUG,
2039 "DPP: Authentication initialization failed");
2040 return;
2041 }
2042}
2043
2044
30d27b04
JM
2045void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
2046 const u8 *buf, size_t len, unsigned int freq)
2047{
8c19ea3f 2048 u8 crypto_suite;
30d27b04 2049 enum dpp_public_action_frame_type type;
dc4d271c 2050 const u8 *hdr;
29ab69e4 2051 unsigned int pkex_t;
30d27b04 2052
dc4d271c
JM
2053 if (len < DPP_HDR_LEN)
2054 return;
2055 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
30d27b04 2056 return;
dc4d271c
JM
2057 hdr = buf;
2058 buf += 4;
2059 len -= 4;
8c19ea3f
JM
2060 crypto_suite = *buf++;
2061 type = *buf++;
2062 len -= 2;
30d27b04
JM
2063
2064 wpa_printf(MSG_DEBUG,
8c19ea3f 2065 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
30d27b04 2066 MACSTR " freq=%u",
8c19ea3f
JM
2067 crypto_suite, type, MAC2STR(src), freq);
2068 if (crypto_suite != 1) {
2069 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2070 crypto_suite);
a7073934
JM
2071 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2072 " freq=%u type=%d ignore=unsupported-crypto-suite",
2073 MAC2STR(src), freq, type);
8c19ea3f
JM
2074 return;
2075 }
30d27b04 2076 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
a7073934
JM
2077 if (dpp_check_attrs(buf, len) < 0) {
2078 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2079 " freq=%u type=%d ignore=invalid-attributes",
2080 MAC2STR(src), freq, type);
30d27b04 2081 return;
a7073934
JM
2082 }
2083 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
2084 MAC2STR(src), freq, type);
30d27b04
JM
2085
2086 switch (type) {
2087 case DPP_PA_AUTHENTICATION_REQ:
dc4d271c 2088 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
30d27b04
JM
2089 break;
2090 case DPP_PA_AUTHENTICATION_RESP:
d2709206 2091 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
30d27b04
JM
2092 break;
2093 case DPP_PA_AUTHENTICATION_CONF:
dc4d271c 2094 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
30d27b04 2095 break;
a0d5c56f
JM
2096 case DPP_PA_PEER_DISCOVERY_RESP:
2097 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
2098 break;
500ed7f0
JM
2099 case DPP_PA_PKEX_EXCHANGE_REQ:
2100 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
2101 break;
2102 case DPP_PA_PKEX_EXCHANGE_RESP:
2103 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
2104 break;
2105 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
4be5bc98
JM
2106 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
2107 freq);
500ed7f0
JM
2108 break;
2109 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
4be5bc98
JM
2110 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
2111 freq);
500ed7f0 2112 break;
22f90b32
JM
2113#ifdef CONFIG_DPP2
2114 case DPP_PA_CONFIGURATION_RESULT:
2115 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
2116 break;
b10e01a7
JM
2117 case DPP_PA_CONNECTION_STATUS_RESULT:
2118 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
2119 break;
22f90b32 2120#endif /* CONFIG_DPP2 */
30d27b04
JM
2121 default:
2122 wpa_printf(MSG_DEBUG,
2123 "DPP: Ignored unsupported frame subtype %d", type);
2124 break;
2125 }
29ab69e4
JM
2126
2127 if (wpa_s->dpp_pkex)
2128 pkex_t = wpa_s->dpp_pkex->t;
2129 else if (wpa_s->dpp_pkex_bi)
2130 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
2131 else
2132 pkex_t = 0;
2133 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2134 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2135 wpas_dpp_pkex_remove(wpa_s, "*");
2136 }
30d27b04
JM
2137}
2138
2139
461d39af
JM
2140static struct wpabuf *
2141wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query,
2142 size_t query_len)
2143{
2144 struct wpa_supplicant *wpa_s = ctx;
2145 struct dpp_authentication *auth = wpa_s->dpp_auth;
2146 struct wpabuf *resp;
2147
2148 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
2149 MAC2STR(sa));
2150 if (!auth || !auth->auth_success ||
2151 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
2152 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2153 return NULL;
2154 }
422e73d6
JM
2155
2156 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
2157 wpa_printf(MSG_DEBUG,
2158 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
2159 /* wpas_dpp_auth_success() would normally have been called from
2160 * TX status handler, but since there was no such handler call
2161 * yet, simply send out the event message and proceed with
2162 * exchange. */
2163 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
2164 wpa_s->dpp_auth_ok_on_ack = 0;
2165 }
2166
461d39af
JM
2167 wpa_hexdump(MSG_DEBUG,
2168 "DPP: Received Configuration Request (GAS Query Request)",
2169 query, query_len);
fd920954
JM
2170 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2171 MAC2STR(sa));
461d39af
JM
2172 resp = dpp_conf_req_rx(auth, query, query_len);
2173 if (!resp)
2174 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
82feacce 2175 auth->conf_resp = resp;
461d39af
JM
2176 return resp;
2177}
2178
2179
2180static void
2181wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
2182{
2183 struct wpa_supplicant *wpa_s = ctx;
2184 struct dpp_authentication *auth = wpa_s->dpp_auth;
2185
2186 if (!auth) {
2187 wpabuf_free(resp);
2188 return;
2189 }
82feacce
JM
2190 if (auth->conf_resp != resp) {
2191 wpa_printf(MSG_DEBUG,
2192 "DPP: Ignore GAS status report (ok=%d) for unknown response",
2193 ok);
2194 wpabuf_free(resp);
2195 return;
2196 }
461d39af
JM
2197
2198 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2199 ok);
2200 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
95b0104a 2201 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
22f90b32
JM
2202#ifdef CONFIG_DPP2
2203 if (ok && auth->peer_version >= 2 &&
2204 auth->conf_resp_status == DPP_STATUS_OK) {
2205 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
2206 auth->waiting_conf_result = 1;
2207 auth->conf_resp = NULL;
2208 wpabuf_free(resp);
2209 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2210 wpa_s, NULL);
2211 eloop_register_timeout(2, 0,
2212 wpas_dpp_config_result_wait_timeout,
2213 wpa_s, NULL);
2214 return;
2215 }
2216#endif /* CONFIG_DPP2 */
461d39af
JM
2217 offchannel_send_action_done(wpa_s);
2218 wpas_dpp_listen_stop(wpa_s);
2219 if (ok)
2220 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
2221 else
2222 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
2223 dpp_auth_deinit(wpa_s->dpp_auth);
2224 wpa_s->dpp_auth = NULL;
2225 wpabuf_free(resp);
2226}
2227
2228
f522bb23
JM
2229int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
2230{
2231 struct dpp_authentication *auth;
2232 int ret = -1;
2233 char *curve = NULL;
2234
2235 auth = os_zalloc(sizeof(*auth));
2236 if (!auth)
2237 return -1;
2238
2239 curve = get_param(cmd, " curve=");
e22c2338 2240 wpas_dpp_set_testing_options(wpa_s, auth);
87d8435c 2241 if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 &&
22f90b32 2242 dpp_configurator_own_config(auth, curve, 0) == 0)
52d469de
JM
2243 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
2244 &auth->conf_obj[0]);
2245 if (!ret)
2246 wpas_dpp_post_process_config(wpa_s, auth);
f522bb23
JM
2247
2248 dpp_auth_deinit(auth);
2249 os_free(curve);
2250
2251 return ret;
2252}
2253
2254
a0d5c56f
JM
2255static void
2256wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
2257 unsigned int freq, const u8 *dst,
2258 const u8 *src, const u8 *bssid,
2259 const u8 *data, size_t data_len,
2260 enum offchannel_send_action_result result)
2261{
af48810b
JM
2262 const char *res_txt;
2263
2264 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2265 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2266 "FAILED");
a0d5c56f
JM
2267 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2268 " result=%s (DPP Peer Discovery Request)",
af48810b
JM
2269 freq, MAC2STR(dst), res_txt);
2270 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2271 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
a0d5c56f
JM
2272 /* TODO: Time out wait for response more quickly in error cases? */
2273}
2274
2275
2276int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2277 struct wpa_bss *bss)
2278{
2279 struct os_time now;
2280 struct wpabuf *msg;
2281 unsigned int wait_time;
dd6c5980
JM
2282 const u8 *rsn;
2283 struct wpa_ie_data ied;
a0d5c56f
JM
2284
2285 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
2286 return 0; /* Not using DPP AKM - continue */
dd6c5980
JM
2287 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2288 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
2289 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
2290 return 0; /* AP does not support DPP AKM - continue */
a0d5c56f
JM
2291 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
2292 return 0; /* PMKSA exists for DPP AKM - continue */
2293
2294 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2295 !ssid->dpp_csign) {
2296 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2297 "missing %s",
2298 !ssid->dpp_connector ? "Connector" :
2299 (!ssid->dpp_netaccesskey ? "netAccessKey" :
2300 "C-sign-key"));
2301 return -1;
2302 }
2303
2304 os_get_time(&now);
2305
a0d5c56f 2306 if (ssid->dpp_netaccesskey_expiry &&
3ca4be1e 2307 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
a0d5c56f
JM
2308 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2309 "netAccessKey expired");
2310 return -1;
2311 }
2312
2313 wpa_printf(MSG_DEBUG,
2314 "DPP: Starting network introduction protocol to derive PMKSA for "
2315 MACSTR, MAC2STR(bss->bssid));
2316
2317 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ,
85fd8263 2318 5 + 4 + os_strlen(ssid->dpp_connector));
a0d5c56f
JM
2319 if (!msg)
2320 return -1;
2321
a306ed5a
JM
2322#ifdef CONFIG_TESTING_OPTIONS
2323 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
2324 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
2325 goto skip_trans_id;
2326 }
55c6c858
JM
2327 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
2328 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
2329 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2330 wpabuf_put_le16(msg, 0);
2331 goto skip_trans_id;
2332 }
a306ed5a
JM
2333#endif /* CONFIG_TESTING_OPTIONS */
2334
85fd8263
JM
2335 /* Transaction ID */
2336 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2337 wpabuf_put_le16(msg, 1);
2338 wpabuf_put_u8(msg, TRANSACTION_ID);
2339
a306ed5a
JM
2340#ifdef CONFIG_TESTING_OPTIONS
2341skip_trans_id:
2342 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
2343 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
2344 goto skip_connector;
2345 }
4b8de0c9
JM
2346 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
2347 char *connector;
2348
2349 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
2350 connector = dpp_corrupt_connector_signature(
2351 ssid->dpp_connector);
2352 if (!connector) {
2353 wpabuf_free(msg);
2354 return -1;
2355 }
2356 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2357 wpabuf_put_le16(msg, os_strlen(connector));
2358 wpabuf_put_str(msg, connector);
2359 os_free(connector);
2360 goto skip_connector;
2361 }
a306ed5a
JM
2362#endif /* CONFIG_TESTING_OPTIONS */
2363
a0d5c56f
JM
2364 /* DPP Connector */
2365 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2366 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
2367 wpabuf_put_str(msg, ssid->dpp_connector);
2368
a306ed5a
JM
2369#ifdef CONFIG_TESTING_OPTIONS
2370skip_connector:
2371#endif /* CONFIG_TESTING_OPTIONS */
2372
a0d5c56f
JM
2373 /* TODO: Timeout on AP response */
2374 wait_time = wpa_s->max_remain_on_chan;
2375 if (wait_time > 2000)
2376 wait_time = 2000;
af48810b
JM
2377 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2378 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
a0d5c56f
JM
2379 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
2380 broadcast,
2381 wpabuf_head(msg), wpabuf_len(msg),
2382 wait_time, wpas_dpp_tx_introduction_status, 0);
2383 wpabuf_free(msg);
2384
2385 /* Request this connection attempt to terminate - new one will be
2386 * started when network introduction protocol completes */
2387 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
2388 wpa_s->dpp_intro_network = ssid;
2389 return 1;
2390}
2391
2392
500ed7f0
JM
2393int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
2394{
2395 struct dpp_bootstrap_info *own_bi;
2396 const char *pos, *end;
2397 unsigned int wait_time;
2398
2399 pos = os_strstr(cmd, " own=");
2400 if (!pos)
2401 return -1;
2402 pos += 5;
87d8435c 2403 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
500ed7f0
JM
2404 if (!own_bi) {
2405 wpa_printf(MSG_DEBUG,
2406 "DPP: Identified bootstrap info not found");
2407 return -1;
2408 }
2409 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2410 wpa_printf(MSG_DEBUG,
2411 "DPP: Identified bootstrap info not for PKEX");
2412 return -1;
2413 }
2414 wpa_s->dpp_pkex_bi = own_bi;
29ab69e4 2415 own_bi->pkex_t = 0; /* clear pending errors on new code */
500ed7f0
JM
2416
2417 os_free(wpa_s->dpp_pkex_identifier);
2418 wpa_s->dpp_pkex_identifier = NULL;
2419 pos = os_strstr(cmd, " identifier=");
2420 if (pos) {
2421 pos += 12;
2422 end = os_strchr(pos, ' ');
2423 if (!end)
2424 return -1;
2425 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
2426 if (!wpa_s->dpp_pkex_identifier)
2427 return -1;
2428 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
2429 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
2430 }
2431
2432 pos = os_strstr(cmd, " code=");
2433 if (!pos)
2434 return -1;
2435 os_free(wpa_s->dpp_pkex_code);
2436 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
2437 if (!wpa_s->dpp_pkex_code)
2438 return -1;
2439
2440 if (os_strstr(cmd, " init=1")) {
00d2d13d 2441 struct dpp_pkex *pkex;
500ed7f0
JM
2442 struct wpabuf *msg;
2443
2444 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
2445 dpp_pkex_free(wpa_s->dpp_pkex);
219d4c9f 2446 wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
500ed7f0
JM
2447 wpa_s->dpp_pkex_identifier,
2448 wpa_s->dpp_pkex_code);
00d2d13d
JM
2449 pkex = wpa_s->dpp_pkex;
2450 if (!pkex)
500ed7f0
JM
2451 return -1;
2452
00d2d13d 2453 msg = pkex->exchange_req;
500ed7f0
JM
2454 wait_time = wpa_s->max_remain_on_chan;
2455 if (wait_time > 2000)
2456 wait_time = 2000;
00d2d13d 2457 pkex->freq = 2437;
af48810b
JM
2458 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2459 " freq=%u type=%d",
00d2d13d
JM
2460 MAC2STR(broadcast), pkex->freq,
2461 DPP_PA_PKEX_EXCHANGE_REQ);
2462 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2463 wpa_s->own_addr, broadcast,
500ed7f0
JM
2464 wpabuf_head(msg), wpabuf_len(msg),
2465 wait_time, wpas_dpp_tx_pkex_status, 0);
00d2d13d
JM
2466 if (wait_time == 0)
2467 wait_time = 2000;
2468 pkex->exch_req_wait_time = wait_time;
2469 pkex->exch_req_tries = 1;
500ed7f0
JM
2470 }
2471
2472 /* TODO: Support multiple PKEX info entries */
2473
2474 os_free(wpa_s->dpp_pkex_auth_cmd);
2475 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
2476
2477 return 1;
2478}
2479
2480
2481int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
2482{
2483 unsigned int id_val;
2484
2485 if (os_strcmp(id, "*") == 0) {
2486 id_val = 0;
2487 } else {
2488 id_val = atoi(id);
2489 if (id_val == 0)
2490 return -1;
2491 }
2492
2493 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
2494 return -1;
2495
2496 /* TODO: Support multiple PKEX entries */
2497 os_free(wpa_s->dpp_pkex_code);
2498 wpa_s->dpp_pkex_code = NULL;
2499 os_free(wpa_s->dpp_pkex_identifier);
2500 wpa_s->dpp_pkex_identifier = NULL;
2501 os_free(wpa_s->dpp_pkex_auth_cmd);
2502 wpa_s->dpp_pkex_auth_cmd = NULL;
2503 wpa_s->dpp_pkex_bi = NULL;
2504 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2505 dpp_pkex_free(wpa_s->dpp_pkex);
2506 wpa_s->dpp_pkex = NULL;
2507 return 0;
2508}
2509
2510
c1d37739
JM
2511void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
2512{
2513 dpp_auth_deinit(wpa_s->dpp_auth);
2514 wpa_s->dpp_auth = NULL;
ed62d401
JM
2515 dpp_pkex_free(wpa_s->dpp_pkex);
2516 wpa_s->dpp_pkex = NULL;
1866dfb5
JM
2517 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
2518 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
c1d37739
JM
2519}
2520
2521
be27e185
JM
2522int wpas_dpp_init(struct wpa_supplicant *wpa_s)
2523{
2ed2b52f 2524 struct dpp_global_config config;
461d39af
JM
2525 u8 adv_proto_id[7];
2526
2527 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
2528 adv_proto_id[1] = 5;
2529 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
2530 adv_proto_id[5] = DPP_OUI_TYPE;
2531 adv_proto_id[6] = 0x01;
2532
2533 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
2534 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
2535 wpas_dpp_gas_status_handler, wpa_s) < 0)
2536 return -1;
2ed2b52f
JM
2537
2538 os_memset(&config, 0, sizeof(config));
2539 config.msg_ctx = wpa_s;
2a5a0680
JM
2540 config.cb_ctx = wpa_s;
2541#ifdef CONFIG_DPP2
2542 config.process_conf_obj = wpas_dpp_process_conf_obj;
2543#endif /* CONFIG_DPP2 */
2ed2b52f 2544 wpa_s->dpp = dpp_global_init(&config);
87d8435c 2545 return wpa_s->dpp ? 0 : -1;
be27e185
JM
2546}
2547
2548
2549void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
2550{
461d39af
JM
2551#ifdef CONFIG_TESTING_OPTIONS
2552 os_free(wpa_s->dpp_config_obj_override);
2553 wpa_s->dpp_config_obj_override = NULL;
2554 os_free(wpa_s->dpp_discovery_override);
2555 wpa_s->dpp_discovery_override = NULL;
2556 os_free(wpa_s->dpp_groups_override);
2557 wpa_s->dpp_groups_override = NULL;
461d39af
JM
2558 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
2559#endif /* CONFIG_TESTING_OPTIONS */
87d8435c 2560 if (!wpa_s->dpp)
be27e185 2561 return;
87d8435c 2562 dpp_global_clear(wpa_s->dpp);
00d2d13d 2563 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
30d27b04 2564 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
f97ace34 2565 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
95b0104a 2566 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
22f90b32
JM
2567#ifdef CONFIG_DPP2
2568 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
b10e01a7
JM
2569 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2570 wpa_s, NULL);
16ef233b 2571 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
10ec6a5f
JM
2572 dpp_pfs_free(wpa_s->dpp_pfs);
2573 wpa_s->dpp_pfs = NULL;
22f90b32 2574#endif /* CONFIG_DPP2 */
30d27b04
JM
2575 offchannel_send_action_done(wpa_s);
2576 wpas_dpp_listen_stop(wpa_s);
fa5c9074 2577 wpas_dpp_stop(wpa_s);
500ed7f0 2578 wpas_dpp_pkex_remove(wpa_s, "*");
a0d5c56f 2579 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
b65b22d6
JM
2580 os_free(wpa_s->dpp_configurator_params);
2581 wpa_s->dpp_configurator_params = NULL;
be27e185 2582}
c02dd10d
JM
2583
2584
2585#ifdef CONFIG_DPP2
2586int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
2587{
2588 struct dpp_controller_config config;
2589 const char *pos;
2590
2591 os_memset(&config, 0, sizeof(config));
2592 if (cmd) {
2593 pos = os_strstr(cmd, " tcp_port=");
2594 if (pos) {
2595 pos += 10;
2596 config.tcp_port = atoi(pos);
2597 }
2598 }
2599 config.configurator_params = wpa_s->dpp_configurator_params;
2600 return dpp_controller_start(wpa_s->dpp, &config);
2601}
2602#endif /* CONFIG_DPP2 */