blob: 70f7a3ba6e46c8437e89e82df9454842c7efa67f [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 Biren3c401c52024-10-10 20:11:18 +000032#include "aidl/vendor/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 */
Sunil Ravi79e6c4f2025-01-04 00:47:06 +000062#ifdef CONFIG_DPP3
63static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
64#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070065
66static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
67
68/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
69 * a single transaction in progress at any point in time. */
70static const u8 TRANSACTION_ID = 1;
71
72
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070073/**
74 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
75 * @wpa_s: Pointer to wpa_supplicant data
76 * @cmd: DPP URI read from a QR Code
77 * Returns: Identifier of the stored info or -1 on failure
78 */
79int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
80{
81 struct dpp_bootstrap_info *bi;
82 struct dpp_authentication *auth = wpa_s->dpp_auth;
83
Hai Shalom021b0b52019-04-10 11:17:58 -070084 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070085 if (!bi)
86 return -1;
87
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070088 if (auth && auth->response_pending &&
89 dpp_notify_new_qr_code(auth, bi) == 1) {
90 wpa_printf(MSG_DEBUG,
91 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070092 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
93 " freq=%u type=%d",
94 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
95 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070096 offchannel_send_action(wpa_s, auth->curr_freq,
97 auth->peer_mac_addr, wpa_s->own_addr,
98 broadcast,
99 wpabuf_head(auth->resp_msg),
100 wpabuf_len(auth->resp_msg),
101 500, wpas_dpp_tx_status, 0);
102 }
103
Hai Shalom899fcc72020-10-19 14:38:18 -0700104#ifdef CONFIG_DPP2
105 dpp_controller_new_qr_code(wpa_s->dpp, bi);
106#endif /* CONFIG_DPP2 */
107
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700108 return bi->id;
109}
110
111
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800112/**
113 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
114 * @wpa_s: Pointer to wpa_supplicant data
115 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
116 * Returns: Identifier of the stored info or -1 on failure
117 */
118int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
119{
120 struct dpp_bootstrap_info *bi;
121
122 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
123 if (!bi)
124 return -1;
125
126 return bi->id;
127}
128
129
Hai Shalomfdcde762020-04-02 11:19:20 -0700130int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd)
131{
132 const char *pos;
133 struct dpp_bootstrap_info *peer_bi, *own_bi;
134
135 pos = os_strstr(cmd, " own=");
136 if (!pos)
137 return -1;
138 pos += 5;
139 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
140 if (!own_bi)
141 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700142 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700143
144 pos = os_strstr(cmd, " uri=");
145 if (!pos)
146 return -1;
147 pos += 5;
148 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
149 if (!peer_bi) {
150 wpa_printf(MSG_INFO,
151 "DPP: Failed to parse URI from NFC Handover Request");
152 return -1;
153 }
154
155 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
156 return -1;
157
158 return peer_bi->id;
159}
160
161
162int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd)
163{
164 const char *pos;
165 struct dpp_bootstrap_info *peer_bi, *own_bi;
166
167 pos = os_strstr(cmd, " own=");
168 if (!pos)
169 return -1;
170 pos += 5;
171 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
172 if (!own_bi)
173 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700174 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700175
176 pos = os_strstr(cmd, " uri=");
177 if (!pos)
178 return -1;
179 pos += 5;
180 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
181 if (!peer_bi) {
182 wpa_printf(MSG_INFO,
183 "DPP: Failed to parse URI from NFC Handover Select");
184 return -1;
185 }
186
187 if (peer_bi->curve != own_bi->curve) {
188 wpa_printf(MSG_INFO,
189 "DPP: Peer (NFC Handover Selector) used different curve");
190 return -1;
191 }
192
193 return peer_bi->id;
194}
195
196
Roshan Pius3a1667e2018-07-03 15:17:14 -0700197static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
198{
199 struct wpa_supplicant *wpa_s = eloop_ctx;
200 struct dpp_authentication *auth = wpa_s->dpp_auth;
201
202 if (!auth || !auth->resp_msg)
203 return;
204
205 wpa_printf(MSG_DEBUG,
206 "DPP: Retry Authentication Response after timeout");
207 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
208 " freq=%u type=%d",
209 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
210 DPP_PA_AUTHENTICATION_RESP);
211 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
212 wpa_s->own_addr, broadcast,
213 wpabuf_head(auth->resp_msg),
214 wpabuf_len(auth->resp_msg),
215 500, wpas_dpp_tx_status, 0);
216}
217
218
219static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
220{
221 struct dpp_authentication *auth = wpa_s->dpp_auth;
222 unsigned int wait_time, max_tries;
223
224 if (!auth || !auth->resp_msg)
225 return;
226
227 if (wpa_s->dpp_resp_max_tries)
228 max_tries = wpa_s->dpp_resp_max_tries;
229 else
230 max_tries = 5;
231 auth->auth_resp_tries++;
232 if (auth->auth_resp_tries >= max_tries) {
233 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
234 offchannel_send_action_done(wpa_s);
235 dpp_auth_deinit(wpa_s->dpp_auth);
236 wpa_s->dpp_auth = NULL;
237 return;
238 }
239
240 if (wpa_s->dpp_resp_retry_time)
241 wait_time = wpa_s->dpp_resp_retry_time;
242 else
243 wait_time = 1000;
Sunil Ravi99c035e2024-07-12 01:42:03 +0000244 if (wpa_s->dpp_tx_chan_change) {
245 wpa_s->dpp_tx_chan_change = false;
246 if (wait_time > 100)
247 wait_time = 100;
248 }
249
Roshan Pius3a1667e2018-07-03 15:17:14 -0700250 wpa_printf(MSG_DEBUG,
251 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
252 wait_time);
253 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
254 eloop_register_timeout(wait_time / 1000,
255 (wait_time % 1000) * 1000,
256 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
257}
258
259
Hai Shalom021b0b52019-04-10 11:17:58 -0700260static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
261{
262 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700263 wpa_s->suitable_network = 0;
264 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700265 wpa_s->disconnected = 0;
266 wpa_s->reassociate = 1;
267 wpa_s->scan_runs = 0;
268 wpa_s->normal_scans = 0;
269 wpa_supplicant_cancel_sched_scan(wpa_s);
270 wpa_supplicant_req_scan(wpa_s, 0, 0);
271}
272
273
Hai Shalomc3565922019-10-28 11:58:20 -0700274#ifdef CONFIG_DPP2
275
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700276static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s,
277 unsigned int freq,
278 unsigned int wait_time)
279{
280 struct os_reltime now, res;
281 unsigned int remaining;
282
283 if (!wpa_s->dpp_listen_freq)
284 return;
285
286 os_get_reltime(&now);
287 if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) {
288 os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res);
289 remaining = res.sec * 1000 + res.usec / 1000;
290 } else {
291 remaining = 0;
292 }
293 if (wpa_s->dpp_listen_freq == freq && remaining > wait_time)
294 return;
295
296 wpa_printf(MSG_DEBUG,
297 "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms",
298 wpa_s->dpp_listen_freq, remaining, freq, wait_time);
299 wpas_dpp_listen_stop(wpa_s);
300
301 /* TODO: Restart listen in some cases after TX? */
302}
303
304
Hai Shalomc3565922019-10-28 11:58:20 -0700305static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
306 void *timeout_ctx)
307{
308 struct wpa_supplicant *wpa_s = eloop_ctx;
309 struct dpp_authentication *auth = wpa_s->dpp_auth;
310 enum dpp_status_error result;
311
Hai Shaloma20dcd72022-02-04 13:43:00 -0800312 if ((!auth || !auth->conn_status_requested) &&
313 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700314 return;
315
316 wpa_printf(MSG_DEBUG,
317 "DPP: Connection timeout - report Connection Status Result");
318 if (wpa_s->suitable_network)
319 result = DPP_STATUS_AUTH_FAILURE;
320 else if (wpa_s->no_suitable_network)
321 result = DPP_STATUS_NO_AP;
322 else
323 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800324 if (wpa_s->wpa_state == WPA_SCANNING)
325 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700326 wpas_dpp_send_conn_status_result(wpa_s, result);
327}
328
329
330static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
331{
332 char *str, *end, *pos;
333 size_t len;
334 unsigned int i;
335 u8 last_op_class = 0;
336 int res;
337
338 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
339 return NULL;
340
341 len = wpa_s->num_last_scan_freqs * 8;
342 str = os_zalloc(len);
343 if (!str)
344 return NULL;
345 end = str + len;
346 pos = str;
347
348 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
349 enum hostapd_hw_mode mode;
350 u8 op_class, channel;
351
352 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
353 0, 0, &op_class, &channel);
354 if (mode == NUM_HOSTAPD_MODES)
355 continue;
356 if (op_class == last_op_class)
357 res = os_snprintf(pos, end - pos, ",%d", channel);
358 else
359 res = os_snprintf(pos, end - pos, "%s%d/%d",
360 pos == str ? "" : ",",
361 op_class, channel);
362 if (os_snprintf_error(end - pos, res)) {
363 *pos = '\0';
364 break;
365 }
366 pos += res;
367 last_op_class = op_class;
368 }
369
370 if (pos == str) {
371 os_free(str);
372 str = NULL;
373 }
374 return str;
375}
376
377
378void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
379 enum dpp_status_error result)
380{
381 struct wpabuf *msg;
382 const char *channel_list = NULL;
383 char *channel_list_buf = NULL;
384 struct wpa_ssid *ssid = wpa_s->current_ssid;
385 struct dpp_authentication *auth = wpa_s->dpp_auth;
386
387 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
388
Hai Shaloma20dcd72022-02-04 13:43:00 -0800389 if ((!auth || !auth->conn_status_requested) &&
390 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700391 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800392
Hai Shalomc3565922019-10-28 11:58:20 -0700393 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
394 result);
395
396 if (result == DPP_STATUS_NO_AP) {
397 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
398 channel_list = channel_list_buf;
399 }
400
Hai Shaloma20dcd72022-02-04 13:43:00 -0800401 if (!auth || !auth->conn_status_requested) {
402 dpp_tcp_send_conn_status(wpa_s->dpp, result,
403 ssid ? ssid->ssid :
404 wpa_s->dpp_last_ssid,
405 ssid ? ssid->ssid_len :
406 wpa_s->dpp_last_ssid_len,
407 channel_list);
408 os_free(channel_list_buf);
409 return;
410 }
411
412 auth->conn_status_requested = 0;
413
Hai Shalomc3565922019-10-28 11:58:20 -0700414 msg = dpp_build_conn_status_result(auth, result,
415 ssid ? ssid->ssid :
416 wpa_s->dpp_last_ssid,
417 ssid ? ssid->ssid_len :
418 wpa_s->dpp_last_ssid_len,
419 channel_list);
420 os_free(channel_list_buf);
421 if (!msg) {
422 dpp_auth_deinit(wpa_s->dpp_auth);
423 wpa_s->dpp_auth = NULL;
424 return;
425 }
426
427 wpa_msg(wpa_s, MSG_INFO,
428 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
429 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
430 DPP_PA_CONNECTION_STATUS_RESULT);
Sunil Ravi546a7b52022-08-26 22:06:04 +0000431 if (offchannel_send_action(wpa_s, auth->curr_freq,
432 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
433 wpabuf_head(msg), wpabuf_len(msg),
434 500, wpas_dpp_tx_status, 0) < 0) {
435 wpas_notify_dpp_connection_status_sent(wpa_s, result);
436 wpabuf_free(msg);
437 dpp_auth_deinit(wpa_s->dpp_auth);
438 wpa_s->dpp_auth = NULL;
439 return;
440 }
441
Hai Shalomc3565922019-10-28 11:58:20 -0700442 wpabuf_free(msg);
443
Sunil Ravi546a7b52022-08-26 22:06:04 +0000444 auth->conn_result_status = result;
445 auth->tx_conn_status_result_started = 1;
Hai Shalomc3565922019-10-28 11:58:20 -0700446 /* This exchange will be terminated in the TX status handler */
447 auth->remove_on_tx_status = 1;
448
449 return;
450}
451
452
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000453static void wpas_dpp_connected_timeout(void *eloop_ctx, void *timeout_ctx)
Hai Shalomc3565922019-10-28 11:58:20 -0700454{
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000455 struct wpa_supplicant *wpa_s = eloop_ctx;
Hai Shalomc3565922019-10-28 11:58:20 -0700456 struct dpp_authentication *auth = wpa_s->dpp_auth;
457
Hai Shaloma20dcd72022-02-04 13:43:00 -0800458 if ((auth && auth->conn_status_requested) ||
459 dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700460 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
461}
462
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000463
464void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
465{
466 struct dpp_authentication *auth = wpa_s->dpp_auth;
467
468 if ((auth && auth->conn_status_requested) ||
469 dpp_tcp_conn_status_requested(wpa_s->dpp)) {
470 /* Report connection result from an eloop timeout to avoid delay
471 * to completing all connection completion steps since this
472 * function is called in a middle of the post 4-way handshake
473 * processing. */
474 eloop_register_timeout(0, 0, wpas_dpp_connected_timeout,
475 wpa_s, NULL);
476 }
477}
478
Hai Shalomc3565922019-10-28 11:58:20 -0700479#endif /* CONFIG_DPP2 */
480
481
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000482static void wpas_dpp_drv_wait_timeout(void *eloop_ctx, void *timeout_ctx)
483{
484 struct wpa_supplicant *wpa_s = eloop_ctx;
485 struct dpp_authentication *auth = wpa_s->dpp_auth;
486
487 if (auth && auth->waiting_auth_resp) {
488 wpa_printf(MSG_DEBUG,
489 "DPP: Call wpas_dpp_auth_init_next() from %s",
490 __func__);
491 wpas_dpp_auth_init_next(wpa_s);
492 } else {
493 wpa_printf(MSG_DEBUG, "DPP: %s, but no waiting_auth_resp",
494 __func__);
495 }
496}
497
498
Sunil Ravi99c035e2024-07-12 01:42:03 +0000499static void wpas_dpp_neg_freq_timeout(void *eloop_ctx, void *timeout_ctx)
500{
501 struct wpa_supplicant *wpa_s = eloop_ctx;
502 struct dpp_authentication *auth = wpa_s->dpp_auth;
503
504 if (!wpa_s->dpp_listen_on_tx_expire || !auth || !auth->neg_freq)
505 return;
506
507 wpa_printf(MSG_DEBUG,
508 "DPP: Start listen on neg_freq %u MHz based on timeout for TX wait expiration",
509 auth->neg_freq);
510 wpas_dpp_listen_start(wpa_s, auth->neg_freq);
511}
512
513
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700514static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
515 unsigned int freq, const u8 *dst,
516 const u8 *src, const u8 *bssid,
517 const u8 *data, size_t data_len,
518 enum offchannel_send_action_result result)
519{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700520 const char *res_txt;
521 struct dpp_authentication *auth = wpa_s->dpp_auth;
522
523 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
524 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
525 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700526 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700527 " result=%s", freq, MAC2STR(dst), res_txt);
528 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
529 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700530
531 if (!wpa_s->dpp_auth) {
532 wpa_printf(MSG_DEBUG,
533 "DPP: Ignore TX status since there is no ongoing authentication exchange");
534 return;
535 }
536
Hai Shalom021b0b52019-04-10 11:17:58 -0700537#ifdef CONFIG_DPP2
538 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700539 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700540 wpa_printf(MSG_DEBUG,
541 "DPP: Try to connect after completed configuration result");
542 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700543 if (auth->conn_status_requested) {
544 wpa_printf(MSG_DEBUG,
545 "DPP: Start 15 second timeout for reporting connection status result");
546 eloop_cancel_timeout(
547 wpas_dpp_conn_status_result_timeout,
548 wpa_s, NULL);
549 eloop_register_timeout(
550 15, 0, wpas_dpp_conn_status_result_timeout,
551 wpa_s, NULL);
552 } else {
553 dpp_auth_deinit(wpa_s->dpp_auth);
554 wpa_s->dpp_auth = NULL;
555 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700556 return;
557 }
558#endif /* CONFIG_DPP2 */
559
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700560 if (wpa_s->dpp_auth->remove_on_tx_status) {
Sunil Ravi546a7b52022-08-26 22:06:04 +0000561 if (auth->tx_conn_status_result_started) {
562 wpas_notify_dpp_connection_status_sent(wpa_s, auth->conn_result_status);
563 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700564 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700565 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700566 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700567 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800568 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
569 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700570 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
571 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700572#ifdef CONFIG_DPP2
573 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
574 wpa_s, NULL);
575#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700576 offchannel_send_action_done(wpa_s);
577 dpp_auth_deinit(wpa_s->dpp_auth);
578 wpa_s->dpp_auth = NULL;
579 return;
580 }
581
582 if (wpa_s->dpp_auth_ok_on_ack)
583 wpas_dpp_auth_success(wpa_s, 1);
584
585 if (!is_broadcast_ether_addr(dst) &&
586 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
587 wpa_printf(MSG_DEBUG,
588 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700589 if (auth->waiting_auth_resp) {
590 /* In case of DPP Authentication Request frame, move to
591 * the next channel immediately. */
592 offchannel_send_action_done(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000593 /* Call wpas_dpp_auth_init_next(wpa_s) from driver event
594 * notifying frame wait was completed or from eloop
595 * timeout. */
596 eloop_register_timeout(0, 10000,
597 wpas_dpp_drv_wait_timeout,
598 wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700599 return;
600 }
601 if (auth->waiting_auth_conf) {
602 wpas_dpp_auth_resp_retry(wpa_s);
603 return;
604 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700605 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700606
Hai Shalom60840252021-02-19 19:02:11 -0800607 if (auth->waiting_auth_conf &&
608 auth->auth_resp_status == DPP_STATUS_OK) {
609 /* Make sure we do not get stuck waiting for Auth Confirm
610 * indefinitely after successfully transmitted Auth Response to
611 * allow new authentication exchanges to be started. */
612 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
613 NULL);
614 eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
615 wpa_s, NULL);
616 }
617
Roshan Pius3a1667e2018-07-03 15:17:14 -0700618 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
619 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
620 /* Allow timeout handling to stop iteration if no response is
621 * received from a peer that has ACKed a request. */
622 auth->auth_req_ack = 1;
623 }
624
625 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
626 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
627 wpa_printf(MSG_DEBUG,
628 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
629 wpa_s->dpp_auth->curr_freq,
630 wpa_s->dpp_auth->neg_freq);
631 offchannel_send_action_done(wpa_s);
Sunil Ravi99c035e2024-07-12 01:42:03 +0000632 wpa_s->dpp_listen_on_tx_expire = true;
633 eloop_register_timeout(0, 100000, wpas_dpp_neg_freq_timeout,
634 wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700635 }
636
637 if (wpa_s->dpp_auth_ok_on_ack)
638 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700639}
640
641
642static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
643{
644 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700645 struct dpp_authentication *auth = wpa_s->dpp_auth;
646 unsigned int freq;
647 struct os_reltime now, diff;
648 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700649
Roshan Pius3a1667e2018-07-03 15:17:14 -0700650 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700651 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700652
653 wait_time = wpa_s->dpp_resp_wait_time ?
654 wpa_s->dpp_resp_wait_time : 2000;
655 os_get_reltime(&now);
656 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
657 diff_ms = diff.sec * 1000 + diff.usec / 1000;
658 wpa_printf(MSG_DEBUG,
659 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
660 wait_time, diff_ms);
661
662 if (auth->auth_req_ack && diff_ms >= wait_time) {
663 /* Peer ACK'ed Authentication Request frame, but did not reply
664 * with Authentication Response frame within two seconds. */
665 wpa_printf(MSG_INFO,
666 "DPP: No response received from responder - stopping initiation attempt");
667 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800668 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700669 offchannel_send_action_done(wpa_s);
670 wpas_dpp_listen_stop(wpa_s);
671 dpp_auth_deinit(auth);
672 wpa_s->dpp_auth = NULL;
673 return;
674 }
675
676 if (diff_ms >= wait_time) {
677 /* Authentication Request frame was not ACK'ed and no reply
678 * was receiving within two seconds. */
679 wpa_printf(MSG_DEBUG,
680 "DPP: Continue Initiator channel iteration");
681 offchannel_send_action_done(wpa_s);
682 wpas_dpp_listen_stop(wpa_s);
683 wpas_dpp_auth_init_next(wpa_s);
684 return;
685 }
686
687 /* Driver did not support 2000 ms long wait_time with TX command, so
688 * schedule listen operation to continue waiting for the response.
689 *
690 * DPP listen operations continue until stopped, so simply schedule a
691 * new call to this function at the point when the two second reply
692 * wait has expired. */
693 wait_time -= diff_ms;
694
695 freq = auth->curr_freq;
696 if (auth->neg_freq > 0)
697 freq = auth->neg_freq;
698 wpa_printf(MSG_DEBUG,
699 "DPP: Continue reply wait on channel %u MHz for %u ms",
700 freq, wait_time);
701 wpa_s->dpp_in_response_listen = 1;
702 wpas_dpp_listen_start(wpa_s, freq);
703
704 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
705 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700706}
707
708
Hai Shalom60840252021-02-19 19:02:11 -0800709static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
710{
711 struct wpa_supplicant *wpa_s = eloop_ctx;
712 struct dpp_authentication *auth = wpa_s->dpp_auth;
713
714 if (!auth || !auth->waiting_auth_conf)
715 return;
716
717 wpa_printf(MSG_DEBUG,
718 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
719 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
720 offchannel_send_action_done(wpa_s);
721 dpp_auth_deinit(auth);
722 wpa_s->dpp_auth = NULL;
723}
724
725
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700726static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
727 struct dpp_authentication *auth)
728{
729#ifdef CONFIG_TESTING_OPTIONS
730 if (wpa_s->dpp_config_obj_override)
731 auth->config_obj_override =
732 os_strdup(wpa_s->dpp_config_obj_override);
733 if (wpa_s->dpp_discovery_override)
734 auth->discovery_override =
735 os_strdup(wpa_s->dpp_discovery_override);
736 if (wpa_s->dpp_groups_override)
737 auth->groups_override =
738 os_strdup(wpa_s->dpp_groups_override);
739 auth->ignore_netaccesskey_mismatch =
740 wpa_s->dpp_ignore_netaccesskey_mismatch;
741#endif /* CONFIG_TESTING_OPTIONS */
742}
743
744
Roshan Pius3a1667e2018-07-03 15:17:14 -0700745static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
746{
747 struct wpa_supplicant *wpa_s = eloop_ctx;
748
749 if (!wpa_s->dpp_auth)
750 return;
751 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
752 wpas_dpp_auth_init_next(wpa_s);
753}
754
755
756static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
757{
758 struct dpp_authentication *auth = wpa_s->dpp_auth;
759 const u8 *dst;
760 unsigned int wait_time, max_wait_time, freq, max_tries, used;
761 struct os_reltime now, diff;
762
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000763 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
764
Roshan Pius3a1667e2018-07-03 15:17:14 -0700765 wpa_s->dpp_in_response_listen = 0;
766 if (!auth)
767 return -1;
768
769 if (auth->freq_idx == 0)
770 os_get_reltime(&wpa_s->dpp_init_iter_start);
771
772 if (auth->freq_idx >= auth->num_freq) {
773 auth->num_freq_iters++;
774 if (wpa_s->dpp_init_max_tries)
775 max_tries = wpa_s->dpp_init_max_tries;
776 else
777 max_tries = 5;
778 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
779 wpa_printf(MSG_INFO,
780 "DPP: No response received from responder - stopping initiation attempt");
781 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800782 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700783 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
784 wpa_s, NULL);
785 offchannel_send_action_done(wpa_s);
786 dpp_auth_deinit(wpa_s->dpp_auth);
787 wpa_s->dpp_auth = NULL;
788 return -1;
789 }
790 auth->freq_idx = 0;
791 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
792 if (wpa_s->dpp_init_retry_time)
793 wait_time = wpa_s->dpp_init_retry_time;
794 else
795 wait_time = 10000;
796 os_get_reltime(&now);
797 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
798 used = diff.sec * 1000 + diff.usec / 1000;
799 if (used > wait_time)
800 wait_time = 0;
801 else
802 wait_time -= used;
803 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
804 wait_time);
805 eloop_register_timeout(wait_time / 1000,
806 (wait_time % 1000) * 1000,
807 wpas_dpp_init_timeout, wpa_s,
808 NULL);
809 return 0;
810 }
811 freq = auth->freq[auth->freq_idx++];
812 auth->curr_freq = freq;
813
Hai Shalom60840252021-02-19 19:02:11 -0800814 if (!is_zero_ether_addr(auth->peer_mac_addr))
815 dst = auth->peer_mac_addr;
816 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700817 dst = broadcast;
818 else
819 dst = auth->peer_bi->mac_addr;
820 wpa_s->dpp_auth_ok_on_ack = 0;
821 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
822 wait_time = wpa_s->max_remain_on_chan;
823 max_wait_time = wpa_s->dpp_resp_wait_time ?
824 wpa_s->dpp_resp_wait_time : 2000;
825 if (wait_time > max_wait_time)
826 wait_time = max_wait_time;
827 wait_time += 10; /* give the driver some extra time to complete */
828 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
829 wpas_dpp_reply_wait_timeout,
830 wpa_s, NULL);
831 wait_time -= 10;
832 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
833 wpa_printf(MSG_DEBUG,
834 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
835 freq, auth->neg_freq);
836 }
837 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
838 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
839 auth->auth_req_ack = 0;
840 os_get_reltime(&wpa_s->dpp_last_init);
841 return offchannel_send_action(wpa_s, freq, dst,
842 wpa_s->own_addr, broadcast,
843 wpabuf_head(auth->req_msg),
844 wpabuf_len(auth->req_msg),
845 wait_time, wpas_dpp_tx_status, 0);
846}
847
848
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700849int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
850{
851 const char *pos;
852 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700853 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700854 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
855 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700856 int tcp = 0;
857#ifdef CONFIG_DPP2
858 int tcp_port = DPP_TCP_PORT;
859 struct hostapd_ip_addr ipaddr;
860 char *addr;
861#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700862
863 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800864 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700865
866 pos = os_strstr(cmd, " peer=");
867 if (!pos)
868 return -1;
869 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700870 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700871 if (!peer_bi) {
872 wpa_printf(MSG_INFO,
873 "DPP: Could not find bootstrapping info for the identified peer");
874 return -1;
875 }
876
Hai Shalom81f62d82019-07-22 12:10:00 -0700877#ifdef CONFIG_DPP2
878 pos = os_strstr(cmd, " tcp_port=");
879 if (pos) {
880 pos += 10;
881 tcp_port = atoi(pos);
882 }
883
884 addr = get_param(cmd, " tcp_addr=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000885 if (addr && os_strcmp(addr, "from-uri") == 0) {
886 os_free(addr);
887 if (!peer_bi->host) {
888 wpa_printf(MSG_INFO,
889 "DPP: TCP address not available in peer URI");
890 return -1;
891 }
892 tcp = 1;
893 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
894 tcp_port = peer_bi->port;
895 } else if (addr) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700896 int res;
897
898 res = hostapd_parse_ip_addr(addr, &ipaddr);
899 os_free(addr);
900 if (res)
901 return -1;
902 tcp = 1;
903 }
904#endif /* CONFIG_DPP2 */
905
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700906 pos = os_strstr(cmd, " own=");
907 if (pos) {
908 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700909 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700910 if (!own_bi) {
911 wpa_printf(MSG_INFO,
912 "DPP: Could not find bootstrapping info for the identified local entry");
913 return -1;
914 }
915
916 if (peer_bi->curve != own_bi->curve) {
917 wpa_printf(MSG_INFO,
918 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
919 peer_bi->curve->name, own_bi->curve->name);
920 return -1;
921 }
922 }
923
924 pos = os_strstr(cmd, " role=");
925 if (pos) {
926 pos += 6;
927 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700928 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700929 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700930 allowed_roles = DPP_CAPAB_ENROLLEE;
931 else if (os_strncmp(pos, "either", 6) == 0)
932 allowed_roles = DPP_CAPAB_CONFIGURATOR |
933 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700934 else
935 goto fail;
936 }
937
938 pos = os_strstr(cmd, " netrole=");
939 if (pos) {
940 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800941 if (os_strncmp(pos, "ap", 2) == 0)
942 wpa_s->dpp_netrole = DPP_NETROLE_AP;
943 else if (os_strncmp(pos, "configurator", 12) == 0)
944 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
945 else
946 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700947 } else {
948 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700949 }
950
Roshan Pius3a1667e2018-07-03 15:17:14 -0700951 pos = os_strstr(cmd, " neg_freq=");
952 if (pos)
953 neg_freq = atoi(pos + 10);
954
Hai Shalom81f62d82019-07-22 12:10:00 -0700955 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700956 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700957 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800958 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
959 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700960 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
961 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700962#ifdef CONFIG_DPP2
963 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
964 wpa_s, NULL);
965#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700966 offchannel_send_action_done(wpa_s);
967 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800968 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700969 }
970
Hai Shalomfdcde762020-04-02 11:19:20 -0700971 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
972 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700973 if (!auth)
974 goto fail;
975 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700976 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700977 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800978 goto fail;
979 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700980
Hai Shalom81f62d82019-07-22 12:10:00 -0700981 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700982
Roshan Pius3a1667e2018-07-03 15:17:14 -0700983 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700984 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700985
Hai Shalom81f62d82019-07-22 12:10:00 -0700986#ifdef CONFIG_DPP2
987 if (tcp)
Hai Shalom899fcc72020-10-19 14:38:18 -0700988 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
989 wpa_s->conf->dpp_name, DPP_NETROLE_STA,
Sunil Ravi89eba102022-09-13 21:04:37 -0700990 wpa_s->conf->dpp_mud_url,
991 wpa_s->conf->dpp_extra_conf_req_name,
992 wpa_s->conf->dpp_extra_conf_req_value,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800993 wpa_s, wpa_s, wpas_dpp_process_conf_obj,
994 wpas_dpp_tcp_msg_sent);
Hai Shalom81f62d82019-07-22 12:10:00 -0700995#endif /* CONFIG_DPP2 */
996
997 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700998 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700999fail:
1000 return -1;
1001}
1002
1003
1004struct wpas_dpp_listen_work {
1005 unsigned int freq;
1006 unsigned int duration;
1007 struct wpabuf *probe_resp_ie;
1008};
1009
1010
1011static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
1012{
1013 if (!lwork)
1014 return;
1015 os_free(lwork);
1016}
1017
1018
1019static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
1020{
1021 struct wpas_dpp_listen_work *lwork;
1022
1023 if (!wpa_s->dpp_listen_work)
1024 return;
1025
1026 lwork = wpa_s->dpp_listen_work->ctx;
1027 wpas_dpp_listen_work_free(lwork);
1028 radio_work_done(wpa_s->dpp_listen_work);
1029 wpa_s->dpp_listen_work = NULL;
1030}
1031
1032
1033static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
1034{
1035 struct wpa_supplicant *wpa_s = work->wpa_s;
1036 struct wpas_dpp_listen_work *lwork = work->ctx;
1037
1038 if (deinit) {
1039 if (work->started) {
1040 wpa_s->dpp_listen_work = NULL;
1041 wpas_dpp_listen_stop(wpa_s);
1042 }
1043 wpas_dpp_listen_work_free(lwork);
1044 return;
1045 }
1046
1047 wpa_s->dpp_listen_work = work;
1048
1049 wpa_s->dpp_pending_listen_freq = lwork->freq;
1050
1051 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
1052 wpa_s->max_remain_on_chan) < 0) {
1053 wpa_printf(MSG_DEBUG,
1054 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
1055 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -08001056 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001057 wpas_dpp_listen_work_done(wpa_s);
1058 wpa_s->dpp_pending_listen_freq = 0;
1059 return;
1060 }
1061 wpa_s->off_channel_freq = 0;
1062 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -07001063 wpa_drv_dpp_listen(wpa_s, true);
Sunil Ravi99c035e2024-07-12 01:42:03 +00001064 wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
1065 wpa_s->dpp_tx_chan_change = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001066}
1067
1068
1069static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
1070 unsigned int freq)
1071{
1072 struct wpas_dpp_listen_work *lwork;
1073
1074 if (wpa_s->dpp_listen_work) {
1075 wpa_printf(MSG_DEBUG,
1076 "DPP: Reject start_listen since dpp_listen_work already exists");
1077 return -1;
1078 }
1079
1080 if (wpa_s->dpp_listen_freq)
1081 wpas_dpp_listen_stop(wpa_s);
1082 wpa_s->dpp_listen_freq = freq;
1083
1084 lwork = os_zalloc(sizeof(*lwork));
1085 if (!lwork)
1086 return -1;
1087 lwork->freq = freq;
1088
1089 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
1090 lwork) < 0) {
1091 wpas_dpp_listen_work_free(lwork);
1092 return -1;
1093 }
1094
1095 return 0;
1096}
1097
1098
1099int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
1100{
1101 int freq;
1102
1103 freq = atoi(cmd);
1104 if (freq <= 0)
1105 return -1;
1106
1107 if (os_strstr(cmd, " role=configurator"))
1108 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
1109 else if (os_strstr(cmd, " role=enrollee"))
1110 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
1111 else
1112 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
1113 DPP_CAPAB_ENROLLEE;
1114 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001115 if (os_strstr(cmd, " netrole=ap"))
1116 wpa_s->dpp_netrole = DPP_NETROLE_AP;
1117 else if (os_strstr(cmd, " netrole=configurator"))
1118 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
1119 else
1120 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001121 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1122 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1123 freq);
1124 return 0;
1125 }
1126
1127 return wpas_dpp_listen_start(wpa_s, freq);
1128}
1129
1130
1131void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1132{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001133 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001134 if (!wpa_s->dpp_listen_freq)
1135 return;
1136
1137 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1138 wpa_s->dpp_listen_freq);
1139 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001140 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001141 wpa_s->dpp_listen_freq = 0;
1142 wpas_dpp_listen_work_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001143 radio_remove_works(wpa_s, "dpp-listen", 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001144}
1145
1146
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001147void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1148 unsigned int freq, unsigned int duration)
1149{
1150 if (wpa_s->dpp_listen_freq != freq)
1151 return;
1152
1153 wpa_printf(MSG_DEBUG,
1154 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
1155 freq, duration);
1156 os_get_reltime(&wpa_s->dpp_listen_end);
1157 wpa_s->dpp_listen_end.usec += duration * 1000;
1158 while (wpa_s->dpp_listen_end.usec >= 1000000) {
1159 wpa_s->dpp_listen_end.sec++;
1160 wpa_s->dpp_listen_end.usec -= 1000000;
1161 }
1162}
1163
1164
Sunil Ravi99c035e2024-07-12 01:42:03 +00001165static void wpas_dpp_tx_auth_resp(struct wpa_supplicant *wpa_s)
1166{
1167 struct dpp_authentication *auth = wpa_s->dpp_auth;
1168
1169 if (!auth)
1170 return;
1171
1172 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1173 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
1174 DPP_PA_AUTHENTICATION_RESP);
1175 offchannel_send_action(wpa_s, auth->curr_freq,
1176 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
1177 wpabuf_head(auth->resp_msg),
1178 wpabuf_len(auth->resp_msg),
1179 500, wpas_dpp_tx_status, 0);
1180}
1181
1182
1183static void wpas_dpp_tx_auth_resp_roc_timeout(void *eloop_ctx,
1184 void *timeout_ctx)
1185{
1186 struct wpa_supplicant *wpa_s = eloop_ctx;
1187 struct dpp_authentication *auth = wpa_s->dpp_auth;
1188
1189 if (!auth || !wpa_s->dpp_tx_auth_resp_on_roc_stop)
1190 return;
1191
1192 wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
1193 wpa_s->dpp_tx_chan_change = true;
1194 wpa_printf(MSG_DEBUG,
1195 "DPP: Send postponed Authentication Response on remain-on-channel termination timeout");
1196 wpas_dpp_tx_auth_resp(wpa_s);
1197}
1198
1199
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001200void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1201 unsigned int freq)
1202{
Sunil Ravi99c035e2024-07-12 01:42:03 +00001203 wpa_printf(MSG_DEBUG, "DPP: Remain on channel cancel for %u MHz", freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001204 wpas_dpp_listen_work_done(wpa_s);
1205
Sunil Ravi99c035e2024-07-12 01:42:03 +00001206 if (wpa_s->dpp_auth && wpa_s->dpp_tx_auth_resp_on_roc_stop) {
1207 eloop_cancel_timeout(wpas_dpp_tx_auth_resp_roc_timeout,
1208 wpa_s, NULL);
1209 wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
1210 wpa_s->dpp_tx_chan_change = true;
1211 wpa_printf(MSG_DEBUG,
1212 "DPP: Send postponed Authentication Response on remain-on-channel termination");
1213 wpas_dpp_tx_auth_resp(wpa_s);
1214 return;
1215 }
1216
Roshan Pius3a1667e2018-07-03 15:17:14 -07001217 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1218 unsigned int new_freq;
1219
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001220 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001221 if (wpa_s->dpp_auth->neg_freq > 0)
1222 new_freq = wpa_s->dpp_auth->neg_freq;
1223 else
1224 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001225 wpa_printf(MSG_DEBUG,
1226 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001227 new_freq);
1228 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001229 return;
1230 }
1231
1232 if (wpa_s->dpp_listen_freq) {
1233 /* Continue listen with a new remain-on-channel */
1234 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1235 }
1236}
1237
1238
1239static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1240 const u8 *hdr, const u8 *buf, size_t len,
1241 unsigned int freq)
1242{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001243 const u8 *r_bootstrap, *i_bootstrap;
1244 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001245 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1246
1247 if (!wpa_s->dpp)
1248 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001249
1250 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1251 MAC2STR(src));
1252
Hai Shalomfdcde762020-04-02 11:19:20 -07001253#ifdef CONFIG_DPP2
1254 wpas_dpp_chirp_stop(wpa_s);
1255#endif /* CONFIG_DPP2 */
1256
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001257 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1258 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001259 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1260 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1261 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001262 return;
1263 }
1264 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1265 r_bootstrap, r_bootstrap_len);
1266
1267 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1268 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001269 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1270 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1271 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001272 return;
1273 }
1274 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1275 i_bootstrap, i_bootstrap_len);
1276
1277 /* Try to find own and peer bootstrapping key matches based on the
1278 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001279 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1280 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001281 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001282 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1283 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001284 return;
1285 }
1286
Sunil Ravi89eba102022-09-13 21:04:37 -07001287 if (own_bi->type == DPP_BOOTSTRAP_PKEX) {
1288 if (!peer_bi || peer_bi->type != DPP_BOOTSTRAP_PKEX) {
1289 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1290 "No matching peer bootstrapping key found for PKEX - ignore message");
1291 return;
1292 }
1293
1294 if (os_memcmp(peer_bi->pubkey_hash, own_bi->peer_pubkey_hash,
1295 SHA256_MAC_LEN) != 0) {
1296 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1297 "Mismatching peer PKEX bootstrapping key - ignore message");
1298 return;
1299 }
1300 }
1301
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001302 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001303 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1304 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001305 return;
1306 }
1307
Sunil Ravia04bd252022-05-02 22:54:18 -07001308 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001309 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001310 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001311 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001312 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1313 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001314 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001315 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001316 if (!wpa_s->dpp_auth) {
1317 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1318 return;
1319 }
1320 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001321 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001322 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001323 dpp_auth_deinit(wpa_s->dpp_auth);
1324 wpa_s->dpp_auth = NULL;
1325 return;
1326 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001327 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1328
Roshan Pius3a1667e2018-07-03 15:17:14 -07001329 if (wpa_s->dpp_listen_freq &&
1330 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1331 wpa_printf(MSG_DEBUG,
1332 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1333 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
Sunil Ravi99c035e2024-07-12 01:42:03 +00001334 wpa_s->dpp_tx_auth_resp_on_roc_stop = true;
1335 eloop_register_timeout(0, 100000,
1336 wpas_dpp_tx_auth_resp_roc_timeout,
1337 wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001338 wpas_dpp_listen_stop(wpa_s);
Sunil Ravi99c035e2024-07-12 01:42:03 +00001339 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001340 }
Sunil Ravi99c035e2024-07-12 01:42:03 +00001341 wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
1342 wpa_s->dpp_tx_chan_change = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001343
Sunil Ravi99c035e2024-07-12 01:42:03 +00001344 wpas_dpp_tx_auth_resp(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001345}
1346
1347
Hai Shaloma20dcd72022-02-04 13:43:00 -08001348void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
1349{
1350 struct dpp_authentication *auth = wpa_s->dpp_auth;
1351 int freq;
1352
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00001353#ifdef CONFIG_DPP3
1354 if (wpa_s->dpp_pb_announcement && wpa_s->dpp_pb_discovery_done) {
1355 wpa_printf(MSG_DEBUG,
1356 "DPP: Failed to send push button announcement");
1357 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
1358 wpa_s, NULL) < 0)
1359 wpas_dpp_push_button_stop(wpa_s);
1360 }
1361#endif /* CONFIG_DPP3 */
1362
Sunil Ravi99c035e2024-07-12 01:42:03 +00001363 if (wpa_s->dpp_listen_on_tx_expire && auth && auth->neg_freq) {
1364 wpa_printf(MSG_DEBUG,
1365 "DPP: Start listen on neg_freq %u MHz based on TX wait expiration on the previous channel",
1366 auth->neg_freq);
1367 eloop_cancel_timeout(wpas_dpp_neg_freq_timeout, wpa_s, NULL);
1368 wpas_dpp_listen_start(wpa_s, auth->neg_freq);
1369 return;
1370 }
1371
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001372 if (!wpa_s->dpp_gas_server || !auth) {
1373 if (auth && auth->waiting_auth_resp &&
1374 eloop_is_timeout_registered(wpas_dpp_drv_wait_timeout,
1375 wpa_s, NULL)) {
1376 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout,
1377 wpa_s, NULL);
1378 wpa_printf(MSG_DEBUG,
1379 "DPP: Call wpas_dpp_auth_init_next() from %s",
1380 __func__);
1381 wpas_dpp_auth_init_next(wpa_s);
1382 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001383 return;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001384 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001385
1386 freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
1387 if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
1388 return; /* listen state is already in progress */
1389
1390 wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
1391 wpa_s->dpp_in_response_listen = 1;
1392 wpas_dpp_listen_start(wpa_s, freq);
1393}
1394
1395
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001396static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1397{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001398 struct dpp_authentication *auth = wpa_s->dpp_auth;
1399
1400 wpa_printf(MSG_DEBUG,
1401 "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
1402 auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
1403 !!wpa_s->dpp_listen_work);
1404 wpa_s->dpp_gas_server = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001405}
1406
1407
1408static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001409 struct dpp_authentication *auth,
1410 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001411{
1412 struct wpa_ssid *ssid;
1413
Hai Shalom021b0b52019-04-10 11:17:58 -07001414#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001415 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001416#ifdef CONFIG_SAE
1417 struct wpa_driver_capa capa;
1418 int res;
1419
1420 res = wpa_drv_get_capa(wpa_s, &capa);
1421 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001422 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1423 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001424 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1425 wpa_printf(MSG_DEBUG,
1426 "DPP: SAE not supported by the driver");
1427 return NULL;
1428 }
1429#else /* CONFIG_SAE */
1430 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1431 return NULL;
1432#endif /* CONFIG_SAE */
1433 }
1434#endif /* CONFIG_DPP2 */
1435
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001436 ssid = wpa_config_add_network(wpa_s->conf);
1437 if (!ssid)
1438 return NULL;
1439 wpas_notify_network_added(wpa_s, ssid);
1440 wpa_config_set_network_defaults(ssid);
1441 ssid->disabled = 1;
1442
Hai Shalomc3565922019-10-28 11:58:20 -07001443 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001444 if (!ssid->ssid)
1445 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001446 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1447 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001448
Sunil Ravic0f5d412024-09-11 22:12:49 +00001449#ifdef CONFIG_DPP3
1450 if (conf->akm == DPP_AKM_SAE && conf->password_id[0]) {
1451 size_t len = os_strlen(conf->password_id);
1452
1453 ssid->sae_password_id = os_zalloc(len + 1);
1454 if (!ssid->sae_password_id)
1455 goto fail;
1456 os_memcpy(ssid->sae_password_id, conf->password_id, len);
1457 }
1458#endif /* CONFIG_DPP3 */
1459
Hai Shalomc3565922019-10-28 11:58:20 -07001460 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001461 if (dpp_akm_dpp(conf->akm)) {
1462 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1463 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1464 }
Hai Shalomc3565922019-10-28 11:58:20 -07001465 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001466 if (!ssid->dpp_connector)
1467 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07001468
1469 ssid->dpp_connector_privacy =
1470 wpa_s->conf->dpp_connector_privacy_default;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001471 }
1472
Hai Shalomc3565922019-10-28 11:58:20 -07001473 if (conf->c_sign_key) {
1474 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001475 if (!ssid->dpp_csign)
1476 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001477 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1478 wpabuf_len(conf->c_sign_key));
1479 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001480 }
1481
Hai Shalom899fcc72020-10-19 14:38:18 -07001482 if (conf->pp_key) {
1483 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1484 if (!ssid->dpp_pp_key)
1485 goto fail;
1486 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1487 wpabuf_len(conf->pp_key));
1488 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1489 }
1490
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001491 if (auth->net_access_key) {
1492 ssid->dpp_netaccesskey =
1493 os_malloc(wpabuf_len(auth->net_access_key));
1494 if (!ssid->dpp_netaccesskey)
1495 goto fail;
1496 os_memcpy(ssid->dpp_netaccesskey,
1497 wpabuf_head(auth->net_access_key),
1498 wpabuf_len(auth->net_access_key));
1499 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1500 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1501 }
1502
Hai Shalomc3565922019-10-28 11:58:20 -07001503 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1504 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001505 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001506 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001507 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001508 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1509 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001510 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001511 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1512 WPA_KEY_MGMT_FT_SAE;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001513 if (dpp_akm_psk(conf->akm))
1514 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1515 else
1516 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Sunil Ravic0f5d412024-09-11 22:12:49 +00001517 if (conf->passphrase[0] && dpp_akm_psk(conf->akm)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001518 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001519 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001520 goto fail;
1521 wpa_config_update_psk(ssid);
1522 ssid->export_keys = 1;
Sunil Ravic0f5d412024-09-11 22:12:49 +00001523 } else if (conf->passphrase[0] && dpp_akm_sae(conf->akm)) {
1524 if (wpa_config_set_quoted(ssid, "sae_password",
1525 conf->passphrase) < 0)
1526 goto fail;
1527 ssid->export_keys = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001528 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001529 ssid->psk_set = conf->psk_set;
1530 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001531 }
1532 }
1533
Hai Shalom899fcc72020-10-19 14:38:18 -07001534#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1535 if (conf->akm == DPP_AKM_DOT1X) {
1536 int i;
1537 char name[100], blobname[128];
1538 struct wpa_config_blob *blob;
1539
1540 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1541 WPA_KEY_MGMT_IEEE8021X_SHA256 |
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001542 WPA_KEY_MGMT_IEEE8021X_SHA384;
Hai Shalom899fcc72020-10-19 14:38:18 -07001543 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1544
1545 if (conf->cacert) {
1546 /* caCert is DER-encoded X.509v3 certificate for the
1547 * server certificate if that is different from the
1548 * trust root included in certBag. */
1549 /* TODO: ssid->eap.cert.ca_cert */
1550 }
1551
1552 if (conf->certs) {
1553 for (i = 0; ; i++) {
1554 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1555 i);
1556 if (!wpa_config_get_blob(wpa_s->conf, name))
1557 break;
1558 }
1559
1560 blob = os_zalloc(sizeof(*blob));
1561 if (!blob)
1562 goto fail;
1563 blob->len = wpabuf_len(conf->certs);
1564 blob->name = os_strdup(name);
1565 blob->data = os_malloc(blob->len);
1566 if (!blob->name || !blob->data) {
1567 wpa_config_free_blob(blob);
1568 goto fail;
1569 }
1570 os_memcpy(blob->data, wpabuf_head(conf->certs),
1571 blob->len);
1572 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1573 name);
1574 wpa_config_set_blob(wpa_s->conf, blob);
1575 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1576 name);
1577 ssid->eap.cert.client_cert = os_strdup(blobname);
1578 if (!ssid->eap.cert.client_cert)
1579 goto fail;
1580
1581 /* TODO: ssid->eap.identity from own certificate */
1582 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1583 0) < 0)
1584 goto fail;
1585 }
1586
1587 if (auth->priv_key) {
1588 for (i = 0; ; i++) {
1589 os_snprintf(name, sizeof(name), "dpp-key-%d",
1590 i);
1591 if (!wpa_config_get_blob(wpa_s->conf, name))
1592 break;
1593 }
1594
1595 blob = os_zalloc(sizeof(*blob));
1596 if (!blob)
1597 goto fail;
1598 blob->len = wpabuf_len(auth->priv_key);
1599 blob->name = os_strdup(name);
1600 blob->data = os_malloc(blob->len);
1601 if (!blob->name || !blob->data) {
1602 wpa_config_free_blob(blob);
1603 goto fail;
1604 }
1605 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1606 blob->len);
1607 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1608 name);
1609 wpa_config_set_blob(wpa_s->conf, blob);
1610 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1611 name);
1612 ssid->eap.cert.private_key = os_strdup(blobname);
1613 if (!ssid->eap.cert.private_key)
1614 goto fail;
1615 }
1616
1617 if (conf->server_name) {
1618 ssid->eap.cert.domain_suffix_match =
1619 os_strdup(conf->server_name);
1620 if (!ssid->eap.cert.domain_suffix_match)
1621 goto fail;
1622 }
1623
1624 /* TODO: Use entCreds::eapMethods */
1625 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1626 goto fail;
1627 }
1628#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1629
Hai Shalomc3565922019-10-28 11:58:20 -07001630 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1631 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1632
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001633 return ssid;
1634fail:
1635 wpas_notify_network_removed(wpa_s, ssid);
1636 wpa_config_remove_network(wpa_s->conf, ssid->id);
1637 return NULL;
1638}
1639
1640
Hai Shalom021b0b52019-04-10 11:17:58 -07001641static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001642 struct dpp_authentication *auth,
1643 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001644{
1645 struct wpa_ssid *ssid;
1646
1647 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001648 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001649
Hai Shalomc3565922019-10-28 11:58:20 -07001650 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001651 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001652 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001653
1654 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001655
Sunil Ravi546a7b52022-08-26 22:06:04 +00001656 wpas_notify_dpp_config_received(wpa_s, ssid, auth->conn_status_requested ? 1 : 0);
Hai Shalom59532852018-12-07 10:32:58 -08001657
Hai Shalom021b0b52019-04-10 11:17:58 -07001658 if (wpa_s->conf->dpp_config_processing == 2)
1659 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001660
Hai Shalom021b0b52019-04-10 11:17:58 -07001661#ifndef CONFIG_NO_CONFIG_WRITE
1662 if (wpa_s->conf->update_config &&
1663 wpa_config_write(wpa_s->confname, wpa_s->conf))
1664 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1665#endif /* CONFIG_NO_CONFIG_WRITE */
1666
Hai Shalomc3565922019-10-28 11:58:20 -07001667 return 0;
1668}
1669
1670
1671static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1672 struct dpp_authentication *auth)
1673{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001674#ifdef CONFIG_DPP2
1675 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1676 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1677 wpa_s->dpp_reconfig_ssid) {
1678 wpa_printf(MSG_DEBUG,
1679 "DPP: Remove reconfigured network profile");
1680 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1681 wpa_config_remove_network(wpa_s->conf,
1682 wpa_s->dpp_reconfig_ssid_id);
1683 wpa_s->dpp_reconfig_ssid = NULL;
1684 wpa_s->dpp_reconfig_ssid_id = -1;
1685 }
1686#endif /* CONFIG_DPP2 */
1687
Hai Shalom021b0b52019-04-10 11:17:58 -07001688 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001689 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001690
1691#ifdef CONFIG_DPP2
1692 if (auth->peer_version >= 2) {
1693 wpa_printf(MSG_DEBUG,
1694 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1695 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001696 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001697 }
1698#endif /* CONFIG_DPP2 */
1699
1700 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001701}
1702
1703
Hai Shalom021b0b52019-04-10 11:17:58 -07001704static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001705 struct dpp_authentication *auth,
1706 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001707{
1708 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001709 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1710 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001711 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001712 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001713 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001714 if (conf->ssid_charset)
1715 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1716 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001717 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001718 /* TODO: Save the Connector and consider using a command
1719 * to fetch the value instead of sending an event with
1720 * it. The Connector could end up being larger than what
1721 * most clients are ready to receive as an event
1722 * message. */
1723 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001724 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001725 }
Hai Shalom60840252021-02-19 19:02:11 -08001726 if (conf->passphrase[0]) {
1727 char hex[64 * 2 + 1];
1728
1729 wpa_snprintf_hex(hex, sizeof(hex),
1730 (const u8 *) conf->passphrase,
1731 os_strlen(conf->passphrase));
1732 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1733 hex);
1734 } else if (conf->psk_set) {
1735 char hex[PMK_LEN * 2 + 1];
1736
1737 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1738 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1739 hex);
1740 }
Sunil Ravic0f5d412024-09-11 22:12:49 +00001741#ifdef CONFIG_DPP3
1742 if (conf->password_id[0]) {
1743 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_IDPASS "%s",
1744 conf->password_id);
1745 }
1746#endif /* CONFIG_DPP3 */
Hai Shalomc3565922019-10-28 11:58:20 -07001747 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001748 char *hex;
1749 size_t hexlen;
1750
Hai Shalomc3565922019-10-28 11:58:20 -07001751 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001752 hex = os_malloc(hexlen);
1753 if (hex) {
1754 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001755 wpabuf_head(conf->c_sign_key),
1756 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001757 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1758 hex);
1759 os_free(hex);
1760 }
1761 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001762 if (conf->pp_key) {
1763 char *hex;
1764 size_t hexlen;
1765
1766 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1767 hex = os_malloc(hexlen);
1768 if (hex) {
1769 wpa_snprintf_hex(hex, hexlen,
1770 wpabuf_head(conf->pp_key),
1771 wpabuf_len(conf->pp_key));
1772 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1773 os_free(hex);
1774 }
1775 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001776 if (auth->net_access_key) {
1777 char *hex;
1778 size_t hexlen;
1779
1780 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1781 hex = os_malloc(hexlen);
1782 if (hex) {
1783 wpa_snprintf_hex(hex, hexlen,
1784 wpabuf_head(auth->net_access_key),
1785 wpabuf_len(auth->net_access_key));
1786 if (auth->net_access_key_expiry)
1787 wpa_msg(wpa_s, MSG_INFO,
1788 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1789 (long unsigned)
1790 auth->net_access_key_expiry);
1791 else
1792 wpa_msg(wpa_s, MSG_INFO,
1793 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1794 os_free(hex);
1795 }
1796 }
1797
Hai Shalom899fcc72020-10-19 14:38:18 -07001798#ifdef CONFIG_DPP2
1799 if (conf->certbag) {
1800 char *b64;
1801
1802 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1803 wpabuf_len(conf->certbag), NULL);
1804 if (b64)
1805 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1806 os_free(b64);
1807 }
1808
1809 if (conf->cacert) {
1810 char *b64;
1811
1812 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1813 wpabuf_len(conf->cacert), NULL);
1814 if (b64)
1815 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1816 os_free(b64);
1817 }
1818
1819 if (conf->server_name)
1820 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1821 conf->server_name);
1822#endif /* CONFIG_DPP2 */
1823
Sunil Ravi89eba102022-09-13 21:04:37 -07001824#ifdef CONFIG_DPP3
1825 if (!wpa_s->dpp_pb_result_indicated) {
1826 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "success");
1827 wpa_s->dpp_pb_result_indicated = true;
1828 }
1829
1830#endif /* CONFIG_DPP3 */
1831
Hai Shalomc3565922019-10-28 11:58:20 -07001832 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001833}
1834
1835
Hai Shalomfdcde762020-04-02 11:19:20 -07001836static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1837 struct dpp_asymmetric_key *key)
1838{
1839#ifdef CONFIG_DPP2
1840 int res;
1841
1842 if (!key)
1843 return 0;
1844
1845 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1846 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001847 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001848
1849 while (key) {
1850 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1851 if (res < 0)
1852 return -1;
1853 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1854 res);
1855 key = key->next;
1856 }
1857#endif /* CONFIG_DPP2 */
1858
1859 return 0;
1860}
1861
1862
Hai Shalom899fcc72020-10-19 14:38:18 -07001863#ifdef CONFIG_DPP2
1864static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1865{
1866 struct wpa_supplicant *wpa_s = eloop_ctx;
1867 struct dpp_authentication *auth = wpa_s->dpp_auth;
1868
1869 if (!auth || !auth->csrattrs)
1870 return;
1871
1872 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1873 wpabuf_free(auth->csr);
1874 /* TODO: Additional information needed for CSR based on csrAttrs */
1875 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1876 wpa_s->conf->dpp_name : "Test");
1877 if (!auth->csr) {
1878 dpp_auth_deinit(wpa_s->dpp_auth);
1879 wpa_s->dpp_auth = NULL;
1880 return;
1881 }
1882
1883 wpas_dpp_start_gas_client(wpa_s);
1884}
1885#endif /* CONFIG_DPP2 */
1886
1887
Sunil Ravia04bd252022-05-02 22:54:18 -07001888#ifdef CONFIG_DPP3
1889static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1890{
1891 struct wpa_supplicant *wpa_s = eloop_ctx;
1892 struct dpp_authentication *auth = wpa_s->dpp_auth;
1893
1894 if (!auth || !auth->waiting_new_key)
1895 return;
1896
1897 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1898 wpas_dpp_start_gas_client(wpa_s);
1899}
1900#endif /* CONFIG_DPP3 */
1901
1902
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001903static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1904 enum gas_query_result result,
1905 const struct wpabuf *adv_proto,
1906 const struct wpabuf *resp, u16 status_code)
1907{
1908 struct wpa_supplicant *wpa_s = ctx;
1909 const u8 *pos;
1910 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001911 int res;
1912 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001913 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001914
Hai Shaloma20dcd72022-02-04 13:43:00 -08001915 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001916 wpa_s->dpp_gas_dialog_token = -1;
1917
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001918 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001919 !ether_addr_equal(addr, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001920 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1921 return;
1922 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001923 if (result != GAS_QUERY_SUCCESS ||
1924 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001925 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1926 goto fail;
1927 }
1928
1929 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1930 adv_proto);
1931 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1932 resp);
1933
1934 if (wpabuf_len(adv_proto) != 10 ||
1935 !(pos = wpabuf_head(adv_proto)) ||
1936 pos[0] != WLAN_EID_ADV_PROTO ||
1937 pos[1] != 8 ||
1938 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1939 pos[4] != 5 ||
1940 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1941 pos[8] != 0x1a ||
1942 pos[9] != 1) {
1943 wpa_printf(MSG_DEBUG,
1944 "DPP: Not a DPP Advertisement Protocol ID");
1945 goto fail;
1946 }
1947
Hai Shalom899fcc72020-10-19 14:38:18 -07001948 res = dpp_conf_resp_rx(auth, resp);
1949#ifdef CONFIG_DPP2
1950 if (res == -2) {
1951 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1952 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1953 return;
1954 }
1955#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001956#ifdef CONFIG_DPP3
1957 if (res == -3) {
1958 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1959 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1960 NULL);
1961 return;
1962 }
1963#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001964 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001965 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1966 goto fail;
1967 }
1968
Hai Shalom899fcc72020-10-19 14:38:18 -07001969 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001970 for (i = 0; i < auth->num_conf_obj; i++) {
1971 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1972 &auth->conf_obj[i]);
1973 if (res < 0)
1974 goto fail;
1975 }
1976 if (auth->num_conf_obj)
1977 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001978 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1979 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001980
Hai Shalom021b0b52019-04-10 11:17:58 -07001981 status = DPP_STATUS_OK;
1982#ifdef CONFIG_TESTING_OPTIONS
1983 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1984 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1985 status = DPP_STATUS_CONFIG_REJECTED;
1986 }
1987#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001988fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001989 if (status != DPP_STATUS_OK) {
1990 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1991 wpas_notify_dpp_configuration_failure(wpa_s);
1992 }
1993#ifdef CONFIG_DPP2
1994 if (auth->peer_version >= 2 &&
1995 auth->conf_resp_status == DPP_STATUS_OK) {
1996 struct wpabuf *msg;
1997
1998 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1999 msg = dpp_build_conf_result(auth, status);
2000 if (!msg)
2001 goto fail2;
2002
2003 wpa_msg(wpa_s, MSG_INFO,
2004 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2005 MAC2STR(addr), auth->curr_freq,
2006 DPP_PA_CONFIGURATION_RESULT);
2007 offchannel_send_action(wpa_s, auth->curr_freq,
2008 addr, wpa_s->own_addr, broadcast,
2009 wpabuf_head(msg),
2010 wpabuf_len(msg),
2011 500, wpas_dpp_tx_status, 0);
2012 wpabuf_free(msg);
2013
2014 /* This exchange will be terminated in the TX status handler */
Sunil Ravi546a7b52022-08-26 22:06:04 +00002015 if (wpa_s->conf->dpp_config_processing < 1 ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002016 wpa_s->dpp_conf_backup_received)
2017 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07002018 return;
2019 }
2020fail2:
2021#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002022 dpp_auth_deinit(wpa_s->dpp_auth);
2023 wpa_s->dpp_auth = NULL;
2024}
2025
2026
Hai Shaloma20dcd72022-02-04 13:43:00 -08002027static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
2028{
2029 struct wpa_supplicant *wpa_s = eloop_ctx;
2030 struct dpp_authentication *auth = wpa_s->dpp_auth;
2031
2032 if (!wpa_s->dpp_gas_client || !auth ||
2033 (!auth->auth_success && !auth->reconfig_success))
2034 return;
2035
2036 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
2037 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
2038 dpp_auth_deinit(wpa_s->dpp_auth);
2039 wpa_s->dpp_auth = NULL;
2040}
2041
2042
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002043static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
2044{
2045 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07002046 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002047 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07002048 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002049
2050 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002051 offchannel_send_action_done(wpa_s);
2052 wpas_dpp_listen_stop(wpa_s);
2053
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002054#ifdef CONFIG_NO_RRM
2055 supp_op_classes = NULL;
2056#else /* CONFIG_NO_RRM */
Hai Shalomc3565922019-10-28 11:58:20 -07002057 supp_op_classes = wpas_supp_op_classes(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002058#endif /* CONFIG_NO_RRM */
Hai Shalomc3565922019-10-28 11:58:20 -07002059 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002060 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07002061 wpa_s->conf->dpp_mud_url,
Sunil Ravi89eba102022-09-13 21:04:37 -07002062 supp_op_classes,
2063 wpa_s->conf->dpp_extra_conf_req_name,
2064 wpa_s->conf->dpp_extra_conf_req_value);
Hai Shalomc3565922019-10-28 11:58:20 -07002065 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07002066 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002067 wpa_printf(MSG_DEBUG,
2068 "DPP: No configuration request data available");
2069 return;
2070 }
2071
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002072 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
2073 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
2074
Hai Shaloma20dcd72022-02-04 13:43:00 -08002075 /* Use a 120 second timeout since the gas_query_req() operation could
2076 * remain waiting indefinitely for the response if the Configurator
2077 * keeps sending out comeback responses with additional delay. The
2078 * DPP technical specification expects the Enrollee to continue sending
2079 * out new Config Requests for 60 seconds, so this gives an extra 60
2080 * second time after the last expected new Config Request for the
2081 * Configurator to determine what kind of configuration to provide. */
2082 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
2083 wpa_s, NULL);
2084
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002085 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07002086 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002087 if (res < 0) {
2088 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
2089 wpabuf_free(buf);
2090 } else {
2091 wpa_printf(MSG_DEBUG,
2092 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002093 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002094 }
2095}
2096
2097
2098static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
2099{
2100 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002101 dpp_notify_auth_success(wpa_s->dpp_auth, initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08002102 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002103#ifdef CONFIG_TESTING_OPTIONS
2104 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
2105 wpa_printf(MSG_INFO,
2106 "DPP: TESTING - stop at Authentication Confirm");
2107 if (wpa_s->dpp_auth->configurator) {
2108 /* Prevent GAS response */
2109 wpa_s->dpp_auth->auth_success = 0;
2110 }
2111 return;
2112 }
2113#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002114
2115 if (wpa_s->dpp_auth->configurator)
2116 wpas_dpp_start_gas_server(wpa_s);
2117 else
2118 wpas_dpp_start_gas_client(wpa_s);
2119}
2120
2121
2122static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002123 const u8 *hdr, const u8 *buf, size_t len,
2124 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002125{
2126 struct dpp_authentication *auth = wpa_s->dpp_auth;
2127 struct wpabuf *msg;
2128
Roshan Pius3a1667e2018-07-03 15:17:14 -07002129 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
2130 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002131
2132 if (!auth) {
2133 wpa_printf(MSG_DEBUG,
2134 "DPP: No DPP Authentication in progress - drop");
2135 return;
2136 }
2137
2138 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002139 !ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002140 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2141 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2142 return;
2143 }
2144
2145 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
2146
Roshan Pius3a1667e2018-07-03 15:17:14 -07002147 if (auth->curr_freq != freq && auth->neg_freq == freq) {
2148 wpa_printf(MSG_DEBUG,
2149 "DPP: Responder accepted request for different negotiation channel");
2150 auth->curr_freq = freq;
2151 }
2152
2153 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002154 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
2155 if (!msg) {
2156 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
2157 wpa_printf(MSG_DEBUG,
2158 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08002159 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002160 offchannel_send_action_done(wpa_s);
2161 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
2162 return;
2163 }
2164 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
2165 return;
2166 }
2167 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2168
Roshan Pius3a1667e2018-07-03 15:17:14 -07002169 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2170 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002171 offchannel_send_action(wpa_s, auth->curr_freq,
2172 src, wpa_s->own_addr, broadcast,
2173 wpabuf_head(msg), wpabuf_len(msg),
2174 500, wpas_dpp_tx_status, 0);
2175 wpabuf_free(msg);
2176 wpa_s->dpp_auth_ok_on_ack = 1;
2177}
2178
2179
2180static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2181 const u8 *hdr, const u8 *buf, size_t len)
2182{
2183 struct dpp_authentication *auth = wpa_s->dpp_auth;
2184
2185 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
2186 MAC2STR(src));
2187
2188 if (!auth) {
2189 wpa_printf(MSG_DEBUG,
2190 "DPP: No DPP Authentication in progress - drop");
2191 return;
2192 }
2193
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002194 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002195 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2196 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2197 return;
2198 }
2199
Hai Shalom60840252021-02-19 19:02:11 -08002200 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
2201
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002202 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
2203 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08002204 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002205 return;
2206 }
2207
2208 wpas_dpp_auth_success(wpa_s, 0);
2209}
2210
2211
Hai Shalom021b0b52019-04-10 11:17:58 -07002212#ifdef CONFIG_DPP2
2213
2214static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
2215 void *timeout_ctx)
2216{
2217 struct wpa_supplicant *wpa_s = eloop_ctx;
2218 struct dpp_authentication *auth = wpa_s->dpp_auth;
2219
2220 if (!auth || !auth->waiting_conf_result)
2221 return;
2222
2223 wpa_printf(MSG_DEBUG,
2224 "DPP: Timeout while waiting for Configuration Result");
2225 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002226 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002227 dpp_auth_deinit(auth);
2228 wpa_s->dpp_auth = NULL;
2229}
2230
2231
Hai Shalomc3565922019-10-28 11:58:20 -07002232static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2233 void *timeout_ctx)
2234{
2235 struct wpa_supplicant *wpa_s = eloop_ctx;
2236 struct dpp_authentication *auth = wpa_s->dpp_auth;
2237
2238 if (!auth || !auth->waiting_conn_status_result)
2239 return;
2240
2241 wpa_printf(MSG_DEBUG,
2242 "DPP: Timeout while waiting for Connection Status Result");
2243 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002244 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002245 wpas_dpp_listen_stop(wpa_s);
2246 dpp_auth_deinit(auth);
2247 wpa_s->dpp_auth = NULL;
2248}
2249
2250
Sunil Ravi89eba102022-09-13 21:04:37 -07002251#ifdef CONFIG_DPP3
2252
2253static bool wpas_dpp_pb_active(struct wpa_supplicant *wpa_s)
2254{
2255 return (wpa_s->dpp_pb_time.sec || wpa_s->dpp_pb_time.usec) &&
2256 wpa_s->dpp_pb_configurator;
2257}
2258
2259
2260static void wpas_dpp_remove_pb_hash(struct wpa_supplicant *wpa_s)
2261{
2262 int i;
2263
2264 if (!wpa_s->dpp_pb_bi)
2265 return;
2266 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2267 struct dpp_pb_info *info = &wpa_s->dpp_pb[i];
2268
2269 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
2270 continue;
2271 if (os_memcmp(info->hash, wpa_s->dpp_pb_resp_hash,
2272 SHA256_MAC_LEN) == 0) {
2273 /* Allow a new push button session to be established
2274 * immediately without the successfully completed
2275 * session triggering session overlap. */
2276 info->rx_time.sec = 0;
2277 info->rx_time.usec = 0;
2278 wpa_printf(MSG_DEBUG,
2279 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
2280 }
2281 }
2282}
2283
2284#endif /* CONFIG_DPP3 */
2285
2286
Hai Shalom021b0b52019-04-10 11:17:58 -07002287static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2288 const u8 *hdr, const u8 *buf, size_t len)
2289{
2290 struct dpp_authentication *auth = wpa_s->dpp_auth;
2291 enum dpp_status_error status;
2292
2293 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2294 MAC2STR(src));
2295
2296 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002297 if (auth &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002298 ether_addr_equal(src, auth->peer_mac_addr) &&
Hai Shalom60840252021-02-19 19:02:11 -08002299 gas_server_response_sent(wpa_s->gas_server,
2300 auth->gas_server_ctx)) {
2301 /* This could happen if the TX status event gets delayed
2302 * long enough for the Enrollee to have time to send
2303 * the next frame before the TX status gets processed
2304 * locally. */
2305 wpa_printf(MSG_DEBUG,
2306 "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");
2307 auth->waiting_conf_result = 1;
2308 } else {
2309 wpa_printf(MSG_DEBUG,
2310 "DPP: No DPP Configuration waiting for result - drop");
2311 return;
2312 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002313 }
2314
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002315 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002316 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2317 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2318 return;
2319 }
2320
2321 status = dpp_conf_result_rx(auth, hdr, buf, len);
2322
Hai Shalomc3565922019-10-28 11:58:20 -07002323 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002324 int freq;
2325
Hai Shalomc3565922019-10-28 11:58:20 -07002326 wpa_msg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07002327 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
2328 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07002329 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002330 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002331 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2332 wpa_s, NULL);
2333 auth->waiting_conn_status_result = 1;
2334 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2335 wpa_s, NULL);
2336 eloop_register_timeout(16, 0,
2337 wpas_dpp_conn_status_result_wait_timeout,
2338 wpa_s, NULL);
2339 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002340 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2341 if (!wpa_s->dpp_in_response_listen ||
2342 (int) wpa_s->dpp_listen_freq != freq)
2343 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002344 return;
2345 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002346 offchannel_send_action_done(wpa_s);
2347 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002348 if (status == DPP_STATUS_OK) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002349 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
2350 auth->conf_resp_status);
Hai Shalome4073332019-11-05 16:20:12 -08002351 wpas_notify_dpp_config_sent(wpa_s);
2352 }
2353 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002354 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002355 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002356 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002357 dpp_auth_deinit(auth);
2358 wpa_s->dpp_auth = NULL;
2359 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07002360#ifdef CONFIG_DPP3
2361 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
2362 if (status == DPP_STATUS_OK)
2363 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2364 "success");
2365 else
2366 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2367 "no-configuration-available");
2368 wpa_s->dpp_pb_result_indicated = true;
2369 if (status == DPP_STATUS_OK)
2370 wpas_dpp_remove_pb_hash(wpa_s);
2371 wpas_dpp_push_button_stop(wpa_s);
2372 }
2373#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002374}
2375
Hai Shalom81f62d82019-07-22 12:10:00 -07002376
Hai Shalomc3565922019-10-28 11:58:20 -07002377static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2378 const u8 *src, const u8 *hdr,
2379 const u8 *buf, size_t len)
2380{
2381 struct dpp_authentication *auth = wpa_s->dpp_auth;
2382 enum dpp_status_error status;
2383 u8 ssid[SSID_MAX_LEN];
2384 size_t ssid_len = 0;
2385 char *channel_list = NULL;
2386
2387 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2388
2389 if (!auth || !auth->waiting_conn_status_result) {
2390 wpa_printf(MSG_DEBUG,
2391 "DPP: No DPP Configuration waiting for connection status result - drop");
2392 return;
2393 }
2394
2395 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2396 ssid, &ssid_len, &channel_list);
2397 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2398 "result=%d ssid=%s channel_list=%s",
2399 status, wpa_ssid_txt(ssid, ssid_len),
2400 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002401 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2402 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002403 os_free(channel_list);
2404 offchannel_send_action_done(wpa_s);
2405 wpas_dpp_listen_stop(wpa_s);
2406 dpp_auth_deinit(auth);
2407 wpa_s->dpp_auth = NULL;
2408 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2409 wpa_s, NULL);
2410}
2411
2412
Hai Shalom81f62d82019-07-22 12:10:00 -07002413static int wpas_dpp_process_conf_obj(void *ctx,
2414 struct dpp_authentication *auth)
2415{
2416 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002417 unsigned int i;
2418 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002419
Hai Shalomc3565922019-10-28 11:58:20 -07002420 for (i = 0; i < auth->num_conf_obj; i++) {
2421 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2422 &auth->conf_obj[i]);
2423 if (res)
2424 break;
2425 }
2426 if (!res)
2427 wpas_dpp_post_process_config(wpa_s, auth);
2428
2429 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002430}
2431
Hai Shalomfdcde762020-04-02 11:19:20 -07002432
Hai Shaloma20dcd72022-02-04 13:43:00 -08002433static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2434{
2435 struct wpa_supplicant *wpa_s = ctx;
2436
2437 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2438
2439 if (auth->connect_on_tx_status) {
2440 auth->connect_on_tx_status = 0;
2441 wpa_printf(MSG_DEBUG,
2442 "DPP: Try to connect after completed configuration result");
2443 wpas_dpp_try_to_connect(wpa_s);
2444 if (auth->conn_status_requested) {
2445 wpa_printf(MSG_DEBUG,
2446 "DPP: Start 15 second timeout for reporting connection status result");
2447 eloop_cancel_timeout(
2448 wpas_dpp_conn_status_result_timeout,
2449 wpa_s, NULL);
2450 eloop_register_timeout(
2451 15, 0, wpas_dpp_conn_status_result_timeout,
2452 wpa_s, NULL);
2453 return true;
2454 }
2455 }
2456
2457 return false;
2458}
2459
2460
Hai Shalomfdcde762020-04-02 11:19:20 -07002461static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2462{
2463 struct wpa_supplicant *wpa_s = ctx;
2464
2465 if (bi == wpa_s->dpp_chirp_bi)
2466 wpas_dpp_chirp_stop(wpa_s);
2467}
2468
2469
2470static void
2471wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2472 const u8 *hdr, const u8 *buf, size_t len,
2473 unsigned int freq)
2474{
2475 const u8 *r_bootstrap;
2476 u16 r_bootstrap_len;
2477 struct dpp_bootstrap_info *peer_bi;
2478 struct dpp_authentication *auth;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002479 unsigned int wait_time, max_wait_time;
Hai Shalomfdcde762020-04-02 11:19:20 -07002480
2481 if (!wpa_s->dpp)
2482 return;
2483
2484 if (wpa_s->dpp_auth) {
2485 wpa_printf(MSG_DEBUG,
2486 "DPP: Ignore Presence Announcement during ongoing Authentication");
2487 return;
2488 }
2489
2490 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2491 MAC2STR(src));
2492
2493 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2494 &r_bootstrap_len);
2495 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2496 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2497 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2498 return;
2499 }
2500 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2501 r_bootstrap, r_bootstrap_len);
2502 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002503 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2504 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002505 if (!peer_bi) {
2506 wpa_printf(MSG_DEBUG,
2507 "DPP: No matching bootstrapping information found");
2508 return;
2509 }
2510
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002511 wpa_printf(MSG_DEBUG, "DPP: Start Authentication exchange with " MACSTR
2512 " based on the received Presence Announcement",
2513 MAC2STR(src));
Hai Shalomfdcde762020-04-02 11:19:20 -07002514 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2515 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2516 if (!auth)
2517 return;
2518 wpas_dpp_set_testing_options(wpa_s, auth);
2519 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2520 dpp_auth_deinit(auth);
2521 return;
2522 }
2523
2524 auth->neg_freq = freq;
2525
Hai Shalom60840252021-02-19 19:02:11 -08002526 /* The source address of the Presence Announcement frame overrides any
2527 * MAC address information from the bootstrapping information. */
2528 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002529
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002530 wait_time = wpa_s->max_remain_on_chan;
2531 max_wait_time = wpa_s->dpp_resp_wait_time ?
2532 wpa_s->dpp_resp_wait_time : 2000;
2533 if (wait_time > max_wait_time)
2534 wait_time = max_wait_time;
2535 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2536
Hai Shalomfdcde762020-04-02 11:19:20 -07002537 wpa_s->dpp_auth = auth;
2538 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2539 dpp_auth_deinit(wpa_s->dpp_auth);
2540 wpa_s->dpp_auth = NULL;
2541 }
2542}
2543
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002544
2545static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2546 void *timeout_ctx)
2547{
2548 struct wpa_supplicant *wpa_s = eloop_ctx;
2549 struct dpp_authentication *auth = wpa_s->dpp_auth;
2550
2551 if (!auth)
2552 return;
2553
2554 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2555 offchannel_send_action_done(wpa_s);
2556 wpas_dpp_listen_stop(wpa_s);
2557 dpp_auth_deinit(auth);
2558 wpa_s->dpp_auth = NULL;
2559}
2560
2561
2562static void
2563wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2564 const u8 *hdr, const u8 *buf, size_t len,
2565 unsigned int freq)
2566{
Hai Shalom899fcc72020-10-19 14:38:18 -07002567 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2568 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002569 struct dpp_configurator *conf;
2570 struct dpp_authentication *auth;
2571 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002572 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002573
2574 if (!wpa_s->dpp)
2575 return;
2576
2577 if (wpa_s->dpp_auth) {
2578 wpa_printf(MSG_DEBUG,
2579 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2580 return;
2581 }
2582
2583 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2584 MAC2STR(src));
2585
2586 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2587 &csign_hash_len);
2588 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2589 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2590 "Missing or invalid required Configurator C-sign key Hash attribute");
2591 return;
2592 }
2593 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2594 csign_hash, csign_hash_len);
2595 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2596 if (!conf) {
2597 wpa_printf(MSG_DEBUG,
2598 "DPP: No matching Configurator information found");
2599 return;
2600 }
2601
Hai Shalom899fcc72020-10-19 14:38:18 -07002602 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2603 &fcgroup_len);
2604 if (!fcgroup || fcgroup_len != 2) {
2605 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2606 "Missing or invalid required Finite Cyclic Group attribute");
2607 return;
2608 }
2609 group = WPA_GET_LE16(fcgroup);
2610 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2611
2612 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2613 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2614
2615 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2616 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002617 if (!auth)
2618 return;
2619 wpas_dpp_set_testing_options(wpa_s, auth);
2620 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2621 dpp_auth_deinit(auth);
2622 return;
2623 }
2624
2625 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2626 wpa_s->dpp_auth = auth;
2627
2628 wpa_s->dpp_in_response_listen = 0;
2629 wpa_s->dpp_auth_ok_on_ack = 0;
2630 wait_time = wpa_s->max_remain_on_chan;
2631 max_wait_time = wpa_s->dpp_resp_wait_time ?
2632 wpa_s->dpp_resp_wait_time : 2000;
2633 if (wait_time > max_wait_time)
2634 wait_time = max_wait_time;
2635 wait_time += 10; /* give the driver some extra time to complete */
2636 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2637 wpas_dpp_reconfig_reply_wait_timeout,
2638 wpa_s, NULL);
2639 wait_time -= 10;
2640
2641 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2642
2643 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2644 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2645 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2646 wpabuf_head(auth->reconfig_req_msg),
2647 wpabuf_len(auth->reconfig_req_msg),
2648 wait_time, wpas_dpp_tx_status, 0) < 0) {
2649 dpp_auth_deinit(wpa_s->dpp_auth);
2650 wpa_s->dpp_auth = NULL;
2651 }
2652}
2653
2654
2655static void
2656wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2657 const u8 *hdr, const u8 *buf, size_t len,
2658 unsigned int freq)
2659{
2660 struct wpa_ssid *ssid;
2661 struct dpp_authentication *auth;
2662
2663 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2664 MACSTR, MAC2STR(src));
2665
Hai Shalom899fcc72020-10-19 14:38:18 -07002666 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002667 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002668 if (wpa_s->dpp_auth) {
2669 wpa_printf(MSG_DEBUG,
2670 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2671 return;
2672 }
2673 if (!wpa_s->dpp_reconfig_ssid) {
2674 wpa_printf(MSG_DEBUG,
2675 "DPP: Not ready for reconfiguration - not requested");
2676 return;
2677 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002678 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2679 if (ssid == wpa_s->dpp_reconfig_ssid &&
2680 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2681 break;
2682 }
2683 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002684 !ssid->dpp_csign) {
2685 wpa_printf(MSG_DEBUG,
2686 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002687 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002688 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002689
2690 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2691 ssid->dpp_netaccesskey,
2692 ssid->dpp_netaccesskey_len,
2693 ssid->dpp_csign, ssid->dpp_csign_len,
2694 freq, hdr, buf, len);
2695 if (!auth)
2696 return;
2697 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2698 wpa_s->dpp_auth = auth;
2699
2700 wpas_dpp_chirp_stop(wpa_s);
2701
2702 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2703 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2704 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2705 wpabuf_head(auth->reconfig_resp_msg),
2706 wpabuf_len(auth->reconfig_resp_msg),
2707 500, wpas_dpp_tx_status, 0) < 0) {
2708 dpp_auth_deinit(wpa_s->dpp_auth);
2709 wpa_s->dpp_auth = NULL;
2710 }
2711}
2712
2713
2714static void
2715wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2716 const u8 *hdr, const u8 *buf, size_t len,
2717 unsigned int freq)
2718{
2719 struct dpp_authentication *auth = wpa_s->dpp_auth;
2720 struct wpabuf *conf;
2721
2722 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2723 MACSTR, MAC2STR(src));
2724
2725 if (!auth || !auth->reconfig || !auth->configurator) {
2726 wpa_printf(MSG_DEBUG,
2727 "DPP: No DPP Reconfig Authentication in progress - drop");
2728 return;
2729 }
2730
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002731 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002732 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2733 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2734 return;
2735 }
2736
2737 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2738 if (!conf)
2739 return;
2740
2741 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2742
2743 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2744 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2745 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2746 wpabuf_head(conf), wpabuf_len(conf),
2747 500, wpas_dpp_tx_status, 0) < 0) {
2748 wpabuf_free(conf);
2749 dpp_auth_deinit(wpa_s->dpp_auth);
2750 wpa_s->dpp_auth = NULL;
2751 return;
2752 }
2753 wpabuf_free(conf);
2754
2755 wpas_dpp_start_gas_server(wpa_s);
2756}
2757
2758
2759static void
2760wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2761 const u8 *hdr, const u8 *buf, size_t len,
2762 unsigned int freq)
2763{
2764 struct dpp_authentication *auth = wpa_s->dpp_auth;
2765
2766 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2767 MACSTR, MAC2STR(src));
2768
2769 if (!auth || !auth->reconfig || auth->configurator) {
2770 wpa_printf(MSG_DEBUG,
2771 "DPP: No DPP Reconfig Authentication in progress - drop");
2772 return;
2773 }
2774
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002775 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002776 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2777 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2778 return;
2779 }
2780
2781 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2782 return;
2783
2784 wpas_dpp_start_gas_client(wpa_s);
2785}
2786
Hai Shalom021b0b52019-04-10 11:17:58 -07002787#endif /* CONFIG_DPP2 */
2788
2789
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002790static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2791 const u8 *src,
2792 const u8 *buf, size_t len)
2793{
2794 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002795 const u8 *connector, *trans_id, *status;
2796 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002797#ifdef CONFIG_DPP2
2798 const u8 *version;
2799 u16 version_len;
2800#endif /* CONFIG_DPP2 */
2801 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002802 struct dpp_introduction intro;
2803 struct rsn_pmksa_cache_entry *entry;
2804 struct os_time now;
2805 struct os_reltime rnow;
2806 os_time_t expiry;
2807 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002808 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002809
2810 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2811 MAC2STR(src));
2812 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002813 !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002814 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2815 MACSTR " - drop", MAC2STR(src));
2816 return;
2817 }
2818 offchannel_send_action_done(wpa_s);
2819
2820 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2821 if (ssid == wpa_s->dpp_intro_network)
2822 break;
2823 }
2824 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2825 !ssid->dpp_csign) {
2826 wpa_printf(MSG_DEBUG,
2827 "DPP: Profile not found for network introduction");
2828 return;
2829 }
2830
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002831 os_memset(&intro, 0, sizeof(intro));
2832
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002833 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2834 &trans_id_len);
2835 if (!trans_id || trans_id_len != 1) {
2836 wpa_printf(MSG_DEBUG,
2837 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002838 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2839 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002840 goto fail;
2841 }
2842 if (trans_id[0] != TRANSACTION_ID) {
2843 wpa_printf(MSG_DEBUG,
2844 "DPP: Ignore frame with unexpected Transaction ID %u",
2845 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002846 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2847 " fail=transaction_id_mismatch", MAC2STR(src));
2848 goto fail;
2849 }
2850
2851 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2852 if (!status || status_len != 1) {
2853 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2854 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2855 " fail=missing_status", MAC2STR(src));
2856 goto fail;
2857 }
2858 if (status[0] != DPP_STATUS_OK) {
2859 wpa_printf(MSG_DEBUG,
2860 "DPP: Peer rejected network introduction: Status %u",
2861 status[0]);
2862 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2863 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002864#ifdef CONFIG_DPP2
2865 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2866#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002867 goto fail;
2868 }
2869
2870 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2871 if (!connector) {
2872 wpa_printf(MSG_DEBUG,
2873 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002874 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2875 " fail=missing_connector", MAC2STR(src));
2876 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002877 }
2878
Roshan Pius3a1667e2018-07-03 15:17:14 -07002879 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2880 ssid->dpp_netaccesskey,
2881 ssid->dpp_netaccesskey_len,
2882 ssid->dpp_csign,
2883 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002884 connector, connector_len, &expiry, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002885 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002886 wpa_printf(MSG_INFO,
2887 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002888 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2889 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002890#ifdef CONFIG_DPP2
2891 wpas_dpp_send_conn_status_result(wpa_s, res);
2892#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002893 goto fail;
2894 }
2895
2896 entry = os_zalloc(sizeof(*entry));
2897 if (!entry)
2898 goto fail;
2899 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002900 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002901 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2902 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2903 entry->pmk_len = intro.pmk_len;
2904 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002905#ifdef CONFIG_DPP2
2906 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2907 &version_len);
2908 if (version && version_len >= 1)
2909 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002910#ifdef CONFIG_DPP3
2911 if (intro.peer_version && intro.peer_version >= 2 &&
2912 peer_version != intro.peer_version) {
2913 wpa_printf(MSG_INFO,
2914 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2915 intro.peer_version, peer_version);
2916 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2917 goto fail;
2918 }
2919#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002920 entry->dpp_pfs = peer_version >= 2;
2921#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002922 if (expiry) {
2923 os_get_time(&now);
2924 seconds = expiry - now.sec;
2925 } else {
2926 seconds = 86400 * 7;
2927 }
2928 os_get_reltime(&rnow);
2929 entry->expiration = rnow.sec + seconds;
2930 entry->reauth_time = rnow.sec + seconds;
2931 entry->network_ctx = ssid;
2932 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2933
Roshan Pius3a1667e2018-07-03 15:17:14 -07002934 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002935 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002936
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002937 wpa_printf(MSG_DEBUG,
2938 "DPP: Try connection again after successful network introduction");
2939 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2940 wpa_supplicant_cancel_sched_scan(wpa_s);
2941 wpa_supplicant_req_scan(wpa_s, 0, 0);
2942 }
2943fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002944 dpp_peer_intro_deinit(&intro);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002945}
2946
2947
Roshan Pius3a1667e2018-07-03 15:17:14 -07002948static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2949{
2950 int i, j;
2951
2952 if (!wpa_s->hw.modes)
2953 return -1;
2954
2955 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2956 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2957
2958 for (j = 0; j < mode->num_channels; j++) {
2959 struct hostapd_channel_data *chan = &mode->channels[j];
2960
2961 if (chan->freq != (int) freq)
2962 continue;
2963
2964 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2965 HOSTAPD_CHAN_NO_IR |
2966 HOSTAPD_CHAN_RADAR))
2967 continue;
2968
2969 return 1;
2970 }
2971 }
2972
2973 wpa_printf(MSG_DEBUG,
2974 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2975 freq);
2976
2977 return 0;
2978}
2979
2980
2981static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2982 struct dpp_pkex *pkex)
2983{
2984 if (pkex->freq == 2437)
2985 pkex->freq = 5745;
2986 else if (pkex->freq == 5745)
2987 pkex->freq = 5220;
2988 else if (pkex->freq == 5220)
2989 pkex->freq = 60480;
2990 else
2991 return -1; /* no more channels to try */
2992
2993 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2994 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2995 pkex->freq);
2996 return 0;
2997 }
2998
2999 /* Could not use this channel - try the next one */
3000 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
3001}
3002
3003
Sunil Ravi89eba102022-09-13 21:04:37 -07003004static void wpas_dpp_pkex_clear_code(struct wpa_supplicant *wpa_s)
3005{
3006 if (!wpa_s->dpp_pkex_code && !wpa_s->dpp_pkex_identifier)
3007 return;
3008
3009 /* Delete PKEX code and identifier on successful completion of
3010 * PKEX. We are not supposed to reuse these without being
3011 * explicitly requested to perform PKEX again. */
3012 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
3013 os_free(wpa_s->dpp_pkex_code);
3014 wpa_s->dpp_pkex_code = NULL;
3015 os_free(wpa_s->dpp_pkex_identifier);
3016 wpa_s->dpp_pkex_identifier = NULL;
3017
3018}
3019
3020
Hai Shaloma20dcd72022-02-04 13:43:00 -08003021#ifdef CONFIG_DPP2
3022static int wpas_dpp_pkex_done(void *ctx, void *conn,
3023 struct dpp_bootstrap_info *peer_bi)
3024{
3025 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -07003026 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -08003027 const char *pos;
3028 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
3029 struct dpp_bootstrap_info *own_bi = NULL;
3030 struct dpp_authentication *auth;
3031
Sunil Ravi89eba102022-09-13 21:04:37 -07003032 wpas_dpp_pkex_clear_code(wpa_s);
3033
3034 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
3035 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003036 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
3037 cmd);
3038
3039 pos = os_strstr(cmd, " own=");
3040 if (pos) {
3041 pos += 5;
3042 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
3043 if (!own_bi) {
3044 wpa_printf(MSG_INFO,
3045 "DPP: Could not find bootstrapping info for the identified local entry");
3046 return -1;
3047 }
3048
3049 if (peer_bi->curve != own_bi->curve) {
3050 wpa_printf(MSG_INFO,
3051 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
3052 peer_bi->curve->name, own_bi->curve->name);
3053 return -1;
3054 }
3055 }
3056
3057 pos = os_strstr(cmd, " role=");
3058 if (pos) {
3059 pos += 6;
3060 if (os_strncmp(pos, "configurator", 12) == 0)
3061 allowed_roles = DPP_CAPAB_CONFIGURATOR;
3062 else if (os_strncmp(pos, "enrollee", 8) == 0)
3063 allowed_roles = DPP_CAPAB_ENROLLEE;
3064 else if (os_strncmp(pos, "either", 6) == 0)
3065 allowed_roles = DPP_CAPAB_CONFIGURATOR |
3066 DPP_CAPAB_ENROLLEE;
3067 else
3068 return -1;
3069 }
3070
3071 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
3072 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
3073 if (!auth)
3074 return -1;
3075
3076 wpas_dpp_set_testing_options(wpa_s, auth);
3077 if (dpp_set_configurator(auth, cmd) < 0) {
3078 dpp_auth_deinit(auth);
3079 return -1;
3080 }
3081
3082 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -07003083 DPP_NETROLE_STA,
3084 wpa_s->conf->dpp_mud_url,
3085 wpa_s->conf->dpp_extra_conf_req_name,
3086 wpa_s->conf->dpp_extra_conf_req_value,
3087 wpas_dpp_process_conf_obj,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003088 wpas_dpp_tcp_msg_sent);
3089}
3090#endif /* CONFIG_DPP2 */
3091
3092
Hai Shaloma20dcd72022-02-04 13:43:00 -08003093static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07003094 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003095 const struct hostapd_ip_addr *ipaddr,
3096 int tcp_port)
3097{
3098 struct dpp_pkex *pkex;
3099 struct wpabuf *msg;
3100 unsigned int wait_time;
3101 bool v2 = ver != PKEX_VER_ONLY_1;
3102
3103 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
3104 dpp_pkex_free(wpa_s->dpp_pkex);
3105 wpa_s->dpp_pkex = NULL;
3106 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3107 wpa_s->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -07003108 wpa_s->dpp_pkex_code, wpa_s->dpp_pkex_code_len,
3109 v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003110 if (!pkex)
3111 return -1;
3112 pkex->forced_ver = ver != PKEX_VER_AUTO;
3113
3114 if (ipaddr) {
3115#ifdef CONFIG_DPP2
3116 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
3117 wpa_s, wpa_s, wpas_dpp_pkex_done);
3118#else /* CONFIG_DPP2 */
3119 return -1;
3120#endif /* CONFIG_DPP2 */
3121 }
3122
3123 wpa_s->dpp_pkex = pkex;
3124 msg = pkex->exchange_req;
3125 wait_time = wpa_s->max_remain_on_chan;
3126 if (wait_time > 2000)
3127 wait_time = 2000;
3128 pkex->freq = 2437;
3129 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3130 " freq=%u type=%d",
3131 MAC2STR(broadcast), pkex->freq,
3132 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3133 DPP_PA_PKEX_V1_EXCHANGE_REQ);
3134 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3135 wpa_s->own_addr, broadcast,
3136 wpabuf_head(msg), wpabuf_len(msg),
3137 wait_time, wpas_dpp_tx_pkex_status, 0);
3138 if (wait_time == 0)
3139 wait_time = 2000;
3140 pkex->exch_req_wait_time = wait_time;
3141 pkex->exch_req_tries = 1;
3142
3143 return 0;
3144}
3145
3146
Roshan Pius3a1667e2018-07-03 15:17:14 -07003147static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
3148{
3149 struct wpa_supplicant *wpa_s = eloop_ctx;
3150 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3151
3152 if (!pkex || !pkex->exchange_req)
3153 return;
3154 if (pkex->exch_req_tries >= 5) {
3155 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003156#ifdef CONFIG_DPP3
3157 if (pkex->v2 && !pkex->forced_ver) {
3158 wpa_printf(MSG_DEBUG,
3159 "DPP: Fall back to PKEXv1");
3160 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
3161 NULL, 0);
3162 return;
3163 }
3164#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003165 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
3166 "No response from PKEX peer");
3167 dpp_pkex_free(pkex);
3168 wpa_s->dpp_pkex = NULL;
3169 return;
3170 }
3171 pkex->exch_req_tries = 0;
3172 }
3173
3174 pkex->exch_req_tries++;
3175 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
3176 pkex->exch_req_tries);
3177 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08003178 MAC2STR(broadcast), pkex->freq,
3179 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3180 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003181 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3182 wpa_s->own_addr, broadcast,
3183 wpabuf_head(pkex->exchange_req),
3184 wpabuf_len(pkex->exchange_req),
3185 pkex->exch_req_wait_time,
3186 wpas_dpp_tx_pkex_status, 0);
3187}
3188
3189
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003190static void
3191wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
3192 unsigned int freq, const u8 *dst,
3193 const u8 *src, const u8 *bssid,
3194 const u8 *data, size_t data_len,
3195 enum offchannel_send_action_result result)
3196{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003197 const char *res_txt;
3198 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3199
3200 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3201 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3202 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003203 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3204 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003205 freq, MAC2STR(dst), res_txt);
3206 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3207 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3208
3209 if (!pkex) {
3210 wpa_printf(MSG_DEBUG,
3211 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
3212 return;
3213 }
3214
3215 if (pkex->failed) {
3216 wpa_printf(MSG_DEBUG,
3217 "DPP: Terminate PKEX exchange due to an earlier error");
3218 if (pkex->t > pkex->own_bi->pkex_t)
3219 pkex->own_bi->pkex_t = pkex->t;
3220 dpp_pkex_free(pkex);
3221 wpa_s->dpp_pkex = NULL;
3222 return;
3223 }
3224
3225 if (pkex->exch_req_wait_time && pkex->exchange_req) {
3226 /* Wait for PKEX Exchange Response frame and retry request if
3227 * no response is seen. */
3228 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3229 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
3230 (pkex->exch_req_wait_time % 1000) * 1000,
3231 wpas_dpp_pkex_retry_timeout, wpa_s,
3232 NULL);
3233 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003234}
3235
3236
3237static void
3238wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003239 const u8 *buf, size_t len, unsigned int freq,
3240 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003241{
3242 struct wpabuf *msg;
3243 unsigned int wait_time;
3244
3245 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
3246 MAC2STR(src));
3247
Sunil Ravia04bd252022-05-02 22:54:18 -07003248 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
3249 wpa_printf(MSG_DEBUG,
3250 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
3251 return;
3252 }
3253 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
3254 wpa_printf(MSG_DEBUG,
3255 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
3256 return;
3257 }
3258
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003259 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3260 * values here */
3261
3262 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
3263 wpa_printf(MSG_DEBUG,
3264 "DPP: No PKEX code configured - ignore request");
3265 return;
3266 }
3267
Sunil Ravi89eba102022-09-13 21:04:37 -07003268#ifdef CONFIG_DPP2
3269 if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) {
3270 wpa_printf(MSG_DEBUG,
3271 "DPP: PKEX Exchange Request is from local Controller - ignore request");
3272 return;
3273 }
3274#endif /* CONFIG_DPP2 */
3275
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003276 if (wpa_s->dpp_pkex) {
3277 /* TODO: Support parallel operations */
3278 wpa_printf(MSG_DEBUG,
3279 "DPP: Already in PKEX session - ignore new request");
3280 return;
3281 }
3282
Roshan Pius3a1667e2018-07-03 15:17:14 -07003283 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003284 wpa_s->own_addr, src,
3285 wpa_s->dpp_pkex_identifier,
3286 wpa_s->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07003287 wpa_s->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003288 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003289 if (!wpa_s->dpp_pkex) {
3290 wpa_printf(MSG_DEBUG,
3291 "DPP: Failed to process the request - ignore it");
3292 return;
3293 }
3294
Sunil Ravi89eba102022-09-13 21:04:37 -07003295#ifdef CONFIG_DPP3
3296 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_announcement) {
3297 wpa_printf(MSG_DEBUG,
3298 "DPP: Started PB PKEX (no more PB announcements)");
3299 wpabuf_free(wpa_s->dpp_pb_announcement);
3300 wpa_s->dpp_pb_announcement = NULL;
3301 }
3302#endif /* CONFIG_DPP3 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003303 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003304 msg = wpa_s->dpp_pkex->exchange_resp;
3305 wait_time = wpa_s->max_remain_on_chan;
3306 if (wait_time > 2000)
3307 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003308 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3309 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003310 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3311 broadcast,
3312 wpabuf_head(msg), wpabuf_len(msg),
3313 wait_time, wpas_dpp_tx_pkex_status, 0);
3314}
3315
3316
3317static void
3318wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3319 const u8 *buf, size_t len, unsigned int freq)
3320{
3321 struct wpabuf *msg;
3322 unsigned int wait_time;
3323
3324 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
3325 MAC2STR(src));
3326
3327 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3328 * values here */
3329
3330 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3331 wpa_s->dpp_pkex->exchange_done) {
3332 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3333 return;
3334 }
3335
Roshan Pius3a1667e2018-07-03 15:17:14 -07003336 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3337 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3338
3339 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003340 if (!msg) {
3341 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3342 return;
3343 }
3344
3345 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3346 MAC2STR(src));
3347
3348 wait_time = wpa_s->max_remain_on_chan;
3349 if (wait_time > 2000)
3350 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003351 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3352 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003353 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3354 broadcast,
3355 wpabuf_head(msg), wpabuf_len(msg),
3356 wait_time, wpas_dpp_tx_pkex_status, 0);
3357 wpabuf_free(msg);
3358}
3359
3360
Roshan Pius3a1667e2018-07-03 15:17:14 -07003361static struct dpp_bootstrap_info *
3362wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3363 unsigned int freq)
3364{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003365 struct dpp_bootstrap_info *bi;
3366
Sunil Ravi89eba102022-09-13 21:04:37 -07003367 wpas_dpp_pkex_clear_code(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003368 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003369 if (!bi)
3370 return NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003371
Roshan Pius3a1667e2018-07-03 15:17:14 -07003372 wpa_s->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003373
3374#ifdef CONFIG_DPP3
3375 if (wpa_s->dpp_pb_bi && !wpa_s->dpp_pb_configurator &&
3376 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_init_hash,
3377 SHA256_MAC_LEN) != 0) {
3378 char id[20];
3379
3380 wpa_printf(MSG_INFO,
3381 "DPP: Peer bootstrap key from PKEX does not match PB announcement response hash");
3382 wpa_hexdump(MSG_DEBUG,
3383 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3384 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3385 wpa_hexdump(MSG_DEBUG,
3386 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement response",
3387 wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN);
3388
3389 os_snprintf(id, sizeof(id), "%u", bi->id);
3390 dpp_bootstrap_remove(wpa_s->dpp, id);
3391 wpas_dpp_push_button_stop(wpa_s);
3392 return NULL;
3393 }
3394#endif /* CONFIG_DPP3 */
3395
Roshan Pius3a1667e2018-07-03 15:17:14 -07003396 return bi;
3397}
3398
3399
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003400static void
3401wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3402 const u8 *hdr, const u8 *buf, size_t len,
3403 unsigned int freq)
3404{
3405 struct wpabuf *msg;
3406 unsigned int wait_time;
3407 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003408
3409 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3410 MAC2STR(src));
3411
3412 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3413 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3414 return;
3415 }
3416
3417 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3418 if (!msg) {
3419 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003420 if (pkex->failed) {
3421 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3422 if (pkex->t > pkex->own_bi->pkex_t)
3423 pkex->own_bi->pkex_t = pkex->t;
3424 dpp_pkex_free(wpa_s->dpp_pkex);
3425 wpa_s->dpp_pkex = NULL;
3426 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003427 return;
3428 }
3429
3430 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3431 MACSTR, MAC2STR(src));
3432
3433 wait_time = wpa_s->max_remain_on_chan;
3434 if (wait_time > 2000)
3435 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003436 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3437 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003438 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3439 broadcast,
3440 wpabuf_head(msg), wpabuf_len(msg),
3441 wait_time, wpas_dpp_tx_pkex_status, 0);
3442 wpabuf_free(msg);
3443
Roshan Pius3a1667e2018-07-03 15:17:14 -07003444 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003445 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003446}
3447
3448
3449static void
3450wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3451 const u8 *hdr, const u8 *buf, size_t len,
3452 unsigned int freq)
3453{
3454 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003455 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003456 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3457 char cmd[500];
3458
3459 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3460 MAC2STR(src));
3461
3462 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3463 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3464 return;
3465 }
3466
3467 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3468 if (res < 0) {
3469 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3470 return;
3471 }
3472
Roshan Pius3a1667e2018-07-03 15:17:14 -07003473 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003474 if (!bi)
3475 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003476
Sunil Ravi89eba102022-09-13 21:04:37 -07003477#ifdef CONFIG_DPP3
3478 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_configurator &&
3479 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_resp_hash,
3480 SHA256_MAC_LEN) != 0) {
3481 char id[20];
3482
3483 wpa_printf(MSG_INFO,
3484 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
3485 wpa_hexdump(MSG_DEBUG,
3486 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3487 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3488 wpa_hexdump(MSG_DEBUG,
3489 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
3490 wpa_s->dpp_pb_resp_hash, SHA256_MAC_LEN);
3491
3492 os_snprintf(id, sizeof(id), "%u", bi->id);
3493 dpp_bootstrap_remove(wpa_s->dpp, id);
3494 wpas_dpp_push_button_stop(wpa_s);
3495 return;
3496 }
3497#endif /* CONFIG_DPP3 */
3498
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003499 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3500 bi->id,
3501 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3502 wpa_printf(MSG_DEBUG,
3503 "DPP: Start authentication after PKEX with parameters: %s",
3504 cmd);
3505 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3506 wpa_printf(MSG_DEBUG,
3507 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003508 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003509 return;
3510 }
3511}
3512
3513
Sunil Ravi89eba102022-09-13 21:04:37 -07003514#ifdef CONFIG_DPP3
3515
3516static void wpas_dpp_pb_pkex_init(struct wpa_supplicant *wpa_s,
3517 unsigned int freq, const u8 *src,
3518 const u8 *r_hash)
3519{
3520 struct dpp_pkex *pkex;
3521 struct wpabuf *msg;
3522 unsigned int wait_time;
3523 size_t len;
3524
3525 if (wpa_s->dpp_pkex) {
3526 wpa_printf(MSG_DEBUG,
3527 "DPP: Sending previously generated PKEX Exchange Request to "
3528 MACSTR, MAC2STR(src));
3529 msg = wpa_s->dpp_pkex->exchange_req;
3530 wait_time = wpa_s->max_remain_on_chan;
3531 if (wait_time > 2000)
3532 wait_time = 2000;
3533 offchannel_send_action(wpa_s, freq, src,
3534 wpa_s->own_addr, broadcast,
3535 wpabuf_head(msg), wpabuf_len(msg),
3536 wait_time, wpas_dpp_tx_pkex_status, 0);
3537 return;
3538 }
3539
3540 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
3541 MACSTR, MAC2STR(src));
3542
3543 if (!wpa_s->dpp_pb_cmd) {
3544 wpa_printf(MSG_INFO,
3545 "DPP: No configuration to provision as push button Configurator");
3546 wpas_dpp_push_button_stop(wpa_s);
3547 return;
3548 }
3549
3550 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
3551 os_memcpy(wpa_s->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
3552
3553 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3554 "PBPKEX", (const char *) wpa_s->dpp_pb_c_nonce,
3555 wpa_s->dpp_pb_bi->curve->nonce_len,
3556 true);
3557 if (!pkex) {
3558 wpas_dpp_push_button_stop(wpa_s);
3559 return;
3560 }
3561 pkex->freq = freq;
3562
3563 wpa_s->dpp_pkex = pkex;
3564 msg = wpa_s->dpp_pkex->exchange_req;
3565 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3566 " freq=%u type=%d", MAC2STR(src), freq,
3567 DPP_PA_PKEX_EXCHANGE_REQ);
3568 wait_time = wpa_s->max_remain_on_chan;
3569 if (wait_time > 2000)
3570 wait_time = 2000;
3571 offchannel_send_action(wpa_s, pkex->freq, src,
3572 wpa_s->own_addr, broadcast,
3573 wpabuf_head(msg), wpabuf_len(msg),
3574 wait_time, wpas_dpp_tx_pkex_status, 0);
3575 pkex->exch_req_wait_time = 2000;
3576 pkex->exch_req_tries = 1;
3577
3578 /* Use the externally provided configuration */
3579 os_free(wpa_s->dpp_pkex_auth_cmd);
3580 len = 30 + os_strlen(wpa_s->dpp_pb_cmd);
3581 wpa_s->dpp_pkex_auth_cmd = os_malloc(len);
3582 if (wpa_s->dpp_pkex_auth_cmd)
3583 os_snprintf(wpa_s->dpp_pkex_auth_cmd, len, " own=%d %s",
3584 wpa_s->dpp_pkex_bi->id, wpa_s->dpp_pb_cmd);
3585 else
3586 wpas_dpp_push_button_stop(wpa_s);
3587}
3588
3589
3590static void
3591wpas_dpp_rx_pb_presence_announcement(struct wpa_supplicant *wpa_s,
3592 const u8 *src, const u8 *hdr,
3593 const u8 *buf, size_t len,
3594 unsigned int freq)
3595{
3596 const u8 *r_hash;
3597 u16 r_hash_len;
3598 unsigned int i;
3599 bool found = false;
3600 struct dpp_pb_info *info, *tmp;
3601 struct os_reltime now, age;
3602 struct wpabuf *msg;
3603
3604 os_get_reltime(&now);
3605 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
3606 MACSTR, MAC2STR(src));
3607
3608 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3609 &r_hash_len);
3610 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
3611 wpa_printf(MSG_DEBUG,
3612 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
3613 return;
3614 }
3615 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3616 r_hash, r_hash_len);
3617
3618 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3619 info = &wpa_s->dpp_pb[i];
3620 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
3621 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
3622 continue;
3623 wpa_printf(MSG_DEBUG,
3624 "DPP: Active push button Enrollee already known");
3625 found = true;
3626 info->rx_time = now;
3627 }
3628
3629 if (!found) {
3630 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3631 tmp = &wpa_s->dpp_pb[i];
3632 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
3633 continue;
3634
3635 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
3636 wpa_hexdump(MSG_DEBUG,
3637 "DPP: Push button Enrollee hash expired",
3638 tmp->hash, SHA256_MAC_LEN);
3639 tmp->rx_time.sec = 0;
3640 tmp->rx_time.usec = 0;
3641 continue;
3642 }
3643
3644 wpa_hexdump(MSG_DEBUG,
3645 "DPP: Push button session overlap with hash",
3646 tmp->hash, SHA256_MAC_LEN);
3647 if (!wpa_s->dpp_pb_result_indicated &&
3648 wpas_dpp_pb_active(wpa_s)) {
3649 wpa_msg(wpa_s, MSG_INFO,
3650 DPP_EVENT_PB_RESULT "session-overlap");
3651 wpa_s->dpp_pb_result_indicated = true;
3652 }
3653 wpas_dpp_push_button_stop(wpa_s);
3654 return;
3655 }
3656
3657 /* Replace the oldest entry */
3658 info = &wpa_s->dpp_pb[0];
3659 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
3660 tmp = &wpa_s->dpp_pb[i];
3661 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
3662 info = tmp;
3663 }
3664 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
3665 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
3666 info->rx_time = now;
3667 }
3668
3669 if (!wpas_dpp_pb_active(wpa_s)) {
3670 wpa_printf(MSG_DEBUG,
3671 "DPP: Discard message since own push button has not been pressed");
3672 return;
3673 }
3674
3675 if (wpa_s->dpp_pb_announce_time.sec == 0 &&
3676 wpa_s->dpp_pb_announce_time.usec == 0) {
3677 /* Start a wait before allowing PKEX to be initiated */
3678 wpa_s->dpp_pb_announce_time = now;
3679 }
3680
3681 if (!wpa_s->dpp_pb_bi) {
3682 int res;
3683
3684 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
3685 if (res < 0)
3686 return;
3687 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
3688 if (!wpa_s->dpp_pb_bi)
3689 return;
3690
3691 if (random_get_bytes(wpa_s->dpp_pb_c_nonce,
3692 wpa_s->dpp_pb_bi->curve->nonce_len)) {
3693 wpa_printf(MSG_ERROR,
3694 "DPP: Failed to generate C-nonce");
3695 wpas_dpp_push_button_stop(wpa_s);
3696 return;
3697 }
3698 }
3699
3700 /* Skip the response if one was sent within last 50 ms since the
3701 * Enrollee is going to send out at least three announcement messages.
3702 */
3703 os_reltime_sub(&now, &wpa_s->dpp_pb_last_resp, &age);
3704 if (age.sec == 0 && age.usec < 50000) {
3705 wpa_printf(MSG_DEBUG,
3706 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
3707 return;
3708 }
3709
3710 msg = dpp_build_pb_announcement_resp(
3711 wpa_s->dpp_pb_bi, r_hash, wpa_s->dpp_pb_c_nonce,
3712 wpa_s->dpp_pb_bi->curve->nonce_len);
3713 if (!msg) {
3714 wpas_dpp_push_button_stop(wpa_s);
3715 return;
3716 }
3717
3718 wpa_printf(MSG_DEBUG,
3719 "DPP: Send Push Button Presence Announcement Response to "
3720 MACSTR, MAC2STR(src));
3721 wpa_s->dpp_pb_last_resp = now;
3722
3723 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3724 MAC2STR(src), freq, DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
3725 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
3726 wpabuf_head(msg), wpabuf_len(msg),
3727 0, NULL, 0);
3728 wpabuf_free(msg);
3729
3730 if (os_reltime_expired(&now, &wpa_s->dpp_pb_announce_time, 15))
3731 wpas_dpp_pb_pkex_init(wpa_s, freq, src, r_hash);
3732}
3733
3734
3735static void
3736wpas_dpp_rx_pb_presence_announcement_resp(struct wpa_supplicant *wpa_s,
3737 const u8 *src, const u8 *hdr,
3738 const u8 *buf, size_t len,
3739 unsigned int freq)
3740{
3741 const u8 *i_hash, *r_hash, *c_nonce;
3742 u16 i_hash_len, r_hash_len, c_nonce_len;
3743 bool overlap = false;
3744
3745 if (!wpa_s->dpp_pb_announcement || !wpa_s->dpp_pb_bi ||
3746 wpa_s->dpp_pb_configurator) {
3747 wpa_printf(MSG_INFO,
3748 "DPP: Not in active push button Enrollee mode - discard Push Button Presence Announcement Response from "
3749 MACSTR, MAC2STR(src));
3750 return;
3751 }
3752
3753 wpa_printf(MSG_DEBUG,
3754 "DPP: Push Button Presence Announcement Response from "
3755 MACSTR, MAC2STR(src));
3756
3757 i_hash = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3758 &i_hash_len);
3759 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3760 &r_hash_len);
3761 c_nonce = dpp_get_attr(buf, len, DPP_ATTR_CONFIGURATOR_NONCE,
3762 &c_nonce_len);
3763 if (!i_hash || i_hash_len != SHA256_MAC_LEN ||
3764 !r_hash || r_hash_len != SHA256_MAC_LEN ||
3765 !c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
3766 wpa_printf(MSG_DEBUG,
3767 "DPP: Missing or invalid required attribute");
3768 return;
3769 }
3770 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
3771 i_hash, i_hash_len);
3772 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3773 r_hash, r_hash_len);
3774 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator Nonce",
3775 c_nonce, c_nonce_len);
3776
3777#ifdef CONFIG_TESTING_OPTIONS
3778 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ &&
3779 os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3780 SHA256_MAC_LEN - 1) == 0)
3781 goto skip_hash_check;
3782#endif /* CONFIG_TESTING_OPTIONS */
3783 if (os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3784 SHA256_MAC_LEN) != 0) {
3785 wpa_printf(MSG_INFO,
3786 "DPP: Unexpected push button Responder hash - abort");
3787 overlap = true;
3788 }
3789#ifdef CONFIG_TESTING_OPTIONS
3790skip_hash_check:
3791#endif /* CONFIG_TESTING_OPTIONS */
3792
3793 if (wpa_s->dpp_pb_resp_freq &&
3794 os_memcmp(i_hash, wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN) != 0) {
3795 wpa_printf(MSG_INFO,
3796 "DPP: Push button session overlap detected - abort");
3797 overlap = true;
3798 }
3799
3800 if (overlap) {
3801 if (!wpa_s->dpp_pb_result_indicated) {
3802 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
3803 "session-overlap");
3804 wpa_s->dpp_pb_result_indicated = true;
3805 }
3806 wpas_dpp_push_button_stop(wpa_s);
3807 return;
3808 }
3809
3810 if (!wpa_s->dpp_pb_resp_freq) {
3811 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
3812 "discovered push button AP/Configurator " MACSTR,
3813 MAC2STR(src));
3814 wpa_s->dpp_pb_resp_freq = freq;
3815 os_memcpy(wpa_s->dpp_pb_init_hash, i_hash, SHA256_MAC_LEN);
3816 os_memcpy(wpa_s->dpp_pb_c_nonce, c_nonce, c_nonce_len);
3817 wpa_s->dpp_pb_c_nonce_len = c_nonce_len;
3818 /* Stop announcement iterations after at least one more full
3819 * round and one extra round for postponed session overlap
3820 * detection. */
3821 wpa_s->dpp_pb_stop_iter = 3;
3822 }
3823}
3824
3825
3826static void
3827wpas_dpp_tx_priv_intro_status(struct wpa_supplicant *wpa_s,
3828 unsigned int freq, const u8 *dst,
3829 const u8 *src, const u8 *bssid,
3830 const u8 *data, size_t data_len,
3831 enum offchannel_send_action_result result)
3832{
3833 const char *res_txt;
3834
3835 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3836 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3837 "FAILED");
3838 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3839 " result=%s (DPP Private Peer Introduction Update)",
3840 freq, MAC2STR(dst), res_txt);
3841 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3842 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3843
3844 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR " version=%u",
3845 MAC2STR(src), wpa_s->dpp_intro_peer_version);
3846
3847 wpa_printf(MSG_DEBUG,
3848 "DPP: Try connection again after successful network introduction");
3849 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3850 wpa_supplicant_cancel_sched_scan(wpa_s);
3851 wpa_supplicant_req_scan(wpa_s, 0, 0);
3852 }
3853}
3854
3855
3856static int
3857wpas_dpp_send_private_peer_intro_update(struct wpa_supplicant *wpa_s,
3858 struct dpp_introduction *intro,
3859 struct wpa_ssid *ssid,
3860 const u8 *dst, unsigned int freq)
3861{
3862 struct wpabuf *pt, *msg, *enc_ct;
3863 size_t len;
3864 u8 ver = DPP_VERSION;
3865 int conn_ver;
3866 const u8 *aad;
3867 size_t aad_len;
3868 unsigned int wait_time;
3869
3870 wpa_printf(MSG_DEBUG, "HPKE(kem_id=%u kdf_id=%u aead_id=%u)",
3871 intro->kem_id, intro->kdf_id, intro->aead_id);
3872
3873 /* Plaintext for HPKE */
3874 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3875 pt = wpabuf_alloc(len);
3876 if (!pt)
3877 return -1;
3878
3879 /* Protocol Version */
3880 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3881 if (conn_ver > 0 && ver != conn_ver) {
3882 wpa_printf(MSG_DEBUG,
3883 "DPP: Use Connector version %d instead of current protocol version %d",
3884 conn_ver, ver);
3885 ver = conn_ver;
3886 }
3887 wpabuf_put_le16(pt, DPP_ATTR_PROTOCOL_VERSION);
3888 wpabuf_put_le16(pt, 1);
3889 wpabuf_put_u8(pt, ver);
3890
3891 /* Connector */
3892 wpabuf_put_le16(pt, DPP_ATTR_CONNECTOR);
3893 wpabuf_put_le16(pt, os_strlen(ssid->dpp_connector));
3894 wpabuf_put_str(pt, ssid->dpp_connector);
3895 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Plaintext for HPKE", pt);
3896
3897 /* HPKE(pt) using AP's public key (from its Connector) */
3898 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, 0);
3899 if (!msg) {
3900 wpabuf_free(pt);
3901 return -1;
3902 }
3903 aad = wpabuf_head_u8(msg) + 2; /* from the OUI field (inclusive) */
3904 aad_len = DPP_HDR_LEN; /* to the DPP Frame Type field (inclusive) */
3905 wpa_hexdump(MSG_MSGDUMP, "DPP: AAD for HPKE", aad, aad_len);
3906
3907 enc_ct = hpke_base_seal(intro->kem_id, intro->kdf_id, intro->aead_id,
3908 intro->peer_key, NULL, 0, aad, aad_len,
3909 wpabuf_head(pt), wpabuf_len(pt));
3910 wpabuf_free(pt);
3911 wpabuf_free(msg);
3912 if (!enc_ct) {
3913 wpa_printf(MSG_INFO, "DPP: HPKE Seal(Connector) failed");
3914 return -1;
3915 }
3916 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE enc|ct", enc_ct);
3917
3918 /* HPKE(pt) to generate payload for Wrapped Data */
3919 len = 5 + 4 + wpabuf_len(enc_ct);
3920 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, len);
3921 if (!msg) {
3922 wpabuf_free(enc_ct);
3923 return -1;
3924 }
3925
3926 /* Transaction ID */
3927 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3928 wpabuf_put_le16(msg, 1);
3929 wpabuf_put_u8(msg, TRANSACTION_ID);
3930
3931 /* Wrapped Data */
3932 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3933 wpabuf_put_le16(msg, wpabuf_len(enc_ct));
3934 wpabuf_put_buf(msg, enc_ct);
3935 wpabuf_free(enc_ct);
3936
3937 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Update", msg);
3938
3939 /* TODO: Timeout on AP response */
3940 wait_time = wpa_s->max_remain_on_chan;
3941 if (wait_time > 2000)
3942 wait_time = 2000;
3943 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3944 MAC2STR(dst), freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
3945 offchannel_send_action(wpa_s, freq, dst, wpa_s->own_addr, broadcast,
3946 wpabuf_head(msg), wpabuf_len(msg),
3947 wait_time, wpas_dpp_tx_priv_intro_status, 0);
3948 wpabuf_free(msg);
3949
3950 return 0;
3951}
3952
3953
3954static void
3955wpas_dpp_rx_priv_peer_intro_notify(struct wpa_supplicant *wpa_s,
3956 const u8 *src, const u8 *hdr,
3957 const u8 *buf, size_t len,
3958 unsigned int freq)
3959{
3960 struct wpa_ssid *ssid;
3961 const u8 *connector, *trans_id, *version;
3962 u16 connector_len, trans_id_len, version_len;
3963 u8 peer_version = 1;
3964 struct dpp_introduction intro;
3965 struct rsn_pmksa_cache_entry *entry;
3966 struct os_time now;
3967 struct os_reltime rnow;
3968 os_time_t expiry;
3969 unsigned int seconds;
3970 enum dpp_status_error res;
3971
3972 os_memset(&intro, 0, sizeof(intro));
3973
3974 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
3975 MACSTR, MAC2STR(src));
3976 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003977 !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
Sunil Ravi89eba102022-09-13 21:04:37 -07003978 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
3979 MACSTR " - drop", MAC2STR(src));
3980 return;
3981 }
3982 offchannel_send_action_done(wpa_s);
3983
3984 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3985 if (ssid == wpa_s->dpp_intro_network)
3986 break;
3987 }
3988 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3989 !ssid->dpp_csign) {
3990 wpa_printf(MSG_DEBUG,
3991 "DPP: Profile not found for network introduction");
3992 return;
3993 }
3994
3995 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
3996 &trans_id_len);
3997 if (!trans_id || trans_id_len != 1) {
3998 wpa_printf(MSG_DEBUG,
3999 "DPP: Peer did not include Transaction ID");
4000 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4001 " fail=missing_transaction_id", MAC2STR(src));
4002 goto fail;
4003 }
4004 if (trans_id[0] != TRANSACTION_ID) {
4005 wpa_printf(MSG_DEBUG,
4006 "DPP: Ignore frame with unexpected Transaction ID %u",
4007 trans_id[0]);
4008 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4009 " fail=transaction_id_mismatch", MAC2STR(src));
4010 goto fail;
4011 }
4012
4013 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
4014 if (!connector) {
4015 wpa_printf(MSG_DEBUG,
4016 "DPP: Peer did not include its Connector");
4017 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4018 " fail=missing_connector", MAC2STR(src));
4019 goto fail;
4020 }
4021
4022 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
4023 &version_len);
4024 if (!version || version_len < 1) {
4025 wpa_printf(MSG_DEBUG,
4026 "DPP: Peer did not include valid Version");
4027 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4028 " fail=missing_version", MAC2STR(src));
4029 goto fail;
4030 }
4031
4032 res = dpp_peer_intro(&intro, ssid->dpp_connector,
4033 ssid->dpp_netaccesskey,
4034 ssid->dpp_netaccesskey_len,
4035 ssid->dpp_csign,
4036 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004037 connector, connector_len, &expiry, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07004038 if (res != DPP_STATUS_OK) {
4039 wpa_printf(MSG_INFO,
4040 "DPP: Network Introduction protocol resulted in failure");
4041 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4042 " fail=peer_connector_validation_failed", MAC2STR(src));
4043 wpas_dpp_send_conn_status_result(wpa_s, res);
4044 goto fail;
4045 }
4046
4047 peer_version = version[0];
4048 if (intro.peer_version && intro.peer_version >= 2 &&
4049 peer_version != intro.peer_version) {
4050 wpa_printf(MSG_INFO,
4051 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
4052 intro.peer_version, peer_version);
4053 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
4054 goto fail;
4055 }
4056 wpa_s->dpp_intro_peer_version = peer_version;
4057
4058 entry = os_zalloc(sizeof(*entry));
4059 if (!entry)
4060 goto fail;
4061 entry->dpp_pfs = peer_version >= 2;
4062 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004063 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Sunil Ravi89eba102022-09-13 21:04:37 -07004064 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
4065 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
4066 entry->pmk_len = intro.pmk_len;
4067 entry->akmp = WPA_KEY_MGMT_DPP;
4068 if (expiry) {
4069 os_get_time(&now);
4070 seconds = expiry - now.sec;
4071 } else {
4072 seconds = 86400 * 7;
4073 }
4074
4075 if (wpas_dpp_send_private_peer_intro_update(wpa_s, &intro, ssid, src,
4076 freq) < 0) {
4077 os_free(entry);
4078 goto fail;
4079 }
4080
4081 os_get_reltime(&rnow);
4082 entry->expiration = rnow.sec + seconds;
4083 entry->reauth_time = rnow.sec + seconds;
4084 entry->network_ctx = ssid;
4085 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
4086
4087 /* Association will be initiated from TX status handler for the Private
4088 * Peer Intro Update: wpas_dpp_tx_priv_intro_status() */
4089
4090fail:
4091 dpp_peer_intro_deinit(&intro);
4092}
4093
4094#endif /* CONFIG_DPP3 */
4095
4096
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004097void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
4098 const u8 *buf, size_t len, unsigned int freq)
4099{
4100 u8 crypto_suite;
4101 enum dpp_public_action_frame_type type;
4102 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004103 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004104
4105 if (len < DPP_HDR_LEN)
4106 return;
4107 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
4108 return;
4109 hdr = buf;
4110 buf += 4;
4111 len -= 4;
4112 crypto_suite = *buf++;
4113 type = *buf++;
4114 len -= 2;
4115
4116 wpa_printf(MSG_DEBUG,
4117 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
4118 MACSTR " freq=%u",
4119 crypto_suite, type, MAC2STR(src), freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07004120#ifdef CONFIG_TESTING_OPTIONS
4121 if (wpa_s->dpp_discard_public_action &&
4122 type != DPP_PA_PEER_DISCOVERY_RESP &&
4123 type != DPP_PA_PRIV_PEER_INTRO_NOTIFY) {
4124 wpa_printf(MSG_DEBUG,
4125 "TESTING: Discard received DPP Public Action frame");
4126 return;
4127 }
4128#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004129 if (crypto_suite != 1) {
4130 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
4131 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004132 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4133 " freq=%u type=%d ignore=unsupported-crypto-suite",
4134 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004135 return;
4136 }
4137 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004138 if (dpp_check_attrs(buf, len) < 0) {
4139 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4140 " freq=%u type=%d ignore=invalid-attributes",
4141 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004142 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004143 }
4144 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
4145 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004146
4147 switch (type) {
4148 case DPP_PA_AUTHENTICATION_REQ:
4149 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
4150 break;
4151 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07004152 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004153 break;
4154 case DPP_PA_AUTHENTICATION_CONF:
4155 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
4156 break;
4157 case DPP_PA_PEER_DISCOVERY_RESP:
4158 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
4159 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004160#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004161 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004162 /* This is for PKEXv2, but for now, process only with
4163 * CONFIG_DPP3 to avoid issues with a capability that has not
4164 * been tested with other implementations. */
4165 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
4166 break;
4167#endif /* CONFIG_DPP3 */
4168 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
4169 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
4170 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004171 break;
4172 case DPP_PA_PKEX_EXCHANGE_RESP:
4173 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
4174 break;
4175 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
4176 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
4177 freq);
4178 break;
4179 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
4180 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
4181 freq);
4182 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004183#ifdef CONFIG_DPP2
4184 case DPP_PA_CONFIGURATION_RESULT:
4185 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
4186 break;
Hai Shalomc3565922019-10-28 11:58:20 -07004187 case DPP_PA_CONNECTION_STATUS_RESULT:
4188 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
4189 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07004190 case DPP_PA_PRESENCE_ANNOUNCEMENT:
4191 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
4192 freq);
4193 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004194 case DPP_PA_RECONFIG_ANNOUNCEMENT:
4195 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
4196 freq);
4197 break;
4198 case DPP_PA_RECONFIG_AUTH_REQ:
4199 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
4200 break;
4201 case DPP_PA_RECONFIG_AUTH_RESP:
4202 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
4203 break;
4204 case DPP_PA_RECONFIG_AUTH_CONF:
4205 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
4206 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004207#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07004208#ifdef CONFIG_DPP3
4209 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
4210 wpas_dpp_rx_pb_presence_announcement(wpa_s, src, hdr,
4211 buf, len, freq);
4212 break;
4213 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP:
4214 wpas_dpp_rx_pb_presence_announcement_resp(wpa_s, src, hdr,
4215 buf, len, freq);
4216 break;
4217 case DPP_PA_PRIV_PEER_INTRO_NOTIFY:
4218 wpas_dpp_rx_priv_peer_intro_notify(wpa_s, src, hdr,
4219 buf, len, freq);
4220 break;
4221#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004222 default:
4223 wpa_printf(MSG_DEBUG,
4224 "DPP: Ignored unsupported frame subtype %d", type);
4225 break;
4226 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004227
4228 if (wpa_s->dpp_pkex)
4229 pkex_t = wpa_s->dpp_pkex->t;
4230 else if (wpa_s->dpp_pkex_bi)
4231 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
4232 else
4233 pkex_t = 0;
4234 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
4235 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
4236 wpas_dpp_pkex_remove(wpa_s, "*");
4237 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004238}
4239
4240
Hai Shaloma20dcd72022-02-04 13:43:00 -08004241static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
4242 void *timeout_ctx)
4243{
4244 struct wpa_supplicant *wpa_s = eloop_ctx;
4245 struct dpp_authentication *auth = wpa_s->dpp_auth;
4246
4247 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
4248 return;
4249
4250 wpa_printf(MSG_DEBUG,
4251 "DPP: No configuration available from upper layers - send initial response with comeback delay");
4252 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
4253 500);
4254}
4255
4256
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004257static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07004258wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08004259 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004260{
4261 struct wpa_supplicant *wpa_s = ctx;
4262 struct dpp_authentication *auth = wpa_s->dpp_auth;
4263 struct wpabuf *resp;
4264
4265 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
4266 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004267 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004268 !ether_addr_equal(sa, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004269 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
4270 return NULL;
4271 }
Hai Shalomc3565922019-10-28 11:58:20 -07004272
4273 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
4274 wpa_printf(MSG_DEBUG,
4275 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
4276 /* wpas_dpp_auth_success() would normally have been called from
4277 * TX status handler, but since there was no such handler call
4278 * yet, simply send out the event message and proceed with
4279 * exchange. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004280 dpp_notify_auth_success(auth, 1);
Hai Shalomc3565922019-10-28 11:58:20 -07004281 wpa_s->dpp_auth_ok_on_ack = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004282#ifdef CONFIG_TESTING_OPTIONS
4283 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
4284 wpa_printf(MSG_INFO,
4285 "DPP: TESTING - stop at Authentication Confirm");
4286 return NULL;
4287 }
4288#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07004289 }
4290
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004291 wpa_hexdump(MSG_DEBUG,
4292 "DPP: Received Configuration Request (GAS Query Request)",
4293 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004294 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
4295 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004296 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004297
Hai Shaloma20dcd72022-02-04 13:43:00 -08004298 auth->gas_server_ctx = resp_ctx;
4299
Hai Shalom899fcc72020-10-19 14:38:18 -07004300#ifdef CONFIG_DPP2
4301 if (!resp && auth->waiting_cert) {
4302 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08004303 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07004304 *comeback_delay = 500;
4305 return NULL;
4306 }
4307#endif /* CONFIG_DPP2 */
4308
Hai Shaloma20dcd72022-02-04 13:43:00 -08004309 if (!resp && auth->waiting_config &&
4310 (auth->peer_bi || auth->tmp_peer_bi)) {
4311 char *buf = NULL, *name = "";
4312 char band[200], *pos, *end;
4313 int i, res, *opclass = auth->e_band_support;
4314 char *mud_url = "N/A";
4315
4316 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
4317 auth->config_resp_ctx = resp_ctx;
4318 *comeback_delay = -1;
4319 if (auth->e_name) {
4320 size_t len = os_strlen(auth->e_name);
4321
4322 buf = os_malloc(len * 4 + 1);
4323 if (buf) {
4324 printf_encode(buf, len * 4 + 1,
4325 (const u8 *) auth->e_name, len);
4326 name = buf;
4327 }
4328 }
4329 band[0] = '\0';
4330 pos = band;
4331 end = band + sizeof(band);
4332 for (i = 0; opclass && opclass[i]; i++) {
4333 res = os_snprintf(pos, end - pos, "%s%d",
4334 pos == band ? "" : ",", opclass[i]);
4335 if (os_snprintf_error(end - pos, res)) {
4336 *pos = '\0';
4337 break;
4338 }
4339 pos += res;
4340 }
4341 if (auth->e_mud_url) {
4342 size_t len = os_strlen(auth->e_mud_url);
4343
4344 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
4345 mud_url = auth->e_mud_url;
4346 }
4347 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
4348 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
4349 auth->peer_bi ? auth->peer_bi->id :
4350 auth->tmp_peer_bi->id, MAC2STR(sa),
4351 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
4352 os_free(buf);
4353
4354 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4355 NULL);
4356 eloop_register_timeout(0, 50000,
4357 wpas_dpp_gas_initial_resp_timeout, wpa_s,
4358 NULL);
4359 return NULL;
4360 }
4361
Sunil Ravia04bd252022-05-02 22:54:18 -07004362 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08004363 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004364 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004365 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07004366 dpp_auth_deinit(wpa_s->dpp_auth);
4367 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08004368 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004369 return resp;
4370}
4371
4372
4373static void
4374wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
4375{
4376 struct wpa_supplicant *wpa_s = ctx;
4377 struct dpp_authentication *auth = wpa_s->dpp_auth;
4378
4379 if (!auth) {
4380 wpabuf_free(resp);
4381 return;
4382 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004383 if (auth->conf_resp != resp) {
4384 wpa_printf(MSG_DEBUG,
4385 "DPP: Ignore GAS status report (ok=%d) for unknown response",
4386 ok);
4387 wpabuf_free(resp);
4388 return;
4389 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004390
Hai Shalom899fcc72020-10-19 14:38:18 -07004391#ifdef CONFIG_DPP2
4392 if (auth->waiting_csr && ok) {
4393 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
4394 wpabuf_free(resp);
4395 return;
4396 }
4397#endif /* CONFIG_DPP2 */
4398
Sunil Ravia04bd252022-05-02 22:54:18 -07004399#ifdef CONFIG_DPP3
4400 if (auth->waiting_new_key && ok) {
4401 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
4402 wpabuf_free(resp);
4403 return;
4404 }
4405#endif /* CONFIG_DPP3 */
4406
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004407 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
4408 ok);
4409 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004410 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004411 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004412#ifdef CONFIG_DPP2
4413 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08004414 auth->conf_resp_status == DPP_STATUS_OK &&
4415 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07004416 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08004417 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07004418 auth->waiting_conf_result = 1;
4419 auth->conf_resp = NULL;
4420 wpabuf_free(resp);
4421 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
4422 wpa_s, NULL);
4423 eloop_register_timeout(2, 0,
4424 wpas_dpp_config_result_wait_timeout,
4425 wpa_s, NULL);
4426 return;
4427 }
4428#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004429 offchannel_send_action_done(wpa_s);
4430 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004431 if (ok) {
Sunil Ravi89eba102022-09-13 21:04:37 -07004432 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
4433 auth->conf_resp_status);
Hai Shalom706f99b2019-01-08 16:23:37 -08004434 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004435 }
4436 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004437 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004438 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004439 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004440 dpp_auth_deinit(wpa_s->dpp_auth);
4441 wpa_s->dpp_auth = NULL;
4442 wpabuf_free(resp);
Sunil Ravi89eba102022-09-13 21:04:37 -07004443#ifdef CONFIG_DPP3
4444 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
4445 if (ok)
4446 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4447 "success");
4448 else
4449 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4450 "could-not-connect");
4451 wpa_s->dpp_pb_result_indicated = true;
4452 if (ok)
4453 wpas_dpp_remove_pb_hash(wpa_s);
4454 wpas_dpp_push_button_stop(wpa_s);
4455 }
4456#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004457}
4458
4459
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004460int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
4461{
4462 struct dpp_authentication *auth;
4463 int ret = -1;
4464 char *curve = NULL;
4465
Hai Shalomfdcde762020-04-02 11:19:20 -07004466 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004467 if (!auth)
4468 return -1;
4469
4470 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08004471 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07004472 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004473 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07004474 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
4475 &auth->conf_obj[0]);
4476 if (!ret)
4477 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004478
4479 dpp_auth_deinit(auth);
4480 os_free(curve);
4481
4482 return ret;
4483}
4484
4485
4486static void
4487wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
4488 unsigned int freq, const u8 *dst,
4489 const u8 *src, const u8 *bssid,
4490 const u8 *data, size_t data_len,
4491 enum offchannel_send_action_result result)
4492{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004493 const char *res_txt;
4494
4495 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
4496 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
4497 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004498 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
4499 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07004500 freq, MAC2STR(dst), res_txt);
4501 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
4502 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004503 /* TODO: Time out wait for response more quickly in error cases? */
4504}
4505
4506
Sunil Ravi89eba102022-09-13 21:04:37 -07004507#ifdef CONFIG_DPP3
4508static int wpas_dpp_start_private_peer_intro(struct wpa_supplicant *wpa_s,
4509 struct wpa_ssid *ssid,
4510 struct wpa_bss *bss)
4511{
4512 struct wpabuf *msg;
4513 unsigned int wait_time;
4514 size_t len;
4515 u8 ver = DPP_VERSION;
4516 int conn_ver;
4517
4518 len = 5 + 5;
4519 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_QUERY, len);
4520 if (!msg)
4521 return -1;
4522
4523 /* Transaction ID */
4524 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4525 wpabuf_put_le16(msg, 1);
4526 wpabuf_put_u8(msg, TRANSACTION_ID);
4527
4528 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4529 if (conn_ver > 0 && ver != conn_ver) {
4530 wpa_printf(MSG_DEBUG,
4531 "DPP: Use Connector version %d instead of current protocol version %d",
4532 conn_ver, ver);
4533 ver = conn_ver;
4534 }
4535
4536 /* Protocol Version */
4537 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4538 wpabuf_put_le16(msg, 1);
4539 wpabuf_put_u8(msg, ver);
4540
4541 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Query", msg);
4542
4543 /* TODO: Timeout on AP response */
4544 wait_time = wpa_s->max_remain_on_chan;
4545 if (wait_time > 2000)
4546 wait_time = 2000;
4547 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4548 MAC2STR(bss->bssid), bss->freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
4549 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4550 broadcast,
4551 wpabuf_head(msg), wpabuf_len(msg),
4552 wait_time, wpas_dpp_tx_introduction_status, 0);
4553 wpabuf_free(msg);
4554
4555 /* Request this connection attempt to terminate - new one will be
4556 * started when network introduction protocol completes */
4557 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4558 wpa_s->dpp_intro_network = ssid;
4559 return 1;
4560}
4561#endif /* CONFIG_DPP3 */
4562
4563
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004564int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4565 struct wpa_bss *bss)
4566{
4567 struct os_time now;
4568 struct wpabuf *msg;
4569 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07004570 const u8 *rsn;
4571 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004572 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004573
4574 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
4575 return 0; /* Not using DPP AKM - continue */
Sunil Ravi7f769292024-07-23 22:21:32 +00004576 rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
Hai Shalom021b0b52019-04-10 11:17:58 -07004577 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
4578 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
4579 return 0; /* AP does not support DPP AKM - continue */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004580 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, wpa_s->own_addr, ssid))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004581 return 0; /* PMKSA exists for DPP AKM - continue */
4582
4583 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4584 !ssid->dpp_csign) {
4585 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4586 "missing %s",
4587 !ssid->dpp_connector ? "Connector" :
4588 (!ssid->dpp_netaccesskey ? "netAccessKey" :
4589 "C-sign-key"));
4590 return -1;
4591 }
4592
4593 os_get_time(&now);
4594
4595 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07004596 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004597 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4598 "netAccessKey expired");
4599 return -1;
4600 }
4601
4602 wpa_printf(MSG_DEBUG,
Sunil Ravi89eba102022-09-13 21:04:37 -07004603 "DPP: Starting %snetwork introduction protocol to derive PMKSA for "
4604 MACSTR,
4605 ssid->dpp_connector_privacy ? "private " : "",
4606 MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07004607 if (wpa_s->wpa_state == WPA_SCANNING)
4608 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004609
Sunil Ravi89eba102022-09-13 21:04:37 -07004610#ifdef CONFIG_DPP3
4611 if (ssid->dpp_connector_privacy)
4612 return wpas_dpp_start_private_peer_intro(wpa_s, ssid, bss);
4613#endif /* CONFIG_DPP3 */
4614
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004615 len = 5 + 4 + os_strlen(ssid->dpp_connector);
4616#ifdef CONFIG_DPP2
4617 len += 5;
4618#endif /* CONFIG_DPP2 */
4619 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004620 if (!msg)
4621 return -1;
4622
Roshan Pius3a1667e2018-07-03 15:17:14 -07004623#ifdef CONFIG_TESTING_OPTIONS
4624 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
4625 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
4626 goto skip_trans_id;
4627 }
4628 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
4629 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
4630 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4631 wpabuf_put_le16(msg, 0);
4632 goto skip_trans_id;
4633 }
4634#endif /* CONFIG_TESTING_OPTIONS */
4635
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004636 /* Transaction ID */
4637 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4638 wpabuf_put_le16(msg, 1);
4639 wpabuf_put_u8(msg, TRANSACTION_ID);
4640
Roshan Pius3a1667e2018-07-03 15:17:14 -07004641#ifdef CONFIG_TESTING_OPTIONS
4642skip_trans_id:
4643 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
4644 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
4645 goto skip_connector;
4646 }
4647 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
4648 char *connector;
4649
4650 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
4651 connector = dpp_corrupt_connector_signature(
4652 ssid->dpp_connector);
4653 if (!connector) {
4654 wpabuf_free(msg);
4655 return -1;
4656 }
4657 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4658 wpabuf_put_le16(msg, os_strlen(connector));
4659 wpabuf_put_str(msg, connector);
4660 os_free(connector);
4661 goto skip_connector;
4662 }
4663#endif /* CONFIG_TESTING_OPTIONS */
4664
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004665 /* DPP Connector */
4666 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4667 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
4668 wpabuf_put_str(msg, ssid->dpp_connector);
4669
Roshan Pius3a1667e2018-07-03 15:17:14 -07004670#ifdef CONFIG_TESTING_OPTIONS
4671skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004672 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
4673 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
4674 goto skip_proto_ver;
4675 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004676#endif /* CONFIG_TESTING_OPTIONS */
4677
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004678#ifdef CONFIG_DPP2
4679 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004680 u8 ver = DPP_VERSION;
4681#ifdef CONFIG_DPP3
4682 int conn_ver;
4683
4684 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4685 if (conn_ver > 0 && ver != conn_ver) {
4686 wpa_printf(MSG_DEBUG,
4687 "DPP: Use Connector version %d instead of current protocol version %d",
4688 conn_ver, ver);
4689 ver = conn_ver;
4690 }
4691#endif /* CONFIG_DPP3 */
4692
4693#ifdef CONFIG_TESTING_OPTIONS
4694 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
4695 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
4696 ver = 1;
4697 }
4698#endif /* CONFIG_TESTING_OPTIONS */
4699
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004700 /* Protocol Version */
4701 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4702 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004703 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004704 }
4705#endif /* CONFIG_DPP2 */
4706
Hai Shaloma20dcd72022-02-04 13:43:00 -08004707#ifdef CONFIG_TESTING_OPTIONS
4708skip_proto_ver:
4709#endif /* CONFIG_TESTING_OPTIONS */
4710
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004711 /* TODO: Timeout on AP response */
4712 wait_time = wpa_s->max_remain_on_chan;
4713 if (wait_time > 2000)
4714 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004715 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4716 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004717 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4718 broadcast,
4719 wpabuf_head(msg), wpabuf_len(msg),
4720 wait_time, wpas_dpp_tx_introduction_status, 0);
4721 wpabuf_free(msg);
4722
4723 /* Request this connection attempt to terminate - new one will be
4724 * started when network introduction protocol completes */
4725 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4726 wpa_s->dpp_intro_network = ssid;
4727 return 1;
4728}
4729
4730
4731int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
4732{
4733 struct dpp_bootstrap_info *own_bi;
4734 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07004735#ifdef CONFIG_DPP3
4736 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
4737#else /* CONFIG_DPP3 */
4738 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
4739#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004740 int tcp_port = DPP_TCP_PORT;
4741 struct hostapd_ip_addr *ipaddr = NULL;
4742#ifdef CONFIG_DPP2
4743 struct hostapd_ip_addr ipaddr_buf;
4744 char *addr;
4745
4746 pos = os_strstr(cmd, " tcp_port=");
4747 if (pos) {
4748 pos += 10;
4749 tcp_port = atoi(pos);
4750 }
4751
4752 addr = get_param(cmd, " tcp_addr=");
4753 if (addr) {
4754 int res;
4755
4756 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
4757 os_free(addr);
4758 if (res)
4759 return -1;
4760 ipaddr = &ipaddr_buf;
4761 }
4762#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004763
4764 pos = os_strstr(cmd, " own=");
4765 if (!pos)
4766 return -1;
4767 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07004768 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004769 if (!own_bi) {
4770 wpa_printf(MSG_DEBUG,
4771 "DPP: Identified bootstrap info not found");
4772 return -1;
4773 }
4774 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
4775 wpa_printf(MSG_DEBUG,
4776 "DPP: Identified bootstrap info not for PKEX");
4777 return -1;
4778 }
4779 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004780 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004781
4782 os_free(wpa_s->dpp_pkex_identifier);
4783 wpa_s->dpp_pkex_identifier = NULL;
4784 pos = os_strstr(cmd, " identifier=");
4785 if (pos) {
4786 pos += 12;
4787 end = os_strchr(pos, ' ');
4788 if (!end)
4789 return -1;
4790 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
4791 if (!wpa_s->dpp_pkex_identifier)
4792 return -1;
4793 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
4794 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
4795 }
4796
4797 pos = os_strstr(cmd, " code=");
4798 if (!pos)
4799 return -1;
4800 os_free(wpa_s->dpp_pkex_code);
4801 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
4802 if (!wpa_s->dpp_pkex_code)
4803 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004804 wpa_s->dpp_pkex_code_len = os_strlen(wpa_s->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004805
Sunil Ravia04bd252022-05-02 22:54:18 -07004806 pos = os_strstr(cmd, " ver=");
4807 if (pos) {
4808 int v;
4809
4810 pos += 5;
4811 v = atoi(pos);
4812 if (v == 1)
4813 ver = PKEX_VER_ONLY_1;
4814 else if (v == 2)
4815 ver = PKEX_VER_ONLY_2;
4816 else
4817 return -1;
4818 }
4819 wpa_s->dpp_pkex_ver = ver;
4820
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004821 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004822 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004823 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004824 } else {
4825#ifdef CONFIG_DPP2
4826 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
4827 wpa_s->dpp_pkex_code,
4828 wpa_s->dpp_pkex_identifier);
4829#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004830 }
4831
4832 /* TODO: Support multiple PKEX info entries */
4833
4834 os_free(wpa_s->dpp_pkex_auth_cmd);
4835 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
4836
4837 return 1;
4838}
4839
4840
4841int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
4842{
4843 unsigned int id_val;
4844
4845 if (os_strcmp(id, "*") == 0) {
4846 id_val = 0;
4847 } else {
4848 id_val = atoi(id);
4849 if (id_val == 0)
4850 return -1;
4851 }
4852
Sunil Ravi89eba102022-09-13 21:04:37 -07004853 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004854 return -1;
4855
4856 /* TODO: Support multiple PKEX entries */
4857 os_free(wpa_s->dpp_pkex_code);
4858 wpa_s->dpp_pkex_code = NULL;
4859 os_free(wpa_s->dpp_pkex_identifier);
4860 wpa_s->dpp_pkex_identifier = NULL;
4861 os_free(wpa_s->dpp_pkex_auth_cmd);
4862 wpa_s->dpp_pkex_auth_cmd = NULL;
4863 wpa_s->dpp_pkex_bi = NULL;
4864 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
4865 dpp_pkex_free(wpa_s->dpp_pkex);
4866 wpa_s->dpp_pkex = NULL;
4867 return 0;
4868}
4869
4870
Roshan Pius3a1667e2018-07-03 15:17:14 -07004871void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
4872{
Sunil Ravia04bd252022-05-02 22:54:18 -07004873 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07004874 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004875 dpp_auth_deinit(wpa_s->dpp_auth);
4876 wpa_s->dpp_auth = NULL;
4877 dpp_pkex_free(wpa_s->dpp_pkex);
4878 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004879 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004880 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
4881 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
Sunil Ravi89eba102022-09-13 21:04:37 -07004882#ifdef CONFIG_DPP3
4883 wpas_dpp_push_button_stop(wpa_s);
4884#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004885}
4886
4887
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004888int wpas_dpp_init(struct wpa_supplicant *wpa_s)
4889{
Hai Shalom81f62d82019-07-22 12:10:00 -07004890 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004891 u8 adv_proto_id[7];
4892
4893 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
4894 adv_proto_id[1] = 5;
4895 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
4896 adv_proto_id[5] = DPP_OUI_TYPE;
4897 adv_proto_id[6] = 0x01;
4898
4899 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
4900 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
4901 wpas_dpp_gas_status_handler, wpa_s) < 0)
4902 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004903
4904 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07004905 config.cb_ctx = wpa_s;
4906#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004907 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07004908#endif /* CONFIG_DPP2 */
4909 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07004910 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004911}
4912
4913
4914void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
4915{
4916#ifdef CONFIG_TESTING_OPTIONS
4917 os_free(wpa_s->dpp_config_obj_override);
4918 wpa_s->dpp_config_obj_override = NULL;
4919 os_free(wpa_s->dpp_discovery_override);
4920 wpa_s->dpp_discovery_override = NULL;
4921 os_free(wpa_s->dpp_groups_override);
4922 wpa_s->dpp_groups_override = NULL;
4923 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
4924#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07004925 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004926 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004927 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004928 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004929 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004930 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
4931 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004932 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4933 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004934 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
Sunil Ravi99c035e2024-07-12 01:42:03 +00004935 eloop_cancel_timeout(wpas_dpp_tx_auth_resp_roc_timeout, wpa_s, NULL);
4936 eloop_cancel_timeout(wpas_dpp_neg_freq_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004937#ifdef CONFIG_DPP2
4938 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07004939 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
4940 wpa_s, NULL);
4941 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004942 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
4943 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004944 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004945 eloop_cancel_timeout(wpas_dpp_connected_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004946 dpp_pfs_free(wpa_s->dpp_pfs);
4947 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004948 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004949 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4950 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07004951#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07004952#ifdef CONFIG_DPP3
4953 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
4954#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004955 offchannel_send_action_done(wpa_s);
4956 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004957 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004958 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004959 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
4960 os_free(wpa_s->dpp_configurator_params);
4961 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07004962 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004963}
Hai Shalom81f62d82019-07-22 12:10:00 -07004964
4965
Hai Shaloma20dcd72022-02-04 13:43:00 -08004966static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
4967 struct dpp_authentication *auth, bool tcp)
4968{
4969 struct wpabuf *resp;
4970
4971 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
4972 auth->e_netrole, true);
4973 if (!resp)
4974 return -1;
4975
4976 if (tcp) {
4977 auth->conf_resp_tcp = resp;
4978 return 0;
4979 }
4980
4981 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4982 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
4983 resp) < 0) {
4984 wpa_printf(MSG_DEBUG,
4985 "DPP: Could not find pending GAS response");
4986 wpabuf_free(resp);
4987 return -1;
4988 }
4989 auth->conf_resp = resp;
4990 return 0;
4991}
4992
4993
4994int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
4995{
4996 int peer;
4997 const char *pos;
4998 struct dpp_authentication *auth = wpa_s->dpp_auth;
4999 bool tcp = false;
5000
5001 pos = os_strstr(cmd, " peer=");
5002 if (!pos)
5003 return -1;
5004 peer = atoi(pos + 6);
5005#ifdef CONFIG_DPP2
5006 if (!auth || !auth->waiting_config ||
5007 (auth->peer_bi &&
5008 (unsigned int) peer != auth->peer_bi->id)) {
5009 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5010 tcp = true;
5011 }
5012#endif /* CONFIG_DPP2 */
5013
5014 if (!auth || !auth->waiting_config) {
5015 wpa_printf(MSG_DEBUG,
5016 "DPP: No authentication exchange waiting for configuration information");
5017 return -1;
5018 }
5019
5020 if ((!auth->peer_bi ||
5021 (unsigned int) peer != auth->peer_bi->id) &&
5022 (!auth->tmp_peer_bi ||
5023 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5024 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5025 return -1;
5026 }
5027
5028 pos = os_strstr(cmd, " comeback=");
5029 if (pos) {
5030 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
5031 NULL);
5032 gas_server_set_comeback_delay(wpa_s->gas_server,
5033 auth->config_resp_ctx,
5034 atoi(pos + 10));
5035 return 0;
5036 }
5037
5038 if (dpp_set_configurator(auth, cmd) < 0)
5039 return -1;
5040
5041 auth->use_config_query = false;
5042 auth->waiting_config = false;
5043 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5044}
5045
5046
Hai Shalom81f62d82019-07-22 12:10:00 -07005047#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07005048
Hai Shalom81f62d82019-07-22 12:10:00 -07005049int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
5050{
5051 struct dpp_controller_config config;
5052 const char *pos;
5053
5054 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005055 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07005056 config.netrole = DPP_NETROLE_STA;
5057 config.msg_ctx = wpa_s;
5058 config.cb_ctx = wpa_s;
5059 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005060 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07005061 if (cmd) {
5062 pos = os_strstr(cmd, " tcp_port=");
5063 if (pos) {
5064 pos += 10;
5065 config.tcp_port = atoi(pos);
5066 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005067
5068 pos = os_strstr(cmd, " role=");
5069 if (pos) {
5070 pos += 6;
5071 if (os_strncmp(pos, "configurator", 12) == 0)
5072 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
5073 else if (os_strncmp(pos, "enrollee", 8) == 0)
5074 config.allowed_roles = DPP_CAPAB_ENROLLEE;
5075 else if (os_strncmp(pos, "either", 6) == 0)
5076 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
5077 DPP_CAPAB_ENROLLEE;
5078 else
5079 return -1;
5080 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005081
5082 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07005083 }
5084 config.configurator_params = wpa_s->dpp_configurator_params;
5085 return dpp_controller_start(wpa_s->dpp, &config);
5086}
Hai Shalomfdcde762020-04-02 11:19:20 -07005087
5088
5089static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
5090
5091static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
5092{
5093 struct wpa_supplicant *wpa_s = eloop_ctx;
5094
5095 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
5096 offchannel_send_action_done(wpa_s);
5097 wpas_dpp_chirp_next(wpa_s, NULL);
5098}
5099
5100
5101static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
5102 unsigned int freq, const u8 *dst,
5103 const u8 *src, const u8 *bssid,
5104 const u8 *data, size_t data_len,
5105 enum offchannel_send_action_result result)
5106{
5107 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5108 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
5109 wpa_s->dpp_chirp_freq);
5110 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
5111 wpa_s, NULL) < 0)
5112 wpas_dpp_chirp_stop(wpa_s);
5113 return;
5114 }
5115
5116 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
5117 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
5118 wpa_s, NULL) < 0)
5119 wpas_dpp_chirp_stop(wpa_s);
5120}
5121
5122
5123static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
5124{
Hai Shalom899fcc72020-10-19 14:38:18 -07005125 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005126 int type;
5127
5128 msg = wpa_s->dpp_presence_announcement;
5129 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
5130 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07005131 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
5132
5133 if (ssid && wpa_s->dpp_reconfig_id &&
5134 wpa_config_get_network(wpa_s->conf,
5135 wpa_s->dpp_reconfig_ssid_id) ==
5136 ssid) {
5137 announce = dpp_build_reconfig_announcement(
5138 ssid->dpp_csign,
5139 ssid->dpp_csign_len,
5140 ssid->dpp_netaccesskey,
5141 ssid->dpp_netaccesskey_len,
5142 wpa_s->dpp_reconfig_id);
5143 msg = announce;
5144 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005145 if (!msg)
5146 return;
5147 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
5148 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005149 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
5150 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005151 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07005152 if (offchannel_send_action(
5153 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
5154 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005155 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07005156 2000, wpas_dpp_chirp_tx_status, 0) < 0)
5157 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07005158
5159 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07005160}
5161
5162
Sunil Ravi89eba102022-09-13 21:04:37 -07005163static int * wpas_dpp_presence_ann_channels(struct wpa_supplicant *wpa_s,
5164 struct dpp_bootstrap_info *bi)
Hai Shalomfdcde762020-04-02 11:19:20 -07005165{
Hai Shalomfdcde762020-04-02 11:19:20 -07005166 unsigned int i;
5167 struct hostapd_hw_modes *mode;
5168 int c;
5169 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005170 bool chan6 = wpa_s->hw.modes == NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005171 int *freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07005172
5173 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005174 if (bi) {
5175 for (i = 0; i < bi->num_freq; i++)
Sunil Ravi89eba102022-09-13 21:04:37 -07005176 int_array_add_unique(&freqs, bi->freq[i]);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005177 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005178
5179 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07005180 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005181 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07005182 if (mode) {
5183 for (c = 0; c < mode->num_channels; c++) {
5184 struct hostapd_channel_data *chan = &mode->channels[c];
5185
5186 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
5187 chan->freq != 2437)
5188 continue;
5189 chan6 = true;
5190 break;
5191 }
5192 }
5193 if (chan6)
Sunil Ravi89eba102022-09-13 21:04:37 -07005194 int_array_add_unique(&freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07005195
5196 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005197 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005198 if (mode) {
5199 int chan44 = 0, chan149 = 0;
5200
5201 for (c = 0; c < mode->num_channels; c++) {
5202 struct hostapd_channel_data *chan = &mode->channels[c];
5203
5204 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
5205 HOSTAPD_CHAN_RADAR))
5206 continue;
5207 if (chan->freq == 5220)
5208 chan44 = 1;
5209 if (chan->freq == 5745)
5210 chan149 = 1;
5211 }
5212 if (chan149)
Sunil Ravi89eba102022-09-13 21:04:37 -07005213 int_array_add_unique(&freqs, 5745);
Hai Shalomfdcde762020-04-02 11:19:20 -07005214 else if (chan44)
Sunil Ravi89eba102022-09-13 21:04:37 -07005215 int_array_add_unique(&freqs, 5220);
Hai Shalomfdcde762020-04-02 11:19:20 -07005216 }
5217
5218 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005219 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005220 if (mode) {
5221 for (c = 0; c < mode->num_channels; c++) {
5222 struct hostapd_channel_data *chan = &mode->channels[c];
5223
5224 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
5225 HOSTAPD_CHAN_RADAR)) ||
5226 chan->freq != 60480)
5227 continue;
Sunil Ravi89eba102022-09-13 21:04:37 -07005228 int_array_add_unique(&freqs, 60480);
Hai Shalomfdcde762020-04-02 11:19:20 -07005229 break;
5230 }
5231 }
5232
5233 /* Add channels from scan results for APs that advertise Configurator
5234 * Connectivity element */
5235 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5236 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
Sunil Ravi89eba102022-09-13 21:04:37 -07005237 int_array_add_unique(&freqs, bss->freq);
Hai Shalomfdcde762020-04-02 11:19:20 -07005238 }
5239
Sunil Ravi89eba102022-09-13 21:04:37 -07005240 return freqs;
5241}
5242
5243
5244static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
5245 struct wpa_scan_results *scan_res)
5246{
5247 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
5248
5249 if (!bi && !wpa_s->dpp_reconfig_ssid)
5250 return;
5251
5252 wpa_s->dpp_chirp_scan_done = 1;
5253
5254 os_free(wpa_s->dpp_chirp_freqs);
5255 wpa_s->dpp_chirp_freqs = wpas_dpp_presence_ann_channels(wpa_s, bi);
5256
Hai Shalomfdcde762020-04-02 11:19:20 -07005257 if (!wpa_s->dpp_chirp_freqs ||
5258 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
5259 wpas_dpp_chirp_stop(wpa_s);
5260}
5261
5262
5263static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
5264{
5265 struct wpa_supplicant *wpa_s = eloop_ctx;
5266 int i;
5267
5268 if (wpa_s->dpp_chirp_listen)
5269 wpas_dpp_listen_stop(wpa_s);
5270
5271 if (wpa_s->dpp_chirp_freq == 0) {
5272 if (wpa_s->dpp_chirp_round % 4 == 0 &&
5273 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08005274 if (wpas_scan_scheduled(wpa_s)) {
5275 wpa_printf(MSG_DEBUG,
5276 "DPP: Deferring chirp scan because another scan is planned already");
5277 if (eloop_register_timeout(1, 0,
5278 wpas_dpp_chirp_next,
5279 wpa_s, NULL) < 0) {
5280 wpas_dpp_chirp_stop(wpa_s);
5281 return;
5282 }
5283 return;
5284 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005285 wpa_printf(MSG_DEBUG,
5286 "DPP: Update channel list for chirping");
5287 wpa_s->scan_req = MANUAL_SCAN_REQ;
5288 wpa_s->scan_res_handler =
5289 wpas_dpp_chirp_scan_res_handler;
5290 wpa_supplicant_req_scan(wpa_s, 0, 0);
5291 return;
5292 }
5293 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
5294 wpa_s->dpp_chirp_round++;
5295 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
5296 wpa_s->dpp_chirp_round);
5297 } else {
5298 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
5299 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
5300 break;
5301 if (!wpa_s->dpp_chirp_freqs[i]) {
5302 wpa_printf(MSG_DEBUG,
5303 "DPP: Previous chirp freq %d not found",
5304 wpa_s->dpp_chirp_freq);
5305 return;
5306 }
5307 i++;
5308 if (wpa_s->dpp_chirp_freqs[i]) {
5309 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
5310 } else {
5311 wpa_s->dpp_chirp_iter--;
5312 if (wpa_s->dpp_chirp_iter <= 0) {
5313 wpa_printf(MSG_DEBUG,
5314 "DPP: Chirping iterations completed");
5315 wpas_dpp_chirp_stop(wpa_s);
5316 return;
5317 }
5318 wpa_s->dpp_chirp_freq = 0;
5319 wpa_s->dpp_chirp_scan_done = 0;
5320 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
5321 wpa_s, NULL) < 0) {
5322 wpas_dpp_chirp_stop(wpa_s);
5323 return;
5324 }
5325 if (wpa_s->dpp_chirp_listen) {
5326 wpa_printf(MSG_DEBUG,
5327 "DPP: Listen on %d MHz during chirp 30 second wait",
5328 wpa_s->dpp_chirp_listen);
5329 wpas_dpp_listen_start(wpa_s,
5330 wpa_s->dpp_chirp_listen);
5331 } else {
5332 wpa_printf(MSG_DEBUG,
5333 "DPP: Wait 30 seconds before starting the next chirping round");
5334 }
5335 return;
5336 }
5337 }
5338
5339 wpas_dpp_chirp_start(wpa_s);
5340}
5341
5342
5343int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
5344{
5345 const char *pos;
5346 int iter = 1, listen_freq = 0;
5347 struct dpp_bootstrap_info *bi;
5348
5349 pos = os_strstr(cmd, " own=");
5350 if (!pos)
5351 return -1;
5352 pos += 5;
5353 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
5354 if (!bi) {
5355 wpa_printf(MSG_DEBUG,
5356 "DPP: Identified bootstrap info not found");
5357 return -1;
5358 }
5359
5360 pos = os_strstr(cmd, " iter=");
5361 if (pos) {
5362 iter = atoi(pos + 6);
5363 if (iter <= 0)
5364 return -1;
5365 }
5366
5367 pos = os_strstr(cmd, " listen=");
5368 if (pos) {
5369 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005370 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005371 return -1;
5372 }
5373
5374 wpas_dpp_chirp_stop(wpa_s);
5375 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005376 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07005377 wpa_s->dpp_qr_mutual = 0;
5378 wpa_s->dpp_chirp_bi = bi;
5379 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
5380 if (!wpa_s->dpp_presence_announcement)
5381 return -1;
5382 wpa_s->dpp_chirp_iter = iter;
5383 wpa_s->dpp_chirp_round = 0;
5384 wpa_s->dpp_chirp_scan_done = 0;
5385 wpa_s->dpp_chirp_listen = listen_freq;
5386
5387 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5388}
5389
5390
5391void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
5392{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005393 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07005394 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005395 offchannel_send_action_done(wpa_s);
5396 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
5397 }
5398 wpa_s->dpp_chirp_bi = NULL;
5399 wpabuf_free(wpa_s->dpp_presence_announcement);
5400 wpa_s->dpp_presence_announcement = NULL;
5401 if (wpa_s->dpp_chirp_listen)
5402 wpas_dpp_listen_stop(wpa_s);
5403 wpa_s->dpp_chirp_listen = 0;
5404 wpa_s->dpp_chirp_freq = 0;
5405 os_free(wpa_s->dpp_chirp_freqs);
5406 wpa_s->dpp_chirp_freqs = NULL;
5407 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
5408 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
5409 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
5410 wpas_abort_ongoing_scan(wpa_s);
5411 wpa_s->scan_res_handler = NULL;
5412 }
5413}
5414
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005415
Hai Shalom899fcc72020-10-19 14:38:18 -07005416int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005417{
Hai Shalom899fcc72020-10-19 14:38:18 -07005418 struct wpa_ssid *ssid;
5419 int iter = 1;
5420 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005421
Hai Shalom899fcc72020-10-19 14:38:18 -07005422 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
5423 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
5424 !ssid->dpp_csign) {
5425 wpa_printf(MSG_DEBUG,
5426 "DPP: Not a valid network profile for reconfiguration");
5427 return -1;
5428 }
5429
5430 pos = os_strstr(cmd, " iter=");
5431 if (pos) {
5432 iter = atoi(pos + 6);
5433 if (iter <= 0)
5434 return -1;
5435 }
5436
5437 if (wpa_s->dpp_auth) {
5438 wpa_printf(MSG_DEBUG,
5439 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
5440 return -1;
5441 }
5442
5443 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
5444 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
5445 ssid->dpp_csign_len,
5446 ssid->dpp_pp_key,
5447 ssid->dpp_pp_key_len);
5448 if (!wpa_s->dpp_reconfig_id) {
5449 wpa_printf(MSG_DEBUG,
5450 "DPP: Failed to generate E-id for reconfiguration");
5451 return -1;
5452 }
5453 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
5454 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
5455 wpa_s->own_disconnect_req = 1;
5456 wpa_supplicant_deauthenticate(
5457 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5458 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005459 wpas_dpp_chirp_stop(wpa_s);
5460 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005461 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005462 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005463 wpa_s->dpp_reconfig_ssid = ssid;
5464 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07005465 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005466 wpa_s->dpp_chirp_round = 0;
5467 wpa_s->dpp_chirp_scan_done = 0;
5468 wpa_s->dpp_chirp_listen = 0;
5469
5470 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5471}
5472
Hai Shalom899fcc72020-10-19 14:38:18 -07005473
Hai Shalom899fcc72020-10-19 14:38:18 -07005474int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
5475{
5476 int peer = -1;
5477 const char *pos, *value;
5478 struct dpp_authentication *auth = wpa_s->dpp_auth;
5479 u8 *bin;
5480 size_t bin_len;
5481 struct wpabuf *buf;
5482 bool tcp = false;
5483
5484 pos = os_strstr(cmd, " peer=");
5485 if (pos) {
5486 peer = atoi(pos + 6);
5487 if (!auth || !auth->waiting_cert ||
5488 (auth->peer_bi &&
5489 (unsigned int) peer != auth->peer_bi->id)) {
5490 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5491 tcp = true;
5492 }
5493 }
5494
5495 if (!auth || !auth->waiting_cert) {
5496 wpa_printf(MSG_DEBUG,
5497 "DPP: No authentication exchange waiting for certificate information");
5498 return -1;
5499 }
5500
5501 if (peer >= 0 &&
5502 (!auth->peer_bi ||
5503 (unsigned int) peer != auth->peer_bi->id) &&
5504 (!auth->tmp_peer_bi ||
5505 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5506 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5507 return -1;
5508 }
5509
5510 pos = os_strstr(cmd, " value=");
5511 if (!pos)
5512 return -1;
5513 value = pos + 7;
5514
5515 pos = os_strstr(cmd, " name=");
5516 if (!pos)
5517 return -1;
5518 pos += 6;
5519
5520 if (os_strncmp(pos, "status ", 7) == 0) {
5521 auth->force_conf_resp_status = atoi(value);
5522 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5523 }
5524
5525 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
5526 os_free(auth->trusted_eap_server_name);
5527 auth->trusted_eap_server_name = os_strdup(value);
5528 return auth->trusted_eap_server_name ? 0 : -1;
5529 }
5530
5531 bin = base64_decode(value, os_strlen(value), &bin_len);
5532 if (!bin)
5533 return -1;
5534 buf = wpabuf_alloc_copy(bin, bin_len);
5535 os_free(bin);
5536
5537 if (os_strncmp(pos, "caCert ", 7) == 0) {
5538 wpabuf_free(auth->cacert);
5539 auth->cacert = buf;
5540 return 0;
5541 }
5542
5543 if (os_strncmp(pos, "certBag ", 8) == 0) {
5544 wpabuf_free(auth->certbag);
5545 auth->certbag = buf;
5546 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5547 }
5548
5549 wpabuf_free(buf);
5550 return -1;
5551}
5552
Hai Shalom81f62d82019-07-22 12:10:00 -07005553#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07005554
5555
5556#ifdef CONFIG_DPP3
5557
5558#define DPP_PB_ANNOUNCE_PER_CHAN 3
5559
5560static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07005561
5562
5563static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
5564 unsigned int freq, const u8 *dst,
5565 const u8 *src, const u8 *bssid,
5566 const u8 *data, size_t data_len,
5567 enum offchannel_send_action_result result)
5568{
5569 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5570 wpa_printf(MSG_DEBUG,
5571 "DPP: Failed to send push button announcement on %d MHz",
5572 freq);
5573 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
5574 wpa_s, NULL) < 0)
5575 wpas_dpp_push_button_stop(wpa_s);
5576 return;
5577 }
5578
5579 wpa_printf(MSG_DEBUG, "DPP: Push button announcement on %d MHz sent",
5580 freq);
5581 if (wpa_s->dpp_pb_discovery_done) {
5582 wpa_s->dpp_pb_announce_count = 0;
5583 wpa_printf(MSG_DEBUG,
5584 "DPP: Wait for push button announcement response and PKEX on %d MHz",
5585 freq);
5586 if (eloop_register_timeout(0, 500000, wpas_dpp_pb_next,
5587 wpa_s, NULL) < 0)
5588 wpas_dpp_push_button_stop(wpa_s);
5589 return;
5590 } else if (wpa_s->dpp_pb_announce_count >= DPP_PB_ANNOUNCE_PER_CHAN) {
5591 wpa_printf(MSG_DEBUG,
5592 "DPP: Wait for push button announcement response on %d MHz",
5593 freq);
5594 if (eloop_register_timeout(0, 50000, wpas_dpp_pb_next,
5595 wpa_s, NULL) < 0)
5596 wpas_dpp_push_button_stop(wpa_s);
5597 return;
5598 }
5599
5600 if (wpas_dpp_pb_announce(wpa_s, freq) < 0)
5601 wpas_dpp_push_button_stop(wpa_s);
5602}
5603
5604
5605static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq)
5606{
5607 struct wpabuf *msg;
5608 int type;
5609
5610 msg = wpa_s->dpp_pb_announcement;
5611 if (!msg)
5612 return -1;
5613
5614 wpa_s->dpp_pb_announce_count++;
5615 wpa_printf(MSG_DEBUG,
5616 "DPP: Send push button announcement %d/%d (%d MHz)",
5617 wpa_s->dpp_pb_announce_count, DPP_PB_ANNOUNCE_PER_CHAN,
5618 freq);
5619
5620 type = DPP_PA_PB_PRESENCE_ANNOUNCEMENT;
5621 if (wpa_s->dpp_pb_announce_count == 1)
5622 wpa_msg(wpa_s, MSG_INFO,
5623 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
5624 MAC2STR(broadcast), freq, type);
5625 if (offchannel_send_action(
5626 wpa_s, freq, broadcast, wpa_s->own_addr, broadcast,
5627 wpabuf_head(msg), wpabuf_len(msg),
5628 1000, wpas_dpp_pb_tx_status, 0) < 0)
5629 return -1;
5630
5631 return 0;
5632}
5633
5634
5635static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx)
5636{
5637 struct wpa_supplicant *wpa_s = eloop_ctx;
5638 struct os_reltime now;
5639 int freq;
5640
5641 if (!wpa_s->dpp_pb_freqs)
5642 return;
5643
5644 os_get_reltime(&now);
5645 offchannel_send_action_done(wpa_s);
5646
5647 if (os_reltime_expired(&now, &wpa_s->dpp_pb_time, 100)) {
5648 wpa_printf(MSG_DEBUG, "DPP: Push button wait time expired");
5649 wpas_dpp_push_button_stop(wpa_s);
5650 return;
5651 }
5652
5653 if (wpa_s->dpp_pb_freq_idx >= int_array_len(wpa_s->dpp_pb_freqs)) {
5654 wpa_printf(MSG_DEBUG,
5655 "DPP: Completed push button announcement round");
5656 wpa_s->dpp_pb_freq_idx = 0;
5657 if (wpa_s->dpp_pb_stop_iter > 0) {
5658 wpa_s->dpp_pb_stop_iter--;
5659
5660 if (wpa_s->dpp_pb_stop_iter == 1) {
5661 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5662 "wait for AP/Configurator to allow PKEX to be initiated");
5663 if (eloop_register_timeout(10, 0,
5664 wpas_dpp_pb_next,
5665 wpa_s, NULL) < 0) {
5666 wpas_dpp_push_button_stop(wpa_s);
5667 return;
5668 }
5669 return;
5670 }
5671
5672 if (wpa_s->dpp_pb_stop_iter == 0) {
5673 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5674 "start push button PKEX responder on the discovered channel (%d MHz)",
5675 wpa_s->dpp_pb_resp_freq);
5676 wpa_s->dpp_pb_discovery_done = true;
5677
5678 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
5679
5680 os_free(wpa_s->dpp_pkex_code);
5681 wpa_s->dpp_pkex_code = os_memdup(
5682 wpa_s->dpp_pb_c_nonce,
5683 wpa_s->dpp_pb_c_nonce_len);
5684 wpa_s->dpp_pkex_code_len =
5685 wpa_s->dpp_pb_c_nonce_len;
5686
5687 os_free(wpa_s->dpp_pkex_identifier);
5688 wpa_s->dpp_pkex_identifier =
5689 os_strdup("PBPKEX");
5690
5691 if (!wpa_s->dpp_pkex_code ||
5692 !wpa_s->dpp_pkex_identifier) {
5693 wpas_dpp_push_button_stop(wpa_s);
5694 return;
5695 }
5696
5697 wpa_s->dpp_pkex_ver = PKEX_VER_ONLY_2;
5698
5699 os_free(wpa_s->dpp_pkex_auth_cmd);
5700 wpa_s->dpp_pkex_auth_cmd = NULL;
5701 }
5702 }
5703 }
5704
5705 if (wpa_s->dpp_pb_discovery_done)
5706 freq = wpa_s->dpp_pb_resp_freq;
5707 else
5708 freq = wpa_s->dpp_pb_freqs[wpa_s->dpp_pb_freq_idx++];
5709 wpa_s->dpp_pb_announce_count = 0;
5710 if (!wpa_s->dpp_pb_announcement) {
5711 wpa_printf(MSG_DEBUG, "DPP: Push button announcements stopped");
5712 return;
5713 }
5714 if (wpas_dpp_pb_announce(wpa_s, freq) < 0) {
5715 wpas_dpp_push_button_stop(wpa_s);
5716 return;
5717 }
5718}
5719
5720
5721static void wpas_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
5722{
5723 struct wpa_supplicant *wpa_s = eloop_ctx;
5724
5725 wpa_printf(MSG_DEBUG,
5726 "DPP: Active push button Configurator mode expired");
5727 wpas_dpp_push_button_stop(wpa_s);
5728}
5729
5730
5731static int wpas_dpp_push_button_configurator(struct wpa_supplicant *wpa_s,
5732 const char *cmd)
5733{
5734 wpa_s->dpp_pb_configurator = true;
5735 wpa_s->dpp_pb_announce_time.sec = 0;
5736 wpa_s->dpp_pb_announce_time.usec = 0;
5737 str_clear_free(wpa_s->dpp_pb_cmd);
5738 wpa_s->dpp_pb_cmd = NULL;
5739 if (cmd) {
5740 wpa_s->dpp_pb_cmd = os_strdup(cmd);
5741 if (!wpa_s->dpp_pb_cmd)
5742 return -1;
5743 }
5744 eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
5745 wpa_s, NULL);
5746
Sunil Ravi99c035e2024-07-12 01:42:03 +00005747 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS "started");
Sunil Ravi89eba102022-09-13 21:04:37 -07005748 return 0;
5749}
5750
5751
5752static void wpas_dpp_pb_scan_res_handler(struct wpa_supplicant *wpa_s,
5753 struct wpa_scan_results *scan_res)
5754{
5755 if (!wpa_s->dpp_pb_time.sec && !wpa_s->dpp_pb_time.usec)
5756 return;
5757
5758 os_free(wpa_s->dpp_pb_freqs);
5759 wpa_s->dpp_pb_freqs = wpas_dpp_presence_ann_channels(wpa_s, NULL);
5760
5761 wpa_printf(MSG_DEBUG, "DPP: Scan completed for PB discovery");
5762 if (!wpa_s->dpp_pb_freqs ||
5763 eloop_register_timeout(0, 0, wpas_dpp_pb_next, wpa_s, NULL) < 0)
5764 wpas_dpp_push_button_stop(wpa_s);
5765}
5766
5767
5768int wpas_dpp_push_button(struct wpa_supplicant *wpa_s, const char *cmd)
5769{
5770 int res;
5771
5772 if (!wpa_s->dpp)
5773 return -1;
5774 wpas_dpp_push_button_stop(wpa_s);
5775 wpas_dpp_stop(wpa_s);
5776 wpas_dpp_chirp_stop(wpa_s);
5777
5778 os_get_reltime(&wpa_s->dpp_pb_time);
5779
5780 if (cmd &&
5781 (os_strstr(cmd, " role=configurator") ||
5782 os_strstr(cmd, " conf=")))
5783 return wpas_dpp_push_button_configurator(wpa_s, cmd);
5784
5785 wpa_s->dpp_pb_configurator = false;
5786
5787 wpa_s->dpp_pb_freq_idx = 0;
5788
5789 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
5790 if (res < 0)
5791 return -1;
5792 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
5793 if (!wpa_s->dpp_pb_bi)
5794 return -1;
5795
5796 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
5797 wpa_s->dpp_netrole = DPP_NETROLE_STA;
5798 wpa_s->dpp_qr_mutual = 0;
5799 wpa_s->dpp_pb_announcement =
5800 dpp_build_pb_announcement(wpa_s->dpp_pb_bi);
5801 if (!wpa_s->dpp_pb_announcement)
5802 return -1;
5803
5804 wpa_printf(MSG_DEBUG,
5805 "DPP: Scan to create channel list for PB discovery");
5806 wpa_s->scan_req = MANUAL_SCAN_REQ;
5807 wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
5808 wpa_supplicant_req_scan(wpa_s, 0, 0);
Sunil Ravi99c035e2024-07-12 01:42:03 +00005809 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS "started");
Sunil Ravi89eba102022-09-13 21:04:37 -07005810 return 0;
5811}
5812
5813
5814void wpas_dpp_push_button_stop(struct wpa_supplicant *wpa_s)
5815{
5816 if (!wpa_s->dpp)
5817 return;
5818 os_free(wpa_s->dpp_pb_freqs);
5819 wpa_s->dpp_pb_freqs = NULL;
5820 wpabuf_free(wpa_s->dpp_pb_announcement);
5821 wpa_s->dpp_pb_announcement = NULL;
5822 if (wpa_s->dpp_pb_bi) {
5823 char id[20];
5824
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005825 if (wpa_s->dpp_pb_bi == wpa_s->dpp_pkex_bi)
5826 wpa_s->dpp_pkex_bi = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005827 os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
5828 dpp_bootstrap_remove(wpa_s->dpp, id);
5829 wpa_s->dpp_pb_bi = NULL;
5830 if (!wpa_s->dpp_pb_result_indicated) {
5831 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5832 wpa_s->dpp_pb_result_indicated = true;
5833 }
5834 }
5835
5836 wpa_s->dpp_pb_resp_freq = 0;
5837 wpa_s->dpp_pb_stop_iter = 0;
5838 wpa_s->dpp_pb_discovery_done = false;
5839 os_free(wpa_s->dpp_pb_cmd);
5840 wpa_s->dpp_pb_cmd = NULL;
5841
5842 eloop_cancel_timeout(wpas_dpp_pb_next, wpa_s, NULL);
5843 eloop_cancel_timeout(wpas_dpp_push_button_expire, wpa_s, NULL);
5844 if (wpas_dpp_pb_active(wpa_s)) {
5845 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
5846 if (!wpa_s->dpp_pb_result_indicated)
5847 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5848 }
5849 wpa_s->dpp_pb_time.sec = 0;
5850 wpa_s->dpp_pb_time.usec = 0;
5851 dpp_pkex_free(wpa_s->dpp_pkex);
5852 wpa_s->dpp_pkex = NULL;
5853 os_free(wpa_s->dpp_pkex_auth_cmd);
5854 wpa_s->dpp_pkex_auth_cmd = NULL;
5855
5856 wpa_s->dpp_pb_result_indicated = false;
5857
5858 str_clear_free(wpa_s->dpp_pb_cmd);
5859 wpa_s->dpp_pb_cmd = NULL;
5860
5861 if (wpa_s->scan_res_handler == wpas_dpp_pb_scan_res_handler) {
5862 wpas_abort_ongoing_scan(wpa_s);
5863 wpa_s->scan_res_handler = NULL;
5864 }
5865}
5866
5867#endif /* CONFIG_DPP3 */