blob: 1b2c756f243760fe9a98279c079a4de55110ba5b [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 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070062
63static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
64
65/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
66 * a single transaction in progress at any point in time. */
67static const u8 TRANSACTION_ID = 1;
68
69
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070070/**
71 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
72 * @wpa_s: Pointer to wpa_supplicant data
73 * @cmd: DPP URI read from a QR Code
74 * Returns: Identifier of the stored info or -1 on failure
75 */
76int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
77{
78 struct dpp_bootstrap_info *bi;
79 struct dpp_authentication *auth = wpa_s->dpp_auth;
80
Hai Shalom021b0b52019-04-10 11:17:58 -070081 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070082 if (!bi)
83 return -1;
84
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070085 if (auth && auth->response_pending &&
86 dpp_notify_new_qr_code(auth, bi) == 1) {
87 wpa_printf(MSG_DEBUG,
88 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070089 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
90 " freq=%u type=%d",
91 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
92 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070093 offchannel_send_action(wpa_s, auth->curr_freq,
94 auth->peer_mac_addr, wpa_s->own_addr,
95 broadcast,
96 wpabuf_head(auth->resp_msg),
97 wpabuf_len(auth->resp_msg),
98 500, wpas_dpp_tx_status, 0);
99 }
100
Hai Shalom899fcc72020-10-19 14:38:18 -0700101#ifdef CONFIG_DPP2
102 dpp_controller_new_qr_code(wpa_s->dpp, bi);
103#endif /* CONFIG_DPP2 */
104
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700105 return bi->id;
106}
107
108
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800109/**
110 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
111 * @wpa_s: Pointer to wpa_supplicant data
112 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
113 * Returns: Identifier of the stored info or -1 on failure
114 */
115int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
116{
117 struct dpp_bootstrap_info *bi;
118
119 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
120 if (!bi)
121 return -1;
122
123 return bi->id;
124}
125
126
Hai Shalomfdcde762020-04-02 11:19:20 -0700127int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd)
128{
129 const char *pos;
130 struct dpp_bootstrap_info *peer_bi, *own_bi;
131
132 pos = os_strstr(cmd, " own=");
133 if (!pos)
134 return -1;
135 pos += 5;
136 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
137 if (!own_bi)
138 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700139 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700140
141 pos = os_strstr(cmd, " uri=");
142 if (!pos)
143 return -1;
144 pos += 5;
145 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
146 if (!peer_bi) {
147 wpa_printf(MSG_INFO,
148 "DPP: Failed to parse URI from NFC Handover Request");
149 return -1;
150 }
151
152 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
153 return -1;
154
155 return peer_bi->id;
156}
157
158
159int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd)
160{
161 const char *pos;
162 struct dpp_bootstrap_info *peer_bi, *own_bi;
163
164 pos = os_strstr(cmd, " own=");
165 if (!pos)
166 return -1;
167 pos += 5;
168 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
169 if (!own_bi)
170 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700171 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700172
173 pos = os_strstr(cmd, " uri=");
174 if (!pos)
175 return -1;
176 pos += 5;
177 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
178 if (!peer_bi) {
179 wpa_printf(MSG_INFO,
180 "DPP: Failed to parse URI from NFC Handover Select");
181 return -1;
182 }
183
184 if (peer_bi->curve != own_bi->curve) {
185 wpa_printf(MSG_INFO,
186 "DPP: Peer (NFC Handover Selector) used different curve");
187 return -1;
188 }
189
190 return peer_bi->id;
191}
192
193
Roshan Pius3a1667e2018-07-03 15:17:14 -0700194static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
195{
196 struct wpa_supplicant *wpa_s = eloop_ctx;
197 struct dpp_authentication *auth = wpa_s->dpp_auth;
198
199 if (!auth || !auth->resp_msg)
200 return;
201
202 wpa_printf(MSG_DEBUG,
203 "DPP: Retry Authentication Response after timeout");
204 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
205 " freq=%u type=%d",
206 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
207 DPP_PA_AUTHENTICATION_RESP);
208 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
209 wpa_s->own_addr, broadcast,
210 wpabuf_head(auth->resp_msg),
211 wpabuf_len(auth->resp_msg),
212 500, wpas_dpp_tx_status, 0);
213}
214
215
216static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
217{
218 struct dpp_authentication *auth = wpa_s->dpp_auth;
219 unsigned int wait_time, max_tries;
220
221 if (!auth || !auth->resp_msg)
222 return;
223
224 if (wpa_s->dpp_resp_max_tries)
225 max_tries = wpa_s->dpp_resp_max_tries;
226 else
227 max_tries = 5;
228 auth->auth_resp_tries++;
229 if (auth->auth_resp_tries >= max_tries) {
230 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
231 offchannel_send_action_done(wpa_s);
232 dpp_auth_deinit(wpa_s->dpp_auth);
233 wpa_s->dpp_auth = NULL;
234 return;
235 }
236
237 if (wpa_s->dpp_resp_retry_time)
238 wait_time = wpa_s->dpp_resp_retry_time;
239 else
240 wait_time = 1000;
Sunil Ravi99c035e2024-07-12 01:42:03 +0000241 if (wpa_s->dpp_tx_chan_change) {
242 wpa_s->dpp_tx_chan_change = false;
243 if (wait_time > 100)
244 wait_time = 100;
245 }
246
Roshan Pius3a1667e2018-07-03 15:17:14 -0700247 wpa_printf(MSG_DEBUG,
248 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
249 wait_time);
250 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
251 eloop_register_timeout(wait_time / 1000,
252 (wait_time % 1000) * 1000,
253 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
254}
255
256
Hai Shalom021b0b52019-04-10 11:17:58 -0700257static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
258{
259 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700260 wpa_s->suitable_network = 0;
261 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700262 wpa_s->disconnected = 0;
263 wpa_s->reassociate = 1;
264 wpa_s->scan_runs = 0;
265 wpa_s->normal_scans = 0;
266 wpa_supplicant_cancel_sched_scan(wpa_s);
267 wpa_supplicant_req_scan(wpa_s, 0, 0);
268}
269
270
Hai Shalomc3565922019-10-28 11:58:20 -0700271#ifdef CONFIG_DPP2
272
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700273static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s,
274 unsigned int freq,
275 unsigned int wait_time)
276{
277 struct os_reltime now, res;
278 unsigned int remaining;
279
280 if (!wpa_s->dpp_listen_freq)
281 return;
282
283 os_get_reltime(&now);
284 if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) {
285 os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res);
286 remaining = res.sec * 1000 + res.usec / 1000;
287 } else {
288 remaining = 0;
289 }
290 if (wpa_s->dpp_listen_freq == freq && remaining > wait_time)
291 return;
292
293 wpa_printf(MSG_DEBUG,
294 "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms",
295 wpa_s->dpp_listen_freq, remaining, freq, wait_time);
296 wpas_dpp_listen_stop(wpa_s);
297
298 /* TODO: Restart listen in some cases after TX? */
299}
300
301
Hai Shalomc3565922019-10-28 11:58:20 -0700302static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
303 void *timeout_ctx)
304{
305 struct wpa_supplicant *wpa_s = eloop_ctx;
306 struct dpp_authentication *auth = wpa_s->dpp_auth;
307 enum dpp_status_error result;
308
Hai Shaloma20dcd72022-02-04 13:43:00 -0800309 if ((!auth || !auth->conn_status_requested) &&
310 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700311 return;
312
313 wpa_printf(MSG_DEBUG,
314 "DPP: Connection timeout - report Connection Status Result");
315 if (wpa_s->suitable_network)
316 result = DPP_STATUS_AUTH_FAILURE;
317 else if (wpa_s->no_suitable_network)
318 result = DPP_STATUS_NO_AP;
319 else
320 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800321 if (wpa_s->wpa_state == WPA_SCANNING)
322 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700323 wpas_dpp_send_conn_status_result(wpa_s, result);
324}
325
326
327static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
328{
329 char *str, *end, *pos;
330 size_t len;
331 unsigned int i;
332 u8 last_op_class = 0;
333 int res;
334
335 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
336 return NULL;
337
338 len = wpa_s->num_last_scan_freqs * 8;
339 str = os_zalloc(len);
340 if (!str)
341 return NULL;
342 end = str + len;
343 pos = str;
344
345 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
346 enum hostapd_hw_mode mode;
347 u8 op_class, channel;
348
349 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
350 0, 0, &op_class, &channel);
351 if (mode == NUM_HOSTAPD_MODES)
352 continue;
353 if (op_class == last_op_class)
354 res = os_snprintf(pos, end - pos, ",%d", channel);
355 else
356 res = os_snprintf(pos, end - pos, "%s%d/%d",
357 pos == str ? "" : ",",
358 op_class, channel);
359 if (os_snprintf_error(end - pos, res)) {
360 *pos = '\0';
361 break;
362 }
363 pos += res;
364 last_op_class = op_class;
365 }
366
367 if (pos == str) {
368 os_free(str);
369 str = NULL;
370 }
371 return str;
372}
373
374
375void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
376 enum dpp_status_error result)
377{
378 struct wpabuf *msg;
379 const char *channel_list = NULL;
380 char *channel_list_buf = NULL;
381 struct wpa_ssid *ssid = wpa_s->current_ssid;
382 struct dpp_authentication *auth = wpa_s->dpp_auth;
383
384 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
385
Hai Shaloma20dcd72022-02-04 13:43:00 -0800386 if ((!auth || !auth->conn_status_requested) &&
387 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700388 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800389
Hai Shalomc3565922019-10-28 11:58:20 -0700390 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
391 result);
392
393 if (result == DPP_STATUS_NO_AP) {
394 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
395 channel_list = channel_list_buf;
396 }
397
Hai Shaloma20dcd72022-02-04 13:43:00 -0800398 if (!auth || !auth->conn_status_requested) {
399 dpp_tcp_send_conn_status(wpa_s->dpp, result,
400 ssid ? ssid->ssid :
401 wpa_s->dpp_last_ssid,
402 ssid ? ssid->ssid_len :
403 wpa_s->dpp_last_ssid_len,
404 channel_list);
405 os_free(channel_list_buf);
406 return;
407 }
408
409 auth->conn_status_requested = 0;
410
Hai Shalomc3565922019-10-28 11:58:20 -0700411 msg = dpp_build_conn_status_result(auth, result,
412 ssid ? ssid->ssid :
413 wpa_s->dpp_last_ssid,
414 ssid ? ssid->ssid_len :
415 wpa_s->dpp_last_ssid_len,
416 channel_list);
417 os_free(channel_list_buf);
418 if (!msg) {
419 dpp_auth_deinit(wpa_s->dpp_auth);
420 wpa_s->dpp_auth = NULL;
421 return;
422 }
423
424 wpa_msg(wpa_s, MSG_INFO,
425 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
426 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
427 DPP_PA_CONNECTION_STATUS_RESULT);
Sunil Ravi546a7b52022-08-26 22:06:04 +0000428 if (offchannel_send_action(wpa_s, auth->curr_freq,
429 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
430 wpabuf_head(msg), wpabuf_len(msg),
431 500, wpas_dpp_tx_status, 0) < 0) {
432 wpas_notify_dpp_connection_status_sent(wpa_s, result);
433 wpabuf_free(msg);
434 dpp_auth_deinit(wpa_s->dpp_auth);
435 wpa_s->dpp_auth = NULL;
436 return;
437 }
438
Hai Shalomc3565922019-10-28 11:58:20 -0700439 wpabuf_free(msg);
440
Sunil Ravi546a7b52022-08-26 22:06:04 +0000441 auth->conn_result_status = result;
442 auth->tx_conn_status_result_started = 1;
Hai Shalomc3565922019-10-28 11:58:20 -0700443 /* This exchange will be terminated in the TX status handler */
444 auth->remove_on_tx_status = 1;
445
446 return;
447}
448
449
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000450static void wpas_dpp_connected_timeout(void *eloop_ctx, void *timeout_ctx)
Hai Shalomc3565922019-10-28 11:58:20 -0700451{
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000452 struct wpa_supplicant *wpa_s = eloop_ctx;
Hai Shalomc3565922019-10-28 11:58:20 -0700453 struct dpp_authentication *auth = wpa_s->dpp_auth;
454
Hai Shaloma20dcd72022-02-04 13:43:00 -0800455 if ((auth && auth->conn_status_requested) ||
456 dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700457 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
458}
459
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000460
461void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
462{
463 struct dpp_authentication *auth = wpa_s->dpp_auth;
464
465 if ((auth && auth->conn_status_requested) ||
466 dpp_tcp_conn_status_requested(wpa_s->dpp)) {
467 /* Report connection result from an eloop timeout to avoid delay
468 * to completing all connection completion steps since this
469 * function is called in a middle of the post 4-way handshake
470 * processing. */
471 eloop_register_timeout(0, 0, wpas_dpp_connected_timeout,
472 wpa_s, NULL);
473 }
474}
475
Hai Shalomc3565922019-10-28 11:58:20 -0700476#endif /* CONFIG_DPP2 */
477
478
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000479static void wpas_dpp_drv_wait_timeout(void *eloop_ctx, void *timeout_ctx)
480{
481 struct wpa_supplicant *wpa_s = eloop_ctx;
482 struct dpp_authentication *auth = wpa_s->dpp_auth;
483
484 if (auth && auth->waiting_auth_resp) {
485 wpa_printf(MSG_DEBUG,
486 "DPP: Call wpas_dpp_auth_init_next() from %s",
487 __func__);
488 wpas_dpp_auth_init_next(wpa_s);
489 } else {
490 wpa_printf(MSG_DEBUG, "DPP: %s, but no waiting_auth_resp",
491 __func__);
492 }
493}
494
495
Sunil Ravi99c035e2024-07-12 01:42:03 +0000496static void wpas_dpp_neg_freq_timeout(void *eloop_ctx, void *timeout_ctx)
497{
498 struct wpa_supplicant *wpa_s = eloop_ctx;
499 struct dpp_authentication *auth = wpa_s->dpp_auth;
500
501 if (!wpa_s->dpp_listen_on_tx_expire || !auth || !auth->neg_freq)
502 return;
503
504 wpa_printf(MSG_DEBUG,
505 "DPP: Start listen on neg_freq %u MHz based on timeout for TX wait expiration",
506 auth->neg_freq);
507 wpas_dpp_listen_start(wpa_s, auth->neg_freq);
508}
509
510
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700511static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
512 unsigned int freq, const u8 *dst,
513 const u8 *src, const u8 *bssid,
514 const u8 *data, size_t data_len,
515 enum offchannel_send_action_result result)
516{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700517 const char *res_txt;
518 struct dpp_authentication *auth = wpa_s->dpp_auth;
519
520 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
521 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
522 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700523 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700524 " result=%s", freq, MAC2STR(dst), res_txt);
525 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
526 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700527
528 if (!wpa_s->dpp_auth) {
529 wpa_printf(MSG_DEBUG,
530 "DPP: Ignore TX status since there is no ongoing authentication exchange");
531 return;
532 }
533
Hai Shalom021b0b52019-04-10 11:17:58 -0700534#ifdef CONFIG_DPP2
535 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700536 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700537 wpa_printf(MSG_DEBUG,
538 "DPP: Try to connect after completed configuration result");
539 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700540 if (auth->conn_status_requested) {
541 wpa_printf(MSG_DEBUG,
542 "DPP: Start 15 second timeout for reporting connection status result");
543 eloop_cancel_timeout(
544 wpas_dpp_conn_status_result_timeout,
545 wpa_s, NULL);
546 eloop_register_timeout(
547 15, 0, wpas_dpp_conn_status_result_timeout,
548 wpa_s, NULL);
549 } else {
550 dpp_auth_deinit(wpa_s->dpp_auth);
551 wpa_s->dpp_auth = NULL;
552 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700553 return;
554 }
555#endif /* CONFIG_DPP2 */
556
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700557 if (wpa_s->dpp_auth->remove_on_tx_status) {
Sunil Ravi546a7b52022-08-26 22:06:04 +0000558 if (auth->tx_conn_status_result_started) {
559 wpas_notify_dpp_connection_status_sent(wpa_s, auth->conn_result_status);
560 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700561 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700562 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700563 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700564 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800565 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
566 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700567 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
568 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700569#ifdef CONFIG_DPP2
570 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
571 wpa_s, NULL);
572#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700573 offchannel_send_action_done(wpa_s);
574 dpp_auth_deinit(wpa_s->dpp_auth);
575 wpa_s->dpp_auth = NULL;
576 return;
577 }
578
579 if (wpa_s->dpp_auth_ok_on_ack)
580 wpas_dpp_auth_success(wpa_s, 1);
581
582 if (!is_broadcast_ether_addr(dst) &&
583 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
584 wpa_printf(MSG_DEBUG,
585 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700586 if (auth->waiting_auth_resp) {
587 /* In case of DPP Authentication Request frame, move to
588 * the next channel immediately. */
589 offchannel_send_action_done(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000590 /* Call wpas_dpp_auth_init_next(wpa_s) from driver event
591 * notifying frame wait was completed or from eloop
592 * timeout. */
593 eloop_register_timeout(0, 10000,
594 wpas_dpp_drv_wait_timeout,
595 wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700596 return;
597 }
598 if (auth->waiting_auth_conf) {
599 wpas_dpp_auth_resp_retry(wpa_s);
600 return;
601 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700602 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700603
Hai Shalom60840252021-02-19 19:02:11 -0800604 if (auth->waiting_auth_conf &&
605 auth->auth_resp_status == DPP_STATUS_OK) {
606 /* Make sure we do not get stuck waiting for Auth Confirm
607 * indefinitely after successfully transmitted Auth Response to
608 * allow new authentication exchanges to be started. */
609 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
610 NULL);
611 eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
612 wpa_s, NULL);
613 }
614
Roshan Pius3a1667e2018-07-03 15:17:14 -0700615 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
616 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
617 /* Allow timeout handling to stop iteration if no response is
618 * received from a peer that has ACKed a request. */
619 auth->auth_req_ack = 1;
620 }
621
622 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
623 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
624 wpa_printf(MSG_DEBUG,
625 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
626 wpa_s->dpp_auth->curr_freq,
627 wpa_s->dpp_auth->neg_freq);
628 offchannel_send_action_done(wpa_s);
Sunil Ravi99c035e2024-07-12 01:42:03 +0000629 wpa_s->dpp_listen_on_tx_expire = true;
630 eloop_register_timeout(0, 100000, wpas_dpp_neg_freq_timeout,
631 wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700632 }
633
634 if (wpa_s->dpp_auth_ok_on_ack)
635 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700636}
637
638
639static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
640{
641 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700642 struct dpp_authentication *auth = wpa_s->dpp_auth;
643 unsigned int freq;
644 struct os_reltime now, diff;
645 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700646
Roshan Pius3a1667e2018-07-03 15:17:14 -0700647 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700648 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700649
650 wait_time = wpa_s->dpp_resp_wait_time ?
651 wpa_s->dpp_resp_wait_time : 2000;
652 os_get_reltime(&now);
653 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
654 diff_ms = diff.sec * 1000 + diff.usec / 1000;
655 wpa_printf(MSG_DEBUG,
656 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
657 wait_time, diff_ms);
658
659 if (auth->auth_req_ack && diff_ms >= wait_time) {
660 /* Peer ACK'ed Authentication Request frame, but did not reply
661 * with Authentication Response frame within two seconds. */
662 wpa_printf(MSG_INFO,
663 "DPP: No response received from responder - stopping initiation attempt");
664 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800665 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700666 offchannel_send_action_done(wpa_s);
667 wpas_dpp_listen_stop(wpa_s);
668 dpp_auth_deinit(auth);
669 wpa_s->dpp_auth = NULL;
670 return;
671 }
672
673 if (diff_ms >= wait_time) {
674 /* Authentication Request frame was not ACK'ed and no reply
675 * was receiving within two seconds. */
676 wpa_printf(MSG_DEBUG,
677 "DPP: Continue Initiator channel iteration");
678 offchannel_send_action_done(wpa_s);
679 wpas_dpp_listen_stop(wpa_s);
680 wpas_dpp_auth_init_next(wpa_s);
681 return;
682 }
683
684 /* Driver did not support 2000 ms long wait_time with TX command, so
685 * schedule listen operation to continue waiting for the response.
686 *
687 * DPP listen operations continue until stopped, so simply schedule a
688 * new call to this function at the point when the two second reply
689 * wait has expired. */
690 wait_time -= diff_ms;
691
692 freq = auth->curr_freq;
693 if (auth->neg_freq > 0)
694 freq = auth->neg_freq;
695 wpa_printf(MSG_DEBUG,
696 "DPP: Continue reply wait on channel %u MHz for %u ms",
697 freq, wait_time);
698 wpa_s->dpp_in_response_listen = 1;
699 wpas_dpp_listen_start(wpa_s, freq);
700
701 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
702 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700703}
704
705
Hai Shalom60840252021-02-19 19:02:11 -0800706static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
707{
708 struct wpa_supplicant *wpa_s = eloop_ctx;
709 struct dpp_authentication *auth = wpa_s->dpp_auth;
710
711 if (!auth || !auth->waiting_auth_conf)
712 return;
713
714 wpa_printf(MSG_DEBUG,
715 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
716 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
717 offchannel_send_action_done(wpa_s);
718 dpp_auth_deinit(auth);
719 wpa_s->dpp_auth = NULL;
720}
721
722
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700723static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
724 struct dpp_authentication *auth)
725{
726#ifdef CONFIG_TESTING_OPTIONS
727 if (wpa_s->dpp_config_obj_override)
728 auth->config_obj_override =
729 os_strdup(wpa_s->dpp_config_obj_override);
730 if (wpa_s->dpp_discovery_override)
731 auth->discovery_override =
732 os_strdup(wpa_s->dpp_discovery_override);
733 if (wpa_s->dpp_groups_override)
734 auth->groups_override =
735 os_strdup(wpa_s->dpp_groups_override);
736 auth->ignore_netaccesskey_mismatch =
737 wpa_s->dpp_ignore_netaccesskey_mismatch;
738#endif /* CONFIG_TESTING_OPTIONS */
739}
740
741
Roshan Pius3a1667e2018-07-03 15:17:14 -0700742static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
743{
744 struct wpa_supplicant *wpa_s = eloop_ctx;
745
746 if (!wpa_s->dpp_auth)
747 return;
748 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
749 wpas_dpp_auth_init_next(wpa_s);
750}
751
752
753static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
754{
755 struct dpp_authentication *auth = wpa_s->dpp_auth;
756 const u8 *dst;
757 unsigned int wait_time, max_wait_time, freq, max_tries, used;
758 struct os_reltime now, diff;
759
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000760 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
761
Roshan Pius3a1667e2018-07-03 15:17:14 -0700762 wpa_s->dpp_in_response_listen = 0;
763 if (!auth)
764 return -1;
765
766 if (auth->freq_idx == 0)
767 os_get_reltime(&wpa_s->dpp_init_iter_start);
768
769 if (auth->freq_idx >= auth->num_freq) {
770 auth->num_freq_iters++;
771 if (wpa_s->dpp_init_max_tries)
772 max_tries = wpa_s->dpp_init_max_tries;
773 else
774 max_tries = 5;
775 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
776 wpa_printf(MSG_INFO,
777 "DPP: No response received from responder - stopping initiation attempt");
778 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800779 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700780 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
781 wpa_s, NULL);
782 offchannel_send_action_done(wpa_s);
783 dpp_auth_deinit(wpa_s->dpp_auth);
784 wpa_s->dpp_auth = NULL;
785 return -1;
786 }
787 auth->freq_idx = 0;
788 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
789 if (wpa_s->dpp_init_retry_time)
790 wait_time = wpa_s->dpp_init_retry_time;
791 else
792 wait_time = 10000;
793 os_get_reltime(&now);
794 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
795 used = diff.sec * 1000 + diff.usec / 1000;
796 if (used > wait_time)
797 wait_time = 0;
798 else
799 wait_time -= used;
800 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
801 wait_time);
802 eloop_register_timeout(wait_time / 1000,
803 (wait_time % 1000) * 1000,
804 wpas_dpp_init_timeout, wpa_s,
805 NULL);
806 return 0;
807 }
808 freq = auth->freq[auth->freq_idx++];
809 auth->curr_freq = freq;
810
Hai Shalom60840252021-02-19 19:02:11 -0800811 if (!is_zero_ether_addr(auth->peer_mac_addr))
812 dst = auth->peer_mac_addr;
813 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700814 dst = broadcast;
815 else
816 dst = auth->peer_bi->mac_addr;
817 wpa_s->dpp_auth_ok_on_ack = 0;
818 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
819 wait_time = wpa_s->max_remain_on_chan;
820 max_wait_time = wpa_s->dpp_resp_wait_time ?
821 wpa_s->dpp_resp_wait_time : 2000;
822 if (wait_time > max_wait_time)
823 wait_time = max_wait_time;
824 wait_time += 10; /* give the driver some extra time to complete */
825 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
826 wpas_dpp_reply_wait_timeout,
827 wpa_s, NULL);
828 wait_time -= 10;
829 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
830 wpa_printf(MSG_DEBUG,
831 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
832 freq, auth->neg_freq);
833 }
834 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
835 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
836 auth->auth_req_ack = 0;
837 os_get_reltime(&wpa_s->dpp_last_init);
838 return offchannel_send_action(wpa_s, freq, dst,
839 wpa_s->own_addr, broadcast,
840 wpabuf_head(auth->req_msg),
841 wpabuf_len(auth->req_msg),
842 wait_time, wpas_dpp_tx_status, 0);
843}
844
845
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700846int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
847{
848 const char *pos;
849 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700850 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700851 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
852 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700853 int tcp = 0;
854#ifdef CONFIG_DPP2
855 int tcp_port = DPP_TCP_PORT;
856 struct hostapd_ip_addr ipaddr;
857 char *addr;
858#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700859
860 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800861 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700862
863 pos = os_strstr(cmd, " peer=");
864 if (!pos)
865 return -1;
866 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700867 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700868 if (!peer_bi) {
869 wpa_printf(MSG_INFO,
870 "DPP: Could not find bootstrapping info for the identified peer");
871 return -1;
872 }
873
Hai Shalom81f62d82019-07-22 12:10:00 -0700874#ifdef CONFIG_DPP2
875 pos = os_strstr(cmd, " tcp_port=");
876 if (pos) {
877 pos += 10;
878 tcp_port = atoi(pos);
879 }
880
881 addr = get_param(cmd, " tcp_addr=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000882 if (addr && os_strcmp(addr, "from-uri") == 0) {
883 os_free(addr);
884 if (!peer_bi->host) {
885 wpa_printf(MSG_INFO,
886 "DPP: TCP address not available in peer URI");
887 return -1;
888 }
889 tcp = 1;
890 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
891 tcp_port = peer_bi->port;
892 } else if (addr) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700893 int res;
894
895 res = hostapd_parse_ip_addr(addr, &ipaddr);
896 os_free(addr);
897 if (res)
898 return -1;
899 tcp = 1;
900 }
901#endif /* CONFIG_DPP2 */
902
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700903 pos = os_strstr(cmd, " own=");
904 if (pos) {
905 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700906 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700907 if (!own_bi) {
908 wpa_printf(MSG_INFO,
909 "DPP: Could not find bootstrapping info for the identified local entry");
910 return -1;
911 }
912
913 if (peer_bi->curve != own_bi->curve) {
914 wpa_printf(MSG_INFO,
915 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
916 peer_bi->curve->name, own_bi->curve->name);
917 return -1;
918 }
919 }
920
921 pos = os_strstr(cmd, " role=");
922 if (pos) {
923 pos += 6;
924 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700925 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700926 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700927 allowed_roles = DPP_CAPAB_ENROLLEE;
928 else if (os_strncmp(pos, "either", 6) == 0)
929 allowed_roles = DPP_CAPAB_CONFIGURATOR |
930 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700931 else
932 goto fail;
933 }
934
935 pos = os_strstr(cmd, " netrole=");
936 if (pos) {
937 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800938 if (os_strncmp(pos, "ap", 2) == 0)
939 wpa_s->dpp_netrole = DPP_NETROLE_AP;
940 else if (os_strncmp(pos, "configurator", 12) == 0)
941 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
942 else
943 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700944 } else {
945 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700946 }
947
Roshan Pius3a1667e2018-07-03 15:17:14 -0700948 pos = os_strstr(cmd, " neg_freq=");
949 if (pos)
950 neg_freq = atoi(pos + 10);
951
Hai Shalom81f62d82019-07-22 12:10:00 -0700952 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700953 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700954 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800955 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
956 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700957 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
958 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700959#ifdef CONFIG_DPP2
960 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
961 wpa_s, NULL);
962#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700963 offchannel_send_action_done(wpa_s);
964 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800965 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700966 }
967
Hai Shalomfdcde762020-04-02 11:19:20 -0700968 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
969 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700970 if (!auth)
971 goto fail;
972 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700973 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700974 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800975 goto fail;
976 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700977
Hai Shalom81f62d82019-07-22 12:10:00 -0700978 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700979
Roshan Pius3a1667e2018-07-03 15:17:14 -0700980 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700981 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700982
Hai Shalom81f62d82019-07-22 12:10:00 -0700983#ifdef CONFIG_DPP2
984 if (tcp)
Hai Shalom899fcc72020-10-19 14:38:18 -0700985 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
986 wpa_s->conf->dpp_name, DPP_NETROLE_STA,
Sunil Ravi89eba102022-09-13 21:04:37 -0700987 wpa_s->conf->dpp_mud_url,
988 wpa_s->conf->dpp_extra_conf_req_name,
989 wpa_s->conf->dpp_extra_conf_req_value,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800990 wpa_s, wpa_s, wpas_dpp_process_conf_obj,
991 wpas_dpp_tcp_msg_sent);
Hai Shalom81f62d82019-07-22 12:10:00 -0700992#endif /* CONFIG_DPP2 */
993
994 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700995 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700996fail:
997 return -1;
998}
999
1000
1001struct wpas_dpp_listen_work {
1002 unsigned int freq;
1003 unsigned int duration;
1004 struct wpabuf *probe_resp_ie;
1005};
1006
1007
1008static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
1009{
1010 if (!lwork)
1011 return;
1012 os_free(lwork);
1013}
1014
1015
1016static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
1017{
1018 struct wpas_dpp_listen_work *lwork;
1019
1020 if (!wpa_s->dpp_listen_work)
1021 return;
1022
1023 lwork = wpa_s->dpp_listen_work->ctx;
1024 wpas_dpp_listen_work_free(lwork);
1025 radio_work_done(wpa_s->dpp_listen_work);
1026 wpa_s->dpp_listen_work = NULL;
1027}
1028
1029
1030static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
1031{
1032 struct wpa_supplicant *wpa_s = work->wpa_s;
1033 struct wpas_dpp_listen_work *lwork = work->ctx;
1034
1035 if (deinit) {
1036 if (work->started) {
1037 wpa_s->dpp_listen_work = NULL;
1038 wpas_dpp_listen_stop(wpa_s);
1039 }
1040 wpas_dpp_listen_work_free(lwork);
1041 return;
1042 }
1043
1044 wpa_s->dpp_listen_work = work;
1045
1046 wpa_s->dpp_pending_listen_freq = lwork->freq;
1047
1048 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
1049 wpa_s->max_remain_on_chan) < 0) {
1050 wpa_printf(MSG_DEBUG,
1051 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
1052 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -08001053 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001054 wpas_dpp_listen_work_done(wpa_s);
1055 wpa_s->dpp_pending_listen_freq = 0;
1056 return;
1057 }
1058 wpa_s->off_channel_freq = 0;
1059 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -07001060 wpa_drv_dpp_listen(wpa_s, true);
Sunil Ravi99c035e2024-07-12 01:42:03 +00001061 wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
1062 wpa_s->dpp_tx_chan_change = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001063}
1064
1065
1066static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
1067 unsigned int freq)
1068{
1069 struct wpas_dpp_listen_work *lwork;
1070
1071 if (wpa_s->dpp_listen_work) {
1072 wpa_printf(MSG_DEBUG,
1073 "DPP: Reject start_listen since dpp_listen_work already exists");
1074 return -1;
1075 }
1076
1077 if (wpa_s->dpp_listen_freq)
1078 wpas_dpp_listen_stop(wpa_s);
1079 wpa_s->dpp_listen_freq = freq;
1080
1081 lwork = os_zalloc(sizeof(*lwork));
1082 if (!lwork)
1083 return -1;
1084 lwork->freq = freq;
1085
1086 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
1087 lwork) < 0) {
1088 wpas_dpp_listen_work_free(lwork);
1089 return -1;
1090 }
1091
1092 return 0;
1093}
1094
1095
1096int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
1097{
1098 int freq;
1099
1100 freq = atoi(cmd);
1101 if (freq <= 0)
1102 return -1;
1103
1104 if (os_strstr(cmd, " role=configurator"))
1105 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
1106 else if (os_strstr(cmd, " role=enrollee"))
1107 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
1108 else
1109 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
1110 DPP_CAPAB_ENROLLEE;
1111 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001112 if (os_strstr(cmd, " netrole=ap"))
1113 wpa_s->dpp_netrole = DPP_NETROLE_AP;
1114 else if (os_strstr(cmd, " netrole=configurator"))
1115 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
1116 else
1117 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001118 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1119 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1120 freq);
1121 return 0;
1122 }
1123
1124 return wpas_dpp_listen_start(wpa_s, freq);
1125}
1126
1127
1128void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1129{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001130 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001131 if (!wpa_s->dpp_listen_freq)
1132 return;
1133
1134 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1135 wpa_s->dpp_listen_freq);
1136 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001137 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001138 wpa_s->dpp_listen_freq = 0;
1139 wpas_dpp_listen_work_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001140 radio_remove_works(wpa_s, "dpp-listen", 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001141}
1142
1143
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001144void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1145 unsigned int freq, unsigned int duration)
1146{
1147 if (wpa_s->dpp_listen_freq != freq)
1148 return;
1149
1150 wpa_printf(MSG_DEBUG,
1151 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
1152 freq, duration);
1153 os_get_reltime(&wpa_s->dpp_listen_end);
1154 wpa_s->dpp_listen_end.usec += duration * 1000;
1155 while (wpa_s->dpp_listen_end.usec >= 1000000) {
1156 wpa_s->dpp_listen_end.sec++;
1157 wpa_s->dpp_listen_end.usec -= 1000000;
1158 }
1159}
1160
1161
Sunil Ravi99c035e2024-07-12 01:42:03 +00001162static void wpas_dpp_tx_auth_resp(struct wpa_supplicant *wpa_s)
1163{
1164 struct dpp_authentication *auth = wpa_s->dpp_auth;
1165
1166 if (!auth)
1167 return;
1168
1169 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1170 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
1171 DPP_PA_AUTHENTICATION_RESP);
1172 offchannel_send_action(wpa_s, auth->curr_freq,
1173 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
1174 wpabuf_head(auth->resp_msg),
1175 wpabuf_len(auth->resp_msg),
1176 500, wpas_dpp_tx_status, 0);
1177}
1178
1179
1180static void wpas_dpp_tx_auth_resp_roc_timeout(void *eloop_ctx,
1181 void *timeout_ctx)
1182{
1183 struct wpa_supplicant *wpa_s = eloop_ctx;
1184 struct dpp_authentication *auth = wpa_s->dpp_auth;
1185
1186 if (!auth || !wpa_s->dpp_tx_auth_resp_on_roc_stop)
1187 return;
1188
1189 wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
1190 wpa_s->dpp_tx_chan_change = true;
1191 wpa_printf(MSG_DEBUG,
1192 "DPP: Send postponed Authentication Response on remain-on-channel termination timeout");
1193 wpas_dpp_tx_auth_resp(wpa_s);
1194}
1195
1196
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001197void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1198 unsigned int freq)
1199{
Sunil Ravi99c035e2024-07-12 01:42:03 +00001200 wpa_printf(MSG_DEBUG, "DPP: Remain on channel cancel for %u MHz", freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001201 wpas_dpp_listen_work_done(wpa_s);
1202
Sunil Ravi99c035e2024-07-12 01:42:03 +00001203 if (wpa_s->dpp_auth && wpa_s->dpp_tx_auth_resp_on_roc_stop) {
1204 eloop_cancel_timeout(wpas_dpp_tx_auth_resp_roc_timeout,
1205 wpa_s, NULL);
1206 wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
1207 wpa_s->dpp_tx_chan_change = true;
1208 wpa_printf(MSG_DEBUG,
1209 "DPP: Send postponed Authentication Response on remain-on-channel termination");
1210 wpas_dpp_tx_auth_resp(wpa_s);
1211 return;
1212 }
1213
Roshan Pius3a1667e2018-07-03 15:17:14 -07001214 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1215 unsigned int new_freq;
1216
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001217 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001218 if (wpa_s->dpp_auth->neg_freq > 0)
1219 new_freq = wpa_s->dpp_auth->neg_freq;
1220 else
1221 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001222 wpa_printf(MSG_DEBUG,
1223 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001224 new_freq);
1225 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001226 return;
1227 }
1228
1229 if (wpa_s->dpp_listen_freq) {
1230 /* Continue listen with a new remain-on-channel */
1231 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1232 }
1233}
1234
1235
1236static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1237 const u8 *hdr, const u8 *buf, size_t len,
1238 unsigned int freq)
1239{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001240 const u8 *r_bootstrap, *i_bootstrap;
1241 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001242 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1243
1244 if (!wpa_s->dpp)
1245 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001246
1247 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1248 MAC2STR(src));
1249
Hai Shalomfdcde762020-04-02 11:19:20 -07001250#ifdef CONFIG_DPP2
1251 wpas_dpp_chirp_stop(wpa_s);
1252#endif /* CONFIG_DPP2 */
1253
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001254 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1255 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001256 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1257 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1258 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001259 return;
1260 }
1261 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1262 r_bootstrap, r_bootstrap_len);
1263
1264 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1265 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001266 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1267 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1268 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001269 return;
1270 }
1271 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1272 i_bootstrap, i_bootstrap_len);
1273
1274 /* Try to find own and peer bootstrapping key matches based on the
1275 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001276 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1277 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001278 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001279 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1280 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001281 return;
1282 }
1283
Sunil Ravi89eba102022-09-13 21:04:37 -07001284 if (own_bi->type == DPP_BOOTSTRAP_PKEX) {
1285 if (!peer_bi || peer_bi->type != DPP_BOOTSTRAP_PKEX) {
1286 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1287 "No matching peer bootstrapping key found for PKEX - ignore message");
1288 return;
1289 }
1290
1291 if (os_memcmp(peer_bi->pubkey_hash, own_bi->peer_pubkey_hash,
1292 SHA256_MAC_LEN) != 0) {
1293 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1294 "Mismatching peer PKEX bootstrapping key - ignore message");
1295 return;
1296 }
1297 }
1298
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001299 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001300 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1301 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001302 return;
1303 }
1304
Sunil Ravia04bd252022-05-02 22:54:18 -07001305 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001306 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001307 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001308 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001309 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1310 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001311 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001312 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001313 if (!wpa_s->dpp_auth) {
1314 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1315 return;
1316 }
1317 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001318 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001319 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001320 dpp_auth_deinit(wpa_s->dpp_auth);
1321 wpa_s->dpp_auth = NULL;
1322 return;
1323 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001324 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1325
Roshan Pius3a1667e2018-07-03 15:17:14 -07001326 if (wpa_s->dpp_listen_freq &&
1327 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1328 wpa_printf(MSG_DEBUG,
1329 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1330 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
Sunil Ravi99c035e2024-07-12 01:42:03 +00001331 wpa_s->dpp_tx_auth_resp_on_roc_stop = true;
1332 eloop_register_timeout(0, 100000,
1333 wpas_dpp_tx_auth_resp_roc_timeout,
1334 wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001335 wpas_dpp_listen_stop(wpa_s);
Sunil Ravi99c035e2024-07-12 01:42:03 +00001336 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001337 }
Sunil Ravi99c035e2024-07-12 01:42:03 +00001338 wpa_s->dpp_tx_auth_resp_on_roc_stop = false;
1339 wpa_s->dpp_tx_chan_change = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001340
Sunil Ravi99c035e2024-07-12 01:42:03 +00001341 wpas_dpp_tx_auth_resp(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001342}
1343
1344
Hai Shaloma20dcd72022-02-04 13:43:00 -08001345void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
1346{
1347 struct dpp_authentication *auth = wpa_s->dpp_auth;
1348 int freq;
1349
Sunil Ravi99c035e2024-07-12 01:42:03 +00001350 if (wpa_s->dpp_listen_on_tx_expire && auth && auth->neg_freq) {
1351 wpa_printf(MSG_DEBUG,
1352 "DPP: Start listen on neg_freq %u MHz based on TX wait expiration on the previous channel",
1353 auth->neg_freq);
1354 eloop_cancel_timeout(wpas_dpp_neg_freq_timeout, wpa_s, NULL);
1355 wpas_dpp_listen_start(wpa_s, auth->neg_freq);
1356 return;
1357 }
1358
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001359 if (!wpa_s->dpp_gas_server || !auth) {
1360 if (auth && auth->waiting_auth_resp &&
1361 eloop_is_timeout_registered(wpas_dpp_drv_wait_timeout,
1362 wpa_s, NULL)) {
1363 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout,
1364 wpa_s, NULL);
1365 wpa_printf(MSG_DEBUG,
1366 "DPP: Call wpas_dpp_auth_init_next() from %s",
1367 __func__);
1368 wpas_dpp_auth_init_next(wpa_s);
1369 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001370 return;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001371 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001372
1373 freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
1374 if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
1375 return; /* listen state is already in progress */
1376
1377 wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
1378 wpa_s->dpp_in_response_listen = 1;
1379 wpas_dpp_listen_start(wpa_s, freq);
1380}
1381
1382
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001383static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1384{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001385 struct dpp_authentication *auth = wpa_s->dpp_auth;
1386
1387 wpa_printf(MSG_DEBUG,
1388 "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
1389 auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
1390 !!wpa_s->dpp_listen_work);
1391 wpa_s->dpp_gas_server = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001392}
1393
1394
1395static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001396 struct dpp_authentication *auth,
1397 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001398{
1399 struct wpa_ssid *ssid;
1400
Hai Shalom021b0b52019-04-10 11:17:58 -07001401#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001402 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001403#ifdef CONFIG_SAE
1404 struct wpa_driver_capa capa;
1405 int res;
1406
1407 res = wpa_drv_get_capa(wpa_s, &capa);
1408 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001409 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1410 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001411 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1412 wpa_printf(MSG_DEBUG,
1413 "DPP: SAE not supported by the driver");
1414 return NULL;
1415 }
1416#else /* CONFIG_SAE */
1417 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1418 return NULL;
1419#endif /* CONFIG_SAE */
1420 }
1421#endif /* CONFIG_DPP2 */
1422
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001423 ssid = wpa_config_add_network(wpa_s->conf);
1424 if (!ssid)
1425 return NULL;
1426 wpas_notify_network_added(wpa_s, ssid);
1427 wpa_config_set_network_defaults(ssid);
1428 ssid->disabled = 1;
1429
Hai Shalomc3565922019-10-28 11:58:20 -07001430 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001431 if (!ssid->ssid)
1432 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001433 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1434 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001435
Sunil Ravic0f5d412024-09-11 22:12:49 +00001436#ifdef CONFIG_DPP3
1437 if (conf->akm == DPP_AKM_SAE && conf->password_id[0]) {
1438 size_t len = os_strlen(conf->password_id);
1439
1440 ssid->sae_password_id = os_zalloc(len + 1);
1441 if (!ssid->sae_password_id)
1442 goto fail;
1443 os_memcpy(ssid->sae_password_id, conf->password_id, len);
1444 }
1445#endif /* CONFIG_DPP3 */
1446
Hai Shalomc3565922019-10-28 11:58:20 -07001447 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001448 if (dpp_akm_dpp(conf->akm)) {
1449 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1450 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1451 }
Hai Shalomc3565922019-10-28 11:58:20 -07001452 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001453 if (!ssid->dpp_connector)
1454 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07001455
1456 ssid->dpp_connector_privacy =
1457 wpa_s->conf->dpp_connector_privacy_default;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001458 }
1459
Hai Shalomc3565922019-10-28 11:58:20 -07001460 if (conf->c_sign_key) {
1461 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001462 if (!ssid->dpp_csign)
1463 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001464 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1465 wpabuf_len(conf->c_sign_key));
1466 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001467 }
1468
Hai Shalom899fcc72020-10-19 14:38:18 -07001469 if (conf->pp_key) {
1470 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1471 if (!ssid->dpp_pp_key)
1472 goto fail;
1473 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1474 wpabuf_len(conf->pp_key));
1475 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1476 }
1477
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001478 if (auth->net_access_key) {
1479 ssid->dpp_netaccesskey =
1480 os_malloc(wpabuf_len(auth->net_access_key));
1481 if (!ssid->dpp_netaccesskey)
1482 goto fail;
1483 os_memcpy(ssid->dpp_netaccesskey,
1484 wpabuf_head(auth->net_access_key),
1485 wpabuf_len(auth->net_access_key));
1486 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1487 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1488 }
1489
Hai Shalomc3565922019-10-28 11:58:20 -07001490 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1491 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001492 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001493 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001494 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001495 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1496 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001497 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001498 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1499 WPA_KEY_MGMT_FT_SAE;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001500 if (dpp_akm_psk(conf->akm))
1501 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1502 else
1503 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Sunil Ravic0f5d412024-09-11 22:12:49 +00001504 if (conf->passphrase[0] && dpp_akm_psk(conf->akm)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001505 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001506 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001507 goto fail;
1508 wpa_config_update_psk(ssid);
1509 ssid->export_keys = 1;
Sunil Ravic0f5d412024-09-11 22:12:49 +00001510 } else if (conf->passphrase[0] && dpp_akm_sae(conf->akm)) {
1511 if (wpa_config_set_quoted(ssid, "sae_password",
1512 conf->passphrase) < 0)
1513 goto fail;
1514 ssid->export_keys = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001515 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001516 ssid->psk_set = conf->psk_set;
1517 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001518 }
1519 }
1520
Hai Shalom899fcc72020-10-19 14:38:18 -07001521#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1522 if (conf->akm == DPP_AKM_DOT1X) {
1523 int i;
1524 char name[100], blobname[128];
1525 struct wpa_config_blob *blob;
1526
1527 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1528 WPA_KEY_MGMT_IEEE8021X_SHA256 |
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001529 WPA_KEY_MGMT_IEEE8021X_SHA384;
Hai Shalom899fcc72020-10-19 14:38:18 -07001530 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1531
1532 if (conf->cacert) {
1533 /* caCert is DER-encoded X.509v3 certificate for the
1534 * server certificate if that is different from the
1535 * trust root included in certBag. */
1536 /* TODO: ssid->eap.cert.ca_cert */
1537 }
1538
1539 if (conf->certs) {
1540 for (i = 0; ; i++) {
1541 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1542 i);
1543 if (!wpa_config_get_blob(wpa_s->conf, name))
1544 break;
1545 }
1546
1547 blob = os_zalloc(sizeof(*blob));
1548 if (!blob)
1549 goto fail;
1550 blob->len = wpabuf_len(conf->certs);
1551 blob->name = os_strdup(name);
1552 blob->data = os_malloc(blob->len);
1553 if (!blob->name || !blob->data) {
1554 wpa_config_free_blob(blob);
1555 goto fail;
1556 }
1557 os_memcpy(blob->data, wpabuf_head(conf->certs),
1558 blob->len);
1559 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1560 name);
1561 wpa_config_set_blob(wpa_s->conf, blob);
1562 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1563 name);
1564 ssid->eap.cert.client_cert = os_strdup(blobname);
1565 if (!ssid->eap.cert.client_cert)
1566 goto fail;
1567
1568 /* TODO: ssid->eap.identity from own certificate */
1569 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1570 0) < 0)
1571 goto fail;
1572 }
1573
1574 if (auth->priv_key) {
1575 for (i = 0; ; i++) {
1576 os_snprintf(name, sizeof(name), "dpp-key-%d",
1577 i);
1578 if (!wpa_config_get_blob(wpa_s->conf, name))
1579 break;
1580 }
1581
1582 blob = os_zalloc(sizeof(*blob));
1583 if (!blob)
1584 goto fail;
1585 blob->len = wpabuf_len(auth->priv_key);
1586 blob->name = os_strdup(name);
1587 blob->data = os_malloc(blob->len);
1588 if (!blob->name || !blob->data) {
1589 wpa_config_free_blob(blob);
1590 goto fail;
1591 }
1592 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1593 blob->len);
1594 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1595 name);
1596 wpa_config_set_blob(wpa_s->conf, blob);
1597 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1598 name);
1599 ssid->eap.cert.private_key = os_strdup(blobname);
1600 if (!ssid->eap.cert.private_key)
1601 goto fail;
1602 }
1603
1604 if (conf->server_name) {
1605 ssid->eap.cert.domain_suffix_match =
1606 os_strdup(conf->server_name);
1607 if (!ssid->eap.cert.domain_suffix_match)
1608 goto fail;
1609 }
1610
1611 /* TODO: Use entCreds::eapMethods */
1612 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1613 goto fail;
1614 }
1615#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1616
Hai Shalomc3565922019-10-28 11:58:20 -07001617 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1618 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1619
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001620 return ssid;
1621fail:
1622 wpas_notify_network_removed(wpa_s, ssid);
1623 wpa_config_remove_network(wpa_s->conf, ssid->id);
1624 return NULL;
1625}
1626
1627
Hai Shalom021b0b52019-04-10 11:17:58 -07001628static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001629 struct dpp_authentication *auth,
1630 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001631{
1632 struct wpa_ssid *ssid;
1633
1634 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001635 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001636
Hai Shalomc3565922019-10-28 11:58:20 -07001637 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001638 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001639 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001640
1641 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001642
Sunil Ravi546a7b52022-08-26 22:06:04 +00001643 wpas_notify_dpp_config_received(wpa_s, ssid, auth->conn_status_requested ? 1 : 0);
Hai Shalom59532852018-12-07 10:32:58 -08001644
Hai Shalom021b0b52019-04-10 11:17:58 -07001645 if (wpa_s->conf->dpp_config_processing == 2)
1646 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001647
Hai Shalom021b0b52019-04-10 11:17:58 -07001648#ifndef CONFIG_NO_CONFIG_WRITE
1649 if (wpa_s->conf->update_config &&
1650 wpa_config_write(wpa_s->confname, wpa_s->conf))
1651 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1652#endif /* CONFIG_NO_CONFIG_WRITE */
1653
Hai Shalomc3565922019-10-28 11:58:20 -07001654 return 0;
1655}
1656
1657
1658static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1659 struct dpp_authentication *auth)
1660{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001661#ifdef CONFIG_DPP2
1662 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1663 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1664 wpa_s->dpp_reconfig_ssid) {
1665 wpa_printf(MSG_DEBUG,
1666 "DPP: Remove reconfigured network profile");
1667 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1668 wpa_config_remove_network(wpa_s->conf,
1669 wpa_s->dpp_reconfig_ssid_id);
1670 wpa_s->dpp_reconfig_ssid = NULL;
1671 wpa_s->dpp_reconfig_ssid_id = -1;
1672 }
1673#endif /* CONFIG_DPP2 */
1674
Hai Shalom021b0b52019-04-10 11:17:58 -07001675 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001676 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001677
1678#ifdef CONFIG_DPP2
1679 if (auth->peer_version >= 2) {
1680 wpa_printf(MSG_DEBUG,
1681 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1682 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001683 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001684 }
1685#endif /* CONFIG_DPP2 */
1686
1687 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001688}
1689
1690
Hai Shalom021b0b52019-04-10 11:17:58 -07001691static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001692 struct dpp_authentication *auth,
1693 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001694{
1695 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001696 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1697 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001698 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001699 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001700 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001701 if (conf->ssid_charset)
1702 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1703 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001704 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001705 /* TODO: Save the Connector and consider using a command
1706 * to fetch the value instead of sending an event with
1707 * it. The Connector could end up being larger than what
1708 * most clients are ready to receive as an event
1709 * message. */
1710 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001711 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001712 }
Hai Shalom60840252021-02-19 19:02:11 -08001713 if (conf->passphrase[0]) {
1714 char hex[64 * 2 + 1];
1715
1716 wpa_snprintf_hex(hex, sizeof(hex),
1717 (const u8 *) conf->passphrase,
1718 os_strlen(conf->passphrase));
1719 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1720 hex);
1721 } else if (conf->psk_set) {
1722 char hex[PMK_LEN * 2 + 1];
1723
1724 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1725 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1726 hex);
1727 }
Sunil Ravic0f5d412024-09-11 22:12:49 +00001728#ifdef CONFIG_DPP3
1729 if (conf->password_id[0]) {
1730 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_IDPASS "%s",
1731 conf->password_id);
1732 }
1733#endif /* CONFIG_DPP3 */
Hai Shalomc3565922019-10-28 11:58:20 -07001734 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001735 char *hex;
1736 size_t hexlen;
1737
Hai Shalomc3565922019-10-28 11:58:20 -07001738 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001739 hex = os_malloc(hexlen);
1740 if (hex) {
1741 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001742 wpabuf_head(conf->c_sign_key),
1743 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001744 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1745 hex);
1746 os_free(hex);
1747 }
1748 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001749 if (conf->pp_key) {
1750 char *hex;
1751 size_t hexlen;
1752
1753 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1754 hex = os_malloc(hexlen);
1755 if (hex) {
1756 wpa_snprintf_hex(hex, hexlen,
1757 wpabuf_head(conf->pp_key),
1758 wpabuf_len(conf->pp_key));
1759 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1760 os_free(hex);
1761 }
1762 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001763 if (auth->net_access_key) {
1764 char *hex;
1765 size_t hexlen;
1766
1767 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1768 hex = os_malloc(hexlen);
1769 if (hex) {
1770 wpa_snprintf_hex(hex, hexlen,
1771 wpabuf_head(auth->net_access_key),
1772 wpabuf_len(auth->net_access_key));
1773 if (auth->net_access_key_expiry)
1774 wpa_msg(wpa_s, MSG_INFO,
1775 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1776 (long unsigned)
1777 auth->net_access_key_expiry);
1778 else
1779 wpa_msg(wpa_s, MSG_INFO,
1780 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1781 os_free(hex);
1782 }
1783 }
1784
Hai Shalom899fcc72020-10-19 14:38:18 -07001785#ifdef CONFIG_DPP2
1786 if (conf->certbag) {
1787 char *b64;
1788
1789 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1790 wpabuf_len(conf->certbag), NULL);
1791 if (b64)
1792 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1793 os_free(b64);
1794 }
1795
1796 if (conf->cacert) {
1797 char *b64;
1798
1799 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1800 wpabuf_len(conf->cacert), NULL);
1801 if (b64)
1802 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1803 os_free(b64);
1804 }
1805
1806 if (conf->server_name)
1807 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1808 conf->server_name);
1809#endif /* CONFIG_DPP2 */
1810
Sunil Ravi89eba102022-09-13 21:04:37 -07001811#ifdef CONFIG_DPP3
1812 if (!wpa_s->dpp_pb_result_indicated) {
1813 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "success");
1814 wpa_s->dpp_pb_result_indicated = true;
1815 }
1816
1817#endif /* CONFIG_DPP3 */
1818
Hai Shalomc3565922019-10-28 11:58:20 -07001819 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001820}
1821
1822
Hai Shalomfdcde762020-04-02 11:19:20 -07001823static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1824 struct dpp_asymmetric_key *key)
1825{
1826#ifdef CONFIG_DPP2
1827 int res;
1828
1829 if (!key)
1830 return 0;
1831
1832 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1833 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001834 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001835
1836 while (key) {
1837 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1838 if (res < 0)
1839 return -1;
1840 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1841 res);
1842 key = key->next;
1843 }
1844#endif /* CONFIG_DPP2 */
1845
1846 return 0;
1847}
1848
1849
Hai Shalom899fcc72020-10-19 14:38:18 -07001850#ifdef CONFIG_DPP2
1851static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1852{
1853 struct wpa_supplicant *wpa_s = eloop_ctx;
1854 struct dpp_authentication *auth = wpa_s->dpp_auth;
1855
1856 if (!auth || !auth->csrattrs)
1857 return;
1858
1859 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1860 wpabuf_free(auth->csr);
1861 /* TODO: Additional information needed for CSR based on csrAttrs */
1862 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1863 wpa_s->conf->dpp_name : "Test");
1864 if (!auth->csr) {
1865 dpp_auth_deinit(wpa_s->dpp_auth);
1866 wpa_s->dpp_auth = NULL;
1867 return;
1868 }
1869
1870 wpas_dpp_start_gas_client(wpa_s);
1871}
1872#endif /* CONFIG_DPP2 */
1873
1874
Sunil Ravia04bd252022-05-02 22:54:18 -07001875#ifdef CONFIG_DPP3
1876static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1877{
1878 struct wpa_supplicant *wpa_s = eloop_ctx;
1879 struct dpp_authentication *auth = wpa_s->dpp_auth;
1880
1881 if (!auth || !auth->waiting_new_key)
1882 return;
1883
1884 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1885 wpas_dpp_start_gas_client(wpa_s);
1886}
1887#endif /* CONFIG_DPP3 */
1888
1889
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001890static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1891 enum gas_query_result result,
1892 const struct wpabuf *adv_proto,
1893 const struct wpabuf *resp, u16 status_code)
1894{
1895 struct wpa_supplicant *wpa_s = ctx;
1896 const u8 *pos;
1897 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001898 int res;
1899 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001900 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001901
Hai Shaloma20dcd72022-02-04 13:43:00 -08001902 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001903 wpa_s->dpp_gas_dialog_token = -1;
1904
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001905 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001906 !ether_addr_equal(addr, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001907 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1908 return;
1909 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001910 if (result != GAS_QUERY_SUCCESS ||
1911 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001912 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1913 goto fail;
1914 }
1915
1916 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1917 adv_proto);
1918 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1919 resp);
1920
1921 if (wpabuf_len(adv_proto) != 10 ||
1922 !(pos = wpabuf_head(adv_proto)) ||
1923 pos[0] != WLAN_EID_ADV_PROTO ||
1924 pos[1] != 8 ||
1925 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1926 pos[4] != 5 ||
1927 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1928 pos[8] != 0x1a ||
1929 pos[9] != 1) {
1930 wpa_printf(MSG_DEBUG,
1931 "DPP: Not a DPP Advertisement Protocol ID");
1932 goto fail;
1933 }
1934
Hai Shalom899fcc72020-10-19 14:38:18 -07001935 res = dpp_conf_resp_rx(auth, resp);
1936#ifdef CONFIG_DPP2
1937 if (res == -2) {
1938 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1939 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1940 return;
1941 }
1942#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001943#ifdef CONFIG_DPP3
1944 if (res == -3) {
1945 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1946 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1947 NULL);
1948 return;
1949 }
1950#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001951 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001952 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1953 goto fail;
1954 }
1955
Hai Shalom899fcc72020-10-19 14:38:18 -07001956 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001957 for (i = 0; i < auth->num_conf_obj; i++) {
1958 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1959 &auth->conf_obj[i]);
1960 if (res < 0)
1961 goto fail;
1962 }
1963 if (auth->num_conf_obj)
1964 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001965 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1966 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001967
Hai Shalom021b0b52019-04-10 11:17:58 -07001968 status = DPP_STATUS_OK;
1969#ifdef CONFIG_TESTING_OPTIONS
1970 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1971 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1972 status = DPP_STATUS_CONFIG_REJECTED;
1973 }
1974#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001975fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001976 if (status != DPP_STATUS_OK) {
1977 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1978 wpas_notify_dpp_configuration_failure(wpa_s);
1979 }
1980#ifdef CONFIG_DPP2
1981 if (auth->peer_version >= 2 &&
1982 auth->conf_resp_status == DPP_STATUS_OK) {
1983 struct wpabuf *msg;
1984
1985 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1986 msg = dpp_build_conf_result(auth, status);
1987 if (!msg)
1988 goto fail2;
1989
1990 wpa_msg(wpa_s, MSG_INFO,
1991 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1992 MAC2STR(addr), auth->curr_freq,
1993 DPP_PA_CONFIGURATION_RESULT);
1994 offchannel_send_action(wpa_s, auth->curr_freq,
1995 addr, wpa_s->own_addr, broadcast,
1996 wpabuf_head(msg),
1997 wpabuf_len(msg),
1998 500, wpas_dpp_tx_status, 0);
1999 wpabuf_free(msg);
2000
2001 /* This exchange will be terminated in the TX status handler */
Sunil Ravi546a7b52022-08-26 22:06:04 +00002002 if (wpa_s->conf->dpp_config_processing < 1 ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002003 wpa_s->dpp_conf_backup_received)
2004 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07002005 return;
2006 }
2007fail2:
2008#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002009 dpp_auth_deinit(wpa_s->dpp_auth);
2010 wpa_s->dpp_auth = NULL;
2011}
2012
2013
Hai Shaloma20dcd72022-02-04 13:43:00 -08002014static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
2015{
2016 struct wpa_supplicant *wpa_s = eloop_ctx;
2017 struct dpp_authentication *auth = wpa_s->dpp_auth;
2018
2019 if (!wpa_s->dpp_gas_client || !auth ||
2020 (!auth->auth_success && !auth->reconfig_success))
2021 return;
2022
2023 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
2024 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
2025 dpp_auth_deinit(wpa_s->dpp_auth);
2026 wpa_s->dpp_auth = NULL;
2027}
2028
2029
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002030static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
2031{
2032 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07002033 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002034 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07002035 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002036
2037 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002038 offchannel_send_action_done(wpa_s);
2039 wpas_dpp_listen_stop(wpa_s);
2040
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002041#ifdef CONFIG_NO_RRM
2042 supp_op_classes = NULL;
2043#else /* CONFIG_NO_RRM */
Hai Shalomc3565922019-10-28 11:58:20 -07002044 supp_op_classes = wpas_supp_op_classes(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002045#endif /* CONFIG_NO_RRM */
Hai Shalomc3565922019-10-28 11:58:20 -07002046 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002047 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07002048 wpa_s->conf->dpp_mud_url,
Sunil Ravi89eba102022-09-13 21:04:37 -07002049 supp_op_classes,
2050 wpa_s->conf->dpp_extra_conf_req_name,
2051 wpa_s->conf->dpp_extra_conf_req_value);
Hai Shalomc3565922019-10-28 11:58:20 -07002052 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07002053 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002054 wpa_printf(MSG_DEBUG,
2055 "DPP: No configuration request data available");
2056 return;
2057 }
2058
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002059 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
2060 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
2061
Hai Shaloma20dcd72022-02-04 13:43:00 -08002062 /* Use a 120 second timeout since the gas_query_req() operation could
2063 * remain waiting indefinitely for the response if the Configurator
2064 * keeps sending out comeback responses with additional delay. The
2065 * DPP technical specification expects the Enrollee to continue sending
2066 * out new Config Requests for 60 seconds, so this gives an extra 60
2067 * second time after the last expected new Config Request for the
2068 * Configurator to determine what kind of configuration to provide. */
2069 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
2070 wpa_s, NULL);
2071
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002072 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07002073 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002074 if (res < 0) {
2075 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
2076 wpabuf_free(buf);
2077 } else {
2078 wpa_printf(MSG_DEBUG,
2079 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002080 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002081 }
2082}
2083
2084
2085static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
2086{
2087 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002088 dpp_notify_auth_success(wpa_s->dpp_auth, initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08002089 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002090#ifdef CONFIG_TESTING_OPTIONS
2091 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
2092 wpa_printf(MSG_INFO,
2093 "DPP: TESTING - stop at Authentication Confirm");
2094 if (wpa_s->dpp_auth->configurator) {
2095 /* Prevent GAS response */
2096 wpa_s->dpp_auth->auth_success = 0;
2097 }
2098 return;
2099 }
2100#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002101
2102 if (wpa_s->dpp_auth->configurator)
2103 wpas_dpp_start_gas_server(wpa_s);
2104 else
2105 wpas_dpp_start_gas_client(wpa_s);
2106}
2107
2108
2109static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002110 const u8 *hdr, const u8 *buf, size_t len,
2111 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002112{
2113 struct dpp_authentication *auth = wpa_s->dpp_auth;
2114 struct wpabuf *msg;
2115
Roshan Pius3a1667e2018-07-03 15:17:14 -07002116 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
2117 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002118
2119 if (!auth) {
2120 wpa_printf(MSG_DEBUG,
2121 "DPP: No DPP Authentication in progress - drop");
2122 return;
2123 }
2124
2125 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002126 !ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002127 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2128 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2129 return;
2130 }
2131
2132 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
2133
Roshan Pius3a1667e2018-07-03 15:17:14 -07002134 if (auth->curr_freq != freq && auth->neg_freq == freq) {
2135 wpa_printf(MSG_DEBUG,
2136 "DPP: Responder accepted request for different negotiation channel");
2137 auth->curr_freq = freq;
2138 }
2139
2140 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002141 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
2142 if (!msg) {
2143 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
2144 wpa_printf(MSG_DEBUG,
2145 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08002146 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002147 offchannel_send_action_done(wpa_s);
2148 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
2149 return;
2150 }
2151 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
2152 return;
2153 }
2154 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2155
Roshan Pius3a1667e2018-07-03 15:17:14 -07002156 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2157 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002158 offchannel_send_action(wpa_s, auth->curr_freq,
2159 src, wpa_s->own_addr, broadcast,
2160 wpabuf_head(msg), wpabuf_len(msg),
2161 500, wpas_dpp_tx_status, 0);
2162 wpabuf_free(msg);
2163 wpa_s->dpp_auth_ok_on_ack = 1;
2164}
2165
2166
2167static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2168 const u8 *hdr, const u8 *buf, size_t len)
2169{
2170 struct dpp_authentication *auth = wpa_s->dpp_auth;
2171
2172 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
2173 MAC2STR(src));
2174
2175 if (!auth) {
2176 wpa_printf(MSG_DEBUG,
2177 "DPP: No DPP Authentication in progress - drop");
2178 return;
2179 }
2180
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002181 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002182 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2183 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2184 return;
2185 }
2186
Hai Shalom60840252021-02-19 19:02:11 -08002187 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
2188
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002189 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
2190 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08002191 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002192 return;
2193 }
2194
2195 wpas_dpp_auth_success(wpa_s, 0);
2196}
2197
2198
Hai Shalom021b0b52019-04-10 11:17:58 -07002199#ifdef CONFIG_DPP2
2200
2201static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
2202 void *timeout_ctx)
2203{
2204 struct wpa_supplicant *wpa_s = eloop_ctx;
2205 struct dpp_authentication *auth = wpa_s->dpp_auth;
2206
2207 if (!auth || !auth->waiting_conf_result)
2208 return;
2209
2210 wpa_printf(MSG_DEBUG,
2211 "DPP: Timeout while waiting for Configuration Result");
2212 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002213 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002214 dpp_auth_deinit(auth);
2215 wpa_s->dpp_auth = NULL;
2216}
2217
2218
Hai Shalomc3565922019-10-28 11:58:20 -07002219static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2220 void *timeout_ctx)
2221{
2222 struct wpa_supplicant *wpa_s = eloop_ctx;
2223 struct dpp_authentication *auth = wpa_s->dpp_auth;
2224
2225 if (!auth || !auth->waiting_conn_status_result)
2226 return;
2227
2228 wpa_printf(MSG_DEBUG,
2229 "DPP: Timeout while waiting for Connection Status Result");
2230 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002231 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002232 wpas_dpp_listen_stop(wpa_s);
2233 dpp_auth_deinit(auth);
2234 wpa_s->dpp_auth = NULL;
2235}
2236
2237
Sunil Ravi89eba102022-09-13 21:04:37 -07002238#ifdef CONFIG_DPP3
2239
2240static bool wpas_dpp_pb_active(struct wpa_supplicant *wpa_s)
2241{
2242 return (wpa_s->dpp_pb_time.sec || wpa_s->dpp_pb_time.usec) &&
2243 wpa_s->dpp_pb_configurator;
2244}
2245
2246
2247static void wpas_dpp_remove_pb_hash(struct wpa_supplicant *wpa_s)
2248{
2249 int i;
2250
2251 if (!wpa_s->dpp_pb_bi)
2252 return;
2253 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2254 struct dpp_pb_info *info = &wpa_s->dpp_pb[i];
2255
2256 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
2257 continue;
2258 if (os_memcmp(info->hash, wpa_s->dpp_pb_resp_hash,
2259 SHA256_MAC_LEN) == 0) {
2260 /* Allow a new push button session to be established
2261 * immediately without the successfully completed
2262 * session triggering session overlap. */
2263 info->rx_time.sec = 0;
2264 info->rx_time.usec = 0;
2265 wpa_printf(MSG_DEBUG,
2266 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
2267 }
2268 }
2269}
2270
2271#endif /* CONFIG_DPP3 */
2272
2273
Hai Shalom021b0b52019-04-10 11:17:58 -07002274static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2275 const u8 *hdr, const u8 *buf, size_t len)
2276{
2277 struct dpp_authentication *auth = wpa_s->dpp_auth;
2278 enum dpp_status_error status;
2279
2280 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2281 MAC2STR(src));
2282
2283 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002284 if (auth &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002285 ether_addr_equal(src, auth->peer_mac_addr) &&
Hai Shalom60840252021-02-19 19:02:11 -08002286 gas_server_response_sent(wpa_s->gas_server,
2287 auth->gas_server_ctx)) {
2288 /* This could happen if the TX status event gets delayed
2289 * long enough for the Enrollee to have time to send
2290 * the next frame before the TX status gets processed
2291 * locally. */
2292 wpa_printf(MSG_DEBUG,
2293 "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");
2294 auth->waiting_conf_result = 1;
2295 } else {
2296 wpa_printf(MSG_DEBUG,
2297 "DPP: No DPP Configuration waiting for result - drop");
2298 return;
2299 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002300 }
2301
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002302 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002303 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2304 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2305 return;
2306 }
2307
2308 status = dpp_conf_result_rx(auth, hdr, buf, len);
2309
Hai Shalomc3565922019-10-28 11:58:20 -07002310 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002311 int freq;
2312
Hai Shalomc3565922019-10-28 11:58:20 -07002313 wpa_msg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07002314 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
2315 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07002316 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002317 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002318 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2319 wpa_s, NULL);
2320 auth->waiting_conn_status_result = 1;
2321 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2322 wpa_s, NULL);
2323 eloop_register_timeout(16, 0,
2324 wpas_dpp_conn_status_result_wait_timeout,
2325 wpa_s, NULL);
2326 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002327 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2328 if (!wpa_s->dpp_in_response_listen ||
2329 (int) wpa_s->dpp_listen_freq != freq)
2330 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002331 return;
2332 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002333 offchannel_send_action_done(wpa_s);
2334 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002335 if (status == DPP_STATUS_OK) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002336 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
2337 auth->conf_resp_status);
Hai Shalome4073332019-11-05 16:20:12 -08002338 wpas_notify_dpp_config_sent(wpa_s);
2339 }
2340 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002341 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002342 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002343 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002344 dpp_auth_deinit(auth);
2345 wpa_s->dpp_auth = NULL;
2346 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07002347#ifdef CONFIG_DPP3
2348 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
2349 if (status == DPP_STATUS_OK)
2350 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2351 "success");
2352 else
2353 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2354 "no-configuration-available");
2355 wpa_s->dpp_pb_result_indicated = true;
2356 if (status == DPP_STATUS_OK)
2357 wpas_dpp_remove_pb_hash(wpa_s);
2358 wpas_dpp_push_button_stop(wpa_s);
2359 }
2360#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002361}
2362
Hai Shalom81f62d82019-07-22 12:10:00 -07002363
Hai Shalomc3565922019-10-28 11:58:20 -07002364static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2365 const u8 *src, const u8 *hdr,
2366 const u8 *buf, size_t len)
2367{
2368 struct dpp_authentication *auth = wpa_s->dpp_auth;
2369 enum dpp_status_error status;
2370 u8 ssid[SSID_MAX_LEN];
2371 size_t ssid_len = 0;
2372 char *channel_list = NULL;
2373
2374 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2375
2376 if (!auth || !auth->waiting_conn_status_result) {
2377 wpa_printf(MSG_DEBUG,
2378 "DPP: No DPP Configuration waiting for connection status result - drop");
2379 return;
2380 }
2381
2382 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2383 ssid, &ssid_len, &channel_list);
2384 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2385 "result=%d ssid=%s channel_list=%s",
2386 status, wpa_ssid_txt(ssid, ssid_len),
2387 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002388 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2389 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002390 os_free(channel_list);
2391 offchannel_send_action_done(wpa_s);
2392 wpas_dpp_listen_stop(wpa_s);
2393 dpp_auth_deinit(auth);
2394 wpa_s->dpp_auth = NULL;
2395 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2396 wpa_s, NULL);
2397}
2398
2399
Hai Shalom81f62d82019-07-22 12:10:00 -07002400static int wpas_dpp_process_conf_obj(void *ctx,
2401 struct dpp_authentication *auth)
2402{
2403 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002404 unsigned int i;
2405 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002406
Hai Shalomc3565922019-10-28 11:58:20 -07002407 for (i = 0; i < auth->num_conf_obj; i++) {
2408 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2409 &auth->conf_obj[i]);
2410 if (res)
2411 break;
2412 }
2413 if (!res)
2414 wpas_dpp_post_process_config(wpa_s, auth);
2415
2416 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002417}
2418
Hai Shalomfdcde762020-04-02 11:19:20 -07002419
Hai Shaloma20dcd72022-02-04 13:43:00 -08002420static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2421{
2422 struct wpa_supplicant *wpa_s = ctx;
2423
2424 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2425
2426 if (auth->connect_on_tx_status) {
2427 auth->connect_on_tx_status = 0;
2428 wpa_printf(MSG_DEBUG,
2429 "DPP: Try to connect after completed configuration result");
2430 wpas_dpp_try_to_connect(wpa_s);
2431 if (auth->conn_status_requested) {
2432 wpa_printf(MSG_DEBUG,
2433 "DPP: Start 15 second timeout for reporting connection status result");
2434 eloop_cancel_timeout(
2435 wpas_dpp_conn_status_result_timeout,
2436 wpa_s, NULL);
2437 eloop_register_timeout(
2438 15, 0, wpas_dpp_conn_status_result_timeout,
2439 wpa_s, NULL);
2440 return true;
2441 }
2442 }
2443
2444 return false;
2445}
2446
2447
Hai Shalomfdcde762020-04-02 11:19:20 -07002448static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2449{
2450 struct wpa_supplicant *wpa_s = ctx;
2451
2452 if (bi == wpa_s->dpp_chirp_bi)
2453 wpas_dpp_chirp_stop(wpa_s);
2454}
2455
2456
2457static void
2458wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2459 const u8 *hdr, const u8 *buf, size_t len,
2460 unsigned int freq)
2461{
2462 const u8 *r_bootstrap;
2463 u16 r_bootstrap_len;
2464 struct dpp_bootstrap_info *peer_bi;
2465 struct dpp_authentication *auth;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002466 unsigned int wait_time, max_wait_time;
Hai Shalomfdcde762020-04-02 11:19:20 -07002467
2468 if (!wpa_s->dpp)
2469 return;
2470
2471 if (wpa_s->dpp_auth) {
2472 wpa_printf(MSG_DEBUG,
2473 "DPP: Ignore Presence Announcement during ongoing Authentication");
2474 return;
2475 }
2476
2477 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2478 MAC2STR(src));
2479
2480 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2481 &r_bootstrap_len);
2482 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2483 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2484 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2485 return;
2486 }
2487 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2488 r_bootstrap, r_bootstrap_len);
2489 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002490 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2491 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002492 if (!peer_bi) {
2493 wpa_printf(MSG_DEBUG,
2494 "DPP: No matching bootstrapping information found");
2495 return;
2496 }
2497
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002498 wpa_printf(MSG_DEBUG, "DPP: Start Authentication exchange with " MACSTR
2499 " based on the received Presence Announcement",
2500 MAC2STR(src));
Hai Shalomfdcde762020-04-02 11:19:20 -07002501 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2502 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2503 if (!auth)
2504 return;
2505 wpas_dpp_set_testing_options(wpa_s, auth);
2506 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2507 dpp_auth_deinit(auth);
2508 return;
2509 }
2510
2511 auth->neg_freq = freq;
2512
Hai Shalom60840252021-02-19 19:02:11 -08002513 /* The source address of the Presence Announcement frame overrides any
2514 * MAC address information from the bootstrapping information. */
2515 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002516
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002517 wait_time = wpa_s->max_remain_on_chan;
2518 max_wait_time = wpa_s->dpp_resp_wait_time ?
2519 wpa_s->dpp_resp_wait_time : 2000;
2520 if (wait_time > max_wait_time)
2521 wait_time = max_wait_time;
2522 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2523
Hai Shalomfdcde762020-04-02 11:19:20 -07002524 wpa_s->dpp_auth = auth;
2525 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2526 dpp_auth_deinit(wpa_s->dpp_auth);
2527 wpa_s->dpp_auth = NULL;
2528 }
2529}
2530
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002531
2532static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2533 void *timeout_ctx)
2534{
2535 struct wpa_supplicant *wpa_s = eloop_ctx;
2536 struct dpp_authentication *auth = wpa_s->dpp_auth;
2537
2538 if (!auth)
2539 return;
2540
2541 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2542 offchannel_send_action_done(wpa_s);
2543 wpas_dpp_listen_stop(wpa_s);
2544 dpp_auth_deinit(auth);
2545 wpa_s->dpp_auth = NULL;
2546}
2547
2548
2549static void
2550wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2551 const u8 *hdr, const u8 *buf, size_t len,
2552 unsigned int freq)
2553{
Hai Shalom899fcc72020-10-19 14:38:18 -07002554 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2555 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002556 struct dpp_configurator *conf;
2557 struct dpp_authentication *auth;
2558 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002559 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002560
2561 if (!wpa_s->dpp)
2562 return;
2563
2564 if (wpa_s->dpp_auth) {
2565 wpa_printf(MSG_DEBUG,
2566 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2567 return;
2568 }
2569
2570 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2571 MAC2STR(src));
2572
2573 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2574 &csign_hash_len);
2575 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2576 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2577 "Missing or invalid required Configurator C-sign key Hash attribute");
2578 return;
2579 }
2580 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2581 csign_hash, csign_hash_len);
2582 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2583 if (!conf) {
2584 wpa_printf(MSG_DEBUG,
2585 "DPP: No matching Configurator information found");
2586 return;
2587 }
2588
Hai Shalom899fcc72020-10-19 14:38:18 -07002589 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2590 &fcgroup_len);
2591 if (!fcgroup || fcgroup_len != 2) {
2592 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2593 "Missing or invalid required Finite Cyclic Group attribute");
2594 return;
2595 }
2596 group = WPA_GET_LE16(fcgroup);
2597 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2598
2599 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2600 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2601
2602 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2603 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002604 if (!auth)
2605 return;
2606 wpas_dpp_set_testing_options(wpa_s, auth);
2607 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2608 dpp_auth_deinit(auth);
2609 return;
2610 }
2611
2612 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2613 wpa_s->dpp_auth = auth;
2614
2615 wpa_s->dpp_in_response_listen = 0;
2616 wpa_s->dpp_auth_ok_on_ack = 0;
2617 wait_time = wpa_s->max_remain_on_chan;
2618 max_wait_time = wpa_s->dpp_resp_wait_time ?
2619 wpa_s->dpp_resp_wait_time : 2000;
2620 if (wait_time > max_wait_time)
2621 wait_time = max_wait_time;
2622 wait_time += 10; /* give the driver some extra time to complete */
2623 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2624 wpas_dpp_reconfig_reply_wait_timeout,
2625 wpa_s, NULL);
2626 wait_time -= 10;
2627
2628 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2629
2630 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2631 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2632 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2633 wpabuf_head(auth->reconfig_req_msg),
2634 wpabuf_len(auth->reconfig_req_msg),
2635 wait_time, wpas_dpp_tx_status, 0) < 0) {
2636 dpp_auth_deinit(wpa_s->dpp_auth);
2637 wpa_s->dpp_auth = NULL;
2638 }
2639}
2640
2641
2642static void
2643wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2644 const u8 *hdr, const u8 *buf, size_t len,
2645 unsigned int freq)
2646{
2647 struct wpa_ssid *ssid;
2648 struct dpp_authentication *auth;
2649
2650 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2651 MACSTR, MAC2STR(src));
2652
Hai Shalom899fcc72020-10-19 14:38:18 -07002653 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002654 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002655 if (wpa_s->dpp_auth) {
2656 wpa_printf(MSG_DEBUG,
2657 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2658 return;
2659 }
2660 if (!wpa_s->dpp_reconfig_ssid) {
2661 wpa_printf(MSG_DEBUG,
2662 "DPP: Not ready for reconfiguration - not requested");
2663 return;
2664 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002665 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2666 if (ssid == wpa_s->dpp_reconfig_ssid &&
2667 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2668 break;
2669 }
2670 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002671 !ssid->dpp_csign) {
2672 wpa_printf(MSG_DEBUG,
2673 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002674 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002675 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002676
2677 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2678 ssid->dpp_netaccesskey,
2679 ssid->dpp_netaccesskey_len,
2680 ssid->dpp_csign, ssid->dpp_csign_len,
2681 freq, hdr, buf, len);
2682 if (!auth)
2683 return;
2684 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2685 wpa_s->dpp_auth = auth;
2686
2687 wpas_dpp_chirp_stop(wpa_s);
2688
2689 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2690 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2691 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2692 wpabuf_head(auth->reconfig_resp_msg),
2693 wpabuf_len(auth->reconfig_resp_msg),
2694 500, wpas_dpp_tx_status, 0) < 0) {
2695 dpp_auth_deinit(wpa_s->dpp_auth);
2696 wpa_s->dpp_auth = NULL;
2697 }
2698}
2699
2700
2701static void
2702wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2703 const u8 *hdr, const u8 *buf, size_t len,
2704 unsigned int freq)
2705{
2706 struct dpp_authentication *auth = wpa_s->dpp_auth;
2707 struct wpabuf *conf;
2708
2709 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2710 MACSTR, MAC2STR(src));
2711
2712 if (!auth || !auth->reconfig || !auth->configurator) {
2713 wpa_printf(MSG_DEBUG,
2714 "DPP: No DPP Reconfig Authentication in progress - drop");
2715 return;
2716 }
2717
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002718 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002719 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2720 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2721 return;
2722 }
2723
2724 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2725 if (!conf)
2726 return;
2727
2728 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2729
2730 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2731 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2732 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2733 wpabuf_head(conf), wpabuf_len(conf),
2734 500, wpas_dpp_tx_status, 0) < 0) {
2735 wpabuf_free(conf);
2736 dpp_auth_deinit(wpa_s->dpp_auth);
2737 wpa_s->dpp_auth = NULL;
2738 return;
2739 }
2740 wpabuf_free(conf);
2741
2742 wpas_dpp_start_gas_server(wpa_s);
2743}
2744
2745
2746static void
2747wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2748 const u8 *hdr, const u8 *buf, size_t len,
2749 unsigned int freq)
2750{
2751 struct dpp_authentication *auth = wpa_s->dpp_auth;
2752
2753 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2754 MACSTR, MAC2STR(src));
2755
2756 if (!auth || !auth->reconfig || auth->configurator) {
2757 wpa_printf(MSG_DEBUG,
2758 "DPP: No DPP Reconfig Authentication in progress - drop");
2759 return;
2760 }
2761
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002762 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002763 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2764 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2765 return;
2766 }
2767
2768 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2769 return;
2770
2771 wpas_dpp_start_gas_client(wpa_s);
2772}
2773
Hai Shalom021b0b52019-04-10 11:17:58 -07002774#endif /* CONFIG_DPP2 */
2775
2776
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002777static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2778 const u8 *src,
2779 const u8 *buf, size_t len)
2780{
2781 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002782 const u8 *connector, *trans_id, *status;
2783 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002784#ifdef CONFIG_DPP2
2785 const u8 *version;
2786 u16 version_len;
2787#endif /* CONFIG_DPP2 */
2788 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002789 struct dpp_introduction intro;
2790 struct rsn_pmksa_cache_entry *entry;
2791 struct os_time now;
2792 struct os_reltime rnow;
2793 os_time_t expiry;
2794 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002795 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002796
2797 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2798 MAC2STR(src));
2799 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002800 !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002801 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2802 MACSTR " - drop", MAC2STR(src));
2803 return;
2804 }
2805 offchannel_send_action_done(wpa_s);
2806
2807 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2808 if (ssid == wpa_s->dpp_intro_network)
2809 break;
2810 }
2811 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2812 !ssid->dpp_csign) {
2813 wpa_printf(MSG_DEBUG,
2814 "DPP: Profile not found for network introduction");
2815 return;
2816 }
2817
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002818 os_memset(&intro, 0, sizeof(intro));
2819
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002820 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2821 &trans_id_len);
2822 if (!trans_id || trans_id_len != 1) {
2823 wpa_printf(MSG_DEBUG,
2824 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002825 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2826 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002827 goto fail;
2828 }
2829 if (trans_id[0] != TRANSACTION_ID) {
2830 wpa_printf(MSG_DEBUG,
2831 "DPP: Ignore frame with unexpected Transaction ID %u",
2832 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002833 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2834 " fail=transaction_id_mismatch", MAC2STR(src));
2835 goto fail;
2836 }
2837
2838 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2839 if (!status || status_len != 1) {
2840 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2841 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2842 " fail=missing_status", MAC2STR(src));
2843 goto fail;
2844 }
2845 if (status[0] != DPP_STATUS_OK) {
2846 wpa_printf(MSG_DEBUG,
2847 "DPP: Peer rejected network introduction: Status %u",
2848 status[0]);
2849 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2850 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002851#ifdef CONFIG_DPP2
2852 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2853#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002854 goto fail;
2855 }
2856
2857 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2858 if (!connector) {
2859 wpa_printf(MSG_DEBUG,
2860 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002861 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2862 " fail=missing_connector", MAC2STR(src));
2863 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002864 }
2865
Roshan Pius3a1667e2018-07-03 15:17:14 -07002866 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2867 ssid->dpp_netaccesskey,
2868 ssid->dpp_netaccesskey_len,
2869 ssid->dpp_csign,
2870 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002871 connector, connector_len, &expiry, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002872 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002873 wpa_printf(MSG_INFO,
2874 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002875 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2876 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002877#ifdef CONFIG_DPP2
2878 wpas_dpp_send_conn_status_result(wpa_s, res);
2879#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002880 goto fail;
2881 }
2882
2883 entry = os_zalloc(sizeof(*entry));
2884 if (!entry)
2885 goto fail;
2886 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002887 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002888 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2889 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2890 entry->pmk_len = intro.pmk_len;
2891 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002892#ifdef CONFIG_DPP2
2893 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2894 &version_len);
2895 if (version && version_len >= 1)
2896 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002897#ifdef CONFIG_DPP3
2898 if (intro.peer_version && intro.peer_version >= 2 &&
2899 peer_version != intro.peer_version) {
2900 wpa_printf(MSG_INFO,
2901 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2902 intro.peer_version, peer_version);
2903 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2904 goto fail;
2905 }
2906#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002907 entry->dpp_pfs = peer_version >= 2;
2908#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002909 if (expiry) {
2910 os_get_time(&now);
2911 seconds = expiry - now.sec;
2912 } else {
2913 seconds = 86400 * 7;
2914 }
2915 os_get_reltime(&rnow);
2916 entry->expiration = rnow.sec + seconds;
2917 entry->reauth_time = rnow.sec + seconds;
2918 entry->network_ctx = ssid;
2919 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2920
Roshan Pius3a1667e2018-07-03 15:17:14 -07002921 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002922 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002923
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002924 wpa_printf(MSG_DEBUG,
2925 "DPP: Try connection again after successful network introduction");
2926 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2927 wpa_supplicant_cancel_sched_scan(wpa_s);
2928 wpa_supplicant_req_scan(wpa_s, 0, 0);
2929 }
2930fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002931 dpp_peer_intro_deinit(&intro);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002932}
2933
2934
Roshan Pius3a1667e2018-07-03 15:17:14 -07002935static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2936{
2937 int i, j;
2938
2939 if (!wpa_s->hw.modes)
2940 return -1;
2941
2942 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2943 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2944
2945 for (j = 0; j < mode->num_channels; j++) {
2946 struct hostapd_channel_data *chan = &mode->channels[j];
2947
2948 if (chan->freq != (int) freq)
2949 continue;
2950
2951 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2952 HOSTAPD_CHAN_NO_IR |
2953 HOSTAPD_CHAN_RADAR))
2954 continue;
2955
2956 return 1;
2957 }
2958 }
2959
2960 wpa_printf(MSG_DEBUG,
2961 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2962 freq);
2963
2964 return 0;
2965}
2966
2967
2968static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2969 struct dpp_pkex *pkex)
2970{
2971 if (pkex->freq == 2437)
2972 pkex->freq = 5745;
2973 else if (pkex->freq == 5745)
2974 pkex->freq = 5220;
2975 else if (pkex->freq == 5220)
2976 pkex->freq = 60480;
2977 else
2978 return -1; /* no more channels to try */
2979
2980 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2981 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2982 pkex->freq);
2983 return 0;
2984 }
2985
2986 /* Could not use this channel - try the next one */
2987 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2988}
2989
2990
Sunil Ravi89eba102022-09-13 21:04:37 -07002991static void wpas_dpp_pkex_clear_code(struct wpa_supplicant *wpa_s)
2992{
2993 if (!wpa_s->dpp_pkex_code && !wpa_s->dpp_pkex_identifier)
2994 return;
2995
2996 /* Delete PKEX code and identifier on successful completion of
2997 * PKEX. We are not supposed to reuse these without being
2998 * explicitly requested to perform PKEX again. */
2999 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
3000 os_free(wpa_s->dpp_pkex_code);
3001 wpa_s->dpp_pkex_code = NULL;
3002 os_free(wpa_s->dpp_pkex_identifier);
3003 wpa_s->dpp_pkex_identifier = NULL;
3004
3005}
3006
3007
Hai Shaloma20dcd72022-02-04 13:43:00 -08003008#ifdef CONFIG_DPP2
3009static int wpas_dpp_pkex_done(void *ctx, void *conn,
3010 struct dpp_bootstrap_info *peer_bi)
3011{
3012 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -07003013 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -08003014 const char *pos;
3015 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
3016 struct dpp_bootstrap_info *own_bi = NULL;
3017 struct dpp_authentication *auth;
3018
Sunil Ravi89eba102022-09-13 21:04:37 -07003019 wpas_dpp_pkex_clear_code(wpa_s);
3020
3021 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
3022 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003023 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
3024 cmd);
3025
3026 pos = os_strstr(cmd, " own=");
3027 if (pos) {
3028 pos += 5;
3029 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
3030 if (!own_bi) {
3031 wpa_printf(MSG_INFO,
3032 "DPP: Could not find bootstrapping info for the identified local entry");
3033 return -1;
3034 }
3035
3036 if (peer_bi->curve != own_bi->curve) {
3037 wpa_printf(MSG_INFO,
3038 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
3039 peer_bi->curve->name, own_bi->curve->name);
3040 return -1;
3041 }
3042 }
3043
3044 pos = os_strstr(cmd, " role=");
3045 if (pos) {
3046 pos += 6;
3047 if (os_strncmp(pos, "configurator", 12) == 0)
3048 allowed_roles = DPP_CAPAB_CONFIGURATOR;
3049 else if (os_strncmp(pos, "enrollee", 8) == 0)
3050 allowed_roles = DPP_CAPAB_ENROLLEE;
3051 else if (os_strncmp(pos, "either", 6) == 0)
3052 allowed_roles = DPP_CAPAB_CONFIGURATOR |
3053 DPP_CAPAB_ENROLLEE;
3054 else
3055 return -1;
3056 }
3057
3058 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
3059 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
3060 if (!auth)
3061 return -1;
3062
3063 wpas_dpp_set_testing_options(wpa_s, auth);
3064 if (dpp_set_configurator(auth, cmd) < 0) {
3065 dpp_auth_deinit(auth);
3066 return -1;
3067 }
3068
3069 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -07003070 DPP_NETROLE_STA,
3071 wpa_s->conf->dpp_mud_url,
3072 wpa_s->conf->dpp_extra_conf_req_name,
3073 wpa_s->conf->dpp_extra_conf_req_value,
3074 wpas_dpp_process_conf_obj,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003075 wpas_dpp_tcp_msg_sent);
3076}
3077#endif /* CONFIG_DPP2 */
3078
3079
Hai Shaloma20dcd72022-02-04 13:43:00 -08003080static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07003081 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003082 const struct hostapd_ip_addr *ipaddr,
3083 int tcp_port)
3084{
3085 struct dpp_pkex *pkex;
3086 struct wpabuf *msg;
3087 unsigned int wait_time;
3088 bool v2 = ver != PKEX_VER_ONLY_1;
3089
3090 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
3091 dpp_pkex_free(wpa_s->dpp_pkex);
3092 wpa_s->dpp_pkex = NULL;
3093 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3094 wpa_s->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -07003095 wpa_s->dpp_pkex_code, wpa_s->dpp_pkex_code_len,
3096 v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003097 if (!pkex)
3098 return -1;
3099 pkex->forced_ver = ver != PKEX_VER_AUTO;
3100
3101 if (ipaddr) {
3102#ifdef CONFIG_DPP2
3103 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
3104 wpa_s, wpa_s, wpas_dpp_pkex_done);
3105#else /* CONFIG_DPP2 */
3106 return -1;
3107#endif /* CONFIG_DPP2 */
3108 }
3109
3110 wpa_s->dpp_pkex = pkex;
3111 msg = pkex->exchange_req;
3112 wait_time = wpa_s->max_remain_on_chan;
3113 if (wait_time > 2000)
3114 wait_time = 2000;
3115 pkex->freq = 2437;
3116 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3117 " freq=%u type=%d",
3118 MAC2STR(broadcast), pkex->freq,
3119 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3120 DPP_PA_PKEX_V1_EXCHANGE_REQ);
3121 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3122 wpa_s->own_addr, broadcast,
3123 wpabuf_head(msg), wpabuf_len(msg),
3124 wait_time, wpas_dpp_tx_pkex_status, 0);
3125 if (wait_time == 0)
3126 wait_time = 2000;
3127 pkex->exch_req_wait_time = wait_time;
3128 pkex->exch_req_tries = 1;
3129
3130 return 0;
3131}
3132
3133
Roshan Pius3a1667e2018-07-03 15:17:14 -07003134static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
3135{
3136 struct wpa_supplicant *wpa_s = eloop_ctx;
3137 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3138
3139 if (!pkex || !pkex->exchange_req)
3140 return;
3141 if (pkex->exch_req_tries >= 5) {
3142 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003143#ifdef CONFIG_DPP3
3144 if (pkex->v2 && !pkex->forced_ver) {
3145 wpa_printf(MSG_DEBUG,
3146 "DPP: Fall back to PKEXv1");
3147 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
3148 NULL, 0);
3149 return;
3150 }
3151#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003152 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
3153 "No response from PKEX peer");
3154 dpp_pkex_free(pkex);
3155 wpa_s->dpp_pkex = NULL;
3156 return;
3157 }
3158 pkex->exch_req_tries = 0;
3159 }
3160
3161 pkex->exch_req_tries++;
3162 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
3163 pkex->exch_req_tries);
3164 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08003165 MAC2STR(broadcast), pkex->freq,
3166 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3167 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003168 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3169 wpa_s->own_addr, broadcast,
3170 wpabuf_head(pkex->exchange_req),
3171 wpabuf_len(pkex->exchange_req),
3172 pkex->exch_req_wait_time,
3173 wpas_dpp_tx_pkex_status, 0);
3174}
3175
3176
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003177static void
3178wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
3179 unsigned int freq, const u8 *dst,
3180 const u8 *src, const u8 *bssid,
3181 const u8 *data, size_t data_len,
3182 enum offchannel_send_action_result result)
3183{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003184 const char *res_txt;
3185 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3186
3187 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3188 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3189 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003190 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3191 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003192 freq, MAC2STR(dst), res_txt);
3193 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3194 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3195
3196 if (!pkex) {
3197 wpa_printf(MSG_DEBUG,
3198 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
3199 return;
3200 }
3201
3202 if (pkex->failed) {
3203 wpa_printf(MSG_DEBUG,
3204 "DPP: Terminate PKEX exchange due to an earlier error");
3205 if (pkex->t > pkex->own_bi->pkex_t)
3206 pkex->own_bi->pkex_t = pkex->t;
3207 dpp_pkex_free(pkex);
3208 wpa_s->dpp_pkex = NULL;
3209 return;
3210 }
3211
3212 if (pkex->exch_req_wait_time && pkex->exchange_req) {
3213 /* Wait for PKEX Exchange Response frame and retry request if
3214 * no response is seen. */
3215 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3216 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
3217 (pkex->exch_req_wait_time % 1000) * 1000,
3218 wpas_dpp_pkex_retry_timeout, wpa_s,
3219 NULL);
3220 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003221}
3222
3223
3224static void
3225wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003226 const u8 *buf, size_t len, unsigned int freq,
3227 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003228{
3229 struct wpabuf *msg;
3230 unsigned int wait_time;
3231
3232 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
3233 MAC2STR(src));
3234
Sunil Ravia04bd252022-05-02 22:54:18 -07003235 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
3236 wpa_printf(MSG_DEBUG,
3237 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
3238 return;
3239 }
3240 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
3241 wpa_printf(MSG_DEBUG,
3242 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
3243 return;
3244 }
3245
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003246 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3247 * values here */
3248
3249 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
3250 wpa_printf(MSG_DEBUG,
3251 "DPP: No PKEX code configured - ignore request");
3252 return;
3253 }
3254
Sunil Ravi89eba102022-09-13 21:04:37 -07003255#ifdef CONFIG_DPP2
3256 if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) {
3257 wpa_printf(MSG_DEBUG,
3258 "DPP: PKEX Exchange Request is from local Controller - ignore request");
3259 return;
3260 }
3261#endif /* CONFIG_DPP2 */
3262
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003263 if (wpa_s->dpp_pkex) {
3264 /* TODO: Support parallel operations */
3265 wpa_printf(MSG_DEBUG,
3266 "DPP: Already in PKEX session - ignore new request");
3267 return;
3268 }
3269
Roshan Pius3a1667e2018-07-03 15:17:14 -07003270 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003271 wpa_s->own_addr, src,
3272 wpa_s->dpp_pkex_identifier,
3273 wpa_s->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07003274 wpa_s->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003275 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003276 if (!wpa_s->dpp_pkex) {
3277 wpa_printf(MSG_DEBUG,
3278 "DPP: Failed to process the request - ignore it");
3279 return;
3280 }
3281
Sunil Ravi89eba102022-09-13 21:04:37 -07003282#ifdef CONFIG_DPP3
3283 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_announcement) {
3284 wpa_printf(MSG_DEBUG,
3285 "DPP: Started PB PKEX (no more PB announcements)");
3286 wpabuf_free(wpa_s->dpp_pb_announcement);
3287 wpa_s->dpp_pb_announcement = NULL;
3288 }
3289#endif /* CONFIG_DPP3 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003290 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003291 msg = wpa_s->dpp_pkex->exchange_resp;
3292 wait_time = wpa_s->max_remain_on_chan;
3293 if (wait_time > 2000)
3294 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003295 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3296 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003297 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3298 broadcast,
3299 wpabuf_head(msg), wpabuf_len(msg),
3300 wait_time, wpas_dpp_tx_pkex_status, 0);
3301}
3302
3303
3304static void
3305wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3306 const u8 *buf, size_t len, unsigned int freq)
3307{
3308 struct wpabuf *msg;
3309 unsigned int wait_time;
3310
3311 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
3312 MAC2STR(src));
3313
3314 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3315 * values here */
3316
3317 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3318 wpa_s->dpp_pkex->exchange_done) {
3319 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3320 return;
3321 }
3322
Roshan Pius3a1667e2018-07-03 15:17:14 -07003323 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3324 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3325
3326 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003327 if (!msg) {
3328 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3329 return;
3330 }
3331
3332 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3333 MAC2STR(src));
3334
3335 wait_time = wpa_s->max_remain_on_chan;
3336 if (wait_time > 2000)
3337 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003338 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3339 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003340 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3341 broadcast,
3342 wpabuf_head(msg), wpabuf_len(msg),
3343 wait_time, wpas_dpp_tx_pkex_status, 0);
3344 wpabuf_free(msg);
3345}
3346
3347
Roshan Pius3a1667e2018-07-03 15:17:14 -07003348static struct dpp_bootstrap_info *
3349wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3350 unsigned int freq)
3351{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003352 struct dpp_bootstrap_info *bi;
3353
Sunil Ravi89eba102022-09-13 21:04:37 -07003354 wpas_dpp_pkex_clear_code(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003355 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003356 if (!bi)
3357 return NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003358
Roshan Pius3a1667e2018-07-03 15:17:14 -07003359 wpa_s->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003360
3361#ifdef CONFIG_DPP3
3362 if (wpa_s->dpp_pb_bi && !wpa_s->dpp_pb_configurator &&
3363 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_init_hash,
3364 SHA256_MAC_LEN) != 0) {
3365 char id[20];
3366
3367 wpa_printf(MSG_INFO,
3368 "DPP: Peer bootstrap key from PKEX does not match PB announcement response hash");
3369 wpa_hexdump(MSG_DEBUG,
3370 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3371 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3372 wpa_hexdump(MSG_DEBUG,
3373 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement response",
3374 wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN);
3375
3376 os_snprintf(id, sizeof(id), "%u", bi->id);
3377 dpp_bootstrap_remove(wpa_s->dpp, id);
3378 wpas_dpp_push_button_stop(wpa_s);
3379 return NULL;
3380 }
3381#endif /* CONFIG_DPP3 */
3382
Roshan Pius3a1667e2018-07-03 15:17:14 -07003383 return bi;
3384}
3385
3386
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003387static void
3388wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3389 const u8 *hdr, const u8 *buf, size_t len,
3390 unsigned int freq)
3391{
3392 struct wpabuf *msg;
3393 unsigned int wait_time;
3394 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003395
3396 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3397 MAC2STR(src));
3398
3399 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3400 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3401 return;
3402 }
3403
3404 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3405 if (!msg) {
3406 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003407 if (pkex->failed) {
3408 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3409 if (pkex->t > pkex->own_bi->pkex_t)
3410 pkex->own_bi->pkex_t = pkex->t;
3411 dpp_pkex_free(wpa_s->dpp_pkex);
3412 wpa_s->dpp_pkex = NULL;
3413 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003414 return;
3415 }
3416
3417 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3418 MACSTR, MAC2STR(src));
3419
3420 wait_time = wpa_s->max_remain_on_chan;
3421 if (wait_time > 2000)
3422 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003423 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3424 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003425 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3426 broadcast,
3427 wpabuf_head(msg), wpabuf_len(msg),
3428 wait_time, wpas_dpp_tx_pkex_status, 0);
3429 wpabuf_free(msg);
3430
Roshan Pius3a1667e2018-07-03 15:17:14 -07003431 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003432 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003433}
3434
3435
3436static void
3437wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3438 const u8 *hdr, const u8 *buf, size_t len,
3439 unsigned int freq)
3440{
3441 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003442 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003443 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3444 char cmd[500];
3445
3446 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3447 MAC2STR(src));
3448
3449 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3450 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3451 return;
3452 }
3453
3454 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3455 if (res < 0) {
3456 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3457 return;
3458 }
3459
Roshan Pius3a1667e2018-07-03 15:17:14 -07003460 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003461 if (!bi)
3462 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003463
Sunil Ravi89eba102022-09-13 21:04:37 -07003464#ifdef CONFIG_DPP3
3465 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_configurator &&
3466 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_resp_hash,
3467 SHA256_MAC_LEN) != 0) {
3468 char id[20];
3469
3470 wpa_printf(MSG_INFO,
3471 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
3472 wpa_hexdump(MSG_DEBUG,
3473 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3474 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3475 wpa_hexdump(MSG_DEBUG,
3476 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
3477 wpa_s->dpp_pb_resp_hash, SHA256_MAC_LEN);
3478
3479 os_snprintf(id, sizeof(id), "%u", bi->id);
3480 dpp_bootstrap_remove(wpa_s->dpp, id);
3481 wpas_dpp_push_button_stop(wpa_s);
3482 return;
3483 }
3484#endif /* CONFIG_DPP3 */
3485
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003486 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3487 bi->id,
3488 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3489 wpa_printf(MSG_DEBUG,
3490 "DPP: Start authentication after PKEX with parameters: %s",
3491 cmd);
3492 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3493 wpa_printf(MSG_DEBUG,
3494 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003495 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003496 return;
3497 }
3498}
3499
3500
Sunil Ravi89eba102022-09-13 21:04:37 -07003501#ifdef CONFIG_DPP3
3502
3503static void wpas_dpp_pb_pkex_init(struct wpa_supplicant *wpa_s,
3504 unsigned int freq, const u8 *src,
3505 const u8 *r_hash)
3506{
3507 struct dpp_pkex *pkex;
3508 struct wpabuf *msg;
3509 unsigned int wait_time;
3510 size_t len;
3511
3512 if (wpa_s->dpp_pkex) {
3513 wpa_printf(MSG_DEBUG,
3514 "DPP: Sending previously generated PKEX Exchange Request to "
3515 MACSTR, MAC2STR(src));
3516 msg = wpa_s->dpp_pkex->exchange_req;
3517 wait_time = wpa_s->max_remain_on_chan;
3518 if (wait_time > 2000)
3519 wait_time = 2000;
3520 offchannel_send_action(wpa_s, freq, src,
3521 wpa_s->own_addr, broadcast,
3522 wpabuf_head(msg), wpabuf_len(msg),
3523 wait_time, wpas_dpp_tx_pkex_status, 0);
3524 return;
3525 }
3526
3527 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
3528 MACSTR, MAC2STR(src));
3529
3530 if (!wpa_s->dpp_pb_cmd) {
3531 wpa_printf(MSG_INFO,
3532 "DPP: No configuration to provision as push button Configurator");
3533 wpas_dpp_push_button_stop(wpa_s);
3534 return;
3535 }
3536
3537 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
3538 os_memcpy(wpa_s->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
3539
3540 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3541 "PBPKEX", (const char *) wpa_s->dpp_pb_c_nonce,
3542 wpa_s->dpp_pb_bi->curve->nonce_len,
3543 true);
3544 if (!pkex) {
3545 wpas_dpp_push_button_stop(wpa_s);
3546 return;
3547 }
3548 pkex->freq = freq;
3549
3550 wpa_s->dpp_pkex = pkex;
3551 msg = wpa_s->dpp_pkex->exchange_req;
3552 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3553 " freq=%u type=%d", MAC2STR(src), freq,
3554 DPP_PA_PKEX_EXCHANGE_REQ);
3555 wait_time = wpa_s->max_remain_on_chan;
3556 if (wait_time > 2000)
3557 wait_time = 2000;
3558 offchannel_send_action(wpa_s, pkex->freq, src,
3559 wpa_s->own_addr, broadcast,
3560 wpabuf_head(msg), wpabuf_len(msg),
3561 wait_time, wpas_dpp_tx_pkex_status, 0);
3562 pkex->exch_req_wait_time = 2000;
3563 pkex->exch_req_tries = 1;
3564
3565 /* Use the externally provided configuration */
3566 os_free(wpa_s->dpp_pkex_auth_cmd);
3567 len = 30 + os_strlen(wpa_s->dpp_pb_cmd);
3568 wpa_s->dpp_pkex_auth_cmd = os_malloc(len);
3569 if (wpa_s->dpp_pkex_auth_cmd)
3570 os_snprintf(wpa_s->dpp_pkex_auth_cmd, len, " own=%d %s",
3571 wpa_s->dpp_pkex_bi->id, wpa_s->dpp_pb_cmd);
3572 else
3573 wpas_dpp_push_button_stop(wpa_s);
3574}
3575
3576
3577static void
3578wpas_dpp_rx_pb_presence_announcement(struct wpa_supplicant *wpa_s,
3579 const u8 *src, const u8 *hdr,
3580 const u8 *buf, size_t len,
3581 unsigned int freq)
3582{
3583 const u8 *r_hash;
3584 u16 r_hash_len;
3585 unsigned int i;
3586 bool found = false;
3587 struct dpp_pb_info *info, *tmp;
3588 struct os_reltime now, age;
3589 struct wpabuf *msg;
3590
3591 os_get_reltime(&now);
3592 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
3593 MACSTR, MAC2STR(src));
3594
3595 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3596 &r_hash_len);
3597 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
3598 wpa_printf(MSG_DEBUG,
3599 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
3600 return;
3601 }
3602 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3603 r_hash, r_hash_len);
3604
3605 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3606 info = &wpa_s->dpp_pb[i];
3607 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
3608 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
3609 continue;
3610 wpa_printf(MSG_DEBUG,
3611 "DPP: Active push button Enrollee already known");
3612 found = true;
3613 info->rx_time = now;
3614 }
3615
3616 if (!found) {
3617 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3618 tmp = &wpa_s->dpp_pb[i];
3619 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
3620 continue;
3621
3622 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
3623 wpa_hexdump(MSG_DEBUG,
3624 "DPP: Push button Enrollee hash expired",
3625 tmp->hash, SHA256_MAC_LEN);
3626 tmp->rx_time.sec = 0;
3627 tmp->rx_time.usec = 0;
3628 continue;
3629 }
3630
3631 wpa_hexdump(MSG_DEBUG,
3632 "DPP: Push button session overlap with hash",
3633 tmp->hash, SHA256_MAC_LEN);
3634 if (!wpa_s->dpp_pb_result_indicated &&
3635 wpas_dpp_pb_active(wpa_s)) {
3636 wpa_msg(wpa_s, MSG_INFO,
3637 DPP_EVENT_PB_RESULT "session-overlap");
3638 wpa_s->dpp_pb_result_indicated = true;
3639 }
3640 wpas_dpp_push_button_stop(wpa_s);
3641 return;
3642 }
3643
3644 /* Replace the oldest entry */
3645 info = &wpa_s->dpp_pb[0];
3646 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
3647 tmp = &wpa_s->dpp_pb[i];
3648 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
3649 info = tmp;
3650 }
3651 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
3652 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
3653 info->rx_time = now;
3654 }
3655
3656 if (!wpas_dpp_pb_active(wpa_s)) {
3657 wpa_printf(MSG_DEBUG,
3658 "DPP: Discard message since own push button has not been pressed");
3659 return;
3660 }
3661
3662 if (wpa_s->dpp_pb_announce_time.sec == 0 &&
3663 wpa_s->dpp_pb_announce_time.usec == 0) {
3664 /* Start a wait before allowing PKEX to be initiated */
3665 wpa_s->dpp_pb_announce_time = now;
3666 }
3667
3668 if (!wpa_s->dpp_pb_bi) {
3669 int res;
3670
3671 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
3672 if (res < 0)
3673 return;
3674 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
3675 if (!wpa_s->dpp_pb_bi)
3676 return;
3677
3678 if (random_get_bytes(wpa_s->dpp_pb_c_nonce,
3679 wpa_s->dpp_pb_bi->curve->nonce_len)) {
3680 wpa_printf(MSG_ERROR,
3681 "DPP: Failed to generate C-nonce");
3682 wpas_dpp_push_button_stop(wpa_s);
3683 return;
3684 }
3685 }
3686
3687 /* Skip the response if one was sent within last 50 ms since the
3688 * Enrollee is going to send out at least three announcement messages.
3689 */
3690 os_reltime_sub(&now, &wpa_s->dpp_pb_last_resp, &age);
3691 if (age.sec == 0 && age.usec < 50000) {
3692 wpa_printf(MSG_DEBUG,
3693 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
3694 return;
3695 }
3696
3697 msg = dpp_build_pb_announcement_resp(
3698 wpa_s->dpp_pb_bi, r_hash, wpa_s->dpp_pb_c_nonce,
3699 wpa_s->dpp_pb_bi->curve->nonce_len);
3700 if (!msg) {
3701 wpas_dpp_push_button_stop(wpa_s);
3702 return;
3703 }
3704
3705 wpa_printf(MSG_DEBUG,
3706 "DPP: Send Push Button Presence Announcement Response to "
3707 MACSTR, MAC2STR(src));
3708 wpa_s->dpp_pb_last_resp = now;
3709
3710 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3711 MAC2STR(src), freq, DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
3712 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
3713 wpabuf_head(msg), wpabuf_len(msg),
3714 0, NULL, 0);
3715 wpabuf_free(msg);
3716
3717 if (os_reltime_expired(&now, &wpa_s->dpp_pb_announce_time, 15))
3718 wpas_dpp_pb_pkex_init(wpa_s, freq, src, r_hash);
3719}
3720
3721
3722static void
3723wpas_dpp_rx_pb_presence_announcement_resp(struct wpa_supplicant *wpa_s,
3724 const u8 *src, const u8 *hdr,
3725 const u8 *buf, size_t len,
3726 unsigned int freq)
3727{
3728 const u8 *i_hash, *r_hash, *c_nonce;
3729 u16 i_hash_len, r_hash_len, c_nonce_len;
3730 bool overlap = false;
3731
3732 if (!wpa_s->dpp_pb_announcement || !wpa_s->dpp_pb_bi ||
3733 wpa_s->dpp_pb_configurator) {
3734 wpa_printf(MSG_INFO,
3735 "DPP: Not in active push button Enrollee mode - discard Push Button Presence Announcement Response from "
3736 MACSTR, MAC2STR(src));
3737 return;
3738 }
3739
3740 wpa_printf(MSG_DEBUG,
3741 "DPP: Push Button Presence Announcement Response from "
3742 MACSTR, MAC2STR(src));
3743
3744 i_hash = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3745 &i_hash_len);
3746 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3747 &r_hash_len);
3748 c_nonce = dpp_get_attr(buf, len, DPP_ATTR_CONFIGURATOR_NONCE,
3749 &c_nonce_len);
3750 if (!i_hash || i_hash_len != SHA256_MAC_LEN ||
3751 !r_hash || r_hash_len != SHA256_MAC_LEN ||
3752 !c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
3753 wpa_printf(MSG_DEBUG,
3754 "DPP: Missing or invalid required attribute");
3755 return;
3756 }
3757 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
3758 i_hash, i_hash_len);
3759 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3760 r_hash, r_hash_len);
3761 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator Nonce",
3762 c_nonce, c_nonce_len);
3763
3764#ifdef CONFIG_TESTING_OPTIONS
3765 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ &&
3766 os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3767 SHA256_MAC_LEN - 1) == 0)
3768 goto skip_hash_check;
3769#endif /* CONFIG_TESTING_OPTIONS */
3770 if (os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3771 SHA256_MAC_LEN) != 0) {
3772 wpa_printf(MSG_INFO,
3773 "DPP: Unexpected push button Responder hash - abort");
3774 overlap = true;
3775 }
3776#ifdef CONFIG_TESTING_OPTIONS
3777skip_hash_check:
3778#endif /* CONFIG_TESTING_OPTIONS */
3779
3780 if (wpa_s->dpp_pb_resp_freq &&
3781 os_memcmp(i_hash, wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN) != 0) {
3782 wpa_printf(MSG_INFO,
3783 "DPP: Push button session overlap detected - abort");
3784 overlap = true;
3785 }
3786
3787 if (overlap) {
3788 if (!wpa_s->dpp_pb_result_indicated) {
3789 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
3790 "session-overlap");
3791 wpa_s->dpp_pb_result_indicated = true;
3792 }
3793 wpas_dpp_push_button_stop(wpa_s);
3794 return;
3795 }
3796
3797 if (!wpa_s->dpp_pb_resp_freq) {
3798 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
3799 "discovered push button AP/Configurator " MACSTR,
3800 MAC2STR(src));
3801 wpa_s->dpp_pb_resp_freq = freq;
3802 os_memcpy(wpa_s->dpp_pb_init_hash, i_hash, SHA256_MAC_LEN);
3803 os_memcpy(wpa_s->dpp_pb_c_nonce, c_nonce, c_nonce_len);
3804 wpa_s->dpp_pb_c_nonce_len = c_nonce_len;
3805 /* Stop announcement iterations after at least one more full
3806 * round and one extra round for postponed session overlap
3807 * detection. */
3808 wpa_s->dpp_pb_stop_iter = 3;
3809 }
3810}
3811
3812
3813static void
3814wpas_dpp_tx_priv_intro_status(struct wpa_supplicant *wpa_s,
3815 unsigned int freq, const u8 *dst,
3816 const u8 *src, const u8 *bssid,
3817 const u8 *data, size_t data_len,
3818 enum offchannel_send_action_result result)
3819{
3820 const char *res_txt;
3821
3822 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3823 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3824 "FAILED");
3825 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3826 " result=%s (DPP Private Peer Introduction Update)",
3827 freq, MAC2STR(dst), res_txt);
3828 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3829 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3830
3831 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR " version=%u",
3832 MAC2STR(src), wpa_s->dpp_intro_peer_version);
3833
3834 wpa_printf(MSG_DEBUG,
3835 "DPP: Try connection again after successful network introduction");
3836 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3837 wpa_supplicant_cancel_sched_scan(wpa_s);
3838 wpa_supplicant_req_scan(wpa_s, 0, 0);
3839 }
3840}
3841
3842
3843static int
3844wpas_dpp_send_private_peer_intro_update(struct wpa_supplicant *wpa_s,
3845 struct dpp_introduction *intro,
3846 struct wpa_ssid *ssid,
3847 const u8 *dst, unsigned int freq)
3848{
3849 struct wpabuf *pt, *msg, *enc_ct;
3850 size_t len;
3851 u8 ver = DPP_VERSION;
3852 int conn_ver;
3853 const u8 *aad;
3854 size_t aad_len;
3855 unsigned int wait_time;
3856
3857 wpa_printf(MSG_DEBUG, "HPKE(kem_id=%u kdf_id=%u aead_id=%u)",
3858 intro->kem_id, intro->kdf_id, intro->aead_id);
3859
3860 /* Plaintext for HPKE */
3861 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3862 pt = wpabuf_alloc(len);
3863 if (!pt)
3864 return -1;
3865
3866 /* Protocol Version */
3867 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3868 if (conn_ver > 0 && ver != conn_ver) {
3869 wpa_printf(MSG_DEBUG,
3870 "DPP: Use Connector version %d instead of current protocol version %d",
3871 conn_ver, ver);
3872 ver = conn_ver;
3873 }
3874 wpabuf_put_le16(pt, DPP_ATTR_PROTOCOL_VERSION);
3875 wpabuf_put_le16(pt, 1);
3876 wpabuf_put_u8(pt, ver);
3877
3878 /* Connector */
3879 wpabuf_put_le16(pt, DPP_ATTR_CONNECTOR);
3880 wpabuf_put_le16(pt, os_strlen(ssid->dpp_connector));
3881 wpabuf_put_str(pt, ssid->dpp_connector);
3882 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Plaintext for HPKE", pt);
3883
3884 /* HPKE(pt) using AP's public key (from its Connector) */
3885 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, 0);
3886 if (!msg) {
3887 wpabuf_free(pt);
3888 return -1;
3889 }
3890 aad = wpabuf_head_u8(msg) + 2; /* from the OUI field (inclusive) */
3891 aad_len = DPP_HDR_LEN; /* to the DPP Frame Type field (inclusive) */
3892 wpa_hexdump(MSG_MSGDUMP, "DPP: AAD for HPKE", aad, aad_len);
3893
3894 enc_ct = hpke_base_seal(intro->kem_id, intro->kdf_id, intro->aead_id,
3895 intro->peer_key, NULL, 0, aad, aad_len,
3896 wpabuf_head(pt), wpabuf_len(pt));
3897 wpabuf_free(pt);
3898 wpabuf_free(msg);
3899 if (!enc_ct) {
3900 wpa_printf(MSG_INFO, "DPP: HPKE Seal(Connector) failed");
3901 return -1;
3902 }
3903 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE enc|ct", enc_ct);
3904
3905 /* HPKE(pt) to generate payload for Wrapped Data */
3906 len = 5 + 4 + wpabuf_len(enc_ct);
3907 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, len);
3908 if (!msg) {
3909 wpabuf_free(enc_ct);
3910 return -1;
3911 }
3912
3913 /* Transaction ID */
3914 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3915 wpabuf_put_le16(msg, 1);
3916 wpabuf_put_u8(msg, TRANSACTION_ID);
3917
3918 /* Wrapped Data */
3919 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3920 wpabuf_put_le16(msg, wpabuf_len(enc_ct));
3921 wpabuf_put_buf(msg, enc_ct);
3922 wpabuf_free(enc_ct);
3923
3924 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Update", msg);
3925
3926 /* TODO: Timeout on AP response */
3927 wait_time = wpa_s->max_remain_on_chan;
3928 if (wait_time > 2000)
3929 wait_time = 2000;
3930 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3931 MAC2STR(dst), freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
3932 offchannel_send_action(wpa_s, freq, dst, wpa_s->own_addr, broadcast,
3933 wpabuf_head(msg), wpabuf_len(msg),
3934 wait_time, wpas_dpp_tx_priv_intro_status, 0);
3935 wpabuf_free(msg);
3936
3937 return 0;
3938}
3939
3940
3941static void
3942wpas_dpp_rx_priv_peer_intro_notify(struct wpa_supplicant *wpa_s,
3943 const u8 *src, const u8 *hdr,
3944 const u8 *buf, size_t len,
3945 unsigned int freq)
3946{
3947 struct wpa_ssid *ssid;
3948 const u8 *connector, *trans_id, *version;
3949 u16 connector_len, trans_id_len, version_len;
3950 u8 peer_version = 1;
3951 struct dpp_introduction intro;
3952 struct rsn_pmksa_cache_entry *entry;
3953 struct os_time now;
3954 struct os_reltime rnow;
3955 os_time_t expiry;
3956 unsigned int seconds;
3957 enum dpp_status_error res;
3958
3959 os_memset(&intro, 0, sizeof(intro));
3960
3961 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
3962 MACSTR, MAC2STR(src));
3963 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003964 !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
Sunil Ravi89eba102022-09-13 21:04:37 -07003965 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
3966 MACSTR " - drop", MAC2STR(src));
3967 return;
3968 }
3969 offchannel_send_action_done(wpa_s);
3970
3971 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3972 if (ssid == wpa_s->dpp_intro_network)
3973 break;
3974 }
3975 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3976 !ssid->dpp_csign) {
3977 wpa_printf(MSG_DEBUG,
3978 "DPP: Profile not found for network introduction");
3979 return;
3980 }
3981
3982 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
3983 &trans_id_len);
3984 if (!trans_id || trans_id_len != 1) {
3985 wpa_printf(MSG_DEBUG,
3986 "DPP: Peer did not include Transaction ID");
3987 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3988 " fail=missing_transaction_id", MAC2STR(src));
3989 goto fail;
3990 }
3991 if (trans_id[0] != TRANSACTION_ID) {
3992 wpa_printf(MSG_DEBUG,
3993 "DPP: Ignore frame with unexpected Transaction ID %u",
3994 trans_id[0]);
3995 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3996 " fail=transaction_id_mismatch", MAC2STR(src));
3997 goto fail;
3998 }
3999
4000 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
4001 if (!connector) {
4002 wpa_printf(MSG_DEBUG,
4003 "DPP: Peer did not include its Connector");
4004 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4005 " fail=missing_connector", MAC2STR(src));
4006 goto fail;
4007 }
4008
4009 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
4010 &version_len);
4011 if (!version || version_len < 1) {
4012 wpa_printf(MSG_DEBUG,
4013 "DPP: Peer did not include valid Version");
4014 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4015 " fail=missing_version", MAC2STR(src));
4016 goto fail;
4017 }
4018
4019 res = dpp_peer_intro(&intro, ssid->dpp_connector,
4020 ssid->dpp_netaccesskey,
4021 ssid->dpp_netaccesskey_len,
4022 ssid->dpp_csign,
4023 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004024 connector, connector_len, &expiry, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07004025 if (res != DPP_STATUS_OK) {
4026 wpa_printf(MSG_INFO,
4027 "DPP: Network Introduction protocol resulted in failure");
4028 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4029 " fail=peer_connector_validation_failed", MAC2STR(src));
4030 wpas_dpp_send_conn_status_result(wpa_s, res);
4031 goto fail;
4032 }
4033
4034 peer_version = version[0];
4035 if (intro.peer_version && intro.peer_version >= 2 &&
4036 peer_version != intro.peer_version) {
4037 wpa_printf(MSG_INFO,
4038 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
4039 intro.peer_version, peer_version);
4040 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
4041 goto fail;
4042 }
4043 wpa_s->dpp_intro_peer_version = peer_version;
4044
4045 entry = os_zalloc(sizeof(*entry));
4046 if (!entry)
4047 goto fail;
4048 entry->dpp_pfs = peer_version >= 2;
4049 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004050 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Sunil Ravi89eba102022-09-13 21:04:37 -07004051 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
4052 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
4053 entry->pmk_len = intro.pmk_len;
4054 entry->akmp = WPA_KEY_MGMT_DPP;
4055 if (expiry) {
4056 os_get_time(&now);
4057 seconds = expiry - now.sec;
4058 } else {
4059 seconds = 86400 * 7;
4060 }
4061
4062 if (wpas_dpp_send_private_peer_intro_update(wpa_s, &intro, ssid, src,
4063 freq) < 0) {
4064 os_free(entry);
4065 goto fail;
4066 }
4067
4068 os_get_reltime(&rnow);
4069 entry->expiration = rnow.sec + seconds;
4070 entry->reauth_time = rnow.sec + seconds;
4071 entry->network_ctx = ssid;
4072 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
4073
4074 /* Association will be initiated from TX status handler for the Private
4075 * Peer Intro Update: wpas_dpp_tx_priv_intro_status() */
4076
4077fail:
4078 dpp_peer_intro_deinit(&intro);
4079}
4080
4081#endif /* CONFIG_DPP3 */
4082
4083
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004084void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
4085 const u8 *buf, size_t len, unsigned int freq)
4086{
4087 u8 crypto_suite;
4088 enum dpp_public_action_frame_type type;
4089 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004090 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004091
4092 if (len < DPP_HDR_LEN)
4093 return;
4094 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
4095 return;
4096 hdr = buf;
4097 buf += 4;
4098 len -= 4;
4099 crypto_suite = *buf++;
4100 type = *buf++;
4101 len -= 2;
4102
4103 wpa_printf(MSG_DEBUG,
4104 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
4105 MACSTR " freq=%u",
4106 crypto_suite, type, MAC2STR(src), freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07004107#ifdef CONFIG_TESTING_OPTIONS
4108 if (wpa_s->dpp_discard_public_action &&
4109 type != DPP_PA_PEER_DISCOVERY_RESP &&
4110 type != DPP_PA_PRIV_PEER_INTRO_NOTIFY) {
4111 wpa_printf(MSG_DEBUG,
4112 "TESTING: Discard received DPP Public Action frame");
4113 return;
4114 }
4115#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004116 if (crypto_suite != 1) {
4117 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
4118 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004119 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4120 " freq=%u type=%d ignore=unsupported-crypto-suite",
4121 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004122 return;
4123 }
4124 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004125 if (dpp_check_attrs(buf, len) < 0) {
4126 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4127 " freq=%u type=%d ignore=invalid-attributes",
4128 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004129 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004130 }
4131 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
4132 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004133
4134 switch (type) {
4135 case DPP_PA_AUTHENTICATION_REQ:
4136 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
4137 break;
4138 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07004139 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004140 break;
4141 case DPP_PA_AUTHENTICATION_CONF:
4142 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
4143 break;
4144 case DPP_PA_PEER_DISCOVERY_RESP:
4145 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
4146 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004147#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004148 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004149 /* This is for PKEXv2, but for now, process only with
4150 * CONFIG_DPP3 to avoid issues with a capability that has not
4151 * been tested with other implementations. */
4152 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
4153 break;
4154#endif /* CONFIG_DPP3 */
4155 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
4156 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
4157 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004158 break;
4159 case DPP_PA_PKEX_EXCHANGE_RESP:
4160 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
4161 break;
4162 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
4163 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
4164 freq);
4165 break;
4166 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
4167 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
4168 freq);
4169 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004170#ifdef CONFIG_DPP2
4171 case DPP_PA_CONFIGURATION_RESULT:
4172 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
4173 break;
Hai Shalomc3565922019-10-28 11:58:20 -07004174 case DPP_PA_CONNECTION_STATUS_RESULT:
4175 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
4176 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07004177 case DPP_PA_PRESENCE_ANNOUNCEMENT:
4178 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
4179 freq);
4180 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004181 case DPP_PA_RECONFIG_ANNOUNCEMENT:
4182 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
4183 freq);
4184 break;
4185 case DPP_PA_RECONFIG_AUTH_REQ:
4186 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
4187 break;
4188 case DPP_PA_RECONFIG_AUTH_RESP:
4189 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
4190 break;
4191 case DPP_PA_RECONFIG_AUTH_CONF:
4192 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
4193 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004194#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07004195#ifdef CONFIG_DPP3
4196 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
4197 wpas_dpp_rx_pb_presence_announcement(wpa_s, src, hdr,
4198 buf, len, freq);
4199 break;
4200 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP:
4201 wpas_dpp_rx_pb_presence_announcement_resp(wpa_s, src, hdr,
4202 buf, len, freq);
4203 break;
4204 case DPP_PA_PRIV_PEER_INTRO_NOTIFY:
4205 wpas_dpp_rx_priv_peer_intro_notify(wpa_s, src, hdr,
4206 buf, len, freq);
4207 break;
4208#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004209 default:
4210 wpa_printf(MSG_DEBUG,
4211 "DPP: Ignored unsupported frame subtype %d", type);
4212 break;
4213 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004214
4215 if (wpa_s->dpp_pkex)
4216 pkex_t = wpa_s->dpp_pkex->t;
4217 else if (wpa_s->dpp_pkex_bi)
4218 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
4219 else
4220 pkex_t = 0;
4221 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
4222 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
4223 wpas_dpp_pkex_remove(wpa_s, "*");
4224 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004225}
4226
4227
Hai Shaloma20dcd72022-02-04 13:43:00 -08004228static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
4229 void *timeout_ctx)
4230{
4231 struct wpa_supplicant *wpa_s = eloop_ctx;
4232 struct dpp_authentication *auth = wpa_s->dpp_auth;
4233
4234 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
4235 return;
4236
4237 wpa_printf(MSG_DEBUG,
4238 "DPP: No configuration available from upper layers - send initial response with comeback delay");
4239 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
4240 500);
4241}
4242
4243
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004244static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07004245wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08004246 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004247{
4248 struct wpa_supplicant *wpa_s = ctx;
4249 struct dpp_authentication *auth = wpa_s->dpp_auth;
4250 struct wpabuf *resp;
4251
4252 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
4253 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004254 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004255 !ether_addr_equal(sa, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004256 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
4257 return NULL;
4258 }
Hai Shalomc3565922019-10-28 11:58:20 -07004259
4260 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
4261 wpa_printf(MSG_DEBUG,
4262 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
4263 /* wpas_dpp_auth_success() would normally have been called from
4264 * TX status handler, but since there was no such handler call
4265 * yet, simply send out the event message and proceed with
4266 * exchange. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004267 dpp_notify_auth_success(auth, 1);
Hai Shalomc3565922019-10-28 11:58:20 -07004268 wpa_s->dpp_auth_ok_on_ack = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004269#ifdef CONFIG_TESTING_OPTIONS
4270 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
4271 wpa_printf(MSG_INFO,
4272 "DPP: TESTING - stop at Authentication Confirm");
4273 return NULL;
4274 }
4275#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07004276 }
4277
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004278 wpa_hexdump(MSG_DEBUG,
4279 "DPP: Received Configuration Request (GAS Query Request)",
4280 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004281 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
4282 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004283 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004284
Hai Shaloma20dcd72022-02-04 13:43:00 -08004285 auth->gas_server_ctx = resp_ctx;
4286
Hai Shalom899fcc72020-10-19 14:38:18 -07004287#ifdef CONFIG_DPP2
4288 if (!resp && auth->waiting_cert) {
4289 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08004290 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07004291 *comeback_delay = 500;
4292 return NULL;
4293 }
4294#endif /* CONFIG_DPP2 */
4295
Hai Shaloma20dcd72022-02-04 13:43:00 -08004296 if (!resp && auth->waiting_config &&
4297 (auth->peer_bi || auth->tmp_peer_bi)) {
4298 char *buf = NULL, *name = "";
4299 char band[200], *pos, *end;
4300 int i, res, *opclass = auth->e_band_support;
4301 char *mud_url = "N/A";
4302
4303 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
4304 auth->config_resp_ctx = resp_ctx;
4305 *comeback_delay = -1;
4306 if (auth->e_name) {
4307 size_t len = os_strlen(auth->e_name);
4308
4309 buf = os_malloc(len * 4 + 1);
4310 if (buf) {
4311 printf_encode(buf, len * 4 + 1,
4312 (const u8 *) auth->e_name, len);
4313 name = buf;
4314 }
4315 }
4316 band[0] = '\0';
4317 pos = band;
4318 end = band + sizeof(band);
4319 for (i = 0; opclass && opclass[i]; i++) {
4320 res = os_snprintf(pos, end - pos, "%s%d",
4321 pos == band ? "" : ",", opclass[i]);
4322 if (os_snprintf_error(end - pos, res)) {
4323 *pos = '\0';
4324 break;
4325 }
4326 pos += res;
4327 }
4328 if (auth->e_mud_url) {
4329 size_t len = os_strlen(auth->e_mud_url);
4330
4331 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
4332 mud_url = auth->e_mud_url;
4333 }
4334 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
4335 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
4336 auth->peer_bi ? auth->peer_bi->id :
4337 auth->tmp_peer_bi->id, MAC2STR(sa),
4338 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
4339 os_free(buf);
4340
4341 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4342 NULL);
4343 eloop_register_timeout(0, 50000,
4344 wpas_dpp_gas_initial_resp_timeout, wpa_s,
4345 NULL);
4346 return NULL;
4347 }
4348
Sunil Ravia04bd252022-05-02 22:54:18 -07004349 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08004350 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004351 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004352 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07004353 dpp_auth_deinit(wpa_s->dpp_auth);
4354 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08004355 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004356 return resp;
4357}
4358
4359
4360static void
4361wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
4362{
4363 struct wpa_supplicant *wpa_s = ctx;
4364 struct dpp_authentication *auth = wpa_s->dpp_auth;
4365
4366 if (!auth) {
4367 wpabuf_free(resp);
4368 return;
4369 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004370 if (auth->conf_resp != resp) {
4371 wpa_printf(MSG_DEBUG,
4372 "DPP: Ignore GAS status report (ok=%d) for unknown response",
4373 ok);
4374 wpabuf_free(resp);
4375 return;
4376 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004377
Hai Shalom899fcc72020-10-19 14:38:18 -07004378#ifdef CONFIG_DPP2
4379 if (auth->waiting_csr && ok) {
4380 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
4381 wpabuf_free(resp);
4382 return;
4383 }
4384#endif /* CONFIG_DPP2 */
4385
Sunil Ravia04bd252022-05-02 22:54:18 -07004386#ifdef CONFIG_DPP3
4387 if (auth->waiting_new_key && ok) {
4388 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
4389 wpabuf_free(resp);
4390 return;
4391 }
4392#endif /* CONFIG_DPP3 */
4393
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004394 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
4395 ok);
4396 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004397 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004398 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004399#ifdef CONFIG_DPP2
4400 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08004401 auth->conf_resp_status == DPP_STATUS_OK &&
4402 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07004403 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08004404 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07004405 auth->waiting_conf_result = 1;
4406 auth->conf_resp = NULL;
4407 wpabuf_free(resp);
4408 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
4409 wpa_s, NULL);
4410 eloop_register_timeout(2, 0,
4411 wpas_dpp_config_result_wait_timeout,
4412 wpa_s, NULL);
4413 return;
4414 }
4415#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004416 offchannel_send_action_done(wpa_s);
4417 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004418 if (ok) {
Sunil Ravi89eba102022-09-13 21:04:37 -07004419 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
4420 auth->conf_resp_status);
Hai Shalom706f99b2019-01-08 16:23:37 -08004421 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004422 }
4423 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004424 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004425 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004426 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004427 dpp_auth_deinit(wpa_s->dpp_auth);
4428 wpa_s->dpp_auth = NULL;
4429 wpabuf_free(resp);
Sunil Ravi89eba102022-09-13 21:04:37 -07004430#ifdef CONFIG_DPP3
4431 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
4432 if (ok)
4433 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4434 "success");
4435 else
4436 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4437 "could-not-connect");
4438 wpa_s->dpp_pb_result_indicated = true;
4439 if (ok)
4440 wpas_dpp_remove_pb_hash(wpa_s);
4441 wpas_dpp_push_button_stop(wpa_s);
4442 }
4443#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004444}
4445
4446
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004447int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
4448{
4449 struct dpp_authentication *auth;
4450 int ret = -1;
4451 char *curve = NULL;
4452
Hai Shalomfdcde762020-04-02 11:19:20 -07004453 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004454 if (!auth)
4455 return -1;
4456
4457 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08004458 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07004459 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004460 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07004461 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
4462 &auth->conf_obj[0]);
4463 if (!ret)
4464 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004465
4466 dpp_auth_deinit(auth);
4467 os_free(curve);
4468
4469 return ret;
4470}
4471
4472
4473static void
4474wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
4475 unsigned int freq, const u8 *dst,
4476 const u8 *src, const u8 *bssid,
4477 const u8 *data, size_t data_len,
4478 enum offchannel_send_action_result result)
4479{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004480 const char *res_txt;
4481
4482 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
4483 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
4484 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004485 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
4486 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07004487 freq, MAC2STR(dst), res_txt);
4488 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
4489 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004490 /* TODO: Time out wait for response more quickly in error cases? */
4491}
4492
4493
Sunil Ravi89eba102022-09-13 21:04:37 -07004494#ifdef CONFIG_DPP3
4495static int wpas_dpp_start_private_peer_intro(struct wpa_supplicant *wpa_s,
4496 struct wpa_ssid *ssid,
4497 struct wpa_bss *bss)
4498{
4499 struct wpabuf *msg;
4500 unsigned int wait_time;
4501 size_t len;
4502 u8 ver = DPP_VERSION;
4503 int conn_ver;
4504
4505 len = 5 + 5;
4506 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_QUERY, len);
4507 if (!msg)
4508 return -1;
4509
4510 /* Transaction ID */
4511 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4512 wpabuf_put_le16(msg, 1);
4513 wpabuf_put_u8(msg, TRANSACTION_ID);
4514
4515 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4516 if (conn_ver > 0 && ver != conn_ver) {
4517 wpa_printf(MSG_DEBUG,
4518 "DPP: Use Connector version %d instead of current protocol version %d",
4519 conn_ver, ver);
4520 ver = conn_ver;
4521 }
4522
4523 /* Protocol Version */
4524 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4525 wpabuf_put_le16(msg, 1);
4526 wpabuf_put_u8(msg, ver);
4527
4528 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Query", msg);
4529
4530 /* TODO: Timeout on AP response */
4531 wait_time = wpa_s->max_remain_on_chan;
4532 if (wait_time > 2000)
4533 wait_time = 2000;
4534 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4535 MAC2STR(bss->bssid), bss->freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
4536 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4537 broadcast,
4538 wpabuf_head(msg), wpabuf_len(msg),
4539 wait_time, wpas_dpp_tx_introduction_status, 0);
4540 wpabuf_free(msg);
4541
4542 /* Request this connection attempt to terminate - new one will be
4543 * started when network introduction protocol completes */
4544 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4545 wpa_s->dpp_intro_network = ssid;
4546 return 1;
4547}
4548#endif /* CONFIG_DPP3 */
4549
4550
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004551int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4552 struct wpa_bss *bss)
4553{
4554 struct os_time now;
4555 struct wpabuf *msg;
4556 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07004557 const u8 *rsn;
4558 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004559 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004560
4561 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
4562 return 0; /* Not using DPP AKM - continue */
Sunil Ravi7f769292024-07-23 22:21:32 +00004563 rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
Hai Shalom021b0b52019-04-10 11:17:58 -07004564 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
4565 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
4566 return 0; /* AP does not support DPP AKM - continue */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004567 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, wpa_s->own_addr, ssid))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004568 return 0; /* PMKSA exists for DPP AKM - continue */
4569
4570 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4571 !ssid->dpp_csign) {
4572 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4573 "missing %s",
4574 !ssid->dpp_connector ? "Connector" :
4575 (!ssid->dpp_netaccesskey ? "netAccessKey" :
4576 "C-sign-key"));
4577 return -1;
4578 }
4579
4580 os_get_time(&now);
4581
4582 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07004583 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004584 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4585 "netAccessKey expired");
4586 return -1;
4587 }
4588
4589 wpa_printf(MSG_DEBUG,
Sunil Ravi89eba102022-09-13 21:04:37 -07004590 "DPP: Starting %snetwork introduction protocol to derive PMKSA for "
4591 MACSTR,
4592 ssid->dpp_connector_privacy ? "private " : "",
4593 MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07004594 if (wpa_s->wpa_state == WPA_SCANNING)
4595 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004596
Sunil Ravi89eba102022-09-13 21:04:37 -07004597#ifdef CONFIG_DPP3
4598 if (ssid->dpp_connector_privacy)
4599 return wpas_dpp_start_private_peer_intro(wpa_s, ssid, bss);
4600#endif /* CONFIG_DPP3 */
4601
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004602 len = 5 + 4 + os_strlen(ssid->dpp_connector);
4603#ifdef CONFIG_DPP2
4604 len += 5;
4605#endif /* CONFIG_DPP2 */
4606 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004607 if (!msg)
4608 return -1;
4609
Roshan Pius3a1667e2018-07-03 15:17:14 -07004610#ifdef CONFIG_TESTING_OPTIONS
4611 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
4612 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
4613 goto skip_trans_id;
4614 }
4615 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
4616 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
4617 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4618 wpabuf_put_le16(msg, 0);
4619 goto skip_trans_id;
4620 }
4621#endif /* CONFIG_TESTING_OPTIONS */
4622
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004623 /* Transaction ID */
4624 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4625 wpabuf_put_le16(msg, 1);
4626 wpabuf_put_u8(msg, TRANSACTION_ID);
4627
Roshan Pius3a1667e2018-07-03 15:17:14 -07004628#ifdef CONFIG_TESTING_OPTIONS
4629skip_trans_id:
4630 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
4631 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
4632 goto skip_connector;
4633 }
4634 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
4635 char *connector;
4636
4637 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
4638 connector = dpp_corrupt_connector_signature(
4639 ssid->dpp_connector);
4640 if (!connector) {
4641 wpabuf_free(msg);
4642 return -1;
4643 }
4644 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4645 wpabuf_put_le16(msg, os_strlen(connector));
4646 wpabuf_put_str(msg, connector);
4647 os_free(connector);
4648 goto skip_connector;
4649 }
4650#endif /* CONFIG_TESTING_OPTIONS */
4651
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004652 /* DPP Connector */
4653 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4654 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
4655 wpabuf_put_str(msg, ssid->dpp_connector);
4656
Roshan Pius3a1667e2018-07-03 15:17:14 -07004657#ifdef CONFIG_TESTING_OPTIONS
4658skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004659 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
4660 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
4661 goto skip_proto_ver;
4662 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004663#endif /* CONFIG_TESTING_OPTIONS */
4664
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004665#ifdef CONFIG_DPP2
4666 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004667 u8 ver = DPP_VERSION;
4668#ifdef CONFIG_DPP3
4669 int conn_ver;
4670
4671 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4672 if (conn_ver > 0 && ver != conn_ver) {
4673 wpa_printf(MSG_DEBUG,
4674 "DPP: Use Connector version %d instead of current protocol version %d",
4675 conn_ver, ver);
4676 ver = conn_ver;
4677 }
4678#endif /* CONFIG_DPP3 */
4679
4680#ifdef CONFIG_TESTING_OPTIONS
4681 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
4682 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
4683 ver = 1;
4684 }
4685#endif /* CONFIG_TESTING_OPTIONS */
4686
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004687 /* Protocol Version */
4688 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4689 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004690 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004691 }
4692#endif /* CONFIG_DPP2 */
4693
Hai Shaloma20dcd72022-02-04 13:43:00 -08004694#ifdef CONFIG_TESTING_OPTIONS
4695skip_proto_ver:
4696#endif /* CONFIG_TESTING_OPTIONS */
4697
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004698 /* TODO: Timeout on AP response */
4699 wait_time = wpa_s->max_remain_on_chan;
4700 if (wait_time > 2000)
4701 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004702 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4703 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004704 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4705 broadcast,
4706 wpabuf_head(msg), wpabuf_len(msg),
4707 wait_time, wpas_dpp_tx_introduction_status, 0);
4708 wpabuf_free(msg);
4709
4710 /* Request this connection attempt to terminate - new one will be
4711 * started when network introduction protocol completes */
4712 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4713 wpa_s->dpp_intro_network = ssid;
4714 return 1;
4715}
4716
4717
4718int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
4719{
4720 struct dpp_bootstrap_info *own_bi;
4721 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07004722#ifdef CONFIG_DPP3
4723 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
4724#else /* CONFIG_DPP3 */
4725 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
4726#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004727 int tcp_port = DPP_TCP_PORT;
4728 struct hostapd_ip_addr *ipaddr = NULL;
4729#ifdef CONFIG_DPP2
4730 struct hostapd_ip_addr ipaddr_buf;
4731 char *addr;
4732
4733 pos = os_strstr(cmd, " tcp_port=");
4734 if (pos) {
4735 pos += 10;
4736 tcp_port = atoi(pos);
4737 }
4738
4739 addr = get_param(cmd, " tcp_addr=");
4740 if (addr) {
4741 int res;
4742
4743 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
4744 os_free(addr);
4745 if (res)
4746 return -1;
4747 ipaddr = &ipaddr_buf;
4748 }
4749#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004750
4751 pos = os_strstr(cmd, " own=");
4752 if (!pos)
4753 return -1;
4754 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07004755 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004756 if (!own_bi) {
4757 wpa_printf(MSG_DEBUG,
4758 "DPP: Identified bootstrap info not found");
4759 return -1;
4760 }
4761 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
4762 wpa_printf(MSG_DEBUG,
4763 "DPP: Identified bootstrap info not for PKEX");
4764 return -1;
4765 }
4766 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004767 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004768
4769 os_free(wpa_s->dpp_pkex_identifier);
4770 wpa_s->dpp_pkex_identifier = NULL;
4771 pos = os_strstr(cmd, " identifier=");
4772 if (pos) {
4773 pos += 12;
4774 end = os_strchr(pos, ' ');
4775 if (!end)
4776 return -1;
4777 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
4778 if (!wpa_s->dpp_pkex_identifier)
4779 return -1;
4780 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
4781 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
4782 }
4783
4784 pos = os_strstr(cmd, " code=");
4785 if (!pos)
4786 return -1;
4787 os_free(wpa_s->dpp_pkex_code);
4788 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
4789 if (!wpa_s->dpp_pkex_code)
4790 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004791 wpa_s->dpp_pkex_code_len = os_strlen(wpa_s->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004792
Sunil Ravia04bd252022-05-02 22:54:18 -07004793 pos = os_strstr(cmd, " ver=");
4794 if (pos) {
4795 int v;
4796
4797 pos += 5;
4798 v = atoi(pos);
4799 if (v == 1)
4800 ver = PKEX_VER_ONLY_1;
4801 else if (v == 2)
4802 ver = PKEX_VER_ONLY_2;
4803 else
4804 return -1;
4805 }
4806 wpa_s->dpp_pkex_ver = ver;
4807
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004808 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004809 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004810 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004811 } else {
4812#ifdef CONFIG_DPP2
4813 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
4814 wpa_s->dpp_pkex_code,
4815 wpa_s->dpp_pkex_identifier);
4816#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004817 }
4818
4819 /* TODO: Support multiple PKEX info entries */
4820
4821 os_free(wpa_s->dpp_pkex_auth_cmd);
4822 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
4823
4824 return 1;
4825}
4826
4827
4828int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
4829{
4830 unsigned int id_val;
4831
4832 if (os_strcmp(id, "*") == 0) {
4833 id_val = 0;
4834 } else {
4835 id_val = atoi(id);
4836 if (id_val == 0)
4837 return -1;
4838 }
4839
Sunil Ravi89eba102022-09-13 21:04:37 -07004840 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004841 return -1;
4842
4843 /* TODO: Support multiple PKEX entries */
4844 os_free(wpa_s->dpp_pkex_code);
4845 wpa_s->dpp_pkex_code = NULL;
4846 os_free(wpa_s->dpp_pkex_identifier);
4847 wpa_s->dpp_pkex_identifier = NULL;
4848 os_free(wpa_s->dpp_pkex_auth_cmd);
4849 wpa_s->dpp_pkex_auth_cmd = NULL;
4850 wpa_s->dpp_pkex_bi = NULL;
4851 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
4852 dpp_pkex_free(wpa_s->dpp_pkex);
4853 wpa_s->dpp_pkex = NULL;
4854 return 0;
4855}
4856
4857
Roshan Pius3a1667e2018-07-03 15:17:14 -07004858void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
4859{
Sunil Ravia04bd252022-05-02 22:54:18 -07004860 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07004861 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004862 dpp_auth_deinit(wpa_s->dpp_auth);
4863 wpa_s->dpp_auth = NULL;
4864 dpp_pkex_free(wpa_s->dpp_pkex);
4865 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004866 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004867 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
4868 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
Sunil Ravi89eba102022-09-13 21:04:37 -07004869#ifdef CONFIG_DPP3
4870 wpas_dpp_push_button_stop(wpa_s);
4871#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004872}
4873
4874
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004875int wpas_dpp_init(struct wpa_supplicant *wpa_s)
4876{
Hai Shalom81f62d82019-07-22 12:10:00 -07004877 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004878 u8 adv_proto_id[7];
4879
4880 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
4881 adv_proto_id[1] = 5;
4882 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
4883 adv_proto_id[5] = DPP_OUI_TYPE;
4884 adv_proto_id[6] = 0x01;
4885
4886 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
4887 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
4888 wpas_dpp_gas_status_handler, wpa_s) < 0)
4889 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004890
4891 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07004892 config.cb_ctx = wpa_s;
4893#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004894 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07004895#endif /* CONFIG_DPP2 */
4896 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07004897 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004898}
4899
4900
4901void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
4902{
4903#ifdef CONFIG_TESTING_OPTIONS
4904 os_free(wpa_s->dpp_config_obj_override);
4905 wpa_s->dpp_config_obj_override = NULL;
4906 os_free(wpa_s->dpp_discovery_override);
4907 wpa_s->dpp_discovery_override = NULL;
4908 os_free(wpa_s->dpp_groups_override);
4909 wpa_s->dpp_groups_override = NULL;
4910 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
4911#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07004912 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004913 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004914 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004915 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004916 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004917 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
4918 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004919 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4920 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004921 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
Sunil Ravi99c035e2024-07-12 01:42:03 +00004922 eloop_cancel_timeout(wpas_dpp_tx_auth_resp_roc_timeout, wpa_s, NULL);
4923 eloop_cancel_timeout(wpas_dpp_neg_freq_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004924#ifdef CONFIG_DPP2
4925 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07004926 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
4927 wpa_s, NULL);
4928 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004929 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
4930 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004931 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004932 eloop_cancel_timeout(wpas_dpp_connected_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004933 dpp_pfs_free(wpa_s->dpp_pfs);
4934 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004935 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004936 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4937 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07004938#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07004939#ifdef CONFIG_DPP3
4940 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
4941#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004942 offchannel_send_action_done(wpa_s);
4943 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004944 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004945 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004946 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
4947 os_free(wpa_s->dpp_configurator_params);
4948 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07004949 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004950}
Hai Shalom81f62d82019-07-22 12:10:00 -07004951
4952
Hai Shaloma20dcd72022-02-04 13:43:00 -08004953static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
4954 struct dpp_authentication *auth, bool tcp)
4955{
4956 struct wpabuf *resp;
4957
4958 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
4959 auth->e_netrole, true);
4960 if (!resp)
4961 return -1;
4962
4963 if (tcp) {
4964 auth->conf_resp_tcp = resp;
4965 return 0;
4966 }
4967
4968 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4969 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
4970 resp) < 0) {
4971 wpa_printf(MSG_DEBUG,
4972 "DPP: Could not find pending GAS response");
4973 wpabuf_free(resp);
4974 return -1;
4975 }
4976 auth->conf_resp = resp;
4977 return 0;
4978}
4979
4980
4981int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
4982{
4983 int peer;
4984 const char *pos;
4985 struct dpp_authentication *auth = wpa_s->dpp_auth;
4986 bool tcp = false;
4987
4988 pos = os_strstr(cmd, " peer=");
4989 if (!pos)
4990 return -1;
4991 peer = atoi(pos + 6);
4992#ifdef CONFIG_DPP2
4993 if (!auth || !auth->waiting_config ||
4994 (auth->peer_bi &&
4995 (unsigned int) peer != auth->peer_bi->id)) {
4996 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4997 tcp = true;
4998 }
4999#endif /* CONFIG_DPP2 */
5000
5001 if (!auth || !auth->waiting_config) {
5002 wpa_printf(MSG_DEBUG,
5003 "DPP: No authentication exchange waiting for configuration information");
5004 return -1;
5005 }
5006
5007 if ((!auth->peer_bi ||
5008 (unsigned int) peer != auth->peer_bi->id) &&
5009 (!auth->tmp_peer_bi ||
5010 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5011 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5012 return -1;
5013 }
5014
5015 pos = os_strstr(cmd, " comeback=");
5016 if (pos) {
5017 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
5018 NULL);
5019 gas_server_set_comeback_delay(wpa_s->gas_server,
5020 auth->config_resp_ctx,
5021 atoi(pos + 10));
5022 return 0;
5023 }
5024
5025 if (dpp_set_configurator(auth, cmd) < 0)
5026 return -1;
5027
5028 auth->use_config_query = false;
5029 auth->waiting_config = false;
5030 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5031}
5032
5033
Hai Shalom81f62d82019-07-22 12:10:00 -07005034#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07005035
Hai Shalom81f62d82019-07-22 12:10:00 -07005036int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
5037{
5038 struct dpp_controller_config config;
5039 const char *pos;
5040
5041 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005042 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07005043 config.netrole = DPP_NETROLE_STA;
5044 config.msg_ctx = wpa_s;
5045 config.cb_ctx = wpa_s;
5046 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005047 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07005048 if (cmd) {
5049 pos = os_strstr(cmd, " tcp_port=");
5050 if (pos) {
5051 pos += 10;
5052 config.tcp_port = atoi(pos);
5053 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005054
5055 pos = os_strstr(cmd, " role=");
5056 if (pos) {
5057 pos += 6;
5058 if (os_strncmp(pos, "configurator", 12) == 0)
5059 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
5060 else if (os_strncmp(pos, "enrollee", 8) == 0)
5061 config.allowed_roles = DPP_CAPAB_ENROLLEE;
5062 else if (os_strncmp(pos, "either", 6) == 0)
5063 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
5064 DPP_CAPAB_ENROLLEE;
5065 else
5066 return -1;
5067 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005068
5069 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07005070 }
5071 config.configurator_params = wpa_s->dpp_configurator_params;
5072 return dpp_controller_start(wpa_s->dpp, &config);
5073}
Hai Shalomfdcde762020-04-02 11:19:20 -07005074
5075
5076static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
5077
5078static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
5079{
5080 struct wpa_supplicant *wpa_s = eloop_ctx;
5081
5082 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
5083 offchannel_send_action_done(wpa_s);
5084 wpas_dpp_chirp_next(wpa_s, NULL);
5085}
5086
5087
5088static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
5089 unsigned int freq, const u8 *dst,
5090 const u8 *src, const u8 *bssid,
5091 const u8 *data, size_t data_len,
5092 enum offchannel_send_action_result result)
5093{
5094 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5095 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
5096 wpa_s->dpp_chirp_freq);
5097 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
5098 wpa_s, NULL) < 0)
5099 wpas_dpp_chirp_stop(wpa_s);
5100 return;
5101 }
5102
5103 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
5104 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
5105 wpa_s, NULL) < 0)
5106 wpas_dpp_chirp_stop(wpa_s);
5107}
5108
5109
5110static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
5111{
Hai Shalom899fcc72020-10-19 14:38:18 -07005112 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005113 int type;
5114
5115 msg = wpa_s->dpp_presence_announcement;
5116 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
5117 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07005118 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
5119
5120 if (ssid && wpa_s->dpp_reconfig_id &&
5121 wpa_config_get_network(wpa_s->conf,
5122 wpa_s->dpp_reconfig_ssid_id) ==
5123 ssid) {
5124 announce = dpp_build_reconfig_announcement(
5125 ssid->dpp_csign,
5126 ssid->dpp_csign_len,
5127 ssid->dpp_netaccesskey,
5128 ssid->dpp_netaccesskey_len,
5129 wpa_s->dpp_reconfig_id);
5130 msg = announce;
5131 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005132 if (!msg)
5133 return;
5134 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
5135 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005136 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
5137 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005138 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07005139 if (offchannel_send_action(
5140 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
5141 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005142 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07005143 2000, wpas_dpp_chirp_tx_status, 0) < 0)
5144 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07005145
5146 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07005147}
5148
5149
Sunil Ravi89eba102022-09-13 21:04:37 -07005150static int * wpas_dpp_presence_ann_channels(struct wpa_supplicant *wpa_s,
5151 struct dpp_bootstrap_info *bi)
Hai Shalomfdcde762020-04-02 11:19:20 -07005152{
Hai Shalomfdcde762020-04-02 11:19:20 -07005153 unsigned int i;
5154 struct hostapd_hw_modes *mode;
5155 int c;
5156 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005157 bool chan6 = wpa_s->hw.modes == NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005158 int *freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07005159
5160 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005161 if (bi) {
5162 for (i = 0; i < bi->num_freq; i++)
Sunil Ravi89eba102022-09-13 21:04:37 -07005163 int_array_add_unique(&freqs, bi->freq[i]);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005164 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005165
5166 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07005167 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005168 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07005169 if (mode) {
5170 for (c = 0; c < mode->num_channels; c++) {
5171 struct hostapd_channel_data *chan = &mode->channels[c];
5172
5173 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
5174 chan->freq != 2437)
5175 continue;
5176 chan6 = true;
5177 break;
5178 }
5179 }
5180 if (chan6)
Sunil Ravi89eba102022-09-13 21:04:37 -07005181 int_array_add_unique(&freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07005182
5183 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005184 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005185 if (mode) {
5186 int chan44 = 0, chan149 = 0;
5187
5188 for (c = 0; c < mode->num_channels; c++) {
5189 struct hostapd_channel_data *chan = &mode->channels[c];
5190
5191 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
5192 HOSTAPD_CHAN_RADAR))
5193 continue;
5194 if (chan->freq == 5220)
5195 chan44 = 1;
5196 if (chan->freq == 5745)
5197 chan149 = 1;
5198 }
5199 if (chan149)
Sunil Ravi89eba102022-09-13 21:04:37 -07005200 int_array_add_unique(&freqs, 5745);
Hai Shalomfdcde762020-04-02 11:19:20 -07005201 else if (chan44)
Sunil Ravi89eba102022-09-13 21:04:37 -07005202 int_array_add_unique(&freqs, 5220);
Hai Shalomfdcde762020-04-02 11:19:20 -07005203 }
5204
5205 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005206 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005207 if (mode) {
5208 for (c = 0; c < mode->num_channels; c++) {
5209 struct hostapd_channel_data *chan = &mode->channels[c];
5210
5211 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
5212 HOSTAPD_CHAN_RADAR)) ||
5213 chan->freq != 60480)
5214 continue;
Sunil Ravi89eba102022-09-13 21:04:37 -07005215 int_array_add_unique(&freqs, 60480);
Hai Shalomfdcde762020-04-02 11:19:20 -07005216 break;
5217 }
5218 }
5219
5220 /* Add channels from scan results for APs that advertise Configurator
5221 * Connectivity element */
5222 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5223 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
Sunil Ravi89eba102022-09-13 21:04:37 -07005224 int_array_add_unique(&freqs, bss->freq);
Hai Shalomfdcde762020-04-02 11:19:20 -07005225 }
5226
Sunil Ravi89eba102022-09-13 21:04:37 -07005227 return freqs;
5228}
5229
5230
5231static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
5232 struct wpa_scan_results *scan_res)
5233{
5234 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
5235
5236 if (!bi && !wpa_s->dpp_reconfig_ssid)
5237 return;
5238
5239 wpa_s->dpp_chirp_scan_done = 1;
5240
5241 os_free(wpa_s->dpp_chirp_freqs);
5242 wpa_s->dpp_chirp_freqs = wpas_dpp_presence_ann_channels(wpa_s, bi);
5243
Hai Shalomfdcde762020-04-02 11:19:20 -07005244 if (!wpa_s->dpp_chirp_freqs ||
5245 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
5246 wpas_dpp_chirp_stop(wpa_s);
5247}
5248
5249
5250static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
5251{
5252 struct wpa_supplicant *wpa_s = eloop_ctx;
5253 int i;
5254
5255 if (wpa_s->dpp_chirp_listen)
5256 wpas_dpp_listen_stop(wpa_s);
5257
5258 if (wpa_s->dpp_chirp_freq == 0) {
5259 if (wpa_s->dpp_chirp_round % 4 == 0 &&
5260 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08005261 if (wpas_scan_scheduled(wpa_s)) {
5262 wpa_printf(MSG_DEBUG,
5263 "DPP: Deferring chirp scan because another scan is planned already");
5264 if (eloop_register_timeout(1, 0,
5265 wpas_dpp_chirp_next,
5266 wpa_s, NULL) < 0) {
5267 wpas_dpp_chirp_stop(wpa_s);
5268 return;
5269 }
5270 return;
5271 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005272 wpa_printf(MSG_DEBUG,
5273 "DPP: Update channel list for chirping");
5274 wpa_s->scan_req = MANUAL_SCAN_REQ;
5275 wpa_s->scan_res_handler =
5276 wpas_dpp_chirp_scan_res_handler;
5277 wpa_supplicant_req_scan(wpa_s, 0, 0);
5278 return;
5279 }
5280 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
5281 wpa_s->dpp_chirp_round++;
5282 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
5283 wpa_s->dpp_chirp_round);
5284 } else {
5285 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
5286 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
5287 break;
5288 if (!wpa_s->dpp_chirp_freqs[i]) {
5289 wpa_printf(MSG_DEBUG,
5290 "DPP: Previous chirp freq %d not found",
5291 wpa_s->dpp_chirp_freq);
5292 return;
5293 }
5294 i++;
5295 if (wpa_s->dpp_chirp_freqs[i]) {
5296 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
5297 } else {
5298 wpa_s->dpp_chirp_iter--;
5299 if (wpa_s->dpp_chirp_iter <= 0) {
5300 wpa_printf(MSG_DEBUG,
5301 "DPP: Chirping iterations completed");
5302 wpas_dpp_chirp_stop(wpa_s);
5303 return;
5304 }
5305 wpa_s->dpp_chirp_freq = 0;
5306 wpa_s->dpp_chirp_scan_done = 0;
5307 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
5308 wpa_s, NULL) < 0) {
5309 wpas_dpp_chirp_stop(wpa_s);
5310 return;
5311 }
5312 if (wpa_s->dpp_chirp_listen) {
5313 wpa_printf(MSG_DEBUG,
5314 "DPP: Listen on %d MHz during chirp 30 second wait",
5315 wpa_s->dpp_chirp_listen);
5316 wpas_dpp_listen_start(wpa_s,
5317 wpa_s->dpp_chirp_listen);
5318 } else {
5319 wpa_printf(MSG_DEBUG,
5320 "DPP: Wait 30 seconds before starting the next chirping round");
5321 }
5322 return;
5323 }
5324 }
5325
5326 wpas_dpp_chirp_start(wpa_s);
5327}
5328
5329
5330int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
5331{
5332 const char *pos;
5333 int iter = 1, listen_freq = 0;
5334 struct dpp_bootstrap_info *bi;
5335
5336 pos = os_strstr(cmd, " own=");
5337 if (!pos)
5338 return -1;
5339 pos += 5;
5340 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
5341 if (!bi) {
5342 wpa_printf(MSG_DEBUG,
5343 "DPP: Identified bootstrap info not found");
5344 return -1;
5345 }
5346
5347 pos = os_strstr(cmd, " iter=");
5348 if (pos) {
5349 iter = atoi(pos + 6);
5350 if (iter <= 0)
5351 return -1;
5352 }
5353
5354 pos = os_strstr(cmd, " listen=");
5355 if (pos) {
5356 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005357 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005358 return -1;
5359 }
5360
5361 wpas_dpp_chirp_stop(wpa_s);
5362 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005363 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07005364 wpa_s->dpp_qr_mutual = 0;
5365 wpa_s->dpp_chirp_bi = bi;
5366 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
5367 if (!wpa_s->dpp_presence_announcement)
5368 return -1;
5369 wpa_s->dpp_chirp_iter = iter;
5370 wpa_s->dpp_chirp_round = 0;
5371 wpa_s->dpp_chirp_scan_done = 0;
5372 wpa_s->dpp_chirp_listen = listen_freq;
5373
5374 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5375}
5376
5377
5378void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
5379{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005380 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07005381 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005382 offchannel_send_action_done(wpa_s);
5383 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
5384 }
5385 wpa_s->dpp_chirp_bi = NULL;
5386 wpabuf_free(wpa_s->dpp_presence_announcement);
5387 wpa_s->dpp_presence_announcement = NULL;
5388 if (wpa_s->dpp_chirp_listen)
5389 wpas_dpp_listen_stop(wpa_s);
5390 wpa_s->dpp_chirp_listen = 0;
5391 wpa_s->dpp_chirp_freq = 0;
5392 os_free(wpa_s->dpp_chirp_freqs);
5393 wpa_s->dpp_chirp_freqs = NULL;
5394 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
5395 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
5396 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
5397 wpas_abort_ongoing_scan(wpa_s);
5398 wpa_s->scan_res_handler = NULL;
5399 }
5400}
5401
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005402
Hai Shalom899fcc72020-10-19 14:38:18 -07005403int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005404{
Hai Shalom899fcc72020-10-19 14:38:18 -07005405 struct wpa_ssid *ssid;
5406 int iter = 1;
5407 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005408
Hai Shalom899fcc72020-10-19 14:38:18 -07005409 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
5410 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
5411 !ssid->dpp_csign) {
5412 wpa_printf(MSG_DEBUG,
5413 "DPP: Not a valid network profile for reconfiguration");
5414 return -1;
5415 }
5416
5417 pos = os_strstr(cmd, " iter=");
5418 if (pos) {
5419 iter = atoi(pos + 6);
5420 if (iter <= 0)
5421 return -1;
5422 }
5423
5424 if (wpa_s->dpp_auth) {
5425 wpa_printf(MSG_DEBUG,
5426 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
5427 return -1;
5428 }
5429
5430 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
5431 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
5432 ssid->dpp_csign_len,
5433 ssid->dpp_pp_key,
5434 ssid->dpp_pp_key_len);
5435 if (!wpa_s->dpp_reconfig_id) {
5436 wpa_printf(MSG_DEBUG,
5437 "DPP: Failed to generate E-id for reconfiguration");
5438 return -1;
5439 }
5440 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
5441 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
5442 wpa_s->own_disconnect_req = 1;
5443 wpa_supplicant_deauthenticate(
5444 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5445 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005446 wpas_dpp_chirp_stop(wpa_s);
5447 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005448 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005449 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005450 wpa_s->dpp_reconfig_ssid = ssid;
5451 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07005452 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005453 wpa_s->dpp_chirp_round = 0;
5454 wpa_s->dpp_chirp_scan_done = 0;
5455 wpa_s->dpp_chirp_listen = 0;
5456
5457 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5458}
5459
Hai Shalom899fcc72020-10-19 14:38:18 -07005460
Hai Shalom899fcc72020-10-19 14:38:18 -07005461int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
5462{
5463 int peer = -1;
5464 const char *pos, *value;
5465 struct dpp_authentication *auth = wpa_s->dpp_auth;
5466 u8 *bin;
5467 size_t bin_len;
5468 struct wpabuf *buf;
5469 bool tcp = false;
5470
5471 pos = os_strstr(cmd, " peer=");
5472 if (pos) {
5473 peer = atoi(pos + 6);
5474 if (!auth || !auth->waiting_cert ||
5475 (auth->peer_bi &&
5476 (unsigned int) peer != auth->peer_bi->id)) {
5477 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5478 tcp = true;
5479 }
5480 }
5481
5482 if (!auth || !auth->waiting_cert) {
5483 wpa_printf(MSG_DEBUG,
5484 "DPP: No authentication exchange waiting for certificate information");
5485 return -1;
5486 }
5487
5488 if (peer >= 0 &&
5489 (!auth->peer_bi ||
5490 (unsigned int) peer != auth->peer_bi->id) &&
5491 (!auth->tmp_peer_bi ||
5492 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5493 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5494 return -1;
5495 }
5496
5497 pos = os_strstr(cmd, " value=");
5498 if (!pos)
5499 return -1;
5500 value = pos + 7;
5501
5502 pos = os_strstr(cmd, " name=");
5503 if (!pos)
5504 return -1;
5505 pos += 6;
5506
5507 if (os_strncmp(pos, "status ", 7) == 0) {
5508 auth->force_conf_resp_status = atoi(value);
5509 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5510 }
5511
5512 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
5513 os_free(auth->trusted_eap_server_name);
5514 auth->trusted_eap_server_name = os_strdup(value);
5515 return auth->trusted_eap_server_name ? 0 : -1;
5516 }
5517
5518 bin = base64_decode(value, os_strlen(value), &bin_len);
5519 if (!bin)
5520 return -1;
5521 buf = wpabuf_alloc_copy(bin, bin_len);
5522 os_free(bin);
5523
5524 if (os_strncmp(pos, "caCert ", 7) == 0) {
5525 wpabuf_free(auth->cacert);
5526 auth->cacert = buf;
5527 return 0;
5528 }
5529
5530 if (os_strncmp(pos, "certBag ", 8) == 0) {
5531 wpabuf_free(auth->certbag);
5532 auth->certbag = buf;
5533 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5534 }
5535
5536 wpabuf_free(buf);
5537 return -1;
5538}
5539
Hai Shalom81f62d82019-07-22 12:10:00 -07005540#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07005541
5542
5543#ifdef CONFIG_DPP3
5544
5545#define DPP_PB_ANNOUNCE_PER_CHAN 3
5546
5547static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
5548static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
5549
5550
5551static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
5552 unsigned int freq, const u8 *dst,
5553 const u8 *src, const u8 *bssid,
5554 const u8 *data, size_t data_len,
5555 enum offchannel_send_action_result result)
5556{
5557 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5558 wpa_printf(MSG_DEBUG,
5559 "DPP: Failed to send push button announcement on %d MHz",
5560 freq);
5561 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
5562 wpa_s, NULL) < 0)
5563 wpas_dpp_push_button_stop(wpa_s);
5564 return;
5565 }
5566
5567 wpa_printf(MSG_DEBUG, "DPP: Push button announcement on %d MHz sent",
5568 freq);
5569 if (wpa_s->dpp_pb_discovery_done) {
5570 wpa_s->dpp_pb_announce_count = 0;
5571 wpa_printf(MSG_DEBUG,
5572 "DPP: Wait for push button announcement response and PKEX on %d MHz",
5573 freq);
5574 if (eloop_register_timeout(0, 500000, wpas_dpp_pb_next,
5575 wpa_s, NULL) < 0)
5576 wpas_dpp_push_button_stop(wpa_s);
5577 return;
5578 } else if (wpa_s->dpp_pb_announce_count >= DPP_PB_ANNOUNCE_PER_CHAN) {
5579 wpa_printf(MSG_DEBUG,
5580 "DPP: Wait for push button announcement response on %d MHz",
5581 freq);
5582 if (eloop_register_timeout(0, 50000, wpas_dpp_pb_next,
5583 wpa_s, NULL) < 0)
5584 wpas_dpp_push_button_stop(wpa_s);
5585 return;
5586 }
5587
5588 if (wpas_dpp_pb_announce(wpa_s, freq) < 0)
5589 wpas_dpp_push_button_stop(wpa_s);
5590}
5591
5592
5593static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq)
5594{
5595 struct wpabuf *msg;
5596 int type;
5597
5598 msg = wpa_s->dpp_pb_announcement;
5599 if (!msg)
5600 return -1;
5601
5602 wpa_s->dpp_pb_announce_count++;
5603 wpa_printf(MSG_DEBUG,
5604 "DPP: Send push button announcement %d/%d (%d MHz)",
5605 wpa_s->dpp_pb_announce_count, DPP_PB_ANNOUNCE_PER_CHAN,
5606 freq);
5607
5608 type = DPP_PA_PB_PRESENCE_ANNOUNCEMENT;
5609 if (wpa_s->dpp_pb_announce_count == 1)
5610 wpa_msg(wpa_s, MSG_INFO,
5611 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
5612 MAC2STR(broadcast), freq, type);
5613 if (offchannel_send_action(
5614 wpa_s, freq, broadcast, wpa_s->own_addr, broadcast,
5615 wpabuf_head(msg), wpabuf_len(msg),
5616 1000, wpas_dpp_pb_tx_status, 0) < 0)
5617 return -1;
5618
5619 return 0;
5620}
5621
5622
5623static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx)
5624{
5625 struct wpa_supplicant *wpa_s = eloop_ctx;
5626 struct os_reltime now;
5627 int freq;
5628
5629 if (!wpa_s->dpp_pb_freqs)
5630 return;
5631
5632 os_get_reltime(&now);
5633 offchannel_send_action_done(wpa_s);
5634
5635 if (os_reltime_expired(&now, &wpa_s->dpp_pb_time, 100)) {
5636 wpa_printf(MSG_DEBUG, "DPP: Push button wait time expired");
5637 wpas_dpp_push_button_stop(wpa_s);
5638 return;
5639 }
5640
5641 if (wpa_s->dpp_pb_freq_idx >= int_array_len(wpa_s->dpp_pb_freqs)) {
5642 wpa_printf(MSG_DEBUG,
5643 "DPP: Completed push button announcement round");
5644 wpa_s->dpp_pb_freq_idx = 0;
5645 if (wpa_s->dpp_pb_stop_iter > 0) {
5646 wpa_s->dpp_pb_stop_iter--;
5647
5648 if (wpa_s->dpp_pb_stop_iter == 1) {
5649 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5650 "wait for AP/Configurator to allow PKEX to be initiated");
5651 if (eloop_register_timeout(10, 0,
5652 wpas_dpp_pb_next,
5653 wpa_s, NULL) < 0) {
5654 wpas_dpp_push_button_stop(wpa_s);
5655 return;
5656 }
5657 return;
5658 }
5659
5660 if (wpa_s->dpp_pb_stop_iter == 0) {
5661 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5662 "start push button PKEX responder on the discovered channel (%d MHz)",
5663 wpa_s->dpp_pb_resp_freq);
5664 wpa_s->dpp_pb_discovery_done = true;
5665
5666 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
5667
5668 os_free(wpa_s->dpp_pkex_code);
5669 wpa_s->dpp_pkex_code = os_memdup(
5670 wpa_s->dpp_pb_c_nonce,
5671 wpa_s->dpp_pb_c_nonce_len);
5672 wpa_s->dpp_pkex_code_len =
5673 wpa_s->dpp_pb_c_nonce_len;
5674
5675 os_free(wpa_s->dpp_pkex_identifier);
5676 wpa_s->dpp_pkex_identifier =
5677 os_strdup("PBPKEX");
5678
5679 if (!wpa_s->dpp_pkex_code ||
5680 !wpa_s->dpp_pkex_identifier) {
5681 wpas_dpp_push_button_stop(wpa_s);
5682 return;
5683 }
5684
5685 wpa_s->dpp_pkex_ver = PKEX_VER_ONLY_2;
5686
5687 os_free(wpa_s->dpp_pkex_auth_cmd);
5688 wpa_s->dpp_pkex_auth_cmd = NULL;
5689 }
5690 }
5691 }
5692
5693 if (wpa_s->dpp_pb_discovery_done)
5694 freq = wpa_s->dpp_pb_resp_freq;
5695 else
5696 freq = wpa_s->dpp_pb_freqs[wpa_s->dpp_pb_freq_idx++];
5697 wpa_s->dpp_pb_announce_count = 0;
5698 if (!wpa_s->dpp_pb_announcement) {
5699 wpa_printf(MSG_DEBUG, "DPP: Push button announcements stopped");
5700 return;
5701 }
5702 if (wpas_dpp_pb_announce(wpa_s, freq) < 0) {
5703 wpas_dpp_push_button_stop(wpa_s);
5704 return;
5705 }
5706}
5707
5708
5709static void wpas_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
5710{
5711 struct wpa_supplicant *wpa_s = eloop_ctx;
5712
5713 wpa_printf(MSG_DEBUG,
5714 "DPP: Active push button Configurator mode expired");
5715 wpas_dpp_push_button_stop(wpa_s);
5716}
5717
5718
5719static int wpas_dpp_push_button_configurator(struct wpa_supplicant *wpa_s,
5720 const char *cmd)
5721{
5722 wpa_s->dpp_pb_configurator = true;
5723 wpa_s->dpp_pb_announce_time.sec = 0;
5724 wpa_s->dpp_pb_announce_time.usec = 0;
5725 str_clear_free(wpa_s->dpp_pb_cmd);
5726 wpa_s->dpp_pb_cmd = NULL;
5727 if (cmd) {
5728 wpa_s->dpp_pb_cmd = os_strdup(cmd);
5729 if (!wpa_s->dpp_pb_cmd)
5730 return -1;
5731 }
5732 eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
5733 wpa_s, NULL);
5734
Sunil Ravi99c035e2024-07-12 01:42:03 +00005735 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS "started");
Sunil Ravi89eba102022-09-13 21:04:37 -07005736 return 0;
5737}
5738
5739
5740static void wpas_dpp_pb_scan_res_handler(struct wpa_supplicant *wpa_s,
5741 struct wpa_scan_results *scan_res)
5742{
5743 if (!wpa_s->dpp_pb_time.sec && !wpa_s->dpp_pb_time.usec)
5744 return;
5745
5746 os_free(wpa_s->dpp_pb_freqs);
5747 wpa_s->dpp_pb_freqs = wpas_dpp_presence_ann_channels(wpa_s, NULL);
5748
5749 wpa_printf(MSG_DEBUG, "DPP: Scan completed for PB discovery");
5750 if (!wpa_s->dpp_pb_freqs ||
5751 eloop_register_timeout(0, 0, wpas_dpp_pb_next, wpa_s, NULL) < 0)
5752 wpas_dpp_push_button_stop(wpa_s);
5753}
5754
5755
5756int wpas_dpp_push_button(struct wpa_supplicant *wpa_s, const char *cmd)
5757{
5758 int res;
5759
5760 if (!wpa_s->dpp)
5761 return -1;
5762 wpas_dpp_push_button_stop(wpa_s);
5763 wpas_dpp_stop(wpa_s);
5764 wpas_dpp_chirp_stop(wpa_s);
5765
5766 os_get_reltime(&wpa_s->dpp_pb_time);
5767
5768 if (cmd &&
5769 (os_strstr(cmd, " role=configurator") ||
5770 os_strstr(cmd, " conf=")))
5771 return wpas_dpp_push_button_configurator(wpa_s, cmd);
5772
5773 wpa_s->dpp_pb_configurator = false;
5774
5775 wpa_s->dpp_pb_freq_idx = 0;
5776
5777 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
5778 if (res < 0)
5779 return -1;
5780 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
5781 if (!wpa_s->dpp_pb_bi)
5782 return -1;
5783
5784 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
5785 wpa_s->dpp_netrole = DPP_NETROLE_STA;
5786 wpa_s->dpp_qr_mutual = 0;
5787 wpa_s->dpp_pb_announcement =
5788 dpp_build_pb_announcement(wpa_s->dpp_pb_bi);
5789 if (!wpa_s->dpp_pb_announcement)
5790 return -1;
5791
5792 wpa_printf(MSG_DEBUG,
5793 "DPP: Scan to create channel list for PB discovery");
5794 wpa_s->scan_req = MANUAL_SCAN_REQ;
5795 wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
5796 wpa_supplicant_req_scan(wpa_s, 0, 0);
Sunil Ravi99c035e2024-07-12 01:42:03 +00005797 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS "started");
Sunil Ravi89eba102022-09-13 21:04:37 -07005798 return 0;
5799}
5800
5801
5802void wpas_dpp_push_button_stop(struct wpa_supplicant *wpa_s)
5803{
5804 if (!wpa_s->dpp)
5805 return;
5806 os_free(wpa_s->dpp_pb_freqs);
5807 wpa_s->dpp_pb_freqs = NULL;
5808 wpabuf_free(wpa_s->dpp_pb_announcement);
5809 wpa_s->dpp_pb_announcement = NULL;
5810 if (wpa_s->dpp_pb_bi) {
5811 char id[20];
5812
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005813 if (wpa_s->dpp_pb_bi == wpa_s->dpp_pkex_bi)
5814 wpa_s->dpp_pkex_bi = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005815 os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
5816 dpp_bootstrap_remove(wpa_s->dpp, id);
5817 wpa_s->dpp_pb_bi = NULL;
5818 if (!wpa_s->dpp_pb_result_indicated) {
5819 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5820 wpa_s->dpp_pb_result_indicated = true;
5821 }
5822 }
5823
5824 wpa_s->dpp_pb_resp_freq = 0;
5825 wpa_s->dpp_pb_stop_iter = 0;
5826 wpa_s->dpp_pb_discovery_done = false;
5827 os_free(wpa_s->dpp_pb_cmd);
5828 wpa_s->dpp_pb_cmd = NULL;
5829
5830 eloop_cancel_timeout(wpas_dpp_pb_next, wpa_s, NULL);
5831 eloop_cancel_timeout(wpas_dpp_push_button_expire, wpa_s, NULL);
5832 if (wpas_dpp_pb_active(wpa_s)) {
5833 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
5834 if (!wpa_s->dpp_pb_result_indicated)
5835 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5836 }
5837 wpa_s->dpp_pb_time.sec = 0;
5838 wpa_s->dpp_pb_time.usec = 0;
5839 dpp_pkex_free(wpa_s->dpp_pkex);
5840 wpa_s->dpp_pkex = NULL;
5841 os_free(wpa_s->dpp_pkex_auth_cmd);
5842 wpa_s->dpp_pkex_auth_cmd = NULL;
5843
5844 wpa_s->dpp_pb_result_indicated = false;
5845
5846 str_clear_free(wpa_s->dpp_pb_cmd);
5847 wpa_s->dpp_pb_cmd = NULL;
5848
5849 if (wpa_s->scan_res_handler == wpas_dpp_pb_scan_res_handler) {
5850 wpas_abort_ongoing_scan(wpa_s);
5851 wpa_s->scan_res_handler = NULL;
5852 }
5853}
5854
5855#endif /* CONFIG_DPP3 */