blob: 55dcd7028f6af677153944415b7a415d6640ffa1 [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * wpa_supplicant - DPP
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
Hai Shalomfdcde762020-04-02 11:19:20 -07004 * Copyright (c) 2018-2020, The Linux Foundation
Hai Shaloma20dcd72022-02-04 13:43:00 -08005 * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "utils/includes.h"
12
13#include "utils/common.h"
14#include "utils/eloop.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070015#include "utils/ip_addr.h"
Hai Shalom899fcc72020-10-19 14:38:18 -070016#include "utils/base64.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070017#include "common/dpp.h"
18#include "common/gas.h"
19#include "common/gas_server.h"
Sunil Ravi89eba102022-09-13 21:04:37 -070020#include "crypto/random.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070021#include "rsn_supp/wpa.h"
22#include "rsn_supp/pmksa_cache.h"
23#include "wpa_supplicant_i.h"
24#include "config.h"
25#include "driver_i.h"
26#include "offchannel.h"
27#include "gas_query.h"
28#include "bss.h"
29#include "scan.h"
30#include "notify.h"
31#include "dpp_supplicant.h"
Gabriel Biren57ededa2021-09-03 16:08:50 +000032#include "aidl.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070033
34
35static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
36 unsigned int freq);
37static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom60840252021-02-19 19:02:11 -080038static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070039static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
40static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
41 unsigned int freq, const u8 *dst,
42 const u8 *src, const u8 *bssid,
43 const u8 *data, size_t data_len,
44 enum offchannel_send_action_result result);
Roshan Pius3a1667e2018-07-03 15:17:14 -070045static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
46static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
47static void
48wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
49 unsigned int freq, const u8 *dst,
50 const u8 *src, const u8 *bssid,
51 const u8 *data, size_t data_len,
52 enum offchannel_send_action_result result);
Hai Shaloma20dcd72022-02-04 13:43:00 -080053static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070054#ifdef CONFIG_DPP2
55static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
56 void *timeout_ctx);
Hai Shalom899fcc72020-10-19 14:38:18 -070057static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s);
58static int wpas_dpp_process_conf_obj(void *ctx,
59 struct dpp_authentication *auth);
Hai Shaloma20dcd72022-02-04 13:43:00 -080060static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070061#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070062
63static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
64
65/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
66 * a single transaction in progress at any point in time. */
67static const u8 TRANSACTION_ID = 1;
68
69
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070070/**
71 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
72 * @wpa_s: Pointer to wpa_supplicant data
73 * @cmd: DPP URI read from a QR Code
74 * Returns: Identifier of the stored info or -1 on failure
75 */
76int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
77{
78 struct dpp_bootstrap_info *bi;
79 struct dpp_authentication *auth = wpa_s->dpp_auth;
80
Hai Shalom021b0b52019-04-10 11:17:58 -070081 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070082 if (!bi)
83 return -1;
84
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070085 if (auth && auth->response_pending &&
86 dpp_notify_new_qr_code(auth, bi) == 1) {
87 wpa_printf(MSG_DEBUG,
88 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070089 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
90 " freq=%u type=%d",
91 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
92 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070093 offchannel_send_action(wpa_s, auth->curr_freq,
94 auth->peer_mac_addr, wpa_s->own_addr,
95 broadcast,
96 wpabuf_head(auth->resp_msg),
97 wpabuf_len(auth->resp_msg),
98 500, wpas_dpp_tx_status, 0);
99 }
100
Hai Shalom899fcc72020-10-19 14:38:18 -0700101#ifdef CONFIG_DPP2
102 dpp_controller_new_qr_code(wpa_s->dpp, bi);
103#endif /* CONFIG_DPP2 */
104
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700105 return bi->id;
106}
107
108
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800109/**
110 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
111 * @wpa_s: Pointer to wpa_supplicant data
112 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
113 * Returns: Identifier of the stored info or -1 on failure
114 */
115int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
116{
117 struct dpp_bootstrap_info *bi;
118
119 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
120 if (!bi)
121 return -1;
122
123 return bi->id;
124}
125
126
Hai Shalomfdcde762020-04-02 11:19:20 -0700127int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd)
128{
129 const char *pos;
130 struct dpp_bootstrap_info *peer_bi, *own_bi;
131
132 pos = os_strstr(cmd, " own=");
133 if (!pos)
134 return -1;
135 pos += 5;
136 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
137 if (!own_bi)
138 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700139 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700140
141 pos = os_strstr(cmd, " uri=");
142 if (!pos)
143 return -1;
144 pos += 5;
145 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
146 if (!peer_bi) {
147 wpa_printf(MSG_INFO,
148 "DPP: Failed to parse URI from NFC Handover Request");
149 return -1;
150 }
151
152 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
153 return -1;
154
155 return peer_bi->id;
156}
157
158
159int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd)
160{
161 const char *pos;
162 struct dpp_bootstrap_info *peer_bi, *own_bi;
163
164 pos = os_strstr(cmd, " own=");
165 if (!pos)
166 return -1;
167 pos += 5;
168 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
169 if (!own_bi)
170 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700171 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700172
173 pos = os_strstr(cmd, " uri=");
174 if (!pos)
175 return -1;
176 pos += 5;
177 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
178 if (!peer_bi) {
179 wpa_printf(MSG_INFO,
180 "DPP: Failed to parse URI from NFC Handover Select");
181 return -1;
182 }
183
184 if (peer_bi->curve != own_bi->curve) {
185 wpa_printf(MSG_INFO,
186 "DPP: Peer (NFC Handover Selector) used different curve");
187 return -1;
188 }
189
190 return peer_bi->id;
191}
192
193
Roshan Pius3a1667e2018-07-03 15:17:14 -0700194static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
195{
196 struct wpa_supplicant *wpa_s = eloop_ctx;
197 struct dpp_authentication *auth = wpa_s->dpp_auth;
198
199 if (!auth || !auth->resp_msg)
200 return;
201
202 wpa_printf(MSG_DEBUG,
203 "DPP: Retry Authentication Response after timeout");
204 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
205 " freq=%u type=%d",
206 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
207 DPP_PA_AUTHENTICATION_RESP);
208 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
209 wpa_s->own_addr, broadcast,
210 wpabuf_head(auth->resp_msg),
211 wpabuf_len(auth->resp_msg),
212 500, wpas_dpp_tx_status, 0);
213}
214
215
216static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
217{
218 struct dpp_authentication *auth = wpa_s->dpp_auth;
219 unsigned int wait_time, max_tries;
220
221 if (!auth || !auth->resp_msg)
222 return;
223
224 if (wpa_s->dpp_resp_max_tries)
225 max_tries = wpa_s->dpp_resp_max_tries;
226 else
227 max_tries = 5;
228 auth->auth_resp_tries++;
229 if (auth->auth_resp_tries >= max_tries) {
230 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
231 offchannel_send_action_done(wpa_s);
232 dpp_auth_deinit(wpa_s->dpp_auth);
233 wpa_s->dpp_auth = NULL;
234 return;
235 }
236
237 if (wpa_s->dpp_resp_retry_time)
238 wait_time = wpa_s->dpp_resp_retry_time;
239 else
240 wait_time = 1000;
241 wpa_printf(MSG_DEBUG,
242 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
243 wait_time);
244 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
245 eloop_register_timeout(wait_time / 1000,
246 (wait_time % 1000) * 1000,
247 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
248}
249
250
Hai Shalom021b0b52019-04-10 11:17:58 -0700251static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
252{
253 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700254 wpa_s->suitable_network = 0;
255 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700256 wpa_s->disconnected = 0;
257 wpa_s->reassociate = 1;
258 wpa_s->scan_runs = 0;
259 wpa_s->normal_scans = 0;
260 wpa_supplicant_cancel_sched_scan(wpa_s);
261 wpa_supplicant_req_scan(wpa_s, 0, 0);
262}
263
264
Hai Shalomc3565922019-10-28 11:58:20 -0700265#ifdef CONFIG_DPP2
266
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700267static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s,
268 unsigned int freq,
269 unsigned int wait_time)
270{
271 struct os_reltime now, res;
272 unsigned int remaining;
273
274 if (!wpa_s->dpp_listen_freq)
275 return;
276
277 os_get_reltime(&now);
278 if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) {
279 os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res);
280 remaining = res.sec * 1000 + res.usec / 1000;
281 } else {
282 remaining = 0;
283 }
284 if (wpa_s->dpp_listen_freq == freq && remaining > wait_time)
285 return;
286
287 wpa_printf(MSG_DEBUG,
288 "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms",
289 wpa_s->dpp_listen_freq, remaining, freq, wait_time);
290 wpas_dpp_listen_stop(wpa_s);
291
292 /* TODO: Restart listen in some cases after TX? */
293}
294
295
Hai Shalomc3565922019-10-28 11:58:20 -0700296static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
297 void *timeout_ctx)
298{
299 struct wpa_supplicant *wpa_s = eloop_ctx;
300 struct dpp_authentication *auth = wpa_s->dpp_auth;
301 enum dpp_status_error result;
302
Hai Shaloma20dcd72022-02-04 13:43:00 -0800303 if ((!auth || !auth->conn_status_requested) &&
304 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700305 return;
306
307 wpa_printf(MSG_DEBUG,
308 "DPP: Connection timeout - report Connection Status Result");
309 if (wpa_s->suitable_network)
310 result = DPP_STATUS_AUTH_FAILURE;
311 else if (wpa_s->no_suitable_network)
312 result = DPP_STATUS_NO_AP;
313 else
314 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800315 if (wpa_s->wpa_state == WPA_SCANNING)
316 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700317 wpas_dpp_send_conn_status_result(wpa_s, result);
318}
319
320
321static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
322{
323 char *str, *end, *pos;
324 size_t len;
325 unsigned int i;
326 u8 last_op_class = 0;
327 int res;
328
329 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
330 return NULL;
331
332 len = wpa_s->num_last_scan_freqs * 8;
333 str = os_zalloc(len);
334 if (!str)
335 return NULL;
336 end = str + len;
337 pos = str;
338
339 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
340 enum hostapd_hw_mode mode;
341 u8 op_class, channel;
342
343 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
344 0, 0, &op_class, &channel);
345 if (mode == NUM_HOSTAPD_MODES)
346 continue;
347 if (op_class == last_op_class)
348 res = os_snprintf(pos, end - pos, ",%d", channel);
349 else
350 res = os_snprintf(pos, end - pos, "%s%d/%d",
351 pos == str ? "" : ",",
352 op_class, channel);
353 if (os_snprintf_error(end - pos, res)) {
354 *pos = '\0';
355 break;
356 }
357 pos += res;
358 last_op_class = op_class;
359 }
360
361 if (pos == str) {
362 os_free(str);
363 str = NULL;
364 }
365 return str;
366}
367
368
369void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
370 enum dpp_status_error result)
371{
372 struct wpabuf *msg;
373 const char *channel_list = NULL;
374 char *channel_list_buf = NULL;
375 struct wpa_ssid *ssid = wpa_s->current_ssid;
376 struct dpp_authentication *auth = wpa_s->dpp_auth;
377
378 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
379
Hai Shaloma20dcd72022-02-04 13:43:00 -0800380 if ((!auth || !auth->conn_status_requested) &&
381 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700382 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800383
Hai Shalomc3565922019-10-28 11:58:20 -0700384 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
385 result);
386
387 if (result == DPP_STATUS_NO_AP) {
388 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
389 channel_list = channel_list_buf;
390 }
391
Hai Shaloma20dcd72022-02-04 13:43:00 -0800392 if (!auth || !auth->conn_status_requested) {
393 dpp_tcp_send_conn_status(wpa_s->dpp, result,
394 ssid ? ssid->ssid :
395 wpa_s->dpp_last_ssid,
396 ssid ? ssid->ssid_len :
397 wpa_s->dpp_last_ssid_len,
398 channel_list);
399 os_free(channel_list_buf);
400 return;
401 }
402
403 auth->conn_status_requested = 0;
404
Hai Shalomc3565922019-10-28 11:58:20 -0700405 msg = dpp_build_conn_status_result(auth, result,
406 ssid ? ssid->ssid :
407 wpa_s->dpp_last_ssid,
408 ssid ? ssid->ssid_len :
409 wpa_s->dpp_last_ssid_len,
410 channel_list);
411 os_free(channel_list_buf);
412 if (!msg) {
413 dpp_auth_deinit(wpa_s->dpp_auth);
414 wpa_s->dpp_auth = NULL;
415 return;
416 }
417
418 wpa_msg(wpa_s, MSG_INFO,
419 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
420 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
421 DPP_PA_CONNECTION_STATUS_RESULT);
422 offchannel_send_action(wpa_s, auth->curr_freq,
423 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
424 wpabuf_head(msg), wpabuf_len(msg),
425 500, wpas_dpp_tx_status, 0);
426 wpabuf_free(msg);
427
428 /* This exchange will be terminated in the TX status handler */
429 auth->remove_on_tx_status = 1;
430
431 return;
432}
433
434
435void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
436{
437 struct dpp_authentication *auth = wpa_s->dpp_auth;
438
Hai Shaloma20dcd72022-02-04 13:43:00 -0800439 if ((auth && auth->conn_status_requested) ||
440 dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700441 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
442}
443
444#endif /* CONFIG_DPP2 */
445
446
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700447static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
448 unsigned int freq, const u8 *dst,
449 const u8 *src, const u8 *bssid,
450 const u8 *data, size_t data_len,
451 enum offchannel_send_action_result result)
452{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700453 const char *res_txt;
454 struct dpp_authentication *auth = wpa_s->dpp_auth;
455
456 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
457 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
458 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700459 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700460 " result=%s", freq, MAC2STR(dst), res_txt);
461 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
462 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700463
464 if (!wpa_s->dpp_auth) {
465 wpa_printf(MSG_DEBUG,
466 "DPP: Ignore TX status since there is no ongoing authentication exchange");
467 return;
468 }
469
Hai Shalom021b0b52019-04-10 11:17:58 -0700470#ifdef CONFIG_DPP2
471 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700472 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700473 wpa_printf(MSG_DEBUG,
474 "DPP: Try to connect after completed configuration result");
475 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700476 if (auth->conn_status_requested) {
477 wpa_printf(MSG_DEBUG,
478 "DPP: Start 15 second timeout for reporting connection status result");
479 eloop_cancel_timeout(
480 wpas_dpp_conn_status_result_timeout,
481 wpa_s, NULL);
482 eloop_register_timeout(
483 15, 0, wpas_dpp_conn_status_result_timeout,
484 wpa_s, NULL);
485 } else {
486 dpp_auth_deinit(wpa_s->dpp_auth);
487 wpa_s->dpp_auth = NULL;
488 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700489 return;
490 }
491#endif /* CONFIG_DPP2 */
492
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700493 if (wpa_s->dpp_auth->remove_on_tx_status) {
494 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700495 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700496 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700497 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800498 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
499 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700500 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
501 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700502#ifdef CONFIG_DPP2
503 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
504 wpa_s, NULL);
505#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700506 offchannel_send_action_done(wpa_s);
507 dpp_auth_deinit(wpa_s->dpp_auth);
508 wpa_s->dpp_auth = NULL;
509 return;
510 }
511
512 if (wpa_s->dpp_auth_ok_on_ack)
513 wpas_dpp_auth_success(wpa_s, 1);
514
515 if (!is_broadcast_ether_addr(dst) &&
516 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
517 wpa_printf(MSG_DEBUG,
518 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700519 if (auth->waiting_auth_resp) {
520 /* In case of DPP Authentication Request frame, move to
521 * the next channel immediately. */
522 offchannel_send_action_done(wpa_s);
523 wpas_dpp_auth_init_next(wpa_s);
524 return;
525 }
526 if (auth->waiting_auth_conf) {
527 wpas_dpp_auth_resp_retry(wpa_s);
528 return;
529 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700530 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700531
Hai Shalom60840252021-02-19 19:02:11 -0800532 if (auth->waiting_auth_conf &&
533 auth->auth_resp_status == DPP_STATUS_OK) {
534 /* Make sure we do not get stuck waiting for Auth Confirm
535 * indefinitely after successfully transmitted Auth Response to
536 * allow new authentication exchanges to be started. */
537 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
538 NULL);
539 eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
540 wpa_s, NULL);
541 }
542
Roshan Pius3a1667e2018-07-03 15:17:14 -0700543 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
544 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
545 /* Allow timeout handling to stop iteration if no response is
546 * received from a peer that has ACKed a request. */
547 auth->auth_req_ack = 1;
548 }
549
550 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
551 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
552 wpa_printf(MSG_DEBUG,
553 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
554 wpa_s->dpp_auth->curr_freq,
555 wpa_s->dpp_auth->neg_freq);
556 offchannel_send_action_done(wpa_s);
557 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
558 }
559
560 if (wpa_s->dpp_auth_ok_on_ack)
561 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700562}
563
564
565static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
566{
567 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700568 struct dpp_authentication *auth = wpa_s->dpp_auth;
569 unsigned int freq;
570 struct os_reltime now, diff;
571 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700572
Roshan Pius3a1667e2018-07-03 15:17:14 -0700573 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700574 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700575
576 wait_time = wpa_s->dpp_resp_wait_time ?
577 wpa_s->dpp_resp_wait_time : 2000;
578 os_get_reltime(&now);
579 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
580 diff_ms = diff.sec * 1000 + diff.usec / 1000;
581 wpa_printf(MSG_DEBUG,
582 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
583 wait_time, diff_ms);
584
585 if (auth->auth_req_ack && diff_ms >= wait_time) {
586 /* Peer ACK'ed Authentication Request frame, but did not reply
587 * with Authentication Response frame within two seconds. */
588 wpa_printf(MSG_INFO,
589 "DPP: No response received from responder - stopping initiation attempt");
590 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800591 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700592 offchannel_send_action_done(wpa_s);
593 wpas_dpp_listen_stop(wpa_s);
594 dpp_auth_deinit(auth);
595 wpa_s->dpp_auth = NULL;
596 return;
597 }
598
599 if (diff_ms >= wait_time) {
600 /* Authentication Request frame was not ACK'ed and no reply
601 * was receiving within two seconds. */
602 wpa_printf(MSG_DEBUG,
603 "DPP: Continue Initiator channel iteration");
604 offchannel_send_action_done(wpa_s);
605 wpas_dpp_listen_stop(wpa_s);
606 wpas_dpp_auth_init_next(wpa_s);
607 return;
608 }
609
610 /* Driver did not support 2000 ms long wait_time with TX command, so
611 * schedule listen operation to continue waiting for the response.
612 *
613 * DPP listen operations continue until stopped, so simply schedule a
614 * new call to this function at the point when the two second reply
615 * wait has expired. */
616 wait_time -= diff_ms;
617
618 freq = auth->curr_freq;
619 if (auth->neg_freq > 0)
620 freq = auth->neg_freq;
621 wpa_printf(MSG_DEBUG,
622 "DPP: Continue reply wait on channel %u MHz for %u ms",
623 freq, wait_time);
624 wpa_s->dpp_in_response_listen = 1;
625 wpas_dpp_listen_start(wpa_s, freq);
626
627 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
628 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700629}
630
631
Hai Shalom60840252021-02-19 19:02:11 -0800632static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
633{
634 struct wpa_supplicant *wpa_s = eloop_ctx;
635 struct dpp_authentication *auth = wpa_s->dpp_auth;
636
637 if (!auth || !auth->waiting_auth_conf)
638 return;
639
640 wpa_printf(MSG_DEBUG,
641 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
642 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
643 offchannel_send_action_done(wpa_s);
644 dpp_auth_deinit(auth);
645 wpa_s->dpp_auth = NULL;
646}
647
648
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700649static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
650 struct dpp_authentication *auth)
651{
652#ifdef CONFIG_TESTING_OPTIONS
653 if (wpa_s->dpp_config_obj_override)
654 auth->config_obj_override =
655 os_strdup(wpa_s->dpp_config_obj_override);
656 if (wpa_s->dpp_discovery_override)
657 auth->discovery_override =
658 os_strdup(wpa_s->dpp_discovery_override);
659 if (wpa_s->dpp_groups_override)
660 auth->groups_override =
661 os_strdup(wpa_s->dpp_groups_override);
662 auth->ignore_netaccesskey_mismatch =
663 wpa_s->dpp_ignore_netaccesskey_mismatch;
664#endif /* CONFIG_TESTING_OPTIONS */
665}
666
667
Roshan Pius3a1667e2018-07-03 15:17:14 -0700668static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
669{
670 struct wpa_supplicant *wpa_s = eloop_ctx;
671
672 if (!wpa_s->dpp_auth)
673 return;
674 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
675 wpas_dpp_auth_init_next(wpa_s);
676}
677
678
679static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
680{
681 struct dpp_authentication *auth = wpa_s->dpp_auth;
682 const u8 *dst;
683 unsigned int wait_time, max_wait_time, freq, max_tries, used;
684 struct os_reltime now, diff;
685
686 wpa_s->dpp_in_response_listen = 0;
687 if (!auth)
688 return -1;
689
690 if (auth->freq_idx == 0)
691 os_get_reltime(&wpa_s->dpp_init_iter_start);
692
693 if (auth->freq_idx >= auth->num_freq) {
694 auth->num_freq_iters++;
695 if (wpa_s->dpp_init_max_tries)
696 max_tries = wpa_s->dpp_init_max_tries;
697 else
698 max_tries = 5;
699 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
700 wpa_printf(MSG_INFO,
701 "DPP: No response received from responder - stopping initiation attempt");
702 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800703 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700704 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
705 wpa_s, NULL);
706 offchannel_send_action_done(wpa_s);
707 dpp_auth_deinit(wpa_s->dpp_auth);
708 wpa_s->dpp_auth = NULL;
709 return -1;
710 }
711 auth->freq_idx = 0;
712 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
713 if (wpa_s->dpp_init_retry_time)
714 wait_time = wpa_s->dpp_init_retry_time;
715 else
716 wait_time = 10000;
717 os_get_reltime(&now);
718 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
719 used = diff.sec * 1000 + diff.usec / 1000;
720 if (used > wait_time)
721 wait_time = 0;
722 else
723 wait_time -= used;
724 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
725 wait_time);
726 eloop_register_timeout(wait_time / 1000,
727 (wait_time % 1000) * 1000,
728 wpas_dpp_init_timeout, wpa_s,
729 NULL);
730 return 0;
731 }
732 freq = auth->freq[auth->freq_idx++];
733 auth->curr_freq = freq;
734
Hai Shalom60840252021-02-19 19:02:11 -0800735 if (!is_zero_ether_addr(auth->peer_mac_addr))
736 dst = auth->peer_mac_addr;
737 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700738 dst = broadcast;
739 else
740 dst = auth->peer_bi->mac_addr;
741 wpa_s->dpp_auth_ok_on_ack = 0;
742 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
743 wait_time = wpa_s->max_remain_on_chan;
744 max_wait_time = wpa_s->dpp_resp_wait_time ?
745 wpa_s->dpp_resp_wait_time : 2000;
746 if (wait_time > max_wait_time)
747 wait_time = max_wait_time;
748 wait_time += 10; /* give the driver some extra time to complete */
749 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
750 wpas_dpp_reply_wait_timeout,
751 wpa_s, NULL);
752 wait_time -= 10;
753 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
754 wpa_printf(MSG_DEBUG,
755 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
756 freq, auth->neg_freq);
757 }
758 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
759 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
760 auth->auth_req_ack = 0;
761 os_get_reltime(&wpa_s->dpp_last_init);
762 return offchannel_send_action(wpa_s, freq, dst,
763 wpa_s->own_addr, broadcast,
764 wpabuf_head(auth->req_msg),
765 wpabuf_len(auth->req_msg),
766 wait_time, wpas_dpp_tx_status, 0);
767}
768
769
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700770int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
771{
772 const char *pos;
773 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700774 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700775 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
776 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700777 int tcp = 0;
778#ifdef CONFIG_DPP2
779 int tcp_port = DPP_TCP_PORT;
780 struct hostapd_ip_addr ipaddr;
781 char *addr;
782#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700783
784 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800785 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700786
787 pos = os_strstr(cmd, " peer=");
788 if (!pos)
789 return -1;
790 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700791 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700792 if (!peer_bi) {
793 wpa_printf(MSG_INFO,
794 "DPP: Could not find bootstrapping info for the identified peer");
795 return -1;
796 }
797
Hai Shalom81f62d82019-07-22 12:10:00 -0700798#ifdef CONFIG_DPP2
799 pos = os_strstr(cmd, " tcp_port=");
800 if (pos) {
801 pos += 10;
802 tcp_port = atoi(pos);
803 }
804
805 addr = get_param(cmd, " tcp_addr=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000806 if (addr && os_strcmp(addr, "from-uri") == 0) {
807 os_free(addr);
808 if (!peer_bi->host) {
809 wpa_printf(MSG_INFO,
810 "DPP: TCP address not available in peer URI");
811 return -1;
812 }
813 tcp = 1;
814 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
815 tcp_port = peer_bi->port;
816 } else if (addr) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700817 int res;
818
819 res = hostapd_parse_ip_addr(addr, &ipaddr);
820 os_free(addr);
821 if (res)
822 return -1;
823 tcp = 1;
824 }
825#endif /* CONFIG_DPP2 */
826
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700827 pos = os_strstr(cmd, " own=");
828 if (pos) {
829 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700830 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700831 if (!own_bi) {
832 wpa_printf(MSG_INFO,
833 "DPP: Could not find bootstrapping info for the identified local entry");
834 return -1;
835 }
836
837 if (peer_bi->curve != own_bi->curve) {
838 wpa_printf(MSG_INFO,
839 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
840 peer_bi->curve->name, own_bi->curve->name);
841 return -1;
842 }
843 }
844
845 pos = os_strstr(cmd, " role=");
846 if (pos) {
847 pos += 6;
848 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700849 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700850 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700851 allowed_roles = DPP_CAPAB_ENROLLEE;
852 else if (os_strncmp(pos, "either", 6) == 0)
853 allowed_roles = DPP_CAPAB_CONFIGURATOR |
854 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700855 else
856 goto fail;
857 }
858
859 pos = os_strstr(cmd, " netrole=");
860 if (pos) {
861 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800862 if (os_strncmp(pos, "ap", 2) == 0)
863 wpa_s->dpp_netrole = DPP_NETROLE_AP;
864 else if (os_strncmp(pos, "configurator", 12) == 0)
865 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
866 else
867 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700868 } else {
869 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700870 }
871
Roshan Pius3a1667e2018-07-03 15:17:14 -0700872 pos = os_strstr(cmd, " neg_freq=");
873 if (pos)
874 neg_freq = atoi(pos + 10);
875
Hai Shalom81f62d82019-07-22 12:10:00 -0700876 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700877 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700878 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800879 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
880 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700881 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
882 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700883#ifdef CONFIG_DPP2
884 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
885 wpa_s, NULL);
886#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700887 offchannel_send_action_done(wpa_s);
888 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800889 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700890 }
891
Hai Shalomfdcde762020-04-02 11:19:20 -0700892 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
893 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700894 if (!auth)
895 goto fail;
896 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700897 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700898 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800899 goto fail;
900 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700901
Hai Shalom81f62d82019-07-22 12:10:00 -0700902 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700903
Roshan Pius3a1667e2018-07-03 15:17:14 -0700904 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700905 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700906
Hai Shalom81f62d82019-07-22 12:10:00 -0700907#ifdef CONFIG_DPP2
908 if (tcp)
Hai Shalom899fcc72020-10-19 14:38:18 -0700909 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
910 wpa_s->conf->dpp_name, DPP_NETROLE_STA,
Sunil Ravi89eba102022-09-13 21:04:37 -0700911 wpa_s->conf->dpp_mud_url,
912 wpa_s->conf->dpp_extra_conf_req_name,
913 wpa_s->conf->dpp_extra_conf_req_value,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800914 wpa_s, wpa_s, wpas_dpp_process_conf_obj,
915 wpas_dpp_tcp_msg_sent);
Hai Shalom81f62d82019-07-22 12:10:00 -0700916#endif /* CONFIG_DPP2 */
917
918 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700919 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700920fail:
921 return -1;
922}
923
924
925struct wpas_dpp_listen_work {
926 unsigned int freq;
927 unsigned int duration;
928 struct wpabuf *probe_resp_ie;
929};
930
931
932static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
933{
934 if (!lwork)
935 return;
936 os_free(lwork);
937}
938
939
940static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
941{
942 struct wpas_dpp_listen_work *lwork;
943
944 if (!wpa_s->dpp_listen_work)
945 return;
946
947 lwork = wpa_s->dpp_listen_work->ctx;
948 wpas_dpp_listen_work_free(lwork);
949 radio_work_done(wpa_s->dpp_listen_work);
950 wpa_s->dpp_listen_work = NULL;
951}
952
953
954static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
955{
956 struct wpa_supplicant *wpa_s = work->wpa_s;
957 struct wpas_dpp_listen_work *lwork = work->ctx;
958
959 if (deinit) {
960 if (work->started) {
961 wpa_s->dpp_listen_work = NULL;
962 wpas_dpp_listen_stop(wpa_s);
963 }
964 wpas_dpp_listen_work_free(lwork);
965 return;
966 }
967
968 wpa_s->dpp_listen_work = work;
969
970 wpa_s->dpp_pending_listen_freq = lwork->freq;
971
972 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
973 wpa_s->max_remain_on_chan) < 0) {
974 wpa_printf(MSG_DEBUG,
975 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
976 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800977 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700978 wpas_dpp_listen_work_done(wpa_s);
979 wpa_s->dpp_pending_listen_freq = 0;
980 return;
981 }
982 wpa_s->off_channel_freq = 0;
983 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700984 wpa_drv_dpp_listen(wpa_s, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700985}
986
987
988static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
989 unsigned int freq)
990{
991 struct wpas_dpp_listen_work *lwork;
992
993 if (wpa_s->dpp_listen_work) {
994 wpa_printf(MSG_DEBUG,
995 "DPP: Reject start_listen since dpp_listen_work already exists");
996 return -1;
997 }
998
999 if (wpa_s->dpp_listen_freq)
1000 wpas_dpp_listen_stop(wpa_s);
1001 wpa_s->dpp_listen_freq = freq;
1002
1003 lwork = os_zalloc(sizeof(*lwork));
1004 if (!lwork)
1005 return -1;
1006 lwork->freq = freq;
1007
1008 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
1009 lwork) < 0) {
1010 wpas_dpp_listen_work_free(lwork);
1011 return -1;
1012 }
1013
1014 return 0;
1015}
1016
1017
1018int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
1019{
1020 int freq;
1021
1022 freq = atoi(cmd);
1023 if (freq <= 0)
1024 return -1;
1025
1026 if (os_strstr(cmd, " role=configurator"))
1027 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
1028 else if (os_strstr(cmd, " role=enrollee"))
1029 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
1030 else
1031 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
1032 DPP_CAPAB_ENROLLEE;
1033 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001034 if (os_strstr(cmd, " netrole=ap"))
1035 wpa_s->dpp_netrole = DPP_NETROLE_AP;
1036 else if (os_strstr(cmd, " netrole=configurator"))
1037 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
1038 else
1039 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001040 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1041 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1042 freq);
1043 return 0;
1044 }
1045
1046 return wpas_dpp_listen_start(wpa_s, freq);
1047}
1048
1049
1050void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1051{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001052 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001053 if (!wpa_s->dpp_listen_freq)
1054 return;
1055
1056 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1057 wpa_s->dpp_listen_freq);
1058 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001059 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001060 wpa_s->dpp_listen_freq = 0;
1061 wpas_dpp_listen_work_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001062 radio_remove_works(wpa_s, "dpp-listen", 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001063}
1064
1065
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001066void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1067 unsigned int freq, unsigned int duration)
1068{
1069 if (wpa_s->dpp_listen_freq != freq)
1070 return;
1071
1072 wpa_printf(MSG_DEBUG,
1073 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
1074 freq, duration);
1075 os_get_reltime(&wpa_s->dpp_listen_end);
1076 wpa_s->dpp_listen_end.usec += duration * 1000;
1077 while (wpa_s->dpp_listen_end.usec >= 1000000) {
1078 wpa_s->dpp_listen_end.sec++;
1079 wpa_s->dpp_listen_end.usec -= 1000000;
1080 }
1081}
1082
1083
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001084void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1085 unsigned int freq)
1086{
1087 wpas_dpp_listen_work_done(wpa_s);
1088
Roshan Pius3a1667e2018-07-03 15:17:14 -07001089 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1090 unsigned int new_freq;
1091
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001092 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001093 if (wpa_s->dpp_auth->neg_freq > 0)
1094 new_freq = wpa_s->dpp_auth->neg_freq;
1095 else
1096 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001097 wpa_printf(MSG_DEBUG,
1098 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001099 new_freq);
1100 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001101 return;
1102 }
1103
1104 if (wpa_s->dpp_listen_freq) {
1105 /* Continue listen with a new remain-on-channel */
1106 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1107 }
1108}
1109
1110
1111static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1112 const u8 *hdr, const u8 *buf, size_t len,
1113 unsigned int freq)
1114{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001115 const u8 *r_bootstrap, *i_bootstrap;
1116 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001117 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1118
1119 if (!wpa_s->dpp)
1120 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001121
1122 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1123 MAC2STR(src));
1124
Hai Shalomfdcde762020-04-02 11:19:20 -07001125#ifdef CONFIG_DPP2
1126 wpas_dpp_chirp_stop(wpa_s);
1127#endif /* CONFIG_DPP2 */
1128
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001129 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1130 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001131 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1132 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1133 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001134 return;
1135 }
1136 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1137 r_bootstrap, r_bootstrap_len);
1138
1139 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1140 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001141 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1142 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1143 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001144 return;
1145 }
1146 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1147 i_bootstrap, i_bootstrap_len);
1148
1149 /* Try to find own and peer bootstrapping key matches based on the
1150 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001151 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1152 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001153 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001154 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1155 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001156 return;
1157 }
1158
Sunil Ravi89eba102022-09-13 21:04:37 -07001159 if (own_bi->type == DPP_BOOTSTRAP_PKEX) {
1160 if (!peer_bi || peer_bi->type != DPP_BOOTSTRAP_PKEX) {
1161 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1162 "No matching peer bootstrapping key found for PKEX - ignore message");
1163 return;
1164 }
1165
1166 if (os_memcmp(peer_bi->pubkey_hash, own_bi->peer_pubkey_hash,
1167 SHA256_MAC_LEN) != 0) {
1168 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1169 "Mismatching peer PKEX bootstrapping key - ignore message");
1170 return;
1171 }
1172 }
1173
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001174 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001175 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1176 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001177 return;
1178 }
1179
Sunil Ravia04bd252022-05-02 22:54:18 -07001180 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001181 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001182 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001183 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001184 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1185 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001186 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001187 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001188 if (!wpa_s->dpp_auth) {
1189 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1190 return;
1191 }
1192 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001193 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001194 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001195 dpp_auth_deinit(wpa_s->dpp_auth);
1196 wpa_s->dpp_auth = NULL;
1197 return;
1198 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001199 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1200
Roshan Pius3a1667e2018-07-03 15:17:14 -07001201 if (wpa_s->dpp_listen_freq &&
1202 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1203 wpa_printf(MSG_DEBUG,
1204 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1205 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1206 wpas_dpp_listen_stop(wpa_s);
1207 }
1208
1209 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1210 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1211 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001212 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1213 src, wpa_s->own_addr, broadcast,
1214 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1215 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1216 500, wpas_dpp_tx_status, 0);
1217}
1218
1219
Hai Shaloma20dcd72022-02-04 13:43:00 -08001220void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
1221{
1222 struct dpp_authentication *auth = wpa_s->dpp_auth;
1223 int freq;
1224
1225 if (!wpa_s->dpp_gas_server || !auth)
1226 return;
1227
1228 freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
1229 if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
1230 return; /* listen state is already in progress */
1231
1232 wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
1233 wpa_s->dpp_in_response_listen = 1;
1234 wpas_dpp_listen_start(wpa_s, freq);
1235}
1236
1237
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001238static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1239{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001240 struct dpp_authentication *auth = wpa_s->dpp_auth;
1241
1242 wpa_printf(MSG_DEBUG,
1243 "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
1244 auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
1245 !!wpa_s->dpp_listen_work);
1246 wpa_s->dpp_gas_server = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001247}
1248
1249
1250static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001251 struct dpp_authentication *auth,
1252 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001253{
1254 struct wpa_ssid *ssid;
1255
Hai Shalom021b0b52019-04-10 11:17:58 -07001256#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001257 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001258#ifdef CONFIG_SAE
1259 struct wpa_driver_capa capa;
1260 int res;
1261
1262 res = wpa_drv_get_capa(wpa_s, &capa);
1263 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001264 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1265 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001266 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1267 wpa_printf(MSG_DEBUG,
1268 "DPP: SAE not supported by the driver");
1269 return NULL;
1270 }
1271#else /* CONFIG_SAE */
1272 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1273 return NULL;
1274#endif /* CONFIG_SAE */
1275 }
1276#endif /* CONFIG_DPP2 */
1277
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001278 ssid = wpa_config_add_network(wpa_s->conf);
1279 if (!ssid)
1280 return NULL;
1281 wpas_notify_network_added(wpa_s, ssid);
1282 wpa_config_set_network_defaults(ssid);
1283 ssid->disabled = 1;
1284
Hai Shalomc3565922019-10-28 11:58:20 -07001285 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001286 if (!ssid->ssid)
1287 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001288 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1289 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001290
Hai Shalomc3565922019-10-28 11:58:20 -07001291 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001292 if (dpp_akm_dpp(conf->akm)) {
1293 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1294 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1295 }
Hai Shalomc3565922019-10-28 11:58:20 -07001296 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001297 if (!ssid->dpp_connector)
1298 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07001299
1300 ssid->dpp_connector_privacy =
1301 wpa_s->conf->dpp_connector_privacy_default;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001302 }
1303
Hai Shalomc3565922019-10-28 11:58:20 -07001304 if (conf->c_sign_key) {
1305 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001306 if (!ssid->dpp_csign)
1307 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001308 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1309 wpabuf_len(conf->c_sign_key));
1310 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001311 }
1312
Hai Shalom899fcc72020-10-19 14:38:18 -07001313 if (conf->pp_key) {
1314 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1315 if (!ssid->dpp_pp_key)
1316 goto fail;
1317 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1318 wpabuf_len(conf->pp_key));
1319 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1320 }
1321
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001322 if (auth->net_access_key) {
1323 ssid->dpp_netaccesskey =
1324 os_malloc(wpabuf_len(auth->net_access_key));
1325 if (!ssid->dpp_netaccesskey)
1326 goto fail;
1327 os_memcpy(ssid->dpp_netaccesskey,
1328 wpabuf_head(auth->net_access_key),
1329 wpabuf_len(auth->net_access_key));
1330 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1331 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1332 }
1333
Hai Shalomc3565922019-10-28 11:58:20 -07001334 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1335 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001336 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001337 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001338 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001339 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1340 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001341 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001342 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1343 WPA_KEY_MGMT_FT_SAE;
1344 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001345 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001346 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001347 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001348 goto fail;
1349 wpa_config_update_psk(ssid);
1350 ssid->export_keys = 1;
1351 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001352 ssid->psk_set = conf->psk_set;
1353 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001354 }
1355 }
1356
Hai Shalom899fcc72020-10-19 14:38:18 -07001357#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1358 if (conf->akm == DPP_AKM_DOT1X) {
1359 int i;
1360 char name[100], blobname[128];
1361 struct wpa_config_blob *blob;
1362
1363 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1364 WPA_KEY_MGMT_IEEE8021X_SHA256 |
1365 WPA_KEY_MGMT_IEEE8021X_SHA256;
1366 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1367
1368 if (conf->cacert) {
1369 /* caCert is DER-encoded X.509v3 certificate for the
1370 * server certificate if that is different from the
1371 * trust root included in certBag. */
1372 /* TODO: ssid->eap.cert.ca_cert */
1373 }
1374
1375 if (conf->certs) {
1376 for (i = 0; ; i++) {
1377 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1378 i);
1379 if (!wpa_config_get_blob(wpa_s->conf, name))
1380 break;
1381 }
1382
1383 blob = os_zalloc(sizeof(*blob));
1384 if (!blob)
1385 goto fail;
1386 blob->len = wpabuf_len(conf->certs);
1387 blob->name = os_strdup(name);
1388 blob->data = os_malloc(blob->len);
1389 if (!blob->name || !blob->data) {
1390 wpa_config_free_blob(blob);
1391 goto fail;
1392 }
1393 os_memcpy(blob->data, wpabuf_head(conf->certs),
1394 blob->len);
1395 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1396 name);
1397 wpa_config_set_blob(wpa_s->conf, blob);
1398 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1399 name);
1400 ssid->eap.cert.client_cert = os_strdup(blobname);
1401 if (!ssid->eap.cert.client_cert)
1402 goto fail;
1403
1404 /* TODO: ssid->eap.identity from own certificate */
1405 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1406 0) < 0)
1407 goto fail;
1408 }
1409
1410 if (auth->priv_key) {
1411 for (i = 0; ; i++) {
1412 os_snprintf(name, sizeof(name), "dpp-key-%d",
1413 i);
1414 if (!wpa_config_get_blob(wpa_s->conf, name))
1415 break;
1416 }
1417
1418 blob = os_zalloc(sizeof(*blob));
1419 if (!blob)
1420 goto fail;
1421 blob->len = wpabuf_len(auth->priv_key);
1422 blob->name = os_strdup(name);
1423 blob->data = os_malloc(blob->len);
1424 if (!blob->name || !blob->data) {
1425 wpa_config_free_blob(blob);
1426 goto fail;
1427 }
1428 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1429 blob->len);
1430 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1431 name);
1432 wpa_config_set_blob(wpa_s->conf, blob);
1433 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1434 name);
1435 ssid->eap.cert.private_key = os_strdup(blobname);
1436 if (!ssid->eap.cert.private_key)
1437 goto fail;
1438 }
1439
1440 if (conf->server_name) {
1441 ssid->eap.cert.domain_suffix_match =
1442 os_strdup(conf->server_name);
1443 if (!ssid->eap.cert.domain_suffix_match)
1444 goto fail;
1445 }
1446
1447 /* TODO: Use entCreds::eapMethods */
1448 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1449 goto fail;
1450 }
1451#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1452
Hai Shalomc3565922019-10-28 11:58:20 -07001453 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1454 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1455
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001456 return ssid;
1457fail:
1458 wpas_notify_network_removed(wpa_s, ssid);
1459 wpa_config_remove_network(wpa_s->conf, ssid->id);
1460 return NULL;
1461}
1462
1463
Hai Shalom021b0b52019-04-10 11:17:58 -07001464static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001465 struct dpp_authentication *auth,
1466 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001467{
1468 struct wpa_ssid *ssid;
1469
1470 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001471 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001472
Hai Shalomc3565922019-10-28 11:58:20 -07001473 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001474 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001475 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001476
1477 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001478
Hai Shalom706f99b2019-01-08 16:23:37 -08001479 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001480
Hai Shalom021b0b52019-04-10 11:17:58 -07001481 if (wpa_s->conf->dpp_config_processing == 2)
1482 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001483
Hai Shalom021b0b52019-04-10 11:17:58 -07001484#ifndef CONFIG_NO_CONFIG_WRITE
1485 if (wpa_s->conf->update_config &&
1486 wpa_config_write(wpa_s->confname, wpa_s->conf))
1487 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1488#endif /* CONFIG_NO_CONFIG_WRITE */
1489
Hai Shalomc3565922019-10-28 11:58:20 -07001490 return 0;
1491}
1492
1493
1494static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1495 struct dpp_authentication *auth)
1496{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001497#ifdef CONFIG_DPP2
1498 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1499 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1500 wpa_s->dpp_reconfig_ssid) {
1501 wpa_printf(MSG_DEBUG,
1502 "DPP: Remove reconfigured network profile");
1503 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1504 wpa_config_remove_network(wpa_s->conf,
1505 wpa_s->dpp_reconfig_ssid_id);
1506 wpa_s->dpp_reconfig_ssid = NULL;
1507 wpa_s->dpp_reconfig_ssid_id = -1;
1508 }
1509#endif /* CONFIG_DPP2 */
1510
Hai Shalom021b0b52019-04-10 11:17:58 -07001511 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001512 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001513
1514#ifdef CONFIG_DPP2
1515 if (auth->peer_version >= 2) {
1516 wpa_printf(MSG_DEBUG,
1517 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1518 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001519 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001520 }
1521#endif /* CONFIG_DPP2 */
1522
1523 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001524}
1525
1526
Hai Shalom021b0b52019-04-10 11:17:58 -07001527static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001528 struct dpp_authentication *auth,
1529 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001530{
1531 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001532 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1533 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001534 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001535 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001536 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001537 if (conf->ssid_charset)
1538 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1539 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001540 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001541 /* TODO: Save the Connector and consider using a command
1542 * to fetch the value instead of sending an event with
1543 * it. The Connector could end up being larger than what
1544 * most clients are ready to receive as an event
1545 * message. */
1546 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001547 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001548 }
Hai Shalom60840252021-02-19 19:02:11 -08001549 if (conf->passphrase[0]) {
1550 char hex[64 * 2 + 1];
1551
1552 wpa_snprintf_hex(hex, sizeof(hex),
1553 (const u8 *) conf->passphrase,
1554 os_strlen(conf->passphrase));
1555 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1556 hex);
1557 } else if (conf->psk_set) {
1558 char hex[PMK_LEN * 2 + 1];
1559
1560 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1561 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1562 hex);
1563 }
Hai Shalomc3565922019-10-28 11:58:20 -07001564 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001565 char *hex;
1566 size_t hexlen;
1567
Hai Shalomc3565922019-10-28 11:58:20 -07001568 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001569 hex = os_malloc(hexlen);
1570 if (hex) {
1571 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001572 wpabuf_head(conf->c_sign_key),
1573 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001574 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1575 hex);
1576 os_free(hex);
1577 }
1578 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001579 if (conf->pp_key) {
1580 char *hex;
1581 size_t hexlen;
1582
1583 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1584 hex = os_malloc(hexlen);
1585 if (hex) {
1586 wpa_snprintf_hex(hex, hexlen,
1587 wpabuf_head(conf->pp_key),
1588 wpabuf_len(conf->pp_key));
1589 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1590 os_free(hex);
1591 }
1592 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001593 if (auth->net_access_key) {
1594 char *hex;
1595 size_t hexlen;
1596
1597 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1598 hex = os_malloc(hexlen);
1599 if (hex) {
1600 wpa_snprintf_hex(hex, hexlen,
1601 wpabuf_head(auth->net_access_key),
1602 wpabuf_len(auth->net_access_key));
1603 if (auth->net_access_key_expiry)
1604 wpa_msg(wpa_s, MSG_INFO,
1605 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1606 (long unsigned)
1607 auth->net_access_key_expiry);
1608 else
1609 wpa_msg(wpa_s, MSG_INFO,
1610 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1611 os_free(hex);
1612 }
1613 }
1614
Hai Shalom899fcc72020-10-19 14:38:18 -07001615#ifdef CONFIG_DPP2
1616 if (conf->certbag) {
1617 char *b64;
1618
1619 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1620 wpabuf_len(conf->certbag), NULL);
1621 if (b64)
1622 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1623 os_free(b64);
1624 }
1625
1626 if (conf->cacert) {
1627 char *b64;
1628
1629 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1630 wpabuf_len(conf->cacert), NULL);
1631 if (b64)
1632 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1633 os_free(b64);
1634 }
1635
1636 if (conf->server_name)
1637 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1638 conf->server_name);
1639#endif /* CONFIG_DPP2 */
1640
Sunil Ravi89eba102022-09-13 21:04:37 -07001641#ifdef CONFIG_DPP3
1642 if (!wpa_s->dpp_pb_result_indicated) {
1643 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "success");
1644 wpa_s->dpp_pb_result_indicated = true;
1645 }
1646
1647#endif /* CONFIG_DPP3 */
1648
Hai Shalomc3565922019-10-28 11:58:20 -07001649 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001650}
1651
1652
Hai Shalomfdcde762020-04-02 11:19:20 -07001653static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1654 struct dpp_asymmetric_key *key)
1655{
1656#ifdef CONFIG_DPP2
1657 int res;
1658
1659 if (!key)
1660 return 0;
1661
1662 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1663 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001664 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001665
1666 while (key) {
1667 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1668 if (res < 0)
1669 return -1;
1670 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1671 res);
1672 key = key->next;
1673 }
1674#endif /* CONFIG_DPP2 */
1675
1676 return 0;
1677}
1678
1679
Hai Shalom899fcc72020-10-19 14:38:18 -07001680#ifdef CONFIG_DPP2
1681static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1682{
1683 struct wpa_supplicant *wpa_s = eloop_ctx;
1684 struct dpp_authentication *auth = wpa_s->dpp_auth;
1685
1686 if (!auth || !auth->csrattrs)
1687 return;
1688
1689 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1690 wpabuf_free(auth->csr);
1691 /* TODO: Additional information needed for CSR based on csrAttrs */
1692 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1693 wpa_s->conf->dpp_name : "Test");
1694 if (!auth->csr) {
1695 dpp_auth_deinit(wpa_s->dpp_auth);
1696 wpa_s->dpp_auth = NULL;
1697 return;
1698 }
1699
1700 wpas_dpp_start_gas_client(wpa_s);
1701}
1702#endif /* CONFIG_DPP2 */
1703
1704
Sunil Ravia04bd252022-05-02 22:54:18 -07001705#ifdef CONFIG_DPP3
1706static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1707{
1708 struct wpa_supplicant *wpa_s = eloop_ctx;
1709 struct dpp_authentication *auth = wpa_s->dpp_auth;
1710
1711 if (!auth || !auth->waiting_new_key)
1712 return;
1713
1714 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1715 wpas_dpp_start_gas_client(wpa_s);
1716}
1717#endif /* CONFIG_DPP3 */
1718
1719
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001720static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1721 enum gas_query_result result,
1722 const struct wpabuf *adv_proto,
1723 const struct wpabuf *resp, u16 status_code)
1724{
1725 struct wpa_supplicant *wpa_s = ctx;
1726 const u8 *pos;
1727 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001728 int res;
1729 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001730 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001731
Hai Shaloma20dcd72022-02-04 13:43:00 -08001732 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001733 wpa_s->dpp_gas_dialog_token = -1;
1734
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001735 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
1736 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001737 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1738 return;
1739 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001740 if (result != GAS_QUERY_SUCCESS ||
1741 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001742 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1743 goto fail;
1744 }
1745
1746 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1747 adv_proto);
1748 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1749 resp);
1750
1751 if (wpabuf_len(adv_proto) != 10 ||
1752 !(pos = wpabuf_head(adv_proto)) ||
1753 pos[0] != WLAN_EID_ADV_PROTO ||
1754 pos[1] != 8 ||
1755 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1756 pos[4] != 5 ||
1757 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1758 pos[8] != 0x1a ||
1759 pos[9] != 1) {
1760 wpa_printf(MSG_DEBUG,
1761 "DPP: Not a DPP Advertisement Protocol ID");
1762 goto fail;
1763 }
1764
Hai Shalom899fcc72020-10-19 14:38:18 -07001765 res = dpp_conf_resp_rx(auth, resp);
1766#ifdef CONFIG_DPP2
1767 if (res == -2) {
1768 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1769 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1770 return;
1771 }
1772#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001773#ifdef CONFIG_DPP3
1774 if (res == -3) {
1775 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1776 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1777 NULL);
1778 return;
1779 }
1780#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001781 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001782 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1783 goto fail;
1784 }
1785
Hai Shalom899fcc72020-10-19 14:38:18 -07001786 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001787 for (i = 0; i < auth->num_conf_obj; i++) {
1788 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1789 &auth->conf_obj[i]);
1790 if (res < 0)
1791 goto fail;
1792 }
1793 if (auth->num_conf_obj)
1794 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001795 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1796 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001797
Hai Shalom021b0b52019-04-10 11:17:58 -07001798 status = DPP_STATUS_OK;
1799#ifdef CONFIG_TESTING_OPTIONS
1800 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1801 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1802 status = DPP_STATUS_CONFIG_REJECTED;
1803 }
1804#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001805fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001806 if (status != DPP_STATUS_OK) {
1807 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1808 wpas_notify_dpp_configuration_failure(wpa_s);
1809 }
1810#ifdef CONFIG_DPP2
1811 if (auth->peer_version >= 2 &&
1812 auth->conf_resp_status == DPP_STATUS_OK) {
1813 struct wpabuf *msg;
1814
1815 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1816 msg = dpp_build_conf_result(auth, status);
1817 if (!msg)
1818 goto fail2;
1819
1820 wpa_msg(wpa_s, MSG_INFO,
1821 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1822 MAC2STR(addr), auth->curr_freq,
1823 DPP_PA_CONFIGURATION_RESULT);
1824 offchannel_send_action(wpa_s, auth->curr_freq,
1825 addr, wpa_s->own_addr, broadcast,
1826 wpabuf_head(msg),
1827 wpabuf_len(msg),
1828 500, wpas_dpp_tx_status, 0);
1829 wpabuf_free(msg);
1830
1831 /* This exchange will be terminated in the TX status handler */
Hai Shalom899fcc72020-10-19 14:38:18 -07001832 if (wpa_s->conf->dpp_config_processing < 2 ||
1833 wpa_s->dpp_conf_backup_received)
1834 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001835 return;
1836 }
1837fail2:
1838#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001839 dpp_auth_deinit(wpa_s->dpp_auth);
1840 wpa_s->dpp_auth = NULL;
1841}
1842
1843
Hai Shaloma20dcd72022-02-04 13:43:00 -08001844static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
1845{
1846 struct wpa_supplicant *wpa_s = eloop_ctx;
1847 struct dpp_authentication *auth = wpa_s->dpp_auth;
1848
1849 if (!wpa_s->dpp_gas_client || !auth ||
1850 (!auth->auth_success && !auth->reconfig_success))
1851 return;
1852
1853 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
1854 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1855 dpp_auth_deinit(wpa_s->dpp_auth);
1856 wpa_s->dpp_auth = NULL;
1857}
1858
1859
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001860static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1861{
1862 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001863 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001864 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001865 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001866
1867 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001868 offchannel_send_action_done(wpa_s);
1869 wpas_dpp_listen_stop(wpa_s);
1870
Hai Shalomc3565922019-10-28 11:58:20 -07001871 supp_op_classes = wpas_supp_op_classes(wpa_s);
1872 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001873 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001874 wpa_s->conf->dpp_mud_url,
Sunil Ravi89eba102022-09-13 21:04:37 -07001875 supp_op_classes,
1876 wpa_s->conf->dpp_extra_conf_req_name,
1877 wpa_s->conf->dpp_extra_conf_req_value);
Hai Shalomc3565922019-10-28 11:58:20 -07001878 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001879 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001880 wpa_printf(MSG_DEBUG,
1881 "DPP: No configuration request data available");
1882 return;
1883 }
1884
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001885 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1886 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1887
Hai Shaloma20dcd72022-02-04 13:43:00 -08001888 /* Use a 120 second timeout since the gas_query_req() operation could
1889 * remain waiting indefinitely for the response if the Configurator
1890 * keeps sending out comeback responses with additional delay. The
1891 * DPP technical specification expects the Enrollee to continue sending
1892 * out new Config Requests for 60 seconds, so this gives an extra 60
1893 * second time after the last expected new Config Request for the
1894 * Configurator to determine what kind of configuration to provide. */
1895 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
1896 wpa_s, NULL);
1897
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001898 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001899 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001900 if (res < 0) {
1901 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1902 wpabuf_free(buf);
1903 } else {
1904 wpa_printf(MSG_DEBUG,
1905 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001906 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001907 }
1908}
1909
1910
1911static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1912{
1913 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1914 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001915 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001916#ifdef CONFIG_TESTING_OPTIONS
1917 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1918 wpa_printf(MSG_INFO,
1919 "DPP: TESTING - stop at Authentication Confirm");
1920 if (wpa_s->dpp_auth->configurator) {
1921 /* Prevent GAS response */
1922 wpa_s->dpp_auth->auth_success = 0;
1923 }
1924 return;
1925 }
1926#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001927
1928 if (wpa_s->dpp_auth->configurator)
1929 wpas_dpp_start_gas_server(wpa_s);
1930 else
1931 wpas_dpp_start_gas_client(wpa_s);
1932}
1933
1934
1935static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001936 const u8 *hdr, const u8 *buf, size_t len,
1937 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001938{
1939 struct dpp_authentication *auth = wpa_s->dpp_auth;
1940 struct wpabuf *msg;
1941
Roshan Pius3a1667e2018-07-03 15:17:14 -07001942 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1943 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001944
1945 if (!auth) {
1946 wpa_printf(MSG_DEBUG,
1947 "DPP: No DPP Authentication in progress - drop");
1948 return;
1949 }
1950
1951 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1952 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1953 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1954 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1955 return;
1956 }
1957
1958 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1959
Roshan Pius3a1667e2018-07-03 15:17:14 -07001960 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1961 wpa_printf(MSG_DEBUG,
1962 "DPP: Responder accepted request for different negotiation channel");
1963 auth->curr_freq = freq;
1964 }
1965
1966 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001967 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1968 if (!msg) {
1969 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1970 wpa_printf(MSG_DEBUG,
1971 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001972 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001973 offchannel_send_action_done(wpa_s);
1974 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1975 return;
1976 }
1977 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1978 return;
1979 }
1980 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1981
Roshan Pius3a1667e2018-07-03 15:17:14 -07001982 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1983 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001984 offchannel_send_action(wpa_s, auth->curr_freq,
1985 src, wpa_s->own_addr, broadcast,
1986 wpabuf_head(msg), wpabuf_len(msg),
1987 500, wpas_dpp_tx_status, 0);
1988 wpabuf_free(msg);
1989 wpa_s->dpp_auth_ok_on_ack = 1;
1990}
1991
1992
1993static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1994 const u8 *hdr, const u8 *buf, size_t len)
1995{
1996 struct dpp_authentication *auth = wpa_s->dpp_auth;
1997
1998 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1999 MAC2STR(src));
2000
2001 if (!auth) {
2002 wpa_printf(MSG_DEBUG,
2003 "DPP: No DPP Authentication in progress - drop");
2004 return;
2005 }
2006
2007 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2008 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2009 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2010 return;
2011 }
2012
Hai Shalom60840252021-02-19 19:02:11 -08002013 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
2014
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002015 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
2016 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08002017 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002018 return;
2019 }
2020
2021 wpas_dpp_auth_success(wpa_s, 0);
2022}
2023
2024
Hai Shalom021b0b52019-04-10 11:17:58 -07002025#ifdef CONFIG_DPP2
2026
2027static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
2028 void *timeout_ctx)
2029{
2030 struct wpa_supplicant *wpa_s = eloop_ctx;
2031 struct dpp_authentication *auth = wpa_s->dpp_auth;
2032
2033 if (!auth || !auth->waiting_conf_result)
2034 return;
2035
2036 wpa_printf(MSG_DEBUG,
2037 "DPP: Timeout while waiting for Configuration Result");
2038 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002039 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002040 dpp_auth_deinit(auth);
2041 wpa_s->dpp_auth = NULL;
2042}
2043
2044
Hai Shalomc3565922019-10-28 11:58:20 -07002045static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2046 void *timeout_ctx)
2047{
2048 struct wpa_supplicant *wpa_s = eloop_ctx;
2049 struct dpp_authentication *auth = wpa_s->dpp_auth;
2050
2051 if (!auth || !auth->waiting_conn_status_result)
2052 return;
2053
2054 wpa_printf(MSG_DEBUG,
2055 "DPP: Timeout while waiting for Connection Status Result");
2056 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002057 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002058 wpas_dpp_listen_stop(wpa_s);
2059 dpp_auth_deinit(auth);
2060 wpa_s->dpp_auth = NULL;
2061}
2062
2063
Sunil Ravi89eba102022-09-13 21:04:37 -07002064#ifdef CONFIG_DPP3
2065
2066static bool wpas_dpp_pb_active(struct wpa_supplicant *wpa_s)
2067{
2068 return (wpa_s->dpp_pb_time.sec || wpa_s->dpp_pb_time.usec) &&
2069 wpa_s->dpp_pb_configurator;
2070}
2071
2072
2073static void wpas_dpp_remove_pb_hash(struct wpa_supplicant *wpa_s)
2074{
2075 int i;
2076
2077 if (!wpa_s->dpp_pb_bi)
2078 return;
2079 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2080 struct dpp_pb_info *info = &wpa_s->dpp_pb[i];
2081
2082 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
2083 continue;
2084 if (os_memcmp(info->hash, wpa_s->dpp_pb_resp_hash,
2085 SHA256_MAC_LEN) == 0) {
2086 /* Allow a new push button session to be established
2087 * immediately without the successfully completed
2088 * session triggering session overlap. */
2089 info->rx_time.sec = 0;
2090 info->rx_time.usec = 0;
2091 wpa_printf(MSG_DEBUG,
2092 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
2093 }
2094 }
2095}
2096
2097#endif /* CONFIG_DPP3 */
2098
2099
Hai Shalom021b0b52019-04-10 11:17:58 -07002100static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2101 const u8 *hdr, const u8 *buf, size_t len)
2102{
2103 struct dpp_authentication *auth = wpa_s->dpp_auth;
2104 enum dpp_status_error status;
2105
2106 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2107 MAC2STR(src));
2108
2109 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002110 if (auth &&
2111 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
2112 gas_server_response_sent(wpa_s->gas_server,
2113 auth->gas_server_ctx)) {
2114 /* This could happen if the TX status event gets delayed
2115 * long enough for the Enrollee to have time to send
2116 * the next frame before the TX status gets processed
2117 * locally. */
2118 wpa_printf(MSG_DEBUG,
2119 "DPP: GAS response was sent but TX status not yet received - assume it was ACKed since the Enrollee sent the next frame in the sequence");
2120 auth->waiting_conf_result = 1;
2121 } else {
2122 wpa_printf(MSG_DEBUG,
2123 "DPP: No DPP Configuration waiting for result - drop");
2124 return;
2125 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002126 }
2127
2128 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2129 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2130 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2131 return;
2132 }
2133
2134 status = dpp_conf_result_rx(auth, hdr, buf, len);
2135
Hai Shalomc3565922019-10-28 11:58:20 -07002136 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002137 int freq;
2138
Hai Shalomc3565922019-10-28 11:58:20 -07002139 wpa_msg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07002140 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
2141 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07002142 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002143 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002144 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2145 wpa_s, NULL);
2146 auth->waiting_conn_status_result = 1;
2147 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2148 wpa_s, NULL);
2149 eloop_register_timeout(16, 0,
2150 wpas_dpp_conn_status_result_wait_timeout,
2151 wpa_s, NULL);
2152 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002153 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2154 if (!wpa_s->dpp_in_response_listen ||
2155 (int) wpa_s->dpp_listen_freq != freq)
2156 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002157 return;
2158 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002159 offchannel_send_action_done(wpa_s);
2160 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002161 if (status == DPP_STATUS_OK) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002162 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
2163 auth->conf_resp_status);
Hai Shalome4073332019-11-05 16:20:12 -08002164 wpas_notify_dpp_config_sent(wpa_s);
2165 }
2166 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002167 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002168 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002169 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002170 dpp_auth_deinit(auth);
2171 wpa_s->dpp_auth = NULL;
2172 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07002173#ifdef CONFIG_DPP3
2174 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
2175 if (status == DPP_STATUS_OK)
2176 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2177 "success");
2178 else
2179 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2180 "no-configuration-available");
2181 wpa_s->dpp_pb_result_indicated = true;
2182 if (status == DPP_STATUS_OK)
2183 wpas_dpp_remove_pb_hash(wpa_s);
2184 wpas_dpp_push_button_stop(wpa_s);
2185 }
2186#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002187}
2188
Hai Shalom81f62d82019-07-22 12:10:00 -07002189
Hai Shalomc3565922019-10-28 11:58:20 -07002190static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2191 const u8 *src, const u8 *hdr,
2192 const u8 *buf, size_t len)
2193{
2194 struct dpp_authentication *auth = wpa_s->dpp_auth;
2195 enum dpp_status_error status;
2196 u8 ssid[SSID_MAX_LEN];
2197 size_t ssid_len = 0;
2198 char *channel_list = NULL;
2199
2200 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2201
2202 if (!auth || !auth->waiting_conn_status_result) {
2203 wpa_printf(MSG_DEBUG,
2204 "DPP: No DPP Configuration waiting for connection status result - drop");
2205 return;
2206 }
2207
2208 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2209 ssid, &ssid_len, &channel_list);
2210 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2211 "result=%d ssid=%s channel_list=%s",
2212 status, wpa_ssid_txt(ssid, ssid_len),
2213 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002214 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2215 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002216 os_free(channel_list);
2217 offchannel_send_action_done(wpa_s);
2218 wpas_dpp_listen_stop(wpa_s);
2219 dpp_auth_deinit(auth);
2220 wpa_s->dpp_auth = NULL;
2221 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2222 wpa_s, NULL);
2223}
2224
2225
Hai Shalom81f62d82019-07-22 12:10:00 -07002226static int wpas_dpp_process_conf_obj(void *ctx,
2227 struct dpp_authentication *auth)
2228{
2229 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002230 unsigned int i;
2231 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002232
Hai Shalomc3565922019-10-28 11:58:20 -07002233 for (i = 0; i < auth->num_conf_obj; i++) {
2234 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2235 &auth->conf_obj[i]);
2236 if (res)
2237 break;
2238 }
2239 if (!res)
2240 wpas_dpp_post_process_config(wpa_s, auth);
2241
2242 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002243}
2244
Hai Shalomfdcde762020-04-02 11:19:20 -07002245
Hai Shaloma20dcd72022-02-04 13:43:00 -08002246static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2247{
2248 struct wpa_supplicant *wpa_s = ctx;
2249
2250 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2251
2252 if (auth->connect_on_tx_status) {
2253 auth->connect_on_tx_status = 0;
2254 wpa_printf(MSG_DEBUG,
2255 "DPP: Try to connect after completed configuration result");
2256 wpas_dpp_try_to_connect(wpa_s);
2257 if (auth->conn_status_requested) {
2258 wpa_printf(MSG_DEBUG,
2259 "DPP: Start 15 second timeout for reporting connection status result");
2260 eloop_cancel_timeout(
2261 wpas_dpp_conn_status_result_timeout,
2262 wpa_s, NULL);
2263 eloop_register_timeout(
2264 15, 0, wpas_dpp_conn_status_result_timeout,
2265 wpa_s, NULL);
2266 return true;
2267 }
2268 }
2269
2270 return false;
2271}
2272
2273
Hai Shalomfdcde762020-04-02 11:19:20 -07002274static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2275{
2276 struct wpa_supplicant *wpa_s = ctx;
2277
2278 if (bi == wpa_s->dpp_chirp_bi)
2279 wpas_dpp_chirp_stop(wpa_s);
2280}
2281
2282
2283static void
2284wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2285 const u8 *hdr, const u8 *buf, size_t len,
2286 unsigned int freq)
2287{
2288 const u8 *r_bootstrap;
2289 u16 r_bootstrap_len;
2290 struct dpp_bootstrap_info *peer_bi;
2291 struct dpp_authentication *auth;
2292
2293 if (!wpa_s->dpp)
2294 return;
2295
2296 if (wpa_s->dpp_auth) {
2297 wpa_printf(MSG_DEBUG,
2298 "DPP: Ignore Presence Announcement during ongoing Authentication");
2299 return;
2300 }
2301
2302 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2303 MAC2STR(src));
2304
2305 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2306 &r_bootstrap_len);
2307 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2308 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2309 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2310 return;
2311 }
2312 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2313 r_bootstrap, r_bootstrap_len);
2314 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002315 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2316 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002317 if (!peer_bi) {
2318 wpa_printf(MSG_DEBUG,
2319 "DPP: No matching bootstrapping information found");
2320 return;
2321 }
2322
2323 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2324 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2325 if (!auth)
2326 return;
2327 wpas_dpp_set_testing_options(wpa_s, auth);
2328 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2329 dpp_auth_deinit(auth);
2330 return;
2331 }
2332
2333 auth->neg_freq = freq;
2334
Hai Shalom60840252021-02-19 19:02:11 -08002335 /* The source address of the Presence Announcement frame overrides any
2336 * MAC address information from the bootstrapping information. */
2337 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002338
2339 wpa_s->dpp_auth = auth;
2340 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2341 dpp_auth_deinit(wpa_s->dpp_auth);
2342 wpa_s->dpp_auth = NULL;
2343 }
2344}
2345
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002346
2347static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2348 void *timeout_ctx)
2349{
2350 struct wpa_supplicant *wpa_s = eloop_ctx;
2351 struct dpp_authentication *auth = wpa_s->dpp_auth;
2352
2353 if (!auth)
2354 return;
2355
2356 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2357 offchannel_send_action_done(wpa_s);
2358 wpas_dpp_listen_stop(wpa_s);
2359 dpp_auth_deinit(auth);
2360 wpa_s->dpp_auth = NULL;
2361}
2362
2363
2364static void
2365wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2366 const u8 *hdr, const u8 *buf, size_t len,
2367 unsigned int freq)
2368{
Hai Shalom899fcc72020-10-19 14:38:18 -07002369 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2370 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002371 struct dpp_configurator *conf;
2372 struct dpp_authentication *auth;
2373 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002374 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002375
2376 if (!wpa_s->dpp)
2377 return;
2378
2379 if (wpa_s->dpp_auth) {
2380 wpa_printf(MSG_DEBUG,
2381 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2382 return;
2383 }
2384
2385 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2386 MAC2STR(src));
2387
2388 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2389 &csign_hash_len);
2390 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2391 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2392 "Missing or invalid required Configurator C-sign key Hash attribute");
2393 return;
2394 }
2395 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2396 csign_hash, csign_hash_len);
2397 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2398 if (!conf) {
2399 wpa_printf(MSG_DEBUG,
2400 "DPP: No matching Configurator information found");
2401 return;
2402 }
2403
Hai Shalom899fcc72020-10-19 14:38:18 -07002404 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2405 &fcgroup_len);
2406 if (!fcgroup || fcgroup_len != 2) {
2407 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2408 "Missing or invalid required Finite Cyclic Group attribute");
2409 return;
2410 }
2411 group = WPA_GET_LE16(fcgroup);
2412 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2413
2414 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2415 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2416
2417 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2418 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002419 if (!auth)
2420 return;
2421 wpas_dpp_set_testing_options(wpa_s, auth);
2422 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2423 dpp_auth_deinit(auth);
2424 return;
2425 }
2426
2427 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2428 wpa_s->dpp_auth = auth;
2429
2430 wpa_s->dpp_in_response_listen = 0;
2431 wpa_s->dpp_auth_ok_on_ack = 0;
2432 wait_time = wpa_s->max_remain_on_chan;
2433 max_wait_time = wpa_s->dpp_resp_wait_time ?
2434 wpa_s->dpp_resp_wait_time : 2000;
2435 if (wait_time > max_wait_time)
2436 wait_time = max_wait_time;
2437 wait_time += 10; /* give the driver some extra time to complete */
2438 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2439 wpas_dpp_reconfig_reply_wait_timeout,
2440 wpa_s, NULL);
2441 wait_time -= 10;
2442
2443 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2444
2445 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2446 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2447 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2448 wpabuf_head(auth->reconfig_req_msg),
2449 wpabuf_len(auth->reconfig_req_msg),
2450 wait_time, wpas_dpp_tx_status, 0) < 0) {
2451 dpp_auth_deinit(wpa_s->dpp_auth);
2452 wpa_s->dpp_auth = NULL;
2453 }
2454}
2455
2456
2457static void
2458wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2459 const u8 *hdr, const u8 *buf, size_t len,
2460 unsigned int freq)
2461{
2462 struct wpa_ssid *ssid;
2463 struct dpp_authentication *auth;
2464
2465 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2466 MACSTR, MAC2STR(src));
2467
Hai Shalom899fcc72020-10-19 14:38:18 -07002468 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002469 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002470 if (wpa_s->dpp_auth) {
2471 wpa_printf(MSG_DEBUG,
2472 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2473 return;
2474 }
2475 if (!wpa_s->dpp_reconfig_ssid) {
2476 wpa_printf(MSG_DEBUG,
2477 "DPP: Not ready for reconfiguration - not requested");
2478 return;
2479 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002480 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2481 if (ssid == wpa_s->dpp_reconfig_ssid &&
2482 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2483 break;
2484 }
2485 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002486 !ssid->dpp_csign) {
2487 wpa_printf(MSG_DEBUG,
2488 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002489 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002490 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002491
2492 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2493 ssid->dpp_netaccesskey,
2494 ssid->dpp_netaccesskey_len,
2495 ssid->dpp_csign, ssid->dpp_csign_len,
2496 freq, hdr, buf, len);
2497 if (!auth)
2498 return;
2499 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2500 wpa_s->dpp_auth = auth;
2501
2502 wpas_dpp_chirp_stop(wpa_s);
2503
2504 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2505 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2506 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2507 wpabuf_head(auth->reconfig_resp_msg),
2508 wpabuf_len(auth->reconfig_resp_msg),
2509 500, wpas_dpp_tx_status, 0) < 0) {
2510 dpp_auth_deinit(wpa_s->dpp_auth);
2511 wpa_s->dpp_auth = NULL;
2512 }
2513}
2514
2515
2516static void
2517wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2518 const u8 *hdr, const u8 *buf, size_t len,
2519 unsigned int freq)
2520{
2521 struct dpp_authentication *auth = wpa_s->dpp_auth;
2522 struct wpabuf *conf;
2523
2524 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2525 MACSTR, MAC2STR(src));
2526
2527 if (!auth || !auth->reconfig || !auth->configurator) {
2528 wpa_printf(MSG_DEBUG,
2529 "DPP: No DPP Reconfig Authentication in progress - drop");
2530 return;
2531 }
2532
2533 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2534 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2535 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2536 return;
2537 }
2538
2539 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2540 if (!conf)
2541 return;
2542
2543 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2544
2545 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2546 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2547 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2548 wpabuf_head(conf), wpabuf_len(conf),
2549 500, wpas_dpp_tx_status, 0) < 0) {
2550 wpabuf_free(conf);
2551 dpp_auth_deinit(wpa_s->dpp_auth);
2552 wpa_s->dpp_auth = NULL;
2553 return;
2554 }
2555 wpabuf_free(conf);
2556
2557 wpas_dpp_start_gas_server(wpa_s);
2558}
2559
2560
2561static void
2562wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2563 const u8 *hdr, const u8 *buf, size_t len,
2564 unsigned int freq)
2565{
2566 struct dpp_authentication *auth = wpa_s->dpp_auth;
2567
2568 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2569 MACSTR, MAC2STR(src));
2570
2571 if (!auth || !auth->reconfig || auth->configurator) {
2572 wpa_printf(MSG_DEBUG,
2573 "DPP: No DPP Reconfig Authentication in progress - drop");
2574 return;
2575 }
2576
2577 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2578 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2579 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2580 return;
2581 }
2582
2583 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2584 return;
2585
2586 wpas_dpp_start_gas_client(wpa_s);
2587}
2588
Hai Shalom021b0b52019-04-10 11:17:58 -07002589#endif /* CONFIG_DPP2 */
2590
2591
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002592static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2593 const u8 *src,
2594 const u8 *buf, size_t len)
2595{
2596 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002597 const u8 *connector, *trans_id, *status;
2598 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002599#ifdef CONFIG_DPP2
2600 const u8 *version;
2601 u16 version_len;
2602#endif /* CONFIG_DPP2 */
2603 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002604 struct dpp_introduction intro;
2605 struct rsn_pmksa_cache_entry *entry;
2606 struct os_time now;
2607 struct os_reltime rnow;
2608 os_time_t expiry;
2609 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002610 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002611
2612 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2613 MAC2STR(src));
2614 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2615 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2616 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2617 MACSTR " - drop", MAC2STR(src));
2618 return;
2619 }
2620 offchannel_send_action_done(wpa_s);
2621
2622 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2623 if (ssid == wpa_s->dpp_intro_network)
2624 break;
2625 }
2626 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2627 !ssid->dpp_csign) {
2628 wpa_printf(MSG_DEBUG,
2629 "DPP: Profile not found for network introduction");
2630 return;
2631 }
2632
2633 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2634 &trans_id_len);
2635 if (!trans_id || trans_id_len != 1) {
2636 wpa_printf(MSG_DEBUG,
2637 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002638 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2639 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002640 goto fail;
2641 }
2642 if (trans_id[0] != TRANSACTION_ID) {
2643 wpa_printf(MSG_DEBUG,
2644 "DPP: Ignore frame with unexpected Transaction ID %u",
2645 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002646 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2647 " fail=transaction_id_mismatch", MAC2STR(src));
2648 goto fail;
2649 }
2650
2651 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2652 if (!status || status_len != 1) {
2653 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2654 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2655 " fail=missing_status", MAC2STR(src));
2656 goto fail;
2657 }
2658 if (status[0] != DPP_STATUS_OK) {
2659 wpa_printf(MSG_DEBUG,
2660 "DPP: Peer rejected network introduction: Status %u",
2661 status[0]);
2662 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2663 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002664#ifdef CONFIG_DPP2
2665 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2666#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002667 goto fail;
2668 }
2669
2670 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2671 if (!connector) {
2672 wpa_printf(MSG_DEBUG,
2673 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002674 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2675 " fail=missing_connector", MAC2STR(src));
2676 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002677 }
2678
Roshan Pius3a1667e2018-07-03 15:17:14 -07002679 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2680 ssid->dpp_netaccesskey,
2681 ssid->dpp_netaccesskey_len,
2682 ssid->dpp_csign,
2683 ssid->dpp_csign_len,
2684 connector, connector_len, &expiry);
2685 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002686 wpa_printf(MSG_INFO,
2687 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002688 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2689 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002690#ifdef CONFIG_DPP2
2691 wpas_dpp_send_conn_status_result(wpa_s, res);
2692#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002693 goto fail;
2694 }
2695
2696 entry = os_zalloc(sizeof(*entry));
2697 if (!entry)
2698 goto fail;
2699 os_memcpy(entry->aa, src, ETH_ALEN);
2700 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2701 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2702 entry->pmk_len = intro.pmk_len;
2703 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002704#ifdef CONFIG_DPP2
2705 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2706 &version_len);
2707 if (version && version_len >= 1)
2708 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002709#ifdef CONFIG_DPP3
2710 if (intro.peer_version && intro.peer_version >= 2 &&
2711 peer_version != intro.peer_version) {
2712 wpa_printf(MSG_INFO,
2713 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2714 intro.peer_version, peer_version);
2715 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2716 goto fail;
2717 }
2718#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002719 entry->dpp_pfs = peer_version >= 2;
2720#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002721 if (expiry) {
2722 os_get_time(&now);
2723 seconds = expiry - now.sec;
2724 } else {
2725 seconds = 86400 * 7;
2726 }
2727 os_get_reltime(&rnow);
2728 entry->expiration = rnow.sec + seconds;
2729 entry->reauth_time = rnow.sec + seconds;
2730 entry->network_ctx = ssid;
2731 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2732
Roshan Pius3a1667e2018-07-03 15:17:14 -07002733 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002734 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002735
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002736 wpa_printf(MSG_DEBUG,
2737 "DPP: Try connection again after successful network introduction");
2738 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2739 wpa_supplicant_cancel_sched_scan(wpa_s);
2740 wpa_supplicant_req_scan(wpa_s, 0, 0);
2741 }
2742fail:
2743 os_memset(&intro, 0, sizeof(intro));
2744}
2745
2746
Roshan Pius3a1667e2018-07-03 15:17:14 -07002747static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2748{
2749 int i, j;
2750
2751 if (!wpa_s->hw.modes)
2752 return -1;
2753
2754 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2755 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2756
2757 for (j = 0; j < mode->num_channels; j++) {
2758 struct hostapd_channel_data *chan = &mode->channels[j];
2759
2760 if (chan->freq != (int) freq)
2761 continue;
2762
2763 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2764 HOSTAPD_CHAN_NO_IR |
2765 HOSTAPD_CHAN_RADAR))
2766 continue;
2767
2768 return 1;
2769 }
2770 }
2771
2772 wpa_printf(MSG_DEBUG,
2773 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2774 freq);
2775
2776 return 0;
2777}
2778
2779
2780static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2781 struct dpp_pkex *pkex)
2782{
2783 if (pkex->freq == 2437)
2784 pkex->freq = 5745;
2785 else if (pkex->freq == 5745)
2786 pkex->freq = 5220;
2787 else if (pkex->freq == 5220)
2788 pkex->freq = 60480;
2789 else
2790 return -1; /* no more channels to try */
2791
2792 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2793 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2794 pkex->freq);
2795 return 0;
2796 }
2797
2798 /* Could not use this channel - try the next one */
2799 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2800}
2801
2802
Sunil Ravi89eba102022-09-13 21:04:37 -07002803static void wpas_dpp_pkex_clear_code(struct wpa_supplicant *wpa_s)
2804{
2805 if (!wpa_s->dpp_pkex_code && !wpa_s->dpp_pkex_identifier)
2806 return;
2807
2808 /* Delete PKEX code and identifier on successful completion of
2809 * PKEX. We are not supposed to reuse these without being
2810 * explicitly requested to perform PKEX again. */
2811 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
2812 os_free(wpa_s->dpp_pkex_code);
2813 wpa_s->dpp_pkex_code = NULL;
2814 os_free(wpa_s->dpp_pkex_identifier);
2815 wpa_s->dpp_pkex_identifier = NULL;
2816
2817}
2818
2819
Hai Shaloma20dcd72022-02-04 13:43:00 -08002820#ifdef CONFIG_DPP2
2821static int wpas_dpp_pkex_done(void *ctx, void *conn,
2822 struct dpp_bootstrap_info *peer_bi)
2823{
2824 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -07002825 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002826 const char *pos;
2827 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2828 struct dpp_bootstrap_info *own_bi = NULL;
2829 struct dpp_authentication *auth;
2830
Sunil Ravi89eba102022-09-13 21:04:37 -07002831 wpas_dpp_pkex_clear_code(wpa_s);
2832
2833 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
2834 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002835 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
2836 cmd);
2837
2838 pos = os_strstr(cmd, " own=");
2839 if (pos) {
2840 pos += 5;
2841 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
2842 if (!own_bi) {
2843 wpa_printf(MSG_INFO,
2844 "DPP: Could not find bootstrapping info for the identified local entry");
2845 return -1;
2846 }
2847
2848 if (peer_bi->curve != own_bi->curve) {
2849 wpa_printf(MSG_INFO,
2850 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
2851 peer_bi->curve->name, own_bi->curve->name);
2852 return -1;
2853 }
2854 }
2855
2856 pos = os_strstr(cmd, " role=");
2857 if (pos) {
2858 pos += 6;
2859 if (os_strncmp(pos, "configurator", 12) == 0)
2860 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2861 else if (os_strncmp(pos, "enrollee", 8) == 0)
2862 allowed_roles = DPP_CAPAB_ENROLLEE;
2863 else if (os_strncmp(pos, "either", 6) == 0)
2864 allowed_roles = DPP_CAPAB_CONFIGURATOR |
2865 DPP_CAPAB_ENROLLEE;
2866 else
2867 return -1;
2868 }
2869
2870 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
2871 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
2872 if (!auth)
2873 return -1;
2874
2875 wpas_dpp_set_testing_options(wpa_s, auth);
2876 if (dpp_set_configurator(auth, cmd) < 0) {
2877 dpp_auth_deinit(auth);
2878 return -1;
2879 }
2880
2881 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -07002882 DPP_NETROLE_STA,
2883 wpa_s->conf->dpp_mud_url,
2884 wpa_s->conf->dpp_extra_conf_req_name,
2885 wpa_s->conf->dpp_extra_conf_req_value,
2886 wpas_dpp_process_conf_obj,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002887 wpas_dpp_tcp_msg_sent);
2888}
2889#endif /* CONFIG_DPP2 */
2890
2891
Hai Shaloma20dcd72022-02-04 13:43:00 -08002892static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07002893 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002894 const struct hostapd_ip_addr *ipaddr,
2895 int tcp_port)
2896{
2897 struct dpp_pkex *pkex;
2898 struct wpabuf *msg;
2899 unsigned int wait_time;
2900 bool v2 = ver != PKEX_VER_ONLY_1;
2901
2902 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
2903 dpp_pkex_free(wpa_s->dpp_pkex);
2904 wpa_s->dpp_pkex = NULL;
2905 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
2906 wpa_s->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -07002907 wpa_s->dpp_pkex_code, wpa_s->dpp_pkex_code_len,
2908 v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002909 if (!pkex)
2910 return -1;
2911 pkex->forced_ver = ver != PKEX_VER_AUTO;
2912
2913 if (ipaddr) {
2914#ifdef CONFIG_DPP2
2915 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
2916 wpa_s, wpa_s, wpas_dpp_pkex_done);
2917#else /* CONFIG_DPP2 */
2918 return -1;
2919#endif /* CONFIG_DPP2 */
2920 }
2921
2922 wpa_s->dpp_pkex = pkex;
2923 msg = pkex->exchange_req;
2924 wait_time = wpa_s->max_remain_on_chan;
2925 if (wait_time > 2000)
2926 wait_time = 2000;
2927 pkex->freq = 2437;
2928 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2929 " freq=%u type=%d",
2930 MAC2STR(broadcast), pkex->freq,
2931 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2932 DPP_PA_PKEX_V1_EXCHANGE_REQ);
2933 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2934 wpa_s->own_addr, broadcast,
2935 wpabuf_head(msg), wpabuf_len(msg),
2936 wait_time, wpas_dpp_tx_pkex_status, 0);
2937 if (wait_time == 0)
2938 wait_time = 2000;
2939 pkex->exch_req_wait_time = wait_time;
2940 pkex->exch_req_tries = 1;
2941
2942 return 0;
2943}
2944
2945
Roshan Pius3a1667e2018-07-03 15:17:14 -07002946static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
2947{
2948 struct wpa_supplicant *wpa_s = eloop_ctx;
2949 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2950
2951 if (!pkex || !pkex->exchange_req)
2952 return;
2953 if (pkex->exch_req_tries >= 5) {
2954 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002955#ifdef CONFIG_DPP3
2956 if (pkex->v2 && !pkex->forced_ver) {
2957 wpa_printf(MSG_DEBUG,
2958 "DPP: Fall back to PKEXv1");
2959 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
2960 NULL, 0);
2961 return;
2962 }
2963#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002964 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2965 "No response from PKEX peer");
2966 dpp_pkex_free(pkex);
2967 wpa_s->dpp_pkex = NULL;
2968 return;
2969 }
2970 pkex->exch_req_tries = 0;
2971 }
2972
2973 pkex->exch_req_tries++;
2974 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
2975 pkex->exch_req_tries);
2976 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08002977 MAC2STR(broadcast), pkex->freq,
2978 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2979 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002980 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2981 wpa_s->own_addr, broadcast,
2982 wpabuf_head(pkex->exchange_req),
2983 wpabuf_len(pkex->exchange_req),
2984 pkex->exch_req_wait_time,
2985 wpas_dpp_tx_pkex_status, 0);
2986}
2987
2988
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002989static void
2990wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
2991 unsigned int freq, const u8 *dst,
2992 const u8 *src, const u8 *bssid,
2993 const u8 *data, size_t data_len,
2994 enum offchannel_send_action_result result)
2995{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002996 const char *res_txt;
2997 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2998
2999 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3000 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3001 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003002 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3003 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003004 freq, MAC2STR(dst), res_txt);
3005 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3006 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3007
3008 if (!pkex) {
3009 wpa_printf(MSG_DEBUG,
3010 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
3011 return;
3012 }
3013
3014 if (pkex->failed) {
3015 wpa_printf(MSG_DEBUG,
3016 "DPP: Terminate PKEX exchange due to an earlier error");
3017 if (pkex->t > pkex->own_bi->pkex_t)
3018 pkex->own_bi->pkex_t = pkex->t;
3019 dpp_pkex_free(pkex);
3020 wpa_s->dpp_pkex = NULL;
3021 return;
3022 }
3023
3024 if (pkex->exch_req_wait_time && pkex->exchange_req) {
3025 /* Wait for PKEX Exchange Response frame and retry request if
3026 * no response is seen. */
3027 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3028 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
3029 (pkex->exch_req_wait_time % 1000) * 1000,
3030 wpas_dpp_pkex_retry_timeout, wpa_s,
3031 NULL);
3032 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003033}
3034
3035
3036static void
3037wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003038 const u8 *buf, size_t len, unsigned int freq,
3039 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003040{
3041 struct wpabuf *msg;
3042 unsigned int wait_time;
3043
3044 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
3045 MAC2STR(src));
3046
Sunil Ravia04bd252022-05-02 22:54:18 -07003047 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
3048 wpa_printf(MSG_DEBUG,
3049 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
3050 return;
3051 }
3052 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
3053 wpa_printf(MSG_DEBUG,
3054 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
3055 return;
3056 }
3057
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003058 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3059 * values here */
3060
3061 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
3062 wpa_printf(MSG_DEBUG,
3063 "DPP: No PKEX code configured - ignore request");
3064 return;
3065 }
3066
Sunil Ravi89eba102022-09-13 21:04:37 -07003067#ifdef CONFIG_DPP2
3068 if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) {
3069 wpa_printf(MSG_DEBUG,
3070 "DPP: PKEX Exchange Request is from local Controller - ignore request");
3071 return;
3072 }
3073#endif /* CONFIG_DPP2 */
3074
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003075 if (wpa_s->dpp_pkex) {
3076 /* TODO: Support parallel operations */
3077 wpa_printf(MSG_DEBUG,
3078 "DPP: Already in PKEX session - ignore new request");
3079 return;
3080 }
3081
Roshan Pius3a1667e2018-07-03 15:17:14 -07003082 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003083 wpa_s->own_addr, src,
3084 wpa_s->dpp_pkex_identifier,
3085 wpa_s->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07003086 wpa_s->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003087 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003088 if (!wpa_s->dpp_pkex) {
3089 wpa_printf(MSG_DEBUG,
3090 "DPP: Failed to process the request - ignore it");
3091 return;
3092 }
3093
Sunil Ravi89eba102022-09-13 21:04:37 -07003094#ifdef CONFIG_DPP3
3095 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_announcement) {
3096 wpa_printf(MSG_DEBUG,
3097 "DPP: Started PB PKEX (no more PB announcements)");
3098 wpabuf_free(wpa_s->dpp_pb_announcement);
3099 wpa_s->dpp_pb_announcement = NULL;
3100 }
3101#endif /* CONFIG_DPP3 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003102 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003103 msg = wpa_s->dpp_pkex->exchange_resp;
3104 wait_time = wpa_s->max_remain_on_chan;
3105 if (wait_time > 2000)
3106 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003107 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3108 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003109 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3110 broadcast,
3111 wpabuf_head(msg), wpabuf_len(msg),
3112 wait_time, wpas_dpp_tx_pkex_status, 0);
3113}
3114
3115
3116static void
3117wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3118 const u8 *buf, size_t len, unsigned int freq)
3119{
3120 struct wpabuf *msg;
3121 unsigned int wait_time;
3122
3123 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
3124 MAC2STR(src));
3125
3126 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3127 * values here */
3128
3129 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3130 wpa_s->dpp_pkex->exchange_done) {
3131 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3132 return;
3133 }
3134
Roshan Pius3a1667e2018-07-03 15:17:14 -07003135 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3136 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3137
3138 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003139 if (!msg) {
3140 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3141 return;
3142 }
3143
3144 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3145 MAC2STR(src));
3146
3147 wait_time = wpa_s->max_remain_on_chan;
3148 if (wait_time > 2000)
3149 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003150 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3151 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003152 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3153 broadcast,
3154 wpabuf_head(msg), wpabuf_len(msg),
3155 wait_time, wpas_dpp_tx_pkex_status, 0);
3156 wpabuf_free(msg);
3157}
3158
3159
Roshan Pius3a1667e2018-07-03 15:17:14 -07003160static struct dpp_bootstrap_info *
3161wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3162 unsigned int freq)
3163{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003164 struct dpp_bootstrap_info *bi;
3165
Sunil Ravi89eba102022-09-13 21:04:37 -07003166 wpas_dpp_pkex_clear_code(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003167 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003168 if (!bi)
3169 return NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003170
Roshan Pius3a1667e2018-07-03 15:17:14 -07003171 wpa_s->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003172
3173#ifdef CONFIG_DPP3
3174 if (wpa_s->dpp_pb_bi && !wpa_s->dpp_pb_configurator &&
3175 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_init_hash,
3176 SHA256_MAC_LEN) != 0) {
3177 char id[20];
3178
3179 wpa_printf(MSG_INFO,
3180 "DPP: Peer bootstrap key from PKEX does not match PB announcement response hash");
3181 wpa_hexdump(MSG_DEBUG,
3182 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3183 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3184 wpa_hexdump(MSG_DEBUG,
3185 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement response",
3186 wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN);
3187
3188 os_snprintf(id, sizeof(id), "%u", bi->id);
3189 dpp_bootstrap_remove(wpa_s->dpp, id);
3190 wpas_dpp_push_button_stop(wpa_s);
3191 return NULL;
3192 }
3193#endif /* CONFIG_DPP3 */
3194
Roshan Pius3a1667e2018-07-03 15:17:14 -07003195 return bi;
3196}
3197
3198
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003199static void
3200wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3201 const u8 *hdr, const u8 *buf, size_t len,
3202 unsigned int freq)
3203{
3204 struct wpabuf *msg;
3205 unsigned int wait_time;
3206 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003207
3208 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3209 MAC2STR(src));
3210
3211 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3212 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3213 return;
3214 }
3215
3216 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3217 if (!msg) {
3218 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003219 if (pkex->failed) {
3220 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3221 if (pkex->t > pkex->own_bi->pkex_t)
3222 pkex->own_bi->pkex_t = pkex->t;
3223 dpp_pkex_free(wpa_s->dpp_pkex);
3224 wpa_s->dpp_pkex = NULL;
3225 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003226 return;
3227 }
3228
3229 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3230 MACSTR, MAC2STR(src));
3231
3232 wait_time = wpa_s->max_remain_on_chan;
3233 if (wait_time > 2000)
3234 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003235 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3236 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003237 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3238 broadcast,
3239 wpabuf_head(msg), wpabuf_len(msg),
3240 wait_time, wpas_dpp_tx_pkex_status, 0);
3241 wpabuf_free(msg);
3242
Roshan Pius3a1667e2018-07-03 15:17:14 -07003243 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003244 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003245}
3246
3247
3248static void
3249wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3250 const u8 *hdr, const u8 *buf, size_t len,
3251 unsigned int freq)
3252{
3253 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003254 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003255 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3256 char cmd[500];
3257
3258 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3259 MAC2STR(src));
3260
3261 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3262 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3263 return;
3264 }
3265
3266 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3267 if (res < 0) {
3268 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3269 return;
3270 }
3271
Roshan Pius3a1667e2018-07-03 15:17:14 -07003272 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003273 if (!bi)
3274 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003275
Sunil Ravi89eba102022-09-13 21:04:37 -07003276#ifdef CONFIG_DPP3
3277 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_configurator &&
3278 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_resp_hash,
3279 SHA256_MAC_LEN) != 0) {
3280 char id[20];
3281
3282 wpa_printf(MSG_INFO,
3283 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
3284 wpa_hexdump(MSG_DEBUG,
3285 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3286 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3287 wpa_hexdump(MSG_DEBUG,
3288 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
3289 wpa_s->dpp_pb_resp_hash, SHA256_MAC_LEN);
3290
3291 os_snprintf(id, sizeof(id), "%u", bi->id);
3292 dpp_bootstrap_remove(wpa_s->dpp, id);
3293 wpas_dpp_push_button_stop(wpa_s);
3294 return;
3295 }
3296#endif /* CONFIG_DPP3 */
3297
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003298 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3299 bi->id,
3300 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3301 wpa_printf(MSG_DEBUG,
3302 "DPP: Start authentication after PKEX with parameters: %s",
3303 cmd);
3304 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3305 wpa_printf(MSG_DEBUG,
3306 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003307 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003308 return;
3309 }
3310}
3311
3312
Sunil Ravi89eba102022-09-13 21:04:37 -07003313#ifdef CONFIG_DPP3
3314
3315static void wpas_dpp_pb_pkex_init(struct wpa_supplicant *wpa_s,
3316 unsigned int freq, const u8 *src,
3317 const u8 *r_hash)
3318{
3319 struct dpp_pkex *pkex;
3320 struct wpabuf *msg;
3321 unsigned int wait_time;
3322 size_t len;
3323
3324 if (wpa_s->dpp_pkex) {
3325 wpa_printf(MSG_DEBUG,
3326 "DPP: Sending previously generated PKEX Exchange Request to "
3327 MACSTR, MAC2STR(src));
3328 msg = wpa_s->dpp_pkex->exchange_req;
3329 wait_time = wpa_s->max_remain_on_chan;
3330 if (wait_time > 2000)
3331 wait_time = 2000;
3332 offchannel_send_action(wpa_s, freq, src,
3333 wpa_s->own_addr, broadcast,
3334 wpabuf_head(msg), wpabuf_len(msg),
3335 wait_time, wpas_dpp_tx_pkex_status, 0);
3336 return;
3337 }
3338
3339 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
3340 MACSTR, MAC2STR(src));
3341
3342 if (!wpa_s->dpp_pb_cmd) {
3343 wpa_printf(MSG_INFO,
3344 "DPP: No configuration to provision as push button Configurator");
3345 wpas_dpp_push_button_stop(wpa_s);
3346 return;
3347 }
3348
3349 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
3350 os_memcpy(wpa_s->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
3351
3352 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3353 "PBPKEX", (const char *) wpa_s->dpp_pb_c_nonce,
3354 wpa_s->dpp_pb_bi->curve->nonce_len,
3355 true);
3356 if (!pkex) {
3357 wpas_dpp_push_button_stop(wpa_s);
3358 return;
3359 }
3360 pkex->freq = freq;
3361
3362 wpa_s->dpp_pkex = pkex;
3363 msg = wpa_s->dpp_pkex->exchange_req;
3364 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3365 " freq=%u type=%d", MAC2STR(src), freq,
3366 DPP_PA_PKEX_EXCHANGE_REQ);
3367 wait_time = wpa_s->max_remain_on_chan;
3368 if (wait_time > 2000)
3369 wait_time = 2000;
3370 offchannel_send_action(wpa_s, pkex->freq, src,
3371 wpa_s->own_addr, broadcast,
3372 wpabuf_head(msg), wpabuf_len(msg),
3373 wait_time, wpas_dpp_tx_pkex_status, 0);
3374 pkex->exch_req_wait_time = 2000;
3375 pkex->exch_req_tries = 1;
3376
3377 /* Use the externally provided configuration */
3378 os_free(wpa_s->dpp_pkex_auth_cmd);
3379 len = 30 + os_strlen(wpa_s->dpp_pb_cmd);
3380 wpa_s->dpp_pkex_auth_cmd = os_malloc(len);
3381 if (wpa_s->dpp_pkex_auth_cmd)
3382 os_snprintf(wpa_s->dpp_pkex_auth_cmd, len, " own=%d %s",
3383 wpa_s->dpp_pkex_bi->id, wpa_s->dpp_pb_cmd);
3384 else
3385 wpas_dpp_push_button_stop(wpa_s);
3386}
3387
3388
3389static void
3390wpas_dpp_rx_pb_presence_announcement(struct wpa_supplicant *wpa_s,
3391 const u8 *src, const u8 *hdr,
3392 const u8 *buf, size_t len,
3393 unsigned int freq)
3394{
3395 const u8 *r_hash;
3396 u16 r_hash_len;
3397 unsigned int i;
3398 bool found = false;
3399 struct dpp_pb_info *info, *tmp;
3400 struct os_reltime now, age;
3401 struct wpabuf *msg;
3402
3403 os_get_reltime(&now);
3404 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
3405 MACSTR, MAC2STR(src));
3406
3407 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3408 &r_hash_len);
3409 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
3410 wpa_printf(MSG_DEBUG,
3411 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
3412 return;
3413 }
3414 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3415 r_hash, r_hash_len);
3416
3417 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3418 info = &wpa_s->dpp_pb[i];
3419 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
3420 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
3421 continue;
3422 wpa_printf(MSG_DEBUG,
3423 "DPP: Active push button Enrollee already known");
3424 found = true;
3425 info->rx_time = now;
3426 }
3427
3428 if (!found) {
3429 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3430 tmp = &wpa_s->dpp_pb[i];
3431 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
3432 continue;
3433
3434 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
3435 wpa_hexdump(MSG_DEBUG,
3436 "DPP: Push button Enrollee hash expired",
3437 tmp->hash, SHA256_MAC_LEN);
3438 tmp->rx_time.sec = 0;
3439 tmp->rx_time.usec = 0;
3440 continue;
3441 }
3442
3443 wpa_hexdump(MSG_DEBUG,
3444 "DPP: Push button session overlap with hash",
3445 tmp->hash, SHA256_MAC_LEN);
3446 if (!wpa_s->dpp_pb_result_indicated &&
3447 wpas_dpp_pb_active(wpa_s)) {
3448 wpa_msg(wpa_s, MSG_INFO,
3449 DPP_EVENT_PB_RESULT "session-overlap");
3450 wpa_s->dpp_pb_result_indicated = true;
3451 }
3452 wpas_dpp_push_button_stop(wpa_s);
3453 return;
3454 }
3455
3456 /* Replace the oldest entry */
3457 info = &wpa_s->dpp_pb[0];
3458 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
3459 tmp = &wpa_s->dpp_pb[i];
3460 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
3461 info = tmp;
3462 }
3463 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
3464 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
3465 info->rx_time = now;
3466 }
3467
3468 if (!wpas_dpp_pb_active(wpa_s)) {
3469 wpa_printf(MSG_DEBUG,
3470 "DPP: Discard message since own push button has not been pressed");
3471 return;
3472 }
3473
3474 if (wpa_s->dpp_pb_announce_time.sec == 0 &&
3475 wpa_s->dpp_pb_announce_time.usec == 0) {
3476 /* Start a wait before allowing PKEX to be initiated */
3477 wpa_s->dpp_pb_announce_time = now;
3478 }
3479
3480 if (!wpa_s->dpp_pb_bi) {
3481 int res;
3482
3483 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
3484 if (res < 0)
3485 return;
3486 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
3487 if (!wpa_s->dpp_pb_bi)
3488 return;
3489
3490 if (random_get_bytes(wpa_s->dpp_pb_c_nonce,
3491 wpa_s->dpp_pb_bi->curve->nonce_len)) {
3492 wpa_printf(MSG_ERROR,
3493 "DPP: Failed to generate C-nonce");
3494 wpas_dpp_push_button_stop(wpa_s);
3495 return;
3496 }
3497 }
3498
3499 /* Skip the response if one was sent within last 50 ms since the
3500 * Enrollee is going to send out at least three announcement messages.
3501 */
3502 os_reltime_sub(&now, &wpa_s->dpp_pb_last_resp, &age);
3503 if (age.sec == 0 && age.usec < 50000) {
3504 wpa_printf(MSG_DEBUG,
3505 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
3506 return;
3507 }
3508
3509 msg = dpp_build_pb_announcement_resp(
3510 wpa_s->dpp_pb_bi, r_hash, wpa_s->dpp_pb_c_nonce,
3511 wpa_s->dpp_pb_bi->curve->nonce_len);
3512 if (!msg) {
3513 wpas_dpp_push_button_stop(wpa_s);
3514 return;
3515 }
3516
3517 wpa_printf(MSG_DEBUG,
3518 "DPP: Send Push Button Presence Announcement Response to "
3519 MACSTR, MAC2STR(src));
3520 wpa_s->dpp_pb_last_resp = now;
3521
3522 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3523 MAC2STR(src), freq, DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
3524 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
3525 wpabuf_head(msg), wpabuf_len(msg),
3526 0, NULL, 0);
3527 wpabuf_free(msg);
3528
3529 if (os_reltime_expired(&now, &wpa_s->dpp_pb_announce_time, 15))
3530 wpas_dpp_pb_pkex_init(wpa_s, freq, src, r_hash);
3531}
3532
3533
3534static void
3535wpas_dpp_rx_pb_presence_announcement_resp(struct wpa_supplicant *wpa_s,
3536 const u8 *src, const u8 *hdr,
3537 const u8 *buf, size_t len,
3538 unsigned int freq)
3539{
3540 const u8 *i_hash, *r_hash, *c_nonce;
3541 u16 i_hash_len, r_hash_len, c_nonce_len;
3542 bool overlap = false;
3543
3544 if (!wpa_s->dpp_pb_announcement || !wpa_s->dpp_pb_bi ||
3545 wpa_s->dpp_pb_configurator) {
3546 wpa_printf(MSG_INFO,
3547 "DPP: Not in active push button Enrollee mode - discard Push Button Presence Announcement Response from "
3548 MACSTR, MAC2STR(src));
3549 return;
3550 }
3551
3552 wpa_printf(MSG_DEBUG,
3553 "DPP: Push Button Presence Announcement Response from "
3554 MACSTR, MAC2STR(src));
3555
3556 i_hash = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3557 &i_hash_len);
3558 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3559 &r_hash_len);
3560 c_nonce = dpp_get_attr(buf, len, DPP_ATTR_CONFIGURATOR_NONCE,
3561 &c_nonce_len);
3562 if (!i_hash || i_hash_len != SHA256_MAC_LEN ||
3563 !r_hash || r_hash_len != SHA256_MAC_LEN ||
3564 !c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
3565 wpa_printf(MSG_DEBUG,
3566 "DPP: Missing or invalid required attribute");
3567 return;
3568 }
3569 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
3570 i_hash, i_hash_len);
3571 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3572 r_hash, r_hash_len);
3573 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator Nonce",
3574 c_nonce, c_nonce_len);
3575
3576#ifdef CONFIG_TESTING_OPTIONS
3577 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ &&
3578 os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3579 SHA256_MAC_LEN - 1) == 0)
3580 goto skip_hash_check;
3581#endif /* CONFIG_TESTING_OPTIONS */
3582 if (os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3583 SHA256_MAC_LEN) != 0) {
3584 wpa_printf(MSG_INFO,
3585 "DPP: Unexpected push button Responder hash - abort");
3586 overlap = true;
3587 }
3588#ifdef CONFIG_TESTING_OPTIONS
3589skip_hash_check:
3590#endif /* CONFIG_TESTING_OPTIONS */
3591
3592 if (wpa_s->dpp_pb_resp_freq &&
3593 os_memcmp(i_hash, wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN) != 0) {
3594 wpa_printf(MSG_INFO,
3595 "DPP: Push button session overlap detected - abort");
3596 overlap = true;
3597 }
3598
3599 if (overlap) {
3600 if (!wpa_s->dpp_pb_result_indicated) {
3601 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
3602 "session-overlap");
3603 wpa_s->dpp_pb_result_indicated = true;
3604 }
3605 wpas_dpp_push_button_stop(wpa_s);
3606 return;
3607 }
3608
3609 if (!wpa_s->dpp_pb_resp_freq) {
3610 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
3611 "discovered push button AP/Configurator " MACSTR,
3612 MAC2STR(src));
3613 wpa_s->dpp_pb_resp_freq = freq;
3614 os_memcpy(wpa_s->dpp_pb_init_hash, i_hash, SHA256_MAC_LEN);
3615 os_memcpy(wpa_s->dpp_pb_c_nonce, c_nonce, c_nonce_len);
3616 wpa_s->dpp_pb_c_nonce_len = c_nonce_len;
3617 /* Stop announcement iterations after at least one more full
3618 * round and one extra round for postponed session overlap
3619 * detection. */
3620 wpa_s->dpp_pb_stop_iter = 3;
3621 }
3622}
3623
3624
3625static void
3626wpas_dpp_tx_priv_intro_status(struct wpa_supplicant *wpa_s,
3627 unsigned int freq, const u8 *dst,
3628 const u8 *src, const u8 *bssid,
3629 const u8 *data, size_t data_len,
3630 enum offchannel_send_action_result result)
3631{
3632 const char *res_txt;
3633
3634 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3635 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3636 "FAILED");
3637 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3638 " result=%s (DPP Private Peer Introduction Update)",
3639 freq, MAC2STR(dst), res_txt);
3640 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3641 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3642
3643 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR " version=%u",
3644 MAC2STR(src), wpa_s->dpp_intro_peer_version);
3645
3646 wpa_printf(MSG_DEBUG,
3647 "DPP: Try connection again after successful network introduction");
3648 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3649 wpa_supplicant_cancel_sched_scan(wpa_s);
3650 wpa_supplicant_req_scan(wpa_s, 0, 0);
3651 }
3652}
3653
3654
3655static int
3656wpas_dpp_send_private_peer_intro_update(struct wpa_supplicant *wpa_s,
3657 struct dpp_introduction *intro,
3658 struct wpa_ssid *ssid,
3659 const u8 *dst, unsigned int freq)
3660{
3661 struct wpabuf *pt, *msg, *enc_ct;
3662 size_t len;
3663 u8 ver = DPP_VERSION;
3664 int conn_ver;
3665 const u8 *aad;
3666 size_t aad_len;
3667 unsigned int wait_time;
3668
3669 wpa_printf(MSG_DEBUG, "HPKE(kem_id=%u kdf_id=%u aead_id=%u)",
3670 intro->kem_id, intro->kdf_id, intro->aead_id);
3671
3672 /* Plaintext for HPKE */
3673 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3674 pt = wpabuf_alloc(len);
3675 if (!pt)
3676 return -1;
3677
3678 /* Protocol Version */
3679 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3680 if (conn_ver > 0 && ver != conn_ver) {
3681 wpa_printf(MSG_DEBUG,
3682 "DPP: Use Connector version %d instead of current protocol version %d",
3683 conn_ver, ver);
3684 ver = conn_ver;
3685 }
3686 wpabuf_put_le16(pt, DPP_ATTR_PROTOCOL_VERSION);
3687 wpabuf_put_le16(pt, 1);
3688 wpabuf_put_u8(pt, ver);
3689
3690 /* Connector */
3691 wpabuf_put_le16(pt, DPP_ATTR_CONNECTOR);
3692 wpabuf_put_le16(pt, os_strlen(ssid->dpp_connector));
3693 wpabuf_put_str(pt, ssid->dpp_connector);
3694 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Plaintext for HPKE", pt);
3695
3696 /* HPKE(pt) using AP's public key (from its Connector) */
3697 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, 0);
3698 if (!msg) {
3699 wpabuf_free(pt);
3700 return -1;
3701 }
3702 aad = wpabuf_head_u8(msg) + 2; /* from the OUI field (inclusive) */
3703 aad_len = DPP_HDR_LEN; /* to the DPP Frame Type field (inclusive) */
3704 wpa_hexdump(MSG_MSGDUMP, "DPP: AAD for HPKE", aad, aad_len);
3705
3706 enc_ct = hpke_base_seal(intro->kem_id, intro->kdf_id, intro->aead_id,
3707 intro->peer_key, NULL, 0, aad, aad_len,
3708 wpabuf_head(pt), wpabuf_len(pt));
3709 wpabuf_free(pt);
3710 wpabuf_free(msg);
3711 if (!enc_ct) {
3712 wpa_printf(MSG_INFO, "DPP: HPKE Seal(Connector) failed");
3713 return -1;
3714 }
3715 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE enc|ct", enc_ct);
3716
3717 /* HPKE(pt) to generate payload for Wrapped Data */
3718 len = 5 + 4 + wpabuf_len(enc_ct);
3719 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, len);
3720 if (!msg) {
3721 wpabuf_free(enc_ct);
3722 return -1;
3723 }
3724
3725 /* Transaction ID */
3726 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3727 wpabuf_put_le16(msg, 1);
3728 wpabuf_put_u8(msg, TRANSACTION_ID);
3729
3730 /* Wrapped Data */
3731 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3732 wpabuf_put_le16(msg, wpabuf_len(enc_ct));
3733 wpabuf_put_buf(msg, enc_ct);
3734 wpabuf_free(enc_ct);
3735
3736 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Update", msg);
3737
3738 /* TODO: Timeout on AP response */
3739 wait_time = wpa_s->max_remain_on_chan;
3740 if (wait_time > 2000)
3741 wait_time = 2000;
3742 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3743 MAC2STR(dst), freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
3744 offchannel_send_action(wpa_s, freq, dst, wpa_s->own_addr, broadcast,
3745 wpabuf_head(msg), wpabuf_len(msg),
3746 wait_time, wpas_dpp_tx_priv_intro_status, 0);
3747 wpabuf_free(msg);
3748
3749 return 0;
3750}
3751
3752
3753static void
3754wpas_dpp_rx_priv_peer_intro_notify(struct wpa_supplicant *wpa_s,
3755 const u8 *src, const u8 *hdr,
3756 const u8 *buf, size_t len,
3757 unsigned int freq)
3758{
3759 struct wpa_ssid *ssid;
3760 const u8 *connector, *trans_id, *version;
3761 u16 connector_len, trans_id_len, version_len;
3762 u8 peer_version = 1;
3763 struct dpp_introduction intro;
3764 struct rsn_pmksa_cache_entry *entry;
3765 struct os_time now;
3766 struct os_reltime rnow;
3767 os_time_t expiry;
3768 unsigned int seconds;
3769 enum dpp_status_error res;
3770
3771 os_memset(&intro, 0, sizeof(intro));
3772
3773 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
3774 MACSTR, MAC2STR(src));
3775 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
3776 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
3777 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
3778 MACSTR " - drop", MAC2STR(src));
3779 return;
3780 }
3781 offchannel_send_action_done(wpa_s);
3782
3783 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3784 if (ssid == wpa_s->dpp_intro_network)
3785 break;
3786 }
3787 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3788 !ssid->dpp_csign) {
3789 wpa_printf(MSG_DEBUG,
3790 "DPP: Profile not found for network introduction");
3791 return;
3792 }
3793
3794 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
3795 &trans_id_len);
3796 if (!trans_id || trans_id_len != 1) {
3797 wpa_printf(MSG_DEBUG,
3798 "DPP: Peer did not include Transaction ID");
3799 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3800 " fail=missing_transaction_id", MAC2STR(src));
3801 goto fail;
3802 }
3803 if (trans_id[0] != TRANSACTION_ID) {
3804 wpa_printf(MSG_DEBUG,
3805 "DPP: Ignore frame with unexpected Transaction ID %u",
3806 trans_id[0]);
3807 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3808 " fail=transaction_id_mismatch", MAC2STR(src));
3809 goto fail;
3810 }
3811
3812 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
3813 if (!connector) {
3814 wpa_printf(MSG_DEBUG,
3815 "DPP: Peer did not include its Connector");
3816 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3817 " fail=missing_connector", MAC2STR(src));
3818 goto fail;
3819 }
3820
3821 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
3822 &version_len);
3823 if (!version || version_len < 1) {
3824 wpa_printf(MSG_DEBUG,
3825 "DPP: Peer did not include valid Version");
3826 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3827 " fail=missing_version", MAC2STR(src));
3828 goto fail;
3829 }
3830
3831 res = dpp_peer_intro(&intro, ssid->dpp_connector,
3832 ssid->dpp_netaccesskey,
3833 ssid->dpp_netaccesskey_len,
3834 ssid->dpp_csign,
3835 ssid->dpp_csign_len,
3836 connector, connector_len, &expiry);
3837 if (res != DPP_STATUS_OK) {
3838 wpa_printf(MSG_INFO,
3839 "DPP: Network Introduction protocol resulted in failure");
3840 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3841 " fail=peer_connector_validation_failed", MAC2STR(src));
3842 wpas_dpp_send_conn_status_result(wpa_s, res);
3843 goto fail;
3844 }
3845
3846 peer_version = version[0];
3847 if (intro.peer_version && intro.peer_version >= 2 &&
3848 peer_version != intro.peer_version) {
3849 wpa_printf(MSG_INFO,
3850 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
3851 intro.peer_version, peer_version);
3852 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
3853 goto fail;
3854 }
3855 wpa_s->dpp_intro_peer_version = peer_version;
3856
3857 entry = os_zalloc(sizeof(*entry));
3858 if (!entry)
3859 goto fail;
3860 entry->dpp_pfs = peer_version >= 2;
3861 os_memcpy(entry->aa, src, ETH_ALEN);
3862 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
3863 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
3864 entry->pmk_len = intro.pmk_len;
3865 entry->akmp = WPA_KEY_MGMT_DPP;
3866 if (expiry) {
3867 os_get_time(&now);
3868 seconds = expiry - now.sec;
3869 } else {
3870 seconds = 86400 * 7;
3871 }
3872
3873 if (wpas_dpp_send_private_peer_intro_update(wpa_s, &intro, ssid, src,
3874 freq) < 0) {
3875 os_free(entry);
3876 goto fail;
3877 }
3878
3879 os_get_reltime(&rnow);
3880 entry->expiration = rnow.sec + seconds;
3881 entry->reauth_time = rnow.sec + seconds;
3882 entry->network_ctx = ssid;
3883 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
3884
3885 /* Association will be initiated from TX status handler for the Private
3886 * Peer Intro Update: wpas_dpp_tx_priv_intro_status() */
3887
3888fail:
3889 dpp_peer_intro_deinit(&intro);
3890}
3891
3892#endif /* CONFIG_DPP3 */
3893
3894
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003895void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
3896 const u8 *buf, size_t len, unsigned int freq)
3897{
3898 u8 crypto_suite;
3899 enum dpp_public_action_frame_type type;
3900 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003901 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003902
3903 if (len < DPP_HDR_LEN)
3904 return;
3905 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
3906 return;
3907 hdr = buf;
3908 buf += 4;
3909 len -= 4;
3910 crypto_suite = *buf++;
3911 type = *buf++;
3912 len -= 2;
3913
3914 wpa_printf(MSG_DEBUG,
3915 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
3916 MACSTR " freq=%u",
3917 crypto_suite, type, MAC2STR(src), freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07003918#ifdef CONFIG_TESTING_OPTIONS
3919 if (wpa_s->dpp_discard_public_action &&
3920 type != DPP_PA_PEER_DISCOVERY_RESP &&
3921 type != DPP_PA_PRIV_PEER_INTRO_NOTIFY) {
3922 wpa_printf(MSG_DEBUG,
3923 "TESTING: Discard received DPP Public Action frame");
3924 return;
3925 }
3926#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003927 if (crypto_suite != 1) {
3928 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
3929 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003930 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3931 " freq=%u type=%d ignore=unsupported-crypto-suite",
3932 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003933 return;
3934 }
3935 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003936 if (dpp_check_attrs(buf, len) < 0) {
3937 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3938 " freq=%u type=%d ignore=invalid-attributes",
3939 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003940 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003941 }
3942 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
3943 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003944
3945 switch (type) {
3946 case DPP_PA_AUTHENTICATION_REQ:
3947 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
3948 break;
3949 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07003950 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003951 break;
3952 case DPP_PA_AUTHENTICATION_CONF:
3953 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
3954 break;
3955 case DPP_PA_PEER_DISCOVERY_RESP:
3956 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
3957 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003958#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003959 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003960 /* This is for PKEXv2, but for now, process only with
3961 * CONFIG_DPP3 to avoid issues with a capability that has not
3962 * been tested with other implementations. */
3963 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
3964 break;
3965#endif /* CONFIG_DPP3 */
3966 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
3967 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
3968 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003969 break;
3970 case DPP_PA_PKEX_EXCHANGE_RESP:
3971 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
3972 break;
3973 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
3974 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
3975 freq);
3976 break;
3977 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
3978 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
3979 freq);
3980 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003981#ifdef CONFIG_DPP2
3982 case DPP_PA_CONFIGURATION_RESULT:
3983 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
3984 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003985 case DPP_PA_CONNECTION_STATUS_RESULT:
3986 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
3987 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07003988 case DPP_PA_PRESENCE_ANNOUNCEMENT:
3989 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
3990 freq);
3991 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003992 case DPP_PA_RECONFIG_ANNOUNCEMENT:
3993 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
3994 freq);
3995 break;
3996 case DPP_PA_RECONFIG_AUTH_REQ:
3997 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
3998 break;
3999 case DPP_PA_RECONFIG_AUTH_RESP:
4000 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
4001 break;
4002 case DPP_PA_RECONFIG_AUTH_CONF:
4003 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
4004 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004005#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07004006#ifdef CONFIG_DPP3
4007 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
4008 wpas_dpp_rx_pb_presence_announcement(wpa_s, src, hdr,
4009 buf, len, freq);
4010 break;
4011 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP:
4012 wpas_dpp_rx_pb_presence_announcement_resp(wpa_s, src, hdr,
4013 buf, len, freq);
4014 break;
4015 case DPP_PA_PRIV_PEER_INTRO_NOTIFY:
4016 wpas_dpp_rx_priv_peer_intro_notify(wpa_s, src, hdr,
4017 buf, len, freq);
4018 break;
4019#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004020 default:
4021 wpa_printf(MSG_DEBUG,
4022 "DPP: Ignored unsupported frame subtype %d", type);
4023 break;
4024 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004025
4026 if (wpa_s->dpp_pkex)
4027 pkex_t = wpa_s->dpp_pkex->t;
4028 else if (wpa_s->dpp_pkex_bi)
4029 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
4030 else
4031 pkex_t = 0;
4032 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
4033 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
4034 wpas_dpp_pkex_remove(wpa_s, "*");
4035 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004036}
4037
4038
Hai Shaloma20dcd72022-02-04 13:43:00 -08004039static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
4040 void *timeout_ctx)
4041{
4042 struct wpa_supplicant *wpa_s = eloop_ctx;
4043 struct dpp_authentication *auth = wpa_s->dpp_auth;
4044
4045 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
4046 return;
4047
4048 wpa_printf(MSG_DEBUG,
4049 "DPP: No configuration available from upper layers - send initial response with comeback delay");
4050 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
4051 500);
4052}
4053
4054
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004055static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07004056wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08004057 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004058{
4059 struct wpa_supplicant *wpa_s = ctx;
4060 struct dpp_authentication *auth = wpa_s->dpp_auth;
4061 struct wpabuf *resp;
4062
4063 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
4064 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004065 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004066 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
4067 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
4068 return NULL;
4069 }
Hai Shalomc3565922019-10-28 11:58:20 -07004070
4071 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
4072 wpa_printf(MSG_DEBUG,
4073 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
4074 /* wpas_dpp_auth_success() would normally have been called from
4075 * TX status handler, but since there was no such handler call
4076 * yet, simply send out the event message and proceed with
4077 * exchange. */
4078 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
4079 wpa_s->dpp_auth_ok_on_ack = 0;
4080 }
4081
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004082 wpa_hexdump(MSG_DEBUG,
4083 "DPP: Received Configuration Request (GAS Query Request)",
4084 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004085 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
4086 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004087 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004088
Hai Shaloma20dcd72022-02-04 13:43:00 -08004089 auth->gas_server_ctx = resp_ctx;
4090
Hai Shalom899fcc72020-10-19 14:38:18 -07004091#ifdef CONFIG_DPP2
4092 if (!resp && auth->waiting_cert) {
4093 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08004094 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07004095 *comeback_delay = 500;
4096 return NULL;
4097 }
4098#endif /* CONFIG_DPP2 */
4099
Hai Shaloma20dcd72022-02-04 13:43:00 -08004100 if (!resp && auth->waiting_config &&
4101 (auth->peer_bi || auth->tmp_peer_bi)) {
4102 char *buf = NULL, *name = "";
4103 char band[200], *pos, *end;
4104 int i, res, *opclass = auth->e_band_support;
4105 char *mud_url = "N/A";
4106
4107 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
4108 auth->config_resp_ctx = resp_ctx;
4109 *comeback_delay = -1;
4110 if (auth->e_name) {
4111 size_t len = os_strlen(auth->e_name);
4112
4113 buf = os_malloc(len * 4 + 1);
4114 if (buf) {
4115 printf_encode(buf, len * 4 + 1,
4116 (const u8 *) auth->e_name, len);
4117 name = buf;
4118 }
4119 }
4120 band[0] = '\0';
4121 pos = band;
4122 end = band + sizeof(band);
4123 for (i = 0; opclass && opclass[i]; i++) {
4124 res = os_snprintf(pos, end - pos, "%s%d",
4125 pos == band ? "" : ",", opclass[i]);
4126 if (os_snprintf_error(end - pos, res)) {
4127 *pos = '\0';
4128 break;
4129 }
4130 pos += res;
4131 }
4132 if (auth->e_mud_url) {
4133 size_t len = os_strlen(auth->e_mud_url);
4134
4135 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
4136 mud_url = auth->e_mud_url;
4137 }
4138 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
4139 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
4140 auth->peer_bi ? auth->peer_bi->id :
4141 auth->tmp_peer_bi->id, MAC2STR(sa),
4142 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
4143 os_free(buf);
4144
4145 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4146 NULL);
4147 eloop_register_timeout(0, 50000,
4148 wpas_dpp_gas_initial_resp_timeout, wpa_s,
4149 NULL);
4150 return NULL;
4151 }
4152
Sunil Ravia04bd252022-05-02 22:54:18 -07004153 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08004154 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004155 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004156 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07004157 dpp_auth_deinit(wpa_s->dpp_auth);
4158 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08004159 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004160 return resp;
4161}
4162
4163
4164static void
4165wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
4166{
4167 struct wpa_supplicant *wpa_s = ctx;
4168 struct dpp_authentication *auth = wpa_s->dpp_auth;
4169
4170 if (!auth) {
4171 wpabuf_free(resp);
4172 return;
4173 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004174 if (auth->conf_resp != resp) {
4175 wpa_printf(MSG_DEBUG,
4176 "DPP: Ignore GAS status report (ok=%d) for unknown response",
4177 ok);
4178 wpabuf_free(resp);
4179 return;
4180 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004181
Hai Shalom899fcc72020-10-19 14:38:18 -07004182#ifdef CONFIG_DPP2
4183 if (auth->waiting_csr && ok) {
4184 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
4185 wpabuf_free(resp);
4186 return;
4187 }
4188#endif /* CONFIG_DPP2 */
4189
Sunil Ravia04bd252022-05-02 22:54:18 -07004190#ifdef CONFIG_DPP3
4191 if (auth->waiting_new_key && ok) {
4192 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
4193 wpabuf_free(resp);
4194 return;
4195 }
4196#endif /* CONFIG_DPP3 */
4197
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004198 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
4199 ok);
4200 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004201 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004202 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004203#ifdef CONFIG_DPP2
4204 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08004205 auth->conf_resp_status == DPP_STATUS_OK &&
4206 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07004207 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08004208 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07004209 auth->waiting_conf_result = 1;
4210 auth->conf_resp = NULL;
4211 wpabuf_free(resp);
4212 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
4213 wpa_s, NULL);
4214 eloop_register_timeout(2, 0,
4215 wpas_dpp_config_result_wait_timeout,
4216 wpa_s, NULL);
4217 return;
4218 }
4219#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004220 offchannel_send_action_done(wpa_s);
4221 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004222 if (ok) {
Sunil Ravi89eba102022-09-13 21:04:37 -07004223 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
4224 auth->conf_resp_status);
Hai Shalom706f99b2019-01-08 16:23:37 -08004225 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004226 }
4227 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004228 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004229 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004230 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004231 dpp_auth_deinit(wpa_s->dpp_auth);
4232 wpa_s->dpp_auth = NULL;
4233 wpabuf_free(resp);
Sunil Ravi89eba102022-09-13 21:04:37 -07004234#ifdef CONFIG_DPP3
4235 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
4236 if (ok)
4237 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4238 "success");
4239 else
4240 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4241 "could-not-connect");
4242 wpa_s->dpp_pb_result_indicated = true;
4243 if (ok)
4244 wpas_dpp_remove_pb_hash(wpa_s);
4245 wpas_dpp_push_button_stop(wpa_s);
4246 }
4247#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004248}
4249
4250
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004251int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
4252{
4253 struct dpp_authentication *auth;
4254 int ret = -1;
4255 char *curve = NULL;
4256
Hai Shalomfdcde762020-04-02 11:19:20 -07004257 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004258 if (!auth)
4259 return -1;
4260
4261 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08004262 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07004263 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004264 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07004265 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
4266 &auth->conf_obj[0]);
4267 if (!ret)
4268 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004269
4270 dpp_auth_deinit(auth);
4271 os_free(curve);
4272
4273 return ret;
4274}
4275
4276
4277static void
4278wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
4279 unsigned int freq, const u8 *dst,
4280 const u8 *src, const u8 *bssid,
4281 const u8 *data, size_t data_len,
4282 enum offchannel_send_action_result result)
4283{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004284 const char *res_txt;
4285
4286 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
4287 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
4288 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004289 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
4290 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07004291 freq, MAC2STR(dst), res_txt);
4292 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
4293 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004294 /* TODO: Time out wait for response more quickly in error cases? */
4295}
4296
4297
Sunil Ravi89eba102022-09-13 21:04:37 -07004298#ifdef CONFIG_DPP3
4299static int wpas_dpp_start_private_peer_intro(struct wpa_supplicant *wpa_s,
4300 struct wpa_ssid *ssid,
4301 struct wpa_bss *bss)
4302{
4303 struct wpabuf *msg;
4304 unsigned int wait_time;
4305 size_t len;
4306 u8 ver = DPP_VERSION;
4307 int conn_ver;
4308
4309 len = 5 + 5;
4310 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_QUERY, len);
4311 if (!msg)
4312 return -1;
4313
4314 /* Transaction ID */
4315 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4316 wpabuf_put_le16(msg, 1);
4317 wpabuf_put_u8(msg, TRANSACTION_ID);
4318
4319 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4320 if (conn_ver > 0 && ver != conn_ver) {
4321 wpa_printf(MSG_DEBUG,
4322 "DPP: Use Connector version %d instead of current protocol version %d",
4323 conn_ver, ver);
4324 ver = conn_ver;
4325 }
4326
4327 /* Protocol Version */
4328 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4329 wpabuf_put_le16(msg, 1);
4330 wpabuf_put_u8(msg, ver);
4331
4332 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Query", msg);
4333
4334 /* TODO: Timeout on AP response */
4335 wait_time = wpa_s->max_remain_on_chan;
4336 if (wait_time > 2000)
4337 wait_time = 2000;
4338 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4339 MAC2STR(bss->bssid), bss->freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
4340 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4341 broadcast,
4342 wpabuf_head(msg), wpabuf_len(msg),
4343 wait_time, wpas_dpp_tx_introduction_status, 0);
4344 wpabuf_free(msg);
4345
4346 /* Request this connection attempt to terminate - new one will be
4347 * started when network introduction protocol completes */
4348 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4349 wpa_s->dpp_intro_network = ssid;
4350 return 1;
4351}
4352#endif /* CONFIG_DPP3 */
4353
4354
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004355int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4356 struct wpa_bss *bss)
4357{
4358 struct os_time now;
4359 struct wpabuf *msg;
4360 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07004361 const u8 *rsn;
4362 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004363 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004364
4365 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
4366 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07004367 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4368 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
4369 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
4370 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004371 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
4372 return 0; /* PMKSA exists for DPP AKM - continue */
4373
4374 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4375 !ssid->dpp_csign) {
4376 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4377 "missing %s",
4378 !ssid->dpp_connector ? "Connector" :
4379 (!ssid->dpp_netaccesskey ? "netAccessKey" :
4380 "C-sign-key"));
4381 return -1;
4382 }
4383
4384 os_get_time(&now);
4385
4386 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07004387 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004388 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4389 "netAccessKey expired");
4390 return -1;
4391 }
4392
4393 wpa_printf(MSG_DEBUG,
Sunil Ravi89eba102022-09-13 21:04:37 -07004394 "DPP: Starting %snetwork introduction protocol to derive PMKSA for "
4395 MACSTR,
4396 ssid->dpp_connector_privacy ? "private " : "",
4397 MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07004398 if (wpa_s->wpa_state == WPA_SCANNING)
4399 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004400
Sunil Ravi89eba102022-09-13 21:04:37 -07004401#ifdef CONFIG_DPP3
4402 if (ssid->dpp_connector_privacy)
4403 return wpas_dpp_start_private_peer_intro(wpa_s, ssid, bss);
4404#endif /* CONFIG_DPP3 */
4405
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004406 len = 5 + 4 + os_strlen(ssid->dpp_connector);
4407#ifdef CONFIG_DPP2
4408 len += 5;
4409#endif /* CONFIG_DPP2 */
4410 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004411 if (!msg)
4412 return -1;
4413
Roshan Pius3a1667e2018-07-03 15:17:14 -07004414#ifdef CONFIG_TESTING_OPTIONS
4415 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
4416 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
4417 goto skip_trans_id;
4418 }
4419 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
4420 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
4421 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4422 wpabuf_put_le16(msg, 0);
4423 goto skip_trans_id;
4424 }
4425#endif /* CONFIG_TESTING_OPTIONS */
4426
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004427 /* Transaction ID */
4428 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4429 wpabuf_put_le16(msg, 1);
4430 wpabuf_put_u8(msg, TRANSACTION_ID);
4431
Roshan Pius3a1667e2018-07-03 15:17:14 -07004432#ifdef CONFIG_TESTING_OPTIONS
4433skip_trans_id:
4434 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
4435 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
4436 goto skip_connector;
4437 }
4438 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
4439 char *connector;
4440
4441 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
4442 connector = dpp_corrupt_connector_signature(
4443 ssid->dpp_connector);
4444 if (!connector) {
4445 wpabuf_free(msg);
4446 return -1;
4447 }
4448 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4449 wpabuf_put_le16(msg, os_strlen(connector));
4450 wpabuf_put_str(msg, connector);
4451 os_free(connector);
4452 goto skip_connector;
4453 }
4454#endif /* CONFIG_TESTING_OPTIONS */
4455
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004456 /* DPP Connector */
4457 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4458 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
4459 wpabuf_put_str(msg, ssid->dpp_connector);
4460
Roshan Pius3a1667e2018-07-03 15:17:14 -07004461#ifdef CONFIG_TESTING_OPTIONS
4462skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004463 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
4464 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
4465 goto skip_proto_ver;
4466 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004467#endif /* CONFIG_TESTING_OPTIONS */
4468
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004469#ifdef CONFIG_DPP2
4470 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004471 u8 ver = DPP_VERSION;
4472#ifdef CONFIG_DPP3
4473 int conn_ver;
4474
4475 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4476 if (conn_ver > 0 && ver != conn_ver) {
4477 wpa_printf(MSG_DEBUG,
4478 "DPP: Use Connector version %d instead of current protocol version %d",
4479 conn_ver, ver);
4480 ver = conn_ver;
4481 }
4482#endif /* CONFIG_DPP3 */
4483
4484#ifdef CONFIG_TESTING_OPTIONS
4485 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
4486 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
4487 ver = 1;
4488 }
4489#endif /* CONFIG_TESTING_OPTIONS */
4490
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004491 /* Protocol Version */
4492 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4493 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004494 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004495 }
4496#endif /* CONFIG_DPP2 */
4497
Hai Shaloma20dcd72022-02-04 13:43:00 -08004498#ifdef CONFIG_TESTING_OPTIONS
4499skip_proto_ver:
4500#endif /* CONFIG_TESTING_OPTIONS */
4501
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004502 /* TODO: Timeout on AP response */
4503 wait_time = wpa_s->max_remain_on_chan;
4504 if (wait_time > 2000)
4505 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004506 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4507 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004508 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4509 broadcast,
4510 wpabuf_head(msg), wpabuf_len(msg),
4511 wait_time, wpas_dpp_tx_introduction_status, 0);
4512 wpabuf_free(msg);
4513
4514 /* Request this connection attempt to terminate - new one will be
4515 * started when network introduction protocol completes */
4516 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4517 wpa_s->dpp_intro_network = ssid;
4518 return 1;
4519}
4520
4521
4522int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
4523{
4524 struct dpp_bootstrap_info *own_bi;
4525 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07004526#ifdef CONFIG_DPP3
4527 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
4528#else /* CONFIG_DPP3 */
4529 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
4530#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004531 int tcp_port = DPP_TCP_PORT;
4532 struct hostapd_ip_addr *ipaddr = NULL;
4533#ifdef CONFIG_DPP2
4534 struct hostapd_ip_addr ipaddr_buf;
4535 char *addr;
4536
4537 pos = os_strstr(cmd, " tcp_port=");
4538 if (pos) {
4539 pos += 10;
4540 tcp_port = atoi(pos);
4541 }
4542
4543 addr = get_param(cmd, " tcp_addr=");
4544 if (addr) {
4545 int res;
4546
4547 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
4548 os_free(addr);
4549 if (res)
4550 return -1;
4551 ipaddr = &ipaddr_buf;
4552 }
4553#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004554
4555 pos = os_strstr(cmd, " own=");
4556 if (!pos)
4557 return -1;
4558 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07004559 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004560 if (!own_bi) {
4561 wpa_printf(MSG_DEBUG,
4562 "DPP: Identified bootstrap info not found");
4563 return -1;
4564 }
4565 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
4566 wpa_printf(MSG_DEBUG,
4567 "DPP: Identified bootstrap info not for PKEX");
4568 return -1;
4569 }
4570 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004571 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004572
4573 os_free(wpa_s->dpp_pkex_identifier);
4574 wpa_s->dpp_pkex_identifier = NULL;
4575 pos = os_strstr(cmd, " identifier=");
4576 if (pos) {
4577 pos += 12;
4578 end = os_strchr(pos, ' ');
4579 if (!end)
4580 return -1;
4581 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
4582 if (!wpa_s->dpp_pkex_identifier)
4583 return -1;
4584 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
4585 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
4586 }
4587
4588 pos = os_strstr(cmd, " code=");
4589 if (!pos)
4590 return -1;
4591 os_free(wpa_s->dpp_pkex_code);
4592 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
4593 if (!wpa_s->dpp_pkex_code)
4594 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004595 wpa_s->dpp_pkex_code_len = os_strlen(wpa_s->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004596
Sunil Ravia04bd252022-05-02 22:54:18 -07004597 pos = os_strstr(cmd, " ver=");
4598 if (pos) {
4599 int v;
4600
4601 pos += 5;
4602 v = atoi(pos);
4603 if (v == 1)
4604 ver = PKEX_VER_ONLY_1;
4605 else if (v == 2)
4606 ver = PKEX_VER_ONLY_2;
4607 else
4608 return -1;
4609 }
4610 wpa_s->dpp_pkex_ver = ver;
4611
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004612 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004613 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004614 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004615 } else {
4616#ifdef CONFIG_DPP2
4617 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
4618 wpa_s->dpp_pkex_code,
4619 wpa_s->dpp_pkex_identifier);
4620#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004621 }
4622
4623 /* TODO: Support multiple PKEX info entries */
4624
4625 os_free(wpa_s->dpp_pkex_auth_cmd);
4626 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
4627
4628 return 1;
4629}
4630
4631
4632int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
4633{
4634 unsigned int id_val;
4635
4636 if (os_strcmp(id, "*") == 0) {
4637 id_val = 0;
4638 } else {
4639 id_val = atoi(id);
4640 if (id_val == 0)
4641 return -1;
4642 }
4643
Sunil Ravi89eba102022-09-13 21:04:37 -07004644 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004645 return -1;
4646
4647 /* TODO: Support multiple PKEX entries */
4648 os_free(wpa_s->dpp_pkex_code);
4649 wpa_s->dpp_pkex_code = NULL;
4650 os_free(wpa_s->dpp_pkex_identifier);
4651 wpa_s->dpp_pkex_identifier = NULL;
4652 os_free(wpa_s->dpp_pkex_auth_cmd);
4653 wpa_s->dpp_pkex_auth_cmd = NULL;
4654 wpa_s->dpp_pkex_bi = NULL;
4655 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
4656 dpp_pkex_free(wpa_s->dpp_pkex);
4657 wpa_s->dpp_pkex = NULL;
4658 return 0;
4659}
4660
4661
Roshan Pius3a1667e2018-07-03 15:17:14 -07004662void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
4663{
Sunil Ravia04bd252022-05-02 22:54:18 -07004664 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07004665 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004666 dpp_auth_deinit(wpa_s->dpp_auth);
4667 wpa_s->dpp_auth = NULL;
4668 dpp_pkex_free(wpa_s->dpp_pkex);
4669 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004670 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004671 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
4672 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
Sunil Ravi89eba102022-09-13 21:04:37 -07004673#ifdef CONFIG_DPP3
4674 wpas_dpp_push_button_stop(wpa_s);
4675#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004676}
4677
4678
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004679int wpas_dpp_init(struct wpa_supplicant *wpa_s)
4680{
Hai Shalom81f62d82019-07-22 12:10:00 -07004681 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004682 u8 adv_proto_id[7];
4683
4684 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
4685 adv_proto_id[1] = 5;
4686 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
4687 adv_proto_id[5] = DPP_OUI_TYPE;
4688 adv_proto_id[6] = 0x01;
4689
4690 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
4691 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
4692 wpas_dpp_gas_status_handler, wpa_s) < 0)
4693 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004694
4695 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07004696 config.cb_ctx = wpa_s;
4697#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004698 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07004699#endif /* CONFIG_DPP2 */
4700 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07004701 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004702}
4703
4704
4705void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
4706{
4707#ifdef CONFIG_TESTING_OPTIONS
4708 os_free(wpa_s->dpp_config_obj_override);
4709 wpa_s->dpp_config_obj_override = NULL;
4710 os_free(wpa_s->dpp_discovery_override);
4711 wpa_s->dpp_discovery_override = NULL;
4712 os_free(wpa_s->dpp_groups_override);
4713 wpa_s->dpp_groups_override = NULL;
4714 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
4715#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07004716 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004717 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004718 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004719 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004720 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004721 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
4722 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004723 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4724 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004725#ifdef CONFIG_DPP2
4726 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07004727 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
4728 wpa_s, NULL);
4729 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004730 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
4731 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004732 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004733 dpp_pfs_free(wpa_s->dpp_pfs);
4734 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004735 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004736 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4737 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07004738#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07004739#ifdef CONFIG_DPP3
4740 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
4741#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004742 offchannel_send_action_done(wpa_s);
4743 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004744 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004745 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004746 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
4747 os_free(wpa_s->dpp_configurator_params);
4748 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07004749 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004750}
Hai Shalom81f62d82019-07-22 12:10:00 -07004751
4752
Hai Shaloma20dcd72022-02-04 13:43:00 -08004753static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
4754 struct dpp_authentication *auth, bool tcp)
4755{
4756 struct wpabuf *resp;
4757
4758 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
4759 auth->e_netrole, true);
4760 if (!resp)
4761 return -1;
4762
4763 if (tcp) {
4764 auth->conf_resp_tcp = resp;
4765 return 0;
4766 }
4767
4768 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4769 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
4770 resp) < 0) {
4771 wpa_printf(MSG_DEBUG,
4772 "DPP: Could not find pending GAS response");
4773 wpabuf_free(resp);
4774 return -1;
4775 }
4776 auth->conf_resp = resp;
4777 return 0;
4778}
4779
4780
4781int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
4782{
4783 int peer;
4784 const char *pos;
4785 struct dpp_authentication *auth = wpa_s->dpp_auth;
4786 bool tcp = false;
4787
4788 pos = os_strstr(cmd, " peer=");
4789 if (!pos)
4790 return -1;
4791 peer = atoi(pos + 6);
4792#ifdef CONFIG_DPP2
4793 if (!auth || !auth->waiting_config ||
4794 (auth->peer_bi &&
4795 (unsigned int) peer != auth->peer_bi->id)) {
4796 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4797 tcp = true;
4798 }
4799#endif /* CONFIG_DPP2 */
4800
4801 if (!auth || !auth->waiting_config) {
4802 wpa_printf(MSG_DEBUG,
4803 "DPP: No authentication exchange waiting for configuration information");
4804 return -1;
4805 }
4806
4807 if ((!auth->peer_bi ||
4808 (unsigned int) peer != auth->peer_bi->id) &&
4809 (!auth->tmp_peer_bi ||
4810 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4811 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4812 return -1;
4813 }
4814
4815 pos = os_strstr(cmd, " comeback=");
4816 if (pos) {
4817 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4818 NULL);
4819 gas_server_set_comeback_delay(wpa_s->gas_server,
4820 auth->config_resp_ctx,
4821 atoi(pos + 10));
4822 return 0;
4823 }
4824
4825 if (dpp_set_configurator(auth, cmd) < 0)
4826 return -1;
4827
4828 auth->use_config_query = false;
4829 auth->waiting_config = false;
4830 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4831}
4832
4833
Hai Shalom81f62d82019-07-22 12:10:00 -07004834#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004835
Hai Shalom81f62d82019-07-22 12:10:00 -07004836int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
4837{
4838 struct dpp_controller_config config;
4839 const char *pos;
4840
4841 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004842 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07004843 config.netrole = DPP_NETROLE_STA;
4844 config.msg_ctx = wpa_s;
4845 config.cb_ctx = wpa_s;
4846 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004847 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07004848 if (cmd) {
4849 pos = os_strstr(cmd, " tcp_port=");
4850 if (pos) {
4851 pos += 10;
4852 config.tcp_port = atoi(pos);
4853 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004854
4855 pos = os_strstr(cmd, " role=");
4856 if (pos) {
4857 pos += 6;
4858 if (os_strncmp(pos, "configurator", 12) == 0)
4859 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
4860 else if (os_strncmp(pos, "enrollee", 8) == 0)
4861 config.allowed_roles = DPP_CAPAB_ENROLLEE;
4862 else if (os_strncmp(pos, "either", 6) == 0)
4863 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
4864 DPP_CAPAB_ENROLLEE;
4865 else
4866 return -1;
4867 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004868
4869 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07004870 }
4871 config.configurator_params = wpa_s->dpp_configurator_params;
4872 return dpp_controller_start(wpa_s->dpp, &config);
4873}
Hai Shalomfdcde762020-04-02 11:19:20 -07004874
4875
4876static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
4877
4878static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
4879{
4880 struct wpa_supplicant *wpa_s = eloop_ctx;
4881
4882 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
4883 offchannel_send_action_done(wpa_s);
4884 wpas_dpp_chirp_next(wpa_s, NULL);
4885}
4886
4887
4888static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
4889 unsigned int freq, const u8 *dst,
4890 const u8 *src, const u8 *bssid,
4891 const u8 *data, size_t data_len,
4892 enum offchannel_send_action_result result)
4893{
4894 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
4895 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
4896 wpa_s->dpp_chirp_freq);
4897 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
4898 wpa_s, NULL) < 0)
4899 wpas_dpp_chirp_stop(wpa_s);
4900 return;
4901 }
4902
4903 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
4904 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
4905 wpa_s, NULL) < 0)
4906 wpas_dpp_chirp_stop(wpa_s);
4907}
4908
4909
4910static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
4911{
Hai Shalom899fcc72020-10-19 14:38:18 -07004912 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004913 int type;
4914
4915 msg = wpa_s->dpp_presence_announcement;
4916 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
4917 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07004918 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
4919
4920 if (ssid && wpa_s->dpp_reconfig_id &&
4921 wpa_config_get_network(wpa_s->conf,
4922 wpa_s->dpp_reconfig_ssid_id) ==
4923 ssid) {
4924 announce = dpp_build_reconfig_announcement(
4925 ssid->dpp_csign,
4926 ssid->dpp_csign_len,
4927 ssid->dpp_netaccesskey,
4928 ssid->dpp_netaccesskey_len,
4929 wpa_s->dpp_reconfig_id);
4930 msg = announce;
4931 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004932 if (!msg)
4933 return;
4934 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
4935 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004936 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
4937 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004938 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07004939 if (offchannel_send_action(
4940 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
4941 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004942 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07004943 2000, wpas_dpp_chirp_tx_status, 0) < 0)
4944 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004945
4946 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07004947}
4948
4949
Sunil Ravi89eba102022-09-13 21:04:37 -07004950static int * wpas_dpp_presence_ann_channels(struct wpa_supplicant *wpa_s,
4951 struct dpp_bootstrap_info *bi)
Hai Shalomfdcde762020-04-02 11:19:20 -07004952{
Hai Shalomfdcde762020-04-02 11:19:20 -07004953 unsigned int i;
4954 struct hostapd_hw_modes *mode;
4955 int c;
4956 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004957 bool chan6 = wpa_s->hw.modes == NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07004958 int *freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004959
4960 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004961 if (bi) {
4962 for (i = 0; i < bi->num_freq; i++)
Sunil Ravi89eba102022-09-13 21:04:37 -07004963 int_array_add_unique(&freqs, bi->freq[i]);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004964 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004965
4966 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07004967 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004968 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07004969 if (mode) {
4970 for (c = 0; c < mode->num_channels; c++) {
4971 struct hostapd_channel_data *chan = &mode->channels[c];
4972
4973 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
4974 chan->freq != 2437)
4975 continue;
4976 chan6 = true;
4977 break;
4978 }
4979 }
4980 if (chan6)
Sunil Ravi89eba102022-09-13 21:04:37 -07004981 int_array_add_unique(&freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07004982
4983 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004984 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07004985 if (mode) {
4986 int chan44 = 0, chan149 = 0;
4987
4988 for (c = 0; c < mode->num_channels; c++) {
4989 struct hostapd_channel_data *chan = &mode->channels[c];
4990
4991 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
4992 HOSTAPD_CHAN_RADAR))
4993 continue;
4994 if (chan->freq == 5220)
4995 chan44 = 1;
4996 if (chan->freq == 5745)
4997 chan149 = 1;
4998 }
4999 if (chan149)
Sunil Ravi89eba102022-09-13 21:04:37 -07005000 int_array_add_unique(&freqs, 5745);
Hai Shalomfdcde762020-04-02 11:19:20 -07005001 else if (chan44)
Sunil Ravi89eba102022-09-13 21:04:37 -07005002 int_array_add_unique(&freqs, 5220);
Hai Shalomfdcde762020-04-02 11:19:20 -07005003 }
5004
5005 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005006 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005007 if (mode) {
5008 for (c = 0; c < mode->num_channels; c++) {
5009 struct hostapd_channel_data *chan = &mode->channels[c];
5010
5011 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
5012 HOSTAPD_CHAN_RADAR)) ||
5013 chan->freq != 60480)
5014 continue;
Sunil Ravi89eba102022-09-13 21:04:37 -07005015 int_array_add_unique(&freqs, 60480);
Hai Shalomfdcde762020-04-02 11:19:20 -07005016 break;
5017 }
5018 }
5019
5020 /* Add channels from scan results for APs that advertise Configurator
5021 * Connectivity element */
5022 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5023 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
Sunil Ravi89eba102022-09-13 21:04:37 -07005024 int_array_add_unique(&freqs, bss->freq);
Hai Shalomfdcde762020-04-02 11:19:20 -07005025 }
5026
Sunil Ravi89eba102022-09-13 21:04:37 -07005027 return freqs;
5028}
5029
5030
5031static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
5032 struct wpa_scan_results *scan_res)
5033{
5034 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
5035
5036 if (!bi && !wpa_s->dpp_reconfig_ssid)
5037 return;
5038
5039 wpa_s->dpp_chirp_scan_done = 1;
5040
5041 os_free(wpa_s->dpp_chirp_freqs);
5042 wpa_s->dpp_chirp_freqs = wpas_dpp_presence_ann_channels(wpa_s, bi);
5043
Hai Shalomfdcde762020-04-02 11:19:20 -07005044 if (!wpa_s->dpp_chirp_freqs ||
5045 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
5046 wpas_dpp_chirp_stop(wpa_s);
5047}
5048
5049
5050static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
5051{
5052 struct wpa_supplicant *wpa_s = eloop_ctx;
5053 int i;
5054
5055 if (wpa_s->dpp_chirp_listen)
5056 wpas_dpp_listen_stop(wpa_s);
5057
5058 if (wpa_s->dpp_chirp_freq == 0) {
5059 if (wpa_s->dpp_chirp_round % 4 == 0 &&
5060 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08005061 if (wpas_scan_scheduled(wpa_s)) {
5062 wpa_printf(MSG_DEBUG,
5063 "DPP: Deferring chirp scan because another scan is planned already");
5064 if (eloop_register_timeout(1, 0,
5065 wpas_dpp_chirp_next,
5066 wpa_s, NULL) < 0) {
5067 wpas_dpp_chirp_stop(wpa_s);
5068 return;
5069 }
5070 return;
5071 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005072 wpa_printf(MSG_DEBUG,
5073 "DPP: Update channel list for chirping");
5074 wpa_s->scan_req = MANUAL_SCAN_REQ;
5075 wpa_s->scan_res_handler =
5076 wpas_dpp_chirp_scan_res_handler;
5077 wpa_supplicant_req_scan(wpa_s, 0, 0);
5078 return;
5079 }
5080 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
5081 wpa_s->dpp_chirp_round++;
5082 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
5083 wpa_s->dpp_chirp_round);
5084 } else {
5085 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
5086 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
5087 break;
5088 if (!wpa_s->dpp_chirp_freqs[i]) {
5089 wpa_printf(MSG_DEBUG,
5090 "DPP: Previous chirp freq %d not found",
5091 wpa_s->dpp_chirp_freq);
5092 return;
5093 }
5094 i++;
5095 if (wpa_s->dpp_chirp_freqs[i]) {
5096 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
5097 } else {
5098 wpa_s->dpp_chirp_iter--;
5099 if (wpa_s->dpp_chirp_iter <= 0) {
5100 wpa_printf(MSG_DEBUG,
5101 "DPP: Chirping iterations completed");
5102 wpas_dpp_chirp_stop(wpa_s);
5103 return;
5104 }
5105 wpa_s->dpp_chirp_freq = 0;
5106 wpa_s->dpp_chirp_scan_done = 0;
5107 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
5108 wpa_s, NULL) < 0) {
5109 wpas_dpp_chirp_stop(wpa_s);
5110 return;
5111 }
5112 if (wpa_s->dpp_chirp_listen) {
5113 wpa_printf(MSG_DEBUG,
5114 "DPP: Listen on %d MHz during chirp 30 second wait",
5115 wpa_s->dpp_chirp_listen);
5116 wpas_dpp_listen_start(wpa_s,
5117 wpa_s->dpp_chirp_listen);
5118 } else {
5119 wpa_printf(MSG_DEBUG,
5120 "DPP: Wait 30 seconds before starting the next chirping round");
5121 }
5122 return;
5123 }
5124 }
5125
5126 wpas_dpp_chirp_start(wpa_s);
5127}
5128
5129
5130int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
5131{
5132 const char *pos;
5133 int iter = 1, listen_freq = 0;
5134 struct dpp_bootstrap_info *bi;
5135
5136 pos = os_strstr(cmd, " own=");
5137 if (!pos)
5138 return -1;
5139 pos += 5;
5140 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
5141 if (!bi) {
5142 wpa_printf(MSG_DEBUG,
5143 "DPP: Identified bootstrap info not found");
5144 return -1;
5145 }
5146
5147 pos = os_strstr(cmd, " iter=");
5148 if (pos) {
5149 iter = atoi(pos + 6);
5150 if (iter <= 0)
5151 return -1;
5152 }
5153
5154 pos = os_strstr(cmd, " listen=");
5155 if (pos) {
5156 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005157 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005158 return -1;
5159 }
5160
5161 wpas_dpp_chirp_stop(wpa_s);
5162 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005163 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07005164 wpa_s->dpp_qr_mutual = 0;
5165 wpa_s->dpp_chirp_bi = bi;
5166 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
5167 if (!wpa_s->dpp_presence_announcement)
5168 return -1;
5169 wpa_s->dpp_chirp_iter = iter;
5170 wpa_s->dpp_chirp_round = 0;
5171 wpa_s->dpp_chirp_scan_done = 0;
5172 wpa_s->dpp_chirp_listen = listen_freq;
5173
5174 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5175}
5176
5177
5178void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
5179{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005180 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07005181 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005182 offchannel_send_action_done(wpa_s);
5183 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
5184 }
5185 wpa_s->dpp_chirp_bi = NULL;
5186 wpabuf_free(wpa_s->dpp_presence_announcement);
5187 wpa_s->dpp_presence_announcement = NULL;
5188 if (wpa_s->dpp_chirp_listen)
5189 wpas_dpp_listen_stop(wpa_s);
5190 wpa_s->dpp_chirp_listen = 0;
5191 wpa_s->dpp_chirp_freq = 0;
5192 os_free(wpa_s->dpp_chirp_freqs);
5193 wpa_s->dpp_chirp_freqs = NULL;
5194 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
5195 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
5196 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
5197 wpas_abort_ongoing_scan(wpa_s);
5198 wpa_s->scan_res_handler = NULL;
5199 }
5200}
5201
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005202
Hai Shalom899fcc72020-10-19 14:38:18 -07005203int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005204{
Hai Shalom899fcc72020-10-19 14:38:18 -07005205 struct wpa_ssid *ssid;
5206 int iter = 1;
5207 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005208
Hai Shalom899fcc72020-10-19 14:38:18 -07005209 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
5210 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
5211 !ssid->dpp_csign) {
5212 wpa_printf(MSG_DEBUG,
5213 "DPP: Not a valid network profile for reconfiguration");
5214 return -1;
5215 }
5216
5217 pos = os_strstr(cmd, " iter=");
5218 if (pos) {
5219 iter = atoi(pos + 6);
5220 if (iter <= 0)
5221 return -1;
5222 }
5223
5224 if (wpa_s->dpp_auth) {
5225 wpa_printf(MSG_DEBUG,
5226 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
5227 return -1;
5228 }
5229
5230 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
5231 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
5232 ssid->dpp_csign_len,
5233 ssid->dpp_pp_key,
5234 ssid->dpp_pp_key_len);
5235 if (!wpa_s->dpp_reconfig_id) {
5236 wpa_printf(MSG_DEBUG,
5237 "DPP: Failed to generate E-id for reconfiguration");
5238 return -1;
5239 }
5240 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
5241 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
5242 wpa_s->own_disconnect_req = 1;
5243 wpa_supplicant_deauthenticate(
5244 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5245 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005246 wpas_dpp_chirp_stop(wpa_s);
5247 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005248 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005249 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005250 wpa_s->dpp_reconfig_ssid = ssid;
5251 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07005252 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005253 wpa_s->dpp_chirp_round = 0;
5254 wpa_s->dpp_chirp_scan_done = 0;
5255 wpa_s->dpp_chirp_listen = 0;
5256
5257 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5258}
5259
Hai Shalom899fcc72020-10-19 14:38:18 -07005260
Hai Shalom899fcc72020-10-19 14:38:18 -07005261int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
5262{
5263 int peer = -1;
5264 const char *pos, *value;
5265 struct dpp_authentication *auth = wpa_s->dpp_auth;
5266 u8 *bin;
5267 size_t bin_len;
5268 struct wpabuf *buf;
5269 bool tcp = false;
5270
5271 pos = os_strstr(cmd, " peer=");
5272 if (pos) {
5273 peer = atoi(pos + 6);
5274 if (!auth || !auth->waiting_cert ||
5275 (auth->peer_bi &&
5276 (unsigned int) peer != auth->peer_bi->id)) {
5277 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5278 tcp = true;
5279 }
5280 }
5281
5282 if (!auth || !auth->waiting_cert) {
5283 wpa_printf(MSG_DEBUG,
5284 "DPP: No authentication exchange waiting for certificate information");
5285 return -1;
5286 }
5287
5288 if (peer >= 0 &&
5289 (!auth->peer_bi ||
5290 (unsigned int) peer != auth->peer_bi->id) &&
5291 (!auth->tmp_peer_bi ||
5292 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5293 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5294 return -1;
5295 }
5296
5297 pos = os_strstr(cmd, " value=");
5298 if (!pos)
5299 return -1;
5300 value = pos + 7;
5301
5302 pos = os_strstr(cmd, " name=");
5303 if (!pos)
5304 return -1;
5305 pos += 6;
5306
5307 if (os_strncmp(pos, "status ", 7) == 0) {
5308 auth->force_conf_resp_status = atoi(value);
5309 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5310 }
5311
5312 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
5313 os_free(auth->trusted_eap_server_name);
5314 auth->trusted_eap_server_name = os_strdup(value);
5315 return auth->trusted_eap_server_name ? 0 : -1;
5316 }
5317
5318 bin = base64_decode(value, os_strlen(value), &bin_len);
5319 if (!bin)
5320 return -1;
5321 buf = wpabuf_alloc_copy(bin, bin_len);
5322 os_free(bin);
5323
5324 if (os_strncmp(pos, "caCert ", 7) == 0) {
5325 wpabuf_free(auth->cacert);
5326 auth->cacert = buf;
5327 return 0;
5328 }
5329
5330 if (os_strncmp(pos, "certBag ", 8) == 0) {
5331 wpabuf_free(auth->certbag);
5332 auth->certbag = buf;
5333 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5334 }
5335
5336 wpabuf_free(buf);
5337 return -1;
5338}
5339
Hai Shalom81f62d82019-07-22 12:10:00 -07005340#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07005341
5342
5343#ifdef CONFIG_DPP3
5344
5345#define DPP_PB_ANNOUNCE_PER_CHAN 3
5346
5347static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
5348static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
5349
5350
5351static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
5352 unsigned int freq, const u8 *dst,
5353 const u8 *src, const u8 *bssid,
5354 const u8 *data, size_t data_len,
5355 enum offchannel_send_action_result result)
5356{
5357 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5358 wpa_printf(MSG_DEBUG,
5359 "DPP: Failed to send push button announcement on %d MHz",
5360 freq);
5361 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
5362 wpa_s, NULL) < 0)
5363 wpas_dpp_push_button_stop(wpa_s);
5364 return;
5365 }
5366
5367 wpa_printf(MSG_DEBUG, "DPP: Push button announcement on %d MHz sent",
5368 freq);
5369 if (wpa_s->dpp_pb_discovery_done) {
5370 wpa_s->dpp_pb_announce_count = 0;
5371 wpa_printf(MSG_DEBUG,
5372 "DPP: Wait for push button announcement response and PKEX on %d MHz",
5373 freq);
5374 if (eloop_register_timeout(0, 500000, wpas_dpp_pb_next,
5375 wpa_s, NULL) < 0)
5376 wpas_dpp_push_button_stop(wpa_s);
5377 return;
5378 } else if (wpa_s->dpp_pb_announce_count >= DPP_PB_ANNOUNCE_PER_CHAN) {
5379 wpa_printf(MSG_DEBUG,
5380 "DPP: Wait for push button announcement response on %d MHz",
5381 freq);
5382 if (eloop_register_timeout(0, 50000, wpas_dpp_pb_next,
5383 wpa_s, NULL) < 0)
5384 wpas_dpp_push_button_stop(wpa_s);
5385 return;
5386 }
5387
5388 if (wpas_dpp_pb_announce(wpa_s, freq) < 0)
5389 wpas_dpp_push_button_stop(wpa_s);
5390}
5391
5392
5393static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq)
5394{
5395 struct wpabuf *msg;
5396 int type;
5397
5398 msg = wpa_s->dpp_pb_announcement;
5399 if (!msg)
5400 return -1;
5401
5402 wpa_s->dpp_pb_announce_count++;
5403 wpa_printf(MSG_DEBUG,
5404 "DPP: Send push button announcement %d/%d (%d MHz)",
5405 wpa_s->dpp_pb_announce_count, DPP_PB_ANNOUNCE_PER_CHAN,
5406 freq);
5407
5408 type = DPP_PA_PB_PRESENCE_ANNOUNCEMENT;
5409 if (wpa_s->dpp_pb_announce_count == 1)
5410 wpa_msg(wpa_s, MSG_INFO,
5411 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
5412 MAC2STR(broadcast), freq, type);
5413 if (offchannel_send_action(
5414 wpa_s, freq, broadcast, wpa_s->own_addr, broadcast,
5415 wpabuf_head(msg), wpabuf_len(msg),
5416 1000, wpas_dpp_pb_tx_status, 0) < 0)
5417 return -1;
5418
5419 return 0;
5420}
5421
5422
5423static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx)
5424{
5425 struct wpa_supplicant *wpa_s = eloop_ctx;
5426 struct os_reltime now;
5427 int freq;
5428
5429 if (!wpa_s->dpp_pb_freqs)
5430 return;
5431
5432 os_get_reltime(&now);
5433 offchannel_send_action_done(wpa_s);
5434
5435 if (os_reltime_expired(&now, &wpa_s->dpp_pb_time, 100)) {
5436 wpa_printf(MSG_DEBUG, "DPP: Push button wait time expired");
5437 wpas_dpp_push_button_stop(wpa_s);
5438 return;
5439 }
5440
5441 if (wpa_s->dpp_pb_freq_idx >= int_array_len(wpa_s->dpp_pb_freqs)) {
5442 wpa_printf(MSG_DEBUG,
5443 "DPP: Completed push button announcement round");
5444 wpa_s->dpp_pb_freq_idx = 0;
5445 if (wpa_s->dpp_pb_stop_iter > 0) {
5446 wpa_s->dpp_pb_stop_iter--;
5447
5448 if (wpa_s->dpp_pb_stop_iter == 1) {
5449 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5450 "wait for AP/Configurator to allow PKEX to be initiated");
5451 if (eloop_register_timeout(10, 0,
5452 wpas_dpp_pb_next,
5453 wpa_s, NULL) < 0) {
5454 wpas_dpp_push_button_stop(wpa_s);
5455 return;
5456 }
5457 return;
5458 }
5459
5460 if (wpa_s->dpp_pb_stop_iter == 0) {
5461 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5462 "start push button PKEX responder on the discovered channel (%d MHz)",
5463 wpa_s->dpp_pb_resp_freq);
5464 wpa_s->dpp_pb_discovery_done = true;
5465
5466 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
5467
5468 os_free(wpa_s->dpp_pkex_code);
5469 wpa_s->dpp_pkex_code = os_memdup(
5470 wpa_s->dpp_pb_c_nonce,
5471 wpa_s->dpp_pb_c_nonce_len);
5472 wpa_s->dpp_pkex_code_len =
5473 wpa_s->dpp_pb_c_nonce_len;
5474
5475 os_free(wpa_s->dpp_pkex_identifier);
5476 wpa_s->dpp_pkex_identifier =
5477 os_strdup("PBPKEX");
5478
5479 if (!wpa_s->dpp_pkex_code ||
5480 !wpa_s->dpp_pkex_identifier) {
5481 wpas_dpp_push_button_stop(wpa_s);
5482 return;
5483 }
5484
5485 wpa_s->dpp_pkex_ver = PKEX_VER_ONLY_2;
5486
5487 os_free(wpa_s->dpp_pkex_auth_cmd);
5488 wpa_s->dpp_pkex_auth_cmd = NULL;
5489 }
5490 }
5491 }
5492
5493 if (wpa_s->dpp_pb_discovery_done)
5494 freq = wpa_s->dpp_pb_resp_freq;
5495 else
5496 freq = wpa_s->dpp_pb_freqs[wpa_s->dpp_pb_freq_idx++];
5497 wpa_s->dpp_pb_announce_count = 0;
5498 if (!wpa_s->dpp_pb_announcement) {
5499 wpa_printf(MSG_DEBUG, "DPP: Push button announcements stopped");
5500 return;
5501 }
5502 if (wpas_dpp_pb_announce(wpa_s, freq) < 0) {
5503 wpas_dpp_push_button_stop(wpa_s);
5504 return;
5505 }
5506}
5507
5508
5509static void wpas_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
5510{
5511 struct wpa_supplicant *wpa_s = eloop_ctx;
5512
5513 wpa_printf(MSG_DEBUG,
5514 "DPP: Active push button Configurator mode expired");
5515 wpas_dpp_push_button_stop(wpa_s);
5516}
5517
5518
5519static int wpas_dpp_push_button_configurator(struct wpa_supplicant *wpa_s,
5520 const char *cmd)
5521{
5522 wpa_s->dpp_pb_configurator = true;
5523 wpa_s->dpp_pb_announce_time.sec = 0;
5524 wpa_s->dpp_pb_announce_time.usec = 0;
5525 str_clear_free(wpa_s->dpp_pb_cmd);
5526 wpa_s->dpp_pb_cmd = NULL;
5527 if (cmd) {
5528 wpa_s->dpp_pb_cmd = os_strdup(cmd);
5529 if (!wpa_s->dpp_pb_cmd)
5530 return -1;
5531 }
5532 eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
5533 wpa_s, NULL);
5534
5535 return 0;
5536}
5537
5538
5539static void wpas_dpp_pb_scan_res_handler(struct wpa_supplicant *wpa_s,
5540 struct wpa_scan_results *scan_res)
5541{
5542 if (!wpa_s->dpp_pb_time.sec && !wpa_s->dpp_pb_time.usec)
5543 return;
5544
5545 os_free(wpa_s->dpp_pb_freqs);
5546 wpa_s->dpp_pb_freqs = wpas_dpp_presence_ann_channels(wpa_s, NULL);
5547
5548 wpa_printf(MSG_DEBUG, "DPP: Scan completed for PB discovery");
5549 if (!wpa_s->dpp_pb_freqs ||
5550 eloop_register_timeout(0, 0, wpas_dpp_pb_next, wpa_s, NULL) < 0)
5551 wpas_dpp_push_button_stop(wpa_s);
5552}
5553
5554
5555int wpas_dpp_push_button(struct wpa_supplicant *wpa_s, const char *cmd)
5556{
5557 int res;
5558
5559 if (!wpa_s->dpp)
5560 return -1;
5561 wpas_dpp_push_button_stop(wpa_s);
5562 wpas_dpp_stop(wpa_s);
5563 wpas_dpp_chirp_stop(wpa_s);
5564
5565 os_get_reltime(&wpa_s->dpp_pb_time);
5566
5567 if (cmd &&
5568 (os_strstr(cmd, " role=configurator") ||
5569 os_strstr(cmd, " conf=")))
5570 return wpas_dpp_push_button_configurator(wpa_s, cmd);
5571
5572 wpa_s->dpp_pb_configurator = false;
5573
5574 wpa_s->dpp_pb_freq_idx = 0;
5575
5576 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
5577 if (res < 0)
5578 return -1;
5579 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
5580 if (!wpa_s->dpp_pb_bi)
5581 return -1;
5582
5583 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
5584 wpa_s->dpp_netrole = DPP_NETROLE_STA;
5585 wpa_s->dpp_qr_mutual = 0;
5586 wpa_s->dpp_pb_announcement =
5587 dpp_build_pb_announcement(wpa_s->dpp_pb_bi);
5588 if (!wpa_s->dpp_pb_announcement)
5589 return -1;
5590
5591 wpa_printf(MSG_DEBUG,
5592 "DPP: Scan to create channel list for PB discovery");
5593 wpa_s->scan_req = MANUAL_SCAN_REQ;
5594 wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
5595 wpa_supplicant_req_scan(wpa_s, 0, 0);
5596 return 0;
5597}
5598
5599
5600void wpas_dpp_push_button_stop(struct wpa_supplicant *wpa_s)
5601{
5602 if (!wpa_s->dpp)
5603 return;
5604 os_free(wpa_s->dpp_pb_freqs);
5605 wpa_s->dpp_pb_freqs = NULL;
5606 wpabuf_free(wpa_s->dpp_pb_announcement);
5607 wpa_s->dpp_pb_announcement = NULL;
5608 if (wpa_s->dpp_pb_bi) {
5609 char id[20];
5610
5611 os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
5612 dpp_bootstrap_remove(wpa_s->dpp, id);
5613 wpa_s->dpp_pb_bi = NULL;
5614 if (!wpa_s->dpp_pb_result_indicated) {
5615 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5616 wpa_s->dpp_pb_result_indicated = true;
5617 }
5618 }
5619
5620 wpa_s->dpp_pb_resp_freq = 0;
5621 wpa_s->dpp_pb_stop_iter = 0;
5622 wpa_s->dpp_pb_discovery_done = false;
5623 os_free(wpa_s->dpp_pb_cmd);
5624 wpa_s->dpp_pb_cmd = NULL;
5625
5626 eloop_cancel_timeout(wpas_dpp_pb_next, wpa_s, NULL);
5627 eloop_cancel_timeout(wpas_dpp_push_button_expire, wpa_s, NULL);
5628 if (wpas_dpp_pb_active(wpa_s)) {
5629 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
5630 if (!wpa_s->dpp_pb_result_indicated)
5631 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5632 }
5633 wpa_s->dpp_pb_time.sec = 0;
5634 wpa_s->dpp_pb_time.usec = 0;
5635 dpp_pkex_free(wpa_s->dpp_pkex);
5636 wpa_s->dpp_pkex = NULL;
5637 os_free(wpa_s->dpp_pkex_auth_cmd);
5638 wpa_s->dpp_pkex_auth_cmd = NULL;
5639
5640 wpa_s->dpp_pb_result_indicated = false;
5641
5642 str_clear_free(wpa_s->dpp_pb_cmd);
5643 wpa_s->dpp_pb_cmd = NULL;
5644
5645 if (wpa_s->scan_res_handler == wpas_dpp_pb_scan_res_handler) {
5646 wpas_abort_ongoing_scan(wpa_s);
5647 wpa_s->scan_res_handler = NULL;
5648 }
5649}
5650
5651#endif /* CONFIG_DPP3 */