blob: d570cfe9fb4f831200587f5a045b63aa8ffb9d39 [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
1151 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001152 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001153 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001154 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1155 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001156 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001157 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001158 if (!wpa_s->dpp_auth) {
1159 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1160 return;
1161 }
1162 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001163 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001164 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001165 dpp_auth_deinit(wpa_s->dpp_auth);
1166 wpa_s->dpp_auth = NULL;
1167 return;
1168 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001169 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1170
Roshan Pius3a1667e2018-07-03 15:17:14 -07001171 if (wpa_s->dpp_listen_freq &&
1172 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1173 wpa_printf(MSG_DEBUG,
1174 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1175 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1176 wpas_dpp_listen_stop(wpa_s);
1177 }
1178
1179 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1180 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1181 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001182 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1183 src, wpa_s->own_addr, broadcast,
1184 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1185 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1186 500, wpas_dpp_tx_status, 0);
1187}
1188
1189
Hai Shaloma20dcd72022-02-04 13:43:00 -08001190void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
1191{
1192 struct dpp_authentication *auth = wpa_s->dpp_auth;
1193 int freq;
1194
1195 if (!wpa_s->dpp_gas_server || !auth)
1196 return;
1197
1198 freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
1199 if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
1200 return; /* listen state is already in progress */
1201
1202 wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
1203 wpa_s->dpp_in_response_listen = 1;
1204 wpas_dpp_listen_start(wpa_s, freq);
1205}
1206
1207
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001208static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1209{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001210 struct dpp_authentication *auth = wpa_s->dpp_auth;
1211
1212 wpa_printf(MSG_DEBUG,
1213 "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
1214 auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
1215 !!wpa_s->dpp_listen_work);
1216 wpa_s->dpp_gas_server = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001217}
1218
1219
1220static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001221 struct dpp_authentication *auth,
1222 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001223{
1224 struct wpa_ssid *ssid;
1225
Hai Shalom021b0b52019-04-10 11:17:58 -07001226#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001227 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001228#ifdef CONFIG_SAE
1229 struct wpa_driver_capa capa;
1230 int res;
1231
1232 res = wpa_drv_get_capa(wpa_s, &capa);
1233 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001234 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1235 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001236 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1237 wpa_printf(MSG_DEBUG,
1238 "DPP: SAE not supported by the driver");
1239 return NULL;
1240 }
1241#else /* CONFIG_SAE */
1242 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1243 return NULL;
1244#endif /* CONFIG_SAE */
1245 }
1246#endif /* CONFIG_DPP2 */
1247
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001248 ssid = wpa_config_add_network(wpa_s->conf);
1249 if (!ssid)
1250 return NULL;
1251 wpas_notify_network_added(wpa_s, ssid);
1252 wpa_config_set_network_defaults(ssid);
1253 ssid->disabled = 1;
1254
Hai Shalomc3565922019-10-28 11:58:20 -07001255 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001256 if (!ssid->ssid)
1257 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001258 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1259 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001260
Hai Shalomc3565922019-10-28 11:58:20 -07001261 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001262 if (dpp_akm_dpp(conf->akm)) {
1263 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1264 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1265 }
Hai Shalomc3565922019-10-28 11:58:20 -07001266 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001267 if (!ssid->dpp_connector)
1268 goto fail;
1269 }
1270
Hai Shalomc3565922019-10-28 11:58:20 -07001271 if (conf->c_sign_key) {
1272 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001273 if (!ssid->dpp_csign)
1274 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001275 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1276 wpabuf_len(conf->c_sign_key));
1277 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001278 }
1279
Hai Shalom899fcc72020-10-19 14:38:18 -07001280 if (conf->pp_key) {
1281 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1282 if (!ssid->dpp_pp_key)
1283 goto fail;
1284 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1285 wpabuf_len(conf->pp_key));
1286 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1287 }
1288
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001289 if (auth->net_access_key) {
1290 ssid->dpp_netaccesskey =
1291 os_malloc(wpabuf_len(auth->net_access_key));
1292 if (!ssid->dpp_netaccesskey)
1293 goto fail;
1294 os_memcpy(ssid->dpp_netaccesskey,
1295 wpabuf_head(auth->net_access_key),
1296 wpabuf_len(auth->net_access_key));
1297 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1298 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1299 }
1300
Hai Shalomc3565922019-10-28 11:58:20 -07001301 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1302 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001303 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001304 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001305 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001306 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1307 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001308 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001309 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1310 WPA_KEY_MGMT_FT_SAE;
1311 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001312 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001313 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001314 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001315 goto fail;
1316 wpa_config_update_psk(ssid);
1317 ssid->export_keys = 1;
1318 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001319 ssid->psk_set = conf->psk_set;
1320 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001321 }
1322 }
1323
Hai Shalom899fcc72020-10-19 14:38:18 -07001324#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1325 if (conf->akm == DPP_AKM_DOT1X) {
1326 int i;
1327 char name[100], blobname[128];
1328 struct wpa_config_blob *blob;
1329
1330 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1331 WPA_KEY_MGMT_IEEE8021X_SHA256 |
1332 WPA_KEY_MGMT_IEEE8021X_SHA256;
1333 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1334
1335 if (conf->cacert) {
1336 /* caCert is DER-encoded X.509v3 certificate for the
1337 * server certificate if that is different from the
1338 * trust root included in certBag. */
1339 /* TODO: ssid->eap.cert.ca_cert */
1340 }
1341
1342 if (conf->certs) {
1343 for (i = 0; ; i++) {
1344 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1345 i);
1346 if (!wpa_config_get_blob(wpa_s->conf, name))
1347 break;
1348 }
1349
1350 blob = os_zalloc(sizeof(*blob));
1351 if (!blob)
1352 goto fail;
1353 blob->len = wpabuf_len(conf->certs);
1354 blob->name = os_strdup(name);
1355 blob->data = os_malloc(blob->len);
1356 if (!blob->name || !blob->data) {
1357 wpa_config_free_blob(blob);
1358 goto fail;
1359 }
1360 os_memcpy(blob->data, wpabuf_head(conf->certs),
1361 blob->len);
1362 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1363 name);
1364 wpa_config_set_blob(wpa_s->conf, blob);
1365 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1366 name);
1367 ssid->eap.cert.client_cert = os_strdup(blobname);
1368 if (!ssid->eap.cert.client_cert)
1369 goto fail;
1370
1371 /* TODO: ssid->eap.identity from own certificate */
1372 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1373 0) < 0)
1374 goto fail;
1375 }
1376
1377 if (auth->priv_key) {
1378 for (i = 0; ; i++) {
1379 os_snprintf(name, sizeof(name), "dpp-key-%d",
1380 i);
1381 if (!wpa_config_get_blob(wpa_s->conf, name))
1382 break;
1383 }
1384
1385 blob = os_zalloc(sizeof(*blob));
1386 if (!blob)
1387 goto fail;
1388 blob->len = wpabuf_len(auth->priv_key);
1389 blob->name = os_strdup(name);
1390 blob->data = os_malloc(blob->len);
1391 if (!blob->name || !blob->data) {
1392 wpa_config_free_blob(blob);
1393 goto fail;
1394 }
1395 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1396 blob->len);
1397 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1398 name);
1399 wpa_config_set_blob(wpa_s->conf, blob);
1400 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1401 name);
1402 ssid->eap.cert.private_key = os_strdup(blobname);
1403 if (!ssid->eap.cert.private_key)
1404 goto fail;
1405 }
1406
1407 if (conf->server_name) {
1408 ssid->eap.cert.domain_suffix_match =
1409 os_strdup(conf->server_name);
1410 if (!ssid->eap.cert.domain_suffix_match)
1411 goto fail;
1412 }
1413
1414 /* TODO: Use entCreds::eapMethods */
1415 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1416 goto fail;
1417 }
1418#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1419
Hai Shalomc3565922019-10-28 11:58:20 -07001420 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1421 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1422
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001423 return ssid;
1424fail:
1425 wpas_notify_network_removed(wpa_s, ssid);
1426 wpa_config_remove_network(wpa_s->conf, ssid->id);
1427 return NULL;
1428}
1429
1430
Hai Shalom021b0b52019-04-10 11:17:58 -07001431static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001432 struct dpp_authentication *auth,
1433 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001434{
1435 struct wpa_ssid *ssid;
1436
1437 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001438 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001439
Hai Shalomc3565922019-10-28 11:58:20 -07001440 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001441 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001442 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001443
1444 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001445
Hai Shalom706f99b2019-01-08 16:23:37 -08001446 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001447
Hai Shalom021b0b52019-04-10 11:17:58 -07001448 if (wpa_s->conf->dpp_config_processing == 2)
1449 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001450
Hai Shalom021b0b52019-04-10 11:17:58 -07001451#ifndef CONFIG_NO_CONFIG_WRITE
1452 if (wpa_s->conf->update_config &&
1453 wpa_config_write(wpa_s->confname, wpa_s->conf))
1454 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1455#endif /* CONFIG_NO_CONFIG_WRITE */
1456
Hai Shalomc3565922019-10-28 11:58:20 -07001457 return 0;
1458}
1459
1460
1461static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1462 struct dpp_authentication *auth)
1463{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001464#ifdef CONFIG_DPP2
1465 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1466 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1467 wpa_s->dpp_reconfig_ssid) {
1468 wpa_printf(MSG_DEBUG,
1469 "DPP: Remove reconfigured network profile");
1470 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1471 wpa_config_remove_network(wpa_s->conf,
1472 wpa_s->dpp_reconfig_ssid_id);
1473 wpa_s->dpp_reconfig_ssid = NULL;
1474 wpa_s->dpp_reconfig_ssid_id = -1;
1475 }
1476#endif /* CONFIG_DPP2 */
1477
Hai Shalom021b0b52019-04-10 11:17:58 -07001478 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001479 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001480
1481#ifdef CONFIG_DPP2
1482 if (auth->peer_version >= 2) {
1483 wpa_printf(MSG_DEBUG,
1484 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1485 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001486 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001487 }
1488#endif /* CONFIG_DPP2 */
1489
1490 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001491}
1492
1493
Hai Shalom021b0b52019-04-10 11:17:58 -07001494static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001495 struct dpp_authentication *auth,
1496 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001497{
1498 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001499 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1500 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001501 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001502 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001503 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001504 if (conf->ssid_charset)
1505 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1506 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001507 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001508 /* TODO: Save the Connector and consider using a command
1509 * to fetch the value instead of sending an event with
1510 * it. The Connector could end up being larger than what
1511 * most clients are ready to receive as an event
1512 * message. */
1513 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001514 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001515 }
Hai Shalom60840252021-02-19 19:02:11 -08001516 if (conf->passphrase[0]) {
1517 char hex[64 * 2 + 1];
1518
1519 wpa_snprintf_hex(hex, sizeof(hex),
1520 (const u8 *) conf->passphrase,
1521 os_strlen(conf->passphrase));
1522 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1523 hex);
1524 } else if (conf->psk_set) {
1525 char hex[PMK_LEN * 2 + 1];
1526
1527 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1528 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1529 hex);
1530 }
Hai Shalomc3565922019-10-28 11:58:20 -07001531 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001532 char *hex;
1533 size_t hexlen;
1534
Hai Shalomc3565922019-10-28 11:58:20 -07001535 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001536 hex = os_malloc(hexlen);
1537 if (hex) {
1538 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001539 wpabuf_head(conf->c_sign_key),
1540 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001541 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1542 hex);
1543 os_free(hex);
1544 }
1545 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001546 if (conf->pp_key) {
1547 char *hex;
1548 size_t hexlen;
1549
1550 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1551 hex = os_malloc(hexlen);
1552 if (hex) {
1553 wpa_snprintf_hex(hex, hexlen,
1554 wpabuf_head(conf->pp_key),
1555 wpabuf_len(conf->pp_key));
1556 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1557 os_free(hex);
1558 }
1559 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001560 if (auth->net_access_key) {
1561 char *hex;
1562 size_t hexlen;
1563
1564 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1565 hex = os_malloc(hexlen);
1566 if (hex) {
1567 wpa_snprintf_hex(hex, hexlen,
1568 wpabuf_head(auth->net_access_key),
1569 wpabuf_len(auth->net_access_key));
1570 if (auth->net_access_key_expiry)
1571 wpa_msg(wpa_s, MSG_INFO,
1572 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1573 (long unsigned)
1574 auth->net_access_key_expiry);
1575 else
1576 wpa_msg(wpa_s, MSG_INFO,
1577 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1578 os_free(hex);
1579 }
1580 }
1581
Hai Shalom899fcc72020-10-19 14:38:18 -07001582#ifdef CONFIG_DPP2
1583 if (conf->certbag) {
1584 char *b64;
1585
1586 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1587 wpabuf_len(conf->certbag), NULL);
1588 if (b64)
1589 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1590 os_free(b64);
1591 }
1592
1593 if (conf->cacert) {
1594 char *b64;
1595
1596 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1597 wpabuf_len(conf->cacert), NULL);
1598 if (b64)
1599 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1600 os_free(b64);
1601 }
1602
1603 if (conf->server_name)
1604 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1605 conf->server_name);
1606#endif /* CONFIG_DPP2 */
1607
Hai Shalomc3565922019-10-28 11:58:20 -07001608 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001609}
1610
1611
Hai Shalomfdcde762020-04-02 11:19:20 -07001612static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1613 struct dpp_asymmetric_key *key)
1614{
1615#ifdef CONFIG_DPP2
1616 int res;
1617
1618 if (!key)
1619 return 0;
1620
1621 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1622 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001623 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001624
1625 while (key) {
1626 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1627 if (res < 0)
1628 return -1;
1629 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1630 res);
1631 key = key->next;
1632 }
1633#endif /* CONFIG_DPP2 */
1634
1635 return 0;
1636}
1637
1638
Hai Shalom899fcc72020-10-19 14:38:18 -07001639#ifdef CONFIG_DPP2
1640static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1641{
1642 struct wpa_supplicant *wpa_s = eloop_ctx;
1643 struct dpp_authentication *auth = wpa_s->dpp_auth;
1644
1645 if (!auth || !auth->csrattrs)
1646 return;
1647
1648 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1649 wpabuf_free(auth->csr);
1650 /* TODO: Additional information needed for CSR based on csrAttrs */
1651 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1652 wpa_s->conf->dpp_name : "Test");
1653 if (!auth->csr) {
1654 dpp_auth_deinit(wpa_s->dpp_auth);
1655 wpa_s->dpp_auth = NULL;
1656 return;
1657 }
1658
1659 wpas_dpp_start_gas_client(wpa_s);
1660}
1661#endif /* CONFIG_DPP2 */
1662
1663
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001664static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1665 enum gas_query_result result,
1666 const struct wpabuf *adv_proto,
1667 const struct wpabuf *resp, u16 status_code)
1668{
1669 struct wpa_supplicant *wpa_s = ctx;
1670 const u8 *pos;
1671 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001672 int res;
1673 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001674 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001675
Hai Shaloma20dcd72022-02-04 13:43:00 -08001676 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001677 wpa_s->dpp_gas_dialog_token = -1;
1678
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001679 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
1680 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001681 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1682 return;
1683 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001684 if (result != GAS_QUERY_SUCCESS ||
1685 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001686 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1687 goto fail;
1688 }
1689
1690 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1691 adv_proto);
1692 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1693 resp);
1694
1695 if (wpabuf_len(adv_proto) != 10 ||
1696 !(pos = wpabuf_head(adv_proto)) ||
1697 pos[0] != WLAN_EID_ADV_PROTO ||
1698 pos[1] != 8 ||
1699 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1700 pos[4] != 5 ||
1701 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1702 pos[8] != 0x1a ||
1703 pos[9] != 1) {
1704 wpa_printf(MSG_DEBUG,
1705 "DPP: Not a DPP Advertisement Protocol ID");
1706 goto fail;
1707 }
1708
Hai Shalom899fcc72020-10-19 14:38:18 -07001709 res = dpp_conf_resp_rx(auth, resp);
1710#ifdef CONFIG_DPP2
1711 if (res == -2) {
1712 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1713 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1714 return;
1715 }
1716#endif /* CONFIG_DPP2 */
1717 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001718 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1719 goto fail;
1720 }
1721
Hai Shalom899fcc72020-10-19 14:38:18 -07001722 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001723 for (i = 0; i < auth->num_conf_obj; i++) {
1724 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1725 &auth->conf_obj[i]);
1726 if (res < 0)
1727 goto fail;
1728 }
1729 if (auth->num_conf_obj)
1730 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001731 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1732 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001733
Hai Shalom021b0b52019-04-10 11:17:58 -07001734 status = DPP_STATUS_OK;
1735#ifdef CONFIG_TESTING_OPTIONS
1736 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1737 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1738 status = DPP_STATUS_CONFIG_REJECTED;
1739 }
1740#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001741fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001742 if (status != DPP_STATUS_OK) {
1743 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1744 wpas_notify_dpp_configuration_failure(wpa_s);
1745 }
1746#ifdef CONFIG_DPP2
1747 if (auth->peer_version >= 2 &&
1748 auth->conf_resp_status == DPP_STATUS_OK) {
1749 struct wpabuf *msg;
1750
1751 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1752 msg = dpp_build_conf_result(auth, status);
1753 if (!msg)
1754 goto fail2;
1755
1756 wpa_msg(wpa_s, MSG_INFO,
1757 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1758 MAC2STR(addr), auth->curr_freq,
1759 DPP_PA_CONFIGURATION_RESULT);
1760 offchannel_send_action(wpa_s, auth->curr_freq,
1761 addr, wpa_s->own_addr, broadcast,
1762 wpabuf_head(msg),
1763 wpabuf_len(msg),
1764 500, wpas_dpp_tx_status, 0);
1765 wpabuf_free(msg);
1766
1767 /* This exchange will be terminated in the TX status handler */
Hai Shalom899fcc72020-10-19 14:38:18 -07001768 if (wpa_s->conf->dpp_config_processing < 2 ||
1769 wpa_s->dpp_conf_backup_received)
1770 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001771 return;
1772 }
1773fail2:
1774#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001775 dpp_auth_deinit(wpa_s->dpp_auth);
1776 wpa_s->dpp_auth = NULL;
1777}
1778
1779
Hai Shaloma20dcd72022-02-04 13:43:00 -08001780static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
1781{
1782 struct wpa_supplicant *wpa_s = eloop_ctx;
1783 struct dpp_authentication *auth = wpa_s->dpp_auth;
1784
1785 if (!wpa_s->dpp_gas_client || !auth ||
1786 (!auth->auth_success && !auth->reconfig_success))
1787 return;
1788
1789 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
1790 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1791 dpp_auth_deinit(wpa_s->dpp_auth);
1792 wpa_s->dpp_auth = NULL;
1793}
1794
1795
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001796static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1797{
1798 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001799 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001800 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001801 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001802
1803 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001804 offchannel_send_action_done(wpa_s);
1805 wpas_dpp_listen_stop(wpa_s);
1806
Hai Shalomc3565922019-10-28 11:58:20 -07001807 supp_op_classes = wpas_supp_op_classes(wpa_s);
1808 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001809 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001810 wpa_s->conf->dpp_mud_url,
1811 supp_op_classes);
1812 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001813 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001814 wpa_printf(MSG_DEBUG,
1815 "DPP: No configuration request data available");
1816 return;
1817 }
1818
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001819 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1820 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1821
Hai Shaloma20dcd72022-02-04 13:43:00 -08001822 /* Use a 120 second timeout since the gas_query_req() operation could
1823 * remain waiting indefinitely for the response if the Configurator
1824 * keeps sending out comeback responses with additional delay. The
1825 * DPP technical specification expects the Enrollee to continue sending
1826 * out new Config Requests for 60 seconds, so this gives an extra 60
1827 * second time after the last expected new Config Request for the
1828 * Configurator to determine what kind of configuration to provide. */
1829 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
1830 wpa_s, NULL);
1831
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001832 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001833 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001834 if (res < 0) {
1835 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1836 wpabuf_free(buf);
1837 } else {
1838 wpa_printf(MSG_DEBUG,
1839 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001840 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001841 }
1842}
1843
1844
1845static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1846{
1847 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1848 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001849 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001850#ifdef CONFIG_TESTING_OPTIONS
1851 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1852 wpa_printf(MSG_INFO,
1853 "DPP: TESTING - stop at Authentication Confirm");
1854 if (wpa_s->dpp_auth->configurator) {
1855 /* Prevent GAS response */
1856 wpa_s->dpp_auth->auth_success = 0;
1857 }
1858 return;
1859 }
1860#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001861
1862 if (wpa_s->dpp_auth->configurator)
1863 wpas_dpp_start_gas_server(wpa_s);
1864 else
1865 wpas_dpp_start_gas_client(wpa_s);
1866}
1867
1868
1869static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001870 const u8 *hdr, const u8 *buf, size_t len,
1871 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001872{
1873 struct dpp_authentication *auth = wpa_s->dpp_auth;
1874 struct wpabuf *msg;
1875
Roshan Pius3a1667e2018-07-03 15:17:14 -07001876 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1877 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001878
1879 if (!auth) {
1880 wpa_printf(MSG_DEBUG,
1881 "DPP: No DPP Authentication in progress - drop");
1882 return;
1883 }
1884
1885 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1886 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1887 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1888 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1889 return;
1890 }
1891
1892 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1893
Roshan Pius3a1667e2018-07-03 15:17:14 -07001894 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1895 wpa_printf(MSG_DEBUG,
1896 "DPP: Responder accepted request for different negotiation channel");
1897 auth->curr_freq = freq;
1898 }
1899
1900 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001901 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1902 if (!msg) {
1903 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1904 wpa_printf(MSG_DEBUG,
1905 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001906 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001907 offchannel_send_action_done(wpa_s);
1908 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1909 return;
1910 }
1911 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1912 return;
1913 }
1914 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1915
Roshan Pius3a1667e2018-07-03 15:17:14 -07001916 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1917 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001918 offchannel_send_action(wpa_s, auth->curr_freq,
1919 src, wpa_s->own_addr, broadcast,
1920 wpabuf_head(msg), wpabuf_len(msg),
1921 500, wpas_dpp_tx_status, 0);
1922 wpabuf_free(msg);
1923 wpa_s->dpp_auth_ok_on_ack = 1;
1924}
1925
1926
1927static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1928 const u8 *hdr, const u8 *buf, size_t len)
1929{
1930 struct dpp_authentication *auth = wpa_s->dpp_auth;
1931
1932 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1933 MAC2STR(src));
1934
1935 if (!auth) {
1936 wpa_printf(MSG_DEBUG,
1937 "DPP: No DPP Authentication in progress - drop");
1938 return;
1939 }
1940
1941 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1942 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1943 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1944 return;
1945 }
1946
Hai Shalom60840252021-02-19 19:02:11 -08001947 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
1948
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001949 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1950 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001951 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001952 return;
1953 }
1954
1955 wpas_dpp_auth_success(wpa_s, 0);
1956}
1957
1958
Hai Shalom021b0b52019-04-10 11:17:58 -07001959#ifdef CONFIG_DPP2
1960
1961static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
1962 void *timeout_ctx)
1963{
1964 struct wpa_supplicant *wpa_s = eloop_ctx;
1965 struct dpp_authentication *auth = wpa_s->dpp_auth;
1966
1967 if (!auth || !auth->waiting_conf_result)
1968 return;
1969
1970 wpa_printf(MSG_DEBUG,
1971 "DPP: Timeout while waiting for Configuration Result");
1972 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001973 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07001974 dpp_auth_deinit(auth);
1975 wpa_s->dpp_auth = NULL;
1976}
1977
1978
Hai Shalomc3565922019-10-28 11:58:20 -07001979static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1980 void *timeout_ctx)
1981{
1982 struct wpa_supplicant *wpa_s = eloop_ctx;
1983 struct dpp_authentication *auth = wpa_s->dpp_auth;
1984
1985 if (!auth || !auth->waiting_conn_status_result)
1986 return;
1987
1988 wpa_printf(MSG_DEBUG,
1989 "DPP: Timeout while waiting for Connection Status Result");
1990 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08001991 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001992 wpas_dpp_listen_stop(wpa_s);
1993 dpp_auth_deinit(auth);
1994 wpa_s->dpp_auth = NULL;
1995}
1996
1997
Hai Shalom021b0b52019-04-10 11:17:58 -07001998static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
1999 const u8 *hdr, const u8 *buf, size_t len)
2000{
2001 struct dpp_authentication *auth = wpa_s->dpp_auth;
2002 enum dpp_status_error status;
2003
2004 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2005 MAC2STR(src));
2006
2007 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002008 if (auth &&
2009 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
2010 gas_server_response_sent(wpa_s->gas_server,
2011 auth->gas_server_ctx)) {
2012 /* This could happen if the TX status event gets delayed
2013 * long enough for the Enrollee to have time to send
2014 * the next frame before the TX status gets processed
2015 * locally. */
2016 wpa_printf(MSG_DEBUG,
2017 "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");
2018 auth->waiting_conf_result = 1;
2019 } else {
2020 wpa_printf(MSG_DEBUG,
2021 "DPP: No DPP Configuration waiting for result - drop");
2022 return;
2023 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002024 }
2025
2026 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2027 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2028 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2029 return;
2030 }
2031
2032 status = dpp_conf_result_rx(auth, hdr, buf, len);
2033
Hai Shalomc3565922019-10-28 11:58:20 -07002034 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002035 int freq;
2036
Hai Shalomc3565922019-10-28 11:58:20 -07002037 wpa_msg(wpa_s, MSG_INFO,
2038 DPP_EVENT_CONF_SENT "wait_conn_status=1");
2039 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002040 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002041 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2042 wpa_s, NULL);
2043 auth->waiting_conn_status_result = 1;
2044 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2045 wpa_s, NULL);
2046 eloop_register_timeout(16, 0,
2047 wpas_dpp_conn_status_result_wait_timeout,
2048 wpa_s, NULL);
2049 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002050 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2051 if (!wpa_s->dpp_in_response_listen ||
2052 (int) wpa_s->dpp_listen_freq != freq)
2053 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002054 return;
2055 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002056 offchannel_send_action_done(wpa_s);
2057 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002058 if (status == DPP_STATUS_OK) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002059 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalome4073332019-11-05 16:20:12 -08002060 wpas_notify_dpp_config_sent(wpa_s);
2061 }
2062 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002063 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002064 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002065 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002066 dpp_auth_deinit(auth);
2067 wpa_s->dpp_auth = NULL;
2068 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
2069}
2070
Hai Shalom81f62d82019-07-22 12:10:00 -07002071
Hai Shalomc3565922019-10-28 11:58:20 -07002072static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2073 const u8 *src, const u8 *hdr,
2074 const u8 *buf, size_t len)
2075{
2076 struct dpp_authentication *auth = wpa_s->dpp_auth;
2077 enum dpp_status_error status;
2078 u8 ssid[SSID_MAX_LEN];
2079 size_t ssid_len = 0;
2080 char *channel_list = NULL;
2081
2082 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2083
2084 if (!auth || !auth->waiting_conn_status_result) {
2085 wpa_printf(MSG_DEBUG,
2086 "DPP: No DPP Configuration waiting for connection status result - drop");
2087 return;
2088 }
2089
2090 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2091 ssid, &ssid_len, &channel_list);
2092 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2093 "result=%d ssid=%s channel_list=%s",
2094 status, wpa_ssid_txt(ssid, ssid_len),
2095 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002096 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2097 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002098 os_free(channel_list);
2099 offchannel_send_action_done(wpa_s);
2100 wpas_dpp_listen_stop(wpa_s);
2101 dpp_auth_deinit(auth);
2102 wpa_s->dpp_auth = NULL;
2103 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2104 wpa_s, NULL);
2105}
2106
2107
Hai Shalom81f62d82019-07-22 12:10:00 -07002108static int wpas_dpp_process_conf_obj(void *ctx,
2109 struct dpp_authentication *auth)
2110{
2111 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002112 unsigned int i;
2113 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002114
Hai Shalomc3565922019-10-28 11:58:20 -07002115 for (i = 0; i < auth->num_conf_obj; i++) {
2116 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2117 &auth->conf_obj[i]);
2118 if (res)
2119 break;
2120 }
2121 if (!res)
2122 wpas_dpp_post_process_config(wpa_s, auth);
2123
2124 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002125}
2126
Hai Shalomfdcde762020-04-02 11:19:20 -07002127
Hai Shaloma20dcd72022-02-04 13:43:00 -08002128static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2129{
2130 struct wpa_supplicant *wpa_s = ctx;
2131
2132 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2133
2134 if (auth->connect_on_tx_status) {
2135 auth->connect_on_tx_status = 0;
2136 wpa_printf(MSG_DEBUG,
2137 "DPP: Try to connect after completed configuration result");
2138 wpas_dpp_try_to_connect(wpa_s);
2139 if (auth->conn_status_requested) {
2140 wpa_printf(MSG_DEBUG,
2141 "DPP: Start 15 second timeout for reporting connection status result");
2142 eloop_cancel_timeout(
2143 wpas_dpp_conn_status_result_timeout,
2144 wpa_s, NULL);
2145 eloop_register_timeout(
2146 15, 0, wpas_dpp_conn_status_result_timeout,
2147 wpa_s, NULL);
2148 return true;
2149 }
2150 }
2151
2152 return false;
2153}
2154
2155
Hai Shalomfdcde762020-04-02 11:19:20 -07002156static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2157{
2158 struct wpa_supplicant *wpa_s = ctx;
2159
2160 if (bi == wpa_s->dpp_chirp_bi)
2161 wpas_dpp_chirp_stop(wpa_s);
2162}
2163
2164
2165static void
2166wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2167 const u8 *hdr, const u8 *buf, size_t len,
2168 unsigned int freq)
2169{
2170 const u8 *r_bootstrap;
2171 u16 r_bootstrap_len;
2172 struct dpp_bootstrap_info *peer_bi;
2173 struct dpp_authentication *auth;
2174
2175 if (!wpa_s->dpp)
2176 return;
2177
2178 if (wpa_s->dpp_auth) {
2179 wpa_printf(MSG_DEBUG,
2180 "DPP: Ignore Presence Announcement during ongoing Authentication");
2181 return;
2182 }
2183
2184 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2185 MAC2STR(src));
2186
2187 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2188 &r_bootstrap_len);
2189 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2190 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2191 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2192 return;
2193 }
2194 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2195 r_bootstrap, r_bootstrap_len);
2196 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002197 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2198 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002199 if (!peer_bi) {
2200 wpa_printf(MSG_DEBUG,
2201 "DPP: No matching bootstrapping information found");
2202 return;
2203 }
2204
2205 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2206 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2207 if (!auth)
2208 return;
2209 wpas_dpp_set_testing_options(wpa_s, auth);
2210 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2211 dpp_auth_deinit(auth);
2212 return;
2213 }
2214
2215 auth->neg_freq = freq;
2216
Hai Shalom60840252021-02-19 19:02:11 -08002217 /* The source address of the Presence Announcement frame overrides any
2218 * MAC address information from the bootstrapping information. */
2219 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002220
2221 wpa_s->dpp_auth = auth;
2222 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2223 dpp_auth_deinit(wpa_s->dpp_auth);
2224 wpa_s->dpp_auth = NULL;
2225 }
2226}
2227
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002228
2229static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2230 void *timeout_ctx)
2231{
2232 struct wpa_supplicant *wpa_s = eloop_ctx;
2233 struct dpp_authentication *auth = wpa_s->dpp_auth;
2234
2235 if (!auth)
2236 return;
2237
2238 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2239 offchannel_send_action_done(wpa_s);
2240 wpas_dpp_listen_stop(wpa_s);
2241 dpp_auth_deinit(auth);
2242 wpa_s->dpp_auth = NULL;
2243}
2244
2245
2246static void
2247wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2248 const u8 *hdr, const u8 *buf, size_t len,
2249 unsigned int freq)
2250{
Hai Shalom899fcc72020-10-19 14:38:18 -07002251 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2252 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002253 struct dpp_configurator *conf;
2254 struct dpp_authentication *auth;
2255 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002256 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002257
2258 if (!wpa_s->dpp)
2259 return;
2260
2261 if (wpa_s->dpp_auth) {
2262 wpa_printf(MSG_DEBUG,
2263 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2264 return;
2265 }
2266
2267 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2268 MAC2STR(src));
2269
2270 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2271 &csign_hash_len);
2272 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2273 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2274 "Missing or invalid required Configurator C-sign key Hash attribute");
2275 return;
2276 }
2277 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2278 csign_hash, csign_hash_len);
2279 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2280 if (!conf) {
2281 wpa_printf(MSG_DEBUG,
2282 "DPP: No matching Configurator information found");
2283 return;
2284 }
2285
Hai Shalom899fcc72020-10-19 14:38:18 -07002286 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2287 &fcgroup_len);
2288 if (!fcgroup || fcgroup_len != 2) {
2289 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2290 "Missing or invalid required Finite Cyclic Group attribute");
2291 return;
2292 }
2293 group = WPA_GET_LE16(fcgroup);
2294 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2295
2296 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2297 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2298
2299 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2300 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002301 if (!auth)
2302 return;
2303 wpas_dpp_set_testing_options(wpa_s, auth);
2304 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2305 dpp_auth_deinit(auth);
2306 return;
2307 }
2308
2309 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2310 wpa_s->dpp_auth = auth;
2311
2312 wpa_s->dpp_in_response_listen = 0;
2313 wpa_s->dpp_auth_ok_on_ack = 0;
2314 wait_time = wpa_s->max_remain_on_chan;
2315 max_wait_time = wpa_s->dpp_resp_wait_time ?
2316 wpa_s->dpp_resp_wait_time : 2000;
2317 if (wait_time > max_wait_time)
2318 wait_time = max_wait_time;
2319 wait_time += 10; /* give the driver some extra time to complete */
2320 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2321 wpas_dpp_reconfig_reply_wait_timeout,
2322 wpa_s, NULL);
2323 wait_time -= 10;
2324
2325 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2326
2327 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2328 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2329 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2330 wpabuf_head(auth->reconfig_req_msg),
2331 wpabuf_len(auth->reconfig_req_msg),
2332 wait_time, wpas_dpp_tx_status, 0) < 0) {
2333 dpp_auth_deinit(wpa_s->dpp_auth);
2334 wpa_s->dpp_auth = NULL;
2335 }
2336}
2337
2338
2339static void
2340wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2341 const u8 *hdr, const u8 *buf, size_t len,
2342 unsigned int freq)
2343{
2344 struct wpa_ssid *ssid;
2345 struct dpp_authentication *auth;
2346
2347 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2348 MACSTR, MAC2STR(src));
2349
Hai Shalom899fcc72020-10-19 14:38:18 -07002350 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002351 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002352 if (wpa_s->dpp_auth) {
2353 wpa_printf(MSG_DEBUG,
2354 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2355 return;
2356 }
2357 if (!wpa_s->dpp_reconfig_ssid) {
2358 wpa_printf(MSG_DEBUG,
2359 "DPP: Not ready for reconfiguration - not requested");
2360 return;
2361 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002362 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2363 if (ssid == wpa_s->dpp_reconfig_ssid &&
2364 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2365 break;
2366 }
2367 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002368 !ssid->dpp_csign) {
2369 wpa_printf(MSG_DEBUG,
2370 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002371 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002372 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002373
2374 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2375 ssid->dpp_netaccesskey,
2376 ssid->dpp_netaccesskey_len,
2377 ssid->dpp_csign, ssid->dpp_csign_len,
2378 freq, hdr, buf, len);
2379 if (!auth)
2380 return;
2381 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2382 wpa_s->dpp_auth = auth;
2383
2384 wpas_dpp_chirp_stop(wpa_s);
2385
2386 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2387 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2388 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2389 wpabuf_head(auth->reconfig_resp_msg),
2390 wpabuf_len(auth->reconfig_resp_msg),
2391 500, wpas_dpp_tx_status, 0) < 0) {
2392 dpp_auth_deinit(wpa_s->dpp_auth);
2393 wpa_s->dpp_auth = NULL;
2394 }
2395}
2396
2397
2398static void
2399wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2400 const u8 *hdr, const u8 *buf, size_t len,
2401 unsigned int freq)
2402{
2403 struct dpp_authentication *auth = wpa_s->dpp_auth;
2404 struct wpabuf *conf;
2405
2406 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2407 MACSTR, MAC2STR(src));
2408
2409 if (!auth || !auth->reconfig || !auth->configurator) {
2410 wpa_printf(MSG_DEBUG,
2411 "DPP: No DPP Reconfig Authentication in progress - drop");
2412 return;
2413 }
2414
2415 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2416 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2417 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2418 return;
2419 }
2420
2421 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2422 if (!conf)
2423 return;
2424
2425 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2426
2427 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2428 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2429 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2430 wpabuf_head(conf), wpabuf_len(conf),
2431 500, wpas_dpp_tx_status, 0) < 0) {
2432 wpabuf_free(conf);
2433 dpp_auth_deinit(wpa_s->dpp_auth);
2434 wpa_s->dpp_auth = NULL;
2435 return;
2436 }
2437 wpabuf_free(conf);
2438
2439 wpas_dpp_start_gas_server(wpa_s);
2440}
2441
2442
2443static void
2444wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2445 const u8 *hdr, const u8 *buf, size_t len,
2446 unsigned int freq)
2447{
2448 struct dpp_authentication *auth = wpa_s->dpp_auth;
2449
2450 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2451 MACSTR, MAC2STR(src));
2452
2453 if (!auth || !auth->reconfig || auth->configurator) {
2454 wpa_printf(MSG_DEBUG,
2455 "DPP: No DPP Reconfig Authentication in progress - drop");
2456 return;
2457 }
2458
2459 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2460 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2461 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2462 return;
2463 }
2464
2465 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2466 return;
2467
2468 wpas_dpp_start_gas_client(wpa_s);
2469}
2470
Hai Shalom021b0b52019-04-10 11:17:58 -07002471#endif /* CONFIG_DPP2 */
2472
2473
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002474static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2475 const u8 *src,
2476 const u8 *buf, size_t len)
2477{
2478 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002479 const u8 *connector, *trans_id, *status;
2480 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002481#ifdef CONFIG_DPP2
2482 const u8 *version;
2483 u16 version_len;
2484#endif /* CONFIG_DPP2 */
2485 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002486 struct dpp_introduction intro;
2487 struct rsn_pmksa_cache_entry *entry;
2488 struct os_time now;
2489 struct os_reltime rnow;
2490 os_time_t expiry;
2491 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002492 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002493
2494 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2495 MAC2STR(src));
2496 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2497 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2498 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2499 MACSTR " - drop", MAC2STR(src));
2500 return;
2501 }
2502 offchannel_send_action_done(wpa_s);
2503
2504 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2505 if (ssid == wpa_s->dpp_intro_network)
2506 break;
2507 }
2508 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2509 !ssid->dpp_csign) {
2510 wpa_printf(MSG_DEBUG,
2511 "DPP: Profile not found for network introduction");
2512 return;
2513 }
2514
2515 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2516 &trans_id_len);
2517 if (!trans_id || trans_id_len != 1) {
2518 wpa_printf(MSG_DEBUG,
2519 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002520 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2521 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002522 goto fail;
2523 }
2524 if (trans_id[0] != TRANSACTION_ID) {
2525 wpa_printf(MSG_DEBUG,
2526 "DPP: Ignore frame with unexpected Transaction ID %u",
2527 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002528 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2529 " fail=transaction_id_mismatch", MAC2STR(src));
2530 goto fail;
2531 }
2532
2533 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2534 if (!status || status_len != 1) {
2535 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2536 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2537 " fail=missing_status", MAC2STR(src));
2538 goto fail;
2539 }
2540 if (status[0] != DPP_STATUS_OK) {
2541 wpa_printf(MSG_DEBUG,
2542 "DPP: Peer rejected network introduction: Status %u",
2543 status[0]);
2544 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2545 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002546#ifdef CONFIG_DPP2
2547 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2548#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002549 goto fail;
2550 }
2551
2552 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2553 if (!connector) {
2554 wpa_printf(MSG_DEBUG,
2555 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002556 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2557 " fail=missing_connector", MAC2STR(src));
2558 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002559 }
2560
Roshan Pius3a1667e2018-07-03 15:17:14 -07002561 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2562 ssid->dpp_netaccesskey,
2563 ssid->dpp_netaccesskey_len,
2564 ssid->dpp_csign,
2565 ssid->dpp_csign_len,
2566 connector, connector_len, &expiry);
2567 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002568 wpa_printf(MSG_INFO,
2569 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002570 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2571 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002572#ifdef CONFIG_DPP2
2573 wpas_dpp_send_conn_status_result(wpa_s, res);
2574#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002575 goto fail;
2576 }
2577
2578 entry = os_zalloc(sizeof(*entry));
2579 if (!entry)
2580 goto fail;
2581 os_memcpy(entry->aa, src, ETH_ALEN);
2582 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2583 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2584 entry->pmk_len = intro.pmk_len;
2585 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002586#ifdef CONFIG_DPP2
2587 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2588 &version_len);
2589 if (version && version_len >= 1)
2590 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002591#ifdef CONFIG_DPP3
2592 if (intro.peer_version && intro.peer_version >= 2 &&
2593 peer_version != intro.peer_version) {
2594 wpa_printf(MSG_INFO,
2595 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2596 intro.peer_version, peer_version);
2597 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2598 goto fail;
2599 }
2600#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002601 entry->dpp_pfs = peer_version >= 2;
2602#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002603 if (expiry) {
2604 os_get_time(&now);
2605 seconds = expiry - now.sec;
2606 } else {
2607 seconds = 86400 * 7;
2608 }
2609 os_get_reltime(&rnow);
2610 entry->expiration = rnow.sec + seconds;
2611 entry->reauth_time = rnow.sec + seconds;
2612 entry->network_ctx = ssid;
2613 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2614
Roshan Pius3a1667e2018-07-03 15:17:14 -07002615 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002616 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002617
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002618 wpa_printf(MSG_DEBUG,
2619 "DPP: Try connection again after successful network introduction");
2620 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2621 wpa_supplicant_cancel_sched_scan(wpa_s);
2622 wpa_supplicant_req_scan(wpa_s, 0, 0);
2623 }
2624fail:
2625 os_memset(&intro, 0, sizeof(intro));
2626}
2627
2628
Roshan Pius3a1667e2018-07-03 15:17:14 -07002629static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2630{
2631 int i, j;
2632
2633 if (!wpa_s->hw.modes)
2634 return -1;
2635
2636 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2637 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2638
2639 for (j = 0; j < mode->num_channels; j++) {
2640 struct hostapd_channel_data *chan = &mode->channels[j];
2641
2642 if (chan->freq != (int) freq)
2643 continue;
2644
2645 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2646 HOSTAPD_CHAN_NO_IR |
2647 HOSTAPD_CHAN_RADAR))
2648 continue;
2649
2650 return 1;
2651 }
2652 }
2653
2654 wpa_printf(MSG_DEBUG,
2655 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2656 freq);
2657
2658 return 0;
2659}
2660
2661
2662static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2663 struct dpp_pkex *pkex)
2664{
2665 if (pkex->freq == 2437)
2666 pkex->freq = 5745;
2667 else if (pkex->freq == 5745)
2668 pkex->freq = 5220;
2669 else if (pkex->freq == 5220)
2670 pkex->freq = 60480;
2671 else
2672 return -1; /* no more channels to try */
2673
2674 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2675 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2676 pkex->freq);
2677 return 0;
2678 }
2679
2680 /* Could not use this channel - try the next one */
2681 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2682}
2683
2684
Hai Shaloma20dcd72022-02-04 13:43:00 -08002685#ifdef CONFIG_DPP2
2686static int wpas_dpp_pkex_done(void *ctx, void *conn,
2687 struct dpp_bootstrap_info *peer_bi)
2688{
2689 struct wpa_supplicant *wpa_s = ctx;
2690 const char *cmd = wpa_s->dpp_pkex_auth_cmd;
2691 const char *pos;
2692 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2693 struct dpp_bootstrap_info *own_bi = NULL;
2694 struct dpp_authentication *auth;
2695
2696 if (!cmd)
2697 cmd = "";
2698 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
2699 cmd);
2700
2701 pos = os_strstr(cmd, " own=");
2702 if (pos) {
2703 pos += 5;
2704 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
2705 if (!own_bi) {
2706 wpa_printf(MSG_INFO,
2707 "DPP: Could not find bootstrapping info for the identified local entry");
2708 return -1;
2709 }
2710
2711 if (peer_bi->curve != own_bi->curve) {
2712 wpa_printf(MSG_INFO,
2713 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
2714 peer_bi->curve->name, own_bi->curve->name);
2715 return -1;
2716 }
2717 }
2718
2719 pos = os_strstr(cmd, " role=");
2720 if (pos) {
2721 pos += 6;
2722 if (os_strncmp(pos, "configurator", 12) == 0)
2723 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2724 else if (os_strncmp(pos, "enrollee", 8) == 0)
2725 allowed_roles = DPP_CAPAB_ENROLLEE;
2726 else if (os_strncmp(pos, "either", 6) == 0)
2727 allowed_roles = DPP_CAPAB_CONFIGURATOR |
2728 DPP_CAPAB_ENROLLEE;
2729 else
2730 return -1;
2731 }
2732
2733 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
2734 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
2735 if (!auth)
2736 return -1;
2737
2738 wpas_dpp_set_testing_options(wpa_s, auth);
2739 if (dpp_set_configurator(auth, cmd) < 0) {
2740 dpp_auth_deinit(auth);
2741 return -1;
2742 }
2743
2744 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
2745 DPP_NETROLE_STA, wpas_dpp_process_conf_obj,
2746 wpas_dpp_tcp_msg_sent);
2747}
2748#endif /* CONFIG_DPP2 */
2749
2750
2751enum wpas_dpp_pkex_ver {
2752 PKEX_VER_AUTO,
2753 PKEX_VER_ONLY_1,
2754 PKEX_VER_ONLY_2,
2755};
2756
2757static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
2758 enum wpas_dpp_pkex_ver ver,
2759 const struct hostapd_ip_addr *ipaddr,
2760 int tcp_port)
2761{
2762 struct dpp_pkex *pkex;
2763 struct wpabuf *msg;
2764 unsigned int wait_time;
2765 bool v2 = ver != PKEX_VER_ONLY_1;
2766
2767 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
2768 dpp_pkex_free(wpa_s->dpp_pkex);
2769 wpa_s->dpp_pkex = NULL;
2770 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
2771 wpa_s->dpp_pkex_identifier,
2772 wpa_s->dpp_pkex_code, v2);
2773 if (!pkex)
2774 return -1;
2775 pkex->forced_ver = ver != PKEX_VER_AUTO;
2776
2777 if (ipaddr) {
2778#ifdef CONFIG_DPP2
2779 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
2780 wpa_s, wpa_s, wpas_dpp_pkex_done);
2781#else /* CONFIG_DPP2 */
2782 return -1;
2783#endif /* CONFIG_DPP2 */
2784 }
2785
2786 wpa_s->dpp_pkex = pkex;
2787 msg = pkex->exchange_req;
2788 wait_time = wpa_s->max_remain_on_chan;
2789 if (wait_time > 2000)
2790 wait_time = 2000;
2791 pkex->freq = 2437;
2792 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2793 " freq=%u type=%d",
2794 MAC2STR(broadcast), pkex->freq,
2795 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2796 DPP_PA_PKEX_V1_EXCHANGE_REQ);
2797 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2798 wpa_s->own_addr, broadcast,
2799 wpabuf_head(msg), wpabuf_len(msg),
2800 wait_time, wpas_dpp_tx_pkex_status, 0);
2801 if (wait_time == 0)
2802 wait_time = 2000;
2803 pkex->exch_req_wait_time = wait_time;
2804 pkex->exch_req_tries = 1;
2805
2806 return 0;
2807}
2808
2809
Roshan Pius3a1667e2018-07-03 15:17:14 -07002810static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
2811{
2812 struct wpa_supplicant *wpa_s = eloop_ctx;
2813 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2814
2815 if (!pkex || !pkex->exchange_req)
2816 return;
2817 if (pkex->exch_req_tries >= 5) {
2818 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002819#ifdef CONFIG_DPP3
2820 if (pkex->v2 && !pkex->forced_ver) {
2821 wpa_printf(MSG_DEBUG,
2822 "DPP: Fall back to PKEXv1");
2823 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
2824 NULL, 0);
2825 return;
2826 }
2827#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002828 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2829 "No response from PKEX peer");
2830 dpp_pkex_free(pkex);
2831 wpa_s->dpp_pkex = NULL;
2832 return;
2833 }
2834 pkex->exch_req_tries = 0;
2835 }
2836
2837 pkex->exch_req_tries++;
2838 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
2839 pkex->exch_req_tries);
2840 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08002841 MAC2STR(broadcast), pkex->freq,
2842 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2843 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002844 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2845 wpa_s->own_addr, broadcast,
2846 wpabuf_head(pkex->exchange_req),
2847 wpabuf_len(pkex->exchange_req),
2848 pkex->exch_req_wait_time,
2849 wpas_dpp_tx_pkex_status, 0);
2850}
2851
2852
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002853static void
2854wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
2855 unsigned int freq, const u8 *dst,
2856 const u8 *src, const u8 *bssid,
2857 const u8 *data, size_t data_len,
2858 enum offchannel_send_action_result result)
2859{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002860 const char *res_txt;
2861 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2862
2863 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2864 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2865 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002866 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2867 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002868 freq, MAC2STR(dst), res_txt);
2869 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2870 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
2871
2872 if (!pkex) {
2873 wpa_printf(MSG_DEBUG,
2874 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
2875 return;
2876 }
2877
2878 if (pkex->failed) {
2879 wpa_printf(MSG_DEBUG,
2880 "DPP: Terminate PKEX exchange due to an earlier error");
2881 if (pkex->t > pkex->own_bi->pkex_t)
2882 pkex->own_bi->pkex_t = pkex->t;
2883 dpp_pkex_free(pkex);
2884 wpa_s->dpp_pkex = NULL;
2885 return;
2886 }
2887
2888 if (pkex->exch_req_wait_time && pkex->exchange_req) {
2889 /* Wait for PKEX Exchange Response frame and retry request if
2890 * no response is seen. */
2891 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
2892 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
2893 (pkex->exch_req_wait_time % 1000) * 1000,
2894 wpas_dpp_pkex_retry_timeout, wpa_s,
2895 NULL);
2896 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002897}
2898
2899
2900static void
2901wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002902 const u8 *buf, size_t len, unsigned int freq,
2903 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002904{
2905 struct wpabuf *msg;
2906 unsigned int wait_time;
2907
2908 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
2909 MAC2STR(src));
2910
2911 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2912 * values here */
2913
2914 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
2915 wpa_printf(MSG_DEBUG,
2916 "DPP: No PKEX code configured - ignore request");
2917 return;
2918 }
2919
2920 if (wpa_s->dpp_pkex) {
2921 /* TODO: Support parallel operations */
2922 wpa_printf(MSG_DEBUG,
2923 "DPP: Already in PKEX session - ignore new request");
2924 return;
2925 }
2926
Roshan Pius3a1667e2018-07-03 15:17:14 -07002927 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002928 wpa_s->own_addr, src,
2929 wpa_s->dpp_pkex_identifier,
2930 wpa_s->dpp_pkex_code,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002931 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002932 if (!wpa_s->dpp_pkex) {
2933 wpa_printf(MSG_DEBUG,
2934 "DPP: Failed to process the request - ignore it");
2935 return;
2936 }
2937
2938 msg = wpa_s->dpp_pkex->exchange_resp;
2939 wait_time = wpa_s->max_remain_on_chan;
2940 if (wait_time > 2000)
2941 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002942 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2943 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002944 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2945 broadcast,
2946 wpabuf_head(msg), wpabuf_len(msg),
2947 wait_time, wpas_dpp_tx_pkex_status, 0);
2948}
2949
2950
2951static void
2952wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2953 const u8 *buf, size_t len, unsigned int freq)
2954{
2955 struct wpabuf *msg;
2956 unsigned int wait_time;
2957
2958 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2959 MAC2STR(src));
2960
2961 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2962 * values here */
2963
2964 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
2965 wpa_s->dpp_pkex->exchange_done) {
2966 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2967 return;
2968 }
2969
Roshan Pius3a1667e2018-07-03 15:17:14 -07002970 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
2971 wpa_s->dpp_pkex->exch_req_wait_time = 0;
2972
2973 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002974 if (!msg) {
2975 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2976 return;
2977 }
2978
2979 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
2980 MAC2STR(src));
2981
2982 wait_time = wpa_s->max_remain_on_chan;
2983 if (wait_time > 2000)
2984 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002985 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2986 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002987 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2988 broadcast,
2989 wpabuf_head(msg), wpabuf_len(msg),
2990 wait_time, wpas_dpp_tx_pkex_status, 0);
2991 wpabuf_free(msg);
2992}
2993
2994
Roshan Pius3a1667e2018-07-03 15:17:14 -07002995static struct dpp_bootstrap_info *
2996wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
2997 unsigned int freq)
2998{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002999 struct dpp_bootstrap_info *bi;
3000
Hai Shalom021b0b52019-04-10 11:17:58 -07003001 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003002 if (!bi)
3003 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003004 wpa_s->dpp_pkex = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003005 return bi;
3006}
3007
3008
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003009static void
3010wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3011 const u8 *hdr, const u8 *buf, size_t len,
3012 unsigned int freq)
3013{
3014 struct wpabuf *msg;
3015 unsigned int wait_time;
3016 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003017
3018 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3019 MAC2STR(src));
3020
3021 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3022 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3023 return;
3024 }
3025
3026 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3027 if (!msg) {
3028 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003029 if (pkex->failed) {
3030 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3031 if (pkex->t > pkex->own_bi->pkex_t)
3032 pkex->own_bi->pkex_t = pkex->t;
3033 dpp_pkex_free(wpa_s->dpp_pkex);
3034 wpa_s->dpp_pkex = NULL;
3035 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003036 return;
3037 }
3038
3039 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3040 MACSTR, MAC2STR(src));
3041
3042 wait_time = wpa_s->max_remain_on_chan;
3043 if (wait_time > 2000)
3044 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003045 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3046 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003047 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3048 broadcast,
3049 wpabuf_head(msg), wpabuf_len(msg),
3050 wait_time, wpas_dpp_tx_pkex_status, 0);
3051 wpabuf_free(msg);
3052
Roshan Pius3a1667e2018-07-03 15:17:14 -07003053 wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003054}
3055
3056
3057static void
3058wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3059 const u8 *hdr, const u8 *buf, size_t len,
3060 unsigned int freq)
3061{
3062 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003063 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003064 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3065 char cmd[500];
3066
3067 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3068 MAC2STR(src));
3069
3070 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3071 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3072 return;
3073 }
3074
3075 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3076 if (res < 0) {
3077 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3078 return;
3079 }
3080
Roshan Pius3a1667e2018-07-03 15:17:14 -07003081 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003082 if (!bi)
3083 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003084
3085 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3086 bi->id,
3087 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3088 wpa_printf(MSG_DEBUG,
3089 "DPP: Start authentication after PKEX with parameters: %s",
3090 cmd);
3091 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3092 wpa_printf(MSG_DEBUG,
3093 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003094 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003095 return;
3096 }
3097}
3098
3099
3100void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
3101 const u8 *buf, size_t len, unsigned int freq)
3102{
3103 u8 crypto_suite;
3104 enum dpp_public_action_frame_type type;
3105 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003106 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003107
3108 if (len < DPP_HDR_LEN)
3109 return;
3110 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
3111 return;
3112 hdr = buf;
3113 buf += 4;
3114 len -= 4;
3115 crypto_suite = *buf++;
3116 type = *buf++;
3117 len -= 2;
3118
3119 wpa_printf(MSG_DEBUG,
3120 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
3121 MACSTR " freq=%u",
3122 crypto_suite, type, MAC2STR(src), freq);
3123 if (crypto_suite != 1) {
3124 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
3125 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003126 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3127 " freq=%u type=%d ignore=unsupported-crypto-suite",
3128 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003129 return;
3130 }
3131 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003132 if (dpp_check_attrs(buf, len) < 0) {
3133 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3134 " freq=%u type=%d ignore=invalid-attributes",
3135 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003136 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003137 }
3138 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
3139 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003140
3141 switch (type) {
3142 case DPP_PA_AUTHENTICATION_REQ:
3143 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
3144 break;
3145 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07003146 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003147 break;
3148 case DPP_PA_AUTHENTICATION_CONF:
3149 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
3150 break;
3151 case DPP_PA_PEER_DISCOVERY_RESP:
3152 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
3153 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003154#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003155 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003156 /* This is for PKEXv2, but for now, process only with
3157 * CONFIG_DPP3 to avoid issues with a capability that has not
3158 * been tested with other implementations. */
3159 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
3160 break;
3161#endif /* CONFIG_DPP3 */
3162 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
3163 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
3164 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003165 break;
3166 case DPP_PA_PKEX_EXCHANGE_RESP:
3167 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
3168 break;
3169 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
3170 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
3171 freq);
3172 break;
3173 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
3174 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
3175 freq);
3176 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003177#ifdef CONFIG_DPP2
3178 case DPP_PA_CONFIGURATION_RESULT:
3179 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
3180 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003181 case DPP_PA_CONNECTION_STATUS_RESULT:
3182 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
3183 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07003184 case DPP_PA_PRESENCE_ANNOUNCEMENT:
3185 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
3186 freq);
3187 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003188 case DPP_PA_RECONFIG_ANNOUNCEMENT:
3189 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
3190 freq);
3191 break;
3192 case DPP_PA_RECONFIG_AUTH_REQ:
3193 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
3194 break;
3195 case DPP_PA_RECONFIG_AUTH_RESP:
3196 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
3197 break;
3198 case DPP_PA_RECONFIG_AUTH_CONF:
3199 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
3200 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003201#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003202 default:
3203 wpa_printf(MSG_DEBUG,
3204 "DPP: Ignored unsupported frame subtype %d", type);
3205 break;
3206 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003207
3208 if (wpa_s->dpp_pkex)
3209 pkex_t = wpa_s->dpp_pkex->t;
3210 else if (wpa_s->dpp_pkex_bi)
3211 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
3212 else
3213 pkex_t = 0;
3214 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
3215 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
3216 wpas_dpp_pkex_remove(wpa_s, "*");
3217 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003218}
3219
3220
Hai Shaloma20dcd72022-02-04 13:43:00 -08003221static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
3222 void *timeout_ctx)
3223{
3224 struct wpa_supplicant *wpa_s = eloop_ctx;
3225 struct dpp_authentication *auth = wpa_s->dpp_auth;
3226
3227 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
3228 return;
3229
3230 wpa_printf(MSG_DEBUG,
3231 "DPP: No configuration available from upper layers - send initial response with comeback delay");
3232 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
3233 500);
3234}
3235
3236
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003237static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07003238wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003239 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003240{
3241 struct wpa_supplicant *wpa_s = ctx;
3242 struct dpp_authentication *auth = wpa_s->dpp_auth;
3243 struct wpabuf *resp;
3244
3245 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
3246 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003247 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003248 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
3249 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
3250 return NULL;
3251 }
Hai Shalomc3565922019-10-28 11:58:20 -07003252
3253 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
3254 wpa_printf(MSG_DEBUG,
3255 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
3256 /* wpas_dpp_auth_success() would normally have been called from
3257 * TX status handler, but since there was no such handler call
3258 * yet, simply send out the event message and proceed with
3259 * exchange. */
3260 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
3261 wpa_s->dpp_auth_ok_on_ack = 0;
3262 }
3263
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003264 wpa_hexdump(MSG_DEBUG,
3265 "DPP: Received Configuration Request (GAS Query Request)",
3266 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003267 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
3268 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003269 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003270
Hai Shaloma20dcd72022-02-04 13:43:00 -08003271 auth->gas_server_ctx = resp_ctx;
3272
Hai Shalom899fcc72020-10-19 14:38:18 -07003273#ifdef CONFIG_DPP2
3274 if (!resp && auth->waiting_cert) {
3275 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003276 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003277 *comeback_delay = 500;
3278 return NULL;
3279 }
3280#endif /* CONFIG_DPP2 */
3281
Hai Shaloma20dcd72022-02-04 13:43:00 -08003282 if (!resp && auth->waiting_config &&
3283 (auth->peer_bi || auth->tmp_peer_bi)) {
3284 char *buf = NULL, *name = "";
3285 char band[200], *pos, *end;
3286 int i, res, *opclass = auth->e_band_support;
3287 char *mud_url = "N/A";
3288
3289 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
3290 auth->config_resp_ctx = resp_ctx;
3291 *comeback_delay = -1;
3292 if (auth->e_name) {
3293 size_t len = os_strlen(auth->e_name);
3294
3295 buf = os_malloc(len * 4 + 1);
3296 if (buf) {
3297 printf_encode(buf, len * 4 + 1,
3298 (const u8 *) auth->e_name, len);
3299 name = buf;
3300 }
3301 }
3302 band[0] = '\0';
3303 pos = band;
3304 end = band + sizeof(band);
3305 for (i = 0; opclass && opclass[i]; i++) {
3306 res = os_snprintf(pos, end - pos, "%s%d",
3307 pos == band ? "" : ",", opclass[i]);
3308 if (os_snprintf_error(end - pos, res)) {
3309 *pos = '\0';
3310 break;
3311 }
3312 pos += res;
3313 }
3314 if (auth->e_mud_url) {
3315 size_t len = os_strlen(auth->e_mud_url);
3316
3317 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
3318 mud_url = auth->e_mud_url;
3319 }
3320 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
3321 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
3322 auth->peer_bi ? auth->peer_bi->id :
3323 auth->tmp_peer_bi->id, MAC2STR(sa),
3324 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
3325 os_free(buf);
3326
3327 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
3328 NULL);
3329 eloop_register_timeout(0, 50000,
3330 wpas_dpp_gas_initial_resp_timeout, wpa_s,
3331 NULL);
3332 return NULL;
3333 }
3334
Hai Shalom59532852018-12-07 10:32:58 -08003335 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003336 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08003337 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003338 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003339 auth->conf_resp = resp;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003340 return resp;
3341}
3342
3343
3344static void
3345wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
3346{
3347 struct wpa_supplicant *wpa_s = ctx;
3348 struct dpp_authentication *auth = wpa_s->dpp_auth;
3349
3350 if (!auth) {
3351 wpabuf_free(resp);
3352 return;
3353 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003354 if (auth->conf_resp != resp) {
3355 wpa_printf(MSG_DEBUG,
3356 "DPP: Ignore GAS status report (ok=%d) for unknown response",
3357 ok);
3358 wpabuf_free(resp);
3359 return;
3360 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003361
Hai Shalom899fcc72020-10-19 14:38:18 -07003362#ifdef CONFIG_DPP2
3363 if (auth->waiting_csr && ok) {
3364 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
3365 wpabuf_free(resp);
3366 return;
3367 }
3368#endif /* CONFIG_DPP2 */
3369
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003370 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
3371 ok);
3372 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003373 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003374 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003375#ifdef CONFIG_DPP2
3376 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08003377 auth->conf_resp_status == DPP_STATUS_OK &&
3378 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003379 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08003380 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003381 auth->waiting_conf_result = 1;
3382 auth->conf_resp = NULL;
3383 wpabuf_free(resp);
3384 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
3385 wpa_s, NULL);
3386 eloop_register_timeout(2, 0,
3387 wpas_dpp_config_result_wait_timeout,
3388 wpa_s, NULL);
3389 return;
3390 }
3391#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003392 offchannel_send_action_done(wpa_s);
3393 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003394 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003395 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08003396 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003397 }
3398 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003399 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08003400 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003401 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003402 dpp_auth_deinit(wpa_s->dpp_auth);
3403 wpa_s->dpp_auth = NULL;
3404 wpabuf_free(resp);
3405}
3406
3407
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003408int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
3409{
3410 struct dpp_authentication *auth;
3411 int ret = -1;
3412 char *curve = NULL;
3413
Hai Shalomfdcde762020-04-02 11:19:20 -07003414 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003415 if (!auth)
3416 return -1;
3417
3418 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08003419 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07003420 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07003421 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07003422 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
3423 &auth->conf_obj[0]);
3424 if (!ret)
3425 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003426
3427 dpp_auth_deinit(auth);
3428 os_free(curve);
3429
3430 return ret;
3431}
3432
3433
3434static void
3435wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
3436 unsigned int freq, const u8 *dst,
3437 const u8 *src, const u8 *bssid,
3438 const u8 *data, size_t data_len,
3439 enum offchannel_send_action_result result)
3440{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003441 const char *res_txt;
3442
3443 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3444 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3445 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003446 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3447 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003448 freq, MAC2STR(dst), res_txt);
3449 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3450 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003451 /* TODO: Time out wait for response more quickly in error cases? */
3452}
3453
3454
3455int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3456 struct wpa_bss *bss)
3457{
3458 struct os_time now;
3459 struct wpabuf *msg;
3460 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07003461 const u8 *rsn;
3462 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003463 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003464
3465 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
3466 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07003467 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3468 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
3469 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
3470 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003471 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
3472 return 0; /* PMKSA exists for DPP AKM - continue */
3473
3474 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3475 !ssid->dpp_csign) {
3476 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
3477 "missing %s",
3478 !ssid->dpp_connector ? "Connector" :
3479 (!ssid->dpp_netaccesskey ? "netAccessKey" :
3480 "C-sign-key"));
3481 return -1;
3482 }
3483
3484 os_get_time(&now);
3485
3486 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07003487 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003488 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
3489 "netAccessKey expired");
3490 return -1;
3491 }
3492
3493 wpa_printf(MSG_DEBUG,
3494 "DPP: Starting network introduction protocol to derive PMKSA for "
3495 MACSTR, MAC2STR(bss->bssid));
3496
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003497 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3498#ifdef CONFIG_DPP2
3499 len += 5;
3500#endif /* CONFIG_DPP2 */
3501 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003502 if (!msg)
3503 return -1;
3504
Roshan Pius3a1667e2018-07-03 15:17:14 -07003505#ifdef CONFIG_TESTING_OPTIONS
3506 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
3507 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
3508 goto skip_trans_id;
3509 }
3510 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
3511 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
3512 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3513 wpabuf_put_le16(msg, 0);
3514 goto skip_trans_id;
3515 }
3516#endif /* CONFIG_TESTING_OPTIONS */
3517
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003518 /* Transaction ID */
3519 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3520 wpabuf_put_le16(msg, 1);
3521 wpabuf_put_u8(msg, TRANSACTION_ID);
3522
Roshan Pius3a1667e2018-07-03 15:17:14 -07003523#ifdef CONFIG_TESTING_OPTIONS
3524skip_trans_id:
3525 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
3526 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
3527 goto skip_connector;
3528 }
3529 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
3530 char *connector;
3531
3532 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
3533 connector = dpp_corrupt_connector_signature(
3534 ssid->dpp_connector);
3535 if (!connector) {
3536 wpabuf_free(msg);
3537 return -1;
3538 }
3539 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
3540 wpabuf_put_le16(msg, os_strlen(connector));
3541 wpabuf_put_str(msg, connector);
3542 os_free(connector);
3543 goto skip_connector;
3544 }
3545#endif /* CONFIG_TESTING_OPTIONS */
3546
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003547 /* DPP Connector */
3548 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
3549 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
3550 wpabuf_put_str(msg, ssid->dpp_connector);
3551
Roshan Pius3a1667e2018-07-03 15:17:14 -07003552#ifdef CONFIG_TESTING_OPTIONS
3553skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003554 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
3555 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
3556 goto skip_proto_ver;
3557 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003558#endif /* CONFIG_TESTING_OPTIONS */
3559
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003560#ifdef CONFIG_DPP2
3561 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003562 u8 ver = DPP_VERSION;
3563#ifdef CONFIG_DPP3
3564 int conn_ver;
3565
3566 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3567 if (conn_ver > 0 && ver != conn_ver) {
3568 wpa_printf(MSG_DEBUG,
3569 "DPP: Use Connector version %d instead of current protocol version %d",
3570 conn_ver, ver);
3571 ver = conn_ver;
3572 }
3573#endif /* CONFIG_DPP3 */
3574
3575#ifdef CONFIG_TESTING_OPTIONS
3576 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
3577 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
3578 ver = 1;
3579 }
3580#endif /* CONFIG_TESTING_OPTIONS */
3581
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003582 /* Protocol Version */
3583 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
3584 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003585 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003586 }
3587#endif /* CONFIG_DPP2 */
3588
Hai Shaloma20dcd72022-02-04 13:43:00 -08003589#ifdef CONFIG_TESTING_OPTIONS
3590skip_proto_ver:
3591#endif /* CONFIG_TESTING_OPTIONS */
3592
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003593 /* TODO: Timeout on AP response */
3594 wait_time = wpa_s->max_remain_on_chan;
3595 if (wait_time > 2000)
3596 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003597 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3598 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003599 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
3600 broadcast,
3601 wpabuf_head(msg), wpabuf_len(msg),
3602 wait_time, wpas_dpp_tx_introduction_status, 0);
3603 wpabuf_free(msg);
3604
3605 /* Request this connection attempt to terminate - new one will be
3606 * started when network introduction protocol completes */
3607 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
3608 wpa_s->dpp_intro_network = ssid;
3609 return 1;
3610}
3611
3612
3613int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
3614{
3615 struct dpp_bootstrap_info *own_bi;
3616 const char *pos, *end;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003617 int tcp_port = DPP_TCP_PORT;
3618 struct hostapd_ip_addr *ipaddr = NULL;
3619#ifdef CONFIG_DPP2
3620 struct hostapd_ip_addr ipaddr_buf;
3621 char *addr;
3622
3623 pos = os_strstr(cmd, " tcp_port=");
3624 if (pos) {
3625 pos += 10;
3626 tcp_port = atoi(pos);
3627 }
3628
3629 addr = get_param(cmd, " tcp_addr=");
3630 if (addr) {
3631 int res;
3632
3633 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
3634 os_free(addr);
3635 if (res)
3636 return -1;
3637 ipaddr = &ipaddr_buf;
3638 }
3639#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003640
3641 pos = os_strstr(cmd, " own=");
3642 if (!pos)
3643 return -1;
3644 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07003645 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003646 if (!own_bi) {
3647 wpa_printf(MSG_DEBUG,
3648 "DPP: Identified bootstrap info not found");
3649 return -1;
3650 }
3651 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
3652 wpa_printf(MSG_DEBUG,
3653 "DPP: Identified bootstrap info not for PKEX");
3654 return -1;
3655 }
3656 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003657 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003658
3659 os_free(wpa_s->dpp_pkex_identifier);
3660 wpa_s->dpp_pkex_identifier = NULL;
3661 pos = os_strstr(cmd, " identifier=");
3662 if (pos) {
3663 pos += 12;
3664 end = os_strchr(pos, ' ');
3665 if (!end)
3666 return -1;
3667 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
3668 if (!wpa_s->dpp_pkex_identifier)
3669 return -1;
3670 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
3671 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
3672 }
3673
3674 pos = os_strstr(cmd, " code=");
3675 if (!pos)
3676 return -1;
3677 os_free(wpa_s->dpp_pkex_code);
3678 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
3679 if (!wpa_s->dpp_pkex_code)
3680 return -1;
3681
3682 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003683#ifdef CONFIG_DPP3
3684 enum wpas_dpp_pkex_ver ver = PKEX_VER_AUTO;
3685#else /* CONFIG_DPP3 */
3686 enum wpas_dpp_pkex_ver ver = PKEX_VER_ONLY_1;
3687#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003688
Hai Shaloma20dcd72022-02-04 13:43:00 -08003689 pos = os_strstr(cmd, " ver=");
3690 if (pos) {
3691 int v;
3692
3693 pos += 5;
3694 v = atoi(pos);
3695 if (v == 1)
3696 ver = PKEX_VER_ONLY_1;
3697 else if (v == 2)
3698 ver = PKEX_VER_ONLY_2;
3699 else
3700 return -1;
3701 }
3702
3703 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003704 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003705 } else {
3706#ifdef CONFIG_DPP2
3707 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
3708 wpa_s->dpp_pkex_code,
3709 wpa_s->dpp_pkex_identifier);
3710#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003711 }
3712
3713 /* TODO: Support multiple PKEX info entries */
3714
3715 os_free(wpa_s->dpp_pkex_auth_cmd);
3716 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
3717
3718 return 1;
3719}
3720
3721
3722int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
3723{
3724 unsigned int id_val;
3725
3726 if (os_strcmp(id, "*") == 0) {
3727 id_val = 0;
3728 } else {
3729 id_val = atoi(id);
3730 if (id_val == 0)
3731 return -1;
3732 }
3733
3734 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
3735 return -1;
3736
3737 /* TODO: Support multiple PKEX entries */
3738 os_free(wpa_s->dpp_pkex_code);
3739 wpa_s->dpp_pkex_code = NULL;
3740 os_free(wpa_s->dpp_pkex_identifier);
3741 wpa_s->dpp_pkex_identifier = NULL;
3742 os_free(wpa_s->dpp_pkex_auth_cmd);
3743 wpa_s->dpp_pkex_auth_cmd = NULL;
3744 wpa_s->dpp_pkex_bi = NULL;
3745 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
3746 dpp_pkex_free(wpa_s->dpp_pkex);
3747 wpa_s->dpp_pkex = NULL;
3748 return 0;
3749}
3750
3751
Roshan Pius3a1667e2018-07-03 15:17:14 -07003752void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
3753{
Hai Shalomfdcde762020-04-02 11:19:20 -07003754 if (wpa_s->dpp_auth || wpa_s->dpp_pkex)
3755 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003756 dpp_auth_deinit(wpa_s->dpp_auth);
3757 wpa_s->dpp_auth = NULL;
3758 dpp_pkex_free(wpa_s->dpp_pkex);
3759 wpa_s->dpp_pkex = NULL;
3760 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
3761 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
3762}
3763
3764
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003765int wpas_dpp_init(struct wpa_supplicant *wpa_s)
3766{
Hai Shalom81f62d82019-07-22 12:10:00 -07003767 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003768 u8 adv_proto_id[7];
3769
3770 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
3771 adv_proto_id[1] = 5;
3772 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
3773 adv_proto_id[5] = DPP_OUI_TYPE;
3774 adv_proto_id[6] = 0x01;
3775
3776 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
3777 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
3778 wpas_dpp_gas_status_handler, wpa_s) < 0)
3779 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07003780
3781 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07003782 config.cb_ctx = wpa_s;
3783#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003784 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07003785#endif /* CONFIG_DPP2 */
3786 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07003787 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003788}
3789
3790
3791void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
3792{
3793#ifdef CONFIG_TESTING_OPTIONS
3794 os_free(wpa_s->dpp_config_obj_override);
3795 wpa_s->dpp_config_obj_override = NULL;
3796 os_free(wpa_s->dpp_discovery_override);
3797 wpa_s->dpp_discovery_override = NULL;
3798 os_free(wpa_s->dpp_groups_override);
3799 wpa_s->dpp_groups_override = NULL;
3800 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
3801#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07003802 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003803 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003804 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003805 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003806 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003807 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
3808 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003809 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
3810 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003811#ifdef CONFIG_DPP2
3812 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07003813 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
3814 wpa_s, NULL);
3815 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003816 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
3817 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07003818 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003819 dpp_pfs_free(wpa_s->dpp_pfs);
3820 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07003821 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07003822 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
3823 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07003824#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003825 offchannel_send_action_done(wpa_s);
3826 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003827 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003828 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003829 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
3830 os_free(wpa_s->dpp_configurator_params);
3831 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07003832 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003833}
Hai Shalom81f62d82019-07-22 12:10:00 -07003834
3835
Hai Shaloma20dcd72022-02-04 13:43:00 -08003836static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
3837 struct dpp_authentication *auth, bool tcp)
3838{
3839 struct wpabuf *resp;
3840
3841 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
3842 auth->e_netrole, true);
3843 if (!resp)
3844 return -1;
3845
3846 if (tcp) {
3847 auth->conf_resp_tcp = resp;
3848 return 0;
3849 }
3850
3851 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
3852 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
3853 resp) < 0) {
3854 wpa_printf(MSG_DEBUG,
3855 "DPP: Could not find pending GAS response");
3856 wpabuf_free(resp);
3857 return -1;
3858 }
3859 auth->conf_resp = resp;
3860 return 0;
3861}
3862
3863
3864int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
3865{
3866 int peer;
3867 const char *pos;
3868 struct dpp_authentication *auth = wpa_s->dpp_auth;
3869 bool tcp = false;
3870
3871 pos = os_strstr(cmd, " peer=");
3872 if (!pos)
3873 return -1;
3874 peer = atoi(pos + 6);
3875#ifdef CONFIG_DPP2
3876 if (!auth || !auth->waiting_config ||
3877 (auth->peer_bi &&
3878 (unsigned int) peer != auth->peer_bi->id)) {
3879 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
3880 tcp = true;
3881 }
3882#endif /* CONFIG_DPP2 */
3883
3884 if (!auth || !auth->waiting_config) {
3885 wpa_printf(MSG_DEBUG,
3886 "DPP: No authentication exchange waiting for configuration information");
3887 return -1;
3888 }
3889
3890 if ((!auth->peer_bi ||
3891 (unsigned int) peer != auth->peer_bi->id) &&
3892 (!auth->tmp_peer_bi ||
3893 (unsigned int) peer != auth->tmp_peer_bi->id)) {
3894 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
3895 return -1;
3896 }
3897
3898 pos = os_strstr(cmd, " comeback=");
3899 if (pos) {
3900 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
3901 NULL);
3902 gas_server_set_comeback_delay(wpa_s->gas_server,
3903 auth->config_resp_ctx,
3904 atoi(pos + 10));
3905 return 0;
3906 }
3907
3908 if (dpp_set_configurator(auth, cmd) < 0)
3909 return -1;
3910
3911 auth->use_config_query = false;
3912 auth->waiting_config = false;
3913 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
3914}
3915
3916
Hai Shalom81f62d82019-07-22 12:10:00 -07003917#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003918
Hai Shalom81f62d82019-07-22 12:10:00 -07003919int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
3920{
3921 struct dpp_controller_config config;
3922 const char *pos;
3923
3924 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003925 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07003926 config.netrole = DPP_NETROLE_STA;
3927 config.msg_ctx = wpa_s;
3928 config.cb_ctx = wpa_s;
3929 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003930 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07003931 if (cmd) {
3932 pos = os_strstr(cmd, " tcp_port=");
3933 if (pos) {
3934 pos += 10;
3935 config.tcp_port = atoi(pos);
3936 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003937
3938 pos = os_strstr(cmd, " role=");
3939 if (pos) {
3940 pos += 6;
3941 if (os_strncmp(pos, "configurator", 12) == 0)
3942 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
3943 else if (os_strncmp(pos, "enrollee", 8) == 0)
3944 config.allowed_roles = DPP_CAPAB_ENROLLEE;
3945 else if (os_strncmp(pos, "either", 6) == 0)
3946 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
3947 DPP_CAPAB_ENROLLEE;
3948 else
3949 return -1;
3950 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003951
3952 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07003953 }
3954 config.configurator_params = wpa_s->dpp_configurator_params;
3955 return dpp_controller_start(wpa_s->dpp, &config);
3956}
Hai Shalomfdcde762020-04-02 11:19:20 -07003957
3958
3959static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
3960
3961static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
3962{
3963 struct wpa_supplicant *wpa_s = eloop_ctx;
3964
3965 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
3966 offchannel_send_action_done(wpa_s);
3967 wpas_dpp_chirp_next(wpa_s, NULL);
3968}
3969
3970
3971static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
3972 unsigned int freq, const u8 *dst,
3973 const u8 *src, const u8 *bssid,
3974 const u8 *data, size_t data_len,
3975 enum offchannel_send_action_result result)
3976{
3977 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
3978 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
3979 wpa_s->dpp_chirp_freq);
3980 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
3981 wpa_s, NULL) < 0)
3982 wpas_dpp_chirp_stop(wpa_s);
3983 return;
3984 }
3985
3986 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
3987 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
3988 wpa_s, NULL) < 0)
3989 wpas_dpp_chirp_stop(wpa_s);
3990}
3991
3992
3993static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
3994{
Hai Shalom899fcc72020-10-19 14:38:18 -07003995 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003996 int type;
3997
3998 msg = wpa_s->dpp_presence_announcement;
3999 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
4000 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07004001 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
4002
4003 if (ssid && wpa_s->dpp_reconfig_id &&
4004 wpa_config_get_network(wpa_s->conf,
4005 wpa_s->dpp_reconfig_ssid_id) ==
4006 ssid) {
4007 announce = dpp_build_reconfig_announcement(
4008 ssid->dpp_csign,
4009 ssid->dpp_csign_len,
4010 ssid->dpp_netaccesskey,
4011 ssid->dpp_netaccesskey_len,
4012 wpa_s->dpp_reconfig_id);
4013 msg = announce;
4014 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004015 if (!msg)
4016 return;
4017 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
4018 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004019 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
4020 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004021 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07004022 if (offchannel_send_action(
4023 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
4024 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004025 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07004026 2000, wpas_dpp_chirp_tx_status, 0) < 0)
4027 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004028
4029 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07004030}
4031
4032
4033static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
4034 struct wpa_scan_results *scan_res)
4035{
4036 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
4037 unsigned int i;
4038 struct hostapd_hw_modes *mode;
4039 int c;
4040 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004041 bool chan6 = wpa_s->hw.modes == NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004042
Hai Shalom899fcc72020-10-19 14:38:18 -07004043 if (!bi && !wpa_s->dpp_reconfig_ssid)
Hai Shalomfdcde762020-04-02 11:19:20 -07004044 return;
4045
4046 wpa_s->dpp_chirp_scan_done = 1;
4047
4048 os_free(wpa_s->dpp_chirp_freqs);
4049 wpa_s->dpp_chirp_freqs = NULL;
4050
4051 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004052 if (bi) {
4053 for (i = 0; i < bi->num_freq; i++)
4054 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
4055 bi->freq[i]);
4056 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004057
4058 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07004059 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004060 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07004061 if (mode) {
4062 for (c = 0; c < mode->num_channels; c++) {
4063 struct hostapd_channel_data *chan = &mode->channels[c];
4064
4065 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
4066 chan->freq != 2437)
4067 continue;
4068 chan6 = true;
4069 break;
4070 }
4071 }
4072 if (chan6)
4073 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07004074
4075 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004076 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07004077 if (mode) {
4078 int chan44 = 0, chan149 = 0;
4079
4080 for (c = 0; c < mode->num_channels; c++) {
4081 struct hostapd_channel_data *chan = &mode->channels[c];
4082
4083 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
4084 HOSTAPD_CHAN_RADAR))
4085 continue;
4086 if (chan->freq == 5220)
4087 chan44 = 1;
4088 if (chan->freq == 5745)
4089 chan149 = 1;
4090 }
4091 if (chan149)
4092 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745);
4093 else if (chan44)
4094 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220);
4095 }
4096
4097 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004098 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07004099 if (mode) {
4100 for (c = 0; c < mode->num_channels; c++) {
4101 struct hostapd_channel_data *chan = &mode->channels[c];
4102
4103 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
4104 HOSTAPD_CHAN_RADAR)) ||
4105 chan->freq != 60480)
4106 continue;
4107 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480);
4108 break;
4109 }
4110 }
4111
4112 /* Add channels from scan results for APs that advertise Configurator
4113 * Connectivity element */
4114 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4115 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
4116 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
4117 bss->freq);
4118 }
4119
4120 if (!wpa_s->dpp_chirp_freqs ||
4121 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
4122 wpas_dpp_chirp_stop(wpa_s);
4123}
4124
4125
4126static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
4127{
4128 struct wpa_supplicant *wpa_s = eloop_ctx;
4129 int i;
4130
4131 if (wpa_s->dpp_chirp_listen)
4132 wpas_dpp_listen_stop(wpa_s);
4133
4134 if (wpa_s->dpp_chirp_freq == 0) {
4135 if (wpa_s->dpp_chirp_round % 4 == 0 &&
4136 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08004137 if (wpas_scan_scheduled(wpa_s)) {
4138 wpa_printf(MSG_DEBUG,
4139 "DPP: Deferring chirp scan because another scan is planned already");
4140 if (eloop_register_timeout(1, 0,
4141 wpas_dpp_chirp_next,
4142 wpa_s, NULL) < 0) {
4143 wpas_dpp_chirp_stop(wpa_s);
4144 return;
4145 }
4146 return;
4147 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004148 wpa_printf(MSG_DEBUG,
4149 "DPP: Update channel list for chirping");
4150 wpa_s->scan_req = MANUAL_SCAN_REQ;
4151 wpa_s->scan_res_handler =
4152 wpas_dpp_chirp_scan_res_handler;
4153 wpa_supplicant_req_scan(wpa_s, 0, 0);
4154 return;
4155 }
4156 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
4157 wpa_s->dpp_chirp_round++;
4158 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
4159 wpa_s->dpp_chirp_round);
4160 } else {
4161 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
4162 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
4163 break;
4164 if (!wpa_s->dpp_chirp_freqs[i]) {
4165 wpa_printf(MSG_DEBUG,
4166 "DPP: Previous chirp freq %d not found",
4167 wpa_s->dpp_chirp_freq);
4168 return;
4169 }
4170 i++;
4171 if (wpa_s->dpp_chirp_freqs[i]) {
4172 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
4173 } else {
4174 wpa_s->dpp_chirp_iter--;
4175 if (wpa_s->dpp_chirp_iter <= 0) {
4176 wpa_printf(MSG_DEBUG,
4177 "DPP: Chirping iterations completed");
4178 wpas_dpp_chirp_stop(wpa_s);
4179 return;
4180 }
4181 wpa_s->dpp_chirp_freq = 0;
4182 wpa_s->dpp_chirp_scan_done = 0;
4183 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
4184 wpa_s, NULL) < 0) {
4185 wpas_dpp_chirp_stop(wpa_s);
4186 return;
4187 }
4188 if (wpa_s->dpp_chirp_listen) {
4189 wpa_printf(MSG_DEBUG,
4190 "DPP: Listen on %d MHz during chirp 30 second wait",
4191 wpa_s->dpp_chirp_listen);
4192 wpas_dpp_listen_start(wpa_s,
4193 wpa_s->dpp_chirp_listen);
4194 } else {
4195 wpa_printf(MSG_DEBUG,
4196 "DPP: Wait 30 seconds before starting the next chirping round");
4197 }
4198 return;
4199 }
4200 }
4201
4202 wpas_dpp_chirp_start(wpa_s);
4203}
4204
4205
4206int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
4207{
4208 const char *pos;
4209 int iter = 1, listen_freq = 0;
4210 struct dpp_bootstrap_info *bi;
4211
4212 pos = os_strstr(cmd, " own=");
4213 if (!pos)
4214 return -1;
4215 pos += 5;
4216 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
4217 if (!bi) {
4218 wpa_printf(MSG_DEBUG,
4219 "DPP: Identified bootstrap info not found");
4220 return -1;
4221 }
4222
4223 pos = os_strstr(cmd, " iter=");
4224 if (pos) {
4225 iter = atoi(pos + 6);
4226 if (iter <= 0)
4227 return -1;
4228 }
4229
4230 pos = os_strstr(cmd, " listen=");
4231 if (pos) {
4232 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004233 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07004234 return -1;
4235 }
4236
4237 wpas_dpp_chirp_stop(wpa_s);
4238 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
4239 wpa_s->dpp_qr_mutual = 0;
4240 wpa_s->dpp_chirp_bi = bi;
4241 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
4242 if (!wpa_s->dpp_presence_announcement)
4243 return -1;
4244 wpa_s->dpp_chirp_iter = iter;
4245 wpa_s->dpp_chirp_round = 0;
4246 wpa_s->dpp_chirp_scan_done = 0;
4247 wpa_s->dpp_chirp_listen = listen_freq;
4248
4249 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
4250}
4251
4252
4253void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
4254{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004255 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07004256 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004257 offchannel_send_action_done(wpa_s);
4258 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
4259 }
4260 wpa_s->dpp_chirp_bi = NULL;
4261 wpabuf_free(wpa_s->dpp_presence_announcement);
4262 wpa_s->dpp_presence_announcement = NULL;
4263 if (wpa_s->dpp_chirp_listen)
4264 wpas_dpp_listen_stop(wpa_s);
4265 wpa_s->dpp_chirp_listen = 0;
4266 wpa_s->dpp_chirp_freq = 0;
4267 os_free(wpa_s->dpp_chirp_freqs);
4268 wpa_s->dpp_chirp_freqs = NULL;
4269 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
4270 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
4271 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
4272 wpas_abort_ongoing_scan(wpa_s);
4273 wpa_s->scan_res_handler = NULL;
4274 }
4275}
4276
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004277
Hai Shalom899fcc72020-10-19 14:38:18 -07004278int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004279{
Hai Shalom899fcc72020-10-19 14:38:18 -07004280 struct wpa_ssid *ssid;
4281 int iter = 1;
4282 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004283
Hai Shalom899fcc72020-10-19 14:38:18 -07004284 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
4285 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4286 !ssid->dpp_csign) {
4287 wpa_printf(MSG_DEBUG,
4288 "DPP: Not a valid network profile for reconfiguration");
4289 return -1;
4290 }
4291
4292 pos = os_strstr(cmd, " iter=");
4293 if (pos) {
4294 iter = atoi(pos + 6);
4295 if (iter <= 0)
4296 return -1;
4297 }
4298
4299 if (wpa_s->dpp_auth) {
4300 wpa_printf(MSG_DEBUG,
4301 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
4302 return -1;
4303 }
4304
4305 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4306 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
4307 ssid->dpp_csign_len,
4308 ssid->dpp_pp_key,
4309 ssid->dpp_pp_key_len);
4310 if (!wpa_s->dpp_reconfig_id) {
4311 wpa_printf(MSG_DEBUG,
4312 "DPP: Failed to generate E-id for reconfiguration");
4313 return -1;
4314 }
4315 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
4316 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
4317 wpa_s->own_disconnect_req = 1;
4318 wpa_supplicant_deauthenticate(
4319 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4320 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004321 wpas_dpp_chirp_stop(wpa_s);
4322 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
4323 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004324 wpa_s->dpp_reconfig_ssid = ssid;
4325 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07004326 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004327 wpa_s->dpp_chirp_round = 0;
4328 wpa_s->dpp_chirp_scan_done = 0;
4329 wpa_s->dpp_chirp_listen = 0;
4330
4331 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
4332}
4333
Hai Shalom899fcc72020-10-19 14:38:18 -07004334
Hai Shalom899fcc72020-10-19 14:38:18 -07004335int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
4336{
4337 int peer = -1;
4338 const char *pos, *value;
4339 struct dpp_authentication *auth = wpa_s->dpp_auth;
4340 u8 *bin;
4341 size_t bin_len;
4342 struct wpabuf *buf;
4343 bool tcp = false;
4344
4345 pos = os_strstr(cmd, " peer=");
4346 if (pos) {
4347 peer = atoi(pos + 6);
4348 if (!auth || !auth->waiting_cert ||
4349 (auth->peer_bi &&
4350 (unsigned int) peer != auth->peer_bi->id)) {
4351 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4352 tcp = true;
4353 }
4354 }
4355
4356 if (!auth || !auth->waiting_cert) {
4357 wpa_printf(MSG_DEBUG,
4358 "DPP: No authentication exchange waiting for certificate information");
4359 return -1;
4360 }
4361
4362 if (peer >= 0 &&
4363 (!auth->peer_bi ||
4364 (unsigned int) peer != auth->peer_bi->id) &&
4365 (!auth->tmp_peer_bi ||
4366 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4367 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4368 return -1;
4369 }
4370
4371 pos = os_strstr(cmd, " value=");
4372 if (!pos)
4373 return -1;
4374 value = pos + 7;
4375
4376 pos = os_strstr(cmd, " name=");
4377 if (!pos)
4378 return -1;
4379 pos += 6;
4380
4381 if (os_strncmp(pos, "status ", 7) == 0) {
4382 auth->force_conf_resp_status = atoi(value);
4383 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4384 }
4385
4386 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
4387 os_free(auth->trusted_eap_server_name);
4388 auth->trusted_eap_server_name = os_strdup(value);
4389 return auth->trusted_eap_server_name ? 0 : -1;
4390 }
4391
4392 bin = base64_decode(value, os_strlen(value), &bin_len);
4393 if (!bin)
4394 return -1;
4395 buf = wpabuf_alloc_copy(bin, bin_len);
4396 os_free(bin);
4397
4398 if (os_strncmp(pos, "caCert ", 7) == 0) {
4399 wpabuf_free(auth->cacert);
4400 auth->cacert = buf;
4401 return 0;
4402 }
4403
4404 if (os_strncmp(pos, "certBag ", 8) == 0) {
4405 wpabuf_free(auth->certbag);
4406 auth->certbag = buf;
4407 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4408 }
4409
4410 wpabuf_free(buf);
4411 return -1;
4412}
4413
Hai Shalom81f62d82019-07-22 12:10:00 -07004414#endif /* CONFIG_DPP2 */