blob: 801e698eae1d56c734ee343c9b6bf885120c4797 [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;
241 wpa_printf(MSG_DEBUG,
242 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
243 wait_time);
244 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
245 eloop_register_timeout(wait_time / 1000,
246 (wait_time % 1000) * 1000,
247 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
248}
249
250
Hai Shalom021b0b52019-04-10 11:17:58 -0700251static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
252{
253 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700254 wpa_s->suitable_network = 0;
255 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700256 wpa_s->disconnected = 0;
257 wpa_s->reassociate = 1;
258 wpa_s->scan_runs = 0;
259 wpa_s->normal_scans = 0;
260 wpa_supplicant_cancel_sched_scan(wpa_s);
261 wpa_supplicant_req_scan(wpa_s, 0, 0);
262}
263
264
Hai Shalomc3565922019-10-28 11:58:20 -0700265#ifdef CONFIG_DPP2
266
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700267static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s,
268 unsigned int freq,
269 unsigned int wait_time)
270{
271 struct os_reltime now, res;
272 unsigned int remaining;
273
274 if (!wpa_s->dpp_listen_freq)
275 return;
276
277 os_get_reltime(&now);
278 if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) {
279 os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res);
280 remaining = res.sec * 1000 + res.usec / 1000;
281 } else {
282 remaining = 0;
283 }
284 if (wpa_s->dpp_listen_freq == freq && remaining > wait_time)
285 return;
286
287 wpa_printf(MSG_DEBUG,
288 "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms",
289 wpa_s->dpp_listen_freq, remaining, freq, wait_time);
290 wpas_dpp_listen_stop(wpa_s);
291
292 /* TODO: Restart listen in some cases after TX? */
293}
294
295
Hai Shalomc3565922019-10-28 11:58:20 -0700296static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
297 void *timeout_ctx)
298{
299 struct wpa_supplicant *wpa_s = eloop_ctx;
300 struct dpp_authentication *auth = wpa_s->dpp_auth;
301 enum dpp_status_error result;
302
Hai Shaloma20dcd72022-02-04 13:43:00 -0800303 if ((!auth || !auth->conn_status_requested) &&
304 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700305 return;
306
307 wpa_printf(MSG_DEBUG,
308 "DPP: Connection timeout - report Connection Status Result");
309 if (wpa_s->suitable_network)
310 result = DPP_STATUS_AUTH_FAILURE;
311 else if (wpa_s->no_suitable_network)
312 result = DPP_STATUS_NO_AP;
313 else
314 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800315 if (wpa_s->wpa_state == WPA_SCANNING)
316 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700317 wpas_dpp_send_conn_status_result(wpa_s, result);
318}
319
320
321static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
322{
323 char *str, *end, *pos;
324 size_t len;
325 unsigned int i;
326 u8 last_op_class = 0;
327 int res;
328
329 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
330 return NULL;
331
332 len = wpa_s->num_last_scan_freqs * 8;
333 str = os_zalloc(len);
334 if (!str)
335 return NULL;
336 end = str + len;
337 pos = str;
338
339 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
340 enum hostapd_hw_mode mode;
341 u8 op_class, channel;
342
343 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
344 0, 0, &op_class, &channel);
345 if (mode == NUM_HOSTAPD_MODES)
346 continue;
347 if (op_class == last_op_class)
348 res = os_snprintf(pos, end - pos, ",%d", channel);
349 else
350 res = os_snprintf(pos, end - pos, "%s%d/%d",
351 pos == str ? "" : ",",
352 op_class, channel);
353 if (os_snprintf_error(end - pos, res)) {
354 *pos = '\0';
355 break;
356 }
357 pos += res;
358 last_op_class = op_class;
359 }
360
361 if (pos == str) {
362 os_free(str);
363 str = NULL;
364 }
365 return str;
366}
367
368
369void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
370 enum dpp_status_error result)
371{
372 struct wpabuf *msg;
373 const char *channel_list = NULL;
374 char *channel_list_buf = NULL;
375 struct wpa_ssid *ssid = wpa_s->current_ssid;
376 struct dpp_authentication *auth = wpa_s->dpp_auth;
377
378 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
379
Hai Shaloma20dcd72022-02-04 13:43:00 -0800380 if ((!auth || !auth->conn_status_requested) &&
381 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700382 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800383
Hai Shalomc3565922019-10-28 11:58:20 -0700384 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
385 result);
386
387 if (result == DPP_STATUS_NO_AP) {
388 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
389 channel_list = channel_list_buf;
390 }
391
Hai Shaloma20dcd72022-02-04 13:43:00 -0800392 if (!auth || !auth->conn_status_requested) {
393 dpp_tcp_send_conn_status(wpa_s->dpp, result,
394 ssid ? ssid->ssid :
395 wpa_s->dpp_last_ssid,
396 ssid ? ssid->ssid_len :
397 wpa_s->dpp_last_ssid_len,
398 channel_list);
399 os_free(channel_list_buf);
400 return;
401 }
402
403 auth->conn_status_requested = 0;
404
Hai Shalomc3565922019-10-28 11:58:20 -0700405 msg = dpp_build_conn_status_result(auth, result,
406 ssid ? ssid->ssid :
407 wpa_s->dpp_last_ssid,
408 ssid ? ssid->ssid_len :
409 wpa_s->dpp_last_ssid_len,
410 channel_list);
411 os_free(channel_list_buf);
412 if (!msg) {
413 dpp_auth_deinit(wpa_s->dpp_auth);
414 wpa_s->dpp_auth = NULL;
415 return;
416 }
417
418 wpa_msg(wpa_s, MSG_INFO,
419 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
420 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
421 DPP_PA_CONNECTION_STATUS_RESULT);
Sunil Ravi546a7b52022-08-26 22:06:04 +0000422 if (offchannel_send_action(wpa_s, auth->curr_freq,
423 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
424 wpabuf_head(msg), wpabuf_len(msg),
425 500, wpas_dpp_tx_status, 0) < 0) {
426 wpas_notify_dpp_connection_status_sent(wpa_s, result);
427 wpabuf_free(msg);
428 dpp_auth_deinit(wpa_s->dpp_auth);
429 wpa_s->dpp_auth = NULL;
430 return;
431 }
432
Hai Shalomc3565922019-10-28 11:58:20 -0700433 wpabuf_free(msg);
434
Sunil Ravi546a7b52022-08-26 22:06:04 +0000435 auth->conn_result_status = result;
436 auth->tx_conn_status_result_started = 1;
Hai Shalomc3565922019-10-28 11:58:20 -0700437 /* This exchange will be terminated in the TX status handler */
438 auth->remove_on_tx_status = 1;
439
440 return;
441}
442
443
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000444static void wpas_dpp_connected_timeout(void *eloop_ctx, void *timeout_ctx)
Hai Shalomc3565922019-10-28 11:58:20 -0700445{
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000446 struct wpa_supplicant *wpa_s = eloop_ctx;
Hai Shalomc3565922019-10-28 11:58:20 -0700447 struct dpp_authentication *auth = wpa_s->dpp_auth;
448
Hai Shaloma20dcd72022-02-04 13:43:00 -0800449 if ((auth && auth->conn_status_requested) ||
450 dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700451 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
452}
453
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000454
455void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
456{
457 struct dpp_authentication *auth = wpa_s->dpp_auth;
458
459 if ((auth && auth->conn_status_requested) ||
460 dpp_tcp_conn_status_requested(wpa_s->dpp)) {
461 /* Report connection result from an eloop timeout to avoid delay
462 * to completing all connection completion steps since this
463 * function is called in a middle of the post 4-way handshake
464 * processing. */
465 eloop_register_timeout(0, 0, wpas_dpp_connected_timeout,
466 wpa_s, NULL);
467 }
468}
469
Hai Shalomc3565922019-10-28 11:58:20 -0700470#endif /* CONFIG_DPP2 */
471
472
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000473static void wpas_dpp_drv_wait_timeout(void *eloop_ctx, void *timeout_ctx)
474{
475 struct wpa_supplicant *wpa_s = eloop_ctx;
476 struct dpp_authentication *auth = wpa_s->dpp_auth;
477
478 if (auth && auth->waiting_auth_resp) {
479 wpa_printf(MSG_DEBUG,
480 "DPP: Call wpas_dpp_auth_init_next() from %s",
481 __func__);
482 wpas_dpp_auth_init_next(wpa_s);
483 } else {
484 wpa_printf(MSG_DEBUG, "DPP: %s, but no waiting_auth_resp",
485 __func__);
486 }
487}
488
489
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700490static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
491 unsigned int freq, const u8 *dst,
492 const u8 *src, const u8 *bssid,
493 const u8 *data, size_t data_len,
494 enum offchannel_send_action_result result)
495{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700496 const char *res_txt;
497 struct dpp_authentication *auth = wpa_s->dpp_auth;
498
499 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
500 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
501 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700502 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700503 " result=%s", freq, MAC2STR(dst), res_txt);
504 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
505 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700506
507 if (!wpa_s->dpp_auth) {
508 wpa_printf(MSG_DEBUG,
509 "DPP: Ignore TX status since there is no ongoing authentication exchange");
510 return;
511 }
512
Hai Shalom021b0b52019-04-10 11:17:58 -0700513#ifdef CONFIG_DPP2
514 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700515 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700516 wpa_printf(MSG_DEBUG,
517 "DPP: Try to connect after completed configuration result");
518 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700519 if (auth->conn_status_requested) {
520 wpa_printf(MSG_DEBUG,
521 "DPP: Start 15 second timeout for reporting connection status result");
522 eloop_cancel_timeout(
523 wpas_dpp_conn_status_result_timeout,
524 wpa_s, NULL);
525 eloop_register_timeout(
526 15, 0, wpas_dpp_conn_status_result_timeout,
527 wpa_s, NULL);
528 } else {
529 dpp_auth_deinit(wpa_s->dpp_auth);
530 wpa_s->dpp_auth = NULL;
531 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700532 return;
533 }
534#endif /* CONFIG_DPP2 */
535
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700536 if (wpa_s->dpp_auth->remove_on_tx_status) {
Sunil Ravi546a7b52022-08-26 22:06:04 +0000537 if (auth->tx_conn_status_result_started) {
538 wpas_notify_dpp_connection_status_sent(wpa_s, auth->conn_result_status);
539 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700540 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700541 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700542 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700543 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800544 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
545 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700546 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
547 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700548#ifdef CONFIG_DPP2
549 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
550 wpa_s, NULL);
551#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700552 offchannel_send_action_done(wpa_s);
553 dpp_auth_deinit(wpa_s->dpp_auth);
554 wpa_s->dpp_auth = NULL;
555 return;
556 }
557
558 if (wpa_s->dpp_auth_ok_on_ack)
559 wpas_dpp_auth_success(wpa_s, 1);
560
561 if (!is_broadcast_ether_addr(dst) &&
562 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
563 wpa_printf(MSG_DEBUG,
564 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700565 if (auth->waiting_auth_resp) {
566 /* In case of DPP Authentication Request frame, move to
567 * the next channel immediately. */
568 offchannel_send_action_done(wpa_s);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000569 /* Call wpas_dpp_auth_init_next(wpa_s) from driver event
570 * notifying frame wait was completed or from eloop
571 * timeout. */
572 eloop_register_timeout(0, 10000,
573 wpas_dpp_drv_wait_timeout,
574 wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700575 return;
576 }
577 if (auth->waiting_auth_conf) {
578 wpas_dpp_auth_resp_retry(wpa_s);
579 return;
580 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700581 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700582
Hai Shalom60840252021-02-19 19:02:11 -0800583 if (auth->waiting_auth_conf &&
584 auth->auth_resp_status == DPP_STATUS_OK) {
585 /* Make sure we do not get stuck waiting for Auth Confirm
586 * indefinitely after successfully transmitted Auth Response to
587 * allow new authentication exchanges to be started. */
588 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
589 NULL);
590 eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
591 wpa_s, NULL);
592 }
593
Roshan Pius3a1667e2018-07-03 15:17:14 -0700594 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
595 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
596 /* Allow timeout handling to stop iteration if no response is
597 * received from a peer that has ACKed a request. */
598 auth->auth_req_ack = 1;
599 }
600
601 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
602 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
603 wpa_printf(MSG_DEBUG,
604 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
605 wpa_s->dpp_auth->curr_freq,
606 wpa_s->dpp_auth->neg_freq);
607 offchannel_send_action_done(wpa_s);
Sunil Ravi88611412024-06-28 17:34:56 +0000608 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700609 }
610
611 if (wpa_s->dpp_auth_ok_on_ack)
612 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700613}
614
615
616static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
617{
618 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700619 struct dpp_authentication *auth = wpa_s->dpp_auth;
620 unsigned int freq;
621 struct os_reltime now, diff;
622 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700623
Roshan Pius3a1667e2018-07-03 15:17:14 -0700624 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700625 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700626
627 wait_time = wpa_s->dpp_resp_wait_time ?
628 wpa_s->dpp_resp_wait_time : 2000;
629 os_get_reltime(&now);
630 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
631 diff_ms = diff.sec * 1000 + diff.usec / 1000;
632 wpa_printf(MSG_DEBUG,
633 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
634 wait_time, diff_ms);
635
636 if (auth->auth_req_ack && diff_ms >= wait_time) {
637 /* Peer ACK'ed Authentication Request frame, but did not reply
638 * with Authentication Response frame within two seconds. */
639 wpa_printf(MSG_INFO,
640 "DPP: No response received from responder - stopping initiation attempt");
641 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800642 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700643 offchannel_send_action_done(wpa_s);
644 wpas_dpp_listen_stop(wpa_s);
645 dpp_auth_deinit(auth);
646 wpa_s->dpp_auth = NULL;
647 return;
648 }
649
650 if (diff_ms >= wait_time) {
651 /* Authentication Request frame was not ACK'ed and no reply
652 * was receiving within two seconds. */
653 wpa_printf(MSG_DEBUG,
654 "DPP: Continue Initiator channel iteration");
655 offchannel_send_action_done(wpa_s);
656 wpas_dpp_listen_stop(wpa_s);
657 wpas_dpp_auth_init_next(wpa_s);
658 return;
659 }
660
661 /* Driver did not support 2000 ms long wait_time with TX command, so
662 * schedule listen operation to continue waiting for the response.
663 *
664 * DPP listen operations continue until stopped, so simply schedule a
665 * new call to this function at the point when the two second reply
666 * wait has expired. */
667 wait_time -= diff_ms;
668
669 freq = auth->curr_freq;
670 if (auth->neg_freq > 0)
671 freq = auth->neg_freq;
672 wpa_printf(MSG_DEBUG,
673 "DPP: Continue reply wait on channel %u MHz for %u ms",
674 freq, wait_time);
675 wpa_s->dpp_in_response_listen = 1;
676 wpas_dpp_listen_start(wpa_s, freq);
677
678 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
679 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700680}
681
682
Hai Shalom60840252021-02-19 19:02:11 -0800683static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
684{
685 struct wpa_supplicant *wpa_s = eloop_ctx;
686 struct dpp_authentication *auth = wpa_s->dpp_auth;
687
688 if (!auth || !auth->waiting_auth_conf)
689 return;
690
691 wpa_printf(MSG_DEBUG,
692 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
693 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
694 offchannel_send_action_done(wpa_s);
695 dpp_auth_deinit(auth);
696 wpa_s->dpp_auth = NULL;
697}
698
699
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700700static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
701 struct dpp_authentication *auth)
702{
703#ifdef CONFIG_TESTING_OPTIONS
704 if (wpa_s->dpp_config_obj_override)
705 auth->config_obj_override =
706 os_strdup(wpa_s->dpp_config_obj_override);
707 if (wpa_s->dpp_discovery_override)
708 auth->discovery_override =
709 os_strdup(wpa_s->dpp_discovery_override);
710 if (wpa_s->dpp_groups_override)
711 auth->groups_override =
712 os_strdup(wpa_s->dpp_groups_override);
713 auth->ignore_netaccesskey_mismatch =
714 wpa_s->dpp_ignore_netaccesskey_mismatch;
715#endif /* CONFIG_TESTING_OPTIONS */
716}
717
718
Roshan Pius3a1667e2018-07-03 15:17:14 -0700719static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
720{
721 struct wpa_supplicant *wpa_s = eloop_ctx;
722
723 if (!wpa_s->dpp_auth)
724 return;
725 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
726 wpas_dpp_auth_init_next(wpa_s);
727}
728
729
730static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
731{
732 struct dpp_authentication *auth = wpa_s->dpp_auth;
733 const u8 *dst;
734 unsigned int wait_time, max_wait_time, freq, max_tries, used;
735 struct os_reltime now, diff;
736
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000737 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
738
Roshan Pius3a1667e2018-07-03 15:17:14 -0700739 wpa_s->dpp_in_response_listen = 0;
740 if (!auth)
741 return -1;
742
743 if (auth->freq_idx == 0)
744 os_get_reltime(&wpa_s->dpp_init_iter_start);
745
746 if (auth->freq_idx >= auth->num_freq) {
747 auth->num_freq_iters++;
748 if (wpa_s->dpp_init_max_tries)
749 max_tries = wpa_s->dpp_init_max_tries;
750 else
751 max_tries = 5;
752 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
753 wpa_printf(MSG_INFO,
754 "DPP: No response received from responder - stopping initiation attempt");
755 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800756 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700757 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
758 wpa_s, NULL);
759 offchannel_send_action_done(wpa_s);
760 dpp_auth_deinit(wpa_s->dpp_auth);
761 wpa_s->dpp_auth = NULL;
762 return -1;
763 }
764 auth->freq_idx = 0;
765 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
766 if (wpa_s->dpp_init_retry_time)
767 wait_time = wpa_s->dpp_init_retry_time;
768 else
769 wait_time = 10000;
770 os_get_reltime(&now);
771 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
772 used = diff.sec * 1000 + diff.usec / 1000;
773 if (used > wait_time)
774 wait_time = 0;
775 else
776 wait_time -= used;
777 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
778 wait_time);
779 eloop_register_timeout(wait_time / 1000,
780 (wait_time % 1000) * 1000,
781 wpas_dpp_init_timeout, wpa_s,
782 NULL);
783 return 0;
784 }
785 freq = auth->freq[auth->freq_idx++];
786 auth->curr_freq = freq;
787
Hai Shalom60840252021-02-19 19:02:11 -0800788 if (!is_zero_ether_addr(auth->peer_mac_addr))
789 dst = auth->peer_mac_addr;
790 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700791 dst = broadcast;
792 else
793 dst = auth->peer_bi->mac_addr;
794 wpa_s->dpp_auth_ok_on_ack = 0;
795 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
796 wait_time = wpa_s->max_remain_on_chan;
797 max_wait_time = wpa_s->dpp_resp_wait_time ?
798 wpa_s->dpp_resp_wait_time : 2000;
799 if (wait_time > max_wait_time)
800 wait_time = max_wait_time;
801 wait_time += 10; /* give the driver some extra time to complete */
802 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
803 wpas_dpp_reply_wait_timeout,
804 wpa_s, NULL);
805 wait_time -= 10;
806 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
807 wpa_printf(MSG_DEBUG,
808 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
809 freq, auth->neg_freq);
810 }
811 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
812 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
813 auth->auth_req_ack = 0;
814 os_get_reltime(&wpa_s->dpp_last_init);
815 return offchannel_send_action(wpa_s, freq, dst,
816 wpa_s->own_addr, broadcast,
817 wpabuf_head(auth->req_msg),
818 wpabuf_len(auth->req_msg),
819 wait_time, wpas_dpp_tx_status, 0);
820}
821
822
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700823int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
824{
825 const char *pos;
826 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700827 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700828 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
829 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700830 int tcp = 0;
831#ifdef CONFIG_DPP2
832 int tcp_port = DPP_TCP_PORT;
833 struct hostapd_ip_addr ipaddr;
834 char *addr;
835#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700836
837 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800838 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700839
840 pos = os_strstr(cmd, " peer=");
841 if (!pos)
842 return -1;
843 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700844 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700845 if (!peer_bi) {
846 wpa_printf(MSG_INFO,
847 "DPP: Could not find bootstrapping info for the identified peer");
848 return -1;
849 }
850
Hai Shalom81f62d82019-07-22 12:10:00 -0700851#ifdef CONFIG_DPP2
852 pos = os_strstr(cmd, " tcp_port=");
853 if (pos) {
854 pos += 10;
855 tcp_port = atoi(pos);
856 }
857
858 addr = get_param(cmd, " tcp_addr=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000859 if (addr && os_strcmp(addr, "from-uri") == 0) {
860 os_free(addr);
861 if (!peer_bi->host) {
862 wpa_printf(MSG_INFO,
863 "DPP: TCP address not available in peer URI");
864 return -1;
865 }
866 tcp = 1;
867 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
868 tcp_port = peer_bi->port;
869 } else if (addr) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700870 int res;
871
872 res = hostapd_parse_ip_addr(addr, &ipaddr);
873 os_free(addr);
874 if (res)
875 return -1;
876 tcp = 1;
877 }
878#endif /* CONFIG_DPP2 */
879
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700880 pos = os_strstr(cmd, " own=");
881 if (pos) {
882 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700883 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700884 if (!own_bi) {
885 wpa_printf(MSG_INFO,
886 "DPP: Could not find bootstrapping info for the identified local entry");
887 return -1;
888 }
889
890 if (peer_bi->curve != own_bi->curve) {
891 wpa_printf(MSG_INFO,
892 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
893 peer_bi->curve->name, own_bi->curve->name);
894 return -1;
895 }
896 }
897
898 pos = os_strstr(cmd, " role=");
899 if (pos) {
900 pos += 6;
901 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700902 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700903 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700904 allowed_roles = DPP_CAPAB_ENROLLEE;
905 else if (os_strncmp(pos, "either", 6) == 0)
906 allowed_roles = DPP_CAPAB_CONFIGURATOR |
907 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700908 else
909 goto fail;
910 }
911
912 pos = os_strstr(cmd, " netrole=");
913 if (pos) {
914 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800915 if (os_strncmp(pos, "ap", 2) == 0)
916 wpa_s->dpp_netrole = DPP_NETROLE_AP;
917 else if (os_strncmp(pos, "configurator", 12) == 0)
918 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
919 else
920 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700921 } else {
922 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700923 }
924
Roshan Pius3a1667e2018-07-03 15:17:14 -0700925 pos = os_strstr(cmd, " neg_freq=");
926 if (pos)
927 neg_freq = atoi(pos + 10);
928
Hai Shalom81f62d82019-07-22 12:10:00 -0700929 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700930 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700931 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800932 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
933 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700934 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
935 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700936#ifdef CONFIG_DPP2
937 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
938 wpa_s, NULL);
939#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700940 offchannel_send_action_done(wpa_s);
941 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800942 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700943 }
944
Hai Shalomfdcde762020-04-02 11:19:20 -0700945 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
946 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700947 if (!auth)
948 goto fail;
949 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700950 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700951 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800952 goto fail;
953 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700954
Hai Shalom81f62d82019-07-22 12:10:00 -0700955 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700956
Roshan Pius3a1667e2018-07-03 15:17:14 -0700957 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700958 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700959
Hai Shalom81f62d82019-07-22 12:10:00 -0700960#ifdef CONFIG_DPP2
961 if (tcp)
Hai Shalom899fcc72020-10-19 14:38:18 -0700962 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
963 wpa_s->conf->dpp_name, DPP_NETROLE_STA,
Sunil Ravi89eba102022-09-13 21:04:37 -0700964 wpa_s->conf->dpp_mud_url,
965 wpa_s->conf->dpp_extra_conf_req_name,
966 wpa_s->conf->dpp_extra_conf_req_value,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800967 wpa_s, wpa_s, wpas_dpp_process_conf_obj,
968 wpas_dpp_tcp_msg_sent);
Hai Shalom81f62d82019-07-22 12:10:00 -0700969#endif /* CONFIG_DPP2 */
970
971 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700972 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700973fail:
974 return -1;
975}
976
977
978struct wpas_dpp_listen_work {
979 unsigned int freq;
980 unsigned int duration;
981 struct wpabuf *probe_resp_ie;
982};
983
984
985static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
986{
987 if (!lwork)
988 return;
989 os_free(lwork);
990}
991
992
993static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
994{
995 struct wpas_dpp_listen_work *lwork;
996
997 if (!wpa_s->dpp_listen_work)
998 return;
999
1000 lwork = wpa_s->dpp_listen_work->ctx;
1001 wpas_dpp_listen_work_free(lwork);
1002 radio_work_done(wpa_s->dpp_listen_work);
1003 wpa_s->dpp_listen_work = NULL;
1004}
1005
1006
1007static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
1008{
1009 struct wpa_supplicant *wpa_s = work->wpa_s;
1010 struct wpas_dpp_listen_work *lwork = work->ctx;
1011
1012 if (deinit) {
1013 if (work->started) {
1014 wpa_s->dpp_listen_work = NULL;
1015 wpas_dpp_listen_stop(wpa_s);
1016 }
1017 wpas_dpp_listen_work_free(lwork);
1018 return;
1019 }
1020
1021 wpa_s->dpp_listen_work = work;
1022
1023 wpa_s->dpp_pending_listen_freq = lwork->freq;
1024
1025 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
1026 wpa_s->max_remain_on_chan) < 0) {
1027 wpa_printf(MSG_DEBUG,
1028 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
1029 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -08001030 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001031 wpas_dpp_listen_work_done(wpa_s);
1032 wpa_s->dpp_pending_listen_freq = 0;
1033 return;
1034 }
1035 wpa_s->off_channel_freq = 0;
1036 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -07001037 wpa_drv_dpp_listen(wpa_s, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001038}
1039
1040
1041static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
1042 unsigned int freq)
1043{
1044 struct wpas_dpp_listen_work *lwork;
1045
1046 if (wpa_s->dpp_listen_work) {
1047 wpa_printf(MSG_DEBUG,
1048 "DPP: Reject start_listen since dpp_listen_work already exists");
1049 return -1;
1050 }
1051
1052 if (wpa_s->dpp_listen_freq)
1053 wpas_dpp_listen_stop(wpa_s);
1054 wpa_s->dpp_listen_freq = freq;
1055
1056 lwork = os_zalloc(sizeof(*lwork));
1057 if (!lwork)
1058 return -1;
1059 lwork->freq = freq;
1060
1061 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
1062 lwork) < 0) {
1063 wpas_dpp_listen_work_free(lwork);
1064 return -1;
1065 }
1066
1067 return 0;
1068}
1069
1070
1071int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
1072{
1073 int freq;
1074
1075 freq = atoi(cmd);
1076 if (freq <= 0)
1077 return -1;
1078
1079 if (os_strstr(cmd, " role=configurator"))
1080 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
1081 else if (os_strstr(cmd, " role=enrollee"))
1082 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
1083 else
1084 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
1085 DPP_CAPAB_ENROLLEE;
1086 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001087 if (os_strstr(cmd, " netrole=ap"))
1088 wpa_s->dpp_netrole = DPP_NETROLE_AP;
1089 else if (os_strstr(cmd, " netrole=configurator"))
1090 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
1091 else
1092 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001093 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1094 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1095 freq);
1096 return 0;
1097 }
1098
1099 return wpas_dpp_listen_start(wpa_s, freq);
1100}
1101
1102
1103void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1104{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001105 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001106 if (!wpa_s->dpp_listen_freq)
1107 return;
1108
1109 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1110 wpa_s->dpp_listen_freq);
1111 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001112 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001113 wpa_s->dpp_listen_freq = 0;
1114 wpas_dpp_listen_work_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001115 radio_remove_works(wpa_s, "dpp-listen", 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001116}
1117
1118
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001119void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1120 unsigned int freq, unsigned int duration)
1121{
1122 if (wpa_s->dpp_listen_freq != freq)
1123 return;
1124
1125 wpa_printf(MSG_DEBUG,
1126 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
1127 freq, duration);
1128 os_get_reltime(&wpa_s->dpp_listen_end);
1129 wpa_s->dpp_listen_end.usec += duration * 1000;
1130 while (wpa_s->dpp_listen_end.usec >= 1000000) {
1131 wpa_s->dpp_listen_end.sec++;
1132 wpa_s->dpp_listen_end.usec -= 1000000;
1133 }
1134}
1135
1136
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001137void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1138 unsigned int freq)
1139{
1140 wpas_dpp_listen_work_done(wpa_s);
1141
Roshan Pius3a1667e2018-07-03 15:17:14 -07001142 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1143 unsigned int new_freq;
1144
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001145 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001146 if (wpa_s->dpp_auth->neg_freq > 0)
1147 new_freq = wpa_s->dpp_auth->neg_freq;
1148 else
1149 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001150 wpa_printf(MSG_DEBUG,
1151 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001152 new_freq);
1153 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001154 return;
1155 }
1156
1157 if (wpa_s->dpp_listen_freq) {
1158 /* Continue listen with a new remain-on-channel */
1159 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1160 }
1161}
1162
1163
1164static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1165 const u8 *hdr, const u8 *buf, size_t len,
1166 unsigned int freq)
1167{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001168 const u8 *r_bootstrap, *i_bootstrap;
1169 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001170 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1171
1172 if (!wpa_s->dpp)
1173 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001174
1175 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1176 MAC2STR(src));
1177
Hai Shalomfdcde762020-04-02 11:19:20 -07001178#ifdef CONFIG_DPP2
1179 wpas_dpp_chirp_stop(wpa_s);
1180#endif /* CONFIG_DPP2 */
1181
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001182 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1183 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001184 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1185 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1186 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001187 return;
1188 }
1189 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1190 r_bootstrap, r_bootstrap_len);
1191
1192 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1193 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001194 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1195 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1196 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001197 return;
1198 }
1199 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1200 i_bootstrap, i_bootstrap_len);
1201
1202 /* Try to find own and peer bootstrapping key matches based on the
1203 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001204 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1205 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001206 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001207 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1208 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001209 return;
1210 }
1211
Sunil Ravi89eba102022-09-13 21:04:37 -07001212 if (own_bi->type == DPP_BOOTSTRAP_PKEX) {
1213 if (!peer_bi || peer_bi->type != DPP_BOOTSTRAP_PKEX) {
1214 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1215 "No matching peer bootstrapping key found for PKEX - ignore message");
1216 return;
1217 }
1218
1219 if (os_memcmp(peer_bi->pubkey_hash, own_bi->peer_pubkey_hash,
1220 SHA256_MAC_LEN) != 0) {
1221 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1222 "Mismatching peer PKEX bootstrapping key - ignore message");
1223 return;
1224 }
1225 }
1226
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001227 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001228 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1229 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001230 return;
1231 }
1232
Sunil Ravia04bd252022-05-02 22:54:18 -07001233 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001234 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001235 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001236 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001237 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1238 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001239 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001240 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001241 if (!wpa_s->dpp_auth) {
1242 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1243 return;
1244 }
1245 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001246 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001247 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001248 dpp_auth_deinit(wpa_s->dpp_auth);
1249 wpa_s->dpp_auth = NULL;
1250 return;
1251 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001252 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1253
Roshan Pius3a1667e2018-07-03 15:17:14 -07001254 if (wpa_s->dpp_listen_freq &&
1255 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1256 wpa_printf(MSG_DEBUG,
1257 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1258 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1259 wpas_dpp_listen_stop(wpa_s);
1260 }
1261
Sunil Ravi88611412024-06-28 17:34:56 +00001262 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1263 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1264 DPP_PA_AUTHENTICATION_RESP);
1265 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1266 src, wpa_s->own_addr, broadcast,
1267 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1268 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1269 500, wpas_dpp_tx_status, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001270}
1271
1272
Hai Shaloma20dcd72022-02-04 13:43:00 -08001273void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
1274{
1275 struct dpp_authentication *auth = wpa_s->dpp_auth;
1276 int freq;
1277
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001278 if (!wpa_s->dpp_gas_server || !auth) {
1279 if (auth && auth->waiting_auth_resp &&
1280 eloop_is_timeout_registered(wpas_dpp_drv_wait_timeout,
1281 wpa_s, NULL)) {
1282 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout,
1283 wpa_s, NULL);
1284 wpa_printf(MSG_DEBUG,
1285 "DPP: Call wpas_dpp_auth_init_next() from %s",
1286 __func__);
1287 wpas_dpp_auth_init_next(wpa_s);
1288 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001289 return;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001290 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001291
1292 freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
1293 if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
1294 return; /* listen state is already in progress */
1295
1296 wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
1297 wpa_s->dpp_in_response_listen = 1;
1298 wpas_dpp_listen_start(wpa_s, freq);
1299}
1300
1301
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001302static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1303{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001304 struct dpp_authentication *auth = wpa_s->dpp_auth;
1305
1306 wpa_printf(MSG_DEBUG,
1307 "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
1308 auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
1309 !!wpa_s->dpp_listen_work);
1310 wpa_s->dpp_gas_server = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001311}
1312
1313
1314static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001315 struct dpp_authentication *auth,
1316 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001317{
1318 struct wpa_ssid *ssid;
1319
Hai Shalom021b0b52019-04-10 11:17:58 -07001320#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001321 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001322#ifdef CONFIG_SAE
1323 struct wpa_driver_capa capa;
1324 int res;
1325
1326 res = wpa_drv_get_capa(wpa_s, &capa);
1327 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001328 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1329 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001330 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1331 wpa_printf(MSG_DEBUG,
1332 "DPP: SAE not supported by the driver");
1333 return NULL;
1334 }
1335#else /* CONFIG_SAE */
1336 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1337 return NULL;
1338#endif /* CONFIG_SAE */
1339 }
1340#endif /* CONFIG_DPP2 */
1341
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001342 ssid = wpa_config_add_network(wpa_s->conf);
1343 if (!ssid)
1344 return NULL;
1345 wpas_notify_network_added(wpa_s, ssid);
1346 wpa_config_set_network_defaults(ssid);
1347 ssid->disabled = 1;
1348
Hai Shalomc3565922019-10-28 11:58:20 -07001349 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001350 if (!ssid->ssid)
1351 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001352 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1353 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001354
Hai Shalomc3565922019-10-28 11:58:20 -07001355 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001356 if (dpp_akm_dpp(conf->akm)) {
1357 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1358 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1359 }
Hai Shalomc3565922019-10-28 11:58:20 -07001360 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001361 if (!ssid->dpp_connector)
1362 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07001363
1364 ssid->dpp_connector_privacy =
1365 wpa_s->conf->dpp_connector_privacy_default;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001366 }
1367
Hai Shalomc3565922019-10-28 11:58:20 -07001368 if (conf->c_sign_key) {
1369 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001370 if (!ssid->dpp_csign)
1371 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001372 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1373 wpabuf_len(conf->c_sign_key));
1374 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001375 }
1376
Hai Shalom899fcc72020-10-19 14:38:18 -07001377 if (conf->pp_key) {
1378 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1379 if (!ssid->dpp_pp_key)
1380 goto fail;
1381 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1382 wpabuf_len(conf->pp_key));
1383 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1384 }
1385
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001386 if (auth->net_access_key) {
1387 ssid->dpp_netaccesskey =
1388 os_malloc(wpabuf_len(auth->net_access_key));
1389 if (!ssid->dpp_netaccesskey)
1390 goto fail;
1391 os_memcpy(ssid->dpp_netaccesskey,
1392 wpabuf_head(auth->net_access_key),
1393 wpabuf_len(auth->net_access_key));
1394 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1395 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1396 }
1397
Hai Shalomc3565922019-10-28 11:58:20 -07001398 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1399 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001400 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001401 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001402 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001403 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1404 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001405 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001406 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1407 WPA_KEY_MGMT_FT_SAE;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001408 if (dpp_akm_psk(conf->akm))
1409 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1410 else
1411 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalomc3565922019-10-28 11:58:20 -07001412 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001413 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001414 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001415 goto fail;
1416 wpa_config_update_psk(ssid);
1417 ssid->export_keys = 1;
1418 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001419 ssid->psk_set = conf->psk_set;
1420 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001421 }
1422 }
1423
Hai Shalom899fcc72020-10-19 14:38:18 -07001424#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1425 if (conf->akm == DPP_AKM_DOT1X) {
1426 int i;
1427 char name[100], blobname[128];
1428 struct wpa_config_blob *blob;
1429
1430 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1431 WPA_KEY_MGMT_IEEE8021X_SHA256 |
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001432 WPA_KEY_MGMT_IEEE8021X_SHA384;
Hai Shalom899fcc72020-10-19 14:38:18 -07001433 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1434
1435 if (conf->cacert) {
1436 /* caCert is DER-encoded X.509v3 certificate for the
1437 * server certificate if that is different from the
1438 * trust root included in certBag. */
1439 /* TODO: ssid->eap.cert.ca_cert */
1440 }
1441
1442 if (conf->certs) {
1443 for (i = 0; ; i++) {
1444 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1445 i);
1446 if (!wpa_config_get_blob(wpa_s->conf, name))
1447 break;
1448 }
1449
1450 blob = os_zalloc(sizeof(*blob));
1451 if (!blob)
1452 goto fail;
1453 blob->len = wpabuf_len(conf->certs);
1454 blob->name = os_strdup(name);
1455 blob->data = os_malloc(blob->len);
1456 if (!blob->name || !blob->data) {
1457 wpa_config_free_blob(blob);
1458 goto fail;
1459 }
1460 os_memcpy(blob->data, wpabuf_head(conf->certs),
1461 blob->len);
1462 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1463 name);
1464 wpa_config_set_blob(wpa_s->conf, blob);
1465 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1466 name);
1467 ssid->eap.cert.client_cert = os_strdup(blobname);
1468 if (!ssid->eap.cert.client_cert)
1469 goto fail;
1470
1471 /* TODO: ssid->eap.identity from own certificate */
1472 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1473 0) < 0)
1474 goto fail;
1475 }
1476
1477 if (auth->priv_key) {
1478 for (i = 0; ; i++) {
1479 os_snprintf(name, sizeof(name), "dpp-key-%d",
1480 i);
1481 if (!wpa_config_get_blob(wpa_s->conf, name))
1482 break;
1483 }
1484
1485 blob = os_zalloc(sizeof(*blob));
1486 if (!blob)
1487 goto fail;
1488 blob->len = wpabuf_len(auth->priv_key);
1489 blob->name = os_strdup(name);
1490 blob->data = os_malloc(blob->len);
1491 if (!blob->name || !blob->data) {
1492 wpa_config_free_blob(blob);
1493 goto fail;
1494 }
1495 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1496 blob->len);
1497 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1498 name);
1499 wpa_config_set_blob(wpa_s->conf, blob);
1500 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1501 name);
1502 ssid->eap.cert.private_key = os_strdup(blobname);
1503 if (!ssid->eap.cert.private_key)
1504 goto fail;
1505 }
1506
1507 if (conf->server_name) {
1508 ssid->eap.cert.domain_suffix_match =
1509 os_strdup(conf->server_name);
1510 if (!ssid->eap.cert.domain_suffix_match)
1511 goto fail;
1512 }
1513
1514 /* TODO: Use entCreds::eapMethods */
1515 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1516 goto fail;
1517 }
1518#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1519
Hai Shalomc3565922019-10-28 11:58:20 -07001520 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1521 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1522
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001523 return ssid;
1524fail:
1525 wpas_notify_network_removed(wpa_s, ssid);
1526 wpa_config_remove_network(wpa_s->conf, ssid->id);
1527 return NULL;
1528}
1529
1530
Hai Shalom021b0b52019-04-10 11:17:58 -07001531static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001532 struct dpp_authentication *auth,
1533 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001534{
1535 struct wpa_ssid *ssid;
1536
1537 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001538 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001539
Hai Shalomc3565922019-10-28 11:58:20 -07001540 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001541 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001542 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001543
1544 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001545
Sunil Ravi546a7b52022-08-26 22:06:04 +00001546 wpas_notify_dpp_config_received(wpa_s, ssid, auth->conn_status_requested ? 1 : 0);
Hai Shalom59532852018-12-07 10:32:58 -08001547
Hai Shalom021b0b52019-04-10 11:17:58 -07001548 if (wpa_s->conf->dpp_config_processing == 2)
1549 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001550
Hai Shalom021b0b52019-04-10 11:17:58 -07001551#ifndef CONFIG_NO_CONFIG_WRITE
1552 if (wpa_s->conf->update_config &&
1553 wpa_config_write(wpa_s->confname, wpa_s->conf))
1554 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1555#endif /* CONFIG_NO_CONFIG_WRITE */
1556
Hai Shalomc3565922019-10-28 11:58:20 -07001557 return 0;
1558}
1559
1560
1561static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1562 struct dpp_authentication *auth)
1563{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001564#ifdef CONFIG_DPP2
1565 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1566 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1567 wpa_s->dpp_reconfig_ssid) {
1568 wpa_printf(MSG_DEBUG,
1569 "DPP: Remove reconfigured network profile");
1570 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1571 wpa_config_remove_network(wpa_s->conf,
1572 wpa_s->dpp_reconfig_ssid_id);
1573 wpa_s->dpp_reconfig_ssid = NULL;
1574 wpa_s->dpp_reconfig_ssid_id = -1;
1575 }
1576#endif /* CONFIG_DPP2 */
1577
Hai Shalom021b0b52019-04-10 11:17:58 -07001578 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001579 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001580
1581#ifdef CONFIG_DPP2
1582 if (auth->peer_version >= 2) {
1583 wpa_printf(MSG_DEBUG,
1584 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1585 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001586 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001587 }
1588#endif /* CONFIG_DPP2 */
1589
1590 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001591}
1592
1593
Hai Shalom021b0b52019-04-10 11:17:58 -07001594static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001595 struct dpp_authentication *auth,
1596 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001597{
1598 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001599 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1600 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001601 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001602 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001603 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001604 if (conf->ssid_charset)
1605 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1606 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001607 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001608 /* TODO: Save the Connector and consider using a command
1609 * to fetch the value instead of sending an event with
1610 * it. The Connector could end up being larger than what
1611 * most clients are ready to receive as an event
1612 * message. */
1613 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001614 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001615 }
Hai Shalom60840252021-02-19 19:02:11 -08001616 if (conf->passphrase[0]) {
1617 char hex[64 * 2 + 1];
1618
1619 wpa_snprintf_hex(hex, sizeof(hex),
1620 (const u8 *) conf->passphrase,
1621 os_strlen(conf->passphrase));
1622 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1623 hex);
1624 } else if (conf->psk_set) {
1625 char hex[PMK_LEN * 2 + 1];
1626
1627 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1628 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1629 hex);
1630 }
Hai Shalomc3565922019-10-28 11:58:20 -07001631 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001632 char *hex;
1633 size_t hexlen;
1634
Hai Shalomc3565922019-10-28 11:58:20 -07001635 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001636 hex = os_malloc(hexlen);
1637 if (hex) {
1638 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001639 wpabuf_head(conf->c_sign_key),
1640 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001641 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1642 hex);
1643 os_free(hex);
1644 }
1645 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001646 if (conf->pp_key) {
1647 char *hex;
1648 size_t hexlen;
1649
1650 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1651 hex = os_malloc(hexlen);
1652 if (hex) {
1653 wpa_snprintf_hex(hex, hexlen,
1654 wpabuf_head(conf->pp_key),
1655 wpabuf_len(conf->pp_key));
1656 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1657 os_free(hex);
1658 }
1659 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001660 if (auth->net_access_key) {
1661 char *hex;
1662 size_t hexlen;
1663
1664 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1665 hex = os_malloc(hexlen);
1666 if (hex) {
1667 wpa_snprintf_hex(hex, hexlen,
1668 wpabuf_head(auth->net_access_key),
1669 wpabuf_len(auth->net_access_key));
1670 if (auth->net_access_key_expiry)
1671 wpa_msg(wpa_s, MSG_INFO,
1672 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1673 (long unsigned)
1674 auth->net_access_key_expiry);
1675 else
1676 wpa_msg(wpa_s, MSG_INFO,
1677 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1678 os_free(hex);
1679 }
1680 }
1681
Hai Shalom899fcc72020-10-19 14:38:18 -07001682#ifdef CONFIG_DPP2
1683 if (conf->certbag) {
1684 char *b64;
1685
1686 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1687 wpabuf_len(conf->certbag), NULL);
1688 if (b64)
1689 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1690 os_free(b64);
1691 }
1692
1693 if (conf->cacert) {
1694 char *b64;
1695
1696 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1697 wpabuf_len(conf->cacert), NULL);
1698 if (b64)
1699 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1700 os_free(b64);
1701 }
1702
1703 if (conf->server_name)
1704 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1705 conf->server_name);
1706#endif /* CONFIG_DPP2 */
1707
Sunil Ravi89eba102022-09-13 21:04:37 -07001708#ifdef CONFIG_DPP3
1709 if (!wpa_s->dpp_pb_result_indicated) {
1710 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "success");
1711 wpa_s->dpp_pb_result_indicated = true;
1712 }
1713
1714#endif /* CONFIG_DPP3 */
1715
Hai Shalomc3565922019-10-28 11:58:20 -07001716 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001717}
1718
1719
Hai Shalomfdcde762020-04-02 11:19:20 -07001720static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1721 struct dpp_asymmetric_key *key)
1722{
1723#ifdef CONFIG_DPP2
1724 int res;
1725
1726 if (!key)
1727 return 0;
1728
1729 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1730 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001731 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001732
1733 while (key) {
1734 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1735 if (res < 0)
1736 return -1;
1737 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1738 res);
1739 key = key->next;
1740 }
1741#endif /* CONFIG_DPP2 */
1742
1743 return 0;
1744}
1745
1746
Hai Shalom899fcc72020-10-19 14:38:18 -07001747#ifdef CONFIG_DPP2
1748static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1749{
1750 struct wpa_supplicant *wpa_s = eloop_ctx;
1751 struct dpp_authentication *auth = wpa_s->dpp_auth;
1752
1753 if (!auth || !auth->csrattrs)
1754 return;
1755
1756 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1757 wpabuf_free(auth->csr);
1758 /* TODO: Additional information needed for CSR based on csrAttrs */
1759 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1760 wpa_s->conf->dpp_name : "Test");
1761 if (!auth->csr) {
1762 dpp_auth_deinit(wpa_s->dpp_auth);
1763 wpa_s->dpp_auth = NULL;
1764 return;
1765 }
1766
1767 wpas_dpp_start_gas_client(wpa_s);
1768}
1769#endif /* CONFIG_DPP2 */
1770
1771
Sunil Ravia04bd252022-05-02 22:54:18 -07001772#ifdef CONFIG_DPP3
1773static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1774{
1775 struct wpa_supplicant *wpa_s = eloop_ctx;
1776 struct dpp_authentication *auth = wpa_s->dpp_auth;
1777
1778 if (!auth || !auth->waiting_new_key)
1779 return;
1780
1781 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1782 wpas_dpp_start_gas_client(wpa_s);
1783}
1784#endif /* CONFIG_DPP3 */
1785
1786
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001787static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1788 enum gas_query_result result,
1789 const struct wpabuf *adv_proto,
1790 const struct wpabuf *resp, u16 status_code)
1791{
1792 struct wpa_supplicant *wpa_s = ctx;
1793 const u8 *pos;
1794 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001795 int res;
1796 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001797 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001798
Hai Shaloma20dcd72022-02-04 13:43:00 -08001799 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001800 wpa_s->dpp_gas_dialog_token = -1;
1801
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001802 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001803 !ether_addr_equal(addr, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001804 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1805 return;
1806 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001807 if (result != GAS_QUERY_SUCCESS ||
1808 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001809 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1810 goto fail;
1811 }
1812
1813 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1814 adv_proto);
1815 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1816 resp);
1817
1818 if (wpabuf_len(adv_proto) != 10 ||
1819 !(pos = wpabuf_head(adv_proto)) ||
1820 pos[0] != WLAN_EID_ADV_PROTO ||
1821 pos[1] != 8 ||
1822 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1823 pos[4] != 5 ||
1824 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1825 pos[8] != 0x1a ||
1826 pos[9] != 1) {
1827 wpa_printf(MSG_DEBUG,
1828 "DPP: Not a DPP Advertisement Protocol ID");
1829 goto fail;
1830 }
1831
Hai Shalom899fcc72020-10-19 14:38:18 -07001832 res = dpp_conf_resp_rx(auth, resp);
1833#ifdef CONFIG_DPP2
1834 if (res == -2) {
1835 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1836 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1837 return;
1838 }
1839#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001840#ifdef CONFIG_DPP3
1841 if (res == -3) {
1842 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1843 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1844 NULL);
1845 return;
1846 }
1847#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001848 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001849 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1850 goto fail;
1851 }
1852
Hai Shalom899fcc72020-10-19 14:38:18 -07001853 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001854 for (i = 0; i < auth->num_conf_obj; i++) {
1855 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1856 &auth->conf_obj[i]);
1857 if (res < 0)
1858 goto fail;
1859 }
1860 if (auth->num_conf_obj)
1861 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001862 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1863 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001864
Hai Shalom021b0b52019-04-10 11:17:58 -07001865 status = DPP_STATUS_OK;
1866#ifdef CONFIG_TESTING_OPTIONS
1867 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1868 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1869 status = DPP_STATUS_CONFIG_REJECTED;
1870 }
1871#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001872fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001873 if (status != DPP_STATUS_OK) {
1874 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1875 wpas_notify_dpp_configuration_failure(wpa_s);
1876 }
1877#ifdef CONFIG_DPP2
1878 if (auth->peer_version >= 2 &&
1879 auth->conf_resp_status == DPP_STATUS_OK) {
1880 struct wpabuf *msg;
1881
1882 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1883 msg = dpp_build_conf_result(auth, status);
1884 if (!msg)
1885 goto fail2;
1886
1887 wpa_msg(wpa_s, MSG_INFO,
1888 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1889 MAC2STR(addr), auth->curr_freq,
1890 DPP_PA_CONFIGURATION_RESULT);
1891 offchannel_send_action(wpa_s, auth->curr_freq,
1892 addr, wpa_s->own_addr, broadcast,
1893 wpabuf_head(msg),
1894 wpabuf_len(msg),
1895 500, wpas_dpp_tx_status, 0);
1896 wpabuf_free(msg);
1897
1898 /* This exchange will be terminated in the TX status handler */
Sunil Ravi546a7b52022-08-26 22:06:04 +00001899 if (wpa_s->conf->dpp_config_processing < 1 ||
Hai Shalom899fcc72020-10-19 14:38:18 -07001900 wpa_s->dpp_conf_backup_received)
1901 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001902 return;
1903 }
1904fail2:
1905#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001906 dpp_auth_deinit(wpa_s->dpp_auth);
1907 wpa_s->dpp_auth = NULL;
1908}
1909
1910
Hai Shaloma20dcd72022-02-04 13:43:00 -08001911static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
1912{
1913 struct wpa_supplicant *wpa_s = eloop_ctx;
1914 struct dpp_authentication *auth = wpa_s->dpp_auth;
1915
1916 if (!wpa_s->dpp_gas_client || !auth ||
1917 (!auth->auth_success && !auth->reconfig_success))
1918 return;
1919
1920 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
1921 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1922 dpp_auth_deinit(wpa_s->dpp_auth);
1923 wpa_s->dpp_auth = NULL;
1924}
1925
1926
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001927static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1928{
1929 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001930 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001931 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001932 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001933
1934 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001935 offchannel_send_action_done(wpa_s);
1936 wpas_dpp_listen_stop(wpa_s);
1937
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001938#ifdef CONFIG_NO_RRM
1939 supp_op_classes = NULL;
1940#else /* CONFIG_NO_RRM */
Hai Shalomc3565922019-10-28 11:58:20 -07001941 supp_op_classes = wpas_supp_op_classes(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001942#endif /* CONFIG_NO_RRM */
Hai Shalomc3565922019-10-28 11:58:20 -07001943 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001944 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001945 wpa_s->conf->dpp_mud_url,
Sunil Ravi89eba102022-09-13 21:04:37 -07001946 supp_op_classes,
1947 wpa_s->conf->dpp_extra_conf_req_name,
1948 wpa_s->conf->dpp_extra_conf_req_value);
Hai Shalomc3565922019-10-28 11:58:20 -07001949 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001950 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001951 wpa_printf(MSG_DEBUG,
1952 "DPP: No configuration request data available");
1953 return;
1954 }
1955
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001956 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1957 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1958
Hai Shaloma20dcd72022-02-04 13:43:00 -08001959 /* Use a 120 second timeout since the gas_query_req() operation could
1960 * remain waiting indefinitely for the response if the Configurator
1961 * keeps sending out comeback responses with additional delay. The
1962 * DPP technical specification expects the Enrollee to continue sending
1963 * out new Config Requests for 60 seconds, so this gives an extra 60
1964 * second time after the last expected new Config Request for the
1965 * Configurator to determine what kind of configuration to provide. */
1966 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
1967 wpa_s, NULL);
1968
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001969 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001970 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001971 if (res < 0) {
1972 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1973 wpabuf_free(buf);
1974 } else {
1975 wpa_printf(MSG_DEBUG,
1976 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001977 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001978 }
1979}
1980
1981
1982static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1983{
1984 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001985 dpp_notify_auth_success(wpa_s->dpp_auth, initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001986 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001987#ifdef CONFIG_TESTING_OPTIONS
1988 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1989 wpa_printf(MSG_INFO,
1990 "DPP: TESTING - stop at Authentication Confirm");
1991 if (wpa_s->dpp_auth->configurator) {
1992 /* Prevent GAS response */
1993 wpa_s->dpp_auth->auth_success = 0;
1994 }
1995 return;
1996 }
1997#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001998
1999 if (wpa_s->dpp_auth->configurator)
2000 wpas_dpp_start_gas_server(wpa_s);
2001 else
2002 wpas_dpp_start_gas_client(wpa_s);
2003}
2004
2005
2006static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002007 const u8 *hdr, const u8 *buf, size_t len,
2008 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002009{
2010 struct dpp_authentication *auth = wpa_s->dpp_auth;
2011 struct wpabuf *msg;
2012
Roshan Pius3a1667e2018-07-03 15:17:14 -07002013 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
2014 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002015
2016 if (!auth) {
2017 wpa_printf(MSG_DEBUG,
2018 "DPP: No DPP Authentication in progress - drop");
2019 return;
2020 }
2021
2022 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002023 !ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002024 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2025 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2026 return;
2027 }
2028
2029 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
2030
Roshan Pius3a1667e2018-07-03 15:17:14 -07002031 if (auth->curr_freq != freq && auth->neg_freq == freq) {
2032 wpa_printf(MSG_DEBUG,
2033 "DPP: Responder accepted request for different negotiation channel");
2034 auth->curr_freq = freq;
2035 }
2036
2037 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002038 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
2039 if (!msg) {
2040 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
2041 wpa_printf(MSG_DEBUG,
2042 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08002043 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002044 offchannel_send_action_done(wpa_s);
2045 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
2046 return;
2047 }
2048 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
2049 return;
2050 }
2051 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2052
Roshan Pius3a1667e2018-07-03 15:17:14 -07002053 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2054 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002055 offchannel_send_action(wpa_s, auth->curr_freq,
2056 src, wpa_s->own_addr, broadcast,
2057 wpabuf_head(msg), wpabuf_len(msg),
2058 500, wpas_dpp_tx_status, 0);
2059 wpabuf_free(msg);
2060 wpa_s->dpp_auth_ok_on_ack = 1;
2061}
2062
2063
2064static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2065 const u8 *hdr, const u8 *buf, size_t len)
2066{
2067 struct dpp_authentication *auth = wpa_s->dpp_auth;
2068
2069 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
2070 MAC2STR(src));
2071
2072 if (!auth) {
2073 wpa_printf(MSG_DEBUG,
2074 "DPP: No DPP Authentication in progress - drop");
2075 return;
2076 }
2077
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002078 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002079 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2080 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2081 return;
2082 }
2083
Hai Shalom60840252021-02-19 19:02:11 -08002084 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
2085
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002086 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
2087 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08002088 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002089 return;
2090 }
2091
2092 wpas_dpp_auth_success(wpa_s, 0);
2093}
2094
2095
Hai Shalom021b0b52019-04-10 11:17:58 -07002096#ifdef CONFIG_DPP2
2097
2098static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
2099 void *timeout_ctx)
2100{
2101 struct wpa_supplicant *wpa_s = eloop_ctx;
2102 struct dpp_authentication *auth = wpa_s->dpp_auth;
2103
2104 if (!auth || !auth->waiting_conf_result)
2105 return;
2106
2107 wpa_printf(MSG_DEBUG,
2108 "DPP: Timeout while waiting for Configuration Result");
2109 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002110 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002111 dpp_auth_deinit(auth);
2112 wpa_s->dpp_auth = NULL;
2113}
2114
2115
Hai Shalomc3565922019-10-28 11:58:20 -07002116static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2117 void *timeout_ctx)
2118{
2119 struct wpa_supplicant *wpa_s = eloop_ctx;
2120 struct dpp_authentication *auth = wpa_s->dpp_auth;
2121
2122 if (!auth || !auth->waiting_conn_status_result)
2123 return;
2124
2125 wpa_printf(MSG_DEBUG,
2126 "DPP: Timeout while waiting for Connection Status Result");
2127 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002128 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002129 wpas_dpp_listen_stop(wpa_s);
2130 dpp_auth_deinit(auth);
2131 wpa_s->dpp_auth = NULL;
2132}
2133
2134
Sunil Ravi89eba102022-09-13 21:04:37 -07002135#ifdef CONFIG_DPP3
2136
2137static bool wpas_dpp_pb_active(struct wpa_supplicant *wpa_s)
2138{
2139 return (wpa_s->dpp_pb_time.sec || wpa_s->dpp_pb_time.usec) &&
2140 wpa_s->dpp_pb_configurator;
2141}
2142
2143
2144static void wpas_dpp_remove_pb_hash(struct wpa_supplicant *wpa_s)
2145{
2146 int i;
2147
2148 if (!wpa_s->dpp_pb_bi)
2149 return;
2150 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2151 struct dpp_pb_info *info = &wpa_s->dpp_pb[i];
2152
2153 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
2154 continue;
2155 if (os_memcmp(info->hash, wpa_s->dpp_pb_resp_hash,
2156 SHA256_MAC_LEN) == 0) {
2157 /* Allow a new push button session to be established
2158 * immediately without the successfully completed
2159 * session triggering session overlap. */
2160 info->rx_time.sec = 0;
2161 info->rx_time.usec = 0;
2162 wpa_printf(MSG_DEBUG,
2163 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
2164 }
2165 }
2166}
2167
2168#endif /* CONFIG_DPP3 */
2169
2170
Hai Shalom021b0b52019-04-10 11:17:58 -07002171static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2172 const u8 *hdr, const u8 *buf, size_t len)
2173{
2174 struct dpp_authentication *auth = wpa_s->dpp_auth;
2175 enum dpp_status_error status;
2176
2177 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2178 MAC2STR(src));
2179
2180 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002181 if (auth &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002182 ether_addr_equal(src, auth->peer_mac_addr) &&
Hai Shalom60840252021-02-19 19:02:11 -08002183 gas_server_response_sent(wpa_s->gas_server,
2184 auth->gas_server_ctx)) {
2185 /* This could happen if the TX status event gets delayed
2186 * long enough for the Enrollee to have time to send
2187 * the next frame before the TX status gets processed
2188 * locally. */
2189 wpa_printf(MSG_DEBUG,
2190 "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");
2191 auth->waiting_conf_result = 1;
2192 } else {
2193 wpa_printf(MSG_DEBUG,
2194 "DPP: No DPP Configuration waiting for result - drop");
2195 return;
2196 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002197 }
2198
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002199 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002200 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2201 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2202 return;
2203 }
2204
2205 status = dpp_conf_result_rx(auth, hdr, buf, len);
2206
Hai Shalomc3565922019-10-28 11:58:20 -07002207 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002208 int freq;
2209
Hai Shalomc3565922019-10-28 11:58:20 -07002210 wpa_msg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07002211 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
2212 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07002213 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002214 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002215 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2216 wpa_s, NULL);
2217 auth->waiting_conn_status_result = 1;
2218 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2219 wpa_s, NULL);
2220 eloop_register_timeout(16, 0,
2221 wpas_dpp_conn_status_result_wait_timeout,
2222 wpa_s, NULL);
2223 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002224 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2225 if (!wpa_s->dpp_in_response_listen ||
2226 (int) wpa_s->dpp_listen_freq != freq)
2227 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002228 return;
2229 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002230 offchannel_send_action_done(wpa_s);
2231 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002232 if (status == DPP_STATUS_OK) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002233 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
2234 auth->conf_resp_status);
Hai Shalome4073332019-11-05 16:20:12 -08002235 wpas_notify_dpp_config_sent(wpa_s);
2236 }
2237 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002238 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002239 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002240 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002241 dpp_auth_deinit(auth);
2242 wpa_s->dpp_auth = NULL;
2243 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07002244#ifdef CONFIG_DPP3
2245 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
2246 if (status == DPP_STATUS_OK)
2247 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2248 "success");
2249 else
2250 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2251 "no-configuration-available");
2252 wpa_s->dpp_pb_result_indicated = true;
2253 if (status == DPP_STATUS_OK)
2254 wpas_dpp_remove_pb_hash(wpa_s);
2255 wpas_dpp_push_button_stop(wpa_s);
2256 }
2257#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002258}
2259
Hai Shalom81f62d82019-07-22 12:10:00 -07002260
Hai Shalomc3565922019-10-28 11:58:20 -07002261static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2262 const u8 *src, const u8 *hdr,
2263 const u8 *buf, size_t len)
2264{
2265 struct dpp_authentication *auth = wpa_s->dpp_auth;
2266 enum dpp_status_error status;
2267 u8 ssid[SSID_MAX_LEN];
2268 size_t ssid_len = 0;
2269 char *channel_list = NULL;
2270
2271 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2272
2273 if (!auth || !auth->waiting_conn_status_result) {
2274 wpa_printf(MSG_DEBUG,
2275 "DPP: No DPP Configuration waiting for connection status result - drop");
2276 return;
2277 }
2278
2279 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2280 ssid, &ssid_len, &channel_list);
2281 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2282 "result=%d ssid=%s channel_list=%s",
2283 status, wpa_ssid_txt(ssid, ssid_len),
2284 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002285 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2286 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002287 os_free(channel_list);
2288 offchannel_send_action_done(wpa_s);
2289 wpas_dpp_listen_stop(wpa_s);
2290 dpp_auth_deinit(auth);
2291 wpa_s->dpp_auth = NULL;
2292 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2293 wpa_s, NULL);
2294}
2295
2296
Hai Shalom81f62d82019-07-22 12:10:00 -07002297static int wpas_dpp_process_conf_obj(void *ctx,
2298 struct dpp_authentication *auth)
2299{
2300 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002301 unsigned int i;
2302 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002303
Hai Shalomc3565922019-10-28 11:58:20 -07002304 for (i = 0; i < auth->num_conf_obj; i++) {
2305 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2306 &auth->conf_obj[i]);
2307 if (res)
2308 break;
2309 }
2310 if (!res)
2311 wpas_dpp_post_process_config(wpa_s, auth);
2312
2313 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002314}
2315
Hai Shalomfdcde762020-04-02 11:19:20 -07002316
Hai Shaloma20dcd72022-02-04 13:43:00 -08002317static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2318{
2319 struct wpa_supplicant *wpa_s = ctx;
2320
2321 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2322
2323 if (auth->connect_on_tx_status) {
2324 auth->connect_on_tx_status = 0;
2325 wpa_printf(MSG_DEBUG,
2326 "DPP: Try to connect after completed configuration result");
2327 wpas_dpp_try_to_connect(wpa_s);
2328 if (auth->conn_status_requested) {
2329 wpa_printf(MSG_DEBUG,
2330 "DPP: Start 15 second timeout for reporting connection status result");
2331 eloop_cancel_timeout(
2332 wpas_dpp_conn_status_result_timeout,
2333 wpa_s, NULL);
2334 eloop_register_timeout(
2335 15, 0, wpas_dpp_conn_status_result_timeout,
2336 wpa_s, NULL);
2337 return true;
2338 }
2339 }
2340
2341 return false;
2342}
2343
2344
Hai Shalomfdcde762020-04-02 11:19:20 -07002345static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2346{
2347 struct wpa_supplicant *wpa_s = ctx;
2348
2349 if (bi == wpa_s->dpp_chirp_bi)
2350 wpas_dpp_chirp_stop(wpa_s);
2351}
2352
2353
2354static void
2355wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2356 const u8 *hdr, const u8 *buf, size_t len,
2357 unsigned int freq)
2358{
2359 const u8 *r_bootstrap;
2360 u16 r_bootstrap_len;
2361 struct dpp_bootstrap_info *peer_bi;
2362 struct dpp_authentication *auth;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002363 unsigned int wait_time, max_wait_time;
Hai Shalomfdcde762020-04-02 11:19:20 -07002364
2365 if (!wpa_s->dpp)
2366 return;
2367
2368 if (wpa_s->dpp_auth) {
2369 wpa_printf(MSG_DEBUG,
2370 "DPP: Ignore Presence Announcement during ongoing Authentication");
2371 return;
2372 }
2373
2374 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2375 MAC2STR(src));
2376
2377 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2378 &r_bootstrap_len);
2379 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2380 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2381 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2382 return;
2383 }
2384 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2385 r_bootstrap, r_bootstrap_len);
2386 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002387 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2388 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002389 if (!peer_bi) {
2390 wpa_printf(MSG_DEBUG,
2391 "DPP: No matching bootstrapping information found");
2392 return;
2393 }
2394
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002395 wpa_printf(MSG_DEBUG, "DPP: Start Authentication exchange with " MACSTR
2396 " based on the received Presence Announcement",
2397 MAC2STR(src));
Hai Shalomfdcde762020-04-02 11:19:20 -07002398 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2399 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2400 if (!auth)
2401 return;
2402 wpas_dpp_set_testing_options(wpa_s, auth);
2403 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2404 dpp_auth_deinit(auth);
2405 return;
2406 }
2407
2408 auth->neg_freq = freq;
2409
Hai Shalom60840252021-02-19 19:02:11 -08002410 /* The source address of the Presence Announcement frame overrides any
2411 * MAC address information from the bootstrapping information. */
2412 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002413
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002414 wait_time = wpa_s->max_remain_on_chan;
2415 max_wait_time = wpa_s->dpp_resp_wait_time ?
2416 wpa_s->dpp_resp_wait_time : 2000;
2417 if (wait_time > max_wait_time)
2418 wait_time = max_wait_time;
2419 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2420
Hai Shalomfdcde762020-04-02 11:19:20 -07002421 wpa_s->dpp_auth = auth;
2422 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2423 dpp_auth_deinit(wpa_s->dpp_auth);
2424 wpa_s->dpp_auth = NULL;
2425 }
2426}
2427
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002428
2429static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2430 void *timeout_ctx)
2431{
2432 struct wpa_supplicant *wpa_s = eloop_ctx;
2433 struct dpp_authentication *auth = wpa_s->dpp_auth;
2434
2435 if (!auth)
2436 return;
2437
2438 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2439 offchannel_send_action_done(wpa_s);
2440 wpas_dpp_listen_stop(wpa_s);
2441 dpp_auth_deinit(auth);
2442 wpa_s->dpp_auth = NULL;
2443}
2444
2445
2446static void
2447wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2448 const u8 *hdr, const u8 *buf, size_t len,
2449 unsigned int freq)
2450{
Hai Shalom899fcc72020-10-19 14:38:18 -07002451 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2452 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002453 struct dpp_configurator *conf;
2454 struct dpp_authentication *auth;
2455 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002456 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002457
2458 if (!wpa_s->dpp)
2459 return;
2460
2461 if (wpa_s->dpp_auth) {
2462 wpa_printf(MSG_DEBUG,
2463 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2464 return;
2465 }
2466
2467 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2468 MAC2STR(src));
2469
2470 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2471 &csign_hash_len);
2472 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2473 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2474 "Missing or invalid required Configurator C-sign key Hash attribute");
2475 return;
2476 }
2477 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2478 csign_hash, csign_hash_len);
2479 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2480 if (!conf) {
2481 wpa_printf(MSG_DEBUG,
2482 "DPP: No matching Configurator information found");
2483 return;
2484 }
2485
Hai Shalom899fcc72020-10-19 14:38:18 -07002486 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2487 &fcgroup_len);
2488 if (!fcgroup || fcgroup_len != 2) {
2489 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2490 "Missing or invalid required Finite Cyclic Group attribute");
2491 return;
2492 }
2493 group = WPA_GET_LE16(fcgroup);
2494 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2495
2496 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2497 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2498
2499 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2500 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002501 if (!auth)
2502 return;
2503 wpas_dpp_set_testing_options(wpa_s, auth);
2504 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2505 dpp_auth_deinit(auth);
2506 return;
2507 }
2508
2509 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2510 wpa_s->dpp_auth = auth;
2511
2512 wpa_s->dpp_in_response_listen = 0;
2513 wpa_s->dpp_auth_ok_on_ack = 0;
2514 wait_time = wpa_s->max_remain_on_chan;
2515 max_wait_time = wpa_s->dpp_resp_wait_time ?
2516 wpa_s->dpp_resp_wait_time : 2000;
2517 if (wait_time > max_wait_time)
2518 wait_time = max_wait_time;
2519 wait_time += 10; /* give the driver some extra time to complete */
2520 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2521 wpas_dpp_reconfig_reply_wait_timeout,
2522 wpa_s, NULL);
2523 wait_time -= 10;
2524
2525 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2526
2527 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2528 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2529 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2530 wpabuf_head(auth->reconfig_req_msg),
2531 wpabuf_len(auth->reconfig_req_msg),
2532 wait_time, wpas_dpp_tx_status, 0) < 0) {
2533 dpp_auth_deinit(wpa_s->dpp_auth);
2534 wpa_s->dpp_auth = NULL;
2535 }
2536}
2537
2538
2539static void
2540wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2541 const u8 *hdr, const u8 *buf, size_t len,
2542 unsigned int freq)
2543{
2544 struct wpa_ssid *ssid;
2545 struct dpp_authentication *auth;
2546
2547 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2548 MACSTR, MAC2STR(src));
2549
Hai Shalom899fcc72020-10-19 14:38:18 -07002550 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002551 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002552 if (wpa_s->dpp_auth) {
2553 wpa_printf(MSG_DEBUG,
2554 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2555 return;
2556 }
2557 if (!wpa_s->dpp_reconfig_ssid) {
2558 wpa_printf(MSG_DEBUG,
2559 "DPP: Not ready for reconfiguration - not requested");
2560 return;
2561 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002562 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2563 if (ssid == wpa_s->dpp_reconfig_ssid &&
2564 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2565 break;
2566 }
2567 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002568 !ssid->dpp_csign) {
2569 wpa_printf(MSG_DEBUG,
2570 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002571 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002572 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002573
2574 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2575 ssid->dpp_netaccesskey,
2576 ssid->dpp_netaccesskey_len,
2577 ssid->dpp_csign, ssid->dpp_csign_len,
2578 freq, hdr, buf, len);
2579 if (!auth)
2580 return;
2581 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2582 wpa_s->dpp_auth = auth;
2583
2584 wpas_dpp_chirp_stop(wpa_s);
2585
2586 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2587 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2588 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2589 wpabuf_head(auth->reconfig_resp_msg),
2590 wpabuf_len(auth->reconfig_resp_msg),
2591 500, wpas_dpp_tx_status, 0) < 0) {
2592 dpp_auth_deinit(wpa_s->dpp_auth);
2593 wpa_s->dpp_auth = NULL;
2594 }
2595}
2596
2597
2598static void
2599wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2600 const u8 *hdr, const u8 *buf, size_t len,
2601 unsigned int freq)
2602{
2603 struct dpp_authentication *auth = wpa_s->dpp_auth;
2604 struct wpabuf *conf;
2605
2606 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2607 MACSTR, MAC2STR(src));
2608
2609 if (!auth || !auth->reconfig || !auth->configurator) {
2610 wpa_printf(MSG_DEBUG,
2611 "DPP: No DPP Reconfig Authentication in progress - drop");
2612 return;
2613 }
2614
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002615 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002616 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2617 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2618 return;
2619 }
2620
2621 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2622 if (!conf)
2623 return;
2624
2625 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2626
2627 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2628 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2629 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2630 wpabuf_head(conf), wpabuf_len(conf),
2631 500, wpas_dpp_tx_status, 0) < 0) {
2632 wpabuf_free(conf);
2633 dpp_auth_deinit(wpa_s->dpp_auth);
2634 wpa_s->dpp_auth = NULL;
2635 return;
2636 }
2637 wpabuf_free(conf);
2638
2639 wpas_dpp_start_gas_server(wpa_s);
2640}
2641
2642
2643static void
2644wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2645 const u8 *hdr, const u8 *buf, size_t len,
2646 unsigned int freq)
2647{
2648 struct dpp_authentication *auth = wpa_s->dpp_auth;
2649
2650 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2651 MACSTR, MAC2STR(src));
2652
2653 if (!auth || !auth->reconfig || auth->configurator) {
2654 wpa_printf(MSG_DEBUG,
2655 "DPP: No DPP Reconfig Authentication in progress - drop");
2656 return;
2657 }
2658
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002659 if (!ether_addr_equal(src, auth->peer_mac_addr)) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002660 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2661 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2662 return;
2663 }
2664
2665 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2666 return;
2667
2668 wpas_dpp_start_gas_client(wpa_s);
2669}
2670
Hai Shalom021b0b52019-04-10 11:17:58 -07002671#endif /* CONFIG_DPP2 */
2672
2673
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002674static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2675 const u8 *src,
2676 const u8 *buf, size_t len)
2677{
2678 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002679 const u8 *connector, *trans_id, *status;
2680 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002681#ifdef CONFIG_DPP2
2682 const u8 *version;
2683 u16 version_len;
2684#endif /* CONFIG_DPP2 */
2685 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002686 struct dpp_introduction intro;
2687 struct rsn_pmksa_cache_entry *entry;
2688 struct os_time now;
2689 struct os_reltime rnow;
2690 os_time_t expiry;
2691 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002692 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002693
2694 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2695 MAC2STR(src));
2696 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002697 !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002698 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2699 MACSTR " - drop", MAC2STR(src));
2700 return;
2701 }
2702 offchannel_send_action_done(wpa_s);
2703
2704 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2705 if (ssid == wpa_s->dpp_intro_network)
2706 break;
2707 }
2708 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2709 !ssid->dpp_csign) {
2710 wpa_printf(MSG_DEBUG,
2711 "DPP: Profile not found for network introduction");
2712 return;
2713 }
2714
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002715 os_memset(&intro, 0, sizeof(intro));
2716
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002717 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2718 &trans_id_len);
2719 if (!trans_id || trans_id_len != 1) {
2720 wpa_printf(MSG_DEBUG,
2721 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002722 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2723 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002724 goto fail;
2725 }
2726 if (trans_id[0] != TRANSACTION_ID) {
2727 wpa_printf(MSG_DEBUG,
2728 "DPP: Ignore frame with unexpected Transaction ID %u",
2729 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002730 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2731 " fail=transaction_id_mismatch", MAC2STR(src));
2732 goto fail;
2733 }
2734
2735 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2736 if (!status || status_len != 1) {
2737 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2738 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2739 " fail=missing_status", MAC2STR(src));
2740 goto fail;
2741 }
2742 if (status[0] != DPP_STATUS_OK) {
2743 wpa_printf(MSG_DEBUG,
2744 "DPP: Peer rejected network introduction: Status %u",
2745 status[0]);
2746 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2747 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002748#ifdef CONFIG_DPP2
2749 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2750#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002751 goto fail;
2752 }
2753
2754 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2755 if (!connector) {
2756 wpa_printf(MSG_DEBUG,
2757 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002758 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2759 " fail=missing_connector", MAC2STR(src));
2760 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002761 }
2762
Roshan Pius3a1667e2018-07-03 15:17:14 -07002763 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2764 ssid->dpp_netaccesskey,
2765 ssid->dpp_netaccesskey_len,
2766 ssid->dpp_csign,
2767 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002768 connector, connector_len, &expiry, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002769 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002770 wpa_printf(MSG_INFO,
2771 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002772 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2773 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002774#ifdef CONFIG_DPP2
2775 wpas_dpp_send_conn_status_result(wpa_s, res);
2776#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002777 goto fail;
2778 }
2779
2780 entry = os_zalloc(sizeof(*entry));
2781 if (!entry)
2782 goto fail;
2783 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002784 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002785 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2786 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2787 entry->pmk_len = intro.pmk_len;
2788 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002789#ifdef CONFIG_DPP2
2790 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2791 &version_len);
2792 if (version && version_len >= 1)
2793 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002794#ifdef CONFIG_DPP3
2795 if (intro.peer_version && intro.peer_version >= 2 &&
2796 peer_version != intro.peer_version) {
2797 wpa_printf(MSG_INFO,
2798 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2799 intro.peer_version, peer_version);
2800 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2801 goto fail;
2802 }
2803#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002804 entry->dpp_pfs = peer_version >= 2;
2805#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002806 if (expiry) {
2807 os_get_time(&now);
2808 seconds = expiry - now.sec;
2809 } else {
2810 seconds = 86400 * 7;
2811 }
2812 os_get_reltime(&rnow);
2813 entry->expiration = rnow.sec + seconds;
2814 entry->reauth_time = rnow.sec + seconds;
2815 entry->network_ctx = ssid;
2816 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2817
Roshan Pius3a1667e2018-07-03 15:17:14 -07002818 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002819 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002820
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002821 wpa_printf(MSG_DEBUG,
2822 "DPP: Try connection again after successful network introduction");
2823 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2824 wpa_supplicant_cancel_sched_scan(wpa_s);
2825 wpa_supplicant_req_scan(wpa_s, 0, 0);
2826 }
2827fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002828 dpp_peer_intro_deinit(&intro);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002829}
2830
2831
Roshan Pius3a1667e2018-07-03 15:17:14 -07002832static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2833{
2834 int i, j;
2835
2836 if (!wpa_s->hw.modes)
2837 return -1;
2838
2839 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2840 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2841
2842 for (j = 0; j < mode->num_channels; j++) {
2843 struct hostapd_channel_data *chan = &mode->channels[j];
2844
2845 if (chan->freq != (int) freq)
2846 continue;
2847
2848 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2849 HOSTAPD_CHAN_NO_IR |
2850 HOSTAPD_CHAN_RADAR))
2851 continue;
2852
2853 return 1;
2854 }
2855 }
2856
2857 wpa_printf(MSG_DEBUG,
2858 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2859 freq);
2860
2861 return 0;
2862}
2863
2864
2865static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2866 struct dpp_pkex *pkex)
2867{
2868 if (pkex->freq == 2437)
2869 pkex->freq = 5745;
2870 else if (pkex->freq == 5745)
2871 pkex->freq = 5220;
2872 else if (pkex->freq == 5220)
2873 pkex->freq = 60480;
2874 else
2875 return -1; /* no more channels to try */
2876
2877 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2878 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2879 pkex->freq);
2880 return 0;
2881 }
2882
2883 /* Could not use this channel - try the next one */
2884 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2885}
2886
2887
Sunil Ravi89eba102022-09-13 21:04:37 -07002888static void wpas_dpp_pkex_clear_code(struct wpa_supplicant *wpa_s)
2889{
2890 if (!wpa_s->dpp_pkex_code && !wpa_s->dpp_pkex_identifier)
2891 return;
2892
2893 /* Delete PKEX code and identifier on successful completion of
2894 * PKEX. We are not supposed to reuse these without being
2895 * explicitly requested to perform PKEX again. */
2896 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
2897 os_free(wpa_s->dpp_pkex_code);
2898 wpa_s->dpp_pkex_code = NULL;
2899 os_free(wpa_s->dpp_pkex_identifier);
2900 wpa_s->dpp_pkex_identifier = NULL;
2901
2902}
2903
2904
Hai Shaloma20dcd72022-02-04 13:43:00 -08002905#ifdef CONFIG_DPP2
2906static int wpas_dpp_pkex_done(void *ctx, void *conn,
2907 struct dpp_bootstrap_info *peer_bi)
2908{
2909 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -07002910 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002911 const char *pos;
2912 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2913 struct dpp_bootstrap_info *own_bi = NULL;
2914 struct dpp_authentication *auth;
2915
Sunil Ravi89eba102022-09-13 21:04:37 -07002916 wpas_dpp_pkex_clear_code(wpa_s);
2917
2918 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
2919 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002920 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
2921 cmd);
2922
2923 pos = os_strstr(cmd, " own=");
2924 if (pos) {
2925 pos += 5;
2926 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
2927 if (!own_bi) {
2928 wpa_printf(MSG_INFO,
2929 "DPP: Could not find bootstrapping info for the identified local entry");
2930 return -1;
2931 }
2932
2933 if (peer_bi->curve != own_bi->curve) {
2934 wpa_printf(MSG_INFO,
2935 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
2936 peer_bi->curve->name, own_bi->curve->name);
2937 return -1;
2938 }
2939 }
2940
2941 pos = os_strstr(cmd, " role=");
2942 if (pos) {
2943 pos += 6;
2944 if (os_strncmp(pos, "configurator", 12) == 0)
2945 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2946 else if (os_strncmp(pos, "enrollee", 8) == 0)
2947 allowed_roles = DPP_CAPAB_ENROLLEE;
2948 else if (os_strncmp(pos, "either", 6) == 0)
2949 allowed_roles = DPP_CAPAB_CONFIGURATOR |
2950 DPP_CAPAB_ENROLLEE;
2951 else
2952 return -1;
2953 }
2954
2955 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
2956 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
2957 if (!auth)
2958 return -1;
2959
2960 wpas_dpp_set_testing_options(wpa_s, auth);
2961 if (dpp_set_configurator(auth, cmd) < 0) {
2962 dpp_auth_deinit(auth);
2963 return -1;
2964 }
2965
2966 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -07002967 DPP_NETROLE_STA,
2968 wpa_s->conf->dpp_mud_url,
2969 wpa_s->conf->dpp_extra_conf_req_name,
2970 wpa_s->conf->dpp_extra_conf_req_value,
2971 wpas_dpp_process_conf_obj,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002972 wpas_dpp_tcp_msg_sent);
2973}
2974#endif /* CONFIG_DPP2 */
2975
2976
Hai Shaloma20dcd72022-02-04 13:43:00 -08002977static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07002978 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002979 const struct hostapd_ip_addr *ipaddr,
2980 int tcp_port)
2981{
2982 struct dpp_pkex *pkex;
2983 struct wpabuf *msg;
2984 unsigned int wait_time;
2985 bool v2 = ver != PKEX_VER_ONLY_1;
2986
2987 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
2988 dpp_pkex_free(wpa_s->dpp_pkex);
2989 wpa_s->dpp_pkex = NULL;
2990 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
2991 wpa_s->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -07002992 wpa_s->dpp_pkex_code, wpa_s->dpp_pkex_code_len,
2993 v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002994 if (!pkex)
2995 return -1;
2996 pkex->forced_ver = ver != PKEX_VER_AUTO;
2997
2998 if (ipaddr) {
2999#ifdef CONFIG_DPP2
3000 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
3001 wpa_s, wpa_s, wpas_dpp_pkex_done);
3002#else /* CONFIG_DPP2 */
3003 return -1;
3004#endif /* CONFIG_DPP2 */
3005 }
3006
3007 wpa_s->dpp_pkex = pkex;
3008 msg = pkex->exchange_req;
3009 wait_time = wpa_s->max_remain_on_chan;
3010 if (wait_time > 2000)
3011 wait_time = 2000;
3012 pkex->freq = 2437;
3013 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3014 " freq=%u type=%d",
3015 MAC2STR(broadcast), pkex->freq,
3016 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3017 DPP_PA_PKEX_V1_EXCHANGE_REQ);
3018 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3019 wpa_s->own_addr, broadcast,
3020 wpabuf_head(msg), wpabuf_len(msg),
3021 wait_time, wpas_dpp_tx_pkex_status, 0);
3022 if (wait_time == 0)
3023 wait_time = 2000;
3024 pkex->exch_req_wait_time = wait_time;
3025 pkex->exch_req_tries = 1;
3026
3027 return 0;
3028}
3029
3030
Roshan Pius3a1667e2018-07-03 15:17:14 -07003031static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
3032{
3033 struct wpa_supplicant *wpa_s = eloop_ctx;
3034 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3035
3036 if (!pkex || !pkex->exchange_req)
3037 return;
3038 if (pkex->exch_req_tries >= 5) {
3039 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003040#ifdef CONFIG_DPP3
3041 if (pkex->v2 && !pkex->forced_ver) {
3042 wpa_printf(MSG_DEBUG,
3043 "DPP: Fall back to PKEXv1");
3044 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
3045 NULL, 0);
3046 return;
3047 }
3048#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003049 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
3050 "No response from PKEX peer");
3051 dpp_pkex_free(pkex);
3052 wpa_s->dpp_pkex = NULL;
3053 return;
3054 }
3055 pkex->exch_req_tries = 0;
3056 }
3057
3058 pkex->exch_req_tries++;
3059 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
3060 pkex->exch_req_tries);
3061 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08003062 MAC2STR(broadcast), pkex->freq,
3063 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3064 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003065 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3066 wpa_s->own_addr, broadcast,
3067 wpabuf_head(pkex->exchange_req),
3068 wpabuf_len(pkex->exchange_req),
3069 pkex->exch_req_wait_time,
3070 wpas_dpp_tx_pkex_status, 0);
3071}
3072
3073
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003074static void
3075wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
3076 unsigned int freq, const u8 *dst,
3077 const u8 *src, const u8 *bssid,
3078 const u8 *data, size_t data_len,
3079 enum offchannel_send_action_result result)
3080{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003081 const char *res_txt;
3082 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3083
3084 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3085 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3086 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003087 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3088 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003089 freq, MAC2STR(dst), res_txt);
3090 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3091 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3092
3093 if (!pkex) {
3094 wpa_printf(MSG_DEBUG,
3095 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
3096 return;
3097 }
3098
3099 if (pkex->failed) {
3100 wpa_printf(MSG_DEBUG,
3101 "DPP: Terminate PKEX exchange due to an earlier error");
3102 if (pkex->t > pkex->own_bi->pkex_t)
3103 pkex->own_bi->pkex_t = pkex->t;
3104 dpp_pkex_free(pkex);
3105 wpa_s->dpp_pkex = NULL;
3106 return;
3107 }
3108
3109 if (pkex->exch_req_wait_time && pkex->exchange_req) {
3110 /* Wait for PKEX Exchange Response frame and retry request if
3111 * no response is seen. */
3112 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3113 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
3114 (pkex->exch_req_wait_time % 1000) * 1000,
3115 wpas_dpp_pkex_retry_timeout, wpa_s,
3116 NULL);
3117 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003118}
3119
3120
3121static void
3122wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003123 const u8 *buf, size_t len, unsigned int freq,
3124 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003125{
3126 struct wpabuf *msg;
3127 unsigned int wait_time;
3128
3129 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
3130 MAC2STR(src));
3131
Sunil Ravia04bd252022-05-02 22:54:18 -07003132 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
3133 wpa_printf(MSG_DEBUG,
3134 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
3135 return;
3136 }
3137 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
3138 wpa_printf(MSG_DEBUG,
3139 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
3140 return;
3141 }
3142
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003143 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3144 * values here */
3145
3146 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
3147 wpa_printf(MSG_DEBUG,
3148 "DPP: No PKEX code configured - ignore request");
3149 return;
3150 }
3151
Sunil Ravi89eba102022-09-13 21:04:37 -07003152#ifdef CONFIG_DPP2
3153 if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) {
3154 wpa_printf(MSG_DEBUG,
3155 "DPP: PKEX Exchange Request is from local Controller - ignore request");
3156 return;
3157 }
3158#endif /* CONFIG_DPP2 */
3159
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003160 if (wpa_s->dpp_pkex) {
3161 /* TODO: Support parallel operations */
3162 wpa_printf(MSG_DEBUG,
3163 "DPP: Already in PKEX session - ignore new request");
3164 return;
3165 }
3166
Roshan Pius3a1667e2018-07-03 15:17:14 -07003167 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003168 wpa_s->own_addr, src,
3169 wpa_s->dpp_pkex_identifier,
3170 wpa_s->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07003171 wpa_s->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003172 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003173 if (!wpa_s->dpp_pkex) {
3174 wpa_printf(MSG_DEBUG,
3175 "DPP: Failed to process the request - ignore it");
3176 return;
3177 }
3178
Sunil Ravi89eba102022-09-13 21:04:37 -07003179#ifdef CONFIG_DPP3
3180 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_announcement) {
3181 wpa_printf(MSG_DEBUG,
3182 "DPP: Started PB PKEX (no more PB announcements)");
3183 wpabuf_free(wpa_s->dpp_pb_announcement);
3184 wpa_s->dpp_pb_announcement = NULL;
3185 }
3186#endif /* CONFIG_DPP3 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003187 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003188 msg = wpa_s->dpp_pkex->exchange_resp;
3189 wait_time = wpa_s->max_remain_on_chan;
3190 if (wait_time > 2000)
3191 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003192 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3193 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003194 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3195 broadcast,
3196 wpabuf_head(msg), wpabuf_len(msg),
3197 wait_time, wpas_dpp_tx_pkex_status, 0);
3198}
3199
3200
3201static void
3202wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3203 const u8 *buf, size_t len, unsigned int freq)
3204{
3205 struct wpabuf *msg;
3206 unsigned int wait_time;
3207
3208 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
3209 MAC2STR(src));
3210
3211 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3212 * values here */
3213
3214 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3215 wpa_s->dpp_pkex->exchange_done) {
3216 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3217 return;
3218 }
3219
Roshan Pius3a1667e2018-07-03 15:17:14 -07003220 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3221 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3222
3223 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003224 if (!msg) {
3225 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3226 return;
3227 }
3228
3229 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3230 MAC2STR(src));
3231
3232 wait_time = wpa_s->max_remain_on_chan;
3233 if (wait_time > 2000)
3234 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003235 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3236 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003237 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3238 broadcast,
3239 wpabuf_head(msg), wpabuf_len(msg),
3240 wait_time, wpas_dpp_tx_pkex_status, 0);
3241 wpabuf_free(msg);
3242}
3243
3244
Roshan Pius3a1667e2018-07-03 15:17:14 -07003245static struct dpp_bootstrap_info *
3246wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3247 unsigned int freq)
3248{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003249 struct dpp_bootstrap_info *bi;
3250
Sunil Ravi89eba102022-09-13 21:04:37 -07003251 wpas_dpp_pkex_clear_code(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003252 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003253 if (!bi)
3254 return NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003255
Roshan Pius3a1667e2018-07-03 15:17:14 -07003256 wpa_s->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003257
3258#ifdef CONFIG_DPP3
3259 if (wpa_s->dpp_pb_bi && !wpa_s->dpp_pb_configurator &&
3260 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_init_hash,
3261 SHA256_MAC_LEN) != 0) {
3262 char id[20];
3263
3264 wpa_printf(MSG_INFO,
3265 "DPP: Peer bootstrap key from PKEX does not match PB announcement response hash");
3266 wpa_hexdump(MSG_DEBUG,
3267 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3268 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3269 wpa_hexdump(MSG_DEBUG,
3270 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement response",
3271 wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN);
3272
3273 os_snprintf(id, sizeof(id), "%u", bi->id);
3274 dpp_bootstrap_remove(wpa_s->dpp, id);
3275 wpas_dpp_push_button_stop(wpa_s);
3276 return NULL;
3277 }
3278#endif /* CONFIG_DPP3 */
3279
Roshan Pius3a1667e2018-07-03 15:17:14 -07003280 return bi;
3281}
3282
3283
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003284static void
3285wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3286 const u8 *hdr, const u8 *buf, size_t len,
3287 unsigned int freq)
3288{
3289 struct wpabuf *msg;
3290 unsigned int wait_time;
3291 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003292
3293 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3294 MAC2STR(src));
3295
3296 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3297 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3298 return;
3299 }
3300
3301 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3302 if (!msg) {
3303 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003304 if (pkex->failed) {
3305 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3306 if (pkex->t > pkex->own_bi->pkex_t)
3307 pkex->own_bi->pkex_t = pkex->t;
3308 dpp_pkex_free(wpa_s->dpp_pkex);
3309 wpa_s->dpp_pkex = NULL;
3310 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003311 return;
3312 }
3313
3314 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3315 MACSTR, MAC2STR(src));
3316
3317 wait_time = wpa_s->max_remain_on_chan;
3318 if (wait_time > 2000)
3319 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003320 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3321 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003322 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3323 broadcast,
3324 wpabuf_head(msg), wpabuf_len(msg),
3325 wait_time, wpas_dpp_tx_pkex_status, 0);
3326 wpabuf_free(msg);
3327
Roshan Pius3a1667e2018-07-03 15:17:14 -07003328 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003329 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003330}
3331
3332
3333static void
3334wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3335 const u8 *hdr, const u8 *buf, size_t len,
3336 unsigned int freq)
3337{
3338 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003339 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003340 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3341 char cmd[500];
3342
3343 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3344 MAC2STR(src));
3345
3346 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3347 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3348 return;
3349 }
3350
3351 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3352 if (res < 0) {
3353 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3354 return;
3355 }
3356
Roshan Pius3a1667e2018-07-03 15:17:14 -07003357 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003358 if (!bi)
3359 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003360
Sunil Ravi89eba102022-09-13 21:04:37 -07003361#ifdef CONFIG_DPP3
3362 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_configurator &&
3363 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_resp_hash,
3364 SHA256_MAC_LEN) != 0) {
3365 char id[20];
3366
3367 wpa_printf(MSG_INFO,
3368 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
3369 wpa_hexdump(MSG_DEBUG,
3370 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3371 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3372 wpa_hexdump(MSG_DEBUG,
3373 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
3374 wpa_s->dpp_pb_resp_hash, SHA256_MAC_LEN);
3375
3376 os_snprintf(id, sizeof(id), "%u", bi->id);
3377 dpp_bootstrap_remove(wpa_s->dpp, id);
3378 wpas_dpp_push_button_stop(wpa_s);
3379 return;
3380 }
3381#endif /* CONFIG_DPP3 */
3382
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003383 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3384 bi->id,
3385 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3386 wpa_printf(MSG_DEBUG,
3387 "DPP: Start authentication after PKEX with parameters: %s",
3388 cmd);
3389 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3390 wpa_printf(MSG_DEBUG,
3391 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003392 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003393 return;
3394 }
3395}
3396
3397
Sunil Ravi89eba102022-09-13 21:04:37 -07003398#ifdef CONFIG_DPP3
3399
3400static void wpas_dpp_pb_pkex_init(struct wpa_supplicant *wpa_s,
3401 unsigned int freq, const u8 *src,
3402 const u8 *r_hash)
3403{
3404 struct dpp_pkex *pkex;
3405 struct wpabuf *msg;
3406 unsigned int wait_time;
3407 size_t len;
3408
3409 if (wpa_s->dpp_pkex) {
3410 wpa_printf(MSG_DEBUG,
3411 "DPP: Sending previously generated PKEX Exchange Request to "
3412 MACSTR, MAC2STR(src));
3413 msg = wpa_s->dpp_pkex->exchange_req;
3414 wait_time = wpa_s->max_remain_on_chan;
3415 if (wait_time > 2000)
3416 wait_time = 2000;
3417 offchannel_send_action(wpa_s, freq, src,
3418 wpa_s->own_addr, broadcast,
3419 wpabuf_head(msg), wpabuf_len(msg),
3420 wait_time, wpas_dpp_tx_pkex_status, 0);
3421 return;
3422 }
3423
3424 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
3425 MACSTR, MAC2STR(src));
3426
3427 if (!wpa_s->dpp_pb_cmd) {
3428 wpa_printf(MSG_INFO,
3429 "DPP: No configuration to provision as push button Configurator");
3430 wpas_dpp_push_button_stop(wpa_s);
3431 return;
3432 }
3433
3434 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
3435 os_memcpy(wpa_s->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
3436
3437 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3438 "PBPKEX", (const char *) wpa_s->dpp_pb_c_nonce,
3439 wpa_s->dpp_pb_bi->curve->nonce_len,
3440 true);
3441 if (!pkex) {
3442 wpas_dpp_push_button_stop(wpa_s);
3443 return;
3444 }
3445 pkex->freq = freq;
3446
3447 wpa_s->dpp_pkex = pkex;
3448 msg = wpa_s->dpp_pkex->exchange_req;
3449 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3450 " freq=%u type=%d", MAC2STR(src), freq,
3451 DPP_PA_PKEX_EXCHANGE_REQ);
3452 wait_time = wpa_s->max_remain_on_chan;
3453 if (wait_time > 2000)
3454 wait_time = 2000;
3455 offchannel_send_action(wpa_s, pkex->freq, src,
3456 wpa_s->own_addr, broadcast,
3457 wpabuf_head(msg), wpabuf_len(msg),
3458 wait_time, wpas_dpp_tx_pkex_status, 0);
3459 pkex->exch_req_wait_time = 2000;
3460 pkex->exch_req_tries = 1;
3461
3462 /* Use the externally provided configuration */
3463 os_free(wpa_s->dpp_pkex_auth_cmd);
3464 len = 30 + os_strlen(wpa_s->dpp_pb_cmd);
3465 wpa_s->dpp_pkex_auth_cmd = os_malloc(len);
3466 if (wpa_s->dpp_pkex_auth_cmd)
3467 os_snprintf(wpa_s->dpp_pkex_auth_cmd, len, " own=%d %s",
3468 wpa_s->dpp_pkex_bi->id, wpa_s->dpp_pb_cmd);
3469 else
3470 wpas_dpp_push_button_stop(wpa_s);
3471}
3472
3473
3474static void
3475wpas_dpp_rx_pb_presence_announcement(struct wpa_supplicant *wpa_s,
3476 const u8 *src, const u8 *hdr,
3477 const u8 *buf, size_t len,
3478 unsigned int freq)
3479{
3480 const u8 *r_hash;
3481 u16 r_hash_len;
3482 unsigned int i;
3483 bool found = false;
3484 struct dpp_pb_info *info, *tmp;
3485 struct os_reltime now, age;
3486 struct wpabuf *msg;
3487
3488 os_get_reltime(&now);
3489 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
3490 MACSTR, MAC2STR(src));
3491
3492 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3493 &r_hash_len);
3494 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
3495 wpa_printf(MSG_DEBUG,
3496 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
3497 return;
3498 }
3499 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3500 r_hash, r_hash_len);
3501
3502 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3503 info = &wpa_s->dpp_pb[i];
3504 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
3505 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
3506 continue;
3507 wpa_printf(MSG_DEBUG,
3508 "DPP: Active push button Enrollee already known");
3509 found = true;
3510 info->rx_time = now;
3511 }
3512
3513 if (!found) {
3514 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3515 tmp = &wpa_s->dpp_pb[i];
3516 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
3517 continue;
3518
3519 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
3520 wpa_hexdump(MSG_DEBUG,
3521 "DPP: Push button Enrollee hash expired",
3522 tmp->hash, SHA256_MAC_LEN);
3523 tmp->rx_time.sec = 0;
3524 tmp->rx_time.usec = 0;
3525 continue;
3526 }
3527
3528 wpa_hexdump(MSG_DEBUG,
3529 "DPP: Push button session overlap with hash",
3530 tmp->hash, SHA256_MAC_LEN);
3531 if (!wpa_s->dpp_pb_result_indicated &&
3532 wpas_dpp_pb_active(wpa_s)) {
3533 wpa_msg(wpa_s, MSG_INFO,
3534 DPP_EVENT_PB_RESULT "session-overlap");
3535 wpa_s->dpp_pb_result_indicated = true;
3536 }
3537 wpas_dpp_push_button_stop(wpa_s);
3538 return;
3539 }
3540
3541 /* Replace the oldest entry */
3542 info = &wpa_s->dpp_pb[0];
3543 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
3544 tmp = &wpa_s->dpp_pb[i];
3545 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
3546 info = tmp;
3547 }
3548 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
3549 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
3550 info->rx_time = now;
3551 }
3552
3553 if (!wpas_dpp_pb_active(wpa_s)) {
3554 wpa_printf(MSG_DEBUG,
3555 "DPP: Discard message since own push button has not been pressed");
3556 return;
3557 }
3558
3559 if (wpa_s->dpp_pb_announce_time.sec == 0 &&
3560 wpa_s->dpp_pb_announce_time.usec == 0) {
3561 /* Start a wait before allowing PKEX to be initiated */
3562 wpa_s->dpp_pb_announce_time = now;
3563 }
3564
3565 if (!wpa_s->dpp_pb_bi) {
3566 int res;
3567
3568 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
3569 if (res < 0)
3570 return;
3571 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
3572 if (!wpa_s->dpp_pb_bi)
3573 return;
3574
3575 if (random_get_bytes(wpa_s->dpp_pb_c_nonce,
3576 wpa_s->dpp_pb_bi->curve->nonce_len)) {
3577 wpa_printf(MSG_ERROR,
3578 "DPP: Failed to generate C-nonce");
3579 wpas_dpp_push_button_stop(wpa_s);
3580 return;
3581 }
3582 }
3583
3584 /* Skip the response if one was sent within last 50 ms since the
3585 * Enrollee is going to send out at least three announcement messages.
3586 */
3587 os_reltime_sub(&now, &wpa_s->dpp_pb_last_resp, &age);
3588 if (age.sec == 0 && age.usec < 50000) {
3589 wpa_printf(MSG_DEBUG,
3590 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
3591 return;
3592 }
3593
3594 msg = dpp_build_pb_announcement_resp(
3595 wpa_s->dpp_pb_bi, r_hash, wpa_s->dpp_pb_c_nonce,
3596 wpa_s->dpp_pb_bi->curve->nonce_len);
3597 if (!msg) {
3598 wpas_dpp_push_button_stop(wpa_s);
3599 return;
3600 }
3601
3602 wpa_printf(MSG_DEBUG,
3603 "DPP: Send Push Button Presence Announcement Response to "
3604 MACSTR, MAC2STR(src));
3605 wpa_s->dpp_pb_last_resp = now;
3606
3607 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3608 MAC2STR(src), freq, DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
3609 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
3610 wpabuf_head(msg), wpabuf_len(msg),
3611 0, NULL, 0);
3612 wpabuf_free(msg);
3613
3614 if (os_reltime_expired(&now, &wpa_s->dpp_pb_announce_time, 15))
3615 wpas_dpp_pb_pkex_init(wpa_s, freq, src, r_hash);
3616}
3617
3618
3619static void
3620wpas_dpp_rx_pb_presence_announcement_resp(struct wpa_supplicant *wpa_s,
3621 const u8 *src, const u8 *hdr,
3622 const u8 *buf, size_t len,
3623 unsigned int freq)
3624{
3625 const u8 *i_hash, *r_hash, *c_nonce;
3626 u16 i_hash_len, r_hash_len, c_nonce_len;
3627 bool overlap = false;
3628
3629 if (!wpa_s->dpp_pb_announcement || !wpa_s->dpp_pb_bi ||
3630 wpa_s->dpp_pb_configurator) {
3631 wpa_printf(MSG_INFO,
3632 "DPP: Not in active push button Enrollee mode - discard Push Button Presence Announcement Response from "
3633 MACSTR, MAC2STR(src));
3634 return;
3635 }
3636
3637 wpa_printf(MSG_DEBUG,
3638 "DPP: Push Button Presence Announcement Response from "
3639 MACSTR, MAC2STR(src));
3640
3641 i_hash = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3642 &i_hash_len);
3643 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3644 &r_hash_len);
3645 c_nonce = dpp_get_attr(buf, len, DPP_ATTR_CONFIGURATOR_NONCE,
3646 &c_nonce_len);
3647 if (!i_hash || i_hash_len != SHA256_MAC_LEN ||
3648 !r_hash || r_hash_len != SHA256_MAC_LEN ||
3649 !c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
3650 wpa_printf(MSG_DEBUG,
3651 "DPP: Missing or invalid required attribute");
3652 return;
3653 }
3654 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
3655 i_hash, i_hash_len);
3656 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3657 r_hash, r_hash_len);
3658 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator Nonce",
3659 c_nonce, c_nonce_len);
3660
3661#ifdef CONFIG_TESTING_OPTIONS
3662 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ &&
3663 os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3664 SHA256_MAC_LEN - 1) == 0)
3665 goto skip_hash_check;
3666#endif /* CONFIG_TESTING_OPTIONS */
3667 if (os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3668 SHA256_MAC_LEN) != 0) {
3669 wpa_printf(MSG_INFO,
3670 "DPP: Unexpected push button Responder hash - abort");
3671 overlap = true;
3672 }
3673#ifdef CONFIG_TESTING_OPTIONS
3674skip_hash_check:
3675#endif /* CONFIG_TESTING_OPTIONS */
3676
3677 if (wpa_s->dpp_pb_resp_freq &&
3678 os_memcmp(i_hash, wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN) != 0) {
3679 wpa_printf(MSG_INFO,
3680 "DPP: Push button session overlap detected - abort");
3681 overlap = true;
3682 }
3683
3684 if (overlap) {
3685 if (!wpa_s->dpp_pb_result_indicated) {
3686 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
3687 "session-overlap");
3688 wpa_s->dpp_pb_result_indicated = true;
3689 }
3690 wpas_dpp_push_button_stop(wpa_s);
3691 return;
3692 }
3693
3694 if (!wpa_s->dpp_pb_resp_freq) {
3695 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
3696 "discovered push button AP/Configurator " MACSTR,
3697 MAC2STR(src));
3698 wpa_s->dpp_pb_resp_freq = freq;
3699 os_memcpy(wpa_s->dpp_pb_init_hash, i_hash, SHA256_MAC_LEN);
3700 os_memcpy(wpa_s->dpp_pb_c_nonce, c_nonce, c_nonce_len);
3701 wpa_s->dpp_pb_c_nonce_len = c_nonce_len;
3702 /* Stop announcement iterations after at least one more full
3703 * round and one extra round for postponed session overlap
3704 * detection. */
3705 wpa_s->dpp_pb_stop_iter = 3;
3706 }
3707}
3708
3709
3710static void
3711wpas_dpp_tx_priv_intro_status(struct wpa_supplicant *wpa_s,
3712 unsigned int freq, const u8 *dst,
3713 const u8 *src, const u8 *bssid,
3714 const u8 *data, size_t data_len,
3715 enum offchannel_send_action_result result)
3716{
3717 const char *res_txt;
3718
3719 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3720 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3721 "FAILED");
3722 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3723 " result=%s (DPP Private Peer Introduction Update)",
3724 freq, MAC2STR(dst), res_txt);
3725 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3726 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3727
3728 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR " version=%u",
3729 MAC2STR(src), wpa_s->dpp_intro_peer_version);
3730
3731 wpa_printf(MSG_DEBUG,
3732 "DPP: Try connection again after successful network introduction");
3733 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3734 wpa_supplicant_cancel_sched_scan(wpa_s);
3735 wpa_supplicant_req_scan(wpa_s, 0, 0);
3736 }
3737}
3738
3739
3740static int
3741wpas_dpp_send_private_peer_intro_update(struct wpa_supplicant *wpa_s,
3742 struct dpp_introduction *intro,
3743 struct wpa_ssid *ssid,
3744 const u8 *dst, unsigned int freq)
3745{
3746 struct wpabuf *pt, *msg, *enc_ct;
3747 size_t len;
3748 u8 ver = DPP_VERSION;
3749 int conn_ver;
3750 const u8 *aad;
3751 size_t aad_len;
3752 unsigned int wait_time;
3753
3754 wpa_printf(MSG_DEBUG, "HPKE(kem_id=%u kdf_id=%u aead_id=%u)",
3755 intro->kem_id, intro->kdf_id, intro->aead_id);
3756
3757 /* Plaintext for HPKE */
3758 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3759 pt = wpabuf_alloc(len);
3760 if (!pt)
3761 return -1;
3762
3763 /* Protocol Version */
3764 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3765 if (conn_ver > 0 && ver != conn_ver) {
3766 wpa_printf(MSG_DEBUG,
3767 "DPP: Use Connector version %d instead of current protocol version %d",
3768 conn_ver, ver);
3769 ver = conn_ver;
3770 }
3771 wpabuf_put_le16(pt, DPP_ATTR_PROTOCOL_VERSION);
3772 wpabuf_put_le16(pt, 1);
3773 wpabuf_put_u8(pt, ver);
3774
3775 /* Connector */
3776 wpabuf_put_le16(pt, DPP_ATTR_CONNECTOR);
3777 wpabuf_put_le16(pt, os_strlen(ssid->dpp_connector));
3778 wpabuf_put_str(pt, ssid->dpp_connector);
3779 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Plaintext for HPKE", pt);
3780
3781 /* HPKE(pt) using AP's public key (from its Connector) */
3782 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, 0);
3783 if (!msg) {
3784 wpabuf_free(pt);
3785 return -1;
3786 }
3787 aad = wpabuf_head_u8(msg) + 2; /* from the OUI field (inclusive) */
3788 aad_len = DPP_HDR_LEN; /* to the DPP Frame Type field (inclusive) */
3789 wpa_hexdump(MSG_MSGDUMP, "DPP: AAD for HPKE", aad, aad_len);
3790
3791 enc_ct = hpke_base_seal(intro->kem_id, intro->kdf_id, intro->aead_id,
3792 intro->peer_key, NULL, 0, aad, aad_len,
3793 wpabuf_head(pt), wpabuf_len(pt));
3794 wpabuf_free(pt);
3795 wpabuf_free(msg);
3796 if (!enc_ct) {
3797 wpa_printf(MSG_INFO, "DPP: HPKE Seal(Connector) failed");
3798 return -1;
3799 }
3800 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE enc|ct", enc_ct);
3801
3802 /* HPKE(pt) to generate payload for Wrapped Data */
3803 len = 5 + 4 + wpabuf_len(enc_ct);
3804 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, len);
3805 if (!msg) {
3806 wpabuf_free(enc_ct);
3807 return -1;
3808 }
3809
3810 /* Transaction ID */
3811 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3812 wpabuf_put_le16(msg, 1);
3813 wpabuf_put_u8(msg, TRANSACTION_ID);
3814
3815 /* Wrapped Data */
3816 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3817 wpabuf_put_le16(msg, wpabuf_len(enc_ct));
3818 wpabuf_put_buf(msg, enc_ct);
3819 wpabuf_free(enc_ct);
3820
3821 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Update", msg);
3822
3823 /* TODO: Timeout on AP response */
3824 wait_time = wpa_s->max_remain_on_chan;
3825 if (wait_time > 2000)
3826 wait_time = 2000;
3827 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3828 MAC2STR(dst), freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
3829 offchannel_send_action(wpa_s, freq, dst, wpa_s->own_addr, broadcast,
3830 wpabuf_head(msg), wpabuf_len(msg),
3831 wait_time, wpas_dpp_tx_priv_intro_status, 0);
3832 wpabuf_free(msg);
3833
3834 return 0;
3835}
3836
3837
3838static void
3839wpas_dpp_rx_priv_peer_intro_notify(struct wpa_supplicant *wpa_s,
3840 const u8 *src, const u8 *hdr,
3841 const u8 *buf, size_t len,
3842 unsigned int freq)
3843{
3844 struct wpa_ssid *ssid;
3845 const u8 *connector, *trans_id, *version;
3846 u16 connector_len, trans_id_len, version_len;
3847 u8 peer_version = 1;
3848 struct dpp_introduction intro;
3849 struct rsn_pmksa_cache_entry *entry;
3850 struct os_time now;
3851 struct os_reltime rnow;
3852 os_time_t expiry;
3853 unsigned int seconds;
3854 enum dpp_status_error res;
3855
3856 os_memset(&intro, 0, sizeof(intro));
3857
3858 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
3859 MACSTR, MAC2STR(src));
3860 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003861 !ether_addr_equal(src, wpa_s->dpp_intro_bssid)) {
Sunil Ravi89eba102022-09-13 21:04:37 -07003862 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
3863 MACSTR " - drop", MAC2STR(src));
3864 return;
3865 }
3866 offchannel_send_action_done(wpa_s);
3867
3868 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3869 if (ssid == wpa_s->dpp_intro_network)
3870 break;
3871 }
3872 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3873 !ssid->dpp_csign) {
3874 wpa_printf(MSG_DEBUG,
3875 "DPP: Profile not found for network introduction");
3876 return;
3877 }
3878
3879 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
3880 &trans_id_len);
3881 if (!trans_id || trans_id_len != 1) {
3882 wpa_printf(MSG_DEBUG,
3883 "DPP: Peer did not include Transaction ID");
3884 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3885 " fail=missing_transaction_id", MAC2STR(src));
3886 goto fail;
3887 }
3888 if (trans_id[0] != TRANSACTION_ID) {
3889 wpa_printf(MSG_DEBUG,
3890 "DPP: Ignore frame with unexpected Transaction ID %u",
3891 trans_id[0]);
3892 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3893 " fail=transaction_id_mismatch", MAC2STR(src));
3894 goto fail;
3895 }
3896
3897 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
3898 if (!connector) {
3899 wpa_printf(MSG_DEBUG,
3900 "DPP: Peer did not include its Connector");
3901 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3902 " fail=missing_connector", MAC2STR(src));
3903 goto fail;
3904 }
3905
3906 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
3907 &version_len);
3908 if (!version || version_len < 1) {
3909 wpa_printf(MSG_DEBUG,
3910 "DPP: Peer did not include valid Version");
3911 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3912 " fail=missing_version", MAC2STR(src));
3913 goto fail;
3914 }
3915
3916 res = dpp_peer_intro(&intro, ssid->dpp_connector,
3917 ssid->dpp_netaccesskey,
3918 ssid->dpp_netaccesskey_len,
3919 ssid->dpp_csign,
3920 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003921 connector, connector_len, &expiry, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07003922 if (res != DPP_STATUS_OK) {
3923 wpa_printf(MSG_INFO,
3924 "DPP: Network Introduction protocol resulted in failure");
3925 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3926 " fail=peer_connector_validation_failed", MAC2STR(src));
3927 wpas_dpp_send_conn_status_result(wpa_s, res);
3928 goto fail;
3929 }
3930
3931 peer_version = version[0];
3932 if (intro.peer_version && intro.peer_version >= 2 &&
3933 peer_version != intro.peer_version) {
3934 wpa_printf(MSG_INFO,
3935 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
3936 intro.peer_version, peer_version);
3937 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
3938 goto fail;
3939 }
3940 wpa_s->dpp_intro_peer_version = peer_version;
3941
3942 entry = os_zalloc(sizeof(*entry));
3943 if (!entry)
3944 goto fail;
3945 entry->dpp_pfs = peer_version >= 2;
3946 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003947 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Sunil Ravi89eba102022-09-13 21:04:37 -07003948 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
3949 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
3950 entry->pmk_len = intro.pmk_len;
3951 entry->akmp = WPA_KEY_MGMT_DPP;
3952 if (expiry) {
3953 os_get_time(&now);
3954 seconds = expiry - now.sec;
3955 } else {
3956 seconds = 86400 * 7;
3957 }
3958
3959 if (wpas_dpp_send_private_peer_intro_update(wpa_s, &intro, ssid, src,
3960 freq) < 0) {
3961 os_free(entry);
3962 goto fail;
3963 }
3964
3965 os_get_reltime(&rnow);
3966 entry->expiration = rnow.sec + seconds;
3967 entry->reauth_time = rnow.sec + seconds;
3968 entry->network_ctx = ssid;
3969 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
3970
3971 /* Association will be initiated from TX status handler for the Private
3972 * Peer Intro Update: wpas_dpp_tx_priv_intro_status() */
3973
3974fail:
3975 dpp_peer_intro_deinit(&intro);
3976}
3977
3978#endif /* CONFIG_DPP3 */
3979
3980
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003981void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
3982 const u8 *buf, size_t len, unsigned int freq)
3983{
3984 u8 crypto_suite;
3985 enum dpp_public_action_frame_type type;
3986 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003987 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003988
3989 if (len < DPP_HDR_LEN)
3990 return;
3991 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
3992 return;
3993 hdr = buf;
3994 buf += 4;
3995 len -= 4;
3996 crypto_suite = *buf++;
3997 type = *buf++;
3998 len -= 2;
3999
4000 wpa_printf(MSG_DEBUG,
4001 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
4002 MACSTR " freq=%u",
4003 crypto_suite, type, MAC2STR(src), freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07004004#ifdef CONFIG_TESTING_OPTIONS
4005 if (wpa_s->dpp_discard_public_action &&
4006 type != DPP_PA_PEER_DISCOVERY_RESP &&
4007 type != DPP_PA_PRIV_PEER_INTRO_NOTIFY) {
4008 wpa_printf(MSG_DEBUG,
4009 "TESTING: Discard received DPP Public Action frame");
4010 return;
4011 }
4012#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004013 if (crypto_suite != 1) {
4014 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
4015 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004016 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4017 " freq=%u type=%d ignore=unsupported-crypto-suite",
4018 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004019 return;
4020 }
4021 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004022 if (dpp_check_attrs(buf, len) < 0) {
4023 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4024 " freq=%u type=%d ignore=invalid-attributes",
4025 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004026 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004027 }
4028 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
4029 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004030
4031 switch (type) {
4032 case DPP_PA_AUTHENTICATION_REQ:
4033 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
4034 break;
4035 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07004036 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004037 break;
4038 case DPP_PA_AUTHENTICATION_CONF:
4039 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
4040 break;
4041 case DPP_PA_PEER_DISCOVERY_RESP:
4042 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
4043 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004044#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004045 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004046 /* This is for PKEXv2, but for now, process only with
4047 * CONFIG_DPP3 to avoid issues with a capability that has not
4048 * been tested with other implementations. */
4049 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
4050 break;
4051#endif /* CONFIG_DPP3 */
4052 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
4053 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
4054 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004055 break;
4056 case DPP_PA_PKEX_EXCHANGE_RESP:
4057 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
4058 break;
4059 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
4060 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
4061 freq);
4062 break;
4063 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
4064 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
4065 freq);
4066 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004067#ifdef CONFIG_DPP2
4068 case DPP_PA_CONFIGURATION_RESULT:
4069 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
4070 break;
Hai Shalomc3565922019-10-28 11:58:20 -07004071 case DPP_PA_CONNECTION_STATUS_RESULT:
4072 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
4073 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07004074 case DPP_PA_PRESENCE_ANNOUNCEMENT:
4075 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
4076 freq);
4077 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004078 case DPP_PA_RECONFIG_ANNOUNCEMENT:
4079 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
4080 freq);
4081 break;
4082 case DPP_PA_RECONFIG_AUTH_REQ:
4083 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
4084 break;
4085 case DPP_PA_RECONFIG_AUTH_RESP:
4086 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
4087 break;
4088 case DPP_PA_RECONFIG_AUTH_CONF:
4089 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
4090 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004091#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07004092#ifdef CONFIG_DPP3
4093 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
4094 wpas_dpp_rx_pb_presence_announcement(wpa_s, src, hdr,
4095 buf, len, freq);
4096 break;
4097 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP:
4098 wpas_dpp_rx_pb_presence_announcement_resp(wpa_s, src, hdr,
4099 buf, len, freq);
4100 break;
4101 case DPP_PA_PRIV_PEER_INTRO_NOTIFY:
4102 wpas_dpp_rx_priv_peer_intro_notify(wpa_s, src, hdr,
4103 buf, len, freq);
4104 break;
4105#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004106 default:
4107 wpa_printf(MSG_DEBUG,
4108 "DPP: Ignored unsupported frame subtype %d", type);
4109 break;
4110 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004111
4112 if (wpa_s->dpp_pkex)
4113 pkex_t = wpa_s->dpp_pkex->t;
4114 else if (wpa_s->dpp_pkex_bi)
4115 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
4116 else
4117 pkex_t = 0;
4118 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
4119 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
4120 wpas_dpp_pkex_remove(wpa_s, "*");
4121 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004122}
4123
4124
Hai Shaloma20dcd72022-02-04 13:43:00 -08004125static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
4126 void *timeout_ctx)
4127{
4128 struct wpa_supplicant *wpa_s = eloop_ctx;
4129 struct dpp_authentication *auth = wpa_s->dpp_auth;
4130
4131 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
4132 return;
4133
4134 wpa_printf(MSG_DEBUG,
4135 "DPP: No configuration available from upper layers - send initial response with comeback delay");
4136 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
4137 500);
4138}
4139
4140
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004141static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07004142wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08004143 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004144{
4145 struct wpa_supplicant *wpa_s = ctx;
4146 struct dpp_authentication *auth = wpa_s->dpp_auth;
4147 struct wpabuf *resp;
4148
4149 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
4150 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004151 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004152 !ether_addr_equal(sa, auth->peer_mac_addr)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004153 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
4154 return NULL;
4155 }
Hai Shalomc3565922019-10-28 11:58:20 -07004156
4157 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
4158 wpa_printf(MSG_DEBUG,
4159 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
4160 /* wpas_dpp_auth_success() would normally have been called from
4161 * TX status handler, but since there was no such handler call
4162 * yet, simply send out the event message and proceed with
4163 * exchange. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004164 dpp_notify_auth_success(auth, 1);
Hai Shalomc3565922019-10-28 11:58:20 -07004165 wpa_s->dpp_auth_ok_on_ack = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004166#ifdef CONFIG_TESTING_OPTIONS
4167 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
4168 wpa_printf(MSG_INFO,
4169 "DPP: TESTING - stop at Authentication Confirm");
4170 return NULL;
4171 }
4172#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07004173 }
4174
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004175 wpa_hexdump(MSG_DEBUG,
4176 "DPP: Received Configuration Request (GAS Query Request)",
4177 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004178 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
4179 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004180 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004181
Hai Shaloma20dcd72022-02-04 13:43:00 -08004182 auth->gas_server_ctx = resp_ctx;
4183
Hai Shalom899fcc72020-10-19 14:38:18 -07004184#ifdef CONFIG_DPP2
4185 if (!resp && auth->waiting_cert) {
4186 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08004187 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07004188 *comeback_delay = 500;
4189 return NULL;
4190 }
4191#endif /* CONFIG_DPP2 */
4192
Hai Shaloma20dcd72022-02-04 13:43:00 -08004193 if (!resp && auth->waiting_config &&
4194 (auth->peer_bi || auth->tmp_peer_bi)) {
4195 char *buf = NULL, *name = "";
4196 char band[200], *pos, *end;
4197 int i, res, *opclass = auth->e_band_support;
4198 char *mud_url = "N/A";
4199
4200 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
4201 auth->config_resp_ctx = resp_ctx;
4202 *comeback_delay = -1;
4203 if (auth->e_name) {
4204 size_t len = os_strlen(auth->e_name);
4205
4206 buf = os_malloc(len * 4 + 1);
4207 if (buf) {
4208 printf_encode(buf, len * 4 + 1,
4209 (const u8 *) auth->e_name, len);
4210 name = buf;
4211 }
4212 }
4213 band[0] = '\0';
4214 pos = band;
4215 end = band + sizeof(band);
4216 for (i = 0; opclass && opclass[i]; i++) {
4217 res = os_snprintf(pos, end - pos, "%s%d",
4218 pos == band ? "" : ",", opclass[i]);
4219 if (os_snprintf_error(end - pos, res)) {
4220 *pos = '\0';
4221 break;
4222 }
4223 pos += res;
4224 }
4225 if (auth->e_mud_url) {
4226 size_t len = os_strlen(auth->e_mud_url);
4227
4228 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
4229 mud_url = auth->e_mud_url;
4230 }
4231 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
4232 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
4233 auth->peer_bi ? auth->peer_bi->id :
4234 auth->tmp_peer_bi->id, MAC2STR(sa),
4235 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
4236 os_free(buf);
4237
4238 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4239 NULL);
4240 eloop_register_timeout(0, 50000,
4241 wpas_dpp_gas_initial_resp_timeout, wpa_s,
4242 NULL);
4243 return NULL;
4244 }
4245
Sunil Ravia04bd252022-05-02 22:54:18 -07004246 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08004247 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004248 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004249 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07004250 dpp_auth_deinit(wpa_s->dpp_auth);
4251 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08004252 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004253 return resp;
4254}
4255
4256
4257static void
4258wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
4259{
4260 struct wpa_supplicant *wpa_s = ctx;
4261 struct dpp_authentication *auth = wpa_s->dpp_auth;
4262
4263 if (!auth) {
4264 wpabuf_free(resp);
4265 return;
4266 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004267 if (auth->conf_resp != resp) {
4268 wpa_printf(MSG_DEBUG,
4269 "DPP: Ignore GAS status report (ok=%d) for unknown response",
4270 ok);
4271 wpabuf_free(resp);
4272 return;
4273 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004274
Hai Shalom899fcc72020-10-19 14:38:18 -07004275#ifdef CONFIG_DPP2
4276 if (auth->waiting_csr && ok) {
4277 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
4278 wpabuf_free(resp);
4279 return;
4280 }
4281#endif /* CONFIG_DPP2 */
4282
Sunil Ravia04bd252022-05-02 22:54:18 -07004283#ifdef CONFIG_DPP3
4284 if (auth->waiting_new_key && ok) {
4285 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
4286 wpabuf_free(resp);
4287 return;
4288 }
4289#endif /* CONFIG_DPP3 */
4290
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004291 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
4292 ok);
4293 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004294 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004295 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004296#ifdef CONFIG_DPP2
4297 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08004298 auth->conf_resp_status == DPP_STATUS_OK &&
4299 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07004300 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08004301 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07004302 auth->waiting_conf_result = 1;
4303 auth->conf_resp = NULL;
4304 wpabuf_free(resp);
4305 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
4306 wpa_s, NULL);
4307 eloop_register_timeout(2, 0,
4308 wpas_dpp_config_result_wait_timeout,
4309 wpa_s, NULL);
4310 return;
4311 }
4312#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004313 offchannel_send_action_done(wpa_s);
4314 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004315 if (ok) {
Sunil Ravi89eba102022-09-13 21:04:37 -07004316 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
4317 auth->conf_resp_status);
Hai Shalom706f99b2019-01-08 16:23:37 -08004318 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004319 }
4320 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004321 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004322 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004323 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004324 dpp_auth_deinit(wpa_s->dpp_auth);
4325 wpa_s->dpp_auth = NULL;
4326 wpabuf_free(resp);
Sunil Ravi89eba102022-09-13 21:04:37 -07004327#ifdef CONFIG_DPP3
4328 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
4329 if (ok)
4330 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4331 "success");
4332 else
4333 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4334 "could-not-connect");
4335 wpa_s->dpp_pb_result_indicated = true;
4336 if (ok)
4337 wpas_dpp_remove_pb_hash(wpa_s);
4338 wpas_dpp_push_button_stop(wpa_s);
4339 }
4340#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004341}
4342
4343
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004344int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
4345{
4346 struct dpp_authentication *auth;
4347 int ret = -1;
4348 char *curve = NULL;
4349
Hai Shalomfdcde762020-04-02 11:19:20 -07004350 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004351 if (!auth)
4352 return -1;
4353
4354 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08004355 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07004356 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004357 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07004358 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
4359 &auth->conf_obj[0]);
4360 if (!ret)
4361 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004362
4363 dpp_auth_deinit(auth);
4364 os_free(curve);
4365
4366 return ret;
4367}
4368
4369
4370static void
4371wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
4372 unsigned int freq, const u8 *dst,
4373 const u8 *src, const u8 *bssid,
4374 const u8 *data, size_t data_len,
4375 enum offchannel_send_action_result result)
4376{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004377 const char *res_txt;
4378
4379 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
4380 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
4381 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004382 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
4383 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07004384 freq, MAC2STR(dst), res_txt);
4385 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
4386 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004387 /* TODO: Time out wait for response more quickly in error cases? */
4388}
4389
4390
Sunil Ravi89eba102022-09-13 21:04:37 -07004391#ifdef CONFIG_DPP3
4392static int wpas_dpp_start_private_peer_intro(struct wpa_supplicant *wpa_s,
4393 struct wpa_ssid *ssid,
4394 struct wpa_bss *bss)
4395{
4396 struct wpabuf *msg;
4397 unsigned int wait_time;
4398 size_t len;
4399 u8 ver = DPP_VERSION;
4400 int conn_ver;
4401
4402 len = 5 + 5;
4403 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_QUERY, len);
4404 if (!msg)
4405 return -1;
4406
4407 /* Transaction ID */
4408 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4409 wpabuf_put_le16(msg, 1);
4410 wpabuf_put_u8(msg, TRANSACTION_ID);
4411
4412 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4413 if (conn_ver > 0 && ver != conn_ver) {
4414 wpa_printf(MSG_DEBUG,
4415 "DPP: Use Connector version %d instead of current protocol version %d",
4416 conn_ver, ver);
4417 ver = conn_ver;
4418 }
4419
4420 /* Protocol Version */
4421 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4422 wpabuf_put_le16(msg, 1);
4423 wpabuf_put_u8(msg, ver);
4424
4425 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Query", msg);
4426
4427 /* TODO: Timeout on AP response */
4428 wait_time = wpa_s->max_remain_on_chan;
4429 if (wait_time > 2000)
4430 wait_time = 2000;
4431 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4432 MAC2STR(bss->bssid), bss->freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
4433 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4434 broadcast,
4435 wpabuf_head(msg), wpabuf_len(msg),
4436 wait_time, wpas_dpp_tx_introduction_status, 0);
4437 wpabuf_free(msg);
4438
4439 /* Request this connection attempt to terminate - new one will be
4440 * started when network introduction protocol completes */
4441 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4442 wpa_s->dpp_intro_network = ssid;
4443 return 1;
4444}
4445#endif /* CONFIG_DPP3 */
4446
4447
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004448int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4449 struct wpa_bss *bss)
4450{
4451 struct os_time now;
4452 struct wpabuf *msg;
4453 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07004454 const u8 *rsn;
4455 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004456 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004457
4458 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
4459 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07004460 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4461 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
4462 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
4463 return 0; /* AP does not support DPP AKM - continue */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004464 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, wpa_s->own_addr, ssid))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004465 return 0; /* PMKSA exists for DPP AKM - continue */
4466
4467 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4468 !ssid->dpp_csign) {
4469 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4470 "missing %s",
4471 !ssid->dpp_connector ? "Connector" :
4472 (!ssid->dpp_netaccesskey ? "netAccessKey" :
4473 "C-sign-key"));
4474 return -1;
4475 }
4476
4477 os_get_time(&now);
4478
4479 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07004480 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004481 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4482 "netAccessKey expired");
4483 return -1;
4484 }
4485
4486 wpa_printf(MSG_DEBUG,
Sunil Ravi89eba102022-09-13 21:04:37 -07004487 "DPP: Starting %snetwork introduction protocol to derive PMKSA for "
4488 MACSTR,
4489 ssid->dpp_connector_privacy ? "private " : "",
4490 MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07004491 if (wpa_s->wpa_state == WPA_SCANNING)
4492 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004493
Sunil Ravi89eba102022-09-13 21:04:37 -07004494#ifdef CONFIG_DPP3
4495 if (ssid->dpp_connector_privacy)
4496 return wpas_dpp_start_private_peer_intro(wpa_s, ssid, bss);
4497#endif /* CONFIG_DPP3 */
4498
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004499 len = 5 + 4 + os_strlen(ssid->dpp_connector);
4500#ifdef CONFIG_DPP2
4501 len += 5;
4502#endif /* CONFIG_DPP2 */
4503 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004504 if (!msg)
4505 return -1;
4506
Roshan Pius3a1667e2018-07-03 15:17:14 -07004507#ifdef CONFIG_TESTING_OPTIONS
4508 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
4509 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
4510 goto skip_trans_id;
4511 }
4512 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
4513 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
4514 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4515 wpabuf_put_le16(msg, 0);
4516 goto skip_trans_id;
4517 }
4518#endif /* CONFIG_TESTING_OPTIONS */
4519
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004520 /* Transaction ID */
4521 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4522 wpabuf_put_le16(msg, 1);
4523 wpabuf_put_u8(msg, TRANSACTION_ID);
4524
Roshan Pius3a1667e2018-07-03 15:17:14 -07004525#ifdef CONFIG_TESTING_OPTIONS
4526skip_trans_id:
4527 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
4528 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
4529 goto skip_connector;
4530 }
4531 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
4532 char *connector;
4533
4534 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
4535 connector = dpp_corrupt_connector_signature(
4536 ssid->dpp_connector);
4537 if (!connector) {
4538 wpabuf_free(msg);
4539 return -1;
4540 }
4541 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4542 wpabuf_put_le16(msg, os_strlen(connector));
4543 wpabuf_put_str(msg, connector);
4544 os_free(connector);
4545 goto skip_connector;
4546 }
4547#endif /* CONFIG_TESTING_OPTIONS */
4548
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004549 /* DPP Connector */
4550 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4551 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
4552 wpabuf_put_str(msg, ssid->dpp_connector);
4553
Roshan Pius3a1667e2018-07-03 15:17:14 -07004554#ifdef CONFIG_TESTING_OPTIONS
4555skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004556 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
4557 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
4558 goto skip_proto_ver;
4559 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004560#endif /* CONFIG_TESTING_OPTIONS */
4561
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004562#ifdef CONFIG_DPP2
4563 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004564 u8 ver = DPP_VERSION;
4565#ifdef CONFIG_DPP3
4566 int conn_ver;
4567
4568 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4569 if (conn_ver > 0 && ver != conn_ver) {
4570 wpa_printf(MSG_DEBUG,
4571 "DPP: Use Connector version %d instead of current protocol version %d",
4572 conn_ver, ver);
4573 ver = conn_ver;
4574 }
4575#endif /* CONFIG_DPP3 */
4576
4577#ifdef CONFIG_TESTING_OPTIONS
4578 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
4579 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
4580 ver = 1;
4581 }
4582#endif /* CONFIG_TESTING_OPTIONS */
4583
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004584 /* Protocol Version */
4585 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4586 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004587 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004588 }
4589#endif /* CONFIG_DPP2 */
4590
Hai Shaloma20dcd72022-02-04 13:43:00 -08004591#ifdef CONFIG_TESTING_OPTIONS
4592skip_proto_ver:
4593#endif /* CONFIG_TESTING_OPTIONS */
4594
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004595 /* TODO: Timeout on AP response */
4596 wait_time = wpa_s->max_remain_on_chan;
4597 if (wait_time > 2000)
4598 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004599 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4600 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004601 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4602 broadcast,
4603 wpabuf_head(msg), wpabuf_len(msg),
4604 wait_time, wpas_dpp_tx_introduction_status, 0);
4605 wpabuf_free(msg);
4606
4607 /* Request this connection attempt to terminate - new one will be
4608 * started when network introduction protocol completes */
4609 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4610 wpa_s->dpp_intro_network = ssid;
4611 return 1;
4612}
4613
4614
4615int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
4616{
4617 struct dpp_bootstrap_info *own_bi;
4618 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07004619#ifdef CONFIG_DPP3
4620 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
4621#else /* CONFIG_DPP3 */
4622 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
4623#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004624 int tcp_port = DPP_TCP_PORT;
4625 struct hostapd_ip_addr *ipaddr = NULL;
4626#ifdef CONFIG_DPP2
4627 struct hostapd_ip_addr ipaddr_buf;
4628 char *addr;
4629
4630 pos = os_strstr(cmd, " tcp_port=");
4631 if (pos) {
4632 pos += 10;
4633 tcp_port = atoi(pos);
4634 }
4635
4636 addr = get_param(cmd, " tcp_addr=");
4637 if (addr) {
4638 int res;
4639
4640 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
4641 os_free(addr);
4642 if (res)
4643 return -1;
4644 ipaddr = &ipaddr_buf;
4645 }
4646#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004647
4648 pos = os_strstr(cmd, " own=");
4649 if (!pos)
4650 return -1;
4651 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07004652 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004653 if (!own_bi) {
4654 wpa_printf(MSG_DEBUG,
4655 "DPP: Identified bootstrap info not found");
4656 return -1;
4657 }
4658 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
4659 wpa_printf(MSG_DEBUG,
4660 "DPP: Identified bootstrap info not for PKEX");
4661 return -1;
4662 }
4663 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004664 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004665
4666 os_free(wpa_s->dpp_pkex_identifier);
4667 wpa_s->dpp_pkex_identifier = NULL;
4668 pos = os_strstr(cmd, " identifier=");
4669 if (pos) {
4670 pos += 12;
4671 end = os_strchr(pos, ' ');
4672 if (!end)
4673 return -1;
4674 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
4675 if (!wpa_s->dpp_pkex_identifier)
4676 return -1;
4677 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
4678 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
4679 }
4680
4681 pos = os_strstr(cmd, " code=");
4682 if (!pos)
4683 return -1;
4684 os_free(wpa_s->dpp_pkex_code);
4685 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
4686 if (!wpa_s->dpp_pkex_code)
4687 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004688 wpa_s->dpp_pkex_code_len = os_strlen(wpa_s->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004689
Sunil Ravia04bd252022-05-02 22:54:18 -07004690 pos = os_strstr(cmd, " ver=");
4691 if (pos) {
4692 int v;
4693
4694 pos += 5;
4695 v = atoi(pos);
4696 if (v == 1)
4697 ver = PKEX_VER_ONLY_1;
4698 else if (v == 2)
4699 ver = PKEX_VER_ONLY_2;
4700 else
4701 return -1;
4702 }
4703 wpa_s->dpp_pkex_ver = ver;
4704
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004705 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004706 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004707 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004708 } else {
4709#ifdef CONFIG_DPP2
4710 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
4711 wpa_s->dpp_pkex_code,
4712 wpa_s->dpp_pkex_identifier);
4713#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004714 }
4715
4716 /* TODO: Support multiple PKEX info entries */
4717
4718 os_free(wpa_s->dpp_pkex_auth_cmd);
4719 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
4720
4721 return 1;
4722}
4723
4724
4725int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
4726{
4727 unsigned int id_val;
4728
4729 if (os_strcmp(id, "*") == 0) {
4730 id_val = 0;
4731 } else {
4732 id_val = atoi(id);
4733 if (id_val == 0)
4734 return -1;
4735 }
4736
Sunil Ravi89eba102022-09-13 21:04:37 -07004737 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004738 return -1;
4739
4740 /* TODO: Support multiple PKEX entries */
4741 os_free(wpa_s->dpp_pkex_code);
4742 wpa_s->dpp_pkex_code = NULL;
4743 os_free(wpa_s->dpp_pkex_identifier);
4744 wpa_s->dpp_pkex_identifier = NULL;
4745 os_free(wpa_s->dpp_pkex_auth_cmd);
4746 wpa_s->dpp_pkex_auth_cmd = NULL;
4747 wpa_s->dpp_pkex_bi = NULL;
4748 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
4749 dpp_pkex_free(wpa_s->dpp_pkex);
4750 wpa_s->dpp_pkex = NULL;
4751 return 0;
4752}
4753
4754
Roshan Pius3a1667e2018-07-03 15:17:14 -07004755void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
4756{
Sunil Ravia04bd252022-05-02 22:54:18 -07004757 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07004758 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004759 dpp_auth_deinit(wpa_s->dpp_auth);
4760 wpa_s->dpp_auth = NULL;
4761 dpp_pkex_free(wpa_s->dpp_pkex);
4762 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004763 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004764 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
4765 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
Sunil Ravi89eba102022-09-13 21:04:37 -07004766#ifdef CONFIG_DPP3
4767 wpas_dpp_push_button_stop(wpa_s);
4768#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004769}
4770
4771
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004772int wpas_dpp_init(struct wpa_supplicant *wpa_s)
4773{
Hai Shalom81f62d82019-07-22 12:10:00 -07004774 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004775 u8 adv_proto_id[7];
4776
4777 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
4778 adv_proto_id[1] = 5;
4779 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
4780 adv_proto_id[5] = DPP_OUI_TYPE;
4781 adv_proto_id[6] = 0x01;
4782
4783 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
4784 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
4785 wpas_dpp_gas_status_handler, wpa_s) < 0)
4786 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004787
4788 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07004789 config.cb_ctx = wpa_s;
4790#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004791 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07004792#endif /* CONFIG_DPP2 */
4793 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07004794 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004795}
4796
4797
4798void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
4799{
4800#ifdef CONFIG_TESTING_OPTIONS
4801 os_free(wpa_s->dpp_config_obj_override);
4802 wpa_s->dpp_config_obj_override = NULL;
4803 os_free(wpa_s->dpp_discovery_override);
4804 wpa_s->dpp_discovery_override = NULL;
4805 os_free(wpa_s->dpp_groups_override);
4806 wpa_s->dpp_groups_override = NULL;
4807 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
4808#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07004809 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004810 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004811 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004812 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004813 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004814 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
4815 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004816 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4817 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004818 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004819#ifdef CONFIG_DPP2
4820 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07004821 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
4822 wpa_s, NULL);
4823 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004824 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
4825 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004826 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004827 eloop_cancel_timeout(wpas_dpp_connected_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004828 dpp_pfs_free(wpa_s->dpp_pfs);
4829 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004830 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004831 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4832 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07004833#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07004834#ifdef CONFIG_DPP3
4835 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
4836#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004837 offchannel_send_action_done(wpa_s);
4838 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004839 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004840 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004841 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
4842 os_free(wpa_s->dpp_configurator_params);
4843 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07004844 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004845}
Hai Shalom81f62d82019-07-22 12:10:00 -07004846
4847
Hai Shaloma20dcd72022-02-04 13:43:00 -08004848static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
4849 struct dpp_authentication *auth, bool tcp)
4850{
4851 struct wpabuf *resp;
4852
4853 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
4854 auth->e_netrole, true);
4855 if (!resp)
4856 return -1;
4857
4858 if (tcp) {
4859 auth->conf_resp_tcp = resp;
4860 return 0;
4861 }
4862
4863 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4864 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
4865 resp) < 0) {
4866 wpa_printf(MSG_DEBUG,
4867 "DPP: Could not find pending GAS response");
4868 wpabuf_free(resp);
4869 return -1;
4870 }
4871 auth->conf_resp = resp;
4872 return 0;
4873}
4874
4875
4876int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
4877{
4878 int peer;
4879 const char *pos;
4880 struct dpp_authentication *auth = wpa_s->dpp_auth;
4881 bool tcp = false;
4882
4883 pos = os_strstr(cmd, " peer=");
4884 if (!pos)
4885 return -1;
4886 peer = atoi(pos + 6);
4887#ifdef CONFIG_DPP2
4888 if (!auth || !auth->waiting_config ||
4889 (auth->peer_bi &&
4890 (unsigned int) peer != auth->peer_bi->id)) {
4891 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4892 tcp = true;
4893 }
4894#endif /* CONFIG_DPP2 */
4895
4896 if (!auth || !auth->waiting_config) {
4897 wpa_printf(MSG_DEBUG,
4898 "DPP: No authentication exchange waiting for configuration information");
4899 return -1;
4900 }
4901
4902 if ((!auth->peer_bi ||
4903 (unsigned int) peer != auth->peer_bi->id) &&
4904 (!auth->tmp_peer_bi ||
4905 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4906 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4907 return -1;
4908 }
4909
4910 pos = os_strstr(cmd, " comeback=");
4911 if (pos) {
4912 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4913 NULL);
4914 gas_server_set_comeback_delay(wpa_s->gas_server,
4915 auth->config_resp_ctx,
4916 atoi(pos + 10));
4917 return 0;
4918 }
4919
4920 if (dpp_set_configurator(auth, cmd) < 0)
4921 return -1;
4922
4923 auth->use_config_query = false;
4924 auth->waiting_config = false;
4925 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4926}
4927
4928
Hai Shalom81f62d82019-07-22 12:10:00 -07004929#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004930
Hai Shalom81f62d82019-07-22 12:10:00 -07004931int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
4932{
4933 struct dpp_controller_config config;
4934 const char *pos;
4935
4936 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004937 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07004938 config.netrole = DPP_NETROLE_STA;
4939 config.msg_ctx = wpa_s;
4940 config.cb_ctx = wpa_s;
4941 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004942 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07004943 if (cmd) {
4944 pos = os_strstr(cmd, " tcp_port=");
4945 if (pos) {
4946 pos += 10;
4947 config.tcp_port = atoi(pos);
4948 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004949
4950 pos = os_strstr(cmd, " role=");
4951 if (pos) {
4952 pos += 6;
4953 if (os_strncmp(pos, "configurator", 12) == 0)
4954 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
4955 else if (os_strncmp(pos, "enrollee", 8) == 0)
4956 config.allowed_roles = DPP_CAPAB_ENROLLEE;
4957 else if (os_strncmp(pos, "either", 6) == 0)
4958 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
4959 DPP_CAPAB_ENROLLEE;
4960 else
4961 return -1;
4962 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004963
4964 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07004965 }
4966 config.configurator_params = wpa_s->dpp_configurator_params;
4967 return dpp_controller_start(wpa_s->dpp, &config);
4968}
Hai Shalomfdcde762020-04-02 11:19:20 -07004969
4970
4971static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
4972
4973static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
4974{
4975 struct wpa_supplicant *wpa_s = eloop_ctx;
4976
4977 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
4978 offchannel_send_action_done(wpa_s);
4979 wpas_dpp_chirp_next(wpa_s, NULL);
4980}
4981
4982
4983static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
4984 unsigned int freq, const u8 *dst,
4985 const u8 *src, const u8 *bssid,
4986 const u8 *data, size_t data_len,
4987 enum offchannel_send_action_result result)
4988{
4989 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
4990 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
4991 wpa_s->dpp_chirp_freq);
4992 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
4993 wpa_s, NULL) < 0)
4994 wpas_dpp_chirp_stop(wpa_s);
4995 return;
4996 }
4997
4998 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
4999 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
5000 wpa_s, NULL) < 0)
5001 wpas_dpp_chirp_stop(wpa_s);
5002}
5003
5004
5005static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
5006{
Hai Shalom899fcc72020-10-19 14:38:18 -07005007 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005008 int type;
5009
5010 msg = wpa_s->dpp_presence_announcement;
5011 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
5012 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07005013 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
5014
5015 if (ssid && wpa_s->dpp_reconfig_id &&
5016 wpa_config_get_network(wpa_s->conf,
5017 wpa_s->dpp_reconfig_ssid_id) ==
5018 ssid) {
5019 announce = dpp_build_reconfig_announcement(
5020 ssid->dpp_csign,
5021 ssid->dpp_csign_len,
5022 ssid->dpp_netaccesskey,
5023 ssid->dpp_netaccesskey_len,
5024 wpa_s->dpp_reconfig_id);
5025 msg = announce;
5026 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005027 if (!msg)
5028 return;
5029 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
5030 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005031 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
5032 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005033 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07005034 if (offchannel_send_action(
5035 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
5036 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005037 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07005038 2000, wpas_dpp_chirp_tx_status, 0) < 0)
5039 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07005040
5041 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07005042}
5043
5044
Sunil Ravi89eba102022-09-13 21:04:37 -07005045static int * wpas_dpp_presence_ann_channels(struct wpa_supplicant *wpa_s,
5046 struct dpp_bootstrap_info *bi)
Hai Shalomfdcde762020-04-02 11:19:20 -07005047{
Hai Shalomfdcde762020-04-02 11:19:20 -07005048 unsigned int i;
5049 struct hostapd_hw_modes *mode;
5050 int c;
5051 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005052 bool chan6 = wpa_s->hw.modes == NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005053 int *freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07005054
5055 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005056 if (bi) {
5057 for (i = 0; i < bi->num_freq; i++)
Sunil Ravi89eba102022-09-13 21:04:37 -07005058 int_array_add_unique(&freqs, bi->freq[i]);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005059 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005060
5061 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07005062 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005063 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07005064 if (mode) {
5065 for (c = 0; c < mode->num_channels; c++) {
5066 struct hostapd_channel_data *chan = &mode->channels[c];
5067
5068 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
5069 chan->freq != 2437)
5070 continue;
5071 chan6 = true;
5072 break;
5073 }
5074 }
5075 if (chan6)
Sunil Ravi89eba102022-09-13 21:04:37 -07005076 int_array_add_unique(&freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07005077
5078 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005079 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005080 if (mode) {
5081 int chan44 = 0, chan149 = 0;
5082
5083 for (c = 0; c < mode->num_channels; c++) {
5084 struct hostapd_channel_data *chan = &mode->channels[c];
5085
5086 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
5087 HOSTAPD_CHAN_RADAR))
5088 continue;
5089 if (chan->freq == 5220)
5090 chan44 = 1;
5091 if (chan->freq == 5745)
5092 chan149 = 1;
5093 }
5094 if (chan149)
Sunil Ravi89eba102022-09-13 21:04:37 -07005095 int_array_add_unique(&freqs, 5745);
Hai Shalomfdcde762020-04-02 11:19:20 -07005096 else if (chan44)
Sunil Ravi89eba102022-09-13 21:04:37 -07005097 int_array_add_unique(&freqs, 5220);
Hai Shalomfdcde762020-04-02 11:19:20 -07005098 }
5099
5100 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005101 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005102 if (mode) {
5103 for (c = 0; c < mode->num_channels; c++) {
5104 struct hostapd_channel_data *chan = &mode->channels[c];
5105
5106 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
5107 HOSTAPD_CHAN_RADAR)) ||
5108 chan->freq != 60480)
5109 continue;
Sunil Ravi89eba102022-09-13 21:04:37 -07005110 int_array_add_unique(&freqs, 60480);
Hai Shalomfdcde762020-04-02 11:19:20 -07005111 break;
5112 }
5113 }
5114
5115 /* Add channels from scan results for APs that advertise Configurator
5116 * Connectivity element */
5117 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5118 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
Sunil Ravi89eba102022-09-13 21:04:37 -07005119 int_array_add_unique(&freqs, bss->freq);
Hai Shalomfdcde762020-04-02 11:19:20 -07005120 }
5121
Sunil Ravi89eba102022-09-13 21:04:37 -07005122 return freqs;
5123}
5124
5125
5126static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
5127 struct wpa_scan_results *scan_res)
5128{
5129 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
5130
5131 if (!bi && !wpa_s->dpp_reconfig_ssid)
5132 return;
5133
5134 wpa_s->dpp_chirp_scan_done = 1;
5135
5136 os_free(wpa_s->dpp_chirp_freqs);
5137 wpa_s->dpp_chirp_freqs = wpas_dpp_presence_ann_channels(wpa_s, bi);
5138
Hai Shalomfdcde762020-04-02 11:19:20 -07005139 if (!wpa_s->dpp_chirp_freqs ||
5140 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
5141 wpas_dpp_chirp_stop(wpa_s);
5142}
5143
5144
5145static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
5146{
5147 struct wpa_supplicant *wpa_s = eloop_ctx;
5148 int i;
5149
5150 if (wpa_s->dpp_chirp_listen)
5151 wpas_dpp_listen_stop(wpa_s);
5152
5153 if (wpa_s->dpp_chirp_freq == 0) {
5154 if (wpa_s->dpp_chirp_round % 4 == 0 &&
5155 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08005156 if (wpas_scan_scheduled(wpa_s)) {
5157 wpa_printf(MSG_DEBUG,
5158 "DPP: Deferring chirp scan because another scan is planned already");
5159 if (eloop_register_timeout(1, 0,
5160 wpas_dpp_chirp_next,
5161 wpa_s, NULL) < 0) {
5162 wpas_dpp_chirp_stop(wpa_s);
5163 return;
5164 }
5165 return;
5166 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005167 wpa_printf(MSG_DEBUG,
5168 "DPP: Update channel list for chirping");
5169 wpa_s->scan_req = MANUAL_SCAN_REQ;
5170 wpa_s->scan_res_handler =
5171 wpas_dpp_chirp_scan_res_handler;
5172 wpa_supplicant_req_scan(wpa_s, 0, 0);
5173 return;
5174 }
5175 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
5176 wpa_s->dpp_chirp_round++;
5177 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
5178 wpa_s->dpp_chirp_round);
5179 } else {
5180 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
5181 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
5182 break;
5183 if (!wpa_s->dpp_chirp_freqs[i]) {
5184 wpa_printf(MSG_DEBUG,
5185 "DPP: Previous chirp freq %d not found",
5186 wpa_s->dpp_chirp_freq);
5187 return;
5188 }
5189 i++;
5190 if (wpa_s->dpp_chirp_freqs[i]) {
5191 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
5192 } else {
5193 wpa_s->dpp_chirp_iter--;
5194 if (wpa_s->dpp_chirp_iter <= 0) {
5195 wpa_printf(MSG_DEBUG,
5196 "DPP: Chirping iterations completed");
5197 wpas_dpp_chirp_stop(wpa_s);
5198 return;
5199 }
5200 wpa_s->dpp_chirp_freq = 0;
5201 wpa_s->dpp_chirp_scan_done = 0;
5202 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
5203 wpa_s, NULL) < 0) {
5204 wpas_dpp_chirp_stop(wpa_s);
5205 return;
5206 }
5207 if (wpa_s->dpp_chirp_listen) {
5208 wpa_printf(MSG_DEBUG,
5209 "DPP: Listen on %d MHz during chirp 30 second wait",
5210 wpa_s->dpp_chirp_listen);
5211 wpas_dpp_listen_start(wpa_s,
5212 wpa_s->dpp_chirp_listen);
5213 } else {
5214 wpa_printf(MSG_DEBUG,
5215 "DPP: Wait 30 seconds before starting the next chirping round");
5216 }
5217 return;
5218 }
5219 }
5220
5221 wpas_dpp_chirp_start(wpa_s);
5222}
5223
5224
5225int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
5226{
5227 const char *pos;
5228 int iter = 1, listen_freq = 0;
5229 struct dpp_bootstrap_info *bi;
5230
5231 pos = os_strstr(cmd, " own=");
5232 if (!pos)
5233 return -1;
5234 pos += 5;
5235 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
5236 if (!bi) {
5237 wpa_printf(MSG_DEBUG,
5238 "DPP: Identified bootstrap info not found");
5239 return -1;
5240 }
5241
5242 pos = os_strstr(cmd, " iter=");
5243 if (pos) {
5244 iter = atoi(pos + 6);
5245 if (iter <= 0)
5246 return -1;
5247 }
5248
5249 pos = os_strstr(cmd, " listen=");
5250 if (pos) {
5251 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005252 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005253 return -1;
5254 }
5255
5256 wpas_dpp_chirp_stop(wpa_s);
5257 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005258 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07005259 wpa_s->dpp_qr_mutual = 0;
5260 wpa_s->dpp_chirp_bi = bi;
5261 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
5262 if (!wpa_s->dpp_presence_announcement)
5263 return -1;
5264 wpa_s->dpp_chirp_iter = iter;
5265 wpa_s->dpp_chirp_round = 0;
5266 wpa_s->dpp_chirp_scan_done = 0;
5267 wpa_s->dpp_chirp_listen = listen_freq;
5268
5269 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5270}
5271
5272
5273void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
5274{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005275 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07005276 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005277 offchannel_send_action_done(wpa_s);
5278 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
5279 }
5280 wpa_s->dpp_chirp_bi = NULL;
5281 wpabuf_free(wpa_s->dpp_presence_announcement);
5282 wpa_s->dpp_presence_announcement = NULL;
5283 if (wpa_s->dpp_chirp_listen)
5284 wpas_dpp_listen_stop(wpa_s);
5285 wpa_s->dpp_chirp_listen = 0;
5286 wpa_s->dpp_chirp_freq = 0;
5287 os_free(wpa_s->dpp_chirp_freqs);
5288 wpa_s->dpp_chirp_freqs = NULL;
5289 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
5290 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
5291 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
5292 wpas_abort_ongoing_scan(wpa_s);
5293 wpa_s->scan_res_handler = NULL;
5294 }
5295}
5296
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005297
Hai Shalom899fcc72020-10-19 14:38:18 -07005298int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005299{
Hai Shalom899fcc72020-10-19 14:38:18 -07005300 struct wpa_ssid *ssid;
5301 int iter = 1;
5302 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005303
Hai Shalom899fcc72020-10-19 14:38:18 -07005304 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
5305 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
5306 !ssid->dpp_csign) {
5307 wpa_printf(MSG_DEBUG,
5308 "DPP: Not a valid network profile for reconfiguration");
5309 return -1;
5310 }
5311
5312 pos = os_strstr(cmd, " iter=");
5313 if (pos) {
5314 iter = atoi(pos + 6);
5315 if (iter <= 0)
5316 return -1;
5317 }
5318
5319 if (wpa_s->dpp_auth) {
5320 wpa_printf(MSG_DEBUG,
5321 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
5322 return -1;
5323 }
5324
5325 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
5326 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
5327 ssid->dpp_csign_len,
5328 ssid->dpp_pp_key,
5329 ssid->dpp_pp_key_len);
5330 if (!wpa_s->dpp_reconfig_id) {
5331 wpa_printf(MSG_DEBUG,
5332 "DPP: Failed to generate E-id for reconfiguration");
5333 return -1;
5334 }
5335 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
5336 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
5337 wpa_s->own_disconnect_req = 1;
5338 wpa_supplicant_deauthenticate(
5339 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5340 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005341 wpas_dpp_chirp_stop(wpa_s);
5342 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005343 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005344 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005345 wpa_s->dpp_reconfig_ssid = ssid;
5346 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07005347 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005348 wpa_s->dpp_chirp_round = 0;
5349 wpa_s->dpp_chirp_scan_done = 0;
5350 wpa_s->dpp_chirp_listen = 0;
5351
5352 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5353}
5354
Hai Shalom899fcc72020-10-19 14:38:18 -07005355
Hai Shalom899fcc72020-10-19 14:38:18 -07005356int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
5357{
5358 int peer = -1;
5359 const char *pos, *value;
5360 struct dpp_authentication *auth = wpa_s->dpp_auth;
5361 u8 *bin;
5362 size_t bin_len;
5363 struct wpabuf *buf;
5364 bool tcp = false;
5365
5366 pos = os_strstr(cmd, " peer=");
5367 if (pos) {
5368 peer = atoi(pos + 6);
5369 if (!auth || !auth->waiting_cert ||
5370 (auth->peer_bi &&
5371 (unsigned int) peer != auth->peer_bi->id)) {
5372 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5373 tcp = true;
5374 }
5375 }
5376
5377 if (!auth || !auth->waiting_cert) {
5378 wpa_printf(MSG_DEBUG,
5379 "DPP: No authentication exchange waiting for certificate information");
5380 return -1;
5381 }
5382
5383 if (peer >= 0 &&
5384 (!auth->peer_bi ||
5385 (unsigned int) peer != auth->peer_bi->id) &&
5386 (!auth->tmp_peer_bi ||
5387 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5388 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5389 return -1;
5390 }
5391
5392 pos = os_strstr(cmd, " value=");
5393 if (!pos)
5394 return -1;
5395 value = pos + 7;
5396
5397 pos = os_strstr(cmd, " name=");
5398 if (!pos)
5399 return -1;
5400 pos += 6;
5401
5402 if (os_strncmp(pos, "status ", 7) == 0) {
5403 auth->force_conf_resp_status = atoi(value);
5404 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5405 }
5406
5407 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
5408 os_free(auth->trusted_eap_server_name);
5409 auth->trusted_eap_server_name = os_strdup(value);
5410 return auth->trusted_eap_server_name ? 0 : -1;
5411 }
5412
5413 bin = base64_decode(value, os_strlen(value), &bin_len);
5414 if (!bin)
5415 return -1;
5416 buf = wpabuf_alloc_copy(bin, bin_len);
5417 os_free(bin);
5418
5419 if (os_strncmp(pos, "caCert ", 7) == 0) {
5420 wpabuf_free(auth->cacert);
5421 auth->cacert = buf;
5422 return 0;
5423 }
5424
5425 if (os_strncmp(pos, "certBag ", 8) == 0) {
5426 wpabuf_free(auth->certbag);
5427 auth->certbag = buf;
5428 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5429 }
5430
5431 wpabuf_free(buf);
5432 return -1;
5433}
5434
Hai Shalom81f62d82019-07-22 12:10:00 -07005435#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07005436
5437
5438#ifdef CONFIG_DPP3
5439
5440#define DPP_PB_ANNOUNCE_PER_CHAN 3
5441
5442static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
5443static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
5444
5445
5446static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
5447 unsigned int freq, const u8 *dst,
5448 const u8 *src, const u8 *bssid,
5449 const u8 *data, size_t data_len,
5450 enum offchannel_send_action_result result)
5451{
5452 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5453 wpa_printf(MSG_DEBUG,
5454 "DPP: Failed to send push button announcement on %d MHz",
5455 freq);
5456 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
5457 wpa_s, NULL) < 0)
5458 wpas_dpp_push_button_stop(wpa_s);
5459 return;
5460 }
5461
5462 wpa_printf(MSG_DEBUG, "DPP: Push button announcement on %d MHz sent",
5463 freq);
5464 if (wpa_s->dpp_pb_discovery_done) {
5465 wpa_s->dpp_pb_announce_count = 0;
5466 wpa_printf(MSG_DEBUG,
5467 "DPP: Wait for push button announcement response and PKEX on %d MHz",
5468 freq);
5469 if (eloop_register_timeout(0, 500000, wpas_dpp_pb_next,
5470 wpa_s, NULL) < 0)
5471 wpas_dpp_push_button_stop(wpa_s);
5472 return;
5473 } else if (wpa_s->dpp_pb_announce_count >= DPP_PB_ANNOUNCE_PER_CHAN) {
5474 wpa_printf(MSG_DEBUG,
5475 "DPP: Wait for push button announcement response on %d MHz",
5476 freq);
5477 if (eloop_register_timeout(0, 50000, wpas_dpp_pb_next,
5478 wpa_s, NULL) < 0)
5479 wpas_dpp_push_button_stop(wpa_s);
5480 return;
5481 }
5482
5483 if (wpas_dpp_pb_announce(wpa_s, freq) < 0)
5484 wpas_dpp_push_button_stop(wpa_s);
5485}
5486
5487
5488static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq)
5489{
5490 struct wpabuf *msg;
5491 int type;
5492
5493 msg = wpa_s->dpp_pb_announcement;
5494 if (!msg)
5495 return -1;
5496
5497 wpa_s->dpp_pb_announce_count++;
5498 wpa_printf(MSG_DEBUG,
5499 "DPP: Send push button announcement %d/%d (%d MHz)",
5500 wpa_s->dpp_pb_announce_count, DPP_PB_ANNOUNCE_PER_CHAN,
5501 freq);
5502
5503 type = DPP_PA_PB_PRESENCE_ANNOUNCEMENT;
5504 if (wpa_s->dpp_pb_announce_count == 1)
5505 wpa_msg(wpa_s, MSG_INFO,
5506 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
5507 MAC2STR(broadcast), freq, type);
5508 if (offchannel_send_action(
5509 wpa_s, freq, broadcast, wpa_s->own_addr, broadcast,
5510 wpabuf_head(msg), wpabuf_len(msg),
5511 1000, wpas_dpp_pb_tx_status, 0) < 0)
5512 return -1;
5513
5514 return 0;
5515}
5516
5517
5518static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx)
5519{
5520 struct wpa_supplicant *wpa_s = eloop_ctx;
5521 struct os_reltime now;
5522 int freq;
5523
5524 if (!wpa_s->dpp_pb_freqs)
5525 return;
5526
5527 os_get_reltime(&now);
5528 offchannel_send_action_done(wpa_s);
5529
5530 if (os_reltime_expired(&now, &wpa_s->dpp_pb_time, 100)) {
5531 wpa_printf(MSG_DEBUG, "DPP: Push button wait time expired");
5532 wpas_dpp_push_button_stop(wpa_s);
5533 return;
5534 }
5535
5536 if (wpa_s->dpp_pb_freq_idx >= int_array_len(wpa_s->dpp_pb_freqs)) {
5537 wpa_printf(MSG_DEBUG,
5538 "DPP: Completed push button announcement round");
5539 wpa_s->dpp_pb_freq_idx = 0;
5540 if (wpa_s->dpp_pb_stop_iter > 0) {
5541 wpa_s->dpp_pb_stop_iter--;
5542
5543 if (wpa_s->dpp_pb_stop_iter == 1) {
5544 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5545 "wait for AP/Configurator to allow PKEX to be initiated");
5546 if (eloop_register_timeout(10, 0,
5547 wpas_dpp_pb_next,
5548 wpa_s, NULL) < 0) {
5549 wpas_dpp_push_button_stop(wpa_s);
5550 return;
5551 }
5552 return;
5553 }
5554
5555 if (wpa_s->dpp_pb_stop_iter == 0) {
5556 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5557 "start push button PKEX responder on the discovered channel (%d MHz)",
5558 wpa_s->dpp_pb_resp_freq);
5559 wpa_s->dpp_pb_discovery_done = true;
5560
5561 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
5562
5563 os_free(wpa_s->dpp_pkex_code);
5564 wpa_s->dpp_pkex_code = os_memdup(
5565 wpa_s->dpp_pb_c_nonce,
5566 wpa_s->dpp_pb_c_nonce_len);
5567 wpa_s->dpp_pkex_code_len =
5568 wpa_s->dpp_pb_c_nonce_len;
5569
5570 os_free(wpa_s->dpp_pkex_identifier);
5571 wpa_s->dpp_pkex_identifier =
5572 os_strdup("PBPKEX");
5573
5574 if (!wpa_s->dpp_pkex_code ||
5575 !wpa_s->dpp_pkex_identifier) {
5576 wpas_dpp_push_button_stop(wpa_s);
5577 return;
5578 }
5579
5580 wpa_s->dpp_pkex_ver = PKEX_VER_ONLY_2;
5581
5582 os_free(wpa_s->dpp_pkex_auth_cmd);
5583 wpa_s->dpp_pkex_auth_cmd = NULL;
5584 }
5585 }
5586 }
5587
5588 if (wpa_s->dpp_pb_discovery_done)
5589 freq = wpa_s->dpp_pb_resp_freq;
5590 else
5591 freq = wpa_s->dpp_pb_freqs[wpa_s->dpp_pb_freq_idx++];
5592 wpa_s->dpp_pb_announce_count = 0;
5593 if (!wpa_s->dpp_pb_announcement) {
5594 wpa_printf(MSG_DEBUG, "DPP: Push button announcements stopped");
5595 return;
5596 }
5597 if (wpas_dpp_pb_announce(wpa_s, freq) < 0) {
5598 wpas_dpp_push_button_stop(wpa_s);
5599 return;
5600 }
5601}
5602
5603
5604static void wpas_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
5605{
5606 struct wpa_supplicant *wpa_s = eloop_ctx;
5607
5608 wpa_printf(MSG_DEBUG,
5609 "DPP: Active push button Configurator mode expired");
5610 wpas_dpp_push_button_stop(wpa_s);
5611}
5612
5613
5614static int wpas_dpp_push_button_configurator(struct wpa_supplicant *wpa_s,
5615 const char *cmd)
5616{
5617 wpa_s->dpp_pb_configurator = true;
5618 wpa_s->dpp_pb_announce_time.sec = 0;
5619 wpa_s->dpp_pb_announce_time.usec = 0;
5620 str_clear_free(wpa_s->dpp_pb_cmd);
5621 wpa_s->dpp_pb_cmd = NULL;
5622 if (cmd) {
5623 wpa_s->dpp_pb_cmd = os_strdup(cmd);
5624 if (!wpa_s->dpp_pb_cmd)
5625 return -1;
5626 }
5627 eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
5628 wpa_s, NULL);
5629
5630 return 0;
5631}
5632
5633
5634static void wpas_dpp_pb_scan_res_handler(struct wpa_supplicant *wpa_s,
5635 struct wpa_scan_results *scan_res)
5636{
5637 if (!wpa_s->dpp_pb_time.sec && !wpa_s->dpp_pb_time.usec)
5638 return;
5639
5640 os_free(wpa_s->dpp_pb_freqs);
5641 wpa_s->dpp_pb_freqs = wpas_dpp_presence_ann_channels(wpa_s, NULL);
5642
5643 wpa_printf(MSG_DEBUG, "DPP: Scan completed for PB discovery");
5644 if (!wpa_s->dpp_pb_freqs ||
5645 eloop_register_timeout(0, 0, wpas_dpp_pb_next, wpa_s, NULL) < 0)
5646 wpas_dpp_push_button_stop(wpa_s);
5647}
5648
5649
5650int wpas_dpp_push_button(struct wpa_supplicant *wpa_s, const char *cmd)
5651{
5652 int res;
5653
5654 if (!wpa_s->dpp)
5655 return -1;
5656 wpas_dpp_push_button_stop(wpa_s);
5657 wpas_dpp_stop(wpa_s);
5658 wpas_dpp_chirp_stop(wpa_s);
5659
5660 os_get_reltime(&wpa_s->dpp_pb_time);
5661
5662 if (cmd &&
5663 (os_strstr(cmd, " role=configurator") ||
5664 os_strstr(cmd, " conf=")))
5665 return wpas_dpp_push_button_configurator(wpa_s, cmd);
5666
5667 wpa_s->dpp_pb_configurator = false;
5668
5669 wpa_s->dpp_pb_freq_idx = 0;
5670
5671 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
5672 if (res < 0)
5673 return -1;
5674 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
5675 if (!wpa_s->dpp_pb_bi)
5676 return -1;
5677
5678 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
5679 wpa_s->dpp_netrole = DPP_NETROLE_STA;
5680 wpa_s->dpp_qr_mutual = 0;
5681 wpa_s->dpp_pb_announcement =
5682 dpp_build_pb_announcement(wpa_s->dpp_pb_bi);
5683 if (!wpa_s->dpp_pb_announcement)
5684 return -1;
5685
5686 wpa_printf(MSG_DEBUG,
5687 "DPP: Scan to create channel list for PB discovery");
5688 wpa_s->scan_req = MANUAL_SCAN_REQ;
5689 wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
5690 wpa_supplicant_req_scan(wpa_s, 0, 0);
5691 return 0;
5692}
5693
5694
5695void wpas_dpp_push_button_stop(struct wpa_supplicant *wpa_s)
5696{
5697 if (!wpa_s->dpp)
5698 return;
5699 os_free(wpa_s->dpp_pb_freqs);
5700 wpa_s->dpp_pb_freqs = NULL;
5701 wpabuf_free(wpa_s->dpp_pb_announcement);
5702 wpa_s->dpp_pb_announcement = NULL;
5703 if (wpa_s->dpp_pb_bi) {
5704 char id[20];
5705
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005706 if (wpa_s->dpp_pb_bi == wpa_s->dpp_pkex_bi)
5707 wpa_s->dpp_pkex_bi = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005708 os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
5709 dpp_bootstrap_remove(wpa_s->dpp, id);
5710 wpa_s->dpp_pb_bi = NULL;
5711 if (!wpa_s->dpp_pb_result_indicated) {
5712 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5713 wpa_s->dpp_pb_result_indicated = true;
5714 }
5715 }
5716
5717 wpa_s->dpp_pb_resp_freq = 0;
5718 wpa_s->dpp_pb_stop_iter = 0;
5719 wpa_s->dpp_pb_discovery_done = false;
5720 os_free(wpa_s->dpp_pb_cmd);
5721 wpa_s->dpp_pb_cmd = NULL;
5722
5723 eloop_cancel_timeout(wpas_dpp_pb_next, wpa_s, NULL);
5724 eloop_cancel_timeout(wpas_dpp_push_button_expire, wpa_s, NULL);
5725 if (wpas_dpp_pb_active(wpa_s)) {
5726 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
5727 if (!wpa_s->dpp_pb_result_indicated)
5728 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5729 }
5730 wpa_s->dpp_pb_time.sec = 0;
5731 wpa_s->dpp_pb_time.usec = 0;
5732 dpp_pkex_free(wpa_s->dpp_pkex);
5733 wpa_s->dpp_pkex = NULL;
5734 os_free(wpa_s->dpp_pkex_auth_cmd);
5735 wpa_s->dpp_pkex_auth_cmd = NULL;
5736
5737 wpa_s->dpp_pb_result_indicated = false;
5738
5739 str_clear_free(wpa_s->dpp_pb_cmd);
5740 wpa_s->dpp_pb_cmd = NULL;
5741
5742 if (wpa_s->scan_res_handler == wpas_dpp_pb_scan_res_handler) {
5743 wpas_abort_ongoing_scan(wpa_s);
5744 wpa_s->scan_res_handler = NULL;
5745 }
5746}
5747
5748#endif /* CONFIG_DPP3 */