blob: 4f5be0a506e085ead8b0549d78138047b9f41075 [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);
608 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
609 }
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
1262 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);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001265 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);
1270}
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) ||
1803 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
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
Hai Shalomc3565922019-10-28 11:58:20 -07001938 supp_op_classes = wpas_supp_op_classes(wpa_s);
1939 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001940 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001941 wpa_s->conf->dpp_mud_url,
Sunil Ravi89eba102022-09-13 21:04:37 -07001942 supp_op_classes,
1943 wpa_s->conf->dpp_extra_conf_req_name,
1944 wpa_s->conf->dpp_extra_conf_req_value);
Hai Shalomc3565922019-10-28 11:58:20 -07001945 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001946 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001947 wpa_printf(MSG_DEBUG,
1948 "DPP: No configuration request data available");
1949 return;
1950 }
1951
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001952 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1953 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1954
Hai Shaloma20dcd72022-02-04 13:43:00 -08001955 /* Use a 120 second timeout since the gas_query_req() operation could
1956 * remain waiting indefinitely for the response if the Configurator
1957 * keeps sending out comeback responses with additional delay. The
1958 * DPP technical specification expects the Enrollee to continue sending
1959 * out new Config Requests for 60 seconds, so this gives an extra 60
1960 * second time after the last expected new Config Request for the
1961 * Configurator to determine what kind of configuration to provide. */
1962 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
1963 wpa_s, NULL);
1964
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001965 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001966 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001967 if (res < 0) {
1968 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1969 wpabuf_free(buf);
1970 } else {
1971 wpa_printf(MSG_DEBUG,
1972 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001973 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001974 }
1975}
1976
1977
1978static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1979{
1980 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001981 dpp_notify_auth_success(wpa_s->dpp_auth, initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001982 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001983#ifdef CONFIG_TESTING_OPTIONS
1984 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1985 wpa_printf(MSG_INFO,
1986 "DPP: TESTING - stop at Authentication Confirm");
1987 if (wpa_s->dpp_auth->configurator) {
1988 /* Prevent GAS response */
1989 wpa_s->dpp_auth->auth_success = 0;
1990 }
1991 return;
1992 }
1993#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001994
1995 if (wpa_s->dpp_auth->configurator)
1996 wpas_dpp_start_gas_server(wpa_s);
1997 else
1998 wpas_dpp_start_gas_client(wpa_s);
1999}
2000
2001
2002static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002003 const u8 *hdr, const u8 *buf, size_t len,
2004 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002005{
2006 struct dpp_authentication *auth = wpa_s->dpp_auth;
2007 struct wpabuf *msg;
2008
Roshan Pius3a1667e2018-07-03 15:17:14 -07002009 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
2010 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002011
2012 if (!auth) {
2013 wpa_printf(MSG_DEBUG,
2014 "DPP: No DPP Authentication in progress - drop");
2015 return;
2016 }
2017
2018 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
2019 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2020 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2021 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2022 return;
2023 }
2024
2025 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
2026
Roshan Pius3a1667e2018-07-03 15:17:14 -07002027 if (auth->curr_freq != freq && auth->neg_freq == freq) {
2028 wpa_printf(MSG_DEBUG,
2029 "DPP: Responder accepted request for different negotiation channel");
2030 auth->curr_freq = freq;
2031 }
2032
2033 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002034 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
2035 if (!msg) {
2036 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
2037 wpa_printf(MSG_DEBUG,
2038 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08002039 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002040 offchannel_send_action_done(wpa_s);
2041 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
2042 return;
2043 }
2044 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
2045 return;
2046 }
2047 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2048
Roshan Pius3a1667e2018-07-03 15:17:14 -07002049 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2050 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002051 offchannel_send_action(wpa_s, auth->curr_freq,
2052 src, wpa_s->own_addr, broadcast,
2053 wpabuf_head(msg), wpabuf_len(msg),
2054 500, wpas_dpp_tx_status, 0);
2055 wpabuf_free(msg);
2056 wpa_s->dpp_auth_ok_on_ack = 1;
2057}
2058
2059
2060static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2061 const u8 *hdr, const u8 *buf, size_t len)
2062{
2063 struct dpp_authentication *auth = wpa_s->dpp_auth;
2064
2065 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
2066 MAC2STR(src));
2067
2068 if (!auth) {
2069 wpa_printf(MSG_DEBUG,
2070 "DPP: No DPP Authentication in progress - drop");
2071 return;
2072 }
2073
2074 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2075 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2076 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2077 return;
2078 }
2079
Hai Shalom60840252021-02-19 19:02:11 -08002080 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
2081
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002082 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
2083 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08002084 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002085 return;
2086 }
2087
2088 wpas_dpp_auth_success(wpa_s, 0);
2089}
2090
2091
Hai Shalom021b0b52019-04-10 11:17:58 -07002092#ifdef CONFIG_DPP2
2093
2094static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
2095 void *timeout_ctx)
2096{
2097 struct wpa_supplicant *wpa_s = eloop_ctx;
2098 struct dpp_authentication *auth = wpa_s->dpp_auth;
2099
2100 if (!auth || !auth->waiting_conf_result)
2101 return;
2102
2103 wpa_printf(MSG_DEBUG,
2104 "DPP: Timeout while waiting for Configuration Result");
2105 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002106 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002107 dpp_auth_deinit(auth);
2108 wpa_s->dpp_auth = NULL;
2109}
2110
2111
Hai Shalomc3565922019-10-28 11:58:20 -07002112static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2113 void *timeout_ctx)
2114{
2115 struct wpa_supplicant *wpa_s = eloop_ctx;
2116 struct dpp_authentication *auth = wpa_s->dpp_auth;
2117
2118 if (!auth || !auth->waiting_conn_status_result)
2119 return;
2120
2121 wpa_printf(MSG_DEBUG,
2122 "DPP: Timeout while waiting for Connection Status Result");
2123 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002124 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002125 wpas_dpp_listen_stop(wpa_s);
2126 dpp_auth_deinit(auth);
2127 wpa_s->dpp_auth = NULL;
2128}
2129
2130
Sunil Ravi89eba102022-09-13 21:04:37 -07002131#ifdef CONFIG_DPP3
2132
2133static bool wpas_dpp_pb_active(struct wpa_supplicant *wpa_s)
2134{
2135 return (wpa_s->dpp_pb_time.sec || wpa_s->dpp_pb_time.usec) &&
2136 wpa_s->dpp_pb_configurator;
2137}
2138
2139
2140static void wpas_dpp_remove_pb_hash(struct wpa_supplicant *wpa_s)
2141{
2142 int i;
2143
2144 if (!wpa_s->dpp_pb_bi)
2145 return;
2146 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2147 struct dpp_pb_info *info = &wpa_s->dpp_pb[i];
2148
2149 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
2150 continue;
2151 if (os_memcmp(info->hash, wpa_s->dpp_pb_resp_hash,
2152 SHA256_MAC_LEN) == 0) {
2153 /* Allow a new push button session to be established
2154 * immediately without the successfully completed
2155 * session triggering session overlap. */
2156 info->rx_time.sec = 0;
2157 info->rx_time.usec = 0;
2158 wpa_printf(MSG_DEBUG,
2159 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
2160 }
2161 }
2162}
2163
2164#endif /* CONFIG_DPP3 */
2165
2166
Hai Shalom021b0b52019-04-10 11:17:58 -07002167static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2168 const u8 *hdr, const u8 *buf, size_t len)
2169{
2170 struct dpp_authentication *auth = wpa_s->dpp_auth;
2171 enum dpp_status_error status;
2172
2173 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2174 MAC2STR(src));
2175
2176 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002177 if (auth &&
2178 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
2179 gas_server_response_sent(wpa_s->gas_server,
2180 auth->gas_server_ctx)) {
2181 /* This could happen if the TX status event gets delayed
2182 * long enough for the Enrollee to have time to send
2183 * the next frame before the TX status gets processed
2184 * locally. */
2185 wpa_printf(MSG_DEBUG,
2186 "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");
2187 auth->waiting_conf_result = 1;
2188 } else {
2189 wpa_printf(MSG_DEBUG,
2190 "DPP: No DPP Configuration waiting for result - drop");
2191 return;
2192 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002193 }
2194
2195 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2196 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2197 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2198 return;
2199 }
2200
2201 status = dpp_conf_result_rx(auth, hdr, buf, len);
2202
Hai Shalomc3565922019-10-28 11:58:20 -07002203 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002204 int freq;
2205
Hai Shalomc3565922019-10-28 11:58:20 -07002206 wpa_msg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07002207 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
2208 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07002209 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002210 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002211 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2212 wpa_s, NULL);
2213 auth->waiting_conn_status_result = 1;
2214 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2215 wpa_s, NULL);
2216 eloop_register_timeout(16, 0,
2217 wpas_dpp_conn_status_result_wait_timeout,
2218 wpa_s, NULL);
2219 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002220 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2221 if (!wpa_s->dpp_in_response_listen ||
2222 (int) wpa_s->dpp_listen_freq != freq)
2223 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002224 return;
2225 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002226 offchannel_send_action_done(wpa_s);
2227 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002228 if (status == DPP_STATUS_OK) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002229 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
2230 auth->conf_resp_status);
Hai Shalome4073332019-11-05 16:20:12 -08002231 wpas_notify_dpp_config_sent(wpa_s);
2232 }
2233 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002234 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002235 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002236 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002237 dpp_auth_deinit(auth);
2238 wpa_s->dpp_auth = NULL;
2239 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07002240#ifdef CONFIG_DPP3
2241 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
2242 if (status == DPP_STATUS_OK)
2243 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2244 "success");
2245 else
2246 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2247 "no-configuration-available");
2248 wpa_s->dpp_pb_result_indicated = true;
2249 if (status == DPP_STATUS_OK)
2250 wpas_dpp_remove_pb_hash(wpa_s);
2251 wpas_dpp_push_button_stop(wpa_s);
2252 }
2253#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002254}
2255
Hai Shalom81f62d82019-07-22 12:10:00 -07002256
Hai Shalomc3565922019-10-28 11:58:20 -07002257static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2258 const u8 *src, const u8 *hdr,
2259 const u8 *buf, size_t len)
2260{
2261 struct dpp_authentication *auth = wpa_s->dpp_auth;
2262 enum dpp_status_error status;
2263 u8 ssid[SSID_MAX_LEN];
2264 size_t ssid_len = 0;
2265 char *channel_list = NULL;
2266
2267 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2268
2269 if (!auth || !auth->waiting_conn_status_result) {
2270 wpa_printf(MSG_DEBUG,
2271 "DPP: No DPP Configuration waiting for connection status result - drop");
2272 return;
2273 }
2274
2275 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2276 ssid, &ssid_len, &channel_list);
2277 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2278 "result=%d ssid=%s channel_list=%s",
2279 status, wpa_ssid_txt(ssid, ssid_len),
2280 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002281 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2282 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002283 os_free(channel_list);
2284 offchannel_send_action_done(wpa_s);
2285 wpas_dpp_listen_stop(wpa_s);
2286 dpp_auth_deinit(auth);
2287 wpa_s->dpp_auth = NULL;
2288 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2289 wpa_s, NULL);
2290}
2291
2292
Hai Shalom81f62d82019-07-22 12:10:00 -07002293static int wpas_dpp_process_conf_obj(void *ctx,
2294 struct dpp_authentication *auth)
2295{
2296 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002297 unsigned int i;
2298 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002299
Hai Shalomc3565922019-10-28 11:58:20 -07002300 for (i = 0; i < auth->num_conf_obj; i++) {
2301 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2302 &auth->conf_obj[i]);
2303 if (res)
2304 break;
2305 }
2306 if (!res)
2307 wpas_dpp_post_process_config(wpa_s, auth);
2308
2309 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002310}
2311
Hai Shalomfdcde762020-04-02 11:19:20 -07002312
Hai Shaloma20dcd72022-02-04 13:43:00 -08002313static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2314{
2315 struct wpa_supplicant *wpa_s = ctx;
2316
2317 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2318
2319 if (auth->connect_on_tx_status) {
2320 auth->connect_on_tx_status = 0;
2321 wpa_printf(MSG_DEBUG,
2322 "DPP: Try to connect after completed configuration result");
2323 wpas_dpp_try_to_connect(wpa_s);
2324 if (auth->conn_status_requested) {
2325 wpa_printf(MSG_DEBUG,
2326 "DPP: Start 15 second timeout for reporting connection status result");
2327 eloop_cancel_timeout(
2328 wpas_dpp_conn_status_result_timeout,
2329 wpa_s, NULL);
2330 eloop_register_timeout(
2331 15, 0, wpas_dpp_conn_status_result_timeout,
2332 wpa_s, NULL);
2333 return true;
2334 }
2335 }
2336
2337 return false;
2338}
2339
2340
Hai Shalomfdcde762020-04-02 11:19:20 -07002341static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2342{
2343 struct wpa_supplicant *wpa_s = ctx;
2344
2345 if (bi == wpa_s->dpp_chirp_bi)
2346 wpas_dpp_chirp_stop(wpa_s);
2347}
2348
2349
2350static void
2351wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2352 const u8 *hdr, const u8 *buf, size_t len,
2353 unsigned int freq)
2354{
2355 const u8 *r_bootstrap;
2356 u16 r_bootstrap_len;
2357 struct dpp_bootstrap_info *peer_bi;
2358 struct dpp_authentication *auth;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002359 unsigned int wait_time, max_wait_time;
Hai Shalomfdcde762020-04-02 11:19:20 -07002360
2361 if (!wpa_s->dpp)
2362 return;
2363
2364 if (wpa_s->dpp_auth) {
2365 wpa_printf(MSG_DEBUG,
2366 "DPP: Ignore Presence Announcement during ongoing Authentication");
2367 return;
2368 }
2369
2370 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2371 MAC2STR(src));
2372
2373 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2374 &r_bootstrap_len);
2375 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2376 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2377 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2378 return;
2379 }
2380 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2381 r_bootstrap, r_bootstrap_len);
2382 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002383 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2384 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002385 if (!peer_bi) {
2386 wpa_printf(MSG_DEBUG,
2387 "DPP: No matching bootstrapping information found");
2388 return;
2389 }
2390
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002391 wpa_printf(MSG_DEBUG, "DPP: Start Authentication exchange with " MACSTR
2392 " based on the received Presence Announcement",
2393 MAC2STR(src));
Hai Shalomfdcde762020-04-02 11:19:20 -07002394 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2395 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2396 if (!auth)
2397 return;
2398 wpas_dpp_set_testing_options(wpa_s, auth);
2399 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2400 dpp_auth_deinit(auth);
2401 return;
2402 }
2403
2404 auth->neg_freq = freq;
2405
Hai Shalom60840252021-02-19 19:02:11 -08002406 /* The source address of the Presence Announcement frame overrides any
2407 * MAC address information from the bootstrapping information. */
2408 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002409
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002410 wait_time = wpa_s->max_remain_on_chan;
2411 max_wait_time = wpa_s->dpp_resp_wait_time ?
2412 wpa_s->dpp_resp_wait_time : 2000;
2413 if (wait_time > max_wait_time)
2414 wait_time = max_wait_time;
2415 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2416
Hai Shalomfdcde762020-04-02 11:19:20 -07002417 wpa_s->dpp_auth = auth;
2418 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2419 dpp_auth_deinit(wpa_s->dpp_auth);
2420 wpa_s->dpp_auth = NULL;
2421 }
2422}
2423
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002424
2425static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2426 void *timeout_ctx)
2427{
2428 struct wpa_supplicant *wpa_s = eloop_ctx;
2429 struct dpp_authentication *auth = wpa_s->dpp_auth;
2430
2431 if (!auth)
2432 return;
2433
2434 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2435 offchannel_send_action_done(wpa_s);
2436 wpas_dpp_listen_stop(wpa_s);
2437 dpp_auth_deinit(auth);
2438 wpa_s->dpp_auth = NULL;
2439}
2440
2441
2442static void
2443wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2444 const u8 *hdr, const u8 *buf, size_t len,
2445 unsigned int freq)
2446{
Hai Shalom899fcc72020-10-19 14:38:18 -07002447 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2448 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002449 struct dpp_configurator *conf;
2450 struct dpp_authentication *auth;
2451 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002452 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002453
2454 if (!wpa_s->dpp)
2455 return;
2456
2457 if (wpa_s->dpp_auth) {
2458 wpa_printf(MSG_DEBUG,
2459 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2460 return;
2461 }
2462
2463 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2464 MAC2STR(src));
2465
2466 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2467 &csign_hash_len);
2468 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2469 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2470 "Missing or invalid required Configurator C-sign key Hash attribute");
2471 return;
2472 }
2473 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2474 csign_hash, csign_hash_len);
2475 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2476 if (!conf) {
2477 wpa_printf(MSG_DEBUG,
2478 "DPP: No matching Configurator information found");
2479 return;
2480 }
2481
Hai Shalom899fcc72020-10-19 14:38:18 -07002482 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2483 &fcgroup_len);
2484 if (!fcgroup || fcgroup_len != 2) {
2485 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2486 "Missing or invalid required Finite Cyclic Group attribute");
2487 return;
2488 }
2489 group = WPA_GET_LE16(fcgroup);
2490 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2491
2492 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2493 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2494
2495 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2496 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002497 if (!auth)
2498 return;
2499 wpas_dpp_set_testing_options(wpa_s, auth);
2500 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2501 dpp_auth_deinit(auth);
2502 return;
2503 }
2504
2505 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2506 wpa_s->dpp_auth = auth;
2507
2508 wpa_s->dpp_in_response_listen = 0;
2509 wpa_s->dpp_auth_ok_on_ack = 0;
2510 wait_time = wpa_s->max_remain_on_chan;
2511 max_wait_time = wpa_s->dpp_resp_wait_time ?
2512 wpa_s->dpp_resp_wait_time : 2000;
2513 if (wait_time > max_wait_time)
2514 wait_time = max_wait_time;
2515 wait_time += 10; /* give the driver some extra time to complete */
2516 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2517 wpas_dpp_reconfig_reply_wait_timeout,
2518 wpa_s, NULL);
2519 wait_time -= 10;
2520
2521 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2522
2523 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2524 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2525 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2526 wpabuf_head(auth->reconfig_req_msg),
2527 wpabuf_len(auth->reconfig_req_msg),
2528 wait_time, wpas_dpp_tx_status, 0) < 0) {
2529 dpp_auth_deinit(wpa_s->dpp_auth);
2530 wpa_s->dpp_auth = NULL;
2531 }
2532}
2533
2534
2535static void
2536wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2537 const u8 *hdr, const u8 *buf, size_t len,
2538 unsigned int freq)
2539{
2540 struct wpa_ssid *ssid;
2541 struct dpp_authentication *auth;
2542
2543 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2544 MACSTR, MAC2STR(src));
2545
Hai Shalom899fcc72020-10-19 14:38:18 -07002546 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002547 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002548 if (wpa_s->dpp_auth) {
2549 wpa_printf(MSG_DEBUG,
2550 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2551 return;
2552 }
2553 if (!wpa_s->dpp_reconfig_ssid) {
2554 wpa_printf(MSG_DEBUG,
2555 "DPP: Not ready for reconfiguration - not requested");
2556 return;
2557 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002558 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2559 if (ssid == wpa_s->dpp_reconfig_ssid &&
2560 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2561 break;
2562 }
2563 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002564 !ssid->dpp_csign) {
2565 wpa_printf(MSG_DEBUG,
2566 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002567 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002568 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002569
2570 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2571 ssid->dpp_netaccesskey,
2572 ssid->dpp_netaccesskey_len,
2573 ssid->dpp_csign, ssid->dpp_csign_len,
2574 freq, hdr, buf, len);
2575 if (!auth)
2576 return;
2577 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2578 wpa_s->dpp_auth = auth;
2579
2580 wpas_dpp_chirp_stop(wpa_s);
2581
2582 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2583 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2584 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2585 wpabuf_head(auth->reconfig_resp_msg),
2586 wpabuf_len(auth->reconfig_resp_msg),
2587 500, wpas_dpp_tx_status, 0) < 0) {
2588 dpp_auth_deinit(wpa_s->dpp_auth);
2589 wpa_s->dpp_auth = NULL;
2590 }
2591}
2592
2593
2594static void
2595wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2596 const u8 *hdr, const u8 *buf, size_t len,
2597 unsigned int freq)
2598{
2599 struct dpp_authentication *auth = wpa_s->dpp_auth;
2600 struct wpabuf *conf;
2601
2602 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2603 MACSTR, MAC2STR(src));
2604
2605 if (!auth || !auth->reconfig || !auth->configurator) {
2606 wpa_printf(MSG_DEBUG,
2607 "DPP: No DPP Reconfig Authentication in progress - drop");
2608 return;
2609 }
2610
2611 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2612 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2613 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2614 return;
2615 }
2616
2617 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2618 if (!conf)
2619 return;
2620
2621 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2622
2623 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2624 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2625 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2626 wpabuf_head(conf), wpabuf_len(conf),
2627 500, wpas_dpp_tx_status, 0) < 0) {
2628 wpabuf_free(conf);
2629 dpp_auth_deinit(wpa_s->dpp_auth);
2630 wpa_s->dpp_auth = NULL;
2631 return;
2632 }
2633 wpabuf_free(conf);
2634
2635 wpas_dpp_start_gas_server(wpa_s);
2636}
2637
2638
2639static void
2640wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2641 const u8 *hdr, const u8 *buf, size_t len,
2642 unsigned int freq)
2643{
2644 struct dpp_authentication *auth = wpa_s->dpp_auth;
2645
2646 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2647 MACSTR, MAC2STR(src));
2648
2649 if (!auth || !auth->reconfig || auth->configurator) {
2650 wpa_printf(MSG_DEBUG,
2651 "DPP: No DPP Reconfig Authentication in progress - drop");
2652 return;
2653 }
2654
2655 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2656 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2657 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2658 return;
2659 }
2660
2661 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2662 return;
2663
2664 wpas_dpp_start_gas_client(wpa_s);
2665}
2666
Hai Shalom021b0b52019-04-10 11:17:58 -07002667#endif /* CONFIG_DPP2 */
2668
2669
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002670static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2671 const u8 *src,
2672 const u8 *buf, size_t len)
2673{
2674 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002675 const u8 *connector, *trans_id, *status;
2676 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002677#ifdef CONFIG_DPP2
2678 const u8 *version;
2679 u16 version_len;
2680#endif /* CONFIG_DPP2 */
2681 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002682 struct dpp_introduction intro;
2683 struct rsn_pmksa_cache_entry *entry;
2684 struct os_time now;
2685 struct os_reltime rnow;
2686 os_time_t expiry;
2687 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002688 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002689
2690 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2691 MAC2STR(src));
2692 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2693 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2694 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2695 MACSTR " - drop", MAC2STR(src));
2696 return;
2697 }
2698 offchannel_send_action_done(wpa_s);
2699
2700 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2701 if (ssid == wpa_s->dpp_intro_network)
2702 break;
2703 }
2704 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2705 !ssid->dpp_csign) {
2706 wpa_printf(MSG_DEBUG,
2707 "DPP: Profile not found for network introduction");
2708 return;
2709 }
2710
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002711 os_memset(&intro, 0, sizeof(intro));
2712
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002713 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2714 &trans_id_len);
2715 if (!trans_id || trans_id_len != 1) {
2716 wpa_printf(MSG_DEBUG,
2717 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002718 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2719 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002720 goto fail;
2721 }
2722 if (trans_id[0] != TRANSACTION_ID) {
2723 wpa_printf(MSG_DEBUG,
2724 "DPP: Ignore frame with unexpected Transaction ID %u",
2725 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002726 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2727 " fail=transaction_id_mismatch", MAC2STR(src));
2728 goto fail;
2729 }
2730
2731 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2732 if (!status || status_len != 1) {
2733 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2734 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2735 " fail=missing_status", MAC2STR(src));
2736 goto fail;
2737 }
2738 if (status[0] != DPP_STATUS_OK) {
2739 wpa_printf(MSG_DEBUG,
2740 "DPP: Peer rejected network introduction: Status %u",
2741 status[0]);
2742 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2743 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002744#ifdef CONFIG_DPP2
2745 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2746#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002747 goto fail;
2748 }
2749
2750 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2751 if (!connector) {
2752 wpa_printf(MSG_DEBUG,
2753 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002754 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2755 " fail=missing_connector", MAC2STR(src));
2756 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002757 }
2758
Roshan Pius3a1667e2018-07-03 15:17:14 -07002759 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2760 ssid->dpp_netaccesskey,
2761 ssid->dpp_netaccesskey_len,
2762 ssid->dpp_csign,
2763 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002764 connector, connector_len, &expiry, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002765 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002766 wpa_printf(MSG_INFO,
2767 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002768 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2769 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002770#ifdef CONFIG_DPP2
2771 wpas_dpp_send_conn_status_result(wpa_s, res);
2772#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002773 goto fail;
2774 }
2775
2776 entry = os_zalloc(sizeof(*entry));
2777 if (!entry)
2778 goto fail;
2779 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002780 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002781 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2782 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2783 entry->pmk_len = intro.pmk_len;
2784 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002785#ifdef CONFIG_DPP2
2786 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2787 &version_len);
2788 if (version && version_len >= 1)
2789 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002790#ifdef CONFIG_DPP3
2791 if (intro.peer_version && intro.peer_version >= 2 &&
2792 peer_version != intro.peer_version) {
2793 wpa_printf(MSG_INFO,
2794 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2795 intro.peer_version, peer_version);
2796 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2797 goto fail;
2798 }
2799#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002800 entry->dpp_pfs = peer_version >= 2;
2801#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002802 if (expiry) {
2803 os_get_time(&now);
2804 seconds = expiry - now.sec;
2805 } else {
2806 seconds = 86400 * 7;
2807 }
2808 os_get_reltime(&rnow);
2809 entry->expiration = rnow.sec + seconds;
2810 entry->reauth_time = rnow.sec + seconds;
2811 entry->network_ctx = ssid;
2812 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2813
Roshan Pius3a1667e2018-07-03 15:17:14 -07002814 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002815 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002816
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002817 wpa_printf(MSG_DEBUG,
2818 "DPP: Try connection again after successful network introduction");
2819 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2820 wpa_supplicant_cancel_sched_scan(wpa_s);
2821 wpa_supplicant_req_scan(wpa_s, 0, 0);
2822 }
2823fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002824 dpp_peer_intro_deinit(&intro);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002825}
2826
2827
Roshan Pius3a1667e2018-07-03 15:17:14 -07002828static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2829{
2830 int i, j;
2831
2832 if (!wpa_s->hw.modes)
2833 return -1;
2834
2835 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2836 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2837
2838 for (j = 0; j < mode->num_channels; j++) {
2839 struct hostapd_channel_data *chan = &mode->channels[j];
2840
2841 if (chan->freq != (int) freq)
2842 continue;
2843
2844 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2845 HOSTAPD_CHAN_NO_IR |
2846 HOSTAPD_CHAN_RADAR))
2847 continue;
2848
2849 return 1;
2850 }
2851 }
2852
2853 wpa_printf(MSG_DEBUG,
2854 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2855 freq);
2856
2857 return 0;
2858}
2859
2860
2861static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2862 struct dpp_pkex *pkex)
2863{
2864 if (pkex->freq == 2437)
2865 pkex->freq = 5745;
2866 else if (pkex->freq == 5745)
2867 pkex->freq = 5220;
2868 else if (pkex->freq == 5220)
2869 pkex->freq = 60480;
2870 else
2871 return -1; /* no more channels to try */
2872
2873 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2874 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2875 pkex->freq);
2876 return 0;
2877 }
2878
2879 /* Could not use this channel - try the next one */
2880 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2881}
2882
2883
Sunil Ravi89eba102022-09-13 21:04:37 -07002884static void wpas_dpp_pkex_clear_code(struct wpa_supplicant *wpa_s)
2885{
2886 if (!wpa_s->dpp_pkex_code && !wpa_s->dpp_pkex_identifier)
2887 return;
2888
2889 /* Delete PKEX code and identifier on successful completion of
2890 * PKEX. We are not supposed to reuse these without being
2891 * explicitly requested to perform PKEX again. */
2892 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
2893 os_free(wpa_s->dpp_pkex_code);
2894 wpa_s->dpp_pkex_code = NULL;
2895 os_free(wpa_s->dpp_pkex_identifier);
2896 wpa_s->dpp_pkex_identifier = NULL;
2897
2898}
2899
2900
Hai Shaloma20dcd72022-02-04 13:43:00 -08002901#ifdef CONFIG_DPP2
2902static int wpas_dpp_pkex_done(void *ctx, void *conn,
2903 struct dpp_bootstrap_info *peer_bi)
2904{
2905 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -07002906 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002907 const char *pos;
2908 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2909 struct dpp_bootstrap_info *own_bi = NULL;
2910 struct dpp_authentication *auth;
2911
Sunil Ravi89eba102022-09-13 21:04:37 -07002912 wpas_dpp_pkex_clear_code(wpa_s);
2913
2914 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
2915 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002916 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
2917 cmd);
2918
2919 pos = os_strstr(cmd, " own=");
2920 if (pos) {
2921 pos += 5;
2922 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
2923 if (!own_bi) {
2924 wpa_printf(MSG_INFO,
2925 "DPP: Could not find bootstrapping info for the identified local entry");
2926 return -1;
2927 }
2928
2929 if (peer_bi->curve != own_bi->curve) {
2930 wpa_printf(MSG_INFO,
2931 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
2932 peer_bi->curve->name, own_bi->curve->name);
2933 return -1;
2934 }
2935 }
2936
2937 pos = os_strstr(cmd, " role=");
2938 if (pos) {
2939 pos += 6;
2940 if (os_strncmp(pos, "configurator", 12) == 0)
2941 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2942 else if (os_strncmp(pos, "enrollee", 8) == 0)
2943 allowed_roles = DPP_CAPAB_ENROLLEE;
2944 else if (os_strncmp(pos, "either", 6) == 0)
2945 allowed_roles = DPP_CAPAB_CONFIGURATOR |
2946 DPP_CAPAB_ENROLLEE;
2947 else
2948 return -1;
2949 }
2950
2951 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
2952 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
2953 if (!auth)
2954 return -1;
2955
2956 wpas_dpp_set_testing_options(wpa_s, auth);
2957 if (dpp_set_configurator(auth, cmd) < 0) {
2958 dpp_auth_deinit(auth);
2959 return -1;
2960 }
2961
2962 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -07002963 DPP_NETROLE_STA,
2964 wpa_s->conf->dpp_mud_url,
2965 wpa_s->conf->dpp_extra_conf_req_name,
2966 wpa_s->conf->dpp_extra_conf_req_value,
2967 wpas_dpp_process_conf_obj,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002968 wpas_dpp_tcp_msg_sent);
2969}
2970#endif /* CONFIG_DPP2 */
2971
2972
Hai Shaloma20dcd72022-02-04 13:43:00 -08002973static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07002974 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002975 const struct hostapd_ip_addr *ipaddr,
2976 int tcp_port)
2977{
2978 struct dpp_pkex *pkex;
2979 struct wpabuf *msg;
2980 unsigned int wait_time;
2981 bool v2 = ver != PKEX_VER_ONLY_1;
2982
2983 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
2984 dpp_pkex_free(wpa_s->dpp_pkex);
2985 wpa_s->dpp_pkex = NULL;
2986 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
2987 wpa_s->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -07002988 wpa_s->dpp_pkex_code, wpa_s->dpp_pkex_code_len,
2989 v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002990 if (!pkex)
2991 return -1;
2992 pkex->forced_ver = ver != PKEX_VER_AUTO;
2993
2994 if (ipaddr) {
2995#ifdef CONFIG_DPP2
2996 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
2997 wpa_s, wpa_s, wpas_dpp_pkex_done);
2998#else /* CONFIG_DPP2 */
2999 return -1;
3000#endif /* CONFIG_DPP2 */
3001 }
3002
3003 wpa_s->dpp_pkex = pkex;
3004 msg = pkex->exchange_req;
3005 wait_time = wpa_s->max_remain_on_chan;
3006 if (wait_time > 2000)
3007 wait_time = 2000;
3008 pkex->freq = 2437;
3009 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3010 " freq=%u type=%d",
3011 MAC2STR(broadcast), pkex->freq,
3012 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3013 DPP_PA_PKEX_V1_EXCHANGE_REQ);
3014 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3015 wpa_s->own_addr, broadcast,
3016 wpabuf_head(msg), wpabuf_len(msg),
3017 wait_time, wpas_dpp_tx_pkex_status, 0);
3018 if (wait_time == 0)
3019 wait_time = 2000;
3020 pkex->exch_req_wait_time = wait_time;
3021 pkex->exch_req_tries = 1;
3022
3023 return 0;
3024}
3025
3026
Roshan Pius3a1667e2018-07-03 15:17:14 -07003027static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
3028{
3029 struct wpa_supplicant *wpa_s = eloop_ctx;
3030 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3031
3032 if (!pkex || !pkex->exchange_req)
3033 return;
3034 if (pkex->exch_req_tries >= 5) {
3035 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003036#ifdef CONFIG_DPP3
3037 if (pkex->v2 && !pkex->forced_ver) {
3038 wpa_printf(MSG_DEBUG,
3039 "DPP: Fall back to PKEXv1");
3040 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
3041 NULL, 0);
3042 return;
3043 }
3044#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003045 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
3046 "No response from PKEX peer");
3047 dpp_pkex_free(pkex);
3048 wpa_s->dpp_pkex = NULL;
3049 return;
3050 }
3051 pkex->exch_req_tries = 0;
3052 }
3053
3054 pkex->exch_req_tries++;
3055 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
3056 pkex->exch_req_tries);
3057 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08003058 MAC2STR(broadcast), pkex->freq,
3059 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3060 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003061 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3062 wpa_s->own_addr, broadcast,
3063 wpabuf_head(pkex->exchange_req),
3064 wpabuf_len(pkex->exchange_req),
3065 pkex->exch_req_wait_time,
3066 wpas_dpp_tx_pkex_status, 0);
3067}
3068
3069
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003070static void
3071wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
3072 unsigned int freq, const u8 *dst,
3073 const u8 *src, const u8 *bssid,
3074 const u8 *data, size_t data_len,
3075 enum offchannel_send_action_result result)
3076{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003077 const char *res_txt;
3078 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3079
3080 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3081 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3082 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003083 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3084 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003085 freq, MAC2STR(dst), res_txt);
3086 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3087 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3088
3089 if (!pkex) {
3090 wpa_printf(MSG_DEBUG,
3091 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
3092 return;
3093 }
3094
3095 if (pkex->failed) {
3096 wpa_printf(MSG_DEBUG,
3097 "DPP: Terminate PKEX exchange due to an earlier error");
3098 if (pkex->t > pkex->own_bi->pkex_t)
3099 pkex->own_bi->pkex_t = pkex->t;
3100 dpp_pkex_free(pkex);
3101 wpa_s->dpp_pkex = NULL;
3102 return;
3103 }
3104
3105 if (pkex->exch_req_wait_time && pkex->exchange_req) {
3106 /* Wait for PKEX Exchange Response frame and retry request if
3107 * no response is seen. */
3108 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3109 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
3110 (pkex->exch_req_wait_time % 1000) * 1000,
3111 wpas_dpp_pkex_retry_timeout, wpa_s,
3112 NULL);
3113 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003114}
3115
3116
3117static void
3118wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003119 const u8 *buf, size_t len, unsigned int freq,
3120 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003121{
3122 struct wpabuf *msg;
3123 unsigned int wait_time;
3124
3125 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
3126 MAC2STR(src));
3127
Sunil Ravia04bd252022-05-02 22:54:18 -07003128 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
3129 wpa_printf(MSG_DEBUG,
3130 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
3131 return;
3132 }
3133 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
3134 wpa_printf(MSG_DEBUG,
3135 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
3136 return;
3137 }
3138
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003139 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3140 * values here */
3141
3142 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
3143 wpa_printf(MSG_DEBUG,
3144 "DPP: No PKEX code configured - ignore request");
3145 return;
3146 }
3147
Sunil Ravi89eba102022-09-13 21:04:37 -07003148#ifdef CONFIG_DPP2
3149 if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) {
3150 wpa_printf(MSG_DEBUG,
3151 "DPP: PKEX Exchange Request is from local Controller - ignore request");
3152 return;
3153 }
3154#endif /* CONFIG_DPP2 */
3155
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003156 if (wpa_s->dpp_pkex) {
3157 /* TODO: Support parallel operations */
3158 wpa_printf(MSG_DEBUG,
3159 "DPP: Already in PKEX session - ignore new request");
3160 return;
3161 }
3162
Roshan Pius3a1667e2018-07-03 15:17:14 -07003163 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003164 wpa_s->own_addr, src,
3165 wpa_s->dpp_pkex_identifier,
3166 wpa_s->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07003167 wpa_s->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003168 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003169 if (!wpa_s->dpp_pkex) {
3170 wpa_printf(MSG_DEBUG,
3171 "DPP: Failed to process the request - ignore it");
3172 return;
3173 }
3174
Sunil Ravi89eba102022-09-13 21:04:37 -07003175#ifdef CONFIG_DPP3
3176 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_announcement) {
3177 wpa_printf(MSG_DEBUG,
3178 "DPP: Started PB PKEX (no more PB announcements)");
3179 wpabuf_free(wpa_s->dpp_pb_announcement);
3180 wpa_s->dpp_pb_announcement = NULL;
3181 }
3182#endif /* CONFIG_DPP3 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003183 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003184 msg = wpa_s->dpp_pkex->exchange_resp;
3185 wait_time = wpa_s->max_remain_on_chan;
3186 if (wait_time > 2000)
3187 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003188 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3189 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003190 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3191 broadcast,
3192 wpabuf_head(msg), wpabuf_len(msg),
3193 wait_time, wpas_dpp_tx_pkex_status, 0);
3194}
3195
3196
3197static void
3198wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3199 const u8 *buf, size_t len, unsigned int freq)
3200{
3201 struct wpabuf *msg;
3202 unsigned int wait_time;
3203
3204 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
3205 MAC2STR(src));
3206
3207 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3208 * values here */
3209
3210 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3211 wpa_s->dpp_pkex->exchange_done) {
3212 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3213 return;
3214 }
3215
Roshan Pius3a1667e2018-07-03 15:17:14 -07003216 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3217 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3218
3219 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003220 if (!msg) {
3221 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3222 return;
3223 }
3224
3225 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3226 MAC2STR(src));
3227
3228 wait_time = wpa_s->max_remain_on_chan;
3229 if (wait_time > 2000)
3230 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003231 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3232 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003233 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3234 broadcast,
3235 wpabuf_head(msg), wpabuf_len(msg),
3236 wait_time, wpas_dpp_tx_pkex_status, 0);
3237 wpabuf_free(msg);
3238}
3239
3240
Roshan Pius3a1667e2018-07-03 15:17:14 -07003241static struct dpp_bootstrap_info *
3242wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3243 unsigned int freq)
3244{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003245 struct dpp_bootstrap_info *bi;
3246
Sunil Ravi89eba102022-09-13 21:04:37 -07003247 wpas_dpp_pkex_clear_code(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003248 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003249 if (!bi)
3250 return NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003251
Roshan Pius3a1667e2018-07-03 15:17:14 -07003252 wpa_s->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003253
3254#ifdef CONFIG_DPP3
3255 if (wpa_s->dpp_pb_bi && !wpa_s->dpp_pb_configurator &&
3256 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_init_hash,
3257 SHA256_MAC_LEN) != 0) {
3258 char id[20];
3259
3260 wpa_printf(MSG_INFO,
3261 "DPP: Peer bootstrap key from PKEX does not match PB announcement response hash");
3262 wpa_hexdump(MSG_DEBUG,
3263 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3264 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3265 wpa_hexdump(MSG_DEBUG,
3266 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement response",
3267 wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN);
3268
3269 os_snprintf(id, sizeof(id), "%u", bi->id);
3270 dpp_bootstrap_remove(wpa_s->dpp, id);
3271 wpas_dpp_push_button_stop(wpa_s);
3272 return NULL;
3273 }
3274#endif /* CONFIG_DPP3 */
3275
Roshan Pius3a1667e2018-07-03 15:17:14 -07003276 return bi;
3277}
3278
3279
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003280static void
3281wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3282 const u8 *hdr, const u8 *buf, size_t len,
3283 unsigned int freq)
3284{
3285 struct wpabuf *msg;
3286 unsigned int wait_time;
3287 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003288
3289 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3290 MAC2STR(src));
3291
3292 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3293 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3294 return;
3295 }
3296
3297 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3298 if (!msg) {
3299 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003300 if (pkex->failed) {
3301 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3302 if (pkex->t > pkex->own_bi->pkex_t)
3303 pkex->own_bi->pkex_t = pkex->t;
3304 dpp_pkex_free(wpa_s->dpp_pkex);
3305 wpa_s->dpp_pkex = NULL;
3306 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003307 return;
3308 }
3309
3310 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3311 MACSTR, MAC2STR(src));
3312
3313 wait_time = wpa_s->max_remain_on_chan;
3314 if (wait_time > 2000)
3315 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003316 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3317 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003318 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3319 broadcast,
3320 wpabuf_head(msg), wpabuf_len(msg),
3321 wait_time, wpas_dpp_tx_pkex_status, 0);
3322 wpabuf_free(msg);
3323
Roshan Pius3a1667e2018-07-03 15:17:14 -07003324 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003325 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003326}
3327
3328
3329static void
3330wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3331 const u8 *hdr, const u8 *buf, size_t len,
3332 unsigned int freq)
3333{
3334 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003335 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003336 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3337 char cmd[500];
3338
3339 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3340 MAC2STR(src));
3341
3342 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3343 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3344 return;
3345 }
3346
3347 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3348 if (res < 0) {
3349 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3350 return;
3351 }
3352
Roshan Pius3a1667e2018-07-03 15:17:14 -07003353 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003354 if (!bi)
3355 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003356
Sunil Ravi89eba102022-09-13 21:04:37 -07003357#ifdef CONFIG_DPP3
3358 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_configurator &&
3359 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_resp_hash,
3360 SHA256_MAC_LEN) != 0) {
3361 char id[20];
3362
3363 wpa_printf(MSG_INFO,
3364 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
3365 wpa_hexdump(MSG_DEBUG,
3366 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3367 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3368 wpa_hexdump(MSG_DEBUG,
3369 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
3370 wpa_s->dpp_pb_resp_hash, SHA256_MAC_LEN);
3371
3372 os_snprintf(id, sizeof(id), "%u", bi->id);
3373 dpp_bootstrap_remove(wpa_s->dpp, id);
3374 wpas_dpp_push_button_stop(wpa_s);
3375 return;
3376 }
3377#endif /* CONFIG_DPP3 */
3378
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003379 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3380 bi->id,
3381 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3382 wpa_printf(MSG_DEBUG,
3383 "DPP: Start authentication after PKEX with parameters: %s",
3384 cmd);
3385 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3386 wpa_printf(MSG_DEBUG,
3387 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003388 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003389 return;
3390 }
3391}
3392
3393
Sunil Ravi89eba102022-09-13 21:04:37 -07003394#ifdef CONFIG_DPP3
3395
3396static void wpas_dpp_pb_pkex_init(struct wpa_supplicant *wpa_s,
3397 unsigned int freq, const u8 *src,
3398 const u8 *r_hash)
3399{
3400 struct dpp_pkex *pkex;
3401 struct wpabuf *msg;
3402 unsigned int wait_time;
3403 size_t len;
3404
3405 if (wpa_s->dpp_pkex) {
3406 wpa_printf(MSG_DEBUG,
3407 "DPP: Sending previously generated PKEX Exchange Request to "
3408 MACSTR, MAC2STR(src));
3409 msg = wpa_s->dpp_pkex->exchange_req;
3410 wait_time = wpa_s->max_remain_on_chan;
3411 if (wait_time > 2000)
3412 wait_time = 2000;
3413 offchannel_send_action(wpa_s, freq, src,
3414 wpa_s->own_addr, broadcast,
3415 wpabuf_head(msg), wpabuf_len(msg),
3416 wait_time, wpas_dpp_tx_pkex_status, 0);
3417 return;
3418 }
3419
3420 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
3421 MACSTR, MAC2STR(src));
3422
3423 if (!wpa_s->dpp_pb_cmd) {
3424 wpa_printf(MSG_INFO,
3425 "DPP: No configuration to provision as push button Configurator");
3426 wpas_dpp_push_button_stop(wpa_s);
3427 return;
3428 }
3429
3430 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
3431 os_memcpy(wpa_s->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
3432
3433 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3434 "PBPKEX", (const char *) wpa_s->dpp_pb_c_nonce,
3435 wpa_s->dpp_pb_bi->curve->nonce_len,
3436 true);
3437 if (!pkex) {
3438 wpas_dpp_push_button_stop(wpa_s);
3439 return;
3440 }
3441 pkex->freq = freq;
3442
3443 wpa_s->dpp_pkex = pkex;
3444 msg = wpa_s->dpp_pkex->exchange_req;
3445 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3446 " freq=%u type=%d", MAC2STR(src), freq,
3447 DPP_PA_PKEX_EXCHANGE_REQ);
3448 wait_time = wpa_s->max_remain_on_chan;
3449 if (wait_time > 2000)
3450 wait_time = 2000;
3451 offchannel_send_action(wpa_s, pkex->freq, src,
3452 wpa_s->own_addr, broadcast,
3453 wpabuf_head(msg), wpabuf_len(msg),
3454 wait_time, wpas_dpp_tx_pkex_status, 0);
3455 pkex->exch_req_wait_time = 2000;
3456 pkex->exch_req_tries = 1;
3457
3458 /* Use the externally provided configuration */
3459 os_free(wpa_s->dpp_pkex_auth_cmd);
3460 len = 30 + os_strlen(wpa_s->dpp_pb_cmd);
3461 wpa_s->dpp_pkex_auth_cmd = os_malloc(len);
3462 if (wpa_s->dpp_pkex_auth_cmd)
3463 os_snprintf(wpa_s->dpp_pkex_auth_cmd, len, " own=%d %s",
3464 wpa_s->dpp_pkex_bi->id, wpa_s->dpp_pb_cmd);
3465 else
3466 wpas_dpp_push_button_stop(wpa_s);
3467}
3468
3469
3470static void
3471wpas_dpp_rx_pb_presence_announcement(struct wpa_supplicant *wpa_s,
3472 const u8 *src, const u8 *hdr,
3473 const u8 *buf, size_t len,
3474 unsigned int freq)
3475{
3476 const u8 *r_hash;
3477 u16 r_hash_len;
3478 unsigned int i;
3479 bool found = false;
3480 struct dpp_pb_info *info, *tmp;
3481 struct os_reltime now, age;
3482 struct wpabuf *msg;
3483
3484 os_get_reltime(&now);
3485 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
3486 MACSTR, MAC2STR(src));
3487
3488 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3489 &r_hash_len);
3490 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
3491 wpa_printf(MSG_DEBUG,
3492 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
3493 return;
3494 }
3495 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3496 r_hash, r_hash_len);
3497
3498 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3499 info = &wpa_s->dpp_pb[i];
3500 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
3501 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
3502 continue;
3503 wpa_printf(MSG_DEBUG,
3504 "DPP: Active push button Enrollee already known");
3505 found = true;
3506 info->rx_time = now;
3507 }
3508
3509 if (!found) {
3510 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3511 tmp = &wpa_s->dpp_pb[i];
3512 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
3513 continue;
3514
3515 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
3516 wpa_hexdump(MSG_DEBUG,
3517 "DPP: Push button Enrollee hash expired",
3518 tmp->hash, SHA256_MAC_LEN);
3519 tmp->rx_time.sec = 0;
3520 tmp->rx_time.usec = 0;
3521 continue;
3522 }
3523
3524 wpa_hexdump(MSG_DEBUG,
3525 "DPP: Push button session overlap with hash",
3526 tmp->hash, SHA256_MAC_LEN);
3527 if (!wpa_s->dpp_pb_result_indicated &&
3528 wpas_dpp_pb_active(wpa_s)) {
3529 wpa_msg(wpa_s, MSG_INFO,
3530 DPP_EVENT_PB_RESULT "session-overlap");
3531 wpa_s->dpp_pb_result_indicated = true;
3532 }
3533 wpas_dpp_push_button_stop(wpa_s);
3534 return;
3535 }
3536
3537 /* Replace the oldest entry */
3538 info = &wpa_s->dpp_pb[0];
3539 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
3540 tmp = &wpa_s->dpp_pb[i];
3541 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
3542 info = tmp;
3543 }
3544 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
3545 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
3546 info->rx_time = now;
3547 }
3548
3549 if (!wpas_dpp_pb_active(wpa_s)) {
3550 wpa_printf(MSG_DEBUG,
3551 "DPP: Discard message since own push button has not been pressed");
3552 return;
3553 }
3554
3555 if (wpa_s->dpp_pb_announce_time.sec == 0 &&
3556 wpa_s->dpp_pb_announce_time.usec == 0) {
3557 /* Start a wait before allowing PKEX to be initiated */
3558 wpa_s->dpp_pb_announce_time = now;
3559 }
3560
3561 if (!wpa_s->dpp_pb_bi) {
3562 int res;
3563
3564 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
3565 if (res < 0)
3566 return;
3567 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
3568 if (!wpa_s->dpp_pb_bi)
3569 return;
3570
3571 if (random_get_bytes(wpa_s->dpp_pb_c_nonce,
3572 wpa_s->dpp_pb_bi->curve->nonce_len)) {
3573 wpa_printf(MSG_ERROR,
3574 "DPP: Failed to generate C-nonce");
3575 wpas_dpp_push_button_stop(wpa_s);
3576 return;
3577 }
3578 }
3579
3580 /* Skip the response if one was sent within last 50 ms since the
3581 * Enrollee is going to send out at least three announcement messages.
3582 */
3583 os_reltime_sub(&now, &wpa_s->dpp_pb_last_resp, &age);
3584 if (age.sec == 0 && age.usec < 50000) {
3585 wpa_printf(MSG_DEBUG,
3586 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
3587 return;
3588 }
3589
3590 msg = dpp_build_pb_announcement_resp(
3591 wpa_s->dpp_pb_bi, r_hash, wpa_s->dpp_pb_c_nonce,
3592 wpa_s->dpp_pb_bi->curve->nonce_len);
3593 if (!msg) {
3594 wpas_dpp_push_button_stop(wpa_s);
3595 return;
3596 }
3597
3598 wpa_printf(MSG_DEBUG,
3599 "DPP: Send Push Button Presence Announcement Response to "
3600 MACSTR, MAC2STR(src));
3601 wpa_s->dpp_pb_last_resp = now;
3602
3603 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3604 MAC2STR(src), freq, DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
3605 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
3606 wpabuf_head(msg), wpabuf_len(msg),
3607 0, NULL, 0);
3608 wpabuf_free(msg);
3609
3610 if (os_reltime_expired(&now, &wpa_s->dpp_pb_announce_time, 15))
3611 wpas_dpp_pb_pkex_init(wpa_s, freq, src, r_hash);
3612}
3613
3614
3615static void
3616wpas_dpp_rx_pb_presence_announcement_resp(struct wpa_supplicant *wpa_s,
3617 const u8 *src, const u8 *hdr,
3618 const u8 *buf, size_t len,
3619 unsigned int freq)
3620{
3621 const u8 *i_hash, *r_hash, *c_nonce;
3622 u16 i_hash_len, r_hash_len, c_nonce_len;
3623 bool overlap = false;
3624
3625 if (!wpa_s->dpp_pb_announcement || !wpa_s->dpp_pb_bi ||
3626 wpa_s->dpp_pb_configurator) {
3627 wpa_printf(MSG_INFO,
3628 "DPP: Not in active push button Enrollee mode - discard Push Button Presence Announcement Response from "
3629 MACSTR, MAC2STR(src));
3630 return;
3631 }
3632
3633 wpa_printf(MSG_DEBUG,
3634 "DPP: Push Button Presence Announcement Response from "
3635 MACSTR, MAC2STR(src));
3636
3637 i_hash = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3638 &i_hash_len);
3639 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3640 &r_hash_len);
3641 c_nonce = dpp_get_attr(buf, len, DPP_ATTR_CONFIGURATOR_NONCE,
3642 &c_nonce_len);
3643 if (!i_hash || i_hash_len != SHA256_MAC_LEN ||
3644 !r_hash || r_hash_len != SHA256_MAC_LEN ||
3645 !c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
3646 wpa_printf(MSG_DEBUG,
3647 "DPP: Missing or invalid required attribute");
3648 return;
3649 }
3650 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
3651 i_hash, i_hash_len);
3652 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3653 r_hash, r_hash_len);
3654 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator Nonce",
3655 c_nonce, c_nonce_len);
3656
3657#ifdef CONFIG_TESTING_OPTIONS
3658 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ &&
3659 os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3660 SHA256_MAC_LEN - 1) == 0)
3661 goto skip_hash_check;
3662#endif /* CONFIG_TESTING_OPTIONS */
3663 if (os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3664 SHA256_MAC_LEN) != 0) {
3665 wpa_printf(MSG_INFO,
3666 "DPP: Unexpected push button Responder hash - abort");
3667 overlap = true;
3668 }
3669#ifdef CONFIG_TESTING_OPTIONS
3670skip_hash_check:
3671#endif /* CONFIG_TESTING_OPTIONS */
3672
3673 if (wpa_s->dpp_pb_resp_freq &&
3674 os_memcmp(i_hash, wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN) != 0) {
3675 wpa_printf(MSG_INFO,
3676 "DPP: Push button session overlap detected - abort");
3677 overlap = true;
3678 }
3679
3680 if (overlap) {
3681 if (!wpa_s->dpp_pb_result_indicated) {
3682 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
3683 "session-overlap");
3684 wpa_s->dpp_pb_result_indicated = true;
3685 }
3686 wpas_dpp_push_button_stop(wpa_s);
3687 return;
3688 }
3689
3690 if (!wpa_s->dpp_pb_resp_freq) {
3691 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
3692 "discovered push button AP/Configurator " MACSTR,
3693 MAC2STR(src));
3694 wpa_s->dpp_pb_resp_freq = freq;
3695 os_memcpy(wpa_s->dpp_pb_init_hash, i_hash, SHA256_MAC_LEN);
3696 os_memcpy(wpa_s->dpp_pb_c_nonce, c_nonce, c_nonce_len);
3697 wpa_s->dpp_pb_c_nonce_len = c_nonce_len;
3698 /* Stop announcement iterations after at least one more full
3699 * round and one extra round for postponed session overlap
3700 * detection. */
3701 wpa_s->dpp_pb_stop_iter = 3;
3702 }
3703}
3704
3705
3706static void
3707wpas_dpp_tx_priv_intro_status(struct wpa_supplicant *wpa_s,
3708 unsigned int freq, const u8 *dst,
3709 const u8 *src, const u8 *bssid,
3710 const u8 *data, size_t data_len,
3711 enum offchannel_send_action_result result)
3712{
3713 const char *res_txt;
3714
3715 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3716 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3717 "FAILED");
3718 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3719 " result=%s (DPP Private Peer Introduction Update)",
3720 freq, MAC2STR(dst), res_txt);
3721 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3722 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3723
3724 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR " version=%u",
3725 MAC2STR(src), wpa_s->dpp_intro_peer_version);
3726
3727 wpa_printf(MSG_DEBUG,
3728 "DPP: Try connection again after successful network introduction");
3729 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3730 wpa_supplicant_cancel_sched_scan(wpa_s);
3731 wpa_supplicant_req_scan(wpa_s, 0, 0);
3732 }
3733}
3734
3735
3736static int
3737wpas_dpp_send_private_peer_intro_update(struct wpa_supplicant *wpa_s,
3738 struct dpp_introduction *intro,
3739 struct wpa_ssid *ssid,
3740 const u8 *dst, unsigned int freq)
3741{
3742 struct wpabuf *pt, *msg, *enc_ct;
3743 size_t len;
3744 u8 ver = DPP_VERSION;
3745 int conn_ver;
3746 const u8 *aad;
3747 size_t aad_len;
3748 unsigned int wait_time;
3749
3750 wpa_printf(MSG_DEBUG, "HPKE(kem_id=%u kdf_id=%u aead_id=%u)",
3751 intro->kem_id, intro->kdf_id, intro->aead_id);
3752
3753 /* Plaintext for HPKE */
3754 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3755 pt = wpabuf_alloc(len);
3756 if (!pt)
3757 return -1;
3758
3759 /* Protocol Version */
3760 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3761 if (conn_ver > 0 && ver != conn_ver) {
3762 wpa_printf(MSG_DEBUG,
3763 "DPP: Use Connector version %d instead of current protocol version %d",
3764 conn_ver, ver);
3765 ver = conn_ver;
3766 }
3767 wpabuf_put_le16(pt, DPP_ATTR_PROTOCOL_VERSION);
3768 wpabuf_put_le16(pt, 1);
3769 wpabuf_put_u8(pt, ver);
3770
3771 /* Connector */
3772 wpabuf_put_le16(pt, DPP_ATTR_CONNECTOR);
3773 wpabuf_put_le16(pt, os_strlen(ssid->dpp_connector));
3774 wpabuf_put_str(pt, ssid->dpp_connector);
3775 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Plaintext for HPKE", pt);
3776
3777 /* HPKE(pt) using AP's public key (from its Connector) */
3778 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, 0);
3779 if (!msg) {
3780 wpabuf_free(pt);
3781 return -1;
3782 }
3783 aad = wpabuf_head_u8(msg) + 2; /* from the OUI field (inclusive) */
3784 aad_len = DPP_HDR_LEN; /* to the DPP Frame Type field (inclusive) */
3785 wpa_hexdump(MSG_MSGDUMP, "DPP: AAD for HPKE", aad, aad_len);
3786
3787 enc_ct = hpke_base_seal(intro->kem_id, intro->kdf_id, intro->aead_id,
3788 intro->peer_key, NULL, 0, aad, aad_len,
3789 wpabuf_head(pt), wpabuf_len(pt));
3790 wpabuf_free(pt);
3791 wpabuf_free(msg);
3792 if (!enc_ct) {
3793 wpa_printf(MSG_INFO, "DPP: HPKE Seal(Connector) failed");
3794 return -1;
3795 }
3796 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE enc|ct", enc_ct);
3797
3798 /* HPKE(pt) to generate payload for Wrapped Data */
3799 len = 5 + 4 + wpabuf_len(enc_ct);
3800 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, len);
3801 if (!msg) {
3802 wpabuf_free(enc_ct);
3803 return -1;
3804 }
3805
3806 /* Transaction ID */
3807 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3808 wpabuf_put_le16(msg, 1);
3809 wpabuf_put_u8(msg, TRANSACTION_ID);
3810
3811 /* Wrapped Data */
3812 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3813 wpabuf_put_le16(msg, wpabuf_len(enc_ct));
3814 wpabuf_put_buf(msg, enc_ct);
3815 wpabuf_free(enc_ct);
3816
3817 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Update", msg);
3818
3819 /* TODO: Timeout on AP response */
3820 wait_time = wpa_s->max_remain_on_chan;
3821 if (wait_time > 2000)
3822 wait_time = 2000;
3823 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3824 MAC2STR(dst), freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
3825 offchannel_send_action(wpa_s, freq, dst, wpa_s->own_addr, broadcast,
3826 wpabuf_head(msg), wpabuf_len(msg),
3827 wait_time, wpas_dpp_tx_priv_intro_status, 0);
3828 wpabuf_free(msg);
3829
3830 return 0;
3831}
3832
3833
3834static void
3835wpas_dpp_rx_priv_peer_intro_notify(struct wpa_supplicant *wpa_s,
3836 const u8 *src, const u8 *hdr,
3837 const u8 *buf, size_t len,
3838 unsigned int freq)
3839{
3840 struct wpa_ssid *ssid;
3841 const u8 *connector, *trans_id, *version;
3842 u16 connector_len, trans_id_len, version_len;
3843 u8 peer_version = 1;
3844 struct dpp_introduction intro;
3845 struct rsn_pmksa_cache_entry *entry;
3846 struct os_time now;
3847 struct os_reltime rnow;
3848 os_time_t expiry;
3849 unsigned int seconds;
3850 enum dpp_status_error res;
3851
3852 os_memset(&intro, 0, sizeof(intro));
3853
3854 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
3855 MACSTR, MAC2STR(src));
3856 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
3857 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
3858 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
3859 MACSTR " - drop", MAC2STR(src));
3860 return;
3861 }
3862 offchannel_send_action_done(wpa_s);
3863
3864 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3865 if (ssid == wpa_s->dpp_intro_network)
3866 break;
3867 }
3868 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3869 !ssid->dpp_csign) {
3870 wpa_printf(MSG_DEBUG,
3871 "DPP: Profile not found for network introduction");
3872 return;
3873 }
3874
3875 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
3876 &trans_id_len);
3877 if (!trans_id || trans_id_len != 1) {
3878 wpa_printf(MSG_DEBUG,
3879 "DPP: Peer did not include Transaction ID");
3880 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3881 " fail=missing_transaction_id", MAC2STR(src));
3882 goto fail;
3883 }
3884 if (trans_id[0] != TRANSACTION_ID) {
3885 wpa_printf(MSG_DEBUG,
3886 "DPP: Ignore frame with unexpected Transaction ID %u",
3887 trans_id[0]);
3888 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3889 " fail=transaction_id_mismatch", MAC2STR(src));
3890 goto fail;
3891 }
3892
3893 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
3894 if (!connector) {
3895 wpa_printf(MSG_DEBUG,
3896 "DPP: Peer did not include its Connector");
3897 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3898 " fail=missing_connector", MAC2STR(src));
3899 goto fail;
3900 }
3901
3902 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
3903 &version_len);
3904 if (!version || version_len < 1) {
3905 wpa_printf(MSG_DEBUG,
3906 "DPP: Peer did not include valid Version");
3907 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3908 " fail=missing_version", MAC2STR(src));
3909 goto fail;
3910 }
3911
3912 res = dpp_peer_intro(&intro, ssid->dpp_connector,
3913 ssid->dpp_netaccesskey,
3914 ssid->dpp_netaccesskey_len,
3915 ssid->dpp_csign,
3916 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003917 connector, connector_len, &expiry, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07003918 if (res != DPP_STATUS_OK) {
3919 wpa_printf(MSG_INFO,
3920 "DPP: Network Introduction protocol resulted in failure");
3921 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3922 " fail=peer_connector_validation_failed", MAC2STR(src));
3923 wpas_dpp_send_conn_status_result(wpa_s, res);
3924 goto fail;
3925 }
3926
3927 peer_version = version[0];
3928 if (intro.peer_version && intro.peer_version >= 2 &&
3929 peer_version != intro.peer_version) {
3930 wpa_printf(MSG_INFO,
3931 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
3932 intro.peer_version, peer_version);
3933 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
3934 goto fail;
3935 }
3936 wpa_s->dpp_intro_peer_version = peer_version;
3937
3938 entry = os_zalloc(sizeof(*entry));
3939 if (!entry)
3940 goto fail;
3941 entry->dpp_pfs = peer_version >= 2;
3942 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003943 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Sunil Ravi89eba102022-09-13 21:04:37 -07003944 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
3945 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
3946 entry->pmk_len = intro.pmk_len;
3947 entry->akmp = WPA_KEY_MGMT_DPP;
3948 if (expiry) {
3949 os_get_time(&now);
3950 seconds = expiry - now.sec;
3951 } else {
3952 seconds = 86400 * 7;
3953 }
3954
3955 if (wpas_dpp_send_private_peer_intro_update(wpa_s, &intro, ssid, src,
3956 freq) < 0) {
3957 os_free(entry);
3958 goto fail;
3959 }
3960
3961 os_get_reltime(&rnow);
3962 entry->expiration = rnow.sec + seconds;
3963 entry->reauth_time = rnow.sec + seconds;
3964 entry->network_ctx = ssid;
3965 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
3966
3967 /* Association will be initiated from TX status handler for the Private
3968 * Peer Intro Update: wpas_dpp_tx_priv_intro_status() */
3969
3970fail:
3971 dpp_peer_intro_deinit(&intro);
3972}
3973
3974#endif /* CONFIG_DPP3 */
3975
3976
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003977void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
3978 const u8 *buf, size_t len, unsigned int freq)
3979{
3980 u8 crypto_suite;
3981 enum dpp_public_action_frame_type type;
3982 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003983 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003984
3985 if (len < DPP_HDR_LEN)
3986 return;
3987 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
3988 return;
3989 hdr = buf;
3990 buf += 4;
3991 len -= 4;
3992 crypto_suite = *buf++;
3993 type = *buf++;
3994 len -= 2;
3995
3996 wpa_printf(MSG_DEBUG,
3997 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
3998 MACSTR " freq=%u",
3999 crypto_suite, type, MAC2STR(src), freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07004000#ifdef CONFIG_TESTING_OPTIONS
4001 if (wpa_s->dpp_discard_public_action &&
4002 type != DPP_PA_PEER_DISCOVERY_RESP &&
4003 type != DPP_PA_PRIV_PEER_INTRO_NOTIFY) {
4004 wpa_printf(MSG_DEBUG,
4005 "TESTING: Discard received DPP Public Action frame");
4006 return;
4007 }
4008#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004009 if (crypto_suite != 1) {
4010 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
4011 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004012 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4013 " freq=%u type=%d ignore=unsupported-crypto-suite",
4014 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004015 return;
4016 }
4017 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004018 if (dpp_check_attrs(buf, len) < 0) {
4019 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
4020 " freq=%u type=%d ignore=invalid-attributes",
4021 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004022 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004023 }
4024 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
4025 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004026
4027 switch (type) {
4028 case DPP_PA_AUTHENTICATION_REQ:
4029 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
4030 break;
4031 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07004032 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004033 break;
4034 case DPP_PA_AUTHENTICATION_CONF:
4035 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
4036 break;
4037 case DPP_PA_PEER_DISCOVERY_RESP:
4038 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
4039 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004040#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004041 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004042 /* This is for PKEXv2, but for now, process only with
4043 * CONFIG_DPP3 to avoid issues with a capability that has not
4044 * been tested with other implementations. */
4045 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
4046 break;
4047#endif /* CONFIG_DPP3 */
4048 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
4049 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
4050 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004051 break;
4052 case DPP_PA_PKEX_EXCHANGE_RESP:
4053 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
4054 break;
4055 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
4056 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
4057 freq);
4058 break;
4059 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
4060 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
4061 freq);
4062 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004063#ifdef CONFIG_DPP2
4064 case DPP_PA_CONFIGURATION_RESULT:
4065 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
4066 break;
Hai Shalomc3565922019-10-28 11:58:20 -07004067 case DPP_PA_CONNECTION_STATUS_RESULT:
4068 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
4069 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07004070 case DPP_PA_PRESENCE_ANNOUNCEMENT:
4071 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
4072 freq);
4073 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004074 case DPP_PA_RECONFIG_ANNOUNCEMENT:
4075 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
4076 freq);
4077 break;
4078 case DPP_PA_RECONFIG_AUTH_REQ:
4079 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
4080 break;
4081 case DPP_PA_RECONFIG_AUTH_RESP:
4082 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
4083 break;
4084 case DPP_PA_RECONFIG_AUTH_CONF:
4085 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
4086 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004087#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07004088#ifdef CONFIG_DPP3
4089 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
4090 wpas_dpp_rx_pb_presence_announcement(wpa_s, src, hdr,
4091 buf, len, freq);
4092 break;
4093 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP:
4094 wpas_dpp_rx_pb_presence_announcement_resp(wpa_s, src, hdr,
4095 buf, len, freq);
4096 break;
4097 case DPP_PA_PRIV_PEER_INTRO_NOTIFY:
4098 wpas_dpp_rx_priv_peer_intro_notify(wpa_s, src, hdr,
4099 buf, len, freq);
4100 break;
4101#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004102 default:
4103 wpa_printf(MSG_DEBUG,
4104 "DPP: Ignored unsupported frame subtype %d", type);
4105 break;
4106 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004107
4108 if (wpa_s->dpp_pkex)
4109 pkex_t = wpa_s->dpp_pkex->t;
4110 else if (wpa_s->dpp_pkex_bi)
4111 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
4112 else
4113 pkex_t = 0;
4114 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
4115 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
4116 wpas_dpp_pkex_remove(wpa_s, "*");
4117 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004118}
4119
4120
Hai Shaloma20dcd72022-02-04 13:43:00 -08004121static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
4122 void *timeout_ctx)
4123{
4124 struct wpa_supplicant *wpa_s = eloop_ctx;
4125 struct dpp_authentication *auth = wpa_s->dpp_auth;
4126
4127 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
4128 return;
4129
4130 wpa_printf(MSG_DEBUG,
4131 "DPP: No configuration available from upper layers - send initial response with comeback delay");
4132 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
4133 500);
4134}
4135
4136
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004137static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07004138wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08004139 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004140{
4141 struct wpa_supplicant *wpa_s = ctx;
4142 struct dpp_authentication *auth = wpa_s->dpp_auth;
4143 struct wpabuf *resp;
4144
4145 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
4146 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004147 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004148 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
4149 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
4150 return NULL;
4151 }
Hai Shalomc3565922019-10-28 11:58:20 -07004152
4153 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
4154 wpa_printf(MSG_DEBUG,
4155 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
4156 /* wpas_dpp_auth_success() would normally have been called from
4157 * TX status handler, but since there was no such handler call
4158 * yet, simply send out the event message and proceed with
4159 * exchange. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004160 dpp_notify_auth_success(auth, 1);
Hai Shalomc3565922019-10-28 11:58:20 -07004161 wpa_s->dpp_auth_ok_on_ack = 0;
4162 }
4163
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004164 wpa_hexdump(MSG_DEBUG,
4165 "DPP: Received Configuration Request (GAS Query Request)",
4166 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004167 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
4168 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004169 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004170
Hai Shaloma20dcd72022-02-04 13:43:00 -08004171 auth->gas_server_ctx = resp_ctx;
4172
Hai Shalom899fcc72020-10-19 14:38:18 -07004173#ifdef CONFIG_DPP2
4174 if (!resp && auth->waiting_cert) {
4175 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08004176 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07004177 *comeback_delay = 500;
4178 return NULL;
4179 }
4180#endif /* CONFIG_DPP2 */
4181
Hai Shaloma20dcd72022-02-04 13:43:00 -08004182 if (!resp && auth->waiting_config &&
4183 (auth->peer_bi || auth->tmp_peer_bi)) {
4184 char *buf = NULL, *name = "";
4185 char band[200], *pos, *end;
4186 int i, res, *opclass = auth->e_band_support;
4187 char *mud_url = "N/A";
4188
4189 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
4190 auth->config_resp_ctx = resp_ctx;
4191 *comeback_delay = -1;
4192 if (auth->e_name) {
4193 size_t len = os_strlen(auth->e_name);
4194
4195 buf = os_malloc(len * 4 + 1);
4196 if (buf) {
4197 printf_encode(buf, len * 4 + 1,
4198 (const u8 *) auth->e_name, len);
4199 name = buf;
4200 }
4201 }
4202 band[0] = '\0';
4203 pos = band;
4204 end = band + sizeof(band);
4205 for (i = 0; opclass && opclass[i]; i++) {
4206 res = os_snprintf(pos, end - pos, "%s%d",
4207 pos == band ? "" : ",", opclass[i]);
4208 if (os_snprintf_error(end - pos, res)) {
4209 *pos = '\0';
4210 break;
4211 }
4212 pos += res;
4213 }
4214 if (auth->e_mud_url) {
4215 size_t len = os_strlen(auth->e_mud_url);
4216
4217 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
4218 mud_url = auth->e_mud_url;
4219 }
4220 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
4221 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
4222 auth->peer_bi ? auth->peer_bi->id :
4223 auth->tmp_peer_bi->id, MAC2STR(sa),
4224 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
4225 os_free(buf);
4226
4227 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4228 NULL);
4229 eloop_register_timeout(0, 50000,
4230 wpas_dpp_gas_initial_resp_timeout, wpa_s,
4231 NULL);
4232 return NULL;
4233 }
4234
Sunil Ravia04bd252022-05-02 22:54:18 -07004235 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08004236 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004237 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004238 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07004239 dpp_auth_deinit(wpa_s->dpp_auth);
4240 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08004241 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004242 return resp;
4243}
4244
4245
4246static void
4247wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
4248{
4249 struct wpa_supplicant *wpa_s = ctx;
4250 struct dpp_authentication *auth = wpa_s->dpp_auth;
4251
4252 if (!auth) {
4253 wpabuf_free(resp);
4254 return;
4255 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004256 if (auth->conf_resp != resp) {
4257 wpa_printf(MSG_DEBUG,
4258 "DPP: Ignore GAS status report (ok=%d) for unknown response",
4259 ok);
4260 wpabuf_free(resp);
4261 return;
4262 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004263
Hai Shalom899fcc72020-10-19 14:38:18 -07004264#ifdef CONFIG_DPP2
4265 if (auth->waiting_csr && ok) {
4266 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
4267 wpabuf_free(resp);
4268 return;
4269 }
4270#endif /* CONFIG_DPP2 */
4271
Sunil Ravia04bd252022-05-02 22:54:18 -07004272#ifdef CONFIG_DPP3
4273 if (auth->waiting_new_key && ok) {
4274 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
4275 wpabuf_free(resp);
4276 return;
4277 }
4278#endif /* CONFIG_DPP3 */
4279
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004280 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
4281 ok);
4282 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004283 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004284 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004285#ifdef CONFIG_DPP2
4286 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08004287 auth->conf_resp_status == DPP_STATUS_OK &&
4288 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07004289 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08004290 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07004291 auth->waiting_conf_result = 1;
4292 auth->conf_resp = NULL;
4293 wpabuf_free(resp);
4294 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
4295 wpa_s, NULL);
4296 eloop_register_timeout(2, 0,
4297 wpas_dpp_config_result_wait_timeout,
4298 wpa_s, NULL);
4299 return;
4300 }
4301#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004302 offchannel_send_action_done(wpa_s);
4303 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004304 if (ok) {
Sunil Ravi89eba102022-09-13 21:04:37 -07004305 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
4306 auth->conf_resp_status);
Hai Shalom706f99b2019-01-08 16:23:37 -08004307 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004308 }
4309 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004310 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004311 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004312 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004313 dpp_auth_deinit(wpa_s->dpp_auth);
4314 wpa_s->dpp_auth = NULL;
4315 wpabuf_free(resp);
Sunil Ravi89eba102022-09-13 21:04:37 -07004316#ifdef CONFIG_DPP3
4317 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
4318 if (ok)
4319 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4320 "success");
4321 else
4322 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4323 "could-not-connect");
4324 wpa_s->dpp_pb_result_indicated = true;
4325 if (ok)
4326 wpas_dpp_remove_pb_hash(wpa_s);
4327 wpas_dpp_push_button_stop(wpa_s);
4328 }
4329#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004330}
4331
4332
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004333int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
4334{
4335 struct dpp_authentication *auth;
4336 int ret = -1;
4337 char *curve = NULL;
4338
Hai Shalomfdcde762020-04-02 11:19:20 -07004339 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004340 if (!auth)
4341 return -1;
4342
4343 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08004344 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07004345 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004346 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07004347 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
4348 &auth->conf_obj[0]);
4349 if (!ret)
4350 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004351
4352 dpp_auth_deinit(auth);
4353 os_free(curve);
4354
4355 return ret;
4356}
4357
4358
4359static void
4360wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
4361 unsigned int freq, const u8 *dst,
4362 const u8 *src, const u8 *bssid,
4363 const u8 *data, size_t data_len,
4364 enum offchannel_send_action_result result)
4365{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004366 const char *res_txt;
4367
4368 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
4369 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
4370 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004371 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
4372 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07004373 freq, MAC2STR(dst), res_txt);
4374 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
4375 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004376 /* TODO: Time out wait for response more quickly in error cases? */
4377}
4378
4379
Sunil Ravi89eba102022-09-13 21:04:37 -07004380#ifdef CONFIG_DPP3
4381static int wpas_dpp_start_private_peer_intro(struct wpa_supplicant *wpa_s,
4382 struct wpa_ssid *ssid,
4383 struct wpa_bss *bss)
4384{
4385 struct wpabuf *msg;
4386 unsigned int wait_time;
4387 size_t len;
4388 u8 ver = DPP_VERSION;
4389 int conn_ver;
4390
4391 len = 5 + 5;
4392 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_QUERY, len);
4393 if (!msg)
4394 return -1;
4395
4396 /* Transaction ID */
4397 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4398 wpabuf_put_le16(msg, 1);
4399 wpabuf_put_u8(msg, TRANSACTION_ID);
4400
4401 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4402 if (conn_ver > 0 && ver != conn_ver) {
4403 wpa_printf(MSG_DEBUG,
4404 "DPP: Use Connector version %d instead of current protocol version %d",
4405 conn_ver, ver);
4406 ver = conn_ver;
4407 }
4408
4409 /* Protocol Version */
4410 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4411 wpabuf_put_le16(msg, 1);
4412 wpabuf_put_u8(msg, ver);
4413
4414 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Query", msg);
4415
4416 /* TODO: Timeout on AP response */
4417 wait_time = wpa_s->max_remain_on_chan;
4418 if (wait_time > 2000)
4419 wait_time = 2000;
4420 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4421 MAC2STR(bss->bssid), bss->freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
4422 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4423 broadcast,
4424 wpabuf_head(msg), wpabuf_len(msg),
4425 wait_time, wpas_dpp_tx_introduction_status, 0);
4426 wpabuf_free(msg);
4427
4428 /* Request this connection attempt to terminate - new one will be
4429 * started when network introduction protocol completes */
4430 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4431 wpa_s->dpp_intro_network = ssid;
4432 return 1;
4433}
4434#endif /* CONFIG_DPP3 */
4435
4436
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004437int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4438 struct wpa_bss *bss)
4439{
4440 struct os_time now;
4441 struct wpabuf *msg;
4442 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07004443 const u8 *rsn;
4444 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004445 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004446
4447 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
4448 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07004449 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4450 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
4451 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
4452 return 0; /* AP does not support DPP AKM - continue */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004453 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, wpa_s->own_addr, ssid))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004454 return 0; /* PMKSA exists for DPP AKM - continue */
4455
4456 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4457 !ssid->dpp_csign) {
4458 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4459 "missing %s",
4460 !ssid->dpp_connector ? "Connector" :
4461 (!ssid->dpp_netaccesskey ? "netAccessKey" :
4462 "C-sign-key"));
4463 return -1;
4464 }
4465
4466 os_get_time(&now);
4467
4468 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07004469 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004470 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4471 "netAccessKey expired");
4472 return -1;
4473 }
4474
4475 wpa_printf(MSG_DEBUG,
Sunil Ravi89eba102022-09-13 21:04:37 -07004476 "DPP: Starting %snetwork introduction protocol to derive PMKSA for "
4477 MACSTR,
4478 ssid->dpp_connector_privacy ? "private " : "",
4479 MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07004480 if (wpa_s->wpa_state == WPA_SCANNING)
4481 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004482
Sunil Ravi89eba102022-09-13 21:04:37 -07004483#ifdef CONFIG_DPP3
4484 if (ssid->dpp_connector_privacy)
4485 return wpas_dpp_start_private_peer_intro(wpa_s, ssid, bss);
4486#endif /* CONFIG_DPP3 */
4487
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004488 len = 5 + 4 + os_strlen(ssid->dpp_connector);
4489#ifdef CONFIG_DPP2
4490 len += 5;
4491#endif /* CONFIG_DPP2 */
4492 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004493 if (!msg)
4494 return -1;
4495
Roshan Pius3a1667e2018-07-03 15:17:14 -07004496#ifdef CONFIG_TESTING_OPTIONS
4497 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
4498 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
4499 goto skip_trans_id;
4500 }
4501 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
4502 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
4503 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4504 wpabuf_put_le16(msg, 0);
4505 goto skip_trans_id;
4506 }
4507#endif /* CONFIG_TESTING_OPTIONS */
4508
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004509 /* Transaction ID */
4510 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4511 wpabuf_put_le16(msg, 1);
4512 wpabuf_put_u8(msg, TRANSACTION_ID);
4513
Roshan Pius3a1667e2018-07-03 15:17:14 -07004514#ifdef CONFIG_TESTING_OPTIONS
4515skip_trans_id:
4516 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
4517 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
4518 goto skip_connector;
4519 }
4520 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
4521 char *connector;
4522
4523 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
4524 connector = dpp_corrupt_connector_signature(
4525 ssid->dpp_connector);
4526 if (!connector) {
4527 wpabuf_free(msg);
4528 return -1;
4529 }
4530 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4531 wpabuf_put_le16(msg, os_strlen(connector));
4532 wpabuf_put_str(msg, connector);
4533 os_free(connector);
4534 goto skip_connector;
4535 }
4536#endif /* CONFIG_TESTING_OPTIONS */
4537
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004538 /* DPP Connector */
4539 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4540 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
4541 wpabuf_put_str(msg, ssid->dpp_connector);
4542
Roshan Pius3a1667e2018-07-03 15:17:14 -07004543#ifdef CONFIG_TESTING_OPTIONS
4544skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004545 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
4546 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
4547 goto skip_proto_ver;
4548 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004549#endif /* CONFIG_TESTING_OPTIONS */
4550
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004551#ifdef CONFIG_DPP2
4552 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004553 u8 ver = DPP_VERSION;
4554#ifdef CONFIG_DPP3
4555 int conn_ver;
4556
4557 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4558 if (conn_ver > 0 && ver != conn_ver) {
4559 wpa_printf(MSG_DEBUG,
4560 "DPP: Use Connector version %d instead of current protocol version %d",
4561 conn_ver, ver);
4562 ver = conn_ver;
4563 }
4564#endif /* CONFIG_DPP3 */
4565
4566#ifdef CONFIG_TESTING_OPTIONS
4567 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
4568 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
4569 ver = 1;
4570 }
4571#endif /* CONFIG_TESTING_OPTIONS */
4572
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004573 /* Protocol Version */
4574 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4575 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004576 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004577 }
4578#endif /* CONFIG_DPP2 */
4579
Hai Shaloma20dcd72022-02-04 13:43:00 -08004580#ifdef CONFIG_TESTING_OPTIONS
4581skip_proto_ver:
4582#endif /* CONFIG_TESTING_OPTIONS */
4583
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004584 /* TODO: Timeout on AP response */
4585 wait_time = wpa_s->max_remain_on_chan;
4586 if (wait_time > 2000)
4587 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004588 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4589 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004590 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4591 broadcast,
4592 wpabuf_head(msg), wpabuf_len(msg),
4593 wait_time, wpas_dpp_tx_introduction_status, 0);
4594 wpabuf_free(msg);
4595
4596 /* Request this connection attempt to terminate - new one will be
4597 * started when network introduction protocol completes */
4598 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4599 wpa_s->dpp_intro_network = ssid;
4600 return 1;
4601}
4602
4603
4604int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
4605{
4606 struct dpp_bootstrap_info *own_bi;
4607 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07004608#ifdef CONFIG_DPP3
4609 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
4610#else /* CONFIG_DPP3 */
4611 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
4612#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004613 int tcp_port = DPP_TCP_PORT;
4614 struct hostapd_ip_addr *ipaddr = NULL;
4615#ifdef CONFIG_DPP2
4616 struct hostapd_ip_addr ipaddr_buf;
4617 char *addr;
4618
4619 pos = os_strstr(cmd, " tcp_port=");
4620 if (pos) {
4621 pos += 10;
4622 tcp_port = atoi(pos);
4623 }
4624
4625 addr = get_param(cmd, " tcp_addr=");
4626 if (addr) {
4627 int res;
4628
4629 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
4630 os_free(addr);
4631 if (res)
4632 return -1;
4633 ipaddr = &ipaddr_buf;
4634 }
4635#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004636
4637 pos = os_strstr(cmd, " own=");
4638 if (!pos)
4639 return -1;
4640 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07004641 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004642 if (!own_bi) {
4643 wpa_printf(MSG_DEBUG,
4644 "DPP: Identified bootstrap info not found");
4645 return -1;
4646 }
4647 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
4648 wpa_printf(MSG_DEBUG,
4649 "DPP: Identified bootstrap info not for PKEX");
4650 return -1;
4651 }
4652 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004653 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004654
4655 os_free(wpa_s->dpp_pkex_identifier);
4656 wpa_s->dpp_pkex_identifier = NULL;
4657 pos = os_strstr(cmd, " identifier=");
4658 if (pos) {
4659 pos += 12;
4660 end = os_strchr(pos, ' ');
4661 if (!end)
4662 return -1;
4663 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
4664 if (!wpa_s->dpp_pkex_identifier)
4665 return -1;
4666 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
4667 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
4668 }
4669
4670 pos = os_strstr(cmd, " code=");
4671 if (!pos)
4672 return -1;
4673 os_free(wpa_s->dpp_pkex_code);
4674 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
4675 if (!wpa_s->dpp_pkex_code)
4676 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004677 wpa_s->dpp_pkex_code_len = os_strlen(wpa_s->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004678
Sunil Ravia04bd252022-05-02 22:54:18 -07004679 pos = os_strstr(cmd, " ver=");
4680 if (pos) {
4681 int v;
4682
4683 pos += 5;
4684 v = atoi(pos);
4685 if (v == 1)
4686 ver = PKEX_VER_ONLY_1;
4687 else if (v == 2)
4688 ver = PKEX_VER_ONLY_2;
4689 else
4690 return -1;
4691 }
4692 wpa_s->dpp_pkex_ver = ver;
4693
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004694 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004695 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004696 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004697 } else {
4698#ifdef CONFIG_DPP2
4699 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
4700 wpa_s->dpp_pkex_code,
4701 wpa_s->dpp_pkex_identifier);
4702#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004703 }
4704
4705 /* TODO: Support multiple PKEX info entries */
4706
4707 os_free(wpa_s->dpp_pkex_auth_cmd);
4708 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
4709
4710 return 1;
4711}
4712
4713
4714int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
4715{
4716 unsigned int id_val;
4717
4718 if (os_strcmp(id, "*") == 0) {
4719 id_val = 0;
4720 } else {
4721 id_val = atoi(id);
4722 if (id_val == 0)
4723 return -1;
4724 }
4725
Sunil Ravi89eba102022-09-13 21:04:37 -07004726 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004727 return -1;
4728
4729 /* TODO: Support multiple PKEX entries */
4730 os_free(wpa_s->dpp_pkex_code);
4731 wpa_s->dpp_pkex_code = NULL;
4732 os_free(wpa_s->dpp_pkex_identifier);
4733 wpa_s->dpp_pkex_identifier = NULL;
4734 os_free(wpa_s->dpp_pkex_auth_cmd);
4735 wpa_s->dpp_pkex_auth_cmd = NULL;
4736 wpa_s->dpp_pkex_bi = NULL;
4737 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
4738 dpp_pkex_free(wpa_s->dpp_pkex);
4739 wpa_s->dpp_pkex = NULL;
4740 return 0;
4741}
4742
4743
Roshan Pius3a1667e2018-07-03 15:17:14 -07004744void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
4745{
Sunil Ravia04bd252022-05-02 22:54:18 -07004746 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07004747 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004748 dpp_auth_deinit(wpa_s->dpp_auth);
4749 wpa_s->dpp_auth = NULL;
4750 dpp_pkex_free(wpa_s->dpp_pkex);
4751 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004752 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004753 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
4754 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
Sunil Ravi89eba102022-09-13 21:04:37 -07004755#ifdef CONFIG_DPP3
4756 wpas_dpp_push_button_stop(wpa_s);
4757#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004758}
4759
4760
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004761int wpas_dpp_init(struct wpa_supplicant *wpa_s)
4762{
Hai Shalom81f62d82019-07-22 12:10:00 -07004763 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004764 u8 adv_proto_id[7];
4765
4766 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
4767 adv_proto_id[1] = 5;
4768 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
4769 adv_proto_id[5] = DPP_OUI_TYPE;
4770 adv_proto_id[6] = 0x01;
4771
4772 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
4773 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
4774 wpas_dpp_gas_status_handler, wpa_s) < 0)
4775 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004776
4777 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07004778 config.cb_ctx = wpa_s;
4779#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004780 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07004781#endif /* CONFIG_DPP2 */
4782 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07004783 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004784}
4785
4786
4787void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
4788{
4789#ifdef CONFIG_TESTING_OPTIONS
4790 os_free(wpa_s->dpp_config_obj_override);
4791 wpa_s->dpp_config_obj_override = NULL;
4792 os_free(wpa_s->dpp_discovery_override);
4793 wpa_s->dpp_discovery_override = NULL;
4794 os_free(wpa_s->dpp_groups_override);
4795 wpa_s->dpp_groups_override = NULL;
4796 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
4797#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07004798 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004799 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004800 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004801 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004802 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004803 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
4804 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004805 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4806 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004807 eloop_cancel_timeout(wpas_dpp_drv_wait_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004808#ifdef CONFIG_DPP2
4809 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07004810 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
4811 wpa_s, NULL);
4812 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004813 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
4814 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004815 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004816 eloop_cancel_timeout(wpas_dpp_connected_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004817 dpp_pfs_free(wpa_s->dpp_pfs);
4818 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004819 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004820 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4821 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07004822#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07004823#ifdef CONFIG_DPP3
4824 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
4825#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004826 offchannel_send_action_done(wpa_s);
4827 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004828 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004829 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004830 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
4831 os_free(wpa_s->dpp_configurator_params);
4832 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07004833 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004834}
Hai Shalom81f62d82019-07-22 12:10:00 -07004835
4836
Hai Shaloma20dcd72022-02-04 13:43:00 -08004837static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
4838 struct dpp_authentication *auth, bool tcp)
4839{
4840 struct wpabuf *resp;
4841
4842 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
4843 auth->e_netrole, true);
4844 if (!resp)
4845 return -1;
4846
4847 if (tcp) {
4848 auth->conf_resp_tcp = resp;
4849 return 0;
4850 }
4851
4852 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4853 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
4854 resp) < 0) {
4855 wpa_printf(MSG_DEBUG,
4856 "DPP: Could not find pending GAS response");
4857 wpabuf_free(resp);
4858 return -1;
4859 }
4860 auth->conf_resp = resp;
4861 return 0;
4862}
4863
4864
4865int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
4866{
4867 int peer;
4868 const char *pos;
4869 struct dpp_authentication *auth = wpa_s->dpp_auth;
4870 bool tcp = false;
4871
4872 pos = os_strstr(cmd, " peer=");
4873 if (!pos)
4874 return -1;
4875 peer = atoi(pos + 6);
4876#ifdef CONFIG_DPP2
4877 if (!auth || !auth->waiting_config ||
4878 (auth->peer_bi &&
4879 (unsigned int) peer != auth->peer_bi->id)) {
4880 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4881 tcp = true;
4882 }
4883#endif /* CONFIG_DPP2 */
4884
4885 if (!auth || !auth->waiting_config) {
4886 wpa_printf(MSG_DEBUG,
4887 "DPP: No authentication exchange waiting for configuration information");
4888 return -1;
4889 }
4890
4891 if ((!auth->peer_bi ||
4892 (unsigned int) peer != auth->peer_bi->id) &&
4893 (!auth->tmp_peer_bi ||
4894 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4895 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4896 return -1;
4897 }
4898
4899 pos = os_strstr(cmd, " comeback=");
4900 if (pos) {
4901 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4902 NULL);
4903 gas_server_set_comeback_delay(wpa_s->gas_server,
4904 auth->config_resp_ctx,
4905 atoi(pos + 10));
4906 return 0;
4907 }
4908
4909 if (dpp_set_configurator(auth, cmd) < 0)
4910 return -1;
4911
4912 auth->use_config_query = false;
4913 auth->waiting_config = false;
4914 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4915}
4916
4917
Hai Shalom81f62d82019-07-22 12:10:00 -07004918#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004919
Hai Shalom81f62d82019-07-22 12:10:00 -07004920int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
4921{
4922 struct dpp_controller_config config;
4923 const char *pos;
4924
4925 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004926 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07004927 config.netrole = DPP_NETROLE_STA;
4928 config.msg_ctx = wpa_s;
4929 config.cb_ctx = wpa_s;
4930 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004931 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07004932 if (cmd) {
4933 pos = os_strstr(cmd, " tcp_port=");
4934 if (pos) {
4935 pos += 10;
4936 config.tcp_port = atoi(pos);
4937 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004938
4939 pos = os_strstr(cmd, " role=");
4940 if (pos) {
4941 pos += 6;
4942 if (os_strncmp(pos, "configurator", 12) == 0)
4943 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
4944 else if (os_strncmp(pos, "enrollee", 8) == 0)
4945 config.allowed_roles = DPP_CAPAB_ENROLLEE;
4946 else if (os_strncmp(pos, "either", 6) == 0)
4947 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
4948 DPP_CAPAB_ENROLLEE;
4949 else
4950 return -1;
4951 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004952
4953 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07004954 }
4955 config.configurator_params = wpa_s->dpp_configurator_params;
4956 return dpp_controller_start(wpa_s->dpp, &config);
4957}
Hai Shalomfdcde762020-04-02 11:19:20 -07004958
4959
4960static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
4961
4962static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
4963{
4964 struct wpa_supplicant *wpa_s = eloop_ctx;
4965
4966 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
4967 offchannel_send_action_done(wpa_s);
4968 wpas_dpp_chirp_next(wpa_s, NULL);
4969}
4970
4971
4972static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
4973 unsigned int freq, const u8 *dst,
4974 const u8 *src, const u8 *bssid,
4975 const u8 *data, size_t data_len,
4976 enum offchannel_send_action_result result)
4977{
4978 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
4979 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
4980 wpa_s->dpp_chirp_freq);
4981 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
4982 wpa_s, NULL) < 0)
4983 wpas_dpp_chirp_stop(wpa_s);
4984 return;
4985 }
4986
4987 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
4988 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
4989 wpa_s, NULL) < 0)
4990 wpas_dpp_chirp_stop(wpa_s);
4991}
4992
4993
4994static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
4995{
Hai Shalom899fcc72020-10-19 14:38:18 -07004996 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004997 int type;
4998
4999 msg = wpa_s->dpp_presence_announcement;
5000 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
5001 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07005002 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
5003
5004 if (ssid && wpa_s->dpp_reconfig_id &&
5005 wpa_config_get_network(wpa_s->conf,
5006 wpa_s->dpp_reconfig_ssid_id) ==
5007 ssid) {
5008 announce = dpp_build_reconfig_announcement(
5009 ssid->dpp_csign,
5010 ssid->dpp_csign_len,
5011 ssid->dpp_netaccesskey,
5012 ssid->dpp_netaccesskey_len,
5013 wpa_s->dpp_reconfig_id);
5014 msg = announce;
5015 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005016 if (!msg)
5017 return;
5018 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
5019 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005020 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
5021 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005022 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07005023 if (offchannel_send_action(
5024 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
5025 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005026 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07005027 2000, wpas_dpp_chirp_tx_status, 0) < 0)
5028 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07005029
5030 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07005031}
5032
5033
Sunil Ravi89eba102022-09-13 21:04:37 -07005034static int * wpas_dpp_presence_ann_channels(struct wpa_supplicant *wpa_s,
5035 struct dpp_bootstrap_info *bi)
Hai Shalomfdcde762020-04-02 11:19:20 -07005036{
Hai Shalomfdcde762020-04-02 11:19:20 -07005037 unsigned int i;
5038 struct hostapd_hw_modes *mode;
5039 int c;
5040 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005041 bool chan6 = wpa_s->hw.modes == NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07005042 int *freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07005043
5044 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005045 if (bi) {
5046 for (i = 0; i < bi->num_freq; i++)
Sunil Ravi89eba102022-09-13 21:04:37 -07005047 int_array_add_unique(&freqs, bi->freq[i]);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005048 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005049
5050 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07005051 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005052 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07005053 if (mode) {
5054 for (c = 0; c < mode->num_channels; c++) {
5055 struct hostapd_channel_data *chan = &mode->channels[c];
5056
5057 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
5058 chan->freq != 2437)
5059 continue;
5060 chan6 = true;
5061 break;
5062 }
5063 }
5064 if (chan6)
Sunil Ravi89eba102022-09-13 21:04:37 -07005065 int_array_add_unique(&freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07005066
5067 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005068 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005069 if (mode) {
5070 int chan44 = 0, chan149 = 0;
5071
5072 for (c = 0; c < mode->num_channels; c++) {
5073 struct hostapd_channel_data *chan = &mode->channels[c];
5074
5075 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
5076 HOSTAPD_CHAN_RADAR))
5077 continue;
5078 if (chan->freq == 5220)
5079 chan44 = 1;
5080 if (chan->freq == 5745)
5081 chan149 = 1;
5082 }
5083 if (chan149)
Sunil Ravi89eba102022-09-13 21:04:37 -07005084 int_array_add_unique(&freqs, 5745);
Hai Shalomfdcde762020-04-02 11:19:20 -07005085 else if (chan44)
Sunil Ravi89eba102022-09-13 21:04:37 -07005086 int_array_add_unique(&freqs, 5220);
Hai Shalomfdcde762020-04-02 11:19:20 -07005087 }
5088
5089 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005090 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005091 if (mode) {
5092 for (c = 0; c < mode->num_channels; c++) {
5093 struct hostapd_channel_data *chan = &mode->channels[c];
5094
5095 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
5096 HOSTAPD_CHAN_RADAR)) ||
5097 chan->freq != 60480)
5098 continue;
Sunil Ravi89eba102022-09-13 21:04:37 -07005099 int_array_add_unique(&freqs, 60480);
Hai Shalomfdcde762020-04-02 11:19:20 -07005100 break;
5101 }
5102 }
5103
5104 /* Add channels from scan results for APs that advertise Configurator
5105 * Connectivity element */
5106 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5107 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
Sunil Ravi89eba102022-09-13 21:04:37 -07005108 int_array_add_unique(&freqs, bss->freq);
Hai Shalomfdcde762020-04-02 11:19:20 -07005109 }
5110
Sunil Ravi89eba102022-09-13 21:04:37 -07005111 return freqs;
5112}
5113
5114
5115static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
5116 struct wpa_scan_results *scan_res)
5117{
5118 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
5119
5120 if (!bi && !wpa_s->dpp_reconfig_ssid)
5121 return;
5122
5123 wpa_s->dpp_chirp_scan_done = 1;
5124
5125 os_free(wpa_s->dpp_chirp_freqs);
5126 wpa_s->dpp_chirp_freqs = wpas_dpp_presence_ann_channels(wpa_s, bi);
5127
Hai Shalomfdcde762020-04-02 11:19:20 -07005128 if (!wpa_s->dpp_chirp_freqs ||
5129 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
5130 wpas_dpp_chirp_stop(wpa_s);
5131}
5132
5133
5134static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
5135{
5136 struct wpa_supplicant *wpa_s = eloop_ctx;
5137 int i;
5138
5139 if (wpa_s->dpp_chirp_listen)
5140 wpas_dpp_listen_stop(wpa_s);
5141
5142 if (wpa_s->dpp_chirp_freq == 0) {
5143 if (wpa_s->dpp_chirp_round % 4 == 0 &&
5144 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08005145 if (wpas_scan_scheduled(wpa_s)) {
5146 wpa_printf(MSG_DEBUG,
5147 "DPP: Deferring chirp scan because another scan is planned already");
5148 if (eloop_register_timeout(1, 0,
5149 wpas_dpp_chirp_next,
5150 wpa_s, NULL) < 0) {
5151 wpas_dpp_chirp_stop(wpa_s);
5152 return;
5153 }
5154 return;
5155 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005156 wpa_printf(MSG_DEBUG,
5157 "DPP: Update channel list for chirping");
5158 wpa_s->scan_req = MANUAL_SCAN_REQ;
5159 wpa_s->scan_res_handler =
5160 wpas_dpp_chirp_scan_res_handler;
5161 wpa_supplicant_req_scan(wpa_s, 0, 0);
5162 return;
5163 }
5164 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
5165 wpa_s->dpp_chirp_round++;
5166 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
5167 wpa_s->dpp_chirp_round);
5168 } else {
5169 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
5170 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
5171 break;
5172 if (!wpa_s->dpp_chirp_freqs[i]) {
5173 wpa_printf(MSG_DEBUG,
5174 "DPP: Previous chirp freq %d not found",
5175 wpa_s->dpp_chirp_freq);
5176 return;
5177 }
5178 i++;
5179 if (wpa_s->dpp_chirp_freqs[i]) {
5180 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
5181 } else {
5182 wpa_s->dpp_chirp_iter--;
5183 if (wpa_s->dpp_chirp_iter <= 0) {
5184 wpa_printf(MSG_DEBUG,
5185 "DPP: Chirping iterations completed");
5186 wpas_dpp_chirp_stop(wpa_s);
5187 return;
5188 }
5189 wpa_s->dpp_chirp_freq = 0;
5190 wpa_s->dpp_chirp_scan_done = 0;
5191 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
5192 wpa_s, NULL) < 0) {
5193 wpas_dpp_chirp_stop(wpa_s);
5194 return;
5195 }
5196 if (wpa_s->dpp_chirp_listen) {
5197 wpa_printf(MSG_DEBUG,
5198 "DPP: Listen on %d MHz during chirp 30 second wait",
5199 wpa_s->dpp_chirp_listen);
5200 wpas_dpp_listen_start(wpa_s,
5201 wpa_s->dpp_chirp_listen);
5202 } else {
5203 wpa_printf(MSG_DEBUG,
5204 "DPP: Wait 30 seconds before starting the next chirping round");
5205 }
5206 return;
5207 }
5208 }
5209
5210 wpas_dpp_chirp_start(wpa_s);
5211}
5212
5213
5214int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
5215{
5216 const char *pos;
5217 int iter = 1, listen_freq = 0;
5218 struct dpp_bootstrap_info *bi;
5219
5220 pos = os_strstr(cmd, " own=");
5221 if (!pos)
5222 return -1;
5223 pos += 5;
5224 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
5225 if (!bi) {
5226 wpa_printf(MSG_DEBUG,
5227 "DPP: Identified bootstrap info not found");
5228 return -1;
5229 }
5230
5231 pos = os_strstr(cmd, " iter=");
5232 if (pos) {
5233 iter = atoi(pos + 6);
5234 if (iter <= 0)
5235 return -1;
5236 }
5237
5238 pos = os_strstr(cmd, " listen=");
5239 if (pos) {
5240 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005241 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005242 return -1;
5243 }
5244
5245 wpas_dpp_chirp_stop(wpa_s);
5246 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005247 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07005248 wpa_s->dpp_qr_mutual = 0;
5249 wpa_s->dpp_chirp_bi = bi;
5250 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
5251 if (!wpa_s->dpp_presence_announcement)
5252 return -1;
5253 wpa_s->dpp_chirp_iter = iter;
5254 wpa_s->dpp_chirp_round = 0;
5255 wpa_s->dpp_chirp_scan_done = 0;
5256 wpa_s->dpp_chirp_listen = listen_freq;
5257
5258 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5259}
5260
5261
5262void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
5263{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005264 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07005265 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005266 offchannel_send_action_done(wpa_s);
5267 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
5268 }
5269 wpa_s->dpp_chirp_bi = NULL;
5270 wpabuf_free(wpa_s->dpp_presence_announcement);
5271 wpa_s->dpp_presence_announcement = NULL;
5272 if (wpa_s->dpp_chirp_listen)
5273 wpas_dpp_listen_stop(wpa_s);
5274 wpa_s->dpp_chirp_listen = 0;
5275 wpa_s->dpp_chirp_freq = 0;
5276 os_free(wpa_s->dpp_chirp_freqs);
5277 wpa_s->dpp_chirp_freqs = NULL;
5278 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
5279 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
5280 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
5281 wpas_abort_ongoing_scan(wpa_s);
5282 wpa_s->scan_res_handler = NULL;
5283 }
5284}
5285
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005286
Hai Shalom899fcc72020-10-19 14:38:18 -07005287int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005288{
Hai Shalom899fcc72020-10-19 14:38:18 -07005289 struct wpa_ssid *ssid;
5290 int iter = 1;
5291 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005292
Hai Shalom899fcc72020-10-19 14:38:18 -07005293 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
5294 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
5295 !ssid->dpp_csign) {
5296 wpa_printf(MSG_DEBUG,
5297 "DPP: Not a valid network profile for reconfiguration");
5298 return -1;
5299 }
5300
5301 pos = os_strstr(cmd, " iter=");
5302 if (pos) {
5303 iter = atoi(pos + 6);
5304 if (iter <= 0)
5305 return -1;
5306 }
5307
5308 if (wpa_s->dpp_auth) {
5309 wpa_printf(MSG_DEBUG,
5310 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
5311 return -1;
5312 }
5313
5314 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
5315 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
5316 ssid->dpp_csign_len,
5317 ssid->dpp_pp_key,
5318 ssid->dpp_pp_key_len);
5319 if (!wpa_s->dpp_reconfig_id) {
5320 wpa_printf(MSG_DEBUG,
5321 "DPP: Failed to generate E-id for reconfiguration");
5322 return -1;
5323 }
5324 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
5325 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
5326 wpa_s->own_disconnect_req = 1;
5327 wpa_supplicant_deauthenticate(
5328 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5329 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005330 wpas_dpp_chirp_stop(wpa_s);
5331 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005332 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005333 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005334 wpa_s->dpp_reconfig_ssid = ssid;
5335 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07005336 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005337 wpa_s->dpp_chirp_round = 0;
5338 wpa_s->dpp_chirp_scan_done = 0;
5339 wpa_s->dpp_chirp_listen = 0;
5340
5341 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5342}
5343
Hai Shalom899fcc72020-10-19 14:38:18 -07005344
Hai Shalom899fcc72020-10-19 14:38:18 -07005345int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
5346{
5347 int peer = -1;
5348 const char *pos, *value;
5349 struct dpp_authentication *auth = wpa_s->dpp_auth;
5350 u8 *bin;
5351 size_t bin_len;
5352 struct wpabuf *buf;
5353 bool tcp = false;
5354
5355 pos = os_strstr(cmd, " peer=");
5356 if (pos) {
5357 peer = atoi(pos + 6);
5358 if (!auth || !auth->waiting_cert ||
5359 (auth->peer_bi &&
5360 (unsigned int) peer != auth->peer_bi->id)) {
5361 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5362 tcp = true;
5363 }
5364 }
5365
5366 if (!auth || !auth->waiting_cert) {
5367 wpa_printf(MSG_DEBUG,
5368 "DPP: No authentication exchange waiting for certificate information");
5369 return -1;
5370 }
5371
5372 if (peer >= 0 &&
5373 (!auth->peer_bi ||
5374 (unsigned int) peer != auth->peer_bi->id) &&
5375 (!auth->tmp_peer_bi ||
5376 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5377 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5378 return -1;
5379 }
5380
5381 pos = os_strstr(cmd, " value=");
5382 if (!pos)
5383 return -1;
5384 value = pos + 7;
5385
5386 pos = os_strstr(cmd, " name=");
5387 if (!pos)
5388 return -1;
5389 pos += 6;
5390
5391 if (os_strncmp(pos, "status ", 7) == 0) {
5392 auth->force_conf_resp_status = atoi(value);
5393 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5394 }
5395
5396 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
5397 os_free(auth->trusted_eap_server_name);
5398 auth->trusted_eap_server_name = os_strdup(value);
5399 return auth->trusted_eap_server_name ? 0 : -1;
5400 }
5401
5402 bin = base64_decode(value, os_strlen(value), &bin_len);
5403 if (!bin)
5404 return -1;
5405 buf = wpabuf_alloc_copy(bin, bin_len);
5406 os_free(bin);
5407
5408 if (os_strncmp(pos, "caCert ", 7) == 0) {
5409 wpabuf_free(auth->cacert);
5410 auth->cacert = buf;
5411 return 0;
5412 }
5413
5414 if (os_strncmp(pos, "certBag ", 8) == 0) {
5415 wpabuf_free(auth->certbag);
5416 auth->certbag = buf;
5417 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5418 }
5419
5420 wpabuf_free(buf);
5421 return -1;
5422}
5423
Hai Shalom81f62d82019-07-22 12:10:00 -07005424#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07005425
5426
5427#ifdef CONFIG_DPP3
5428
5429#define DPP_PB_ANNOUNCE_PER_CHAN 3
5430
5431static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
5432static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
5433
5434
5435static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
5436 unsigned int freq, const u8 *dst,
5437 const u8 *src, const u8 *bssid,
5438 const u8 *data, size_t data_len,
5439 enum offchannel_send_action_result result)
5440{
5441 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5442 wpa_printf(MSG_DEBUG,
5443 "DPP: Failed to send push button announcement on %d MHz",
5444 freq);
5445 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
5446 wpa_s, NULL) < 0)
5447 wpas_dpp_push_button_stop(wpa_s);
5448 return;
5449 }
5450
5451 wpa_printf(MSG_DEBUG, "DPP: Push button announcement on %d MHz sent",
5452 freq);
5453 if (wpa_s->dpp_pb_discovery_done) {
5454 wpa_s->dpp_pb_announce_count = 0;
5455 wpa_printf(MSG_DEBUG,
5456 "DPP: Wait for push button announcement response and PKEX on %d MHz",
5457 freq);
5458 if (eloop_register_timeout(0, 500000, wpas_dpp_pb_next,
5459 wpa_s, NULL) < 0)
5460 wpas_dpp_push_button_stop(wpa_s);
5461 return;
5462 } else if (wpa_s->dpp_pb_announce_count >= DPP_PB_ANNOUNCE_PER_CHAN) {
5463 wpa_printf(MSG_DEBUG,
5464 "DPP: Wait for push button announcement response on %d MHz",
5465 freq);
5466 if (eloop_register_timeout(0, 50000, wpas_dpp_pb_next,
5467 wpa_s, NULL) < 0)
5468 wpas_dpp_push_button_stop(wpa_s);
5469 return;
5470 }
5471
5472 if (wpas_dpp_pb_announce(wpa_s, freq) < 0)
5473 wpas_dpp_push_button_stop(wpa_s);
5474}
5475
5476
5477static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq)
5478{
5479 struct wpabuf *msg;
5480 int type;
5481
5482 msg = wpa_s->dpp_pb_announcement;
5483 if (!msg)
5484 return -1;
5485
5486 wpa_s->dpp_pb_announce_count++;
5487 wpa_printf(MSG_DEBUG,
5488 "DPP: Send push button announcement %d/%d (%d MHz)",
5489 wpa_s->dpp_pb_announce_count, DPP_PB_ANNOUNCE_PER_CHAN,
5490 freq);
5491
5492 type = DPP_PA_PB_PRESENCE_ANNOUNCEMENT;
5493 if (wpa_s->dpp_pb_announce_count == 1)
5494 wpa_msg(wpa_s, MSG_INFO,
5495 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
5496 MAC2STR(broadcast), freq, type);
5497 if (offchannel_send_action(
5498 wpa_s, freq, broadcast, wpa_s->own_addr, broadcast,
5499 wpabuf_head(msg), wpabuf_len(msg),
5500 1000, wpas_dpp_pb_tx_status, 0) < 0)
5501 return -1;
5502
5503 return 0;
5504}
5505
5506
5507static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx)
5508{
5509 struct wpa_supplicant *wpa_s = eloop_ctx;
5510 struct os_reltime now;
5511 int freq;
5512
5513 if (!wpa_s->dpp_pb_freqs)
5514 return;
5515
5516 os_get_reltime(&now);
5517 offchannel_send_action_done(wpa_s);
5518
5519 if (os_reltime_expired(&now, &wpa_s->dpp_pb_time, 100)) {
5520 wpa_printf(MSG_DEBUG, "DPP: Push button wait time expired");
5521 wpas_dpp_push_button_stop(wpa_s);
5522 return;
5523 }
5524
5525 if (wpa_s->dpp_pb_freq_idx >= int_array_len(wpa_s->dpp_pb_freqs)) {
5526 wpa_printf(MSG_DEBUG,
5527 "DPP: Completed push button announcement round");
5528 wpa_s->dpp_pb_freq_idx = 0;
5529 if (wpa_s->dpp_pb_stop_iter > 0) {
5530 wpa_s->dpp_pb_stop_iter--;
5531
5532 if (wpa_s->dpp_pb_stop_iter == 1) {
5533 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5534 "wait for AP/Configurator to allow PKEX to be initiated");
5535 if (eloop_register_timeout(10, 0,
5536 wpas_dpp_pb_next,
5537 wpa_s, NULL) < 0) {
5538 wpas_dpp_push_button_stop(wpa_s);
5539 return;
5540 }
5541 return;
5542 }
5543
5544 if (wpa_s->dpp_pb_stop_iter == 0) {
5545 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5546 "start push button PKEX responder on the discovered channel (%d MHz)",
5547 wpa_s->dpp_pb_resp_freq);
5548 wpa_s->dpp_pb_discovery_done = true;
5549
5550 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
5551
5552 os_free(wpa_s->dpp_pkex_code);
5553 wpa_s->dpp_pkex_code = os_memdup(
5554 wpa_s->dpp_pb_c_nonce,
5555 wpa_s->dpp_pb_c_nonce_len);
5556 wpa_s->dpp_pkex_code_len =
5557 wpa_s->dpp_pb_c_nonce_len;
5558
5559 os_free(wpa_s->dpp_pkex_identifier);
5560 wpa_s->dpp_pkex_identifier =
5561 os_strdup("PBPKEX");
5562
5563 if (!wpa_s->dpp_pkex_code ||
5564 !wpa_s->dpp_pkex_identifier) {
5565 wpas_dpp_push_button_stop(wpa_s);
5566 return;
5567 }
5568
5569 wpa_s->dpp_pkex_ver = PKEX_VER_ONLY_2;
5570
5571 os_free(wpa_s->dpp_pkex_auth_cmd);
5572 wpa_s->dpp_pkex_auth_cmd = NULL;
5573 }
5574 }
5575 }
5576
5577 if (wpa_s->dpp_pb_discovery_done)
5578 freq = wpa_s->dpp_pb_resp_freq;
5579 else
5580 freq = wpa_s->dpp_pb_freqs[wpa_s->dpp_pb_freq_idx++];
5581 wpa_s->dpp_pb_announce_count = 0;
5582 if (!wpa_s->dpp_pb_announcement) {
5583 wpa_printf(MSG_DEBUG, "DPP: Push button announcements stopped");
5584 return;
5585 }
5586 if (wpas_dpp_pb_announce(wpa_s, freq) < 0) {
5587 wpas_dpp_push_button_stop(wpa_s);
5588 return;
5589 }
5590}
5591
5592
5593static void wpas_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
5594{
5595 struct wpa_supplicant *wpa_s = eloop_ctx;
5596
5597 wpa_printf(MSG_DEBUG,
5598 "DPP: Active push button Configurator mode expired");
5599 wpas_dpp_push_button_stop(wpa_s);
5600}
5601
5602
5603static int wpas_dpp_push_button_configurator(struct wpa_supplicant *wpa_s,
5604 const char *cmd)
5605{
5606 wpa_s->dpp_pb_configurator = true;
5607 wpa_s->dpp_pb_announce_time.sec = 0;
5608 wpa_s->dpp_pb_announce_time.usec = 0;
5609 str_clear_free(wpa_s->dpp_pb_cmd);
5610 wpa_s->dpp_pb_cmd = NULL;
5611 if (cmd) {
5612 wpa_s->dpp_pb_cmd = os_strdup(cmd);
5613 if (!wpa_s->dpp_pb_cmd)
5614 return -1;
5615 }
5616 eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
5617 wpa_s, NULL);
5618
5619 return 0;
5620}
5621
5622
5623static void wpas_dpp_pb_scan_res_handler(struct wpa_supplicant *wpa_s,
5624 struct wpa_scan_results *scan_res)
5625{
5626 if (!wpa_s->dpp_pb_time.sec && !wpa_s->dpp_pb_time.usec)
5627 return;
5628
5629 os_free(wpa_s->dpp_pb_freqs);
5630 wpa_s->dpp_pb_freqs = wpas_dpp_presence_ann_channels(wpa_s, NULL);
5631
5632 wpa_printf(MSG_DEBUG, "DPP: Scan completed for PB discovery");
5633 if (!wpa_s->dpp_pb_freqs ||
5634 eloop_register_timeout(0, 0, wpas_dpp_pb_next, wpa_s, NULL) < 0)
5635 wpas_dpp_push_button_stop(wpa_s);
5636}
5637
5638
5639int wpas_dpp_push_button(struct wpa_supplicant *wpa_s, const char *cmd)
5640{
5641 int res;
5642
5643 if (!wpa_s->dpp)
5644 return -1;
5645 wpas_dpp_push_button_stop(wpa_s);
5646 wpas_dpp_stop(wpa_s);
5647 wpas_dpp_chirp_stop(wpa_s);
5648
5649 os_get_reltime(&wpa_s->dpp_pb_time);
5650
5651 if (cmd &&
5652 (os_strstr(cmd, " role=configurator") ||
5653 os_strstr(cmd, " conf=")))
5654 return wpas_dpp_push_button_configurator(wpa_s, cmd);
5655
5656 wpa_s->dpp_pb_configurator = false;
5657
5658 wpa_s->dpp_pb_freq_idx = 0;
5659
5660 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
5661 if (res < 0)
5662 return -1;
5663 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
5664 if (!wpa_s->dpp_pb_bi)
5665 return -1;
5666
5667 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
5668 wpa_s->dpp_netrole = DPP_NETROLE_STA;
5669 wpa_s->dpp_qr_mutual = 0;
5670 wpa_s->dpp_pb_announcement =
5671 dpp_build_pb_announcement(wpa_s->dpp_pb_bi);
5672 if (!wpa_s->dpp_pb_announcement)
5673 return -1;
5674
5675 wpa_printf(MSG_DEBUG,
5676 "DPP: Scan to create channel list for PB discovery");
5677 wpa_s->scan_req = MANUAL_SCAN_REQ;
5678 wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
5679 wpa_supplicant_req_scan(wpa_s, 0, 0);
5680 return 0;
5681}
5682
5683
5684void wpas_dpp_push_button_stop(struct wpa_supplicant *wpa_s)
5685{
5686 if (!wpa_s->dpp)
5687 return;
5688 os_free(wpa_s->dpp_pb_freqs);
5689 wpa_s->dpp_pb_freqs = NULL;
5690 wpabuf_free(wpa_s->dpp_pb_announcement);
5691 wpa_s->dpp_pb_announcement = NULL;
5692 if (wpa_s->dpp_pb_bi) {
5693 char id[20];
5694
5695 os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
5696 dpp_bootstrap_remove(wpa_s->dpp, id);
5697 wpa_s->dpp_pb_bi = NULL;
5698 if (!wpa_s->dpp_pb_result_indicated) {
5699 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5700 wpa_s->dpp_pb_result_indicated = true;
5701 }
5702 }
5703
5704 wpa_s->dpp_pb_resp_freq = 0;
5705 wpa_s->dpp_pb_stop_iter = 0;
5706 wpa_s->dpp_pb_discovery_done = false;
5707 os_free(wpa_s->dpp_pb_cmd);
5708 wpa_s->dpp_pb_cmd = NULL;
5709
5710 eloop_cancel_timeout(wpas_dpp_pb_next, wpa_s, NULL);
5711 eloop_cancel_timeout(wpas_dpp_push_button_expire, wpa_s, NULL);
5712 if (wpas_dpp_pb_active(wpa_s)) {
5713 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
5714 if (!wpa_s->dpp_pb_result_indicated)
5715 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5716 }
5717 wpa_s->dpp_pb_time.sec = 0;
5718 wpa_s->dpp_pb_time.usec = 0;
5719 dpp_pkex_free(wpa_s->dpp_pkex);
5720 wpa_s->dpp_pkex = NULL;
5721 os_free(wpa_s->dpp_pkex_auth_cmd);
5722 wpa_s->dpp_pkex_auth_cmd = NULL;
5723
5724 wpa_s->dpp_pb_result_indicated = false;
5725
5726 str_clear_free(wpa_s->dpp_pb_cmd);
5727 wpa_s->dpp_pb_cmd = NULL;
5728
5729 if (wpa_s->scan_res_handler == wpas_dpp_pb_scan_res_handler) {
5730 wpas_abort_ongoing_scan(wpa_s);
5731 wpa_s->scan_res_handler = NULL;
5732 }
5733}
5734
5735#endif /* CONFIG_DPP3 */