blob: b6dbc98a5c5f4f5e1bddf03142340be74674ce37 [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"
20#include "rsn_supp/wpa.h"
21#include "rsn_supp/pmksa_cache.h"
22#include "wpa_supplicant_i.h"
23#include "config.h"
24#include "driver_i.h"
25#include "offchannel.h"
26#include "gas_query.h"
27#include "bss.h"
28#include "scan.h"
29#include "notify.h"
30#include "dpp_supplicant.h"
Gabriel Biren57ededa2021-09-03 16:08:50 +000031#include "aidl.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070032
33
34static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
35 unsigned int freq);
36static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom60840252021-02-19 19:02:11 -080037static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070038static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
39static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
40 unsigned int freq, const u8 *dst,
41 const u8 *src, const u8 *bssid,
42 const u8 *data, size_t data_len,
43 enum offchannel_send_action_result result);
Roshan Pius3a1667e2018-07-03 15:17:14 -070044static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
45static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
46static void
47wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
48 unsigned int freq, const u8 *dst,
49 const u8 *src, const u8 *bssid,
50 const u8 *data, size_t data_len,
51 enum offchannel_send_action_result result);
Hai Shaloma20dcd72022-02-04 13:43:00 -080052static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070053#ifdef CONFIG_DPP2
54static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
55 void *timeout_ctx);
Hai Shalom899fcc72020-10-19 14:38:18 -070056static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s);
57static int wpas_dpp_process_conf_obj(void *ctx,
58 struct dpp_authentication *auth);
Hai Shaloma20dcd72022-02-04 13:43:00 -080059static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070060#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070061
62static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
63
64/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
65 * a single transaction in progress at any point in time. */
66static const u8 TRANSACTION_ID = 1;
67
68
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070069/**
70 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
71 * @wpa_s: Pointer to wpa_supplicant data
72 * @cmd: DPP URI read from a QR Code
73 * Returns: Identifier of the stored info or -1 on failure
74 */
75int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
76{
77 struct dpp_bootstrap_info *bi;
78 struct dpp_authentication *auth = wpa_s->dpp_auth;
79
Hai Shalom021b0b52019-04-10 11:17:58 -070080 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070081 if (!bi)
82 return -1;
83
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070084 if (auth && auth->response_pending &&
85 dpp_notify_new_qr_code(auth, bi) == 1) {
86 wpa_printf(MSG_DEBUG,
87 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070088 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
89 " freq=%u type=%d",
90 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
91 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070092 offchannel_send_action(wpa_s, auth->curr_freq,
93 auth->peer_mac_addr, wpa_s->own_addr,
94 broadcast,
95 wpabuf_head(auth->resp_msg),
96 wpabuf_len(auth->resp_msg),
97 500, wpas_dpp_tx_status, 0);
98 }
99
Hai Shalom899fcc72020-10-19 14:38:18 -0700100#ifdef CONFIG_DPP2
101 dpp_controller_new_qr_code(wpa_s->dpp, bi);
102#endif /* CONFIG_DPP2 */
103
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700104 return bi->id;
105}
106
107
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800108/**
109 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
110 * @wpa_s: Pointer to wpa_supplicant data
111 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
112 * Returns: Identifier of the stored info or -1 on failure
113 */
114int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
115{
116 struct dpp_bootstrap_info *bi;
117
118 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
119 if (!bi)
120 return -1;
121
122 return bi->id;
123}
124
125
Hai Shalomfdcde762020-04-02 11:19:20 -0700126int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd)
127{
128 const char *pos;
129 struct dpp_bootstrap_info *peer_bi, *own_bi;
130
131 pos = os_strstr(cmd, " own=");
132 if (!pos)
133 return -1;
134 pos += 5;
135 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
136 if (!own_bi)
137 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700138 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700139
140 pos = os_strstr(cmd, " uri=");
141 if (!pos)
142 return -1;
143 pos += 5;
144 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
145 if (!peer_bi) {
146 wpa_printf(MSG_INFO,
147 "DPP: Failed to parse URI from NFC Handover Request");
148 return -1;
149 }
150
151 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
152 return -1;
153
154 return peer_bi->id;
155}
156
157
158int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd)
159{
160 const char *pos;
161 struct dpp_bootstrap_info *peer_bi, *own_bi;
162
163 pos = os_strstr(cmd, " own=");
164 if (!pos)
165 return -1;
166 pos += 5;
167 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
168 if (!own_bi)
169 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700170 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700171
172 pos = os_strstr(cmd, " uri=");
173 if (!pos)
174 return -1;
175 pos += 5;
176 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
177 if (!peer_bi) {
178 wpa_printf(MSG_INFO,
179 "DPP: Failed to parse URI from NFC Handover Select");
180 return -1;
181 }
182
183 if (peer_bi->curve != own_bi->curve) {
184 wpa_printf(MSG_INFO,
185 "DPP: Peer (NFC Handover Selector) used different curve");
186 return -1;
187 }
188
189 return peer_bi->id;
190}
191
192
Roshan Pius3a1667e2018-07-03 15:17:14 -0700193static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
194{
195 struct wpa_supplicant *wpa_s = eloop_ctx;
196 struct dpp_authentication *auth = wpa_s->dpp_auth;
197
198 if (!auth || !auth->resp_msg)
199 return;
200
201 wpa_printf(MSG_DEBUG,
202 "DPP: Retry Authentication Response after timeout");
203 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
204 " freq=%u type=%d",
205 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
206 DPP_PA_AUTHENTICATION_RESP);
207 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
208 wpa_s->own_addr, broadcast,
209 wpabuf_head(auth->resp_msg),
210 wpabuf_len(auth->resp_msg),
211 500, wpas_dpp_tx_status, 0);
212}
213
214
215static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
216{
217 struct dpp_authentication *auth = wpa_s->dpp_auth;
218 unsigned int wait_time, max_tries;
219
220 if (!auth || !auth->resp_msg)
221 return;
222
223 if (wpa_s->dpp_resp_max_tries)
224 max_tries = wpa_s->dpp_resp_max_tries;
225 else
226 max_tries = 5;
227 auth->auth_resp_tries++;
228 if (auth->auth_resp_tries >= max_tries) {
229 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
230 offchannel_send_action_done(wpa_s);
231 dpp_auth_deinit(wpa_s->dpp_auth);
232 wpa_s->dpp_auth = NULL;
233 return;
234 }
235
236 if (wpa_s->dpp_resp_retry_time)
237 wait_time = wpa_s->dpp_resp_retry_time;
238 else
239 wait_time = 1000;
240 wpa_printf(MSG_DEBUG,
241 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
242 wait_time);
243 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
244 eloop_register_timeout(wait_time / 1000,
245 (wait_time % 1000) * 1000,
246 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
247}
248
249
Hai Shalom021b0b52019-04-10 11:17:58 -0700250static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
251{
252 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700253 wpa_s->suitable_network = 0;
254 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700255 wpa_s->disconnected = 0;
256 wpa_s->reassociate = 1;
257 wpa_s->scan_runs = 0;
258 wpa_s->normal_scans = 0;
259 wpa_supplicant_cancel_sched_scan(wpa_s);
260 wpa_supplicant_req_scan(wpa_s, 0, 0);
261}
262
263
Hai Shalomc3565922019-10-28 11:58:20 -0700264#ifdef CONFIG_DPP2
265
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700266static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s,
267 unsigned int freq,
268 unsigned int wait_time)
269{
270 struct os_reltime now, res;
271 unsigned int remaining;
272
273 if (!wpa_s->dpp_listen_freq)
274 return;
275
276 os_get_reltime(&now);
277 if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) {
278 os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res);
279 remaining = res.sec * 1000 + res.usec / 1000;
280 } else {
281 remaining = 0;
282 }
283 if (wpa_s->dpp_listen_freq == freq && remaining > wait_time)
284 return;
285
286 wpa_printf(MSG_DEBUG,
287 "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms",
288 wpa_s->dpp_listen_freq, remaining, freq, wait_time);
289 wpas_dpp_listen_stop(wpa_s);
290
291 /* TODO: Restart listen in some cases after TX? */
292}
293
294
Hai Shalomc3565922019-10-28 11:58:20 -0700295static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
296 void *timeout_ctx)
297{
298 struct wpa_supplicant *wpa_s = eloop_ctx;
299 struct dpp_authentication *auth = wpa_s->dpp_auth;
300 enum dpp_status_error result;
301
Hai Shaloma20dcd72022-02-04 13:43:00 -0800302 if ((!auth || !auth->conn_status_requested) &&
303 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700304 return;
305
306 wpa_printf(MSG_DEBUG,
307 "DPP: Connection timeout - report Connection Status Result");
308 if (wpa_s->suitable_network)
309 result = DPP_STATUS_AUTH_FAILURE;
310 else if (wpa_s->no_suitable_network)
311 result = DPP_STATUS_NO_AP;
312 else
313 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800314 if (wpa_s->wpa_state == WPA_SCANNING)
315 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700316 wpas_dpp_send_conn_status_result(wpa_s, result);
317}
318
319
320static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
321{
322 char *str, *end, *pos;
323 size_t len;
324 unsigned int i;
325 u8 last_op_class = 0;
326 int res;
327
328 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
329 return NULL;
330
331 len = wpa_s->num_last_scan_freqs * 8;
332 str = os_zalloc(len);
333 if (!str)
334 return NULL;
335 end = str + len;
336 pos = str;
337
338 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
339 enum hostapd_hw_mode mode;
340 u8 op_class, channel;
341
342 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
343 0, 0, &op_class, &channel);
344 if (mode == NUM_HOSTAPD_MODES)
345 continue;
346 if (op_class == last_op_class)
347 res = os_snprintf(pos, end - pos, ",%d", channel);
348 else
349 res = os_snprintf(pos, end - pos, "%s%d/%d",
350 pos == str ? "" : ",",
351 op_class, channel);
352 if (os_snprintf_error(end - pos, res)) {
353 *pos = '\0';
354 break;
355 }
356 pos += res;
357 last_op_class = op_class;
358 }
359
360 if (pos == str) {
361 os_free(str);
362 str = NULL;
363 }
364 return str;
365}
366
367
368void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
369 enum dpp_status_error result)
370{
371 struct wpabuf *msg;
372 const char *channel_list = NULL;
373 char *channel_list_buf = NULL;
374 struct wpa_ssid *ssid = wpa_s->current_ssid;
375 struct dpp_authentication *auth = wpa_s->dpp_auth;
376
377 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
378
Hai Shaloma20dcd72022-02-04 13:43:00 -0800379 if ((!auth || !auth->conn_status_requested) &&
380 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700381 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800382
Hai Shalomc3565922019-10-28 11:58:20 -0700383 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
384 result);
385
386 if (result == DPP_STATUS_NO_AP) {
387 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
388 channel_list = channel_list_buf;
389 }
390
Hai Shaloma20dcd72022-02-04 13:43:00 -0800391 if (!auth || !auth->conn_status_requested) {
392 dpp_tcp_send_conn_status(wpa_s->dpp, result,
393 ssid ? ssid->ssid :
394 wpa_s->dpp_last_ssid,
395 ssid ? ssid->ssid_len :
396 wpa_s->dpp_last_ssid_len,
397 channel_list);
398 os_free(channel_list_buf);
399 return;
400 }
401
402 auth->conn_status_requested = 0;
403
Hai Shalomc3565922019-10-28 11:58:20 -0700404 msg = dpp_build_conn_status_result(auth, result,
405 ssid ? ssid->ssid :
406 wpa_s->dpp_last_ssid,
407 ssid ? ssid->ssid_len :
408 wpa_s->dpp_last_ssid_len,
409 channel_list);
410 os_free(channel_list_buf);
411 if (!msg) {
412 dpp_auth_deinit(wpa_s->dpp_auth);
413 wpa_s->dpp_auth = NULL;
414 return;
415 }
416
417 wpa_msg(wpa_s, MSG_INFO,
418 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
419 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
420 DPP_PA_CONNECTION_STATUS_RESULT);
421 offchannel_send_action(wpa_s, auth->curr_freq,
422 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
423 wpabuf_head(msg), wpabuf_len(msg),
424 500, wpas_dpp_tx_status, 0);
425 wpabuf_free(msg);
426
427 /* This exchange will be terminated in the TX status handler */
428 auth->remove_on_tx_status = 1;
429
430 return;
431}
432
433
434void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
435{
436 struct dpp_authentication *auth = wpa_s->dpp_auth;
437
Hai Shaloma20dcd72022-02-04 13:43:00 -0800438 if ((auth && auth->conn_status_requested) ||
439 dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700440 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
441}
442
443#endif /* CONFIG_DPP2 */
444
445
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700446static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
447 unsigned int freq, const u8 *dst,
448 const u8 *src, const u8 *bssid,
449 const u8 *data, size_t data_len,
450 enum offchannel_send_action_result result)
451{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700452 const char *res_txt;
453 struct dpp_authentication *auth = wpa_s->dpp_auth;
454
455 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
456 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
457 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700458 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700459 " result=%s", freq, MAC2STR(dst), res_txt);
460 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
461 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700462
463 if (!wpa_s->dpp_auth) {
464 wpa_printf(MSG_DEBUG,
465 "DPP: Ignore TX status since there is no ongoing authentication exchange");
466 return;
467 }
468
Hai Shalom021b0b52019-04-10 11:17:58 -0700469#ifdef CONFIG_DPP2
470 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700471 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700472 wpa_printf(MSG_DEBUG,
473 "DPP: Try to connect after completed configuration result");
474 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700475 if (auth->conn_status_requested) {
476 wpa_printf(MSG_DEBUG,
477 "DPP: Start 15 second timeout for reporting connection status result");
478 eloop_cancel_timeout(
479 wpas_dpp_conn_status_result_timeout,
480 wpa_s, NULL);
481 eloop_register_timeout(
482 15, 0, wpas_dpp_conn_status_result_timeout,
483 wpa_s, NULL);
484 } else {
485 dpp_auth_deinit(wpa_s->dpp_auth);
486 wpa_s->dpp_auth = NULL;
487 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700488 return;
489 }
490#endif /* CONFIG_DPP2 */
491
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700492 if (wpa_s->dpp_auth->remove_on_tx_status) {
493 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700494 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700495 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700496 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800497 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
498 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700499 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
500 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700501#ifdef CONFIG_DPP2
502 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
503 wpa_s, NULL);
504#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700505 offchannel_send_action_done(wpa_s);
506 dpp_auth_deinit(wpa_s->dpp_auth);
507 wpa_s->dpp_auth = NULL;
508 return;
509 }
510
511 if (wpa_s->dpp_auth_ok_on_ack)
512 wpas_dpp_auth_success(wpa_s, 1);
513
514 if (!is_broadcast_ether_addr(dst) &&
515 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
516 wpa_printf(MSG_DEBUG,
517 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700518 if (auth->waiting_auth_resp) {
519 /* In case of DPP Authentication Request frame, move to
520 * the next channel immediately. */
521 offchannel_send_action_done(wpa_s);
522 wpas_dpp_auth_init_next(wpa_s);
523 return;
524 }
525 if (auth->waiting_auth_conf) {
526 wpas_dpp_auth_resp_retry(wpa_s);
527 return;
528 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700529 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700530
Hai Shalom60840252021-02-19 19:02:11 -0800531 if (auth->waiting_auth_conf &&
532 auth->auth_resp_status == DPP_STATUS_OK) {
533 /* Make sure we do not get stuck waiting for Auth Confirm
534 * indefinitely after successfully transmitted Auth Response to
535 * allow new authentication exchanges to be started. */
536 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
537 NULL);
538 eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
539 wpa_s, NULL);
540 }
541
Roshan Pius3a1667e2018-07-03 15:17:14 -0700542 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
543 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
544 /* Allow timeout handling to stop iteration if no response is
545 * received from a peer that has ACKed a request. */
546 auth->auth_req_ack = 1;
547 }
548
549 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
550 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
551 wpa_printf(MSG_DEBUG,
552 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
553 wpa_s->dpp_auth->curr_freq,
554 wpa_s->dpp_auth->neg_freq);
555 offchannel_send_action_done(wpa_s);
556 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
557 }
558
559 if (wpa_s->dpp_auth_ok_on_ack)
560 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700561}
562
563
564static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
565{
566 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700567 struct dpp_authentication *auth = wpa_s->dpp_auth;
568 unsigned int freq;
569 struct os_reltime now, diff;
570 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700571
Roshan Pius3a1667e2018-07-03 15:17:14 -0700572 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700573 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700574
575 wait_time = wpa_s->dpp_resp_wait_time ?
576 wpa_s->dpp_resp_wait_time : 2000;
577 os_get_reltime(&now);
578 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
579 diff_ms = diff.sec * 1000 + diff.usec / 1000;
580 wpa_printf(MSG_DEBUG,
581 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
582 wait_time, diff_ms);
583
584 if (auth->auth_req_ack && diff_ms >= wait_time) {
585 /* Peer ACK'ed Authentication Request frame, but did not reply
586 * with Authentication Response frame within two seconds. */
587 wpa_printf(MSG_INFO,
588 "DPP: No response received from responder - stopping initiation attempt");
589 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800590 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700591 offchannel_send_action_done(wpa_s);
592 wpas_dpp_listen_stop(wpa_s);
593 dpp_auth_deinit(auth);
594 wpa_s->dpp_auth = NULL;
595 return;
596 }
597
598 if (diff_ms >= wait_time) {
599 /* Authentication Request frame was not ACK'ed and no reply
600 * was receiving within two seconds. */
601 wpa_printf(MSG_DEBUG,
602 "DPP: Continue Initiator channel iteration");
603 offchannel_send_action_done(wpa_s);
604 wpas_dpp_listen_stop(wpa_s);
605 wpas_dpp_auth_init_next(wpa_s);
606 return;
607 }
608
609 /* Driver did not support 2000 ms long wait_time with TX command, so
610 * schedule listen operation to continue waiting for the response.
611 *
612 * DPP listen operations continue until stopped, so simply schedule a
613 * new call to this function at the point when the two second reply
614 * wait has expired. */
615 wait_time -= diff_ms;
616
617 freq = auth->curr_freq;
618 if (auth->neg_freq > 0)
619 freq = auth->neg_freq;
620 wpa_printf(MSG_DEBUG,
621 "DPP: Continue reply wait on channel %u MHz for %u ms",
622 freq, wait_time);
623 wpa_s->dpp_in_response_listen = 1;
624 wpas_dpp_listen_start(wpa_s, freq);
625
626 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
627 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700628}
629
630
Hai Shalom60840252021-02-19 19:02:11 -0800631static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
632{
633 struct wpa_supplicant *wpa_s = eloop_ctx;
634 struct dpp_authentication *auth = wpa_s->dpp_auth;
635
636 if (!auth || !auth->waiting_auth_conf)
637 return;
638
639 wpa_printf(MSG_DEBUG,
640 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
641 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
642 offchannel_send_action_done(wpa_s);
643 dpp_auth_deinit(auth);
644 wpa_s->dpp_auth = NULL;
645}
646
647
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700648static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
649 struct dpp_authentication *auth)
650{
651#ifdef CONFIG_TESTING_OPTIONS
652 if (wpa_s->dpp_config_obj_override)
653 auth->config_obj_override =
654 os_strdup(wpa_s->dpp_config_obj_override);
655 if (wpa_s->dpp_discovery_override)
656 auth->discovery_override =
657 os_strdup(wpa_s->dpp_discovery_override);
658 if (wpa_s->dpp_groups_override)
659 auth->groups_override =
660 os_strdup(wpa_s->dpp_groups_override);
661 auth->ignore_netaccesskey_mismatch =
662 wpa_s->dpp_ignore_netaccesskey_mismatch;
663#endif /* CONFIG_TESTING_OPTIONS */
664}
665
666
Roshan Pius3a1667e2018-07-03 15:17:14 -0700667static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
668{
669 struct wpa_supplicant *wpa_s = eloop_ctx;
670
671 if (!wpa_s->dpp_auth)
672 return;
673 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
674 wpas_dpp_auth_init_next(wpa_s);
675}
676
677
678static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
679{
680 struct dpp_authentication *auth = wpa_s->dpp_auth;
681 const u8 *dst;
682 unsigned int wait_time, max_wait_time, freq, max_tries, used;
683 struct os_reltime now, diff;
684
685 wpa_s->dpp_in_response_listen = 0;
686 if (!auth)
687 return -1;
688
689 if (auth->freq_idx == 0)
690 os_get_reltime(&wpa_s->dpp_init_iter_start);
691
692 if (auth->freq_idx >= auth->num_freq) {
693 auth->num_freq_iters++;
694 if (wpa_s->dpp_init_max_tries)
695 max_tries = wpa_s->dpp_init_max_tries;
696 else
697 max_tries = 5;
698 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
699 wpa_printf(MSG_INFO,
700 "DPP: No response received from responder - stopping initiation attempt");
701 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800702 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700703 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
704 wpa_s, NULL);
705 offchannel_send_action_done(wpa_s);
706 dpp_auth_deinit(wpa_s->dpp_auth);
707 wpa_s->dpp_auth = NULL;
708 return -1;
709 }
710 auth->freq_idx = 0;
711 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
712 if (wpa_s->dpp_init_retry_time)
713 wait_time = wpa_s->dpp_init_retry_time;
714 else
715 wait_time = 10000;
716 os_get_reltime(&now);
717 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
718 used = diff.sec * 1000 + diff.usec / 1000;
719 if (used > wait_time)
720 wait_time = 0;
721 else
722 wait_time -= used;
723 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
724 wait_time);
725 eloop_register_timeout(wait_time / 1000,
726 (wait_time % 1000) * 1000,
727 wpas_dpp_init_timeout, wpa_s,
728 NULL);
729 return 0;
730 }
731 freq = auth->freq[auth->freq_idx++];
732 auth->curr_freq = freq;
733
Hai Shalom60840252021-02-19 19:02:11 -0800734 if (!is_zero_ether_addr(auth->peer_mac_addr))
735 dst = auth->peer_mac_addr;
736 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700737 dst = broadcast;
738 else
739 dst = auth->peer_bi->mac_addr;
740 wpa_s->dpp_auth_ok_on_ack = 0;
741 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
742 wait_time = wpa_s->max_remain_on_chan;
743 max_wait_time = wpa_s->dpp_resp_wait_time ?
744 wpa_s->dpp_resp_wait_time : 2000;
745 if (wait_time > max_wait_time)
746 wait_time = max_wait_time;
747 wait_time += 10; /* give the driver some extra time to complete */
748 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
749 wpas_dpp_reply_wait_timeout,
750 wpa_s, NULL);
751 wait_time -= 10;
752 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
753 wpa_printf(MSG_DEBUG,
754 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
755 freq, auth->neg_freq);
756 }
757 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
758 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
759 auth->auth_req_ack = 0;
760 os_get_reltime(&wpa_s->dpp_last_init);
761 return offchannel_send_action(wpa_s, freq, dst,
762 wpa_s->own_addr, broadcast,
763 wpabuf_head(auth->req_msg),
764 wpabuf_len(auth->req_msg),
765 wait_time, wpas_dpp_tx_status, 0);
766}
767
768
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700769int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
770{
771 const char *pos;
772 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700773 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700774 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
775 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700776 int tcp = 0;
777#ifdef CONFIG_DPP2
778 int tcp_port = DPP_TCP_PORT;
779 struct hostapd_ip_addr ipaddr;
780 char *addr;
781#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700782
783 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800784 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700785
786 pos = os_strstr(cmd, " peer=");
787 if (!pos)
788 return -1;
789 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700790 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700791 if (!peer_bi) {
792 wpa_printf(MSG_INFO,
793 "DPP: Could not find bootstrapping info for the identified peer");
794 return -1;
795 }
796
Hai Shalom81f62d82019-07-22 12:10:00 -0700797#ifdef CONFIG_DPP2
798 pos = os_strstr(cmd, " tcp_port=");
799 if (pos) {
800 pos += 10;
801 tcp_port = atoi(pos);
802 }
803
804 addr = get_param(cmd, " tcp_addr=");
805 if (addr) {
806 int res;
807
808 res = hostapd_parse_ip_addr(addr, &ipaddr);
809 os_free(addr);
810 if (res)
811 return -1;
812 tcp = 1;
813 }
814#endif /* CONFIG_DPP2 */
815
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700816 pos = os_strstr(cmd, " own=");
817 if (pos) {
818 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700819 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700820 if (!own_bi) {
821 wpa_printf(MSG_INFO,
822 "DPP: Could not find bootstrapping info for the identified local entry");
823 return -1;
824 }
825
826 if (peer_bi->curve != own_bi->curve) {
827 wpa_printf(MSG_INFO,
828 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
829 peer_bi->curve->name, own_bi->curve->name);
830 return -1;
831 }
832 }
833
834 pos = os_strstr(cmd, " role=");
835 if (pos) {
836 pos += 6;
837 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700838 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700839 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700840 allowed_roles = DPP_CAPAB_ENROLLEE;
841 else if (os_strncmp(pos, "either", 6) == 0)
842 allowed_roles = DPP_CAPAB_CONFIGURATOR |
843 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700844 else
845 goto fail;
846 }
847
848 pos = os_strstr(cmd, " netrole=");
849 if (pos) {
850 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800851 if (os_strncmp(pos, "ap", 2) == 0)
852 wpa_s->dpp_netrole = DPP_NETROLE_AP;
853 else if (os_strncmp(pos, "configurator", 12) == 0)
854 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
855 else
856 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700857 } else {
858 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700859 }
860
Roshan Pius3a1667e2018-07-03 15:17:14 -0700861 pos = os_strstr(cmd, " neg_freq=");
862 if (pos)
863 neg_freq = atoi(pos + 10);
864
Hai Shalom81f62d82019-07-22 12:10:00 -0700865 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700866 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700867 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800868 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
869 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700870 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
871 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700872#ifdef CONFIG_DPP2
873 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
874 wpa_s, NULL);
875#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700876 offchannel_send_action_done(wpa_s);
877 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800878 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700879 }
880
Hai Shalomfdcde762020-04-02 11:19:20 -0700881 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
882 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700883 if (!auth)
884 goto fail;
885 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700886 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700887 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800888 goto fail;
889 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700890
Hai Shalom81f62d82019-07-22 12:10:00 -0700891 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700892
Roshan Pius3a1667e2018-07-03 15:17:14 -0700893 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700894 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700895
Hai Shalom81f62d82019-07-22 12:10:00 -0700896#ifdef CONFIG_DPP2
897 if (tcp)
Hai Shalom899fcc72020-10-19 14:38:18 -0700898 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
899 wpa_s->conf->dpp_name, DPP_NETROLE_STA,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800900 wpa_s, wpa_s, wpas_dpp_process_conf_obj,
901 wpas_dpp_tcp_msg_sent);
Hai Shalom81f62d82019-07-22 12:10:00 -0700902#endif /* CONFIG_DPP2 */
903
904 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700905 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700906fail:
907 return -1;
908}
909
910
911struct wpas_dpp_listen_work {
912 unsigned int freq;
913 unsigned int duration;
914 struct wpabuf *probe_resp_ie;
915};
916
917
918static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
919{
920 if (!lwork)
921 return;
922 os_free(lwork);
923}
924
925
926static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
927{
928 struct wpas_dpp_listen_work *lwork;
929
930 if (!wpa_s->dpp_listen_work)
931 return;
932
933 lwork = wpa_s->dpp_listen_work->ctx;
934 wpas_dpp_listen_work_free(lwork);
935 radio_work_done(wpa_s->dpp_listen_work);
936 wpa_s->dpp_listen_work = NULL;
937}
938
939
940static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
941{
942 struct wpa_supplicant *wpa_s = work->wpa_s;
943 struct wpas_dpp_listen_work *lwork = work->ctx;
944
945 if (deinit) {
946 if (work->started) {
947 wpa_s->dpp_listen_work = NULL;
948 wpas_dpp_listen_stop(wpa_s);
949 }
950 wpas_dpp_listen_work_free(lwork);
951 return;
952 }
953
954 wpa_s->dpp_listen_work = work;
955
956 wpa_s->dpp_pending_listen_freq = lwork->freq;
957
958 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
959 wpa_s->max_remain_on_chan) < 0) {
960 wpa_printf(MSG_DEBUG,
961 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
962 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800963 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700964 wpas_dpp_listen_work_done(wpa_s);
965 wpa_s->dpp_pending_listen_freq = 0;
966 return;
967 }
968 wpa_s->off_channel_freq = 0;
969 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700970 wpa_drv_dpp_listen(wpa_s, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700971}
972
973
974static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
975 unsigned int freq)
976{
977 struct wpas_dpp_listen_work *lwork;
978
979 if (wpa_s->dpp_listen_work) {
980 wpa_printf(MSG_DEBUG,
981 "DPP: Reject start_listen since dpp_listen_work already exists");
982 return -1;
983 }
984
985 if (wpa_s->dpp_listen_freq)
986 wpas_dpp_listen_stop(wpa_s);
987 wpa_s->dpp_listen_freq = freq;
988
989 lwork = os_zalloc(sizeof(*lwork));
990 if (!lwork)
991 return -1;
992 lwork->freq = freq;
993
994 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
995 lwork) < 0) {
996 wpas_dpp_listen_work_free(lwork);
997 return -1;
998 }
999
1000 return 0;
1001}
1002
1003
1004int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
1005{
1006 int freq;
1007
1008 freq = atoi(cmd);
1009 if (freq <= 0)
1010 return -1;
1011
1012 if (os_strstr(cmd, " role=configurator"))
1013 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
1014 else if (os_strstr(cmd, " role=enrollee"))
1015 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
1016 else
1017 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
1018 DPP_CAPAB_ENROLLEE;
1019 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001020 if (os_strstr(cmd, " netrole=ap"))
1021 wpa_s->dpp_netrole = DPP_NETROLE_AP;
1022 else if (os_strstr(cmd, " netrole=configurator"))
1023 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
1024 else
1025 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001026 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1027 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1028 freq);
1029 return 0;
1030 }
1031
1032 return wpas_dpp_listen_start(wpa_s, freq);
1033}
1034
1035
1036void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1037{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001038 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001039 if (!wpa_s->dpp_listen_freq)
1040 return;
1041
1042 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1043 wpa_s->dpp_listen_freq);
1044 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001045 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001046 wpa_s->dpp_listen_freq = 0;
1047 wpas_dpp_listen_work_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001048 radio_remove_works(wpa_s, "dpp-listen", 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001049}
1050
1051
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001052void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1053 unsigned int freq, unsigned int duration)
1054{
1055 if (wpa_s->dpp_listen_freq != freq)
1056 return;
1057
1058 wpa_printf(MSG_DEBUG,
1059 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
1060 freq, duration);
1061 os_get_reltime(&wpa_s->dpp_listen_end);
1062 wpa_s->dpp_listen_end.usec += duration * 1000;
1063 while (wpa_s->dpp_listen_end.usec >= 1000000) {
1064 wpa_s->dpp_listen_end.sec++;
1065 wpa_s->dpp_listen_end.usec -= 1000000;
1066 }
1067}
1068
1069
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001070void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1071 unsigned int freq)
1072{
1073 wpas_dpp_listen_work_done(wpa_s);
1074
Roshan Pius3a1667e2018-07-03 15:17:14 -07001075 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1076 unsigned int new_freq;
1077
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001078 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001079 if (wpa_s->dpp_auth->neg_freq > 0)
1080 new_freq = wpa_s->dpp_auth->neg_freq;
1081 else
1082 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001083 wpa_printf(MSG_DEBUG,
1084 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001085 new_freq);
1086 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001087 return;
1088 }
1089
1090 if (wpa_s->dpp_listen_freq) {
1091 /* Continue listen with a new remain-on-channel */
1092 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1093 }
1094}
1095
1096
1097static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1098 const u8 *hdr, const u8 *buf, size_t len,
1099 unsigned int freq)
1100{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001101 const u8 *r_bootstrap, *i_bootstrap;
1102 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001103 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1104
1105 if (!wpa_s->dpp)
1106 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001107
1108 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1109 MAC2STR(src));
1110
Hai Shalomfdcde762020-04-02 11:19:20 -07001111#ifdef CONFIG_DPP2
1112 wpas_dpp_chirp_stop(wpa_s);
1113#endif /* CONFIG_DPP2 */
1114
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001115 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1116 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001117 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1118 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1119 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001120 return;
1121 }
1122 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1123 r_bootstrap, r_bootstrap_len);
1124
1125 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1126 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001127 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1128 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1129 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001130 return;
1131 }
1132 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1133 i_bootstrap, i_bootstrap_len);
1134
1135 /* Try to find own and peer bootstrapping key matches based on the
1136 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001137 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1138 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001139 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001140 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1141 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001142 return;
1143 }
1144
1145 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001146 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1147 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001148 return;
1149 }
1150
Sunil Ravia04bd252022-05-02 22:54:18 -07001151 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001152 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001153 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001154 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001155 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1156 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001157 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001158 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001159 if (!wpa_s->dpp_auth) {
1160 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1161 return;
1162 }
1163 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001164 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001165 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001166 dpp_auth_deinit(wpa_s->dpp_auth);
1167 wpa_s->dpp_auth = NULL;
1168 return;
1169 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001170 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1171
Roshan Pius3a1667e2018-07-03 15:17:14 -07001172 if (wpa_s->dpp_listen_freq &&
1173 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1174 wpa_printf(MSG_DEBUG,
1175 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1176 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1177 wpas_dpp_listen_stop(wpa_s);
1178 }
1179
1180 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1181 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1182 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001183 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1184 src, wpa_s->own_addr, broadcast,
1185 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1186 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1187 500, wpas_dpp_tx_status, 0);
1188}
1189
1190
Hai Shaloma20dcd72022-02-04 13:43:00 -08001191void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
1192{
1193 struct dpp_authentication *auth = wpa_s->dpp_auth;
1194 int freq;
1195
1196 if (!wpa_s->dpp_gas_server || !auth)
1197 return;
1198
1199 freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
1200 if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
1201 return; /* listen state is already in progress */
1202
1203 wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
1204 wpa_s->dpp_in_response_listen = 1;
1205 wpas_dpp_listen_start(wpa_s, freq);
1206}
1207
1208
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001209static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1210{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001211 struct dpp_authentication *auth = wpa_s->dpp_auth;
1212
1213 wpa_printf(MSG_DEBUG,
1214 "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
1215 auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
1216 !!wpa_s->dpp_listen_work);
1217 wpa_s->dpp_gas_server = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001218}
1219
1220
1221static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001222 struct dpp_authentication *auth,
1223 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001224{
1225 struct wpa_ssid *ssid;
1226
Hai Shalom021b0b52019-04-10 11:17:58 -07001227#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001228 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001229#ifdef CONFIG_SAE
1230 struct wpa_driver_capa capa;
1231 int res;
1232
1233 res = wpa_drv_get_capa(wpa_s, &capa);
1234 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001235 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1236 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001237 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1238 wpa_printf(MSG_DEBUG,
1239 "DPP: SAE not supported by the driver");
1240 return NULL;
1241 }
1242#else /* CONFIG_SAE */
1243 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1244 return NULL;
1245#endif /* CONFIG_SAE */
1246 }
1247#endif /* CONFIG_DPP2 */
1248
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001249 ssid = wpa_config_add_network(wpa_s->conf);
1250 if (!ssid)
1251 return NULL;
1252 wpas_notify_network_added(wpa_s, ssid);
1253 wpa_config_set_network_defaults(ssid);
1254 ssid->disabled = 1;
1255
Hai Shalomc3565922019-10-28 11:58:20 -07001256 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001257 if (!ssid->ssid)
1258 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001259 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1260 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001261
Hai Shalomc3565922019-10-28 11:58:20 -07001262 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001263 if (dpp_akm_dpp(conf->akm)) {
1264 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1265 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1266 }
Hai Shalomc3565922019-10-28 11:58:20 -07001267 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001268 if (!ssid->dpp_connector)
1269 goto fail;
1270 }
1271
Hai Shalomc3565922019-10-28 11:58:20 -07001272 if (conf->c_sign_key) {
1273 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001274 if (!ssid->dpp_csign)
1275 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001276 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1277 wpabuf_len(conf->c_sign_key));
1278 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001279 }
1280
Hai Shalom899fcc72020-10-19 14:38:18 -07001281 if (conf->pp_key) {
1282 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1283 if (!ssid->dpp_pp_key)
1284 goto fail;
1285 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1286 wpabuf_len(conf->pp_key));
1287 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1288 }
1289
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001290 if (auth->net_access_key) {
1291 ssid->dpp_netaccesskey =
1292 os_malloc(wpabuf_len(auth->net_access_key));
1293 if (!ssid->dpp_netaccesskey)
1294 goto fail;
1295 os_memcpy(ssid->dpp_netaccesskey,
1296 wpabuf_head(auth->net_access_key),
1297 wpabuf_len(auth->net_access_key));
1298 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1299 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1300 }
1301
Hai Shalomc3565922019-10-28 11:58:20 -07001302 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1303 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001304 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001305 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001306 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001307 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1308 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001309 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001310 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1311 WPA_KEY_MGMT_FT_SAE;
1312 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001313 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001314 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001315 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001316 goto fail;
1317 wpa_config_update_psk(ssid);
1318 ssid->export_keys = 1;
1319 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001320 ssid->psk_set = conf->psk_set;
1321 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001322 }
1323 }
1324
Hai Shalom899fcc72020-10-19 14:38:18 -07001325#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1326 if (conf->akm == DPP_AKM_DOT1X) {
1327 int i;
1328 char name[100], blobname[128];
1329 struct wpa_config_blob *blob;
1330
1331 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1332 WPA_KEY_MGMT_IEEE8021X_SHA256 |
1333 WPA_KEY_MGMT_IEEE8021X_SHA256;
1334 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1335
1336 if (conf->cacert) {
1337 /* caCert is DER-encoded X.509v3 certificate for the
1338 * server certificate if that is different from the
1339 * trust root included in certBag. */
1340 /* TODO: ssid->eap.cert.ca_cert */
1341 }
1342
1343 if (conf->certs) {
1344 for (i = 0; ; i++) {
1345 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1346 i);
1347 if (!wpa_config_get_blob(wpa_s->conf, name))
1348 break;
1349 }
1350
1351 blob = os_zalloc(sizeof(*blob));
1352 if (!blob)
1353 goto fail;
1354 blob->len = wpabuf_len(conf->certs);
1355 blob->name = os_strdup(name);
1356 blob->data = os_malloc(blob->len);
1357 if (!blob->name || !blob->data) {
1358 wpa_config_free_blob(blob);
1359 goto fail;
1360 }
1361 os_memcpy(blob->data, wpabuf_head(conf->certs),
1362 blob->len);
1363 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1364 name);
1365 wpa_config_set_blob(wpa_s->conf, blob);
1366 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1367 name);
1368 ssid->eap.cert.client_cert = os_strdup(blobname);
1369 if (!ssid->eap.cert.client_cert)
1370 goto fail;
1371
1372 /* TODO: ssid->eap.identity from own certificate */
1373 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1374 0) < 0)
1375 goto fail;
1376 }
1377
1378 if (auth->priv_key) {
1379 for (i = 0; ; i++) {
1380 os_snprintf(name, sizeof(name), "dpp-key-%d",
1381 i);
1382 if (!wpa_config_get_blob(wpa_s->conf, name))
1383 break;
1384 }
1385
1386 blob = os_zalloc(sizeof(*blob));
1387 if (!blob)
1388 goto fail;
1389 blob->len = wpabuf_len(auth->priv_key);
1390 blob->name = os_strdup(name);
1391 blob->data = os_malloc(blob->len);
1392 if (!blob->name || !blob->data) {
1393 wpa_config_free_blob(blob);
1394 goto fail;
1395 }
1396 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1397 blob->len);
1398 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1399 name);
1400 wpa_config_set_blob(wpa_s->conf, blob);
1401 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1402 name);
1403 ssid->eap.cert.private_key = os_strdup(blobname);
1404 if (!ssid->eap.cert.private_key)
1405 goto fail;
1406 }
1407
1408 if (conf->server_name) {
1409 ssid->eap.cert.domain_suffix_match =
1410 os_strdup(conf->server_name);
1411 if (!ssid->eap.cert.domain_suffix_match)
1412 goto fail;
1413 }
1414
1415 /* TODO: Use entCreds::eapMethods */
1416 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1417 goto fail;
1418 }
1419#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1420
Hai Shalomc3565922019-10-28 11:58:20 -07001421 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1422 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1423
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001424 return ssid;
1425fail:
1426 wpas_notify_network_removed(wpa_s, ssid);
1427 wpa_config_remove_network(wpa_s->conf, ssid->id);
1428 return NULL;
1429}
1430
1431
Hai Shalom021b0b52019-04-10 11:17:58 -07001432static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001433 struct dpp_authentication *auth,
1434 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001435{
1436 struct wpa_ssid *ssid;
1437
1438 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001439 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001440
Hai Shalomc3565922019-10-28 11:58:20 -07001441 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001442 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001443 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001444
1445 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001446
Hai Shalom706f99b2019-01-08 16:23:37 -08001447 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001448
Hai Shalom021b0b52019-04-10 11:17:58 -07001449 if (wpa_s->conf->dpp_config_processing == 2)
1450 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001451
Hai Shalom021b0b52019-04-10 11:17:58 -07001452#ifndef CONFIG_NO_CONFIG_WRITE
1453 if (wpa_s->conf->update_config &&
1454 wpa_config_write(wpa_s->confname, wpa_s->conf))
1455 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1456#endif /* CONFIG_NO_CONFIG_WRITE */
1457
Hai Shalomc3565922019-10-28 11:58:20 -07001458 return 0;
1459}
1460
1461
1462static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1463 struct dpp_authentication *auth)
1464{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001465#ifdef CONFIG_DPP2
1466 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1467 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1468 wpa_s->dpp_reconfig_ssid) {
1469 wpa_printf(MSG_DEBUG,
1470 "DPP: Remove reconfigured network profile");
1471 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1472 wpa_config_remove_network(wpa_s->conf,
1473 wpa_s->dpp_reconfig_ssid_id);
1474 wpa_s->dpp_reconfig_ssid = NULL;
1475 wpa_s->dpp_reconfig_ssid_id = -1;
1476 }
1477#endif /* CONFIG_DPP2 */
1478
Hai Shalom021b0b52019-04-10 11:17:58 -07001479 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001480 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001481
1482#ifdef CONFIG_DPP2
1483 if (auth->peer_version >= 2) {
1484 wpa_printf(MSG_DEBUG,
1485 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1486 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001487 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001488 }
1489#endif /* CONFIG_DPP2 */
1490
1491 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001492}
1493
1494
Hai Shalom021b0b52019-04-10 11:17:58 -07001495static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001496 struct dpp_authentication *auth,
1497 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001498{
1499 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001500 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1501 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001502 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001503 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001504 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001505 if (conf->ssid_charset)
1506 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1507 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001508 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001509 /* TODO: Save the Connector and consider using a command
1510 * to fetch the value instead of sending an event with
1511 * it. The Connector could end up being larger than what
1512 * most clients are ready to receive as an event
1513 * message. */
1514 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001515 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001516 }
Hai Shalom60840252021-02-19 19:02:11 -08001517 if (conf->passphrase[0]) {
1518 char hex[64 * 2 + 1];
1519
1520 wpa_snprintf_hex(hex, sizeof(hex),
1521 (const u8 *) conf->passphrase,
1522 os_strlen(conf->passphrase));
1523 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1524 hex);
1525 } else if (conf->psk_set) {
1526 char hex[PMK_LEN * 2 + 1];
1527
1528 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1529 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1530 hex);
1531 }
Hai Shalomc3565922019-10-28 11:58:20 -07001532 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001533 char *hex;
1534 size_t hexlen;
1535
Hai Shalomc3565922019-10-28 11:58:20 -07001536 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001537 hex = os_malloc(hexlen);
1538 if (hex) {
1539 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001540 wpabuf_head(conf->c_sign_key),
1541 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001542 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1543 hex);
1544 os_free(hex);
1545 }
1546 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001547 if (conf->pp_key) {
1548 char *hex;
1549 size_t hexlen;
1550
1551 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1552 hex = os_malloc(hexlen);
1553 if (hex) {
1554 wpa_snprintf_hex(hex, hexlen,
1555 wpabuf_head(conf->pp_key),
1556 wpabuf_len(conf->pp_key));
1557 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1558 os_free(hex);
1559 }
1560 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001561 if (auth->net_access_key) {
1562 char *hex;
1563 size_t hexlen;
1564
1565 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1566 hex = os_malloc(hexlen);
1567 if (hex) {
1568 wpa_snprintf_hex(hex, hexlen,
1569 wpabuf_head(auth->net_access_key),
1570 wpabuf_len(auth->net_access_key));
1571 if (auth->net_access_key_expiry)
1572 wpa_msg(wpa_s, MSG_INFO,
1573 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1574 (long unsigned)
1575 auth->net_access_key_expiry);
1576 else
1577 wpa_msg(wpa_s, MSG_INFO,
1578 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1579 os_free(hex);
1580 }
1581 }
1582
Hai Shalom899fcc72020-10-19 14:38:18 -07001583#ifdef CONFIG_DPP2
1584 if (conf->certbag) {
1585 char *b64;
1586
1587 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1588 wpabuf_len(conf->certbag), NULL);
1589 if (b64)
1590 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1591 os_free(b64);
1592 }
1593
1594 if (conf->cacert) {
1595 char *b64;
1596
1597 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1598 wpabuf_len(conf->cacert), NULL);
1599 if (b64)
1600 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1601 os_free(b64);
1602 }
1603
1604 if (conf->server_name)
1605 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1606 conf->server_name);
1607#endif /* CONFIG_DPP2 */
1608
Hai Shalomc3565922019-10-28 11:58:20 -07001609 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001610}
1611
1612
Hai Shalomfdcde762020-04-02 11:19:20 -07001613static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1614 struct dpp_asymmetric_key *key)
1615{
1616#ifdef CONFIG_DPP2
1617 int res;
1618
1619 if (!key)
1620 return 0;
1621
1622 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1623 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001624 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001625
1626 while (key) {
1627 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1628 if (res < 0)
1629 return -1;
1630 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1631 res);
1632 key = key->next;
1633 }
1634#endif /* CONFIG_DPP2 */
1635
1636 return 0;
1637}
1638
1639
Hai Shalom899fcc72020-10-19 14:38:18 -07001640#ifdef CONFIG_DPP2
1641static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1642{
1643 struct wpa_supplicant *wpa_s = eloop_ctx;
1644 struct dpp_authentication *auth = wpa_s->dpp_auth;
1645
1646 if (!auth || !auth->csrattrs)
1647 return;
1648
1649 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1650 wpabuf_free(auth->csr);
1651 /* TODO: Additional information needed for CSR based on csrAttrs */
1652 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1653 wpa_s->conf->dpp_name : "Test");
1654 if (!auth->csr) {
1655 dpp_auth_deinit(wpa_s->dpp_auth);
1656 wpa_s->dpp_auth = NULL;
1657 return;
1658 }
1659
1660 wpas_dpp_start_gas_client(wpa_s);
1661}
1662#endif /* CONFIG_DPP2 */
1663
1664
Sunil Ravia04bd252022-05-02 22:54:18 -07001665#ifdef CONFIG_DPP3
1666static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1667{
1668 struct wpa_supplicant *wpa_s = eloop_ctx;
1669 struct dpp_authentication *auth = wpa_s->dpp_auth;
1670
1671 if (!auth || !auth->waiting_new_key)
1672 return;
1673
1674 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1675 wpas_dpp_start_gas_client(wpa_s);
1676}
1677#endif /* CONFIG_DPP3 */
1678
1679
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001680static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1681 enum gas_query_result result,
1682 const struct wpabuf *adv_proto,
1683 const struct wpabuf *resp, u16 status_code)
1684{
1685 struct wpa_supplicant *wpa_s = ctx;
1686 const u8 *pos;
1687 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001688 int res;
1689 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001690 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001691
Hai Shaloma20dcd72022-02-04 13:43:00 -08001692 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001693 wpa_s->dpp_gas_dialog_token = -1;
1694
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001695 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
1696 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001697 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1698 return;
1699 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001700 if (result != GAS_QUERY_SUCCESS ||
1701 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001702 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1703 goto fail;
1704 }
1705
1706 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1707 adv_proto);
1708 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1709 resp);
1710
1711 if (wpabuf_len(adv_proto) != 10 ||
1712 !(pos = wpabuf_head(adv_proto)) ||
1713 pos[0] != WLAN_EID_ADV_PROTO ||
1714 pos[1] != 8 ||
1715 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1716 pos[4] != 5 ||
1717 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1718 pos[8] != 0x1a ||
1719 pos[9] != 1) {
1720 wpa_printf(MSG_DEBUG,
1721 "DPP: Not a DPP Advertisement Protocol ID");
1722 goto fail;
1723 }
1724
Hai Shalom899fcc72020-10-19 14:38:18 -07001725 res = dpp_conf_resp_rx(auth, resp);
1726#ifdef CONFIG_DPP2
1727 if (res == -2) {
1728 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1729 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1730 return;
1731 }
1732#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001733#ifdef CONFIG_DPP3
1734 if (res == -3) {
1735 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1736 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1737 NULL);
1738 return;
1739 }
1740#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001741 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001742 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1743 goto fail;
1744 }
1745
Hai Shalom899fcc72020-10-19 14:38:18 -07001746 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001747 for (i = 0; i < auth->num_conf_obj; i++) {
1748 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1749 &auth->conf_obj[i]);
1750 if (res < 0)
1751 goto fail;
1752 }
1753 if (auth->num_conf_obj)
1754 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001755 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1756 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001757
Hai Shalom021b0b52019-04-10 11:17:58 -07001758 status = DPP_STATUS_OK;
1759#ifdef CONFIG_TESTING_OPTIONS
1760 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1761 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1762 status = DPP_STATUS_CONFIG_REJECTED;
1763 }
1764#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001765fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001766 if (status != DPP_STATUS_OK) {
1767 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1768 wpas_notify_dpp_configuration_failure(wpa_s);
1769 }
1770#ifdef CONFIG_DPP2
1771 if (auth->peer_version >= 2 &&
1772 auth->conf_resp_status == DPP_STATUS_OK) {
1773 struct wpabuf *msg;
1774
1775 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1776 msg = dpp_build_conf_result(auth, status);
1777 if (!msg)
1778 goto fail2;
1779
1780 wpa_msg(wpa_s, MSG_INFO,
1781 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1782 MAC2STR(addr), auth->curr_freq,
1783 DPP_PA_CONFIGURATION_RESULT);
1784 offchannel_send_action(wpa_s, auth->curr_freq,
1785 addr, wpa_s->own_addr, broadcast,
1786 wpabuf_head(msg),
1787 wpabuf_len(msg),
1788 500, wpas_dpp_tx_status, 0);
1789 wpabuf_free(msg);
1790
1791 /* This exchange will be terminated in the TX status handler */
Hai Shalom899fcc72020-10-19 14:38:18 -07001792 if (wpa_s->conf->dpp_config_processing < 2 ||
1793 wpa_s->dpp_conf_backup_received)
1794 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001795 return;
1796 }
1797fail2:
1798#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001799 dpp_auth_deinit(wpa_s->dpp_auth);
1800 wpa_s->dpp_auth = NULL;
1801}
1802
1803
Hai Shaloma20dcd72022-02-04 13:43:00 -08001804static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
1805{
1806 struct wpa_supplicant *wpa_s = eloop_ctx;
1807 struct dpp_authentication *auth = wpa_s->dpp_auth;
1808
1809 if (!wpa_s->dpp_gas_client || !auth ||
1810 (!auth->auth_success && !auth->reconfig_success))
1811 return;
1812
1813 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
1814 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1815 dpp_auth_deinit(wpa_s->dpp_auth);
1816 wpa_s->dpp_auth = NULL;
1817}
1818
1819
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001820static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1821{
1822 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001823 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001824 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001825 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001826
1827 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001828 offchannel_send_action_done(wpa_s);
1829 wpas_dpp_listen_stop(wpa_s);
1830
Hai Shalomc3565922019-10-28 11:58:20 -07001831 supp_op_classes = wpas_supp_op_classes(wpa_s);
1832 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001833 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001834 wpa_s->conf->dpp_mud_url,
1835 supp_op_classes);
1836 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001837 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001838 wpa_printf(MSG_DEBUG,
1839 "DPP: No configuration request data available");
1840 return;
1841 }
1842
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001843 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1844 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1845
Hai Shaloma20dcd72022-02-04 13:43:00 -08001846 /* Use a 120 second timeout since the gas_query_req() operation could
1847 * remain waiting indefinitely for the response if the Configurator
1848 * keeps sending out comeback responses with additional delay. The
1849 * DPP technical specification expects the Enrollee to continue sending
1850 * out new Config Requests for 60 seconds, so this gives an extra 60
1851 * second time after the last expected new Config Request for the
1852 * Configurator to determine what kind of configuration to provide. */
1853 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
1854 wpa_s, NULL);
1855
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001856 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001857 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001858 if (res < 0) {
1859 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1860 wpabuf_free(buf);
1861 } else {
1862 wpa_printf(MSG_DEBUG,
1863 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001864 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001865 }
1866}
1867
1868
1869static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1870{
1871 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1872 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001873 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001874#ifdef CONFIG_TESTING_OPTIONS
1875 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1876 wpa_printf(MSG_INFO,
1877 "DPP: TESTING - stop at Authentication Confirm");
1878 if (wpa_s->dpp_auth->configurator) {
1879 /* Prevent GAS response */
1880 wpa_s->dpp_auth->auth_success = 0;
1881 }
1882 return;
1883 }
1884#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001885
1886 if (wpa_s->dpp_auth->configurator)
1887 wpas_dpp_start_gas_server(wpa_s);
1888 else
1889 wpas_dpp_start_gas_client(wpa_s);
1890}
1891
1892
1893static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001894 const u8 *hdr, const u8 *buf, size_t len,
1895 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001896{
1897 struct dpp_authentication *auth = wpa_s->dpp_auth;
1898 struct wpabuf *msg;
1899
Roshan Pius3a1667e2018-07-03 15:17:14 -07001900 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1901 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001902
1903 if (!auth) {
1904 wpa_printf(MSG_DEBUG,
1905 "DPP: No DPP Authentication in progress - drop");
1906 return;
1907 }
1908
1909 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1910 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1911 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1912 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1913 return;
1914 }
1915
1916 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1917
Roshan Pius3a1667e2018-07-03 15:17:14 -07001918 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1919 wpa_printf(MSG_DEBUG,
1920 "DPP: Responder accepted request for different negotiation channel");
1921 auth->curr_freq = freq;
1922 }
1923
1924 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001925 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1926 if (!msg) {
1927 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1928 wpa_printf(MSG_DEBUG,
1929 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001930 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001931 offchannel_send_action_done(wpa_s);
1932 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1933 return;
1934 }
1935 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1936 return;
1937 }
1938 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1939
Roshan Pius3a1667e2018-07-03 15:17:14 -07001940 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1941 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001942 offchannel_send_action(wpa_s, auth->curr_freq,
1943 src, wpa_s->own_addr, broadcast,
1944 wpabuf_head(msg), wpabuf_len(msg),
1945 500, wpas_dpp_tx_status, 0);
1946 wpabuf_free(msg);
1947 wpa_s->dpp_auth_ok_on_ack = 1;
1948}
1949
1950
1951static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1952 const u8 *hdr, const u8 *buf, size_t len)
1953{
1954 struct dpp_authentication *auth = wpa_s->dpp_auth;
1955
1956 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1957 MAC2STR(src));
1958
1959 if (!auth) {
1960 wpa_printf(MSG_DEBUG,
1961 "DPP: No DPP Authentication in progress - drop");
1962 return;
1963 }
1964
1965 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1966 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1967 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1968 return;
1969 }
1970
Hai Shalom60840252021-02-19 19:02:11 -08001971 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
1972
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001973 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1974 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001975 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001976 return;
1977 }
1978
1979 wpas_dpp_auth_success(wpa_s, 0);
1980}
1981
1982
Hai Shalom021b0b52019-04-10 11:17:58 -07001983#ifdef CONFIG_DPP2
1984
1985static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
1986 void *timeout_ctx)
1987{
1988 struct wpa_supplicant *wpa_s = eloop_ctx;
1989 struct dpp_authentication *auth = wpa_s->dpp_auth;
1990
1991 if (!auth || !auth->waiting_conf_result)
1992 return;
1993
1994 wpa_printf(MSG_DEBUG,
1995 "DPP: Timeout while waiting for Configuration Result");
1996 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001997 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07001998 dpp_auth_deinit(auth);
1999 wpa_s->dpp_auth = NULL;
2000}
2001
2002
Hai Shalomc3565922019-10-28 11:58:20 -07002003static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2004 void *timeout_ctx)
2005{
2006 struct wpa_supplicant *wpa_s = eloop_ctx;
2007 struct dpp_authentication *auth = wpa_s->dpp_auth;
2008
2009 if (!auth || !auth->waiting_conn_status_result)
2010 return;
2011
2012 wpa_printf(MSG_DEBUG,
2013 "DPP: Timeout while waiting for Connection Status Result");
2014 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002015 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002016 wpas_dpp_listen_stop(wpa_s);
2017 dpp_auth_deinit(auth);
2018 wpa_s->dpp_auth = NULL;
2019}
2020
2021
Hai Shalom021b0b52019-04-10 11:17:58 -07002022static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2023 const u8 *hdr, const u8 *buf, size_t len)
2024{
2025 struct dpp_authentication *auth = wpa_s->dpp_auth;
2026 enum dpp_status_error status;
2027
2028 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2029 MAC2STR(src));
2030
2031 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002032 if (auth &&
2033 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
2034 gas_server_response_sent(wpa_s->gas_server,
2035 auth->gas_server_ctx)) {
2036 /* This could happen if the TX status event gets delayed
2037 * long enough for the Enrollee to have time to send
2038 * the next frame before the TX status gets processed
2039 * locally. */
2040 wpa_printf(MSG_DEBUG,
2041 "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");
2042 auth->waiting_conf_result = 1;
2043 } else {
2044 wpa_printf(MSG_DEBUG,
2045 "DPP: No DPP Configuration waiting for result - drop");
2046 return;
2047 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002048 }
2049
2050 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2051 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2052 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2053 return;
2054 }
2055
2056 status = dpp_conf_result_rx(auth, hdr, buf, len);
2057
Hai Shalomc3565922019-10-28 11:58:20 -07002058 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002059 int freq;
2060
Hai Shalomc3565922019-10-28 11:58:20 -07002061 wpa_msg(wpa_s, MSG_INFO,
2062 DPP_EVENT_CONF_SENT "wait_conn_status=1");
2063 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002064 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002065 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2066 wpa_s, NULL);
2067 auth->waiting_conn_status_result = 1;
2068 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2069 wpa_s, NULL);
2070 eloop_register_timeout(16, 0,
2071 wpas_dpp_conn_status_result_wait_timeout,
2072 wpa_s, NULL);
2073 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002074 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2075 if (!wpa_s->dpp_in_response_listen ||
2076 (int) wpa_s->dpp_listen_freq != freq)
2077 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002078 return;
2079 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002080 offchannel_send_action_done(wpa_s);
2081 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002082 if (status == DPP_STATUS_OK) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002083 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalome4073332019-11-05 16:20:12 -08002084 wpas_notify_dpp_config_sent(wpa_s);
2085 }
2086 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002087 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002088 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002089 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002090 dpp_auth_deinit(auth);
2091 wpa_s->dpp_auth = NULL;
2092 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
2093}
2094
Hai Shalom81f62d82019-07-22 12:10:00 -07002095
Hai Shalomc3565922019-10-28 11:58:20 -07002096static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2097 const u8 *src, const u8 *hdr,
2098 const u8 *buf, size_t len)
2099{
2100 struct dpp_authentication *auth = wpa_s->dpp_auth;
2101 enum dpp_status_error status;
2102 u8 ssid[SSID_MAX_LEN];
2103 size_t ssid_len = 0;
2104 char *channel_list = NULL;
2105
2106 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2107
2108 if (!auth || !auth->waiting_conn_status_result) {
2109 wpa_printf(MSG_DEBUG,
2110 "DPP: No DPP Configuration waiting for connection status result - drop");
2111 return;
2112 }
2113
2114 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2115 ssid, &ssid_len, &channel_list);
2116 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2117 "result=%d ssid=%s channel_list=%s",
2118 status, wpa_ssid_txt(ssid, ssid_len),
2119 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002120 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2121 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002122 os_free(channel_list);
2123 offchannel_send_action_done(wpa_s);
2124 wpas_dpp_listen_stop(wpa_s);
2125 dpp_auth_deinit(auth);
2126 wpa_s->dpp_auth = NULL;
2127 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2128 wpa_s, NULL);
2129}
2130
2131
Hai Shalom81f62d82019-07-22 12:10:00 -07002132static int wpas_dpp_process_conf_obj(void *ctx,
2133 struct dpp_authentication *auth)
2134{
2135 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002136 unsigned int i;
2137 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002138
Hai Shalomc3565922019-10-28 11:58:20 -07002139 for (i = 0; i < auth->num_conf_obj; i++) {
2140 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2141 &auth->conf_obj[i]);
2142 if (res)
2143 break;
2144 }
2145 if (!res)
2146 wpas_dpp_post_process_config(wpa_s, auth);
2147
2148 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002149}
2150
Hai Shalomfdcde762020-04-02 11:19:20 -07002151
Hai Shaloma20dcd72022-02-04 13:43:00 -08002152static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2153{
2154 struct wpa_supplicant *wpa_s = ctx;
2155
2156 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2157
2158 if (auth->connect_on_tx_status) {
2159 auth->connect_on_tx_status = 0;
2160 wpa_printf(MSG_DEBUG,
2161 "DPP: Try to connect after completed configuration result");
2162 wpas_dpp_try_to_connect(wpa_s);
2163 if (auth->conn_status_requested) {
2164 wpa_printf(MSG_DEBUG,
2165 "DPP: Start 15 second timeout for reporting connection status result");
2166 eloop_cancel_timeout(
2167 wpas_dpp_conn_status_result_timeout,
2168 wpa_s, NULL);
2169 eloop_register_timeout(
2170 15, 0, wpas_dpp_conn_status_result_timeout,
2171 wpa_s, NULL);
2172 return true;
2173 }
2174 }
2175
2176 return false;
2177}
2178
2179
Hai Shalomfdcde762020-04-02 11:19:20 -07002180static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2181{
2182 struct wpa_supplicant *wpa_s = ctx;
2183
2184 if (bi == wpa_s->dpp_chirp_bi)
2185 wpas_dpp_chirp_stop(wpa_s);
2186}
2187
2188
2189static void
2190wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2191 const u8 *hdr, const u8 *buf, size_t len,
2192 unsigned int freq)
2193{
2194 const u8 *r_bootstrap;
2195 u16 r_bootstrap_len;
2196 struct dpp_bootstrap_info *peer_bi;
2197 struct dpp_authentication *auth;
2198
2199 if (!wpa_s->dpp)
2200 return;
2201
2202 if (wpa_s->dpp_auth) {
2203 wpa_printf(MSG_DEBUG,
2204 "DPP: Ignore Presence Announcement during ongoing Authentication");
2205 return;
2206 }
2207
2208 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2209 MAC2STR(src));
2210
2211 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2212 &r_bootstrap_len);
2213 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2214 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2215 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2216 return;
2217 }
2218 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2219 r_bootstrap, r_bootstrap_len);
2220 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002221 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2222 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002223 if (!peer_bi) {
2224 wpa_printf(MSG_DEBUG,
2225 "DPP: No matching bootstrapping information found");
2226 return;
2227 }
2228
2229 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2230 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2231 if (!auth)
2232 return;
2233 wpas_dpp_set_testing_options(wpa_s, auth);
2234 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2235 dpp_auth_deinit(auth);
2236 return;
2237 }
2238
2239 auth->neg_freq = freq;
2240
Hai Shalom60840252021-02-19 19:02:11 -08002241 /* The source address of the Presence Announcement frame overrides any
2242 * MAC address information from the bootstrapping information. */
2243 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002244
2245 wpa_s->dpp_auth = auth;
2246 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2247 dpp_auth_deinit(wpa_s->dpp_auth);
2248 wpa_s->dpp_auth = NULL;
2249 }
2250}
2251
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002252
2253static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2254 void *timeout_ctx)
2255{
2256 struct wpa_supplicant *wpa_s = eloop_ctx;
2257 struct dpp_authentication *auth = wpa_s->dpp_auth;
2258
2259 if (!auth)
2260 return;
2261
2262 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2263 offchannel_send_action_done(wpa_s);
2264 wpas_dpp_listen_stop(wpa_s);
2265 dpp_auth_deinit(auth);
2266 wpa_s->dpp_auth = NULL;
2267}
2268
2269
2270static void
2271wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2272 const u8 *hdr, const u8 *buf, size_t len,
2273 unsigned int freq)
2274{
Hai Shalom899fcc72020-10-19 14:38:18 -07002275 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2276 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002277 struct dpp_configurator *conf;
2278 struct dpp_authentication *auth;
2279 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002280 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002281
2282 if (!wpa_s->dpp)
2283 return;
2284
2285 if (wpa_s->dpp_auth) {
2286 wpa_printf(MSG_DEBUG,
2287 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2288 return;
2289 }
2290
2291 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2292 MAC2STR(src));
2293
2294 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2295 &csign_hash_len);
2296 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2297 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2298 "Missing or invalid required Configurator C-sign key Hash attribute");
2299 return;
2300 }
2301 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2302 csign_hash, csign_hash_len);
2303 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2304 if (!conf) {
2305 wpa_printf(MSG_DEBUG,
2306 "DPP: No matching Configurator information found");
2307 return;
2308 }
2309
Hai Shalom899fcc72020-10-19 14:38:18 -07002310 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2311 &fcgroup_len);
2312 if (!fcgroup || fcgroup_len != 2) {
2313 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2314 "Missing or invalid required Finite Cyclic Group attribute");
2315 return;
2316 }
2317 group = WPA_GET_LE16(fcgroup);
2318 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2319
2320 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2321 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2322
2323 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2324 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002325 if (!auth)
2326 return;
2327 wpas_dpp_set_testing_options(wpa_s, auth);
2328 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2329 dpp_auth_deinit(auth);
2330 return;
2331 }
2332
2333 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2334 wpa_s->dpp_auth = auth;
2335
2336 wpa_s->dpp_in_response_listen = 0;
2337 wpa_s->dpp_auth_ok_on_ack = 0;
2338 wait_time = wpa_s->max_remain_on_chan;
2339 max_wait_time = wpa_s->dpp_resp_wait_time ?
2340 wpa_s->dpp_resp_wait_time : 2000;
2341 if (wait_time > max_wait_time)
2342 wait_time = max_wait_time;
2343 wait_time += 10; /* give the driver some extra time to complete */
2344 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2345 wpas_dpp_reconfig_reply_wait_timeout,
2346 wpa_s, NULL);
2347 wait_time -= 10;
2348
2349 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2350
2351 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2352 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2353 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2354 wpabuf_head(auth->reconfig_req_msg),
2355 wpabuf_len(auth->reconfig_req_msg),
2356 wait_time, wpas_dpp_tx_status, 0) < 0) {
2357 dpp_auth_deinit(wpa_s->dpp_auth);
2358 wpa_s->dpp_auth = NULL;
2359 }
2360}
2361
2362
2363static void
2364wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2365 const u8 *hdr, const u8 *buf, size_t len,
2366 unsigned int freq)
2367{
2368 struct wpa_ssid *ssid;
2369 struct dpp_authentication *auth;
2370
2371 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2372 MACSTR, MAC2STR(src));
2373
Hai Shalom899fcc72020-10-19 14:38:18 -07002374 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002375 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002376 if (wpa_s->dpp_auth) {
2377 wpa_printf(MSG_DEBUG,
2378 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2379 return;
2380 }
2381 if (!wpa_s->dpp_reconfig_ssid) {
2382 wpa_printf(MSG_DEBUG,
2383 "DPP: Not ready for reconfiguration - not requested");
2384 return;
2385 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002386 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2387 if (ssid == wpa_s->dpp_reconfig_ssid &&
2388 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2389 break;
2390 }
2391 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002392 !ssid->dpp_csign) {
2393 wpa_printf(MSG_DEBUG,
2394 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002395 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002396 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002397
2398 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2399 ssid->dpp_netaccesskey,
2400 ssid->dpp_netaccesskey_len,
2401 ssid->dpp_csign, ssid->dpp_csign_len,
2402 freq, hdr, buf, len);
2403 if (!auth)
2404 return;
2405 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2406 wpa_s->dpp_auth = auth;
2407
2408 wpas_dpp_chirp_stop(wpa_s);
2409
2410 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2411 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2412 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2413 wpabuf_head(auth->reconfig_resp_msg),
2414 wpabuf_len(auth->reconfig_resp_msg),
2415 500, wpas_dpp_tx_status, 0) < 0) {
2416 dpp_auth_deinit(wpa_s->dpp_auth);
2417 wpa_s->dpp_auth = NULL;
2418 }
2419}
2420
2421
2422static void
2423wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2424 const u8 *hdr, const u8 *buf, size_t len,
2425 unsigned int freq)
2426{
2427 struct dpp_authentication *auth = wpa_s->dpp_auth;
2428 struct wpabuf *conf;
2429
2430 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2431 MACSTR, MAC2STR(src));
2432
2433 if (!auth || !auth->reconfig || !auth->configurator) {
2434 wpa_printf(MSG_DEBUG,
2435 "DPP: No DPP Reconfig Authentication in progress - drop");
2436 return;
2437 }
2438
2439 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2440 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2441 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2442 return;
2443 }
2444
2445 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2446 if (!conf)
2447 return;
2448
2449 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2450
2451 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2452 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2453 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2454 wpabuf_head(conf), wpabuf_len(conf),
2455 500, wpas_dpp_tx_status, 0) < 0) {
2456 wpabuf_free(conf);
2457 dpp_auth_deinit(wpa_s->dpp_auth);
2458 wpa_s->dpp_auth = NULL;
2459 return;
2460 }
2461 wpabuf_free(conf);
2462
2463 wpas_dpp_start_gas_server(wpa_s);
2464}
2465
2466
2467static void
2468wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2469 const u8 *hdr, const u8 *buf, size_t len,
2470 unsigned int freq)
2471{
2472 struct dpp_authentication *auth = wpa_s->dpp_auth;
2473
2474 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2475 MACSTR, MAC2STR(src));
2476
2477 if (!auth || !auth->reconfig || auth->configurator) {
2478 wpa_printf(MSG_DEBUG,
2479 "DPP: No DPP Reconfig Authentication in progress - drop");
2480 return;
2481 }
2482
2483 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2484 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2485 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2486 return;
2487 }
2488
2489 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2490 return;
2491
2492 wpas_dpp_start_gas_client(wpa_s);
2493}
2494
Hai Shalom021b0b52019-04-10 11:17:58 -07002495#endif /* CONFIG_DPP2 */
2496
2497
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002498static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2499 const u8 *src,
2500 const u8 *buf, size_t len)
2501{
2502 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002503 const u8 *connector, *trans_id, *status;
2504 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002505#ifdef CONFIG_DPP2
2506 const u8 *version;
2507 u16 version_len;
2508#endif /* CONFIG_DPP2 */
2509 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002510 struct dpp_introduction intro;
2511 struct rsn_pmksa_cache_entry *entry;
2512 struct os_time now;
2513 struct os_reltime rnow;
2514 os_time_t expiry;
2515 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002516 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002517
2518 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2519 MAC2STR(src));
2520 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2521 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2522 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2523 MACSTR " - drop", MAC2STR(src));
2524 return;
2525 }
2526 offchannel_send_action_done(wpa_s);
2527
2528 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2529 if (ssid == wpa_s->dpp_intro_network)
2530 break;
2531 }
2532 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2533 !ssid->dpp_csign) {
2534 wpa_printf(MSG_DEBUG,
2535 "DPP: Profile not found for network introduction");
2536 return;
2537 }
2538
2539 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2540 &trans_id_len);
2541 if (!trans_id || trans_id_len != 1) {
2542 wpa_printf(MSG_DEBUG,
2543 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002544 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2545 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002546 goto fail;
2547 }
2548 if (trans_id[0] != TRANSACTION_ID) {
2549 wpa_printf(MSG_DEBUG,
2550 "DPP: Ignore frame with unexpected Transaction ID %u",
2551 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002552 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2553 " fail=transaction_id_mismatch", MAC2STR(src));
2554 goto fail;
2555 }
2556
2557 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2558 if (!status || status_len != 1) {
2559 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2560 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2561 " fail=missing_status", MAC2STR(src));
2562 goto fail;
2563 }
2564 if (status[0] != DPP_STATUS_OK) {
2565 wpa_printf(MSG_DEBUG,
2566 "DPP: Peer rejected network introduction: Status %u",
2567 status[0]);
2568 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2569 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002570#ifdef CONFIG_DPP2
2571 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2572#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002573 goto fail;
2574 }
2575
2576 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2577 if (!connector) {
2578 wpa_printf(MSG_DEBUG,
2579 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002580 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2581 " fail=missing_connector", MAC2STR(src));
2582 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002583 }
2584
Roshan Pius3a1667e2018-07-03 15:17:14 -07002585 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2586 ssid->dpp_netaccesskey,
2587 ssid->dpp_netaccesskey_len,
2588 ssid->dpp_csign,
2589 ssid->dpp_csign_len,
2590 connector, connector_len, &expiry);
2591 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002592 wpa_printf(MSG_INFO,
2593 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002594 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2595 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002596#ifdef CONFIG_DPP2
2597 wpas_dpp_send_conn_status_result(wpa_s, res);
2598#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002599 goto fail;
2600 }
2601
2602 entry = os_zalloc(sizeof(*entry));
2603 if (!entry)
2604 goto fail;
2605 os_memcpy(entry->aa, src, ETH_ALEN);
2606 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2607 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2608 entry->pmk_len = intro.pmk_len;
2609 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002610#ifdef CONFIG_DPP2
2611 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2612 &version_len);
2613 if (version && version_len >= 1)
2614 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002615#ifdef CONFIG_DPP3
2616 if (intro.peer_version && intro.peer_version >= 2 &&
2617 peer_version != intro.peer_version) {
2618 wpa_printf(MSG_INFO,
2619 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2620 intro.peer_version, peer_version);
2621 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2622 goto fail;
2623 }
2624#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002625 entry->dpp_pfs = peer_version >= 2;
2626#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002627 if (expiry) {
2628 os_get_time(&now);
2629 seconds = expiry - now.sec;
2630 } else {
2631 seconds = 86400 * 7;
2632 }
2633 os_get_reltime(&rnow);
2634 entry->expiration = rnow.sec + seconds;
2635 entry->reauth_time = rnow.sec + seconds;
2636 entry->network_ctx = ssid;
2637 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2638
Roshan Pius3a1667e2018-07-03 15:17:14 -07002639 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002640 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002641
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002642 wpa_printf(MSG_DEBUG,
2643 "DPP: Try connection again after successful network introduction");
2644 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2645 wpa_supplicant_cancel_sched_scan(wpa_s);
2646 wpa_supplicant_req_scan(wpa_s, 0, 0);
2647 }
2648fail:
2649 os_memset(&intro, 0, sizeof(intro));
2650}
2651
2652
Roshan Pius3a1667e2018-07-03 15:17:14 -07002653static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2654{
2655 int i, j;
2656
2657 if (!wpa_s->hw.modes)
2658 return -1;
2659
2660 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2661 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2662
2663 for (j = 0; j < mode->num_channels; j++) {
2664 struct hostapd_channel_data *chan = &mode->channels[j];
2665
2666 if (chan->freq != (int) freq)
2667 continue;
2668
2669 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2670 HOSTAPD_CHAN_NO_IR |
2671 HOSTAPD_CHAN_RADAR))
2672 continue;
2673
2674 return 1;
2675 }
2676 }
2677
2678 wpa_printf(MSG_DEBUG,
2679 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2680 freq);
2681
2682 return 0;
2683}
2684
2685
2686static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2687 struct dpp_pkex *pkex)
2688{
2689 if (pkex->freq == 2437)
2690 pkex->freq = 5745;
2691 else if (pkex->freq == 5745)
2692 pkex->freq = 5220;
2693 else if (pkex->freq == 5220)
2694 pkex->freq = 60480;
2695 else
2696 return -1; /* no more channels to try */
2697
2698 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2699 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2700 pkex->freq);
2701 return 0;
2702 }
2703
2704 /* Could not use this channel - try the next one */
2705 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2706}
2707
2708
Hai Shaloma20dcd72022-02-04 13:43:00 -08002709#ifdef CONFIG_DPP2
2710static int wpas_dpp_pkex_done(void *ctx, void *conn,
2711 struct dpp_bootstrap_info *peer_bi)
2712{
2713 struct wpa_supplicant *wpa_s = ctx;
2714 const char *cmd = wpa_s->dpp_pkex_auth_cmd;
2715 const char *pos;
2716 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2717 struct dpp_bootstrap_info *own_bi = NULL;
2718 struct dpp_authentication *auth;
2719
2720 if (!cmd)
2721 cmd = "";
2722 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
2723 cmd);
2724
2725 pos = os_strstr(cmd, " own=");
2726 if (pos) {
2727 pos += 5;
2728 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
2729 if (!own_bi) {
2730 wpa_printf(MSG_INFO,
2731 "DPP: Could not find bootstrapping info for the identified local entry");
2732 return -1;
2733 }
2734
2735 if (peer_bi->curve != own_bi->curve) {
2736 wpa_printf(MSG_INFO,
2737 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
2738 peer_bi->curve->name, own_bi->curve->name);
2739 return -1;
2740 }
2741 }
2742
2743 pos = os_strstr(cmd, " role=");
2744 if (pos) {
2745 pos += 6;
2746 if (os_strncmp(pos, "configurator", 12) == 0)
2747 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2748 else if (os_strncmp(pos, "enrollee", 8) == 0)
2749 allowed_roles = DPP_CAPAB_ENROLLEE;
2750 else if (os_strncmp(pos, "either", 6) == 0)
2751 allowed_roles = DPP_CAPAB_CONFIGURATOR |
2752 DPP_CAPAB_ENROLLEE;
2753 else
2754 return -1;
2755 }
2756
2757 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
2758 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
2759 if (!auth)
2760 return -1;
2761
2762 wpas_dpp_set_testing_options(wpa_s, auth);
2763 if (dpp_set_configurator(auth, cmd) < 0) {
2764 dpp_auth_deinit(auth);
2765 return -1;
2766 }
2767
2768 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
2769 DPP_NETROLE_STA, wpas_dpp_process_conf_obj,
2770 wpas_dpp_tcp_msg_sent);
2771}
2772#endif /* CONFIG_DPP2 */
2773
2774
Hai Shaloma20dcd72022-02-04 13:43:00 -08002775static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07002776 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002777 const struct hostapd_ip_addr *ipaddr,
2778 int tcp_port)
2779{
2780 struct dpp_pkex *pkex;
2781 struct wpabuf *msg;
2782 unsigned int wait_time;
2783 bool v2 = ver != PKEX_VER_ONLY_1;
2784
2785 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
2786 dpp_pkex_free(wpa_s->dpp_pkex);
2787 wpa_s->dpp_pkex = NULL;
2788 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
2789 wpa_s->dpp_pkex_identifier,
2790 wpa_s->dpp_pkex_code, v2);
2791 if (!pkex)
2792 return -1;
2793 pkex->forced_ver = ver != PKEX_VER_AUTO;
2794
2795 if (ipaddr) {
2796#ifdef CONFIG_DPP2
2797 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
2798 wpa_s, wpa_s, wpas_dpp_pkex_done);
2799#else /* CONFIG_DPP2 */
2800 return -1;
2801#endif /* CONFIG_DPP2 */
2802 }
2803
2804 wpa_s->dpp_pkex = pkex;
2805 msg = pkex->exchange_req;
2806 wait_time = wpa_s->max_remain_on_chan;
2807 if (wait_time > 2000)
2808 wait_time = 2000;
2809 pkex->freq = 2437;
2810 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2811 " freq=%u type=%d",
2812 MAC2STR(broadcast), pkex->freq,
2813 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2814 DPP_PA_PKEX_V1_EXCHANGE_REQ);
2815 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2816 wpa_s->own_addr, broadcast,
2817 wpabuf_head(msg), wpabuf_len(msg),
2818 wait_time, wpas_dpp_tx_pkex_status, 0);
2819 if (wait_time == 0)
2820 wait_time = 2000;
2821 pkex->exch_req_wait_time = wait_time;
2822 pkex->exch_req_tries = 1;
2823
2824 return 0;
2825}
2826
2827
Roshan Pius3a1667e2018-07-03 15:17:14 -07002828static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
2829{
2830 struct wpa_supplicant *wpa_s = eloop_ctx;
2831 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2832
2833 if (!pkex || !pkex->exchange_req)
2834 return;
2835 if (pkex->exch_req_tries >= 5) {
2836 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002837#ifdef CONFIG_DPP3
2838 if (pkex->v2 && !pkex->forced_ver) {
2839 wpa_printf(MSG_DEBUG,
2840 "DPP: Fall back to PKEXv1");
2841 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
2842 NULL, 0);
2843 return;
2844 }
2845#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002846 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2847 "No response from PKEX peer");
2848 dpp_pkex_free(pkex);
2849 wpa_s->dpp_pkex = NULL;
2850 return;
2851 }
2852 pkex->exch_req_tries = 0;
2853 }
2854
2855 pkex->exch_req_tries++;
2856 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
2857 pkex->exch_req_tries);
2858 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08002859 MAC2STR(broadcast), pkex->freq,
2860 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2861 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002862 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2863 wpa_s->own_addr, broadcast,
2864 wpabuf_head(pkex->exchange_req),
2865 wpabuf_len(pkex->exchange_req),
2866 pkex->exch_req_wait_time,
2867 wpas_dpp_tx_pkex_status, 0);
2868}
2869
2870
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002871static void
2872wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
2873 unsigned int freq, const u8 *dst,
2874 const u8 *src, const u8 *bssid,
2875 const u8 *data, size_t data_len,
2876 enum offchannel_send_action_result result)
2877{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002878 const char *res_txt;
2879 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2880
2881 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2882 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2883 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002884 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2885 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002886 freq, MAC2STR(dst), res_txt);
2887 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2888 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
2889
2890 if (!pkex) {
2891 wpa_printf(MSG_DEBUG,
2892 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
2893 return;
2894 }
2895
2896 if (pkex->failed) {
2897 wpa_printf(MSG_DEBUG,
2898 "DPP: Terminate PKEX exchange due to an earlier error");
2899 if (pkex->t > pkex->own_bi->pkex_t)
2900 pkex->own_bi->pkex_t = pkex->t;
2901 dpp_pkex_free(pkex);
2902 wpa_s->dpp_pkex = NULL;
2903 return;
2904 }
2905
2906 if (pkex->exch_req_wait_time && pkex->exchange_req) {
2907 /* Wait for PKEX Exchange Response frame and retry request if
2908 * no response is seen. */
2909 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
2910 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
2911 (pkex->exch_req_wait_time % 1000) * 1000,
2912 wpas_dpp_pkex_retry_timeout, wpa_s,
2913 NULL);
2914 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002915}
2916
2917
2918static void
2919wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002920 const u8 *buf, size_t len, unsigned int freq,
2921 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002922{
2923 struct wpabuf *msg;
2924 unsigned int wait_time;
2925
2926 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
2927 MAC2STR(src));
2928
Sunil Ravia04bd252022-05-02 22:54:18 -07002929 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
2930 wpa_printf(MSG_DEBUG,
2931 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
2932 return;
2933 }
2934 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
2935 wpa_printf(MSG_DEBUG,
2936 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
2937 return;
2938 }
2939
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002940 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2941 * values here */
2942
2943 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
2944 wpa_printf(MSG_DEBUG,
2945 "DPP: No PKEX code configured - ignore request");
2946 return;
2947 }
2948
2949 if (wpa_s->dpp_pkex) {
2950 /* TODO: Support parallel operations */
2951 wpa_printf(MSG_DEBUG,
2952 "DPP: Already in PKEX session - ignore new request");
2953 return;
2954 }
2955
Roshan Pius3a1667e2018-07-03 15:17:14 -07002956 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002957 wpa_s->own_addr, src,
2958 wpa_s->dpp_pkex_identifier,
2959 wpa_s->dpp_pkex_code,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002960 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002961 if (!wpa_s->dpp_pkex) {
2962 wpa_printf(MSG_DEBUG,
2963 "DPP: Failed to process the request - ignore it");
2964 return;
2965 }
2966
Sunil Ravia04bd252022-05-02 22:54:18 -07002967 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002968 msg = wpa_s->dpp_pkex->exchange_resp;
2969 wait_time = wpa_s->max_remain_on_chan;
2970 if (wait_time > 2000)
2971 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002972 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2973 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002974 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2975 broadcast,
2976 wpabuf_head(msg), wpabuf_len(msg),
2977 wait_time, wpas_dpp_tx_pkex_status, 0);
2978}
2979
2980
2981static void
2982wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2983 const u8 *buf, size_t len, unsigned int freq)
2984{
2985 struct wpabuf *msg;
2986 unsigned int wait_time;
2987
2988 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2989 MAC2STR(src));
2990
2991 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2992 * values here */
2993
2994 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
2995 wpa_s->dpp_pkex->exchange_done) {
2996 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2997 return;
2998 }
2999
Roshan Pius3a1667e2018-07-03 15:17:14 -07003000 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3001 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3002
3003 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003004 if (!msg) {
3005 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3006 return;
3007 }
3008
3009 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3010 MAC2STR(src));
3011
3012 wait_time = wpa_s->max_remain_on_chan;
3013 if (wait_time > 2000)
3014 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003015 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3016 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003017 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3018 broadcast,
3019 wpabuf_head(msg), wpabuf_len(msg),
3020 wait_time, wpas_dpp_tx_pkex_status, 0);
3021 wpabuf_free(msg);
3022}
3023
3024
Roshan Pius3a1667e2018-07-03 15:17:14 -07003025static struct dpp_bootstrap_info *
3026wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3027 unsigned int freq)
3028{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003029 struct dpp_bootstrap_info *bi;
3030
Hai Shalom021b0b52019-04-10 11:17:58 -07003031 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003032 if (!bi)
3033 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003034 wpa_s->dpp_pkex = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003035 return bi;
3036}
3037
3038
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003039static void
3040wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3041 const u8 *hdr, const u8 *buf, size_t len,
3042 unsigned int freq)
3043{
3044 struct wpabuf *msg;
3045 unsigned int wait_time;
3046 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003047
3048 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3049 MAC2STR(src));
3050
3051 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3052 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3053 return;
3054 }
3055
3056 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3057 if (!msg) {
3058 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003059 if (pkex->failed) {
3060 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3061 if (pkex->t > pkex->own_bi->pkex_t)
3062 pkex->own_bi->pkex_t = pkex->t;
3063 dpp_pkex_free(wpa_s->dpp_pkex);
3064 wpa_s->dpp_pkex = NULL;
3065 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003066 return;
3067 }
3068
3069 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3070 MACSTR, MAC2STR(src));
3071
3072 wait_time = wpa_s->max_remain_on_chan;
3073 if (wait_time > 2000)
3074 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003075 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3076 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003077 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3078 broadcast,
3079 wpabuf_head(msg), wpabuf_len(msg),
3080 wait_time, wpas_dpp_tx_pkex_status, 0);
3081 wpabuf_free(msg);
3082
Roshan Pius3a1667e2018-07-03 15:17:14 -07003083 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003084 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003085}
3086
3087
3088static void
3089wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3090 const u8 *hdr, const u8 *buf, size_t len,
3091 unsigned int freq)
3092{
3093 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003094 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003095 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3096 char cmd[500];
3097
3098 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3099 MAC2STR(src));
3100
3101 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3102 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3103 return;
3104 }
3105
3106 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3107 if (res < 0) {
3108 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3109 return;
3110 }
3111
Roshan Pius3a1667e2018-07-03 15:17:14 -07003112 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003113 if (!bi)
3114 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003115
3116 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3117 bi->id,
3118 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3119 wpa_printf(MSG_DEBUG,
3120 "DPP: Start authentication after PKEX with parameters: %s",
3121 cmd);
3122 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3123 wpa_printf(MSG_DEBUG,
3124 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003125 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003126 return;
3127 }
3128}
3129
3130
3131void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
3132 const u8 *buf, size_t len, unsigned int freq)
3133{
3134 u8 crypto_suite;
3135 enum dpp_public_action_frame_type type;
3136 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003137 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003138
3139 if (len < DPP_HDR_LEN)
3140 return;
3141 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
3142 return;
3143 hdr = buf;
3144 buf += 4;
3145 len -= 4;
3146 crypto_suite = *buf++;
3147 type = *buf++;
3148 len -= 2;
3149
3150 wpa_printf(MSG_DEBUG,
3151 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
3152 MACSTR " freq=%u",
3153 crypto_suite, type, MAC2STR(src), freq);
3154 if (crypto_suite != 1) {
3155 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
3156 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003157 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3158 " freq=%u type=%d ignore=unsupported-crypto-suite",
3159 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003160 return;
3161 }
3162 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003163 if (dpp_check_attrs(buf, len) < 0) {
3164 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3165 " freq=%u type=%d ignore=invalid-attributes",
3166 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003167 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003168 }
3169 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
3170 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003171
3172 switch (type) {
3173 case DPP_PA_AUTHENTICATION_REQ:
3174 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
3175 break;
3176 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07003177 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003178 break;
3179 case DPP_PA_AUTHENTICATION_CONF:
3180 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
3181 break;
3182 case DPP_PA_PEER_DISCOVERY_RESP:
3183 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
3184 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003185#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003186 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003187 /* This is for PKEXv2, but for now, process only with
3188 * CONFIG_DPP3 to avoid issues with a capability that has not
3189 * been tested with other implementations. */
3190 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
3191 break;
3192#endif /* CONFIG_DPP3 */
3193 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
3194 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
3195 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003196 break;
3197 case DPP_PA_PKEX_EXCHANGE_RESP:
3198 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
3199 break;
3200 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
3201 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
3202 freq);
3203 break;
3204 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
3205 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
3206 freq);
3207 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003208#ifdef CONFIG_DPP2
3209 case DPP_PA_CONFIGURATION_RESULT:
3210 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
3211 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003212 case DPP_PA_CONNECTION_STATUS_RESULT:
3213 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
3214 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07003215 case DPP_PA_PRESENCE_ANNOUNCEMENT:
3216 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
3217 freq);
3218 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003219 case DPP_PA_RECONFIG_ANNOUNCEMENT:
3220 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
3221 freq);
3222 break;
3223 case DPP_PA_RECONFIG_AUTH_REQ:
3224 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
3225 break;
3226 case DPP_PA_RECONFIG_AUTH_RESP:
3227 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
3228 break;
3229 case DPP_PA_RECONFIG_AUTH_CONF:
3230 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
3231 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003232#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003233 default:
3234 wpa_printf(MSG_DEBUG,
3235 "DPP: Ignored unsupported frame subtype %d", type);
3236 break;
3237 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003238
3239 if (wpa_s->dpp_pkex)
3240 pkex_t = wpa_s->dpp_pkex->t;
3241 else if (wpa_s->dpp_pkex_bi)
3242 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
3243 else
3244 pkex_t = 0;
3245 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
3246 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
3247 wpas_dpp_pkex_remove(wpa_s, "*");
3248 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003249}
3250
3251
Hai Shaloma20dcd72022-02-04 13:43:00 -08003252static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
3253 void *timeout_ctx)
3254{
3255 struct wpa_supplicant *wpa_s = eloop_ctx;
3256 struct dpp_authentication *auth = wpa_s->dpp_auth;
3257
3258 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
3259 return;
3260
3261 wpa_printf(MSG_DEBUG,
3262 "DPP: No configuration available from upper layers - send initial response with comeback delay");
3263 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
3264 500);
3265}
3266
3267
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003268static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07003269wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003270 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003271{
3272 struct wpa_supplicant *wpa_s = ctx;
3273 struct dpp_authentication *auth = wpa_s->dpp_auth;
3274 struct wpabuf *resp;
3275
3276 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
3277 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003278 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003279 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
3280 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
3281 return NULL;
3282 }
Hai Shalomc3565922019-10-28 11:58:20 -07003283
3284 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
3285 wpa_printf(MSG_DEBUG,
3286 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
3287 /* wpas_dpp_auth_success() would normally have been called from
3288 * TX status handler, but since there was no such handler call
3289 * yet, simply send out the event message and proceed with
3290 * exchange. */
3291 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
3292 wpa_s->dpp_auth_ok_on_ack = 0;
3293 }
3294
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003295 wpa_hexdump(MSG_DEBUG,
3296 "DPP: Received Configuration Request (GAS Query Request)",
3297 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003298 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
3299 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003300 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003301
Hai Shaloma20dcd72022-02-04 13:43:00 -08003302 auth->gas_server_ctx = resp_ctx;
3303
Hai Shalom899fcc72020-10-19 14:38:18 -07003304#ifdef CONFIG_DPP2
3305 if (!resp && auth->waiting_cert) {
3306 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003307 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003308 *comeback_delay = 500;
3309 return NULL;
3310 }
3311#endif /* CONFIG_DPP2 */
3312
Hai Shaloma20dcd72022-02-04 13:43:00 -08003313 if (!resp && auth->waiting_config &&
3314 (auth->peer_bi || auth->tmp_peer_bi)) {
3315 char *buf = NULL, *name = "";
3316 char band[200], *pos, *end;
3317 int i, res, *opclass = auth->e_band_support;
3318 char *mud_url = "N/A";
3319
3320 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
3321 auth->config_resp_ctx = resp_ctx;
3322 *comeback_delay = -1;
3323 if (auth->e_name) {
3324 size_t len = os_strlen(auth->e_name);
3325
3326 buf = os_malloc(len * 4 + 1);
3327 if (buf) {
3328 printf_encode(buf, len * 4 + 1,
3329 (const u8 *) auth->e_name, len);
3330 name = buf;
3331 }
3332 }
3333 band[0] = '\0';
3334 pos = band;
3335 end = band + sizeof(band);
3336 for (i = 0; opclass && opclass[i]; i++) {
3337 res = os_snprintf(pos, end - pos, "%s%d",
3338 pos == band ? "" : ",", opclass[i]);
3339 if (os_snprintf_error(end - pos, res)) {
3340 *pos = '\0';
3341 break;
3342 }
3343 pos += res;
3344 }
3345 if (auth->e_mud_url) {
3346 size_t len = os_strlen(auth->e_mud_url);
3347
3348 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
3349 mud_url = auth->e_mud_url;
3350 }
3351 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
3352 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
3353 auth->peer_bi ? auth->peer_bi->id :
3354 auth->tmp_peer_bi->id, MAC2STR(sa),
3355 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
3356 os_free(buf);
3357
3358 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
3359 NULL);
3360 eloop_register_timeout(0, 50000,
3361 wpas_dpp_gas_initial_resp_timeout, wpa_s,
3362 NULL);
3363 return NULL;
3364 }
3365
Sunil Ravia04bd252022-05-02 22:54:18 -07003366 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08003367 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003368 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08003369 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07003370 dpp_auth_deinit(wpa_s->dpp_auth);
3371 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08003372 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003373 return resp;
3374}
3375
3376
3377static void
3378wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
3379{
3380 struct wpa_supplicant *wpa_s = ctx;
3381 struct dpp_authentication *auth = wpa_s->dpp_auth;
3382
3383 if (!auth) {
3384 wpabuf_free(resp);
3385 return;
3386 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003387 if (auth->conf_resp != resp) {
3388 wpa_printf(MSG_DEBUG,
3389 "DPP: Ignore GAS status report (ok=%d) for unknown response",
3390 ok);
3391 wpabuf_free(resp);
3392 return;
3393 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003394
Hai Shalom899fcc72020-10-19 14:38:18 -07003395#ifdef CONFIG_DPP2
3396 if (auth->waiting_csr && ok) {
3397 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
3398 wpabuf_free(resp);
3399 return;
3400 }
3401#endif /* CONFIG_DPP2 */
3402
Sunil Ravia04bd252022-05-02 22:54:18 -07003403#ifdef CONFIG_DPP3
3404 if (auth->waiting_new_key && ok) {
3405 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
3406 wpabuf_free(resp);
3407 return;
3408 }
3409#endif /* CONFIG_DPP3 */
3410
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003411 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
3412 ok);
3413 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003414 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003415 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003416#ifdef CONFIG_DPP2
3417 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08003418 auth->conf_resp_status == DPP_STATUS_OK &&
3419 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003420 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08003421 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003422 auth->waiting_conf_result = 1;
3423 auth->conf_resp = NULL;
3424 wpabuf_free(resp);
3425 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
3426 wpa_s, NULL);
3427 eloop_register_timeout(2, 0,
3428 wpas_dpp_config_result_wait_timeout,
3429 wpa_s, NULL);
3430 return;
3431 }
3432#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003433 offchannel_send_action_done(wpa_s);
3434 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003435 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003436 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08003437 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003438 }
3439 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003440 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08003441 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003442 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003443 dpp_auth_deinit(wpa_s->dpp_auth);
3444 wpa_s->dpp_auth = NULL;
3445 wpabuf_free(resp);
3446}
3447
3448
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003449int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
3450{
3451 struct dpp_authentication *auth;
3452 int ret = -1;
3453 char *curve = NULL;
3454
Hai Shalomfdcde762020-04-02 11:19:20 -07003455 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003456 if (!auth)
3457 return -1;
3458
3459 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08003460 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07003461 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07003462 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07003463 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
3464 &auth->conf_obj[0]);
3465 if (!ret)
3466 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003467
3468 dpp_auth_deinit(auth);
3469 os_free(curve);
3470
3471 return ret;
3472}
3473
3474
3475static void
3476wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
3477 unsigned int freq, const u8 *dst,
3478 const u8 *src, const u8 *bssid,
3479 const u8 *data, size_t data_len,
3480 enum offchannel_send_action_result result)
3481{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003482 const char *res_txt;
3483
3484 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3485 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3486 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003487 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3488 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003489 freq, MAC2STR(dst), res_txt);
3490 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3491 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003492 /* TODO: Time out wait for response more quickly in error cases? */
3493}
3494
3495
3496int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3497 struct wpa_bss *bss)
3498{
3499 struct os_time now;
3500 struct wpabuf *msg;
3501 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07003502 const u8 *rsn;
3503 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003504 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003505
3506 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
3507 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07003508 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3509 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
3510 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
3511 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003512 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
3513 return 0; /* PMKSA exists for DPP AKM - continue */
3514
3515 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3516 !ssid->dpp_csign) {
3517 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
3518 "missing %s",
3519 !ssid->dpp_connector ? "Connector" :
3520 (!ssid->dpp_netaccesskey ? "netAccessKey" :
3521 "C-sign-key"));
3522 return -1;
3523 }
3524
3525 os_get_time(&now);
3526
3527 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07003528 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003529 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
3530 "netAccessKey expired");
3531 return -1;
3532 }
3533
3534 wpa_printf(MSG_DEBUG,
3535 "DPP: Starting network introduction protocol to derive PMKSA for "
3536 MACSTR, MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07003537 if (wpa_s->wpa_state == WPA_SCANNING)
3538 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003539
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003540 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3541#ifdef CONFIG_DPP2
3542 len += 5;
3543#endif /* CONFIG_DPP2 */
3544 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003545 if (!msg)
3546 return -1;
3547
Roshan Pius3a1667e2018-07-03 15:17:14 -07003548#ifdef CONFIG_TESTING_OPTIONS
3549 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
3550 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
3551 goto skip_trans_id;
3552 }
3553 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
3554 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
3555 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3556 wpabuf_put_le16(msg, 0);
3557 goto skip_trans_id;
3558 }
3559#endif /* CONFIG_TESTING_OPTIONS */
3560
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003561 /* Transaction ID */
3562 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3563 wpabuf_put_le16(msg, 1);
3564 wpabuf_put_u8(msg, TRANSACTION_ID);
3565
Roshan Pius3a1667e2018-07-03 15:17:14 -07003566#ifdef CONFIG_TESTING_OPTIONS
3567skip_trans_id:
3568 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
3569 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
3570 goto skip_connector;
3571 }
3572 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
3573 char *connector;
3574
3575 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
3576 connector = dpp_corrupt_connector_signature(
3577 ssid->dpp_connector);
3578 if (!connector) {
3579 wpabuf_free(msg);
3580 return -1;
3581 }
3582 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
3583 wpabuf_put_le16(msg, os_strlen(connector));
3584 wpabuf_put_str(msg, connector);
3585 os_free(connector);
3586 goto skip_connector;
3587 }
3588#endif /* CONFIG_TESTING_OPTIONS */
3589
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003590 /* DPP Connector */
3591 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
3592 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
3593 wpabuf_put_str(msg, ssid->dpp_connector);
3594
Roshan Pius3a1667e2018-07-03 15:17:14 -07003595#ifdef CONFIG_TESTING_OPTIONS
3596skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003597 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
3598 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
3599 goto skip_proto_ver;
3600 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003601#endif /* CONFIG_TESTING_OPTIONS */
3602
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003603#ifdef CONFIG_DPP2
3604 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003605 u8 ver = DPP_VERSION;
3606#ifdef CONFIG_DPP3
3607 int conn_ver;
3608
3609 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3610 if (conn_ver > 0 && ver != conn_ver) {
3611 wpa_printf(MSG_DEBUG,
3612 "DPP: Use Connector version %d instead of current protocol version %d",
3613 conn_ver, ver);
3614 ver = conn_ver;
3615 }
3616#endif /* CONFIG_DPP3 */
3617
3618#ifdef CONFIG_TESTING_OPTIONS
3619 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
3620 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
3621 ver = 1;
3622 }
3623#endif /* CONFIG_TESTING_OPTIONS */
3624
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003625 /* Protocol Version */
3626 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
3627 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003628 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003629 }
3630#endif /* CONFIG_DPP2 */
3631
Hai Shaloma20dcd72022-02-04 13:43:00 -08003632#ifdef CONFIG_TESTING_OPTIONS
3633skip_proto_ver:
3634#endif /* CONFIG_TESTING_OPTIONS */
3635
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003636 /* TODO: Timeout on AP response */
3637 wait_time = wpa_s->max_remain_on_chan;
3638 if (wait_time > 2000)
3639 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003640 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3641 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003642 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
3643 broadcast,
3644 wpabuf_head(msg), wpabuf_len(msg),
3645 wait_time, wpas_dpp_tx_introduction_status, 0);
3646 wpabuf_free(msg);
3647
3648 /* Request this connection attempt to terminate - new one will be
3649 * started when network introduction protocol completes */
3650 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
3651 wpa_s->dpp_intro_network = ssid;
3652 return 1;
3653}
3654
3655
3656int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
3657{
3658 struct dpp_bootstrap_info *own_bi;
3659 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07003660#ifdef CONFIG_DPP3
3661 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
3662#else /* CONFIG_DPP3 */
3663 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
3664#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003665 int tcp_port = DPP_TCP_PORT;
3666 struct hostapd_ip_addr *ipaddr = NULL;
3667#ifdef CONFIG_DPP2
3668 struct hostapd_ip_addr ipaddr_buf;
3669 char *addr;
3670
3671 pos = os_strstr(cmd, " tcp_port=");
3672 if (pos) {
3673 pos += 10;
3674 tcp_port = atoi(pos);
3675 }
3676
3677 addr = get_param(cmd, " tcp_addr=");
3678 if (addr) {
3679 int res;
3680
3681 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
3682 os_free(addr);
3683 if (res)
3684 return -1;
3685 ipaddr = &ipaddr_buf;
3686 }
3687#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003688
3689 pos = os_strstr(cmd, " own=");
3690 if (!pos)
3691 return -1;
3692 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07003693 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003694 if (!own_bi) {
3695 wpa_printf(MSG_DEBUG,
3696 "DPP: Identified bootstrap info not found");
3697 return -1;
3698 }
3699 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
3700 wpa_printf(MSG_DEBUG,
3701 "DPP: Identified bootstrap info not for PKEX");
3702 return -1;
3703 }
3704 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003705 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003706
3707 os_free(wpa_s->dpp_pkex_identifier);
3708 wpa_s->dpp_pkex_identifier = NULL;
3709 pos = os_strstr(cmd, " identifier=");
3710 if (pos) {
3711 pos += 12;
3712 end = os_strchr(pos, ' ');
3713 if (!end)
3714 return -1;
3715 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
3716 if (!wpa_s->dpp_pkex_identifier)
3717 return -1;
3718 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
3719 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
3720 }
3721
3722 pos = os_strstr(cmd, " code=");
3723 if (!pos)
3724 return -1;
3725 os_free(wpa_s->dpp_pkex_code);
3726 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
3727 if (!wpa_s->dpp_pkex_code)
3728 return -1;
3729
Sunil Ravia04bd252022-05-02 22:54:18 -07003730 pos = os_strstr(cmd, " ver=");
3731 if (pos) {
3732 int v;
3733
3734 pos += 5;
3735 v = atoi(pos);
3736 if (v == 1)
3737 ver = PKEX_VER_ONLY_1;
3738 else if (v == 2)
3739 ver = PKEX_VER_ONLY_2;
3740 else
3741 return -1;
3742 }
3743 wpa_s->dpp_pkex_ver = ver;
3744
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003745 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003746 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003747 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003748 } else {
3749#ifdef CONFIG_DPP2
3750 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
3751 wpa_s->dpp_pkex_code,
3752 wpa_s->dpp_pkex_identifier);
3753#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003754 }
3755
3756 /* TODO: Support multiple PKEX info entries */
3757
3758 os_free(wpa_s->dpp_pkex_auth_cmd);
3759 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
3760
3761 return 1;
3762}
3763
3764
3765int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
3766{
3767 unsigned int id_val;
3768
3769 if (os_strcmp(id, "*") == 0) {
3770 id_val = 0;
3771 } else {
3772 id_val = atoi(id);
3773 if (id_val == 0)
3774 return -1;
3775 }
3776
3777 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
3778 return -1;
3779
3780 /* TODO: Support multiple PKEX entries */
3781 os_free(wpa_s->dpp_pkex_code);
3782 wpa_s->dpp_pkex_code = NULL;
3783 os_free(wpa_s->dpp_pkex_identifier);
3784 wpa_s->dpp_pkex_identifier = NULL;
3785 os_free(wpa_s->dpp_pkex_auth_cmd);
3786 wpa_s->dpp_pkex_auth_cmd = NULL;
3787 wpa_s->dpp_pkex_bi = NULL;
3788 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
3789 dpp_pkex_free(wpa_s->dpp_pkex);
3790 wpa_s->dpp_pkex = NULL;
3791 return 0;
3792}
3793
3794
Roshan Pius3a1667e2018-07-03 15:17:14 -07003795void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
3796{
Sunil Ravia04bd252022-05-02 22:54:18 -07003797 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07003798 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003799 dpp_auth_deinit(wpa_s->dpp_auth);
3800 wpa_s->dpp_auth = NULL;
3801 dpp_pkex_free(wpa_s->dpp_pkex);
3802 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07003803 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003804 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
3805 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
3806}
3807
3808
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003809int wpas_dpp_init(struct wpa_supplicant *wpa_s)
3810{
Hai Shalom81f62d82019-07-22 12:10:00 -07003811 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003812 u8 adv_proto_id[7];
3813
3814 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
3815 adv_proto_id[1] = 5;
3816 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
3817 adv_proto_id[5] = DPP_OUI_TYPE;
3818 adv_proto_id[6] = 0x01;
3819
3820 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
3821 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
3822 wpas_dpp_gas_status_handler, wpa_s) < 0)
3823 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07003824
3825 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07003826 config.cb_ctx = wpa_s;
3827#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003828 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07003829#endif /* CONFIG_DPP2 */
3830 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07003831 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003832}
3833
3834
3835void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
3836{
3837#ifdef CONFIG_TESTING_OPTIONS
3838 os_free(wpa_s->dpp_config_obj_override);
3839 wpa_s->dpp_config_obj_override = NULL;
3840 os_free(wpa_s->dpp_discovery_override);
3841 wpa_s->dpp_discovery_override = NULL;
3842 os_free(wpa_s->dpp_groups_override);
3843 wpa_s->dpp_groups_override = NULL;
3844 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
3845#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07003846 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003847 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003848 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003849 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003850 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003851 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
3852 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003853 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
3854 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003855#ifdef CONFIG_DPP2
3856 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07003857 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
3858 wpa_s, NULL);
3859 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003860 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
3861 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07003862 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003863 dpp_pfs_free(wpa_s->dpp_pfs);
3864 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07003865 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07003866 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
3867 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07003868#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003869#ifdef CONFIG_DPP3
3870 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
3871#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003872 offchannel_send_action_done(wpa_s);
3873 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003874 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003875 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003876 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
3877 os_free(wpa_s->dpp_configurator_params);
3878 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07003879 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003880}
Hai Shalom81f62d82019-07-22 12:10:00 -07003881
3882
Hai Shaloma20dcd72022-02-04 13:43:00 -08003883static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
3884 struct dpp_authentication *auth, bool tcp)
3885{
3886 struct wpabuf *resp;
3887
3888 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
3889 auth->e_netrole, true);
3890 if (!resp)
3891 return -1;
3892
3893 if (tcp) {
3894 auth->conf_resp_tcp = resp;
3895 return 0;
3896 }
3897
3898 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
3899 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
3900 resp) < 0) {
3901 wpa_printf(MSG_DEBUG,
3902 "DPP: Could not find pending GAS response");
3903 wpabuf_free(resp);
3904 return -1;
3905 }
3906 auth->conf_resp = resp;
3907 return 0;
3908}
3909
3910
3911int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
3912{
3913 int peer;
3914 const char *pos;
3915 struct dpp_authentication *auth = wpa_s->dpp_auth;
3916 bool tcp = false;
3917
3918 pos = os_strstr(cmd, " peer=");
3919 if (!pos)
3920 return -1;
3921 peer = atoi(pos + 6);
3922#ifdef CONFIG_DPP2
3923 if (!auth || !auth->waiting_config ||
3924 (auth->peer_bi &&
3925 (unsigned int) peer != auth->peer_bi->id)) {
3926 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
3927 tcp = true;
3928 }
3929#endif /* CONFIG_DPP2 */
3930
3931 if (!auth || !auth->waiting_config) {
3932 wpa_printf(MSG_DEBUG,
3933 "DPP: No authentication exchange waiting for configuration information");
3934 return -1;
3935 }
3936
3937 if ((!auth->peer_bi ||
3938 (unsigned int) peer != auth->peer_bi->id) &&
3939 (!auth->tmp_peer_bi ||
3940 (unsigned int) peer != auth->tmp_peer_bi->id)) {
3941 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
3942 return -1;
3943 }
3944
3945 pos = os_strstr(cmd, " comeback=");
3946 if (pos) {
3947 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
3948 NULL);
3949 gas_server_set_comeback_delay(wpa_s->gas_server,
3950 auth->config_resp_ctx,
3951 atoi(pos + 10));
3952 return 0;
3953 }
3954
3955 if (dpp_set_configurator(auth, cmd) < 0)
3956 return -1;
3957
3958 auth->use_config_query = false;
3959 auth->waiting_config = false;
3960 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
3961}
3962
3963
Hai Shalom81f62d82019-07-22 12:10:00 -07003964#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003965
Hai Shalom81f62d82019-07-22 12:10:00 -07003966int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
3967{
3968 struct dpp_controller_config config;
3969 const char *pos;
3970
3971 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003972 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07003973 config.netrole = DPP_NETROLE_STA;
3974 config.msg_ctx = wpa_s;
3975 config.cb_ctx = wpa_s;
3976 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003977 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07003978 if (cmd) {
3979 pos = os_strstr(cmd, " tcp_port=");
3980 if (pos) {
3981 pos += 10;
3982 config.tcp_port = atoi(pos);
3983 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003984
3985 pos = os_strstr(cmd, " role=");
3986 if (pos) {
3987 pos += 6;
3988 if (os_strncmp(pos, "configurator", 12) == 0)
3989 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
3990 else if (os_strncmp(pos, "enrollee", 8) == 0)
3991 config.allowed_roles = DPP_CAPAB_ENROLLEE;
3992 else if (os_strncmp(pos, "either", 6) == 0)
3993 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
3994 DPP_CAPAB_ENROLLEE;
3995 else
3996 return -1;
3997 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003998
3999 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07004000 }
4001 config.configurator_params = wpa_s->dpp_configurator_params;
4002 return dpp_controller_start(wpa_s->dpp, &config);
4003}
Hai Shalomfdcde762020-04-02 11:19:20 -07004004
4005
4006static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
4007
4008static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
4009{
4010 struct wpa_supplicant *wpa_s = eloop_ctx;
4011
4012 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
4013 offchannel_send_action_done(wpa_s);
4014 wpas_dpp_chirp_next(wpa_s, NULL);
4015}
4016
4017
4018static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
4019 unsigned int freq, const u8 *dst,
4020 const u8 *src, const u8 *bssid,
4021 const u8 *data, size_t data_len,
4022 enum offchannel_send_action_result result)
4023{
4024 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
4025 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
4026 wpa_s->dpp_chirp_freq);
4027 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
4028 wpa_s, NULL) < 0)
4029 wpas_dpp_chirp_stop(wpa_s);
4030 return;
4031 }
4032
4033 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
4034 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
4035 wpa_s, NULL) < 0)
4036 wpas_dpp_chirp_stop(wpa_s);
4037}
4038
4039
4040static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
4041{
Hai Shalom899fcc72020-10-19 14:38:18 -07004042 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004043 int type;
4044
4045 msg = wpa_s->dpp_presence_announcement;
4046 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
4047 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07004048 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
4049
4050 if (ssid && wpa_s->dpp_reconfig_id &&
4051 wpa_config_get_network(wpa_s->conf,
4052 wpa_s->dpp_reconfig_ssid_id) ==
4053 ssid) {
4054 announce = dpp_build_reconfig_announcement(
4055 ssid->dpp_csign,
4056 ssid->dpp_csign_len,
4057 ssid->dpp_netaccesskey,
4058 ssid->dpp_netaccesskey_len,
4059 wpa_s->dpp_reconfig_id);
4060 msg = announce;
4061 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004062 if (!msg)
4063 return;
4064 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
4065 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004066 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
4067 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004068 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07004069 if (offchannel_send_action(
4070 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
4071 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004072 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07004073 2000, wpas_dpp_chirp_tx_status, 0) < 0)
4074 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004075
4076 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07004077}
4078
4079
4080static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
4081 struct wpa_scan_results *scan_res)
4082{
4083 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
4084 unsigned int i;
4085 struct hostapd_hw_modes *mode;
4086 int c;
4087 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004088 bool chan6 = wpa_s->hw.modes == NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004089
Hai Shalom899fcc72020-10-19 14:38:18 -07004090 if (!bi && !wpa_s->dpp_reconfig_ssid)
Hai Shalomfdcde762020-04-02 11:19:20 -07004091 return;
4092
4093 wpa_s->dpp_chirp_scan_done = 1;
4094
4095 os_free(wpa_s->dpp_chirp_freqs);
4096 wpa_s->dpp_chirp_freqs = NULL;
4097
4098 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004099 if (bi) {
4100 for (i = 0; i < bi->num_freq; i++)
4101 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
4102 bi->freq[i]);
4103 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004104
4105 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07004106 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004107 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07004108 if (mode) {
4109 for (c = 0; c < mode->num_channels; c++) {
4110 struct hostapd_channel_data *chan = &mode->channels[c];
4111
4112 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
4113 chan->freq != 2437)
4114 continue;
4115 chan6 = true;
4116 break;
4117 }
4118 }
4119 if (chan6)
4120 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07004121
4122 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004123 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07004124 if (mode) {
4125 int chan44 = 0, chan149 = 0;
4126
4127 for (c = 0; c < mode->num_channels; c++) {
4128 struct hostapd_channel_data *chan = &mode->channels[c];
4129
4130 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
4131 HOSTAPD_CHAN_RADAR))
4132 continue;
4133 if (chan->freq == 5220)
4134 chan44 = 1;
4135 if (chan->freq == 5745)
4136 chan149 = 1;
4137 }
4138 if (chan149)
4139 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745);
4140 else if (chan44)
4141 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220);
4142 }
4143
4144 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004145 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07004146 if (mode) {
4147 for (c = 0; c < mode->num_channels; c++) {
4148 struct hostapd_channel_data *chan = &mode->channels[c];
4149
4150 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
4151 HOSTAPD_CHAN_RADAR)) ||
4152 chan->freq != 60480)
4153 continue;
4154 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480);
4155 break;
4156 }
4157 }
4158
4159 /* Add channels from scan results for APs that advertise Configurator
4160 * Connectivity element */
4161 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4162 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
4163 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
4164 bss->freq);
4165 }
4166
4167 if (!wpa_s->dpp_chirp_freqs ||
4168 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
4169 wpas_dpp_chirp_stop(wpa_s);
4170}
4171
4172
4173static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
4174{
4175 struct wpa_supplicant *wpa_s = eloop_ctx;
4176 int i;
4177
4178 if (wpa_s->dpp_chirp_listen)
4179 wpas_dpp_listen_stop(wpa_s);
4180
4181 if (wpa_s->dpp_chirp_freq == 0) {
4182 if (wpa_s->dpp_chirp_round % 4 == 0 &&
4183 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08004184 if (wpas_scan_scheduled(wpa_s)) {
4185 wpa_printf(MSG_DEBUG,
4186 "DPP: Deferring chirp scan because another scan is planned already");
4187 if (eloop_register_timeout(1, 0,
4188 wpas_dpp_chirp_next,
4189 wpa_s, NULL) < 0) {
4190 wpas_dpp_chirp_stop(wpa_s);
4191 return;
4192 }
4193 return;
4194 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004195 wpa_printf(MSG_DEBUG,
4196 "DPP: Update channel list for chirping");
4197 wpa_s->scan_req = MANUAL_SCAN_REQ;
4198 wpa_s->scan_res_handler =
4199 wpas_dpp_chirp_scan_res_handler;
4200 wpa_supplicant_req_scan(wpa_s, 0, 0);
4201 return;
4202 }
4203 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
4204 wpa_s->dpp_chirp_round++;
4205 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
4206 wpa_s->dpp_chirp_round);
4207 } else {
4208 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
4209 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
4210 break;
4211 if (!wpa_s->dpp_chirp_freqs[i]) {
4212 wpa_printf(MSG_DEBUG,
4213 "DPP: Previous chirp freq %d not found",
4214 wpa_s->dpp_chirp_freq);
4215 return;
4216 }
4217 i++;
4218 if (wpa_s->dpp_chirp_freqs[i]) {
4219 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
4220 } else {
4221 wpa_s->dpp_chirp_iter--;
4222 if (wpa_s->dpp_chirp_iter <= 0) {
4223 wpa_printf(MSG_DEBUG,
4224 "DPP: Chirping iterations completed");
4225 wpas_dpp_chirp_stop(wpa_s);
4226 return;
4227 }
4228 wpa_s->dpp_chirp_freq = 0;
4229 wpa_s->dpp_chirp_scan_done = 0;
4230 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
4231 wpa_s, NULL) < 0) {
4232 wpas_dpp_chirp_stop(wpa_s);
4233 return;
4234 }
4235 if (wpa_s->dpp_chirp_listen) {
4236 wpa_printf(MSG_DEBUG,
4237 "DPP: Listen on %d MHz during chirp 30 second wait",
4238 wpa_s->dpp_chirp_listen);
4239 wpas_dpp_listen_start(wpa_s,
4240 wpa_s->dpp_chirp_listen);
4241 } else {
4242 wpa_printf(MSG_DEBUG,
4243 "DPP: Wait 30 seconds before starting the next chirping round");
4244 }
4245 return;
4246 }
4247 }
4248
4249 wpas_dpp_chirp_start(wpa_s);
4250}
4251
4252
4253int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
4254{
4255 const char *pos;
4256 int iter = 1, listen_freq = 0;
4257 struct dpp_bootstrap_info *bi;
4258
4259 pos = os_strstr(cmd, " own=");
4260 if (!pos)
4261 return -1;
4262 pos += 5;
4263 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
4264 if (!bi) {
4265 wpa_printf(MSG_DEBUG,
4266 "DPP: Identified bootstrap info not found");
4267 return -1;
4268 }
4269
4270 pos = os_strstr(cmd, " iter=");
4271 if (pos) {
4272 iter = atoi(pos + 6);
4273 if (iter <= 0)
4274 return -1;
4275 }
4276
4277 pos = os_strstr(cmd, " listen=");
4278 if (pos) {
4279 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004280 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07004281 return -1;
4282 }
4283
4284 wpas_dpp_chirp_stop(wpa_s);
4285 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07004286 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07004287 wpa_s->dpp_qr_mutual = 0;
4288 wpa_s->dpp_chirp_bi = bi;
4289 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
4290 if (!wpa_s->dpp_presence_announcement)
4291 return -1;
4292 wpa_s->dpp_chirp_iter = iter;
4293 wpa_s->dpp_chirp_round = 0;
4294 wpa_s->dpp_chirp_scan_done = 0;
4295 wpa_s->dpp_chirp_listen = listen_freq;
4296
4297 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
4298}
4299
4300
4301void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
4302{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004303 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07004304 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004305 offchannel_send_action_done(wpa_s);
4306 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
4307 }
4308 wpa_s->dpp_chirp_bi = NULL;
4309 wpabuf_free(wpa_s->dpp_presence_announcement);
4310 wpa_s->dpp_presence_announcement = NULL;
4311 if (wpa_s->dpp_chirp_listen)
4312 wpas_dpp_listen_stop(wpa_s);
4313 wpa_s->dpp_chirp_listen = 0;
4314 wpa_s->dpp_chirp_freq = 0;
4315 os_free(wpa_s->dpp_chirp_freqs);
4316 wpa_s->dpp_chirp_freqs = NULL;
4317 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
4318 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
4319 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
4320 wpas_abort_ongoing_scan(wpa_s);
4321 wpa_s->scan_res_handler = NULL;
4322 }
4323}
4324
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004325
Hai Shalom899fcc72020-10-19 14:38:18 -07004326int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004327{
Hai Shalom899fcc72020-10-19 14:38:18 -07004328 struct wpa_ssid *ssid;
4329 int iter = 1;
4330 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004331
Hai Shalom899fcc72020-10-19 14:38:18 -07004332 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
4333 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4334 !ssid->dpp_csign) {
4335 wpa_printf(MSG_DEBUG,
4336 "DPP: Not a valid network profile for reconfiguration");
4337 return -1;
4338 }
4339
4340 pos = os_strstr(cmd, " iter=");
4341 if (pos) {
4342 iter = atoi(pos + 6);
4343 if (iter <= 0)
4344 return -1;
4345 }
4346
4347 if (wpa_s->dpp_auth) {
4348 wpa_printf(MSG_DEBUG,
4349 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
4350 return -1;
4351 }
4352
4353 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4354 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
4355 ssid->dpp_csign_len,
4356 ssid->dpp_pp_key,
4357 ssid->dpp_pp_key_len);
4358 if (!wpa_s->dpp_reconfig_id) {
4359 wpa_printf(MSG_DEBUG,
4360 "DPP: Failed to generate E-id for reconfiguration");
4361 return -1;
4362 }
4363 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
4364 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
4365 wpa_s->own_disconnect_req = 1;
4366 wpa_supplicant_deauthenticate(
4367 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4368 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004369 wpas_dpp_chirp_stop(wpa_s);
4370 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07004371 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004372 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004373 wpa_s->dpp_reconfig_ssid = ssid;
4374 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07004375 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004376 wpa_s->dpp_chirp_round = 0;
4377 wpa_s->dpp_chirp_scan_done = 0;
4378 wpa_s->dpp_chirp_listen = 0;
4379
4380 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
4381}
4382
Hai Shalom899fcc72020-10-19 14:38:18 -07004383
Hai Shalom899fcc72020-10-19 14:38:18 -07004384int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
4385{
4386 int peer = -1;
4387 const char *pos, *value;
4388 struct dpp_authentication *auth = wpa_s->dpp_auth;
4389 u8 *bin;
4390 size_t bin_len;
4391 struct wpabuf *buf;
4392 bool tcp = false;
4393
4394 pos = os_strstr(cmd, " peer=");
4395 if (pos) {
4396 peer = atoi(pos + 6);
4397 if (!auth || !auth->waiting_cert ||
4398 (auth->peer_bi &&
4399 (unsigned int) peer != auth->peer_bi->id)) {
4400 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4401 tcp = true;
4402 }
4403 }
4404
4405 if (!auth || !auth->waiting_cert) {
4406 wpa_printf(MSG_DEBUG,
4407 "DPP: No authentication exchange waiting for certificate information");
4408 return -1;
4409 }
4410
4411 if (peer >= 0 &&
4412 (!auth->peer_bi ||
4413 (unsigned int) peer != auth->peer_bi->id) &&
4414 (!auth->tmp_peer_bi ||
4415 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4416 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4417 return -1;
4418 }
4419
4420 pos = os_strstr(cmd, " value=");
4421 if (!pos)
4422 return -1;
4423 value = pos + 7;
4424
4425 pos = os_strstr(cmd, " name=");
4426 if (!pos)
4427 return -1;
4428 pos += 6;
4429
4430 if (os_strncmp(pos, "status ", 7) == 0) {
4431 auth->force_conf_resp_status = atoi(value);
4432 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4433 }
4434
4435 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
4436 os_free(auth->trusted_eap_server_name);
4437 auth->trusted_eap_server_name = os_strdup(value);
4438 return auth->trusted_eap_server_name ? 0 : -1;
4439 }
4440
4441 bin = base64_decode(value, os_strlen(value), &bin_len);
4442 if (!bin)
4443 return -1;
4444 buf = wpabuf_alloc_copy(bin, bin_len);
4445 os_free(bin);
4446
4447 if (os_strncmp(pos, "caCert ", 7) == 0) {
4448 wpabuf_free(auth->cacert);
4449 auth->cacert = buf;
4450 return 0;
4451 }
4452
4453 if (os_strncmp(pos, "certBag ", 8) == 0) {
4454 wpabuf_free(auth->certbag);
4455 auth->certbag = buf;
4456 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4457 }
4458
4459 wpabuf_free(buf);
4460 return -1;
4461}
4462
Hai Shalom81f62d82019-07-22 12:10:00 -07004463#endif /* CONFIG_DPP2 */