blob: e223450c03fc732222bdfa8d1a345534ba2bfb91 [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"
Shivani Baranwalc58b6092022-12-01 11:17:24 +053032#include "aidl/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
Hai Shalomc3565922019-10-28 11:58:20 -07001436 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001437 if (dpp_akm_dpp(conf->akm)) {
1438 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1439 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1440 }
Hai Shalomc3565922019-10-28 11:58:20 -07001441 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001442 if (!ssid->dpp_connector)
1443 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07001444
1445 ssid->dpp_connector_privacy =
1446 wpa_s->conf->dpp_connector_privacy_default;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001447 }
1448
Hai Shalomc3565922019-10-28 11:58:20 -07001449 if (conf->c_sign_key) {
1450 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001451 if (!ssid->dpp_csign)
1452 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001453 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1454 wpabuf_len(conf->c_sign_key));
1455 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001456 }
1457
Hai Shalom899fcc72020-10-19 14:38:18 -07001458 if (conf->pp_key) {
1459 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1460 if (!ssid->dpp_pp_key)
1461 goto fail;
1462 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1463 wpabuf_len(conf->pp_key));
1464 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1465 }
1466
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001467 if (auth->net_access_key) {
1468 ssid->dpp_netaccesskey =
1469 os_malloc(wpabuf_len(auth->net_access_key));
1470 if (!ssid->dpp_netaccesskey)
1471 goto fail;
1472 os_memcpy(ssid->dpp_netaccesskey,
1473 wpabuf_head(auth->net_access_key),
1474 wpabuf_len(auth->net_access_key));
1475 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1476 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1477 }
1478
Hai Shalomc3565922019-10-28 11:58:20 -07001479 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1480 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001481 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001482 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001483 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001484 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1485 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001486 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001487 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1488 WPA_KEY_MGMT_FT_SAE;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001489 if (dpp_akm_psk(conf->akm))
1490 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1491 else
1492 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalomc3565922019-10-28 11:58:20 -07001493 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001494 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001495 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001496 goto fail;
1497 wpa_config_update_psk(ssid);
1498 ssid->export_keys = 1;
1499 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001500 ssid->psk_set = conf->psk_set;
1501 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001502 }
1503 }
1504
Hai Shalom899fcc72020-10-19 14:38:18 -07001505#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1506 if (conf->akm == DPP_AKM_DOT1X) {
1507 int i;
1508 char name[100], blobname[128];
1509 struct wpa_config_blob *blob;
1510
1511 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1512 WPA_KEY_MGMT_IEEE8021X_SHA256 |
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001513 WPA_KEY_MGMT_IEEE8021X_SHA384;
Hai Shalom899fcc72020-10-19 14:38:18 -07001514 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1515
1516 if (conf->cacert) {
1517 /* caCert is DER-encoded X.509v3 certificate for the
1518 * server certificate if that is different from the
1519 * trust root included in certBag. */
1520 /* TODO: ssid->eap.cert.ca_cert */
1521 }
1522
1523 if (conf->certs) {
1524 for (i = 0; ; i++) {
1525 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1526 i);
1527 if (!wpa_config_get_blob(wpa_s->conf, name))
1528 break;
1529 }
1530
1531 blob = os_zalloc(sizeof(*blob));
1532 if (!blob)
1533 goto fail;
1534 blob->len = wpabuf_len(conf->certs);
1535 blob->name = os_strdup(name);
1536 blob->data = os_malloc(blob->len);
1537 if (!blob->name || !blob->data) {
1538 wpa_config_free_blob(blob);
1539 goto fail;
1540 }
1541 os_memcpy(blob->data, wpabuf_head(conf->certs),
1542 blob->len);
1543 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1544 name);
1545 wpa_config_set_blob(wpa_s->conf, blob);
1546 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1547 name);
1548 ssid->eap.cert.client_cert = os_strdup(blobname);
1549 if (!ssid->eap.cert.client_cert)
1550 goto fail;
1551
1552 /* TODO: ssid->eap.identity from own certificate */
1553 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1554 0) < 0)
1555 goto fail;
1556 }
1557
1558 if (auth->priv_key) {
1559 for (i = 0; ; i++) {
1560 os_snprintf(name, sizeof(name), "dpp-key-%d",
1561 i);
1562 if (!wpa_config_get_blob(wpa_s->conf, name))
1563 break;
1564 }
1565
1566 blob = os_zalloc(sizeof(*blob));
1567 if (!blob)
1568 goto fail;
1569 blob->len = wpabuf_len(auth->priv_key);
1570 blob->name = os_strdup(name);
1571 blob->data = os_malloc(blob->len);
1572 if (!blob->name || !blob->data) {
1573 wpa_config_free_blob(blob);
1574 goto fail;
1575 }
1576 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1577 blob->len);
1578 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1579 name);
1580 wpa_config_set_blob(wpa_s->conf, blob);
1581 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1582 name);
1583 ssid->eap.cert.private_key = os_strdup(blobname);
1584 if (!ssid->eap.cert.private_key)
1585 goto fail;
1586 }
1587
1588 if (conf->server_name) {
1589 ssid->eap.cert.domain_suffix_match =
1590 os_strdup(conf->server_name);
1591 if (!ssid->eap.cert.domain_suffix_match)
1592 goto fail;
1593 }
1594
1595 /* TODO: Use entCreds::eapMethods */
1596 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1597 goto fail;
1598 }
1599#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1600
Hai Shalomc3565922019-10-28 11:58:20 -07001601 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1602 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1603
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001604 return ssid;
1605fail:
1606 wpas_notify_network_removed(wpa_s, ssid);
1607 wpa_config_remove_network(wpa_s->conf, ssid->id);
1608 return NULL;
1609}
1610
1611
Hai Shalom021b0b52019-04-10 11:17:58 -07001612static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001613 struct dpp_authentication *auth,
1614 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001615{
1616 struct wpa_ssid *ssid;
1617
1618 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001619 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001620
Hai Shalomc3565922019-10-28 11:58:20 -07001621 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001622 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001623 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001624
1625 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001626
Sunil Ravi546a7b52022-08-26 22:06:04 +00001627 wpas_notify_dpp_config_received(wpa_s, ssid, auth->conn_status_requested ? 1 : 0);
Hai Shalom59532852018-12-07 10:32:58 -08001628
Hai Shalom021b0b52019-04-10 11:17:58 -07001629 if (wpa_s->conf->dpp_config_processing == 2)
1630 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001631
Hai Shalom021b0b52019-04-10 11:17:58 -07001632#ifndef CONFIG_NO_CONFIG_WRITE
1633 if (wpa_s->conf->update_config &&
1634 wpa_config_write(wpa_s->confname, wpa_s->conf))
1635 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1636#endif /* CONFIG_NO_CONFIG_WRITE */
1637
Hai Shalomc3565922019-10-28 11:58:20 -07001638 return 0;
1639}
1640
1641
1642static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1643 struct dpp_authentication *auth)
1644{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001645#ifdef CONFIG_DPP2
1646 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1647 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1648 wpa_s->dpp_reconfig_ssid) {
1649 wpa_printf(MSG_DEBUG,
1650 "DPP: Remove reconfigured network profile");
1651 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1652 wpa_config_remove_network(wpa_s->conf,
1653 wpa_s->dpp_reconfig_ssid_id);
1654 wpa_s->dpp_reconfig_ssid = NULL;
1655 wpa_s->dpp_reconfig_ssid_id = -1;
1656 }
1657#endif /* CONFIG_DPP2 */
1658
Hai Shalom021b0b52019-04-10 11:17:58 -07001659 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001660 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001661
1662#ifdef CONFIG_DPP2
1663 if (auth->peer_version >= 2) {
1664 wpa_printf(MSG_DEBUG,
1665 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1666 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001667 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001668 }
1669#endif /* CONFIG_DPP2 */
1670
1671 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001672}
1673
1674
Hai Shalom021b0b52019-04-10 11:17:58 -07001675static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001676 struct dpp_authentication *auth,
1677 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001678{
1679 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001680 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1681 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001682 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001683 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001684 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001685 if (conf->ssid_charset)
1686 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1687 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001688 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001689 /* TODO: Save the Connector and consider using a command
1690 * to fetch the value instead of sending an event with
1691 * it. The Connector could end up being larger than what
1692 * most clients are ready to receive as an event
1693 * message. */
1694 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001695 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001696 }
Hai Shalom60840252021-02-19 19:02:11 -08001697 if (conf->passphrase[0]) {
1698 char hex[64 * 2 + 1];
1699
1700 wpa_snprintf_hex(hex, sizeof(hex),
1701 (const u8 *) conf->passphrase,
1702 os_strlen(conf->passphrase));
1703 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1704 hex);
1705 } else if (conf->psk_set) {
1706 char hex[PMK_LEN * 2 + 1];
1707
1708 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1709 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1710 hex);
1711 }
Hai Shalomc3565922019-10-28 11:58:20 -07001712 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001713 char *hex;
1714 size_t hexlen;
1715
Hai Shalomc3565922019-10-28 11:58:20 -07001716 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001717 hex = os_malloc(hexlen);
1718 if (hex) {
1719 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001720 wpabuf_head(conf->c_sign_key),
1721 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001722 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1723 hex);
1724 os_free(hex);
1725 }
1726 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001727 if (conf->pp_key) {
1728 char *hex;
1729 size_t hexlen;
1730
1731 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1732 hex = os_malloc(hexlen);
1733 if (hex) {
1734 wpa_snprintf_hex(hex, hexlen,
1735 wpabuf_head(conf->pp_key),
1736 wpabuf_len(conf->pp_key));
1737 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1738 os_free(hex);
1739 }
1740 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001741 if (auth->net_access_key) {
1742 char *hex;
1743 size_t hexlen;
1744
1745 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1746 hex = os_malloc(hexlen);
1747 if (hex) {
1748 wpa_snprintf_hex(hex, hexlen,
1749 wpabuf_head(auth->net_access_key),
1750 wpabuf_len(auth->net_access_key));
1751 if (auth->net_access_key_expiry)
1752 wpa_msg(wpa_s, MSG_INFO,
1753 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1754 (long unsigned)
1755 auth->net_access_key_expiry);
1756 else
1757 wpa_msg(wpa_s, MSG_INFO,
1758 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1759 os_free(hex);
1760 }
1761 }
1762
Hai Shalom899fcc72020-10-19 14:38:18 -07001763#ifdef CONFIG_DPP2
1764 if (conf->certbag) {
1765 char *b64;
1766
1767 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1768 wpabuf_len(conf->certbag), NULL);
1769 if (b64)
1770 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1771 os_free(b64);
1772 }
1773
1774 if (conf->cacert) {
1775 char *b64;
1776
1777 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1778 wpabuf_len(conf->cacert), NULL);
1779 if (b64)
1780 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1781 os_free(b64);
1782 }
1783
1784 if (conf->server_name)
1785 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1786 conf->server_name);
1787#endif /* CONFIG_DPP2 */
1788
Sunil Ravi89eba102022-09-13 21:04:37 -07001789#ifdef CONFIG_DPP3
1790 if (!wpa_s->dpp_pb_result_indicated) {
1791 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "success");
1792 wpa_s->dpp_pb_result_indicated = true;
1793 }
1794
1795#endif /* CONFIG_DPP3 */
1796
Hai Shalomc3565922019-10-28 11:58:20 -07001797 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001798}
1799
1800
Hai Shalomfdcde762020-04-02 11:19:20 -07001801static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1802 struct dpp_asymmetric_key *key)
1803{
1804#ifdef CONFIG_DPP2
1805 int res;
1806
1807 if (!key)
1808 return 0;
1809
1810 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1811 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001812 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001813
1814 while (key) {
1815 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1816 if (res < 0)
1817 return -1;
1818 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1819 res);
1820 key = key->next;
1821 }
1822#endif /* CONFIG_DPP2 */
1823
1824 return 0;
1825}
1826
1827
Hai Shalom899fcc72020-10-19 14:38:18 -07001828#ifdef CONFIG_DPP2
1829static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1830{
1831 struct wpa_supplicant *wpa_s = eloop_ctx;
1832 struct dpp_authentication *auth = wpa_s->dpp_auth;
1833
1834 if (!auth || !auth->csrattrs)
1835 return;
1836
1837 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1838 wpabuf_free(auth->csr);
1839 /* TODO: Additional information needed for CSR based on csrAttrs */
1840 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1841 wpa_s->conf->dpp_name : "Test");
1842 if (!auth->csr) {
1843 dpp_auth_deinit(wpa_s->dpp_auth);
1844 wpa_s->dpp_auth = NULL;
1845 return;
1846 }
1847
1848 wpas_dpp_start_gas_client(wpa_s);
1849}
1850#endif /* CONFIG_DPP2 */
1851
1852
Sunil Ravia04bd252022-05-02 22:54:18 -07001853#ifdef CONFIG_DPP3
1854static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1855{
1856 struct wpa_supplicant *wpa_s = eloop_ctx;
1857 struct dpp_authentication *auth = wpa_s->dpp_auth;
1858
1859 if (!auth || !auth->waiting_new_key)
1860 return;
1861
1862 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1863 wpas_dpp_start_gas_client(wpa_s);
1864}
1865#endif /* CONFIG_DPP3 */
1866
1867
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001868static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1869 enum gas_query_result result,
1870 const struct wpabuf *adv_proto,
1871 const struct wpabuf *resp, u16 status_code)
1872{
1873 struct wpa_supplicant *wpa_s = ctx;
1874 const u8 *pos;
1875 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001876 int res;
1877 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001878 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001879
Hai Shaloma20dcd72022-02-04 13:43:00 -08001880 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001881 wpa_s->dpp_gas_dialog_token = -1;
1882
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001883 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001884 !ether_addr_equal(addr, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001885 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1886 return;
1887 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001888 if (result != GAS_QUERY_SUCCESS ||
1889 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001890 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1891 goto fail;
1892 }
1893
1894 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1895 adv_proto);
1896 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1897 resp);
1898
1899 if (wpabuf_len(adv_proto) != 10 ||
1900 !(pos = wpabuf_head(adv_proto)) ||
1901 pos[0] != WLAN_EID_ADV_PROTO ||
1902 pos[1] != 8 ||
1903 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1904 pos[4] != 5 ||
1905 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1906 pos[8] != 0x1a ||
1907 pos[9] != 1) {
1908 wpa_printf(MSG_DEBUG,
1909 "DPP: Not a DPP Advertisement Protocol ID");
1910 goto fail;
1911 }
1912
Hai Shalom899fcc72020-10-19 14:38:18 -07001913 res = dpp_conf_resp_rx(auth, resp);
1914#ifdef CONFIG_DPP2
1915 if (res == -2) {
1916 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1917 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1918 return;
1919 }
1920#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001921#ifdef CONFIG_DPP3
1922 if (res == -3) {
1923 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1924 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1925 NULL);
1926 return;
1927 }
1928#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001929 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001930 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1931 goto fail;
1932 }
1933
Hai Shalom899fcc72020-10-19 14:38:18 -07001934 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001935 for (i = 0; i < auth->num_conf_obj; i++) {
1936 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1937 &auth->conf_obj[i]);
1938 if (res < 0)
1939 goto fail;
1940 }
1941 if (auth->num_conf_obj)
1942 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001943 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1944 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001945
Hai Shalom021b0b52019-04-10 11:17:58 -07001946 status = DPP_STATUS_OK;
1947#ifdef CONFIG_TESTING_OPTIONS
1948 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1949 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1950 status = DPP_STATUS_CONFIG_REJECTED;
1951 }
1952#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001953fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001954 if (status != DPP_STATUS_OK) {
1955 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1956 wpas_notify_dpp_configuration_failure(wpa_s);
1957 }
1958#ifdef CONFIG_DPP2
1959 if (auth->peer_version >= 2 &&
1960 auth->conf_resp_status == DPP_STATUS_OK) {
1961 struct wpabuf *msg;
1962
1963 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1964 msg = dpp_build_conf_result(auth, status);
1965 if (!msg)
1966 goto fail2;
1967
1968 wpa_msg(wpa_s, MSG_INFO,
1969 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1970 MAC2STR(addr), auth->curr_freq,
1971 DPP_PA_CONFIGURATION_RESULT);
1972 offchannel_send_action(wpa_s, auth->curr_freq,
1973 addr, wpa_s->own_addr, broadcast,
1974 wpabuf_head(msg),
1975 wpabuf_len(msg),
1976 500, wpas_dpp_tx_status, 0);
1977 wpabuf_free(msg);
1978
1979 /* This exchange will be terminated in the TX status handler */
Sunil Ravi546a7b52022-08-26 22:06:04 +00001980 if (wpa_s->conf->dpp_config_processing < 1 ||
Hai Shalom899fcc72020-10-19 14:38:18 -07001981 wpa_s->dpp_conf_backup_received)
1982 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001983 return;
1984 }
1985fail2:
1986#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001987 dpp_auth_deinit(wpa_s->dpp_auth);
1988 wpa_s->dpp_auth = NULL;
1989}
1990
1991
Hai Shaloma20dcd72022-02-04 13:43:00 -08001992static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
1993{
1994 struct wpa_supplicant *wpa_s = eloop_ctx;
1995 struct dpp_authentication *auth = wpa_s->dpp_auth;
1996
1997 if (!wpa_s->dpp_gas_client || !auth ||
1998 (!auth->auth_success && !auth->reconfig_success))
1999 return;
2000
2001 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
2002 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
2003 dpp_auth_deinit(wpa_s->dpp_auth);
2004 wpa_s->dpp_auth = NULL;
2005}
2006
2007
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002008static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
2009{
2010 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07002011 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002012 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07002013 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002014
2015 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002016 offchannel_send_action_done(wpa_s);
2017 wpas_dpp_listen_stop(wpa_s);
2018
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002019#ifdef CONFIG_NO_RRM
2020 supp_op_classes = NULL;
2021#else /* CONFIG_NO_RRM */
Hai Shalomc3565922019-10-28 11:58:20 -07002022 supp_op_classes = wpas_supp_op_classes(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002023#endif /* CONFIG_NO_RRM */
Hai Shalomc3565922019-10-28 11:58:20 -07002024 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002025 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07002026 wpa_s->conf->dpp_mud_url,
Sunil Ravi89eba102022-09-13 21:04:37 -07002027 supp_op_classes,
2028 wpa_s->conf->dpp_extra_conf_req_name,
2029 wpa_s->conf->dpp_extra_conf_req_value);
Hai Shalomc3565922019-10-28 11:58:20 -07002030 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07002031 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002032 wpa_printf(MSG_DEBUG,
2033 "DPP: No configuration request data available");
2034 return;
2035 }
2036
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002037 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
2038 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
2039
Hai Shaloma20dcd72022-02-04 13:43:00 -08002040 /* Use a 120 second timeout since the gas_query_req() operation could
2041 * remain waiting indefinitely for the response if the Configurator
2042 * keeps sending out comeback responses with additional delay. The
2043 * DPP technical specification expects the Enrollee to continue sending
2044 * out new Config Requests for 60 seconds, so this gives an extra 60
2045 * second time after the last expected new Config Request for the
2046 * Configurator to determine what kind of configuration to provide. */
2047 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
2048 wpa_s, NULL);
2049
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002050 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07002051 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002052 if (res < 0) {
2053 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
2054 wpabuf_free(buf);
2055 } else {
2056 wpa_printf(MSG_DEBUG,
2057 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002058 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002059 }
2060}
2061
2062
2063static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
2064{
2065 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002066 dpp_notify_auth_success(wpa_s->dpp_auth, initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08002067 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002068#ifdef CONFIG_TESTING_OPTIONS
2069 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
2070 wpa_printf(MSG_INFO,
2071 "DPP: TESTING - stop at Authentication Confirm");
2072 if (wpa_s->dpp_auth->configurator) {
2073 /* Prevent GAS response */
2074 wpa_s->dpp_auth->auth_success = 0;
2075 }
2076 return;
2077 }
2078#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002079
2080 if (wpa_s->dpp_auth->configurator)
2081 wpas_dpp_start_gas_server(wpa_s);
2082 else
2083 wpas_dpp_start_gas_client(wpa_s);
2084}
2085
2086
2087static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002088 const u8 *hdr, const u8 *buf, size_t len,
2089 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002090{
2091 struct dpp_authentication *auth = wpa_s->dpp_auth;
2092 struct wpabuf *msg;
2093
Roshan Pius3a1667e2018-07-03 15:17:14 -07002094 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
2095 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002096
2097 if (!auth) {
2098 wpa_printf(MSG_DEBUG,
2099 "DPP: No DPP Authentication in progress - drop");
2100 return;
2101 }
2102
2103 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002104 !ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002105 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2106 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2107 return;
2108 }
2109
2110 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
2111
Roshan Pius3a1667e2018-07-03 15:17:14 -07002112 if (auth->curr_freq != freq && auth->neg_freq == freq) {
2113 wpa_printf(MSG_DEBUG,
2114 "DPP: Responder accepted request for different negotiation channel");
2115 auth->curr_freq = freq;
2116 }
2117
2118 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002119 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
2120 if (!msg) {
2121 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
2122 wpa_printf(MSG_DEBUG,
2123 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08002124 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002125 offchannel_send_action_done(wpa_s);
2126 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
2127 return;
2128 }
2129 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
2130 return;
2131 }
2132 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2133
Roshan Pius3a1667e2018-07-03 15:17:14 -07002134 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2135 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002136 offchannel_send_action(wpa_s, auth->curr_freq,
2137 src, wpa_s->own_addr, broadcast,
2138 wpabuf_head(msg), wpabuf_len(msg),
2139 500, wpas_dpp_tx_status, 0);
2140 wpabuf_free(msg);
2141 wpa_s->dpp_auth_ok_on_ack = 1;
2142}
2143
2144
2145static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2146 const u8 *hdr, const u8 *buf, size_t len)
2147{
2148 struct dpp_authentication *auth = wpa_s->dpp_auth;
2149
2150 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
2151 MAC2STR(src));
2152
2153 if (!auth) {
2154 wpa_printf(MSG_DEBUG,
2155 "DPP: No DPP Authentication in progress - drop");
2156 return;
2157 }
2158
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002159 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002160 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2161 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2162 return;
2163 }
2164
Hai Shalom60840252021-02-19 19:02:11 -08002165 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
2166
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002167 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
2168 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08002169 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002170 return;
2171 }
2172
2173 wpas_dpp_auth_success(wpa_s, 0);
2174}
2175
2176
Hai Shalom021b0b52019-04-10 11:17:58 -07002177#ifdef CONFIG_DPP2
2178
2179static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
2180 void *timeout_ctx)
2181{
2182 struct wpa_supplicant *wpa_s = eloop_ctx;
2183 struct dpp_authentication *auth = wpa_s->dpp_auth;
2184
2185 if (!auth || !auth->waiting_conf_result)
2186 return;
2187
2188 wpa_printf(MSG_DEBUG,
2189 "DPP: Timeout while waiting for Configuration Result");
2190 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002191 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002192 dpp_auth_deinit(auth);
2193 wpa_s->dpp_auth = NULL;
2194}
2195
2196
Hai Shalomc3565922019-10-28 11:58:20 -07002197static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2198 void *timeout_ctx)
2199{
2200 struct wpa_supplicant *wpa_s = eloop_ctx;
2201 struct dpp_authentication *auth = wpa_s->dpp_auth;
2202
2203 if (!auth || !auth->waiting_conn_status_result)
2204 return;
2205
2206 wpa_printf(MSG_DEBUG,
2207 "DPP: Timeout while waiting for Connection Status Result");
2208 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002209 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002210 wpas_dpp_listen_stop(wpa_s);
2211 dpp_auth_deinit(auth);
2212 wpa_s->dpp_auth = NULL;
2213}
2214
2215
Sunil Ravi89eba102022-09-13 21:04:37 -07002216#ifdef CONFIG_DPP3
2217
2218static bool wpas_dpp_pb_active(struct wpa_supplicant *wpa_s)
2219{
2220 return (wpa_s->dpp_pb_time.sec || wpa_s->dpp_pb_time.usec) &&
2221 wpa_s->dpp_pb_configurator;
2222}
2223
2224
2225static void wpas_dpp_remove_pb_hash(struct wpa_supplicant *wpa_s)
2226{
2227 int i;
2228
2229 if (!wpa_s->dpp_pb_bi)
2230 return;
2231 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2232 struct dpp_pb_info *info = &wpa_s->dpp_pb[i];
2233
2234 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
2235 continue;
2236 if (os_memcmp(info->hash, wpa_s->dpp_pb_resp_hash,
2237 SHA256_MAC_LEN) == 0) {
2238 /* Allow a new push button session to be established
2239 * immediately without the successfully completed
2240 * session triggering session overlap. */
2241 info->rx_time.sec = 0;
2242 info->rx_time.usec = 0;
2243 wpa_printf(MSG_DEBUG,
2244 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
2245 }
2246 }
2247}
2248
2249#endif /* CONFIG_DPP3 */
2250
2251
Hai Shalom021b0b52019-04-10 11:17:58 -07002252static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2253 const u8 *hdr, const u8 *buf, size_t len)
2254{
2255 struct dpp_authentication *auth = wpa_s->dpp_auth;
2256 enum dpp_status_error status;
2257
2258 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2259 MAC2STR(src));
2260
2261 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002262 if (auth &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002263 ether_addr_equal(src, auth->peer_mac_addr) &&
Hai Shalom60840252021-02-19 19:02:11 -08002264 gas_server_response_sent(wpa_s->gas_server,
2265 auth->gas_server_ctx)) {
2266 /* This could happen if the TX status event gets delayed
2267 * long enough for the Enrollee to have time to send
2268 * the next frame before the TX status gets processed
2269 * locally. */
2270 wpa_printf(MSG_DEBUG,
2271 "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");
2272 auth->waiting_conf_result = 1;
2273 } else {
2274 wpa_printf(MSG_DEBUG,
2275 "DPP: No DPP Configuration waiting for result - drop");
2276 return;
2277 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002278 }
2279
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002280 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002281 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2282 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2283 return;
2284 }
2285
2286 status = dpp_conf_result_rx(auth, hdr, buf, len);
2287
Hai Shalomc3565922019-10-28 11:58:20 -07002288 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002289 int freq;
2290
Hai Shalomc3565922019-10-28 11:58:20 -07002291 wpa_msg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07002292 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
2293 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07002294 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002295 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002296 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2297 wpa_s, NULL);
2298 auth->waiting_conn_status_result = 1;
2299 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2300 wpa_s, NULL);
2301 eloop_register_timeout(16, 0,
2302 wpas_dpp_conn_status_result_wait_timeout,
2303 wpa_s, NULL);
2304 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002305 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2306 if (!wpa_s->dpp_in_response_listen ||
2307 (int) wpa_s->dpp_listen_freq != freq)
2308 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002309 return;
2310 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002311 offchannel_send_action_done(wpa_s);
2312 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002313 if (status == DPP_STATUS_OK) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002314 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
2315 auth->conf_resp_status);
Hai Shalome4073332019-11-05 16:20:12 -08002316 wpas_notify_dpp_config_sent(wpa_s);
2317 }
2318 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002319 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002320 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002321 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002322 dpp_auth_deinit(auth);
2323 wpa_s->dpp_auth = NULL;
2324 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07002325#ifdef CONFIG_DPP3
2326 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
2327 if (status == DPP_STATUS_OK)
2328 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2329 "success");
2330 else
2331 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2332 "no-configuration-available");
2333 wpa_s->dpp_pb_result_indicated = true;
2334 if (status == DPP_STATUS_OK)
2335 wpas_dpp_remove_pb_hash(wpa_s);
2336 wpas_dpp_push_button_stop(wpa_s);
2337 }
2338#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002339}
2340
Hai Shalom81f62d82019-07-22 12:10:00 -07002341
Hai Shalomc3565922019-10-28 11:58:20 -07002342static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2343 const u8 *src, const u8 *hdr,
2344 const u8 *buf, size_t len)
2345{
2346 struct dpp_authentication *auth = wpa_s->dpp_auth;
2347 enum dpp_status_error status;
2348 u8 ssid[SSID_MAX_LEN];
2349 size_t ssid_len = 0;
2350 char *channel_list = NULL;
2351
2352 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2353
2354 if (!auth || !auth->waiting_conn_status_result) {
2355 wpa_printf(MSG_DEBUG,
2356 "DPP: No DPP Configuration waiting for connection status result - drop");
2357 return;
2358 }
2359
2360 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2361 ssid, &ssid_len, &channel_list);
2362 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2363 "result=%d ssid=%s channel_list=%s",
2364 status, wpa_ssid_txt(ssid, ssid_len),
2365 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002366 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2367 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002368 os_free(channel_list);
2369 offchannel_send_action_done(wpa_s);
2370 wpas_dpp_listen_stop(wpa_s);
2371 dpp_auth_deinit(auth);
2372 wpa_s->dpp_auth = NULL;
2373 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2374 wpa_s, NULL);
2375}
2376
2377
Hai Shalom81f62d82019-07-22 12:10:00 -07002378static int wpas_dpp_process_conf_obj(void *ctx,
2379 struct dpp_authentication *auth)
2380{
2381 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002382 unsigned int i;
2383 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002384
Hai Shalomc3565922019-10-28 11:58:20 -07002385 for (i = 0; i < auth->num_conf_obj; i++) {
2386 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2387 &auth->conf_obj[i]);
2388 if (res)
2389 break;
2390 }
2391 if (!res)
2392 wpas_dpp_post_process_config(wpa_s, auth);
2393
2394 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002395}
2396
Hai Shalomfdcde762020-04-02 11:19:20 -07002397
Hai Shaloma20dcd72022-02-04 13:43:00 -08002398static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2399{
2400 struct wpa_supplicant *wpa_s = ctx;
2401
2402 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2403
2404 if (auth->connect_on_tx_status) {
2405 auth->connect_on_tx_status = 0;
2406 wpa_printf(MSG_DEBUG,
2407 "DPP: Try to connect after completed configuration result");
2408 wpas_dpp_try_to_connect(wpa_s);
2409 if (auth->conn_status_requested) {
2410 wpa_printf(MSG_DEBUG,
2411 "DPP: Start 15 second timeout for reporting connection status result");
2412 eloop_cancel_timeout(
2413 wpas_dpp_conn_status_result_timeout,
2414 wpa_s, NULL);
2415 eloop_register_timeout(
2416 15, 0, wpas_dpp_conn_status_result_timeout,
2417 wpa_s, NULL);
2418 return true;
2419 }
2420 }
2421
2422 return false;
2423}
2424
2425
Hai Shalomfdcde762020-04-02 11:19:20 -07002426static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2427{
2428 struct wpa_supplicant *wpa_s = ctx;
2429
2430 if (bi == wpa_s->dpp_chirp_bi)
2431 wpas_dpp_chirp_stop(wpa_s);
2432}
2433
2434
2435static void
2436wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2437 const u8 *hdr, const u8 *buf, size_t len,
2438 unsigned int freq)
2439{
2440 const u8 *r_bootstrap;
2441 u16 r_bootstrap_len;
2442 struct dpp_bootstrap_info *peer_bi;
2443 struct dpp_authentication *auth;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002444 unsigned int wait_time, max_wait_time;
Hai Shalomfdcde762020-04-02 11:19:20 -07002445
2446 if (!wpa_s->dpp)
2447 return;
2448
2449 if (wpa_s->dpp_auth) {
2450 wpa_printf(MSG_DEBUG,
2451 "DPP: Ignore Presence Announcement during ongoing Authentication");
2452 return;
2453 }
2454
2455 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2456 MAC2STR(src));
2457
2458 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2459 &r_bootstrap_len);
2460 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2461 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2462 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2463 return;
2464 }
2465 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2466 r_bootstrap, r_bootstrap_len);
2467 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002468 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2469 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002470 if (!peer_bi) {
2471 wpa_printf(MSG_DEBUG,
2472 "DPP: No matching bootstrapping information found");
2473 return;
2474 }
2475
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002476 wpa_printf(MSG_DEBUG, "DPP: Start Authentication exchange with " MACSTR
2477 " based on the received Presence Announcement",
2478 MAC2STR(src));
Hai Shalomfdcde762020-04-02 11:19:20 -07002479 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2480 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2481 if (!auth)
2482 return;
2483 wpas_dpp_set_testing_options(wpa_s, auth);
2484 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2485 dpp_auth_deinit(auth);
2486 return;
2487 }
2488
2489 auth->neg_freq = freq;
2490
Hai Shalom60840252021-02-19 19:02:11 -08002491 /* The source address of the Presence Announcement frame overrides any
2492 * MAC address information from the bootstrapping information. */
2493 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002494
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002495 wait_time = wpa_s->max_remain_on_chan;
2496 max_wait_time = wpa_s->dpp_resp_wait_time ?
2497 wpa_s->dpp_resp_wait_time : 2000;
2498 if (wait_time > max_wait_time)
2499 wait_time = max_wait_time;
2500 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2501
Hai Shalomfdcde762020-04-02 11:19:20 -07002502 wpa_s->dpp_auth = auth;
2503 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2504 dpp_auth_deinit(wpa_s->dpp_auth);
2505 wpa_s->dpp_auth = NULL;
2506 }
2507}
2508
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002509
2510static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2511 void *timeout_ctx)
2512{
2513 struct wpa_supplicant *wpa_s = eloop_ctx;
2514 struct dpp_authentication *auth = wpa_s->dpp_auth;
2515
2516 if (!auth)
2517 return;
2518
2519 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2520 offchannel_send_action_done(wpa_s);
2521 wpas_dpp_listen_stop(wpa_s);
2522 dpp_auth_deinit(auth);
2523 wpa_s->dpp_auth = NULL;
2524}
2525
2526
2527static void
2528wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2529 const u8 *hdr, const u8 *buf, size_t len,
2530 unsigned int freq)
2531{
Hai Shalom899fcc72020-10-19 14:38:18 -07002532 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2533 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002534 struct dpp_configurator *conf;
2535 struct dpp_authentication *auth;
2536 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002537 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002538
2539 if (!wpa_s->dpp)
2540 return;
2541
2542 if (wpa_s->dpp_auth) {
2543 wpa_printf(MSG_DEBUG,
2544 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2545 return;
2546 }
2547
2548 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2549 MAC2STR(src));
2550
2551 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2552 &csign_hash_len);
2553 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2554 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2555 "Missing or invalid required Configurator C-sign key Hash attribute");
2556 return;
2557 }
2558 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2559 csign_hash, csign_hash_len);
2560 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2561 if (!conf) {
2562 wpa_printf(MSG_DEBUG,
2563 "DPP: No matching Configurator information found");
2564 return;
2565 }
2566
Hai Shalom899fcc72020-10-19 14:38:18 -07002567 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2568 &fcgroup_len);
2569 if (!fcgroup || fcgroup_len != 2) {
2570 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2571 "Missing or invalid required Finite Cyclic Group attribute");
2572 return;
2573 }
2574 group = WPA_GET_LE16(fcgroup);
2575 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2576
2577 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2578 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2579
2580 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2581 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002582 if (!auth)
2583 return;
2584 wpas_dpp_set_testing_options(wpa_s, auth);
2585 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2586 dpp_auth_deinit(auth);
2587 return;
2588 }
2589
2590 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2591 wpa_s->dpp_auth = auth;
2592
2593 wpa_s->dpp_in_response_listen = 0;
2594 wpa_s->dpp_auth_ok_on_ack = 0;
2595 wait_time = wpa_s->max_remain_on_chan;
2596 max_wait_time = wpa_s->dpp_resp_wait_time ?
2597 wpa_s->dpp_resp_wait_time : 2000;
2598 if (wait_time > max_wait_time)
2599 wait_time = max_wait_time;
2600 wait_time += 10; /* give the driver some extra time to complete */
2601 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2602 wpas_dpp_reconfig_reply_wait_timeout,
2603 wpa_s, NULL);
2604 wait_time -= 10;
2605
2606 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2607
2608 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2609 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2610 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2611 wpabuf_head(auth->reconfig_req_msg),
2612 wpabuf_len(auth->reconfig_req_msg),
2613 wait_time, wpas_dpp_tx_status, 0) < 0) {
2614 dpp_auth_deinit(wpa_s->dpp_auth);
2615 wpa_s->dpp_auth = NULL;
2616 }
2617}
2618
2619
2620static void
2621wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2622 const u8 *hdr, const u8 *buf, size_t len,
2623 unsigned int freq)
2624{
2625 struct wpa_ssid *ssid;
2626 struct dpp_authentication *auth;
2627
2628 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2629 MACSTR, MAC2STR(src));
2630
Hai Shalom899fcc72020-10-19 14:38:18 -07002631 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002632 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002633 if (wpa_s->dpp_auth) {
2634 wpa_printf(MSG_DEBUG,
2635 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2636 return;
2637 }
2638 if (!wpa_s->dpp_reconfig_ssid) {
2639 wpa_printf(MSG_DEBUG,
2640 "DPP: Not ready for reconfiguration - not requested");
2641 return;
2642 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002643 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2644 if (ssid == wpa_s->dpp_reconfig_ssid &&
2645 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2646 break;
2647 }
2648 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002649 !ssid->dpp_csign) {
2650 wpa_printf(MSG_DEBUG,
2651 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002652 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002653 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002654
2655 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2656 ssid->dpp_netaccesskey,
2657 ssid->dpp_netaccesskey_len,
2658 ssid->dpp_csign, ssid->dpp_csign_len,
2659 freq, hdr, buf, len);
2660 if (!auth)
2661 return;
2662 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2663 wpa_s->dpp_auth = auth;
2664
2665 wpas_dpp_chirp_stop(wpa_s);
2666
2667 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2668 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2669 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2670 wpabuf_head(auth->reconfig_resp_msg),
2671 wpabuf_len(auth->reconfig_resp_msg),
2672 500, wpas_dpp_tx_status, 0) < 0) {
2673 dpp_auth_deinit(wpa_s->dpp_auth);
2674 wpa_s->dpp_auth = NULL;
2675 }
2676}
2677
2678
2679static void
2680wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2681 const u8 *hdr, const u8 *buf, size_t len,
2682 unsigned int freq)
2683{
2684 struct dpp_authentication *auth = wpa_s->dpp_auth;
2685 struct wpabuf *conf;
2686
2687 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2688 MACSTR, MAC2STR(src));
2689
2690 if (!auth || !auth->reconfig || !auth->configurator) {
2691 wpa_printf(MSG_DEBUG,
2692 "DPP: No DPP Reconfig Authentication in progress - drop");
2693 return;
2694 }
2695
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002696 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002697 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2698 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2699 return;
2700 }
2701
2702 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2703 if (!conf)
2704 return;
2705
2706 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2707
2708 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2709 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2710 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2711 wpabuf_head(conf), wpabuf_len(conf),
2712 500, wpas_dpp_tx_status, 0) < 0) {
2713 wpabuf_free(conf);
2714 dpp_auth_deinit(wpa_s->dpp_auth);
2715 wpa_s->dpp_auth = NULL;
2716 return;
2717 }
2718 wpabuf_free(conf);
2719
2720 wpas_dpp_start_gas_server(wpa_s);
2721}
2722
2723
2724static void
2725wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2726 const u8 *hdr, const u8 *buf, size_t len,
2727 unsigned int freq)
2728{
2729 struct dpp_authentication *auth = wpa_s->dpp_auth;
2730
2731 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2732 MACSTR, MAC2STR(src));
2733
2734 if (!auth || !auth->reconfig || auth->configurator) {
2735 wpa_printf(MSG_DEBUG,
2736 "DPP: No DPP Reconfig Authentication in progress - drop");
2737 return;
2738 }
2739
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002740 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002741 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2742 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2743 return;
2744 }
2745
2746 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2747 return;
2748
2749 wpas_dpp_start_gas_client(wpa_s);
2750}
2751
Hai Shalom021b0b52019-04-10 11:17:58 -07002752#endif /* CONFIG_DPP2 */
2753
2754
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002755static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2756 const u8 *src,
2757 const u8 *buf, size_t len)
2758{
2759 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002760 const u8 *connector, *trans_id, *status;
2761 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002762#ifdef CONFIG_DPP2
2763 const u8 *version;
2764 u16 version_len;
2765#endif /* CONFIG_DPP2 */
2766 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002767 struct dpp_introduction intro;
2768 struct rsn_pmksa_cache_entry *entry;
2769 struct os_time now;
2770 struct os_reltime rnow;
2771 os_time_t expiry;
2772 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002773 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002774
2775 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2776 MAC2STR(src));
2777 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002778 !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002779 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2780 MACSTR " - drop", MAC2STR(src));
2781 return;
2782 }
2783 offchannel_send_action_done(wpa_s);
2784
2785 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2786 if (ssid == wpa_s->dpp_intro_network)
2787 break;
2788 }
2789 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2790 !ssid->dpp_csign) {
2791 wpa_printf(MSG_DEBUG,
2792 "DPP: Profile not found for network introduction");
2793 return;
2794 }
2795
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002796 os_memset(&intro, 0, sizeof(intro));
2797
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002798 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2799 &trans_id_len);
2800 if (!trans_id || trans_id_len != 1) {
2801 wpa_printf(MSG_DEBUG,
2802 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002803 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2804 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002805 goto fail;
2806 }
2807 if (trans_id[0] != TRANSACTION_ID) {
2808 wpa_printf(MSG_DEBUG,
2809 "DPP: Ignore frame with unexpected Transaction ID %u",
2810 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002811 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2812 " fail=transaction_id_mismatch", MAC2STR(src));
2813 goto fail;
2814 }
2815
2816 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2817 if (!status || status_len != 1) {
2818 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2819 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2820 " fail=missing_status", MAC2STR(src));
2821 goto fail;
2822 }
2823 if (status[0] != DPP_STATUS_OK) {
2824 wpa_printf(MSG_DEBUG,
2825 "DPP: Peer rejected network introduction: Status %u",
2826 status[0]);
2827 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2828 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002829#ifdef CONFIG_DPP2
2830 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2831#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002832 goto fail;
2833 }
2834
2835 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2836 if (!connector) {
2837 wpa_printf(MSG_DEBUG,
2838 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002839 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2840 " fail=missing_connector", MAC2STR(src));
2841 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002842 }
2843
Roshan Pius3a1667e2018-07-03 15:17:14 -07002844 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2845 ssid->dpp_netaccesskey,
2846 ssid->dpp_netaccesskey_len,
2847 ssid->dpp_csign,
2848 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002849 connector, connector_len, &expiry, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002850 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002851 wpa_printf(MSG_INFO,
2852 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002853 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2854 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002855#ifdef CONFIG_DPP2
2856 wpas_dpp_send_conn_status_result(wpa_s, res);
2857#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002858 goto fail;
2859 }
2860
2861 entry = os_zalloc(sizeof(*entry));
2862 if (!entry)
2863 goto fail;
2864 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002865 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002866 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2867 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2868 entry->pmk_len = intro.pmk_len;
2869 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002870#ifdef CONFIG_DPP2
2871 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2872 &version_len);
2873 if (version && version_len >= 1)
2874 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002875#ifdef CONFIG_DPP3
2876 if (intro.peer_version && intro.peer_version >= 2 &&
2877 peer_version != intro.peer_version) {
2878 wpa_printf(MSG_INFO,
2879 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2880 intro.peer_version, peer_version);
2881 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2882 goto fail;
2883 }
2884#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002885 entry->dpp_pfs = peer_version >= 2;
2886#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002887 if (expiry) {
2888 os_get_time(&now);
2889 seconds = expiry - now.sec;
2890 } else {
2891 seconds = 86400 * 7;
2892 }
2893 os_get_reltime(&rnow);
2894 entry->expiration = rnow.sec + seconds;
2895 entry->reauth_time = rnow.sec + seconds;
2896 entry->network_ctx = ssid;
2897 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2898
Roshan Pius3a1667e2018-07-03 15:17:14 -07002899 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002900 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002901
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002902 wpa_printf(MSG_DEBUG,
2903 "DPP: Try connection again after successful network introduction");
2904 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2905 wpa_supplicant_cancel_sched_scan(wpa_s);
2906 wpa_supplicant_req_scan(wpa_s, 0, 0);
2907 }
2908fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002909 dpp_peer_intro_deinit(&intro);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002910}
2911
2912
Roshan Pius3a1667e2018-07-03 15:17:14 -07002913static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2914{
2915 int i, j;
2916
2917 if (!wpa_s->hw.modes)
2918 return -1;
2919
2920 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2921 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2922
2923 for (j = 0; j < mode->num_channels; j++) {
2924 struct hostapd_channel_data *chan = &mode->channels[j];
2925
2926 if (chan->freq != (int) freq)
2927 continue;
2928
2929 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2930 HOSTAPD_CHAN_NO_IR |
2931 HOSTAPD_CHAN_RADAR))
2932 continue;
2933
2934 return 1;
2935 }
2936 }
2937
2938 wpa_printf(MSG_DEBUG,
2939 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2940 freq);
2941
2942 return 0;
2943}
2944
2945
2946static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2947 struct dpp_pkex *pkex)
2948{
2949 if (pkex->freq == 2437)
2950 pkex->freq = 5745;
2951 else if (pkex->freq == 5745)
2952 pkex->freq = 5220;
2953 else if (pkex->freq == 5220)
2954 pkex->freq = 60480;
2955 else
2956 return -1; /* no more channels to try */
2957
2958 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2959 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2960 pkex->freq);
2961 return 0;
2962 }
2963
2964 /* Could not use this channel - try the next one */
2965 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2966}
2967
2968
Sunil Ravi89eba102022-09-13 21:04:37 -07002969static void wpas_dpp_pkex_clear_code(struct wpa_supplicant *wpa_s)
2970{
2971 if (!wpa_s->dpp_pkex_code && !wpa_s->dpp_pkex_identifier)
2972 return;
2973
2974 /* Delete PKEX code and identifier on successful completion of
2975 * PKEX. We are not supposed to reuse these without being
2976 * explicitly requested to perform PKEX again. */
2977 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
2978 os_free(wpa_s->dpp_pkex_code);
2979 wpa_s->dpp_pkex_code = NULL;
2980 os_free(wpa_s->dpp_pkex_identifier);
2981 wpa_s->dpp_pkex_identifier = NULL;
2982
2983}
2984
2985
Hai Shaloma20dcd72022-02-04 13:43:00 -08002986#ifdef CONFIG_DPP2
2987static int wpas_dpp_pkex_done(void *ctx, void *conn,
2988 struct dpp_bootstrap_info *peer_bi)
2989{
2990 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -07002991 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002992 const char *pos;
2993 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2994 struct dpp_bootstrap_info *own_bi = NULL;
2995 struct dpp_authentication *auth;
2996
Sunil Ravi89eba102022-09-13 21:04:37 -07002997 wpas_dpp_pkex_clear_code(wpa_s);
2998
2999 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
3000 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003001 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
3002 cmd);
3003
3004 pos = os_strstr(cmd, " own=");
3005 if (pos) {
3006 pos += 5;
3007 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
3008 if (!own_bi) {
3009 wpa_printf(MSG_INFO,
3010 "DPP: Could not find bootstrapping info for the identified local entry");
3011 return -1;
3012 }
3013
3014 if (peer_bi->curve != own_bi->curve) {
3015 wpa_printf(MSG_INFO,
3016 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
3017 peer_bi->curve->name, own_bi->curve->name);
3018 return -1;
3019 }
3020 }
3021
3022 pos = os_strstr(cmd, " role=");
3023 if (pos) {
3024 pos += 6;
3025 if (os_strncmp(pos, "configurator", 12) == 0)
3026 allowed_roles = DPP_CAPAB_CONFIGURATOR;
3027 else if (os_strncmp(pos, "enrollee", 8) == 0)
3028 allowed_roles = DPP_CAPAB_ENROLLEE;
3029 else if (os_strncmp(pos, "either", 6) == 0)
3030 allowed_roles = DPP_CAPAB_CONFIGURATOR |
3031 DPP_CAPAB_ENROLLEE;
3032 else
3033 return -1;
3034 }
3035
3036 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
3037 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
3038 if (!auth)
3039 return -1;
3040
3041 wpas_dpp_set_testing_options(wpa_s, auth);
3042 if (dpp_set_configurator(auth, cmd) < 0) {
3043 dpp_auth_deinit(auth);
3044 return -1;
3045 }
3046
3047 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -07003048 DPP_NETROLE_STA,
3049 wpa_s->conf->dpp_mud_url,
3050 wpa_s->conf->dpp_extra_conf_req_name,
3051 wpa_s->conf->dpp_extra_conf_req_value,
3052 wpas_dpp_process_conf_obj,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003053 wpas_dpp_tcp_msg_sent);
3054}
3055#endif /* CONFIG_DPP2 */
3056
3057
Hai Shaloma20dcd72022-02-04 13:43:00 -08003058static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07003059 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003060 const struct hostapd_ip_addr *ipaddr,
3061 int tcp_port)
3062{
3063 struct dpp_pkex *pkex;
3064 struct wpabuf *msg;
3065 unsigned int wait_time;
3066 bool v2 = ver != PKEX_VER_ONLY_1;
3067
3068 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
3069 dpp_pkex_free(wpa_s->dpp_pkex);
3070 wpa_s->dpp_pkex = NULL;
3071 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3072 wpa_s->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -07003073 wpa_s->dpp_pkex_code, wpa_s->dpp_pkex_code_len,
3074 v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003075 if (!pkex)
3076 return -1;
3077 pkex->forced_ver = ver != PKEX_VER_AUTO;
3078
3079 if (ipaddr) {
3080#ifdef CONFIG_DPP2
3081 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
3082 wpa_s, wpa_s, wpas_dpp_pkex_done);
3083#else /* CONFIG_DPP2 */
3084 return -1;
3085#endif /* CONFIG_DPP2 */
3086 }
3087
3088 wpa_s->dpp_pkex = pkex;
3089 msg = pkex->exchange_req;
3090 wait_time = wpa_s->max_remain_on_chan;
3091 if (wait_time > 2000)
3092 wait_time = 2000;
3093 pkex->freq = 2437;
3094 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3095 " freq=%u type=%d",
3096 MAC2STR(broadcast), pkex->freq,
3097 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3098 DPP_PA_PKEX_V1_EXCHANGE_REQ);
3099 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3100 wpa_s->own_addr, broadcast,
3101 wpabuf_head(msg), wpabuf_len(msg),
3102 wait_time, wpas_dpp_tx_pkex_status, 0);
3103 if (wait_time == 0)
3104 wait_time = 2000;
3105 pkex->exch_req_wait_time = wait_time;
3106 pkex->exch_req_tries = 1;
3107
3108 return 0;
3109}
3110
3111
Roshan Pius3a1667e2018-07-03 15:17:14 -07003112static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
3113{
3114 struct wpa_supplicant *wpa_s = eloop_ctx;
3115 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3116
3117 if (!pkex || !pkex->exchange_req)
3118 return;
3119 if (pkex->exch_req_tries >= 5) {
3120 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003121#ifdef CONFIG_DPP3
3122 if (pkex->v2 && !pkex->forced_ver) {
3123 wpa_printf(MSG_DEBUG,
3124 "DPP: Fall back to PKEXv1");
3125 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
3126 NULL, 0);
3127 return;
3128 }
3129#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003130 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
3131 "No response from PKEX peer");
3132 dpp_pkex_free(pkex);
3133 wpa_s->dpp_pkex = NULL;
3134 return;
3135 }
3136 pkex->exch_req_tries = 0;
3137 }
3138
3139 pkex->exch_req_tries++;
3140 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
3141 pkex->exch_req_tries);
3142 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08003143 MAC2STR(broadcast), pkex->freq,
3144 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3145 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003146 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3147 wpa_s->own_addr, broadcast,
3148 wpabuf_head(pkex->exchange_req),
3149 wpabuf_len(pkex->exchange_req),
3150 pkex->exch_req_wait_time,
3151 wpas_dpp_tx_pkex_status, 0);
3152}
3153
3154
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003155static void
3156wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
3157 unsigned int freq, const u8 *dst,
3158 const u8 *src, const u8 *bssid,
3159 const u8 *data, size_t data_len,
3160 enum offchannel_send_action_result result)
3161{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003162 const char *res_txt;
3163 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3164
3165 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3166 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3167 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003168 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3169 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003170 freq, MAC2STR(dst), res_txt);
3171 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3172 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3173
3174 if (!pkex) {
3175 wpa_printf(MSG_DEBUG,
3176 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
3177 return;
3178 }
3179
3180 if (pkex->failed) {
3181 wpa_printf(MSG_DEBUG,
3182 "DPP: Terminate PKEX exchange due to an earlier error");
3183 if (pkex->t > pkex->own_bi->pkex_t)
3184 pkex->own_bi->pkex_t = pkex->t;
3185 dpp_pkex_free(pkex);
3186 wpa_s->dpp_pkex = NULL;
3187 return;
3188 }
3189
3190 if (pkex->exch_req_wait_time && pkex->exchange_req) {
3191 /* Wait for PKEX Exchange Response frame and retry request if
3192 * no response is seen. */
3193 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3194 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
3195 (pkex->exch_req_wait_time % 1000) * 1000,
3196 wpas_dpp_pkex_retry_timeout, wpa_s,
3197 NULL);
3198 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003199}
3200
3201
3202static void
3203wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003204 const u8 *buf, size_t len, unsigned int freq,
3205 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003206{
3207 struct wpabuf *msg;
3208 unsigned int wait_time;
3209
3210 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
3211 MAC2STR(src));
3212
Sunil Ravia04bd252022-05-02 22:54:18 -07003213 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
3214 wpa_printf(MSG_DEBUG,
3215 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
3216 return;
3217 }
3218 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
3219 wpa_printf(MSG_DEBUG,
3220 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
3221 return;
3222 }
3223
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003224 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3225 * values here */
3226
3227 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
3228 wpa_printf(MSG_DEBUG,
3229 "DPP: No PKEX code configured - ignore request");
3230 return;
3231 }
3232
Sunil Ravi89eba102022-09-13 21:04:37 -07003233#ifdef CONFIG_DPP2
3234 if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) {
3235 wpa_printf(MSG_DEBUG,
3236 "DPP: PKEX Exchange Request is from local Controller - ignore request");
3237 return;
3238 }
3239#endif /* CONFIG_DPP2 */
3240
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003241 if (wpa_s->dpp_pkex) {
3242 /* TODO: Support parallel operations */
3243 wpa_printf(MSG_DEBUG,
3244 "DPP: Already in PKEX session - ignore new request");
3245 return;
3246 }
3247
Roshan Pius3a1667e2018-07-03 15:17:14 -07003248 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003249 wpa_s->own_addr, src,
3250 wpa_s->dpp_pkex_identifier,
3251 wpa_s->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07003252 wpa_s->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003253 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003254 if (!wpa_s->dpp_pkex) {
3255 wpa_printf(MSG_DEBUG,
3256 "DPP: Failed to process the request - ignore it");
3257 return;
3258 }
3259
Sunil Ravi89eba102022-09-13 21:04:37 -07003260#ifdef CONFIG_DPP3
3261 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_announcement) {
3262 wpa_printf(MSG_DEBUG,
3263 "DPP: Started PB PKEX (no more PB announcements)");
3264 wpabuf_free(wpa_s->dpp_pb_announcement);
3265 wpa_s->dpp_pb_announcement = NULL;
3266 }
3267#endif /* CONFIG_DPP3 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003268 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003269 msg = wpa_s->dpp_pkex->exchange_resp;
3270 wait_time = wpa_s->max_remain_on_chan;
3271 if (wait_time > 2000)
3272 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003273 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3274 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003275 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3276 broadcast,
3277 wpabuf_head(msg), wpabuf_len(msg),
3278 wait_time, wpas_dpp_tx_pkex_status, 0);
3279}
3280
3281
3282static void
3283wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3284 const u8 *buf, size_t len, unsigned int freq)
3285{
3286 struct wpabuf *msg;
3287 unsigned int wait_time;
3288
3289 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
3290 MAC2STR(src));
3291
3292 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3293 * values here */
3294
3295 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3296 wpa_s->dpp_pkex->exchange_done) {
3297 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3298 return;
3299 }
3300
Roshan Pius3a1667e2018-07-03 15:17:14 -07003301 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3302 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3303
3304 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003305 if (!msg) {
3306 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3307 return;
3308 }
3309
3310 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3311 MAC2STR(src));
3312
3313 wait_time = wpa_s->max_remain_on_chan;
3314 if (wait_time > 2000)
3315 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003316 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3317 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003318 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3319 broadcast,
3320 wpabuf_head(msg), wpabuf_len(msg),
3321 wait_time, wpas_dpp_tx_pkex_status, 0);
3322 wpabuf_free(msg);
3323}
3324
3325
Roshan Pius3a1667e2018-07-03 15:17:14 -07003326static struct dpp_bootstrap_info *
3327wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3328 unsigned int freq)
3329{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003330 struct dpp_bootstrap_info *bi;
3331
Sunil Ravi89eba102022-09-13 21:04:37 -07003332 wpas_dpp_pkex_clear_code(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003333 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003334 if (!bi)
3335 return NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003336
Roshan Pius3a1667e2018-07-03 15:17:14 -07003337 wpa_s->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003338
3339#ifdef CONFIG_DPP3
3340 if (wpa_s->dpp_pb_bi && !wpa_s->dpp_pb_configurator &&
3341 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_init_hash,
3342 SHA256_MAC_LEN) != 0) {
3343 char id[20];
3344
3345 wpa_printf(MSG_INFO,
3346 "DPP: Peer bootstrap key from PKEX does not match PB announcement response hash");
3347 wpa_hexdump(MSG_DEBUG,
3348 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3349 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3350 wpa_hexdump(MSG_DEBUG,
3351 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement response",
3352 wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN);
3353
3354 os_snprintf(id, sizeof(id), "%u", bi->id);
3355 dpp_bootstrap_remove(wpa_s->dpp, id);
3356 wpas_dpp_push_button_stop(wpa_s);
3357 return NULL;
3358 }
3359#endif /* CONFIG_DPP3 */
3360
Roshan Pius3a1667e2018-07-03 15:17:14 -07003361 return bi;
3362}
3363
3364
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003365static void
3366wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3367 const u8 *hdr, const u8 *buf, size_t len,
3368 unsigned int freq)
3369{
3370 struct wpabuf *msg;
3371 unsigned int wait_time;
3372 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003373
3374 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3375 MAC2STR(src));
3376
3377 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3378 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3379 return;
3380 }
3381
3382 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3383 if (!msg) {
3384 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003385 if (pkex->failed) {
3386 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3387 if (pkex->t > pkex->own_bi->pkex_t)
3388 pkex->own_bi->pkex_t = pkex->t;
3389 dpp_pkex_free(wpa_s->dpp_pkex);
3390 wpa_s->dpp_pkex = NULL;
3391 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003392 return;
3393 }
3394
3395 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3396 MACSTR, MAC2STR(src));
3397
3398 wait_time = wpa_s->max_remain_on_chan;
3399 if (wait_time > 2000)
3400 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003401 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3402 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003403 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3404 broadcast,
3405 wpabuf_head(msg), wpabuf_len(msg),
3406 wait_time, wpas_dpp_tx_pkex_status, 0);
3407 wpabuf_free(msg);
3408
Roshan Pius3a1667e2018-07-03 15:17:14 -07003409 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003410 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003411}
3412
3413
3414static void
3415wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3416 const u8 *hdr, const u8 *buf, size_t len,
3417 unsigned int freq)
3418{
3419 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003420 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003421 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3422 char cmd[500];
3423
3424 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3425 MAC2STR(src));
3426
3427 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3428 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3429 return;
3430 }
3431
3432 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3433 if (res < 0) {
3434 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3435 return;
3436 }
3437
Roshan Pius3a1667e2018-07-03 15:17:14 -07003438 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003439 if (!bi)
3440 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003441
Sunil Ravi89eba102022-09-13 21:04:37 -07003442#ifdef CONFIG_DPP3
3443 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_configurator &&
3444 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_resp_hash,
3445 SHA256_MAC_LEN) != 0) {
3446 char id[20];
3447
3448 wpa_printf(MSG_INFO,
3449 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
3450 wpa_hexdump(MSG_DEBUG,
3451 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3452 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3453 wpa_hexdump(MSG_DEBUG,
3454 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
3455 wpa_s->dpp_pb_resp_hash, SHA256_MAC_LEN);
3456
3457 os_snprintf(id, sizeof(id), "%u", bi->id);
3458 dpp_bootstrap_remove(wpa_s->dpp, id);
3459 wpas_dpp_push_button_stop(wpa_s);
3460 return;
3461 }
3462#endif /* CONFIG_DPP3 */
3463
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003464 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3465 bi->id,
3466 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3467 wpa_printf(MSG_DEBUG,
3468 "DPP: Start authentication after PKEX with parameters: %s",
3469 cmd);
3470 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3471 wpa_printf(MSG_DEBUG,
3472 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003473 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003474 return;
3475 }
3476}
3477
3478
Sunil Ravi89eba102022-09-13 21:04:37 -07003479#ifdef CONFIG_DPP3
3480
3481static void wpas_dpp_pb_pkex_init(struct wpa_supplicant *wpa_s,
3482 unsigned int freq, const u8 *src,
3483 const u8 *r_hash)
3484{
3485 struct dpp_pkex *pkex;
3486 struct wpabuf *msg;
3487 unsigned int wait_time;
3488 size_t len;
3489
3490 if (wpa_s->dpp_pkex) {
3491 wpa_printf(MSG_DEBUG,
3492 "DPP: Sending previously generated PKEX Exchange Request to "
3493 MACSTR, MAC2STR(src));
3494 msg = wpa_s->dpp_pkex->exchange_req;
3495 wait_time = wpa_s->max_remain_on_chan;
3496 if (wait_time > 2000)
3497 wait_time = 2000;
3498 offchannel_send_action(wpa_s, freq, src,
3499 wpa_s->own_addr, broadcast,
3500 wpabuf_head(msg), wpabuf_len(msg),
3501 wait_time, wpas_dpp_tx_pkex_status, 0);
3502 return;
3503 }
3504
3505 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
3506 MACSTR, MAC2STR(src));
3507
3508 if (!wpa_s->dpp_pb_cmd) {
3509 wpa_printf(MSG_INFO,
3510 "DPP: No configuration to provision as push button Configurator");
3511 wpas_dpp_push_button_stop(wpa_s);
3512 return;
3513 }
3514
3515 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
3516 os_memcpy(wpa_s->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
3517
3518 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3519 "PBPKEX", (const char *) wpa_s->dpp_pb_c_nonce,
3520 wpa_s->dpp_pb_bi->curve->nonce_len,
3521 true);
3522 if (!pkex) {
3523 wpas_dpp_push_button_stop(wpa_s);
3524 return;
3525 }
3526 pkex->freq = freq;
3527
3528 wpa_s->dpp_pkex = pkex;
3529 msg = wpa_s->dpp_pkex->exchange_req;
3530 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3531 " freq=%u type=%d", MAC2STR(src), freq,
3532 DPP_PA_PKEX_EXCHANGE_REQ);
3533 wait_time = wpa_s->max_remain_on_chan;
3534 if (wait_time > 2000)
3535 wait_time = 2000;
3536 offchannel_send_action(wpa_s, pkex->freq, src,
3537 wpa_s->own_addr, broadcast,
3538 wpabuf_head(msg), wpabuf_len(msg),
3539 wait_time, wpas_dpp_tx_pkex_status, 0);
3540 pkex->exch_req_wait_time = 2000;
3541 pkex->exch_req_tries = 1;
3542
3543 /* Use the externally provided configuration */
3544 os_free(wpa_s->dpp_pkex_auth_cmd);
3545 len = 30 + os_strlen(wpa_s->dpp_pb_cmd);
3546 wpa_s->dpp_pkex_auth_cmd = os_malloc(len);
3547 if (wpa_s->dpp_pkex_auth_cmd)
3548 os_snprintf(wpa_s->dpp_pkex_auth_cmd, len, " own=%d %s",
3549 wpa_s->dpp_pkex_bi->id, wpa_s->dpp_pb_cmd);
3550 else
3551 wpas_dpp_push_button_stop(wpa_s);
3552}
3553
3554
3555static void
3556wpas_dpp_rx_pb_presence_announcement(struct wpa_supplicant *wpa_s,
3557 const u8 *src, const u8 *hdr,
3558 const u8 *buf, size_t len,
3559 unsigned int freq)
3560{
3561 const u8 *r_hash;
3562 u16 r_hash_len;
3563 unsigned int i;
3564 bool found = false;
3565 struct dpp_pb_info *info, *tmp;
3566 struct os_reltime now, age;
3567 struct wpabuf *msg;
3568
3569 os_get_reltime(&now);
3570 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
3571 MACSTR, MAC2STR(src));
3572
3573 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3574 &r_hash_len);
3575 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
3576 wpa_printf(MSG_DEBUG,
3577 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
3578 return;
3579 }
3580 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3581 r_hash, r_hash_len);
3582
3583 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3584 info = &wpa_s->dpp_pb[i];
3585 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
3586 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
3587 continue;
3588 wpa_printf(MSG_DEBUG,
3589 "DPP: Active push button Enrollee already known");
3590 found = true;
3591 info->rx_time = now;
3592 }
3593
3594 if (!found) {
3595 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3596 tmp = &wpa_s->dpp_pb[i];
3597 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
3598 continue;
3599
3600 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
3601 wpa_hexdump(MSG_DEBUG,
3602 "DPP: Push button Enrollee hash expired",
3603 tmp->hash, SHA256_MAC_LEN);
3604 tmp->rx_time.sec = 0;
3605 tmp->rx_time.usec = 0;
3606 continue;
3607 }
3608
3609 wpa_hexdump(MSG_DEBUG,
3610 "DPP: Push button session overlap with hash",
3611 tmp->hash, SHA256_MAC_LEN);
3612 if (!wpa_s->dpp_pb_result_indicated &&
3613 wpas_dpp_pb_active(wpa_s)) {
3614 wpa_msg(wpa_s, MSG_INFO,
3615 DPP_EVENT_PB_RESULT "session-overlap");
3616 wpa_s->dpp_pb_result_indicated = true;
3617 }
3618 wpas_dpp_push_button_stop(wpa_s);
3619 return;
3620 }
3621
3622 /* Replace the oldest entry */
3623 info = &wpa_s->dpp_pb[0];
3624 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
3625 tmp = &wpa_s->dpp_pb[i];
3626 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
3627 info = tmp;
3628 }
3629 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
3630 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
3631 info->rx_time = now;
3632 }
3633
3634 if (!wpas_dpp_pb_active(wpa_s)) {
3635 wpa_printf(MSG_DEBUG,
3636 "DPP: Discard message since own push button has not been pressed");
3637 return;
3638 }
3639
3640 if (wpa_s->dpp_pb_announce_time.sec == 0 &&
3641 wpa_s->dpp_pb_announce_time.usec == 0) {
3642 /* Start a wait before allowing PKEX to be initiated */
3643 wpa_s->dpp_pb_announce_time = now;
3644 }
3645
3646 if (!wpa_s->dpp_pb_bi) {
3647 int res;
3648
3649 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
3650 if (res < 0)
3651 return;
3652 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
3653 if (!wpa_s->dpp_pb_bi)
3654 return;
3655
3656 if (random_get_bytes(wpa_s->dpp_pb_c_nonce,
3657 wpa_s->dpp_pb_bi->curve->nonce_len)) {
3658 wpa_printf(MSG_ERROR,
3659 "DPP: Failed to generate C-nonce");
3660 wpas_dpp_push_button_stop(wpa_s);
3661 return;
3662 }
3663 }
3664
3665 /* Skip the response if one was sent within last 50 ms since the
3666 * Enrollee is going to send out at least three announcement messages.
3667 */
3668 os_reltime_sub(&now, &wpa_s->dpp_pb_last_resp, &age);
3669 if (age.sec == 0 && age.usec < 50000) {
3670 wpa_printf(MSG_DEBUG,
3671 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
3672 return;
3673 }
3674
3675 msg = dpp_build_pb_announcement_resp(
3676 wpa_s->dpp_pb_bi, r_hash, wpa_s->dpp_pb_c_nonce,
3677 wpa_s->dpp_pb_bi->curve->nonce_len);
3678 if (!msg) {
3679 wpas_dpp_push_button_stop(wpa_s);
3680 return;
3681 }
3682
3683 wpa_printf(MSG_DEBUG,
3684 "DPP: Send Push Button Presence Announcement Response to "
3685 MACSTR, MAC2STR(src));
3686 wpa_s->dpp_pb_last_resp = now;
3687
3688 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3689 MAC2STR(src), freq, DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
3690 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
3691 wpabuf_head(msg), wpabuf_len(msg),
3692 0, NULL, 0);
3693 wpabuf_free(msg);
3694
3695 if (os_reltime_expired(&now, &wpa_s->dpp_pb_announce_time, 15))
3696 wpas_dpp_pb_pkex_init(wpa_s, freq, src, r_hash);
3697}
3698
3699
3700static void
3701wpas_dpp_rx_pb_presence_announcement_resp(struct wpa_supplicant *wpa_s,
3702 const u8 *src, const u8 *hdr,
3703 const u8 *buf, size_t len,
3704 unsigned int freq)
3705{
3706 const u8 *i_hash, *r_hash, *c_nonce;
3707 u16 i_hash_len, r_hash_len, c_nonce_len;
3708 bool overlap = false;
3709
3710 if (!wpa_s->dpp_pb_announcement || !wpa_s->dpp_pb_bi ||
3711 wpa_s->dpp_pb_configurator) {
3712 wpa_printf(MSG_INFO,
3713 "DPP: Not in active push button Enrollee mode - discard Push Button Presence Announcement Response from "
3714 MACSTR, MAC2STR(src));
3715 return;
3716 }
3717
3718 wpa_printf(MSG_DEBUG,
3719 "DPP: Push Button Presence Announcement Response from "
3720 MACSTR, MAC2STR(src));
3721
3722 i_hash = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3723 &i_hash_len);
3724 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3725 &r_hash_len);
3726 c_nonce = dpp_get_attr(buf, len, DPP_ATTR_CONFIGURATOR_NONCE,
3727 &c_nonce_len);
3728 if (!i_hash || i_hash_len != SHA256_MAC_LEN ||
3729 !r_hash || r_hash_len != SHA256_MAC_LEN ||
3730 !c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
3731 wpa_printf(MSG_DEBUG,
3732 "DPP: Missing or invalid required attribute");
3733 return;
3734 }
3735 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
3736 i_hash, i_hash_len);
3737 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3738 r_hash, r_hash_len);
3739 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator Nonce",
3740 c_nonce, c_nonce_len);
3741
3742#ifdef CONFIG_TESTING_OPTIONS
3743 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ &&
3744 os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3745 SHA256_MAC_LEN - 1) == 0)
3746 goto skip_hash_check;
3747#endif /* CONFIG_TESTING_OPTIONS */
3748 if (os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3749 SHA256_MAC_LEN) != 0) {
3750 wpa_printf(MSG_INFO,
3751 "DPP: Unexpected push button Responder hash - abort");
3752 overlap = true;
3753 }
3754#ifdef CONFIG_TESTING_OPTIONS
3755skip_hash_check:
3756#endif /* CONFIG_TESTING_OPTIONS */
3757
3758 if (wpa_s->dpp_pb_resp_freq &&
3759 os_memcmp(i_hash, wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN) != 0) {
3760 wpa_printf(MSG_INFO,
3761 "DPP: Push button session overlap detected - abort");
3762 overlap = true;
3763 }
3764
3765 if (overlap) {
3766 if (!wpa_s->dpp_pb_result_indicated) {
3767 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
3768 "session-overlap");
3769 wpa_s->dpp_pb_result_indicated = true;
3770 }
3771 wpas_dpp_push_button_stop(wpa_s);
3772 return;
3773 }
3774
3775 if (!wpa_s->dpp_pb_resp_freq) {
3776 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
3777 "discovered push button AP/Configurator " MACSTR,
3778 MAC2STR(src));
3779 wpa_s->dpp_pb_resp_freq = freq;
3780 os_memcpy(wpa_s->dpp_pb_init_hash, i_hash, SHA256_MAC_LEN);
3781 os_memcpy(wpa_s->dpp_pb_c_nonce, c_nonce, c_nonce_len);
3782 wpa_s->dpp_pb_c_nonce_len = c_nonce_len;
3783 /* Stop announcement iterations after at least one more full
3784 * round and one extra round for postponed session overlap
3785 * detection. */
3786 wpa_s->dpp_pb_stop_iter = 3;
3787 }
3788}
3789
3790
3791static void
3792wpas_dpp_tx_priv_intro_status(struct wpa_supplicant *wpa_s,
3793 unsigned int freq, const u8 *dst,
3794 const u8 *src, const u8 *bssid,
3795 const u8 *data, size_t data_len,
3796 enum offchannel_send_action_result result)
3797{
3798 const char *res_txt;
3799
3800 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3801 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3802 "FAILED");
3803 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3804 " result=%s (DPP Private Peer Introduction Update)",
3805 freq, MAC2STR(dst), res_txt);
3806 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3807 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3808
3809 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR " version=%u",
3810 MAC2STR(src), wpa_s->dpp_intro_peer_version);
3811
3812 wpa_printf(MSG_DEBUG,
3813 "DPP: Try connection again after successful network introduction");
3814 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3815 wpa_supplicant_cancel_sched_scan(wpa_s);
3816 wpa_supplicant_req_scan(wpa_s, 0, 0);
3817 }
3818}
3819
3820
3821static int
3822wpas_dpp_send_private_peer_intro_update(struct wpa_supplicant *wpa_s,
3823 struct dpp_introduction *intro,
3824 struct wpa_ssid *ssid,
3825 const u8 *dst, unsigned int freq)
3826{
3827 struct wpabuf *pt, *msg, *enc_ct;
3828 size_t len;
3829 u8 ver = DPP_VERSION;
3830 int conn_ver;
3831 const u8 *aad;
3832 size_t aad_len;
3833 unsigned int wait_time;
3834
3835 wpa_printf(MSG_DEBUG, "HPKE(kem_id=%u kdf_id=%u aead_id=%u)",
3836 intro->kem_id, intro->kdf_id, intro->aead_id);
3837
3838 /* Plaintext for HPKE */
3839 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3840 pt = wpabuf_alloc(len);
3841 if (!pt)
3842 return -1;
3843
3844 /* Protocol Version */
3845 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3846 if (conn_ver > 0 && ver != conn_ver) {
3847 wpa_printf(MSG_DEBUG,
3848 "DPP: Use Connector version %d instead of current protocol version %d",
3849 conn_ver, ver);
3850 ver = conn_ver;
3851 }
3852 wpabuf_put_le16(pt, DPP_ATTR_PROTOCOL_VERSION);
3853 wpabuf_put_le16(pt, 1);
3854 wpabuf_put_u8(pt, ver);
3855
3856 /* Connector */
3857 wpabuf_put_le16(pt, DPP_ATTR_CONNECTOR);
3858 wpabuf_put_le16(pt, os_strlen(ssid->dpp_connector));
3859 wpabuf_put_str(pt, ssid->dpp_connector);
3860 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Plaintext for HPKE", pt);
3861
3862 /* HPKE(pt) using AP's public key (from its Connector) */
3863 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, 0);
3864 if (!msg) {
3865 wpabuf_free(pt);
3866 return -1;
3867 }
3868 aad = wpabuf_head_u8(msg) + 2; /* from the OUI field (inclusive) */
3869 aad_len = DPP_HDR_LEN; /* to the DPP Frame Type field (inclusive) */
3870 wpa_hexdump(MSG_MSGDUMP, "DPP: AAD for HPKE", aad, aad_len);
3871
3872 enc_ct = hpke_base_seal(intro->kem_id, intro->kdf_id, intro->aead_id,
3873 intro->peer_key, NULL, 0, aad, aad_len,
3874 wpabuf_head(pt), wpabuf_len(pt));
3875 wpabuf_free(pt);
3876 wpabuf_free(msg);
3877 if (!enc_ct) {
3878 wpa_printf(MSG_INFO, "DPP: HPKE Seal(Connector) failed");
3879 return -1;
3880 }
3881 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE enc|ct", enc_ct);
3882
3883 /* HPKE(pt) to generate payload for Wrapped Data */
3884 len = 5 + 4 + wpabuf_len(enc_ct);
3885 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, len);
3886 if (!msg) {
3887 wpabuf_free(enc_ct);
3888 return -1;
3889 }
3890
3891 /* Transaction ID */
3892 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3893 wpabuf_put_le16(msg, 1);
3894 wpabuf_put_u8(msg, TRANSACTION_ID);
3895
3896 /* Wrapped Data */
3897 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3898 wpabuf_put_le16(msg, wpabuf_len(enc_ct));
3899 wpabuf_put_buf(msg, enc_ct);
3900 wpabuf_free(enc_ct);
3901
3902 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Update", msg);
3903
3904 /* TODO: Timeout on AP response */
3905 wait_time = wpa_s->max_remain_on_chan;
3906 if (wait_time > 2000)
3907 wait_time = 2000;
3908 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3909 MAC2STR(dst), freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
3910 offchannel_send_action(wpa_s, freq, dst, wpa_s->own_addr, broadcast,
3911 wpabuf_head(msg), wpabuf_len(msg),
3912 wait_time, wpas_dpp_tx_priv_intro_status, 0);
3913 wpabuf_free(msg);
3914
3915 return 0;
3916}
3917
3918
3919static void
3920wpas_dpp_rx_priv_peer_intro_notify(struct wpa_supplicant *wpa_s,
3921 const u8 *src, const u8 *hdr,
3922 const u8 *buf, size_t len,
3923 unsigned int freq)
3924{
3925 struct wpa_ssid *ssid;
3926 const u8 *connector, *trans_id, *version;
3927 u16 connector_len, trans_id_len, version_len;
3928 u8 peer_version = 1;
3929 struct dpp_introduction intro;
3930 struct rsn_pmksa_cache_entry *entry;
3931 struct os_time now;
3932 struct os_reltime rnow;
3933 os_time_t expiry;
3934 unsigned int seconds;
3935 enum dpp_status_error res;
3936
3937 os_memset(&intro, 0, sizeof(intro));
3938
3939 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
3940 MACSTR, MAC2STR(src));
3941 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003942 !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
Sunil Ravi89eba102022-09-13 21:04:37 -07003943 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
3944 MACSTR " - drop", MAC2STR(src));
3945 return;
3946 }
3947 offchannel_send_action_done(wpa_s);
3948
3949 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3950 if (ssid == wpa_s->dpp_intro_network)
3951 break;
3952 }
3953 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3954 !ssid->dpp_csign) {
3955 wpa_printf(MSG_DEBUG,
3956 "DPP: Profile not found for network introduction");
3957 return;
3958 }
3959
3960 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
3961 &trans_id_len);
3962 if (!trans_id || trans_id_len != 1) {
3963 wpa_printf(MSG_DEBUG,
3964 "DPP: Peer did not include Transaction ID");
3965 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3966 " fail=missing_transaction_id", MAC2STR(src));
3967 goto fail;
3968 }
3969 if (trans_id[0] != TRANSACTION_ID) {
3970 wpa_printf(MSG_DEBUG,
3971 "DPP: Ignore frame with unexpected Transaction ID %u",
3972 trans_id[0]);
3973 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3974 " fail=transaction_id_mismatch", MAC2STR(src));
3975 goto fail;
3976 }
3977
3978 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
3979 if (!connector) {
3980 wpa_printf(MSG_DEBUG,
3981 "DPP: Peer did not include its Connector");
3982 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3983 " fail=missing_connector", MAC2STR(src));
3984 goto fail;
3985 }
3986
3987 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
3988 &version_len);
3989 if (!version || version_len < 1) {
3990 wpa_printf(MSG_DEBUG,
3991 "DPP: Peer did not include valid Version");
3992 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3993 " fail=missing_version", MAC2STR(src));
3994 goto fail;
3995 }
3996
3997 res = dpp_peer_intro(&intro, ssid->dpp_connector,
3998 ssid->dpp_netaccesskey,
3999 ssid->dpp_netaccesskey_len,
4000 ssid->dpp_csign,
4001 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004002 connector, connector_len, &expiry, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07004003 if (res != DPP_STATUS_OK) {
4004 wpa_printf(MSG_INFO,
4005 "DPP: Network Introduction protocol resulted in failure");
4006 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
4007 " fail=peer_connector_validation_failed", MAC2STR(src));
4008 wpas_dpp_send_conn_status_result(wpa_s, res);
4009 goto fail;
4010 }
4011
4012 peer_version = version[0];
4013 if (intro.peer_version && intro.peer_version >= 2 &&
4014 peer_version != intro.peer_version) {
4015 wpa_printf(MSG_INFO,
4016 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
4017 intro.peer_version, peer_version);
4018 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
4019 goto fail;
4020 }
4021 wpa_s->dpp_intro_peer_version = peer_version;
4022
4023 entry = os_zalloc(sizeof(*entry));
4024 if (!entry)
4025 goto fail;
4026 entry->dpp_pfs = peer_version >= 2;
4027 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004028 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Sunil Ravi89eba102022-09-13 21:04:37 -07004029 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
4030 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
4031 entry->pmk_len = intro.pmk_len;
4032 entry->akmp = WPA_KEY_MGMT_DPP;
4033 if (expiry) {
4034 os_get_time(&now);
4035 seconds = expiry - now.sec;
4036 } else {
4037 seconds = 86400 * 7;
4038 }
4039
4040 if (wpas_dpp_send_private_peer_intro_update(wpa_s, &intro, ssid, src,
4041 freq) < 0) {
4042 os_free(entry);
4043 goto fail;
4044 }
4045
4046 os_get_reltime(&rnow);
4047 entry->expiration = rnow.sec + seconds;
4048 entry->reauth_time = rnow.sec + seconds;
4049 entry->network_ctx = ssid;
4050 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
4051
4052 /* Association will be initiated from TX status handler for the Private
4053 * Peer Intro Update: wpas_dpp_tx_priv_intro_status() */
4054
4055fail:
4056 dpp_peer_intro_deinit(&intro);
4057}
4058
4059#endif /* CONFIG_DPP3 */
4060
4061
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004062void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
4063 const u8 *buf, size_t len, unsigned int freq)
4064{
4065 u8 crypto_suite;
4066 enum dpp_public_action_frame_type type;
4067 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004068 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004069
4070 if (len < DPP_HDR_LEN)
4071 return;
4072 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
4073 return;
4074 hdr = buf;
4075 buf += 4;
4076 len -= 4;
4077 crypto_suite = *buf++;
4078 type = *buf++;
4079 len -= 2;
4080
4081 wpa_printf(MSG_DEBUG,
4082 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
4083 MACSTR " freq=%u",
4084 crypto_suite, type, MAC2STR(src), freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07004085#ifdef CONFIG_TESTING_OPTIONS
4086 if (wpa_s->dpp_discard_public_action &&
4087 type != DPP_PA_PEER_DISCOVERY_RESP &&
4088 type != DPP_PA_PRIV_PEER_INTRO_NOTIFY) {
4089 wpa_printf(MSG_DEBUG,
4090 "TESTING: Discard received DPP Public Action frame");
4091 return;
4092 }
4093#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004094 if (crypto_suite != 1) {
4095 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
4096 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004097 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4098 " freq=%u type=%d ignore=unsupported-crypto-suite",
4099 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004100 return;
4101 }
4102 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004103 if (dpp_check_attrs(buf, len) < 0) {
4104 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4105 " freq=%u type=%d ignore=invalid-attributes",
4106 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004107 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004108 }
4109 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
4110 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004111
4112 switch (type) {
4113 case DPP_PA_AUTHENTICATION_REQ:
4114 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
4115 break;
4116 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07004117 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004118 break;
4119 case DPP_PA_AUTHENTICATION_CONF:
4120 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
4121 break;
4122 case DPP_PA_PEER_DISCOVERY_RESP:
4123 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
4124 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004125#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004126 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004127 /* This is for PKEXv2, but for now, process only with
4128 * CONFIG_DPP3 to avoid issues with a capability that has not
4129 * been tested with other implementations. */
4130 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
4131 break;
4132#endif /* CONFIG_DPP3 */
4133 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
4134 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
4135 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004136 break;
4137 case DPP_PA_PKEX_EXCHANGE_RESP:
4138 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
4139 break;
4140 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
4141 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
4142 freq);
4143 break;
4144 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
4145 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
4146 freq);
4147 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004148#ifdef CONFIG_DPP2
4149 case DPP_PA_CONFIGURATION_RESULT:
4150 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
4151 break;
Hai Shalomc3565922019-10-28 11:58:20 -07004152 case DPP_PA_CONNECTION_STATUS_RESULT:
4153 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
4154 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07004155 case DPP_PA_PRESENCE_ANNOUNCEMENT:
4156 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
4157 freq);
4158 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004159 case DPP_PA_RECONFIG_ANNOUNCEMENT:
4160 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
4161 freq);
4162 break;
4163 case DPP_PA_RECONFIG_AUTH_REQ:
4164 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
4165 break;
4166 case DPP_PA_RECONFIG_AUTH_RESP:
4167 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
4168 break;
4169 case DPP_PA_RECONFIG_AUTH_CONF:
4170 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
4171 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004172#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07004173#ifdef CONFIG_DPP3
4174 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
4175 wpas_dpp_rx_pb_presence_announcement(wpa_s, src, hdr,
4176 buf, len, freq);
4177 break;
4178 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP:
4179 wpas_dpp_rx_pb_presence_announcement_resp(wpa_s, src, hdr,
4180 buf, len, freq);
4181 break;
4182 case DPP_PA_PRIV_PEER_INTRO_NOTIFY:
4183 wpas_dpp_rx_priv_peer_intro_notify(wpa_s, src, hdr,
4184 buf, len, freq);
4185 break;
4186#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004187 default:
4188 wpa_printf(MSG_DEBUG,
4189 "DPP: Ignored unsupported frame subtype %d", type);
4190 break;
4191 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004192
4193 if (wpa_s->dpp_pkex)
4194 pkex_t = wpa_s->dpp_pkex->t;
4195 else if (wpa_s->dpp_pkex_bi)
4196 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
4197 else
4198 pkex_t = 0;
4199 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
4200 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
4201 wpas_dpp_pkex_remove(wpa_s, "*");
4202 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004203}
4204
4205
Hai Shaloma20dcd72022-02-04 13:43:00 -08004206static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
4207 void *timeout_ctx)
4208{
4209 struct wpa_supplicant *wpa_s = eloop_ctx;
4210 struct dpp_authentication *auth = wpa_s->dpp_auth;
4211
4212 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
4213 return;
4214
4215 wpa_printf(MSG_DEBUG,
4216 "DPP: No configuration available from upper layers - send initial response with comeback delay");
4217 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
4218 500);
4219}
4220
4221
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004222static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07004223wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08004224 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004225{
4226 struct wpa_supplicant *wpa_s = ctx;
4227 struct dpp_authentication *auth = wpa_s->dpp_auth;
4228 struct wpabuf *resp;
4229
4230 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
4231 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004232 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004233 !ether_addr_equal(sa, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004234 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
4235 return NULL;
4236 }
Hai Shalomc3565922019-10-28 11:58:20 -07004237
4238 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
4239 wpa_printf(MSG_DEBUG,
4240 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
4241 /* wpas_dpp_auth_success() would normally have been called from
4242 * TX status handler, but since there was no such handler call
4243 * yet, simply send out the event message and proceed with
4244 * exchange. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004245 dpp_notify_auth_success(auth, 1);
Hai Shalomc3565922019-10-28 11:58:20 -07004246 wpa_s->dpp_auth_ok_on_ack = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004247#ifdef CONFIG_TESTING_OPTIONS
4248 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
4249 wpa_printf(MSG_INFO,
4250 "DPP: TESTING - stop at Authentication Confirm");
4251 return NULL;
4252 }
4253#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07004254 }
4255
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004256 wpa_hexdump(MSG_DEBUG,
4257 "DPP: Received Configuration Request (GAS Query Request)",
4258 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004259 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
4260 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004261 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004262
Hai Shaloma20dcd72022-02-04 13:43:00 -08004263 auth->gas_server_ctx = resp_ctx;
4264
Hai Shalom899fcc72020-10-19 14:38:18 -07004265#ifdef CONFIG_DPP2
4266 if (!resp && auth->waiting_cert) {
4267 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08004268 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07004269 *comeback_delay = 500;
4270 return NULL;
4271 }
4272#endif /* CONFIG_DPP2 */
4273
Hai Shaloma20dcd72022-02-04 13:43:00 -08004274 if (!resp && auth->waiting_config &&
4275 (auth->peer_bi || auth->tmp_peer_bi)) {
4276 char *buf = NULL, *name = "";
4277 char band[200], *pos, *end;
4278 int i, res, *opclass = auth->e_band_support;
4279 char *mud_url = "N/A";
4280
4281 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
4282 auth->config_resp_ctx = resp_ctx;
4283 *comeback_delay = -1;
4284 if (auth->e_name) {
4285 size_t len = os_strlen(auth->e_name);
4286
4287 buf = os_malloc(len * 4 + 1);
4288 if (buf) {
4289 printf_encode(buf, len * 4 + 1,
4290 (const u8 *) auth->e_name, len);
4291 name = buf;
4292 }
4293 }
4294 band[0] = '\0';
4295 pos = band;
4296 end = band + sizeof(band);
4297 for (i = 0; opclass && opclass[i]; i++) {
4298 res = os_snprintf(pos, end - pos, "%s%d",
4299 pos == band ? "" : ",", opclass[i]);
4300 if (os_snprintf_error(end - pos, res)) {
4301 *pos = '\0';
4302 break;
4303 }
4304 pos += res;
4305 }
4306 if (auth->e_mud_url) {
4307 size_t len = os_strlen(auth->e_mud_url);
4308
4309 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
4310 mud_url = auth->e_mud_url;
4311 }
4312 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
4313 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
4314 auth->peer_bi ? auth->peer_bi->id :
4315 auth->tmp_peer_bi->id, MAC2STR(sa),
4316 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
4317 os_free(buf);
4318
4319 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4320 NULL);
4321 eloop_register_timeout(0, 50000,
4322 wpas_dpp_gas_initial_resp_timeout, wpa_s,
4323 NULL);
4324 return NULL;
4325 }
4326
Sunil Ravia04bd252022-05-02 22:54:18 -07004327 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08004328 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004329 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004330 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07004331 dpp_auth_deinit(wpa_s->dpp_auth);
4332 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08004333 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004334 return resp;
4335}
4336
4337
4338static void
4339wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
4340{
4341 struct wpa_supplicant *wpa_s = ctx;
4342 struct dpp_authentication *auth = wpa_s->dpp_auth;
4343
4344 if (!auth) {
4345 wpabuf_free(resp);
4346 return;
4347 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004348 if (auth->conf_resp != resp) {
4349 wpa_printf(MSG_DEBUG,
4350 "DPP: Ignore GAS status report (ok=%d) for unknown response",
4351 ok);
4352 wpabuf_free(resp);
4353 return;
4354 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004355
Hai Shalom899fcc72020-10-19 14:38:18 -07004356#ifdef CONFIG_DPP2
4357 if (auth->waiting_csr && ok) {
4358 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
4359 wpabuf_free(resp);
4360 return;
4361 }
4362#endif /* CONFIG_DPP2 */
4363
Sunil Ravia04bd252022-05-02 22:54:18 -07004364#ifdef CONFIG_DPP3
4365 if (auth->waiting_new_key && ok) {
4366 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
4367 wpabuf_free(resp);
4368 return;
4369 }
4370#endif /* CONFIG_DPP3 */
4371
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004372 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
4373 ok);
4374 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004375 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004376 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004377#ifdef CONFIG_DPP2
4378 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08004379 auth->conf_resp_status == DPP_STATUS_OK &&
4380 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07004381 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08004382 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07004383 auth->waiting_conf_result = 1;
4384 auth->conf_resp = NULL;
4385 wpabuf_free(resp);
4386 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
4387 wpa_s, NULL);
4388 eloop_register_timeout(2, 0,
4389 wpas_dpp_config_result_wait_timeout,
4390 wpa_s, NULL);
4391 return;
4392 }
4393#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004394 offchannel_send_action_done(wpa_s);
4395 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004396 if (ok) {
Sunil Ravi89eba102022-09-13 21:04:37 -07004397 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
4398 auth->conf_resp_status);
Hai Shalom706f99b2019-01-08 16:23:37 -08004399 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004400 }
4401 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004402 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004403 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004404 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004405 dpp_auth_deinit(wpa_s->dpp_auth);
4406 wpa_s->dpp_auth = NULL;
4407 wpabuf_free(resp);
Sunil Ravi89eba102022-09-13 21:04:37 -07004408#ifdef CONFIG_DPP3
4409 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
4410 if (ok)
4411 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4412 "success");
4413 else
4414 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4415 "could-not-connect");
4416 wpa_s->dpp_pb_result_indicated = true;
4417 if (ok)
4418 wpas_dpp_remove_pb_hash(wpa_s);
4419 wpas_dpp_push_button_stop(wpa_s);
4420 }
4421#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004422}
4423
4424
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004425int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
4426{
4427 struct dpp_authentication *auth;
4428 int ret = -1;
4429 char *curve = NULL;
4430
Hai Shalomfdcde762020-04-02 11:19:20 -07004431 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004432 if (!auth)
4433 return -1;
4434
4435 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08004436 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07004437 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004438 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07004439 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
4440 &auth->conf_obj[0]);
4441 if (!ret)
4442 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004443
4444 dpp_auth_deinit(auth);
4445 os_free(curve);
4446
4447 return ret;
4448}
4449
4450
4451static void
4452wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
4453 unsigned int freq, const u8 *dst,
4454 const u8 *src, const u8 *bssid,
4455 const u8 *data, size_t data_len,
4456 enum offchannel_send_action_result result)
4457{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004458 const char *res_txt;
4459
4460 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
4461 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
4462 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004463 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
4464 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07004465 freq, MAC2STR(dst), res_txt);
4466 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
4467 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004468 /* TODO: Time out wait for response more quickly in error cases? */
4469}
4470
4471
Sunil Ravi89eba102022-09-13 21:04:37 -07004472#ifdef CONFIG_DPP3
4473static int wpas_dpp_start_private_peer_intro(struct wpa_supplicant *wpa_s,
4474 struct wpa_ssid *ssid,
4475 struct wpa_bss *bss)
4476{
4477 struct wpabuf *msg;
4478 unsigned int wait_time;
4479 size_t len;
4480 u8 ver = DPP_VERSION;
4481 int conn_ver;
4482
4483 len = 5 + 5;
4484 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_QUERY, len);
4485 if (!msg)
4486 return -1;
4487
4488 /* Transaction ID */
4489 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4490 wpabuf_put_le16(msg, 1);
4491 wpabuf_put_u8(msg, TRANSACTION_ID);
4492
4493 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4494 if (conn_ver > 0 && ver != conn_ver) {
4495 wpa_printf(MSG_DEBUG,
4496 "DPP: Use Connector version %d instead of current protocol version %d",
4497 conn_ver, ver);
4498 ver = conn_ver;
4499 }
4500
4501 /* Protocol Version */
4502 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4503 wpabuf_put_le16(msg, 1);
4504 wpabuf_put_u8(msg, ver);
4505
4506 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Query", msg);
4507
4508 /* TODO: Timeout on AP response */
4509 wait_time = wpa_s->max_remain_on_chan;
4510 if (wait_time > 2000)
4511 wait_time = 2000;
4512 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4513 MAC2STR(bss->bssid), bss->freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
4514 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4515 broadcast,
4516 wpabuf_head(msg), wpabuf_len(msg),
4517 wait_time, wpas_dpp_tx_introduction_status, 0);
4518 wpabuf_free(msg);
4519
4520 /* Request this connection attempt to terminate - new one will be
4521 * started when network introduction protocol completes */
4522 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4523 wpa_s->dpp_intro_network = ssid;
4524 return 1;
4525}
4526#endif /* CONFIG_DPP3 */
4527
4528
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004529int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4530 struct wpa_bss *bss)
4531{
4532 struct os_time now;
4533 struct wpabuf *msg;
4534 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07004535 const u8 *rsn;
4536 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004537 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004538
4539 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
4540 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07004541 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4542 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
4543 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
4544 return 0; /* AP does not support DPP AKM - continue */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004545 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, wpa_s->own_addr, ssid))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004546 return 0; /* PMKSA exists for DPP AKM - continue */
4547
4548 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4549 !ssid->dpp_csign) {
4550 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4551 "missing %s",
4552 !ssid->dpp_connector ? "Connector" :
4553 (!ssid->dpp_netaccesskey ? "netAccessKey" :
4554 "C-sign-key"));
4555 return -1;
4556 }
4557
4558 os_get_time(&now);
4559
4560 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07004561 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004562 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4563 "netAccessKey expired");
4564 return -1;
4565 }
4566
4567 wpa_printf(MSG_DEBUG,
Sunil Ravi89eba102022-09-13 21:04:37 -07004568 "DPP: Starting %snetwork introduction protocol to derive PMKSA for "
4569 MACSTR,
4570 ssid->dpp_connector_privacy ? "private " : "",
4571 MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07004572 if (wpa_s->wpa_state == WPA_SCANNING)
4573 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004574
Sunil Ravi89eba102022-09-13 21:04:37 -07004575#ifdef CONFIG_DPP3
4576 if (ssid->dpp_connector_privacy)
4577 return wpas_dpp_start_private_peer_intro(wpa_s, ssid, bss);
4578#endif /* CONFIG_DPP3 */
4579
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004580 len = 5 + 4 + os_strlen(ssid->dpp_connector);
4581#ifdef CONFIG_DPP2
4582 len += 5;
4583#endif /* CONFIG_DPP2 */
4584 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004585 if (!msg)
4586 return -1;
4587
Roshan Pius3a1667e2018-07-03 15:17:14 -07004588#ifdef CONFIG_TESTING_OPTIONS
4589 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
4590 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
4591 goto skip_trans_id;
4592 }
4593 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
4594 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
4595 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4596 wpabuf_put_le16(msg, 0);
4597 goto skip_trans_id;
4598 }
4599#endif /* CONFIG_TESTING_OPTIONS */
4600
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004601 /* Transaction ID */
4602 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4603 wpabuf_put_le16(msg, 1);
4604 wpabuf_put_u8(msg, TRANSACTION_ID);
4605
Roshan Pius3a1667e2018-07-03 15:17:14 -07004606#ifdef CONFIG_TESTING_OPTIONS
4607skip_trans_id:
4608 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
4609 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
4610 goto skip_connector;
4611 }
4612 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
4613 char *connector;
4614
4615 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
4616 connector = dpp_corrupt_connector_signature(
4617 ssid->dpp_connector);
4618 if (!connector) {
4619 wpabuf_free(msg);
4620 return -1;
4621 }
4622 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4623 wpabuf_put_le16(msg, os_strlen(connector));
4624 wpabuf_put_str(msg, connector);
4625 os_free(connector);
4626 goto skip_connector;
4627 }
4628#endif /* CONFIG_TESTING_OPTIONS */
4629
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004630 /* DPP Connector */
4631 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4632 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
4633 wpabuf_put_str(msg, ssid->dpp_connector);
4634
Roshan Pius3a1667e2018-07-03 15:17:14 -07004635#ifdef CONFIG_TESTING_OPTIONS
4636skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004637 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
4638 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
4639 goto skip_proto_ver;
4640 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004641#endif /* CONFIG_TESTING_OPTIONS */
4642
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004643#ifdef CONFIG_DPP2
4644 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004645 u8 ver = DPP_VERSION;
4646#ifdef CONFIG_DPP3
4647 int conn_ver;
4648
4649 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4650 if (conn_ver > 0 && ver != conn_ver) {
4651 wpa_printf(MSG_DEBUG,
4652 "DPP: Use Connector version %d instead of current protocol version %d",
4653 conn_ver, ver);
4654 ver = conn_ver;
4655 }
4656#endif /* CONFIG_DPP3 */
4657
4658#ifdef CONFIG_TESTING_OPTIONS
4659 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
4660 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
4661 ver = 1;
4662 }
4663#endif /* CONFIG_TESTING_OPTIONS */
4664
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004665 /* Protocol Version */
4666 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4667 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004668 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004669 }
4670#endif /* CONFIG_DPP2 */
4671
Hai Shaloma20dcd72022-02-04 13:43:00 -08004672#ifdef CONFIG_TESTING_OPTIONS
4673skip_proto_ver:
4674#endif /* CONFIG_TESTING_OPTIONS */
4675
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004676 /* TODO: Timeout on AP response */
4677 wait_time = wpa_s->max_remain_on_chan;
4678 if (wait_time > 2000)
4679 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004680 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4681 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004682 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4683 broadcast,
4684 wpabuf_head(msg), wpabuf_len(msg),
4685 wait_time, wpas_dpp_tx_introduction_status, 0);
4686 wpabuf_free(msg);
4687
4688 /* Request this connection attempt to terminate - new one will be
4689 * started when network introduction protocol completes */
4690 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4691 wpa_s->dpp_intro_network = ssid;
4692 return 1;
4693}
4694
4695
4696int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
4697{
4698 struct dpp_bootstrap_info *own_bi;
4699 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07004700#ifdef CONFIG_DPP3
4701 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
4702#else /* CONFIG_DPP3 */
4703 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
4704#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004705 int tcp_port = DPP_TCP_PORT;
4706 struct hostapd_ip_addr *ipaddr = NULL;
4707#ifdef CONFIG_DPP2
4708 struct hostapd_ip_addr ipaddr_buf;
4709 char *addr;
4710
4711 pos = os_strstr(cmd, " tcp_port=");
4712 if (pos) {
4713 pos += 10;
4714 tcp_port = atoi(pos);
4715 }
4716
4717 addr = get_param(cmd, " tcp_addr=");
4718 if (addr) {
4719 int res;
4720
4721 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
4722 os_free(addr);
4723 if (res)
4724 return -1;
4725 ipaddr = &ipaddr_buf;
4726 }
4727#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004728
4729 pos = os_strstr(cmd, " own=");
4730 if (!pos)
4731 return -1;
4732 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07004733 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004734 if (!own_bi) {
4735 wpa_printf(MSG_DEBUG,
4736 "DPP: Identified bootstrap info not found");
4737 return -1;
4738 }
4739 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
4740 wpa_printf(MSG_DEBUG,
4741 "DPP: Identified bootstrap info not for PKEX");
4742 return -1;
4743 }
4744 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004745 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004746
4747 os_free(wpa_s->dpp_pkex_identifier);
4748 wpa_s->dpp_pkex_identifier = NULL;
4749 pos = os_strstr(cmd, " identifier=");
4750 if (pos) {
4751 pos += 12;
4752 end = os_strchr(pos, ' ');
4753 if (!end)
4754 return -1;
4755 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
4756 if (!wpa_s->dpp_pkex_identifier)
4757 return -1;
4758 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
4759 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
4760 }
4761
4762 pos = os_strstr(cmd, " code=");
4763 if (!pos)
4764 return -1;
4765 os_free(wpa_s->dpp_pkex_code);
4766 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
4767 if (!wpa_s->dpp_pkex_code)
4768 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004769 wpa_s->dpp_pkex_code_len = os_strlen(wpa_s->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004770
Sunil Ravia04bd252022-05-02 22:54:18 -07004771 pos = os_strstr(cmd, " ver=");
4772 if (pos) {
4773 int v;
4774
4775 pos += 5;
4776 v = atoi(pos);
4777 if (v == 1)
4778 ver = PKEX_VER_ONLY_1;
4779 else if (v == 2)
4780 ver = PKEX_VER_ONLY_2;
4781 else
4782 return -1;
4783 }
4784 wpa_s->dpp_pkex_ver = ver;
4785
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004786 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004787 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004788 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004789 } else {
4790#ifdef CONFIG_DPP2
4791 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
4792 wpa_s->dpp_pkex_code,
4793 wpa_s->dpp_pkex_identifier);
4794#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004795 }
4796
4797 /* TODO: Support multiple PKEX info entries */
4798
4799 os_free(wpa_s->dpp_pkex_auth_cmd);
4800 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
4801
4802 return 1;
4803}
4804
4805
4806int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
4807{
4808 unsigned int id_val;
4809
4810 if (os_strcmp(id, "*") == 0) {
4811 id_val = 0;
4812 } else {
4813 id_val = atoi(id);
4814 if (id_val == 0)
4815 return -1;
4816 }
4817
Sunil Ravi89eba102022-09-13 21:04:37 -07004818 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004819 return -1;
4820
4821 /* TODO: Support multiple PKEX entries */
4822 os_free(wpa_s->dpp_pkex_code);
4823 wpa_s->dpp_pkex_code = NULL;
4824 os_free(wpa_s->dpp_pkex_identifier);
4825 wpa_s->dpp_pkex_identifier = NULL;
4826 os_free(wpa_s->dpp_pkex_auth_cmd);
4827 wpa_s->dpp_pkex_auth_cmd = NULL;
4828 wpa_s->dpp_pkex_bi = NULL;
4829 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
4830 dpp_pkex_free(wpa_s->dpp_pkex);
4831 wpa_s->dpp_pkex = NULL;
4832 return 0;
4833}
4834
4835
Roshan Pius3a1667e2018-07-03 15:17:14 -07004836void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
4837{
Sunil Ravia04bd252022-05-02 22:54:18 -07004838 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07004839 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004840 dpp_auth_deinit(wpa_s->dpp_auth);
4841 wpa_s->dpp_auth = NULL;
4842 dpp_pkex_free(wpa_s->dpp_pkex);
4843 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004844 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004845 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
4846 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
Sunil Ravi89eba102022-09-13 21:04:37 -07004847#ifdef CONFIG_DPP3
4848 wpas_dpp_push_button_stop(wpa_s);
4849#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004850}
4851
4852
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004853int wpas_dpp_init(struct wpa_supplicant *wpa_s)
4854{
Hai Shalom81f62d82019-07-22 12:10:00 -07004855 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004856 u8 adv_proto_id[7];
4857
4858 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
4859 adv_proto_id[1] = 5;
4860 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
4861 adv_proto_id[5] = DPP_OUI_TYPE;
4862 adv_proto_id[6] = 0x01;
4863
4864 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
4865 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
4866 wpas_dpp_gas_status_handler, wpa_s) < 0)
4867 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004868
4869 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07004870 config.cb_ctx = wpa_s;
4871#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004872 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07004873#endif /* CONFIG_DPP2 */
4874 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07004875 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004876}
4877
4878
4879void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
4880{
4881#ifdef CONFIG_TESTING_OPTIONS
4882 os_free(wpa_s->dpp_config_obj_override);
4883 wpa_s->dpp_config_obj_override = NULL;
4884 os_free(wpa_s->dpp_discovery_override);
4885 wpa_s->dpp_discovery_override = NULL;
4886 os_free(wpa_s->dpp_groups_override);
4887 wpa_s->dpp_groups_override = NULL;
4888 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
4889#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07004890 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004891 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004892 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004893 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004894 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004895 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
4896 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004897 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4898 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004899 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
Sunil Ravi99c035e2024-07-12 01:42:03 +00004900 eloop_cancel_timeout(wpas_dpp_tx_auth_resp_roc_timeout, wpa_s, NULL);
4901 eloop_cancel_timeout(wpas_dpp_neg_freq_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004902#ifdef CONFIG_DPP2
4903 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07004904 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
4905 wpa_s, NULL);
4906 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004907 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
4908 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004909 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004910 eloop_cancel_timeout(wpas_dpp_connected_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004911 dpp_pfs_free(wpa_s->dpp_pfs);
4912 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004913 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004914 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4915 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07004916#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07004917#ifdef CONFIG_DPP3
4918 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
4919#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004920 offchannel_send_action_done(wpa_s);
4921 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004922 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004923 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004924 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
4925 os_free(wpa_s->dpp_configurator_params);
4926 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07004927 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004928}
Hai Shalom81f62d82019-07-22 12:10:00 -07004929
4930
Hai Shaloma20dcd72022-02-04 13:43:00 -08004931static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
4932 struct dpp_authentication *auth, bool tcp)
4933{
4934 struct wpabuf *resp;
4935
4936 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
4937 auth->e_netrole, true);
4938 if (!resp)
4939 return -1;
4940
4941 if (tcp) {
4942 auth->conf_resp_tcp = resp;
4943 return 0;
4944 }
4945
4946 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4947 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
4948 resp) < 0) {
4949 wpa_printf(MSG_DEBUG,
4950 "DPP: Could not find pending GAS response");
4951 wpabuf_free(resp);
4952 return -1;
4953 }
4954 auth->conf_resp = resp;
4955 return 0;
4956}
4957
4958
4959int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
4960{
4961 int peer;
4962 const char *pos;
4963 struct dpp_authentication *auth = wpa_s->dpp_auth;
4964 bool tcp = false;
4965
4966 pos = os_strstr(cmd, " peer=");
4967 if (!pos)
4968 return -1;
4969 peer = atoi(pos + 6);
4970#ifdef CONFIG_DPP2
4971 if (!auth || !auth->waiting_config ||
4972 (auth->peer_bi &&
4973 (unsigned int) peer != auth->peer_bi->id)) {
4974 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4975 tcp = true;
4976 }
4977#endif /* CONFIG_DPP2 */
4978
4979 if (!auth || !auth->waiting_config) {
4980 wpa_printf(MSG_DEBUG,
4981 "DPP: No authentication exchange waiting for configuration information");
4982 return -1;
4983 }
4984
4985 if ((!auth->peer_bi ||
4986 (unsigned int) peer != auth->peer_bi->id) &&
4987 (!auth->tmp_peer_bi ||
4988 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4989 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4990 return -1;
4991 }
4992
4993 pos = os_strstr(cmd, " comeback=");
4994 if (pos) {
4995 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4996 NULL);
4997 gas_server_set_comeback_delay(wpa_s->gas_server,
4998 auth->config_resp_ctx,
4999 atoi(pos + 10));
5000 return 0;
5001 }
5002
5003 if (dpp_set_configurator(auth, cmd) < 0)
5004 return -1;
5005
5006 auth->use_config_query = false;
5007 auth->waiting_config = false;
5008 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5009}
5010
5011
Hai Shalom81f62d82019-07-22 12:10:00 -07005012#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07005013
Hai Shalom81f62d82019-07-22 12:10:00 -07005014int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
5015{
5016 struct dpp_controller_config config;
5017 const char *pos;
5018
5019 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005020 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07005021 config.netrole = DPP_NETROLE_STA;
5022 config.msg_ctx = wpa_s;
5023 config.cb_ctx = wpa_s;
5024 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005025 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07005026 if (cmd) {
5027 pos = os_strstr(cmd, " tcp_port=");
5028 if (pos) {
5029 pos += 10;
5030 config.tcp_port = atoi(pos);
5031 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005032
5033 pos = os_strstr(cmd, " role=");
5034 if (pos) {
5035 pos += 6;
5036 if (os_strncmp(pos, "configurator", 12) == 0)
5037 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
5038 else if (os_strncmp(pos, "enrollee", 8) == 0)
5039 config.allowed_roles = DPP_CAPAB_ENROLLEE;
5040 else if (os_strncmp(pos, "either", 6) == 0)
5041 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
5042 DPP_CAPAB_ENROLLEE;
5043 else
5044 return -1;
5045 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005046
5047 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07005048 }
5049 config.configurator_params = wpa_s->dpp_configurator_params;
5050 return dpp_controller_start(wpa_s->dpp, &config);
5051}
Hai Shalomfdcde762020-04-02 11:19:20 -07005052
5053
5054static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
5055
5056static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
5057{
5058 struct wpa_supplicant *wpa_s = eloop_ctx;
5059
5060 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
5061 offchannel_send_action_done(wpa_s);
5062 wpas_dpp_chirp_next(wpa_s, NULL);
5063}
5064
5065
5066static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
5067 unsigned int freq, const u8 *dst,
5068 const u8 *src, const u8 *bssid,
5069 const u8 *data, size_t data_len,
5070 enum offchannel_send_action_result result)
5071{
5072 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5073 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
5074 wpa_s->dpp_chirp_freq);
5075 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
5076 wpa_s, NULL) < 0)
5077 wpas_dpp_chirp_stop(wpa_s);
5078 return;
5079 }
5080
5081 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
5082 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
5083 wpa_s, NULL) < 0)
5084 wpas_dpp_chirp_stop(wpa_s);
5085}
5086
5087
5088static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
5089{
Hai Shalom899fcc72020-10-19 14:38:18 -07005090 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005091 int type;
5092
5093 msg = wpa_s->dpp_presence_announcement;
5094 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
5095 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07005096 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
5097
5098 if (ssid && wpa_s->dpp_reconfig_id &&
5099 wpa_config_get_network(wpa_s->conf,
5100 wpa_s->dpp_reconfig_ssid_id) ==
5101 ssid) {
5102 announce = dpp_build_reconfig_announcement(
5103 ssid->dpp_csign,
5104 ssid->dpp_csign_len,
5105 ssid->dpp_netaccesskey,
5106 ssid->dpp_netaccesskey_len,
5107 wpa_s->dpp_reconfig_id);
5108 msg = announce;
5109 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005110 if (!msg)
5111 return;
5112 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
5113 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005114 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
5115 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005116 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07005117 if (offchannel_send_action(
5118 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
5119 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005120 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07005121 2000, wpas_dpp_chirp_tx_status, 0) < 0)
5122 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07005123
5124 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07005125}
5126
5127
Sunil Ravi89eba102022-09-13 21:04:37 -07005128static int * wpas_dpp_presence_ann_channels(struct wpa_supplicant *wpa_s,
5129 struct dpp_bootstrap_info *bi)
Hai Shalomfdcde762020-04-02 11:19:20 -07005130{
Hai Shalomfdcde762020-04-02 11:19:20 -07005131 unsigned int i;
5132 struct hostapd_hw_modes *mode;
5133 int c;
5134 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005135 bool chan6 = wpa_s->hw.modes == NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005136 int *freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07005137
5138 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005139 if (bi) {
5140 for (i = 0; i < bi->num_freq; i++)
Sunil Ravi89eba102022-09-13 21:04:37 -07005141 int_array_add_unique(&freqs, bi->freq[i]);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005142 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005143
5144 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07005145 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005146 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07005147 if (mode) {
5148 for (c = 0; c < mode->num_channels; c++) {
5149 struct hostapd_channel_data *chan = &mode->channels[c];
5150
5151 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
5152 chan->freq != 2437)
5153 continue;
5154 chan6 = true;
5155 break;
5156 }
5157 }
5158 if (chan6)
Sunil Ravi89eba102022-09-13 21:04:37 -07005159 int_array_add_unique(&freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07005160
5161 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005162 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005163 if (mode) {
5164 int chan44 = 0, chan149 = 0;
5165
5166 for (c = 0; c < mode->num_channels; c++) {
5167 struct hostapd_channel_data *chan = &mode->channels[c];
5168
5169 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
5170 HOSTAPD_CHAN_RADAR))
5171 continue;
5172 if (chan->freq == 5220)
5173 chan44 = 1;
5174 if (chan->freq == 5745)
5175 chan149 = 1;
5176 }
5177 if (chan149)
Sunil Ravi89eba102022-09-13 21:04:37 -07005178 int_array_add_unique(&freqs, 5745);
Hai Shalomfdcde762020-04-02 11:19:20 -07005179 else if (chan44)
Sunil Ravi89eba102022-09-13 21:04:37 -07005180 int_array_add_unique(&freqs, 5220);
Hai Shalomfdcde762020-04-02 11:19:20 -07005181 }
5182
5183 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005184 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005185 if (mode) {
5186 for (c = 0; c < mode->num_channels; c++) {
5187 struct hostapd_channel_data *chan = &mode->channels[c];
5188
5189 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
5190 HOSTAPD_CHAN_RADAR)) ||
5191 chan->freq != 60480)
5192 continue;
Sunil Ravi89eba102022-09-13 21:04:37 -07005193 int_array_add_unique(&freqs, 60480);
Hai Shalomfdcde762020-04-02 11:19:20 -07005194 break;
5195 }
5196 }
5197
5198 /* Add channels from scan results for APs that advertise Configurator
5199 * Connectivity element */
5200 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5201 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
Sunil Ravi89eba102022-09-13 21:04:37 -07005202 int_array_add_unique(&freqs, bss->freq);
Hai Shalomfdcde762020-04-02 11:19:20 -07005203 }
5204
Sunil Ravi89eba102022-09-13 21:04:37 -07005205 return freqs;
5206}
5207
5208
5209static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
5210 struct wpa_scan_results *scan_res)
5211{
5212 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
5213
5214 if (!bi && !wpa_s->dpp_reconfig_ssid)
5215 return;
5216
5217 wpa_s->dpp_chirp_scan_done = 1;
5218
5219 os_free(wpa_s->dpp_chirp_freqs);
5220 wpa_s->dpp_chirp_freqs = wpas_dpp_presence_ann_channels(wpa_s, bi);
5221
Hai Shalomfdcde762020-04-02 11:19:20 -07005222 if (!wpa_s->dpp_chirp_freqs ||
5223 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
5224 wpas_dpp_chirp_stop(wpa_s);
5225}
5226
5227
5228static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
5229{
5230 struct wpa_supplicant *wpa_s = eloop_ctx;
5231 int i;
5232
5233 if (wpa_s->dpp_chirp_listen)
5234 wpas_dpp_listen_stop(wpa_s);
5235
5236 if (wpa_s->dpp_chirp_freq == 0) {
5237 if (wpa_s->dpp_chirp_round % 4 == 0 &&
5238 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08005239 if (wpas_scan_scheduled(wpa_s)) {
5240 wpa_printf(MSG_DEBUG,
5241 "DPP: Deferring chirp scan because another scan is planned already");
5242 if (eloop_register_timeout(1, 0,
5243 wpas_dpp_chirp_next,
5244 wpa_s, NULL) < 0) {
5245 wpas_dpp_chirp_stop(wpa_s);
5246 return;
5247 }
5248 return;
5249 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005250 wpa_printf(MSG_DEBUG,
5251 "DPP: Update channel list for chirping");
5252 wpa_s->scan_req = MANUAL_SCAN_REQ;
5253 wpa_s->scan_res_handler =
5254 wpas_dpp_chirp_scan_res_handler;
5255 wpa_supplicant_req_scan(wpa_s, 0, 0);
5256 return;
5257 }
5258 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
5259 wpa_s->dpp_chirp_round++;
5260 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
5261 wpa_s->dpp_chirp_round);
5262 } else {
5263 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
5264 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
5265 break;
5266 if (!wpa_s->dpp_chirp_freqs[i]) {
5267 wpa_printf(MSG_DEBUG,
5268 "DPP: Previous chirp freq %d not found",
5269 wpa_s->dpp_chirp_freq);
5270 return;
5271 }
5272 i++;
5273 if (wpa_s->dpp_chirp_freqs[i]) {
5274 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
5275 } else {
5276 wpa_s->dpp_chirp_iter--;
5277 if (wpa_s->dpp_chirp_iter <= 0) {
5278 wpa_printf(MSG_DEBUG,
5279 "DPP: Chirping iterations completed");
5280 wpas_dpp_chirp_stop(wpa_s);
5281 return;
5282 }
5283 wpa_s->dpp_chirp_freq = 0;
5284 wpa_s->dpp_chirp_scan_done = 0;
5285 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
5286 wpa_s, NULL) < 0) {
5287 wpas_dpp_chirp_stop(wpa_s);
5288 return;
5289 }
5290 if (wpa_s->dpp_chirp_listen) {
5291 wpa_printf(MSG_DEBUG,
5292 "DPP: Listen on %d MHz during chirp 30 second wait",
5293 wpa_s->dpp_chirp_listen);
5294 wpas_dpp_listen_start(wpa_s,
5295 wpa_s->dpp_chirp_listen);
5296 } else {
5297 wpa_printf(MSG_DEBUG,
5298 "DPP: Wait 30 seconds before starting the next chirping round");
5299 }
5300 return;
5301 }
5302 }
5303
5304 wpas_dpp_chirp_start(wpa_s);
5305}
5306
5307
5308int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
5309{
5310 const char *pos;
5311 int iter = 1, listen_freq = 0;
5312 struct dpp_bootstrap_info *bi;
5313
5314 pos = os_strstr(cmd, " own=");
5315 if (!pos)
5316 return -1;
5317 pos += 5;
5318 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
5319 if (!bi) {
5320 wpa_printf(MSG_DEBUG,
5321 "DPP: Identified bootstrap info not found");
5322 return -1;
5323 }
5324
5325 pos = os_strstr(cmd, " iter=");
5326 if (pos) {
5327 iter = atoi(pos + 6);
5328 if (iter <= 0)
5329 return -1;
5330 }
5331
5332 pos = os_strstr(cmd, " listen=");
5333 if (pos) {
5334 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005335 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005336 return -1;
5337 }
5338
5339 wpas_dpp_chirp_stop(wpa_s);
5340 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005341 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07005342 wpa_s->dpp_qr_mutual = 0;
5343 wpa_s->dpp_chirp_bi = bi;
5344 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
5345 if (!wpa_s->dpp_presence_announcement)
5346 return -1;
5347 wpa_s->dpp_chirp_iter = iter;
5348 wpa_s->dpp_chirp_round = 0;
5349 wpa_s->dpp_chirp_scan_done = 0;
5350 wpa_s->dpp_chirp_listen = listen_freq;
5351
5352 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5353}
5354
5355
5356void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
5357{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005358 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07005359 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005360 offchannel_send_action_done(wpa_s);
5361 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
5362 }
5363 wpa_s->dpp_chirp_bi = NULL;
5364 wpabuf_free(wpa_s->dpp_presence_announcement);
5365 wpa_s->dpp_presence_announcement = NULL;
5366 if (wpa_s->dpp_chirp_listen)
5367 wpas_dpp_listen_stop(wpa_s);
5368 wpa_s->dpp_chirp_listen = 0;
5369 wpa_s->dpp_chirp_freq = 0;
5370 os_free(wpa_s->dpp_chirp_freqs);
5371 wpa_s->dpp_chirp_freqs = NULL;
5372 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
5373 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
5374 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
5375 wpas_abort_ongoing_scan(wpa_s);
5376 wpa_s->scan_res_handler = NULL;
5377 }
5378}
5379
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005380
Hai Shalom899fcc72020-10-19 14:38:18 -07005381int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005382{
Hai Shalom899fcc72020-10-19 14:38:18 -07005383 struct wpa_ssid *ssid;
5384 int iter = 1;
5385 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005386
Hai Shalom899fcc72020-10-19 14:38:18 -07005387 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
5388 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
5389 !ssid->dpp_csign) {
5390 wpa_printf(MSG_DEBUG,
5391 "DPP: Not a valid network profile for reconfiguration");
5392 return -1;
5393 }
5394
5395 pos = os_strstr(cmd, " iter=");
5396 if (pos) {
5397 iter = atoi(pos + 6);
5398 if (iter <= 0)
5399 return -1;
5400 }
5401
5402 if (wpa_s->dpp_auth) {
5403 wpa_printf(MSG_DEBUG,
5404 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
5405 return -1;
5406 }
5407
5408 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
5409 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
5410 ssid->dpp_csign_len,
5411 ssid->dpp_pp_key,
5412 ssid->dpp_pp_key_len);
5413 if (!wpa_s->dpp_reconfig_id) {
5414 wpa_printf(MSG_DEBUG,
5415 "DPP: Failed to generate E-id for reconfiguration");
5416 return -1;
5417 }
5418 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
5419 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
5420 wpa_s->own_disconnect_req = 1;
5421 wpa_supplicant_deauthenticate(
5422 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5423 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005424 wpas_dpp_chirp_stop(wpa_s);
5425 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005426 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005427 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005428 wpa_s->dpp_reconfig_ssid = ssid;
5429 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07005430 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005431 wpa_s->dpp_chirp_round = 0;
5432 wpa_s->dpp_chirp_scan_done = 0;
5433 wpa_s->dpp_chirp_listen = 0;
5434
5435 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5436}
5437
Hai Shalom899fcc72020-10-19 14:38:18 -07005438
Hai Shalom899fcc72020-10-19 14:38:18 -07005439int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
5440{
5441 int peer = -1;
5442 const char *pos, *value;
5443 struct dpp_authentication *auth = wpa_s->dpp_auth;
5444 u8 *bin;
5445 size_t bin_len;
5446 struct wpabuf *buf;
5447 bool tcp = false;
5448
5449 pos = os_strstr(cmd, " peer=");
5450 if (pos) {
5451 peer = atoi(pos + 6);
5452 if (!auth || !auth->waiting_cert ||
5453 (auth->peer_bi &&
5454 (unsigned int) peer != auth->peer_bi->id)) {
5455 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5456 tcp = true;
5457 }
5458 }
5459
5460 if (!auth || !auth->waiting_cert) {
5461 wpa_printf(MSG_DEBUG,
5462 "DPP: No authentication exchange waiting for certificate information");
5463 return -1;
5464 }
5465
5466 if (peer >= 0 &&
5467 (!auth->peer_bi ||
5468 (unsigned int) peer != auth->peer_bi->id) &&
5469 (!auth->tmp_peer_bi ||
5470 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5471 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5472 return -1;
5473 }
5474
5475 pos = os_strstr(cmd, " value=");
5476 if (!pos)
5477 return -1;
5478 value = pos + 7;
5479
5480 pos = os_strstr(cmd, " name=");
5481 if (!pos)
5482 return -1;
5483 pos += 6;
5484
5485 if (os_strncmp(pos, "status ", 7) == 0) {
5486 auth->force_conf_resp_status = atoi(value);
5487 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5488 }
5489
5490 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
5491 os_free(auth->trusted_eap_server_name);
5492 auth->trusted_eap_server_name = os_strdup(value);
5493 return auth->trusted_eap_server_name ? 0 : -1;
5494 }
5495
5496 bin = base64_decode(value, os_strlen(value), &bin_len);
5497 if (!bin)
5498 return -1;
5499 buf = wpabuf_alloc_copy(bin, bin_len);
5500 os_free(bin);
5501
5502 if (os_strncmp(pos, "caCert ", 7) == 0) {
5503 wpabuf_free(auth->cacert);
5504 auth->cacert = buf;
5505 return 0;
5506 }
5507
5508 if (os_strncmp(pos, "certBag ", 8) == 0) {
5509 wpabuf_free(auth->certbag);
5510 auth->certbag = buf;
5511 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5512 }
5513
5514 wpabuf_free(buf);
5515 return -1;
5516}
5517
Hai Shalom81f62d82019-07-22 12:10:00 -07005518#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07005519
5520
5521#ifdef CONFIG_DPP3
5522
5523#define DPP_PB_ANNOUNCE_PER_CHAN 3
5524
5525static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
5526static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
5527
5528
5529static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
5530 unsigned int freq, const u8 *dst,
5531 const u8 *src, const u8 *bssid,
5532 const u8 *data, size_t data_len,
5533 enum offchannel_send_action_result result)
5534{
5535 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5536 wpa_printf(MSG_DEBUG,
5537 "DPP: Failed to send push button announcement on %d MHz",
5538 freq);
5539 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
5540 wpa_s, NULL) < 0)
5541 wpas_dpp_push_button_stop(wpa_s);
5542 return;
5543 }
5544
5545 wpa_printf(MSG_DEBUG, "DPP: Push button announcement on %d MHz sent",
5546 freq);
5547 if (wpa_s->dpp_pb_discovery_done) {
5548 wpa_s->dpp_pb_announce_count = 0;
5549 wpa_printf(MSG_DEBUG,
5550 "DPP: Wait for push button announcement response and PKEX on %d MHz",
5551 freq);
5552 if (eloop_register_timeout(0, 500000, wpas_dpp_pb_next,
5553 wpa_s, NULL) < 0)
5554 wpas_dpp_push_button_stop(wpa_s);
5555 return;
5556 } else if (wpa_s->dpp_pb_announce_count >= DPP_PB_ANNOUNCE_PER_CHAN) {
5557 wpa_printf(MSG_DEBUG,
5558 "DPP: Wait for push button announcement response on %d MHz",
5559 freq);
5560 if (eloop_register_timeout(0, 50000, wpas_dpp_pb_next,
5561 wpa_s, NULL) < 0)
5562 wpas_dpp_push_button_stop(wpa_s);
5563 return;
5564 }
5565
5566 if (wpas_dpp_pb_announce(wpa_s, freq) < 0)
5567 wpas_dpp_push_button_stop(wpa_s);
5568}
5569
5570
5571static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq)
5572{
5573 struct wpabuf *msg;
5574 int type;
5575
5576 msg = wpa_s->dpp_pb_announcement;
5577 if (!msg)
5578 return -1;
5579
5580 wpa_s->dpp_pb_announce_count++;
5581 wpa_printf(MSG_DEBUG,
5582 "DPP: Send push button announcement %d/%d (%d MHz)",
5583 wpa_s->dpp_pb_announce_count, DPP_PB_ANNOUNCE_PER_CHAN,
5584 freq);
5585
5586 type = DPP_PA_PB_PRESENCE_ANNOUNCEMENT;
5587 if (wpa_s->dpp_pb_announce_count == 1)
5588 wpa_msg(wpa_s, MSG_INFO,
5589 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
5590 MAC2STR(broadcast), freq, type);
5591 if (offchannel_send_action(
5592 wpa_s, freq, broadcast, wpa_s->own_addr, broadcast,
5593 wpabuf_head(msg), wpabuf_len(msg),
5594 1000, wpas_dpp_pb_tx_status, 0) < 0)
5595 return -1;
5596
5597 return 0;
5598}
5599
5600
5601static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx)
5602{
5603 struct wpa_supplicant *wpa_s = eloop_ctx;
5604 struct os_reltime now;
5605 int freq;
5606
5607 if (!wpa_s->dpp_pb_freqs)
5608 return;
5609
5610 os_get_reltime(&now);
5611 offchannel_send_action_done(wpa_s);
5612
5613 if (os_reltime_expired(&now, &wpa_s->dpp_pb_time, 100)) {
5614 wpa_printf(MSG_DEBUG, "DPP: Push button wait time expired");
5615 wpas_dpp_push_button_stop(wpa_s);
5616 return;
5617 }
5618
5619 if (wpa_s->dpp_pb_freq_idx >= int_array_len(wpa_s->dpp_pb_freqs)) {
5620 wpa_printf(MSG_DEBUG,
5621 "DPP: Completed push button announcement round");
5622 wpa_s->dpp_pb_freq_idx = 0;
5623 if (wpa_s->dpp_pb_stop_iter > 0) {
5624 wpa_s->dpp_pb_stop_iter--;
5625
5626 if (wpa_s->dpp_pb_stop_iter == 1) {
5627 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5628 "wait for AP/Configurator to allow PKEX to be initiated");
5629 if (eloop_register_timeout(10, 0,
5630 wpas_dpp_pb_next,
5631 wpa_s, NULL) < 0) {
5632 wpas_dpp_push_button_stop(wpa_s);
5633 return;
5634 }
5635 return;
5636 }
5637
5638 if (wpa_s->dpp_pb_stop_iter == 0) {
5639 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5640 "start push button PKEX responder on the discovered channel (%d MHz)",
5641 wpa_s->dpp_pb_resp_freq);
5642 wpa_s->dpp_pb_discovery_done = true;
5643
5644 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
5645
5646 os_free(wpa_s->dpp_pkex_code);
5647 wpa_s->dpp_pkex_code = os_memdup(
5648 wpa_s->dpp_pb_c_nonce,
5649 wpa_s->dpp_pb_c_nonce_len);
5650 wpa_s->dpp_pkex_code_len =
5651 wpa_s->dpp_pb_c_nonce_len;
5652
5653 os_free(wpa_s->dpp_pkex_identifier);
5654 wpa_s->dpp_pkex_identifier =
5655 os_strdup("PBPKEX");
5656
5657 if (!wpa_s->dpp_pkex_code ||
5658 !wpa_s->dpp_pkex_identifier) {
5659 wpas_dpp_push_button_stop(wpa_s);
5660 return;
5661 }
5662
5663 wpa_s->dpp_pkex_ver = PKEX_VER_ONLY_2;
5664
5665 os_free(wpa_s->dpp_pkex_auth_cmd);
5666 wpa_s->dpp_pkex_auth_cmd = NULL;
5667 }
5668 }
5669 }
5670
5671 if (wpa_s->dpp_pb_discovery_done)
5672 freq = wpa_s->dpp_pb_resp_freq;
5673 else
5674 freq = wpa_s->dpp_pb_freqs[wpa_s->dpp_pb_freq_idx++];
5675 wpa_s->dpp_pb_announce_count = 0;
5676 if (!wpa_s->dpp_pb_announcement) {
5677 wpa_printf(MSG_DEBUG, "DPP: Push button announcements stopped");
5678 return;
5679 }
5680 if (wpas_dpp_pb_announce(wpa_s, freq) < 0) {
5681 wpas_dpp_push_button_stop(wpa_s);
5682 return;
5683 }
5684}
5685
5686
5687static void wpas_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
5688{
5689 struct wpa_supplicant *wpa_s = eloop_ctx;
5690
5691 wpa_printf(MSG_DEBUG,
5692 "DPP: Active push button Configurator mode expired");
5693 wpas_dpp_push_button_stop(wpa_s);
5694}
5695
5696
5697static int wpas_dpp_push_button_configurator(struct wpa_supplicant *wpa_s,
5698 const char *cmd)
5699{
5700 wpa_s->dpp_pb_configurator = true;
5701 wpa_s->dpp_pb_announce_time.sec = 0;
5702 wpa_s->dpp_pb_announce_time.usec = 0;
5703 str_clear_free(wpa_s->dpp_pb_cmd);
5704 wpa_s->dpp_pb_cmd = NULL;
5705 if (cmd) {
5706 wpa_s->dpp_pb_cmd = os_strdup(cmd);
5707 if (!wpa_s->dpp_pb_cmd)
5708 return -1;
5709 }
5710 eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
5711 wpa_s, NULL);
5712
Sunil Ravi99c035e2024-07-12 01:42:03 +00005713 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS "started");
Sunil Ravi89eba102022-09-13 21:04:37 -07005714 return 0;
5715}
5716
5717
5718static void wpas_dpp_pb_scan_res_handler(struct wpa_supplicant *wpa_s,
5719 struct wpa_scan_results *scan_res)
5720{
5721 if (!wpa_s->dpp_pb_time.sec && !wpa_s->dpp_pb_time.usec)
5722 return;
5723
5724 os_free(wpa_s->dpp_pb_freqs);
5725 wpa_s->dpp_pb_freqs = wpas_dpp_presence_ann_channels(wpa_s, NULL);
5726
5727 wpa_printf(MSG_DEBUG, "DPP: Scan completed for PB discovery");
5728 if (!wpa_s->dpp_pb_freqs ||
5729 eloop_register_timeout(0, 0, wpas_dpp_pb_next, wpa_s, NULL) < 0)
5730 wpas_dpp_push_button_stop(wpa_s);
5731}
5732
5733
5734int wpas_dpp_push_button(struct wpa_supplicant *wpa_s, const char *cmd)
5735{
5736 int res;
5737
5738 if (!wpa_s->dpp)
5739 return -1;
5740 wpas_dpp_push_button_stop(wpa_s);
5741 wpas_dpp_stop(wpa_s);
5742 wpas_dpp_chirp_stop(wpa_s);
5743
5744 os_get_reltime(&wpa_s->dpp_pb_time);
5745
5746 if (cmd &&
5747 (os_strstr(cmd, " role=configurator") ||
5748 os_strstr(cmd, " conf=")))
5749 return wpas_dpp_push_button_configurator(wpa_s, cmd);
5750
5751 wpa_s->dpp_pb_configurator = false;
5752
5753 wpa_s->dpp_pb_freq_idx = 0;
5754
5755 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
5756 if (res < 0)
5757 return -1;
5758 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
5759 if (!wpa_s->dpp_pb_bi)
5760 return -1;
5761
5762 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
5763 wpa_s->dpp_netrole = DPP_NETROLE_STA;
5764 wpa_s->dpp_qr_mutual = 0;
5765 wpa_s->dpp_pb_announcement =
5766 dpp_build_pb_announcement(wpa_s->dpp_pb_bi);
5767 if (!wpa_s->dpp_pb_announcement)
5768 return -1;
5769
5770 wpa_printf(MSG_DEBUG,
5771 "DPP: Scan to create channel list for PB discovery");
5772 wpa_s->scan_req = MANUAL_SCAN_REQ;
5773 wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
5774 wpa_supplicant_req_scan(wpa_s, 0, 0);
Sunil Ravi99c035e2024-07-12 01:42:03 +00005775 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS "started");
Sunil Ravi89eba102022-09-13 21:04:37 -07005776 return 0;
5777}
5778
5779
5780void wpas_dpp_push_button_stop(struct wpa_supplicant *wpa_s)
5781{
5782 if (!wpa_s->dpp)
5783 return;
5784 os_free(wpa_s->dpp_pb_freqs);
5785 wpa_s->dpp_pb_freqs = NULL;
5786 wpabuf_free(wpa_s->dpp_pb_announcement);
5787 wpa_s->dpp_pb_announcement = NULL;
5788 if (wpa_s->dpp_pb_bi) {
5789 char id[20];
5790
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005791 if (wpa_s->dpp_pb_bi == wpa_s->dpp_pkex_bi)
5792 wpa_s->dpp_pkex_bi = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005793 os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
5794 dpp_bootstrap_remove(wpa_s->dpp, id);
5795 wpa_s->dpp_pb_bi = NULL;
5796 if (!wpa_s->dpp_pb_result_indicated) {
5797 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5798 wpa_s->dpp_pb_result_indicated = true;
5799 }
5800 }
5801
5802 wpa_s->dpp_pb_resp_freq = 0;
5803 wpa_s->dpp_pb_stop_iter = 0;
5804 wpa_s->dpp_pb_discovery_done = false;
5805 os_free(wpa_s->dpp_pb_cmd);
5806 wpa_s->dpp_pb_cmd = NULL;
5807
5808 eloop_cancel_timeout(wpas_dpp_pb_next, wpa_s, NULL);
5809 eloop_cancel_timeout(wpas_dpp_push_button_expire, wpa_s, NULL);
5810 if (wpas_dpp_pb_active(wpa_s)) {
5811 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
5812 if (!wpa_s->dpp_pb_result_indicated)
5813 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5814 }
5815 wpa_s->dpp_pb_time.sec = 0;
5816 wpa_s->dpp_pb_time.usec = 0;
5817 dpp_pkex_free(wpa_s->dpp_pkex);
5818 wpa_s->dpp_pkex = NULL;
5819 os_free(wpa_s->dpp_pkex_auth_cmd);
5820 wpa_s->dpp_pkex_auth_cmd = NULL;
5821
5822 wpa_s->dpp_pb_result_indicated = false;
5823
5824 str_clear_free(wpa_s->dpp_pb_cmd);
5825 wpa_s->dpp_pb_cmd = NULL;
5826
5827 if (wpa_s->scan_res_handler == wpas_dpp_pb_scan_res_handler) {
5828 wpas_abort_ongoing_scan(wpa_s);
5829 wpa_s->scan_res_handler = NULL;
5830 }
5831}
5832
5833#endif /* CONFIG_DPP3 */