blob: 60342cd8eac325d9542316d7afee7e6c254e4c92 [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=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000805 if (addr && os_strcmp(addr, "from-uri") == 0) {
806 os_free(addr);
807 if (!peer_bi->host) {
808 wpa_printf(MSG_INFO,
809 "DPP: TCP address not available in peer URI");
810 return -1;
811 }
812 tcp = 1;
813 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
814 tcp_port = peer_bi->port;
815 } else if (addr) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700816 int res;
817
818 res = hostapd_parse_ip_addr(addr, &ipaddr);
819 os_free(addr);
820 if (res)
821 return -1;
822 tcp = 1;
823 }
824#endif /* CONFIG_DPP2 */
825
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700826 pos = os_strstr(cmd, " own=");
827 if (pos) {
828 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700829 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700830 if (!own_bi) {
831 wpa_printf(MSG_INFO,
832 "DPP: Could not find bootstrapping info for the identified local entry");
833 return -1;
834 }
835
836 if (peer_bi->curve != own_bi->curve) {
837 wpa_printf(MSG_INFO,
838 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
839 peer_bi->curve->name, own_bi->curve->name);
840 return -1;
841 }
842 }
843
844 pos = os_strstr(cmd, " role=");
845 if (pos) {
846 pos += 6;
847 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700848 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700849 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700850 allowed_roles = DPP_CAPAB_ENROLLEE;
851 else if (os_strncmp(pos, "either", 6) == 0)
852 allowed_roles = DPP_CAPAB_CONFIGURATOR |
853 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700854 else
855 goto fail;
856 }
857
858 pos = os_strstr(cmd, " netrole=");
859 if (pos) {
860 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800861 if (os_strncmp(pos, "ap", 2) == 0)
862 wpa_s->dpp_netrole = DPP_NETROLE_AP;
863 else if (os_strncmp(pos, "configurator", 12) == 0)
864 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
865 else
866 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700867 } else {
868 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700869 }
870
Roshan Pius3a1667e2018-07-03 15:17:14 -0700871 pos = os_strstr(cmd, " neg_freq=");
872 if (pos)
873 neg_freq = atoi(pos + 10);
874
Hai Shalom81f62d82019-07-22 12:10:00 -0700875 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700876 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700877 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800878 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
879 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700880 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
881 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700882#ifdef CONFIG_DPP2
883 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
884 wpa_s, NULL);
885#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700886 offchannel_send_action_done(wpa_s);
887 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800888 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700889 }
890
Hai Shalomfdcde762020-04-02 11:19:20 -0700891 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
892 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700893 if (!auth)
894 goto fail;
895 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700896 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700897 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800898 goto fail;
899 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700900
Hai Shalom81f62d82019-07-22 12:10:00 -0700901 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700902
Roshan Pius3a1667e2018-07-03 15:17:14 -0700903 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700904 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700905
Hai Shalom81f62d82019-07-22 12:10:00 -0700906#ifdef CONFIG_DPP2
907 if (tcp)
Hai Shalom899fcc72020-10-19 14:38:18 -0700908 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
909 wpa_s->conf->dpp_name, DPP_NETROLE_STA,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800910 wpa_s, wpa_s, wpas_dpp_process_conf_obj,
911 wpas_dpp_tcp_msg_sent);
Hai Shalom81f62d82019-07-22 12:10:00 -0700912#endif /* CONFIG_DPP2 */
913
914 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700915 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700916fail:
917 return -1;
918}
919
920
921struct wpas_dpp_listen_work {
922 unsigned int freq;
923 unsigned int duration;
924 struct wpabuf *probe_resp_ie;
925};
926
927
928static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
929{
930 if (!lwork)
931 return;
932 os_free(lwork);
933}
934
935
936static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
937{
938 struct wpas_dpp_listen_work *lwork;
939
940 if (!wpa_s->dpp_listen_work)
941 return;
942
943 lwork = wpa_s->dpp_listen_work->ctx;
944 wpas_dpp_listen_work_free(lwork);
945 radio_work_done(wpa_s->dpp_listen_work);
946 wpa_s->dpp_listen_work = NULL;
947}
948
949
950static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
951{
952 struct wpa_supplicant *wpa_s = work->wpa_s;
953 struct wpas_dpp_listen_work *lwork = work->ctx;
954
955 if (deinit) {
956 if (work->started) {
957 wpa_s->dpp_listen_work = NULL;
958 wpas_dpp_listen_stop(wpa_s);
959 }
960 wpas_dpp_listen_work_free(lwork);
961 return;
962 }
963
964 wpa_s->dpp_listen_work = work;
965
966 wpa_s->dpp_pending_listen_freq = lwork->freq;
967
968 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
969 wpa_s->max_remain_on_chan) < 0) {
970 wpa_printf(MSG_DEBUG,
971 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
972 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800973 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700974 wpas_dpp_listen_work_done(wpa_s);
975 wpa_s->dpp_pending_listen_freq = 0;
976 return;
977 }
978 wpa_s->off_channel_freq = 0;
979 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700980 wpa_drv_dpp_listen(wpa_s, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700981}
982
983
984static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
985 unsigned int freq)
986{
987 struct wpas_dpp_listen_work *lwork;
988
989 if (wpa_s->dpp_listen_work) {
990 wpa_printf(MSG_DEBUG,
991 "DPP: Reject start_listen since dpp_listen_work already exists");
992 return -1;
993 }
994
995 if (wpa_s->dpp_listen_freq)
996 wpas_dpp_listen_stop(wpa_s);
997 wpa_s->dpp_listen_freq = freq;
998
999 lwork = os_zalloc(sizeof(*lwork));
1000 if (!lwork)
1001 return -1;
1002 lwork->freq = freq;
1003
1004 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
1005 lwork) < 0) {
1006 wpas_dpp_listen_work_free(lwork);
1007 return -1;
1008 }
1009
1010 return 0;
1011}
1012
1013
1014int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
1015{
1016 int freq;
1017
1018 freq = atoi(cmd);
1019 if (freq <= 0)
1020 return -1;
1021
1022 if (os_strstr(cmd, " role=configurator"))
1023 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
1024 else if (os_strstr(cmd, " role=enrollee"))
1025 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
1026 else
1027 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
1028 DPP_CAPAB_ENROLLEE;
1029 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001030 if (os_strstr(cmd, " netrole=ap"))
1031 wpa_s->dpp_netrole = DPP_NETROLE_AP;
1032 else if (os_strstr(cmd, " netrole=configurator"))
1033 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
1034 else
1035 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001036 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1037 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1038 freq);
1039 return 0;
1040 }
1041
1042 return wpas_dpp_listen_start(wpa_s, freq);
1043}
1044
1045
1046void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1047{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001048 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001049 if (!wpa_s->dpp_listen_freq)
1050 return;
1051
1052 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1053 wpa_s->dpp_listen_freq);
1054 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001055 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001056 wpa_s->dpp_listen_freq = 0;
1057 wpas_dpp_listen_work_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001058 radio_remove_works(wpa_s, "dpp-listen", 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001059}
1060
1061
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001062void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1063 unsigned int freq, unsigned int duration)
1064{
1065 if (wpa_s->dpp_listen_freq != freq)
1066 return;
1067
1068 wpa_printf(MSG_DEBUG,
1069 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
1070 freq, duration);
1071 os_get_reltime(&wpa_s->dpp_listen_end);
1072 wpa_s->dpp_listen_end.usec += duration * 1000;
1073 while (wpa_s->dpp_listen_end.usec >= 1000000) {
1074 wpa_s->dpp_listen_end.sec++;
1075 wpa_s->dpp_listen_end.usec -= 1000000;
1076 }
1077}
1078
1079
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001080void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1081 unsigned int freq)
1082{
1083 wpas_dpp_listen_work_done(wpa_s);
1084
Roshan Pius3a1667e2018-07-03 15:17:14 -07001085 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1086 unsigned int new_freq;
1087
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001088 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001089 if (wpa_s->dpp_auth->neg_freq > 0)
1090 new_freq = wpa_s->dpp_auth->neg_freq;
1091 else
1092 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001093 wpa_printf(MSG_DEBUG,
1094 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001095 new_freq);
1096 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001097 return;
1098 }
1099
1100 if (wpa_s->dpp_listen_freq) {
1101 /* Continue listen with a new remain-on-channel */
1102 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1103 }
1104}
1105
1106
1107static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1108 const u8 *hdr, const u8 *buf, size_t len,
1109 unsigned int freq)
1110{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001111 const u8 *r_bootstrap, *i_bootstrap;
1112 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001113 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1114
1115 if (!wpa_s->dpp)
1116 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001117
1118 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1119 MAC2STR(src));
1120
Hai Shalomfdcde762020-04-02 11:19:20 -07001121#ifdef CONFIG_DPP2
1122 wpas_dpp_chirp_stop(wpa_s);
1123#endif /* CONFIG_DPP2 */
1124
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001125 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1126 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001127 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1128 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1129 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001130 return;
1131 }
1132 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1133 r_bootstrap, r_bootstrap_len);
1134
1135 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1136 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001137 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1138 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1139 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001140 return;
1141 }
1142 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1143 i_bootstrap, i_bootstrap_len);
1144
1145 /* Try to find own and peer bootstrapping key matches based on the
1146 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001147 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1148 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001149 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001150 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1151 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001152 return;
1153 }
1154
1155 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001156 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1157 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001158 return;
1159 }
1160
Sunil Ravia04bd252022-05-02 22:54:18 -07001161 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001162 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001163 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001164 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001165 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1166 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001167 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001168 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001169 if (!wpa_s->dpp_auth) {
1170 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1171 return;
1172 }
1173 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001174 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001175 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001176 dpp_auth_deinit(wpa_s->dpp_auth);
1177 wpa_s->dpp_auth = NULL;
1178 return;
1179 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001180 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1181
Roshan Pius3a1667e2018-07-03 15:17:14 -07001182 if (wpa_s->dpp_listen_freq &&
1183 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1184 wpa_printf(MSG_DEBUG,
1185 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1186 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1187 wpas_dpp_listen_stop(wpa_s);
1188 }
1189
1190 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1191 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1192 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001193 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1194 src, wpa_s->own_addr, broadcast,
1195 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1196 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1197 500, wpas_dpp_tx_status, 0);
1198}
1199
1200
Hai Shaloma20dcd72022-02-04 13:43:00 -08001201void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
1202{
1203 struct dpp_authentication *auth = wpa_s->dpp_auth;
1204 int freq;
1205
1206 if (!wpa_s->dpp_gas_server || !auth)
1207 return;
1208
1209 freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
1210 if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
1211 return; /* listen state is already in progress */
1212
1213 wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
1214 wpa_s->dpp_in_response_listen = 1;
1215 wpas_dpp_listen_start(wpa_s, freq);
1216}
1217
1218
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001219static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1220{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001221 struct dpp_authentication *auth = wpa_s->dpp_auth;
1222
1223 wpa_printf(MSG_DEBUG,
1224 "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
1225 auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
1226 !!wpa_s->dpp_listen_work);
1227 wpa_s->dpp_gas_server = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001228}
1229
1230
1231static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001232 struct dpp_authentication *auth,
1233 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001234{
1235 struct wpa_ssid *ssid;
1236
Hai Shalom021b0b52019-04-10 11:17:58 -07001237#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001238 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001239#ifdef CONFIG_SAE
1240 struct wpa_driver_capa capa;
1241 int res;
1242
1243 res = wpa_drv_get_capa(wpa_s, &capa);
1244 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001245 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1246 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001247 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1248 wpa_printf(MSG_DEBUG,
1249 "DPP: SAE not supported by the driver");
1250 return NULL;
1251 }
1252#else /* CONFIG_SAE */
1253 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1254 return NULL;
1255#endif /* CONFIG_SAE */
1256 }
1257#endif /* CONFIG_DPP2 */
1258
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001259 ssid = wpa_config_add_network(wpa_s->conf);
1260 if (!ssid)
1261 return NULL;
1262 wpas_notify_network_added(wpa_s, ssid);
1263 wpa_config_set_network_defaults(ssid);
1264 ssid->disabled = 1;
1265
Hai Shalomc3565922019-10-28 11:58:20 -07001266 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001267 if (!ssid->ssid)
1268 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001269 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1270 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001271
Hai Shalomc3565922019-10-28 11:58:20 -07001272 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001273 if (dpp_akm_dpp(conf->akm)) {
1274 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1275 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1276 }
Hai Shalomc3565922019-10-28 11:58:20 -07001277 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001278 if (!ssid->dpp_connector)
1279 goto fail;
1280 }
1281
Hai Shalomc3565922019-10-28 11:58:20 -07001282 if (conf->c_sign_key) {
1283 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001284 if (!ssid->dpp_csign)
1285 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001286 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1287 wpabuf_len(conf->c_sign_key));
1288 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001289 }
1290
Hai Shalom899fcc72020-10-19 14:38:18 -07001291 if (conf->pp_key) {
1292 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1293 if (!ssid->dpp_pp_key)
1294 goto fail;
1295 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1296 wpabuf_len(conf->pp_key));
1297 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1298 }
1299
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001300 if (auth->net_access_key) {
1301 ssid->dpp_netaccesskey =
1302 os_malloc(wpabuf_len(auth->net_access_key));
1303 if (!ssid->dpp_netaccesskey)
1304 goto fail;
1305 os_memcpy(ssid->dpp_netaccesskey,
1306 wpabuf_head(auth->net_access_key),
1307 wpabuf_len(auth->net_access_key));
1308 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1309 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1310 }
1311
Hai Shalomc3565922019-10-28 11:58:20 -07001312 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1313 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001314 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001315 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001316 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001317 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1318 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001319 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001320 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1321 WPA_KEY_MGMT_FT_SAE;
1322 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001323 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001324 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001325 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001326 goto fail;
1327 wpa_config_update_psk(ssid);
1328 ssid->export_keys = 1;
1329 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001330 ssid->psk_set = conf->psk_set;
1331 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001332 }
1333 }
1334
Hai Shalom899fcc72020-10-19 14:38:18 -07001335#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1336 if (conf->akm == DPP_AKM_DOT1X) {
1337 int i;
1338 char name[100], blobname[128];
1339 struct wpa_config_blob *blob;
1340
1341 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1342 WPA_KEY_MGMT_IEEE8021X_SHA256 |
1343 WPA_KEY_MGMT_IEEE8021X_SHA256;
1344 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1345
1346 if (conf->cacert) {
1347 /* caCert is DER-encoded X.509v3 certificate for the
1348 * server certificate if that is different from the
1349 * trust root included in certBag. */
1350 /* TODO: ssid->eap.cert.ca_cert */
1351 }
1352
1353 if (conf->certs) {
1354 for (i = 0; ; i++) {
1355 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1356 i);
1357 if (!wpa_config_get_blob(wpa_s->conf, name))
1358 break;
1359 }
1360
1361 blob = os_zalloc(sizeof(*blob));
1362 if (!blob)
1363 goto fail;
1364 blob->len = wpabuf_len(conf->certs);
1365 blob->name = os_strdup(name);
1366 blob->data = os_malloc(blob->len);
1367 if (!blob->name || !blob->data) {
1368 wpa_config_free_blob(blob);
1369 goto fail;
1370 }
1371 os_memcpy(blob->data, wpabuf_head(conf->certs),
1372 blob->len);
1373 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1374 name);
1375 wpa_config_set_blob(wpa_s->conf, blob);
1376 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1377 name);
1378 ssid->eap.cert.client_cert = os_strdup(blobname);
1379 if (!ssid->eap.cert.client_cert)
1380 goto fail;
1381
1382 /* TODO: ssid->eap.identity from own certificate */
1383 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1384 0) < 0)
1385 goto fail;
1386 }
1387
1388 if (auth->priv_key) {
1389 for (i = 0; ; i++) {
1390 os_snprintf(name, sizeof(name), "dpp-key-%d",
1391 i);
1392 if (!wpa_config_get_blob(wpa_s->conf, name))
1393 break;
1394 }
1395
1396 blob = os_zalloc(sizeof(*blob));
1397 if (!blob)
1398 goto fail;
1399 blob->len = wpabuf_len(auth->priv_key);
1400 blob->name = os_strdup(name);
1401 blob->data = os_malloc(blob->len);
1402 if (!blob->name || !blob->data) {
1403 wpa_config_free_blob(blob);
1404 goto fail;
1405 }
1406 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1407 blob->len);
1408 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1409 name);
1410 wpa_config_set_blob(wpa_s->conf, blob);
1411 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1412 name);
1413 ssid->eap.cert.private_key = os_strdup(blobname);
1414 if (!ssid->eap.cert.private_key)
1415 goto fail;
1416 }
1417
1418 if (conf->server_name) {
1419 ssid->eap.cert.domain_suffix_match =
1420 os_strdup(conf->server_name);
1421 if (!ssid->eap.cert.domain_suffix_match)
1422 goto fail;
1423 }
1424
1425 /* TODO: Use entCreds::eapMethods */
1426 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1427 goto fail;
1428 }
1429#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1430
Hai Shalomc3565922019-10-28 11:58:20 -07001431 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1432 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1433
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001434 return ssid;
1435fail:
1436 wpas_notify_network_removed(wpa_s, ssid);
1437 wpa_config_remove_network(wpa_s->conf, ssid->id);
1438 return NULL;
1439}
1440
1441
Hai Shalom021b0b52019-04-10 11:17:58 -07001442static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001443 struct dpp_authentication *auth,
1444 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001445{
1446 struct wpa_ssid *ssid;
1447
1448 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001449 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001450
Hai Shalomc3565922019-10-28 11:58:20 -07001451 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001452 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001453 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001454
1455 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001456
Hai Shalom706f99b2019-01-08 16:23:37 -08001457 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001458
Hai Shalom021b0b52019-04-10 11:17:58 -07001459 if (wpa_s->conf->dpp_config_processing == 2)
1460 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001461
Hai Shalom021b0b52019-04-10 11:17:58 -07001462#ifndef CONFIG_NO_CONFIG_WRITE
1463 if (wpa_s->conf->update_config &&
1464 wpa_config_write(wpa_s->confname, wpa_s->conf))
1465 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1466#endif /* CONFIG_NO_CONFIG_WRITE */
1467
Hai Shalomc3565922019-10-28 11:58:20 -07001468 return 0;
1469}
1470
1471
1472static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1473 struct dpp_authentication *auth)
1474{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001475#ifdef CONFIG_DPP2
1476 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1477 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1478 wpa_s->dpp_reconfig_ssid) {
1479 wpa_printf(MSG_DEBUG,
1480 "DPP: Remove reconfigured network profile");
1481 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1482 wpa_config_remove_network(wpa_s->conf,
1483 wpa_s->dpp_reconfig_ssid_id);
1484 wpa_s->dpp_reconfig_ssid = NULL;
1485 wpa_s->dpp_reconfig_ssid_id = -1;
1486 }
1487#endif /* CONFIG_DPP2 */
1488
Hai Shalom021b0b52019-04-10 11:17:58 -07001489 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001490 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001491
1492#ifdef CONFIG_DPP2
1493 if (auth->peer_version >= 2) {
1494 wpa_printf(MSG_DEBUG,
1495 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1496 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001497 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001498 }
1499#endif /* CONFIG_DPP2 */
1500
1501 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001502}
1503
1504
Hai Shalom021b0b52019-04-10 11:17:58 -07001505static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001506 struct dpp_authentication *auth,
1507 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001508{
1509 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001510 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1511 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001512 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001513 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001514 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001515 if (conf->ssid_charset)
1516 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1517 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001518 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001519 /* TODO: Save the Connector and consider using a command
1520 * to fetch the value instead of sending an event with
1521 * it. The Connector could end up being larger than what
1522 * most clients are ready to receive as an event
1523 * message. */
1524 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001525 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001526 }
Hai Shalom60840252021-02-19 19:02:11 -08001527 if (conf->passphrase[0]) {
1528 char hex[64 * 2 + 1];
1529
1530 wpa_snprintf_hex(hex, sizeof(hex),
1531 (const u8 *) conf->passphrase,
1532 os_strlen(conf->passphrase));
1533 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1534 hex);
1535 } else if (conf->psk_set) {
1536 char hex[PMK_LEN * 2 + 1];
1537
1538 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1539 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1540 hex);
1541 }
Hai Shalomc3565922019-10-28 11:58:20 -07001542 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001543 char *hex;
1544 size_t hexlen;
1545
Hai Shalomc3565922019-10-28 11:58:20 -07001546 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001547 hex = os_malloc(hexlen);
1548 if (hex) {
1549 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001550 wpabuf_head(conf->c_sign_key),
1551 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001552 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1553 hex);
1554 os_free(hex);
1555 }
1556 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001557 if (conf->pp_key) {
1558 char *hex;
1559 size_t hexlen;
1560
1561 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1562 hex = os_malloc(hexlen);
1563 if (hex) {
1564 wpa_snprintf_hex(hex, hexlen,
1565 wpabuf_head(conf->pp_key),
1566 wpabuf_len(conf->pp_key));
1567 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1568 os_free(hex);
1569 }
1570 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001571 if (auth->net_access_key) {
1572 char *hex;
1573 size_t hexlen;
1574
1575 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1576 hex = os_malloc(hexlen);
1577 if (hex) {
1578 wpa_snprintf_hex(hex, hexlen,
1579 wpabuf_head(auth->net_access_key),
1580 wpabuf_len(auth->net_access_key));
1581 if (auth->net_access_key_expiry)
1582 wpa_msg(wpa_s, MSG_INFO,
1583 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1584 (long unsigned)
1585 auth->net_access_key_expiry);
1586 else
1587 wpa_msg(wpa_s, MSG_INFO,
1588 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1589 os_free(hex);
1590 }
1591 }
1592
Hai Shalom899fcc72020-10-19 14:38:18 -07001593#ifdef CONFIG_DPP2
1594 if (conf->certbag) {
1595 char *b64;
1596
1597 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1598 wpabuf_len(conf->certbag), NULL);
1599 if (b64)
1600 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1601 os_free(b64);
1602 }
1603
1604 if (conf->cacert) {
1605 char *b64;
1606
1607 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1608 wpabuf_len(conf->cacert), NULL);
1609 if (b64)
1610 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1611 os_free(b64);
1612 }
1613
1614 if (conf->server_name)
1615 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1616 conf->server_name);
1617#endif /* CONFIG_DPP2 */
1618
Hai Shalomc3565922019-10-28 11:58:20 -07001619 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001620}
1621
1622
Hai Shalomfdcde762020-04-02 11:19:20 -07001623static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1624 struct dpp_asymmetric_key *key)
1625{
1626#ifdef CONFIG_DPP2
1627 int res;
1628
1629 if (!key)
1630 return 0;
1631
1632 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1633 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001634 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001635
1636 while (key) {
1637 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1638 if (res < 0)
1639 return -1;
1640 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1641 res);
1642 key = key->next;
1643 }
1644#endif /* CONFIG_DPP2 */
1645
1646 return 0;
1647}
1648
1649
Hai Shalom899fcc72020-10-19 14:38:18 -07001650#ifdef CONFIG_DPP2
1651static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1652{
1653 struct wpa_supplicant *wpa_s = eloop_ctx;
1654 struct dpp_authentication *auth = wpa_s->dpp_auth;
1655
1656 if (!auth || !auth->csrattrs)
1657 return;
1658
1659 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1660 wpabuf_free(auth->csr);
1661 /* TODO: Additional information needed for CSR based on csrAttrs */
1662 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1663 wpa_s->conf->dpp_name : "Test");
1664 if (!auth->csr) {
1665 dpp_auth_deinit(wpa_s->dpp_auth);
1666 wpa_s->dpp_auth = NULL;
1667 return;
1668 }
1669
1670 wpas_dpp_start_gas_client(wpa_s);
1671}
1672#endif /* CONFIG_DPP2 */
1673
1674
Sunil Ravia04bd252022-05-02 22:54:18 -07001675#ifdef CONFIG_DPP3
1676static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1677{
1678 struct wpa_supplicant *wpa_s = eloop_ctx;
1679 struct dpp_authentication *auth = wpa_s->dpp_auth;
1680
1681 if (!auth || !auth->waiting_new_key)
1682 return;
1683
1684 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1685 wpas_dpp_start_gas_client(wpa_s);
1686}
1687#endif /* CONFIG_DPP3 */
1688
1689
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001690static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1691 enum gas_query_result result,
1692 const struct wpabuf *adv_proto,
1693 const struct wpabuf *resp, u16 status_code)
1694{
1695 struct wpa_supplicant *wpa_s = ctx;
1696 const u8 *pos;
1697 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001698 int res;
1699 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001700 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001701
Hai Shaloma20dcd72022-02-04 13:43:00 -08001702 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001703 wpa_s->dpp_gas_dialog_token = -1;
1704
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001705 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
1706 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001707 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1708 return;
1709 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001710 if (result != GAS_QUERY_SUCCESS ||
1711 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001712 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1713 goto fail;
1714 }
1715
1716 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1717 adv_proto);
1718 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1719 resp);
1720
1721 if (wpabuf_len(adv_proto) != 10 ||
1722 !(pos = wpabuf_head(adv_proto)) ||
1723 pos[0] != WLAN_EID_ADV_PROTO ||
1724 pos[1] != 8 ||
1725 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1726 pos[4] != 5 ||
1727 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1728 pos[8] != 0x1a ||
1729 pos[9] != 1) {
1730 wpa_printf(MSG_DEBUG,
1731 "DPP: Not a DPP Advertisement Protocol ID");
1732 goto fail;
1733 }
1734
Hai Shalom899fcc72020-10-19 14:38:18 -07001735 res = dpp_conf_resp_rx(auth, resp);
1736#ifdef CONFIG_DPP2
1737 if (res == -2) {
1738 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1739 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1740 return;
1741 }
1742#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001743#ifdef CONFIG_DPP3
1744 if (res == -3) {
1745 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1746 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1747 NULL);
1748 return;
1749 }
1750#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001751 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001752 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1753 goto fail;
1754 }
1755
Hai Shalom899fcc72020-10-19 14:38:18 -07001756 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001757 for (i = 0; i < auth->num_conf_obj; i++) {
1758 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1759 &auth->conf_obj[i]);
1760 if (res < 0)
1761 goto fail;
1762 }
1763 if (auth->num_conf_obj)
1764 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001765 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1766 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001767
Hai Shalom021b0b52019-04-10 11:17:58 -07001768 status = DPP_STATUS_OK;
1769#ifdef CONFIG_TESTING_OPTIONS
1770 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1771 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1772 status = DPP_STATUS_CONFIG_REJECTED;
1773 }
1774#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001775fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001776 if (status != DPP_STATUS_OK) {
1777 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1778 wpas_notify_dpp_configuration_failure(wpa_s);
1779 }
1780#ifdef CONFIG_DPP2
1781 if (auth->peer_version >= 2 &&
1782 auth->conf_resp_status == DPP_STATUS_OK) {
1783 struct wpabuf *msg;
1784
1785 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1786 msg = dpp_build_conf_result(auth, status);
1787 if (!msg)
1788 goto fail2;
1789
1790 wpa_msg(wpa_s, MSG_INFO,
1791 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1792 MAC2STR(addr), auth->curr_freq,
1793 DPP_PA_CONFIGURATION_RESULT);
1794 offchannel_send_action(wpa_s, auth->curr_freq,
1795 addr, wpa_s->own_addr, broadcast,
1796 wpabuf_head(msg),
1797 wpabuf_len(msg),
1798 500, wpas_dpp_tx_status, 0);
1799 wpabuf_free(msg);
1800
1801 /* This exchange will be terminated in the TX status handler */
Hai Shalom899fcc72020-10-19 14:38:18 -07001802 if (wpa_s->conf->dpp_config_processing < 2 ||
1803 wpa_s->dpp_conf_backup_received)
1804 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001805 return;
1806 }
1807fail2:
1808#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001809 dpp_auth_deinit(wpa_s->dpp_auth);
1810 wpa_s->dpp_auth = NULL;
1811}
1812
1813
Hai Shaloma20dcd72022-02-04 13:43:00 -08001814static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
1815{
1816 struct wpa_supplicant *wpa_s = eloop_ctx;
1817 struct dpp_authentication *auth = wpa_s->dpp_auth;
1818
1819 if (!wpa_s->dpp_gas_client || !auth ||
1820 (!auth->auth_success && !auth->reconfig_success))
1821 return;
1822
1823 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
1824 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1825 dpp_auth_deinit(wpa_s->dpp_auth);
1826 wpa_s->dpp_auth = NULL;
1827}
1828
1829
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001830static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1831{
1832 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001833 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001834 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001835 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001836
1837 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001838 offchannel_send_action_done(wpa_s);
1839 wpas_dpp_listen_stop(wpa_s);
1840
Hai Shalomc3565922019-10-28 11:58:20 -07001841 supp_op_classes = wpas_supp_op_classes(wpa_s);
1842 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001843 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001844 wpa_s->conf->dpp_mud_url,
1845 supp_op_classes);
1846 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001847 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001848 wpa_printf(MSG_DEBUG,
1849 "DPP: No configuration request data available");
1850 return;
1851 }
1852
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001853 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1854 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1855
Hai Shaloma20dcd72022-02-04 13:43:00 -08001856 /* Use a 120 second timeout since the gas_query_req() operation could
1857 * remain waiting indefinitely for the response if the Configurator
1858 * keeps sending out comeback responses with additional delay. The
1859 * DPP technical specification expects the Enrollee to continue sending
1860 * out new Config Requests for 60 seconds, so this gives an extra 60
1861 * second time after the last expected new Config Request for the
1862 * Configurator to determine what kind of configuration to provide. */
1863 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
1864 wpa_s, NULL);
1865
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001866 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001867 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001868 if (res < 0) {
1869 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1870 wpabuf_free(buf);
1871 } else {
1872 wpa_printf(MSG_DEBUG,
1873 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001874 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001875 }
1876}
1877
1878
1879static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1880{
1881 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1882 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001883 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001884#ifdef CONFIG_TESTING_OPTIONS
1885 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1886 wpa_printf(MSG_INFO,
1887 "DPP: TESTING - stop at Authentication Confirm");
1888 if (wpa_s->dpp_auth->configurator) {
1889 /* Prevent GAS response */
1890 wpa_s->dpp_auth->auth_success = 0;
1891 }
1892 return;
1893 }
1894#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001895
1896 if (wpa_s->dpp_auth->configurator)
1897 wpas_dpp_start_gas_server(wpa_s);
1898 else
1899 wpas_dpp_start_gas_client(wpa_s);
1900}
1901
1902
1903static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001904 const u8 *hdr, const u8 *buf, size_t len,
1905 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001906{
1907 struct dpp_authentication *auth = wpa_s->dpp_auth;
1908 struct wpabuf *msg;
1909
Roshan Pius3a1667e2018-07-03 15:17:14 -07001910 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1911 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001912
1913 if (!auth) {
1914 wpa_printf(MSG_DEBUG,
1915 "DPP: No DPP Authentication in progress - drop");
1916 return;
1917 }
1918
1919 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1920 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1921 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1922 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1923 return;
1924 }
1925
1926 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1927
Roshan Pius3a1667e2018-07-03 15:17:14 -07001928 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1929 wpa_printf(MSG_DEBUG,
1930 "DPP: Responder accepted request for different negotiation channel");
1931 auth->curr_freq = freq;
1932 }
1933
1934 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001935 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1936 if (!msg) {
1937 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1938 wpa_printf(MSG_DEBUG,
1939 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001940 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001941 offchannel_send_action_done(wpa_s);
1942 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1943 return;
1944 }
1945 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1946 return;
1947 }
1948 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1949
Roshan Pius3a1667e2018-07-03 15:17:14 -07001950 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1951 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001952 offchannel_send_action(wpa_s, auth->curr_freq,
1953 src, wpa_s->own_addr, broadcast,
1954 wpabuf_head(msg), wpabuf_len(msg),
1955 500, wpas_dpp_tx_status, 0);
1956 wpabuf_free(msg);
1957 wpa_s->dpp_auth_ok_on_ack = 1;
1958}
1959
1960
1961static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1962 const u8 *hdr, const u8 *buf, size_t len)
1963{
1964 struct dpp_authentication *auth = wpa_s->dpp_auth;
1965
1966 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1967 MAC2STR(src));
1968
1969 if (!auth) {
1970 wpa_printf(MSG_DEBUG,
1971 "DPP: No DPP Authentication in progress - drop");
1972 return;
1973 }
1974
1975 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1976 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1977 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1978 return;
1979 }
1980
Hai Shalom60840252021-02-19 19:02:11 -08001981 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
1982
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001983 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1984 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001985 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001986 return;
1987 }
1988
1989 wpas_dpp_auth_success(wpa_s, 0);
1990}
1991
1992
Hai Shalom021b0b52019-04-10 11:17:58 -07001993#ifdef CONFIG_DPP2
1994
1995static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
1996 void *timeout_ctx)
1997{
1998 struct wpa_supplicant *wpa_s = eloop_ctx;
1999 struct dpp_authentication *auth = wpa_s->dpp_auth;
2000
2001 if (!auth || !auth->waiting_conf_result)
2002 return;
2003
2004 wpa_printf(MSG_DEBUG,
2005 "DPP: Timeout while waiting for Configuration Result");
2006 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002007 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002008 dpp_auth_deinit(auth);
2009 wpa_s->dpp_auth = NULL;
2010}
2011
2012
Hai Shalomc3565922019-10-28 11:58:20 -07002013static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2014 void *timeout_ctx)
2015{
2016 struct wpa_supplicant *wpa_s = eloop_ctx;
2017 struct dpp_authentication *auth = wpa_s->dpp_auth;
2018
2019 if (!auth || !auth->waiting_conn_status_result)
2020 return;
2021
2022 wpa_printf(MSG_DEBUG,
2023 "DPP: Timeout while waiting for Connection Status Result");
2024 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002025 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002026 wpas_dpp_listen_stop(wpa_s);
2027 dpp_auth_deinit(auth);
2028 wpa_s->dpp_auth = NULL;
2029}
2030
2031
Hai Shalom021b0b52019-04-10 11:17:58 -07002032static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2033 const u8 *hdr, const u8 *buf, size_t len)
2034{
2035 struct dpp_authentication *auth = wpa_s->dpp_auth;
2036 enum dpp_status_error status;
2037
2038 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2039 MAC2STR(src));
2040
2041 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002042 if (auth &&
2043 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
2044 gas_server_response_sent(wpa_s->gas_server,
2045 auth->gas_server_ctx)) {
2046 /* This could happen if the TX status event gets delayed
2047 * long enough for the Enrollee to have time to send
2048 * the next frame before the TX status gets processed
2049 * locally. */
2050 wpa_printf(MSG_DEBUG,
2051 "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");
2052 auth->waiting_conf_result = 1;
2053 } else {
2054 wpa_printf(MSG_DEBUG,
2055 "DPP: No DPP Configuration waiting for result - drop");
2056 return;
2057 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002058 }
2059
2060 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2061 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2062 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2063 return;
2064 }
2065
2066 status = dpp_conf_result_rx(auth, hdr, buf, len);
2067
Hai Shalomc3565922019-10-28 11:58:20 -07002068 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002069 int freq;
2070
Hai Shalomc3565922019-10-28 11:58:20 -07002071 wpa_msg(wpa_s, MSG_INFO,
2072 DPP_EVENT_CONF_SENT "wait_conn_status=1");
2073 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002074 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002075 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2076 wpa_s, NULL);
2077 auth->waiting_conn_status_result = 1;
2078 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2079 wpa_s, NULL);
2080 eloop_register_timeout(16, 0,
2081 wpas_dpp_conn_status_result_wait_timeout,
2082 wpa_s, NULL);
2083 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002084 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2085 if (!wpa_s->dpp_in_response_listen ||
2086 (int) wpa_s->dpp_listen_freq != freq)
2087 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002088 return;
2089 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002090 offchannel_send_action_done(wpa_s);
2091 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002092 if (status == DPP_STATUS_OK) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002093 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalome4073332019-11-05 16:20:12 -08002094 wpas_notify_dpp_config_sent(wpa_s);
2095 }
2096 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002097 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002098 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002099 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002100 dpp_auth_deinit(auth);
2101 wpa_s->dpp_auth = NULL;
2102 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
2103}
2104
Hai Shalom81f62d82019-07-22 12:10:00 -07002105
Hai Shalomc3565922019-10-28 11:58:20 -07002106static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2107 const u8 *src, const u8 *hdr,
2108 const u8 *buf, size_t len)
2109{
2110 struct dpp_authentication *auth = wpa_s->dpp_auth;
2111 enum dpp_status_error status;
2112 u8 ssid[SSID_MAX_LEN];
2113 size_t ssid_len = 0;
2114 char *channel_list = NULL;
2115
2116 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2117
2118 if (!auth || !auth->waiting_conn_status_result) {
2119 wpa_printf(MSG_DEBUG,
2120 "DPP: No DPP Configuration waiting for connection status result - drop");
2121 return;
2122 }
2123
2124 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2125 ssid, &ssid_len, &channel_list);
2126 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2127 "result=%d ssid=%s channel_list=%s",
2128 status, wpa_ssid_txt(ssid, ssid_len),
2129 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002130 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2131 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002132 os_free(channel_list);
2133 offchannel_send_action_done(wpa_s);
2134 wpas_dpp_listen_stop(wpa_s);
2135 dpp_auth_deinit(auth);
2136 wpa_s->dpp_auth = NULL;
2137 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2138 wpa_s, NULL);
2139}
2140
2141
Hai Shalom81f62d82019-07-22 12:10:00 -07002142static int wpas_dpp_process_conf_obj(void *ctx,
2143 struct dpp_authentication *auth)
2144{
2145 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002146 unsigned int i;
2147 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002148
Hai Shalomc3565922019-10-28 11:58:20 -07002149 for (i = 0; i < auth->num_conf_obj; i++) {
2150 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2151 &auth->conf_obj[i]);
2152 if (res)
2153 break;
2154 }
2155 if (!res)
2156 wpas_dpp_post_process_config(wpa_s, auth);
2157
2158 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002159}
2160
Hai Shalomfdcde762020-04-02 11:19:20 -07002161
Hai Shaloma20dcd72022-02-04 13:43:00 -08002162static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2163{
2164 struct wpa_supplicant *wpa_s = ctx;
2165
2166 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2167
2168 if (auth->connect_on_tx_status) {
2169 auth->connect_on_tx_status = 0;
2170 wpa_printf(MSG_DEBUG,
2171 "DPP: Try to connect after completed configuration result");
2172 wpas_dpp_try_to_connect(wpa_s);
2173 if (auth->conn_status_requested) {
2174 wpa_printf(MSG_DEBUG,
2175 "DPP: Start 15 second timeout for reporting connection status result");
2176 eloop_cancel_timeout(
2177 wpas_dpp_conn_status_result_timeout,
2178 wpa_s, NULL);
2179 eloop_register_timeout(
2180 15, 0, wpas_dpp_conn_status_result_timeout,
2181 wpa_s, NULL);
2182 return true;
2183 }
2184 }
2185
2186 return false;
2187}
2188
2189
Hai Shalomfdcde762020-04-02 11:19:20 -07002190static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2191{
2192 struct wpa_supplicant *wpa_s = ctx;
2193
2194 if (bi == wpa_s->dpp_chirp_bi)
2195 wpas_dpp_chirp_stop(wpa_s);
2196}
2197
2198
2199static void
2200wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2201 const u8 *hdr, const u8 *buf, size_t len,
2202 unsigned int freq)
2203{
2204 const u8 *r_bootstrap;
2205 u16 r_bootstrap_len;
2206 struct dpp_bootstrap_info *peer_bi;
2207 struct dpp_authentication *auth;
2208
2209 if (!wpa_s->dpp)
2210 return;
2211
2212 if (wpa_s->dpp_auth) {
2213 wpa_printf(MSG_DEBUG,
2214 "DPP: Ignore Presence Announcement during ongoing Authentication");
2215 return;
2216 }
2217
2218 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2219 MAC2STR(src));
2220
2221 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2222 &r_bootstrap_len);
2223 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2224 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2225 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2226 return;
2227 }
2228 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2229 r_bootstrap, r_bootstrap_len);
2230 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002231 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2232 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002233 if (!peer_bi) {
2234 wpa_printf(MSG_DEBUG,
2235 "DPP: No matching bootstrapping information found");
2236 return;
2237 }
2238
2239 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2240 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2241 if (!auth)
2242 return;
2243 wpas_dpp_set_testing_options(wpa_s, auth);
2244 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2245 dpp_auth_deinit(auth);
2246 return;
2247 }
2248
2249 auth->neg_freq = freq;
2250
Hai Shalom60840252021-02-19 19:02:11 -08002251 /* The source address of the Presence Announcement frame overrides any
2252 * MAC address information from the bootstrapping information. */
2253 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002254
2255 wpa_s->dpp_auth = auth;
2256 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2257 dpp_auth_deinit(wpa_s->dpp_auth);
2258 wpa_s->dpp_auth = NULL;
2259 }
2260}
2261
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002262
2263static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2264 void *timeout_ctx)
2265{
2266 struct wpa_supplicant *wpa_s = eloop_ctx;
2267 struct dpp_authentication *auth = wpa_s->dpp_auth;
2268
2269 if (!auth)
2270 return;
2271
2272 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2273 offchannel_send_action_done(wpa_s);
2274 wpas_dpp_listen_stop(wpa_s);
2275 dpp_auth_deinit(auth);
2276 wpa_s->dpp_auth = NULL;
2277}
2278
2279
2280static void
2281wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2282 const u8 *hdr, const u8 *buf, size_t len,
2283 unsigned int freq)
2284{
Hai Shalom899fcc72020-10-19 14:38:18 -07002285 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2286 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002287 struct dpp_configurator *conf;
2288 struct dpp_authentication *auth;
2289 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002290 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002291
2292 if (!wpa_s->dpp)
2293 return;
2294
2295 if (wpa_s->dpp_auth) {
2296 wpa_printf(MSG_DEBUG,
2297 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2298 return;
2299 }
2300
2301 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2302 MAC2STR(src));
2303
2304 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2305 &csign_hash_len);
2306 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2307 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2308 "Missing or invalid required Configurator C-sign key Hash attribute");
2309 return;
2310 }
2311 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2312 csign_hash, csign_hash_len);
2313 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2314 if (!conf) {
2315 wpa_printf(MSG_DEBUG,
2316 "DPP: No matching Configurator information found");
2317 return;
2318 }
2319
Hai Shalom899fcc72020-10-19 14:38:18 -07002320 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2321 &fcgroup_len);
2322 if (!fcgroup || fcgroup_len != 2) {
2323 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2324 "Missing or invalid required Finite Cyclic Group attribute");
2325 return;
2326 }
2327 group = WPA_GET_LE16(fcgroup);
2328 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2329
2330 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2331 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2332
2333 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2334 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002335 if (!auth)
2336 return;
2337 wpas_dpp_set_testing_options(wpa_s, auth);
2338 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2339 dpp_auth_deinit(auth);
2340 return;
2341 }
2342
2343 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2344 wpa_s->dpp_auth = auth;
2345
2346 wpa_s->dpp_in_response_listen = 0;
2347 wpa_s->dpp_auth_ok_on_ack = 0;
2348 wait_time = wpa_s->max_remain_on_chan;
2349 max_wait_time = wpa_s->dpp_resp_wait_time ?
2350 wpa_s->dpp_resp_wait_time : 2000;
2351 if (wait_time > max_wait_time)
2352 wait_time = max_wait_time;
2353 wait_time += 10; /* give the driver some extra time to complete */
2354 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2355 wpas_dpp_reconfig_reply_wait_timeout,
2356 wpa_s, NULL);
2357 wait_time -= 10;
2358
2359 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2360
2361 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2362 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2363 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2364 wpabuf_head(auth->reconfig_req_msg),
2365 wpabuf_len(auth->reconfig_req_msg),
2366 wait_time, wpas_dpp_tx_status, 0) < 0) {
2367 dpp_auth_deinit(wpa_s->dpp_auth);
2368 wpa_s->dpp_auth = NULL;
2369 }
2370}
2371
2372
2373static void
2374wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2375 const u8 *hdr, const u8 *buf, size_t len,
2376 unsigned int freq)
2377{
2378 struct wpa_ssid *ssid;
2379 struct dpp_authentication *auth;
2380
2381 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2382 MACSTR, MAC2STR(src));
2383
Hai Shalom899fcc72020-10-19 14:38:18 -07002384 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002385 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002386 if (wpa_s->dpp_auth) {
2387 wpa_printf(MSG_DEBUG,
2388 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2389 return;
2390 }
2391 if (!wpa_s->dpp_reconfig_ssid) {
2392 wpa_printf(MSG_DEBUG,
2393 "DPP: Not ready for reconfiguration - not requested");
2394 return;
2395 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002396 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2397 if (ssid == wpa_s->dpp_reconfig_ssid &&
2398 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2399 break;
2400 }
2401 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002402 !ssid->dpp_csign) {
2403 wpa_printf(MSG_DEBUG,
2404 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002405 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002406 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002407
2408 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2409 ssid->dpp_netaccesskey,
2410 ssid->dpp_netaccesskey_len,
2411 ssid->dpp_csign, ssid->dpp_csign_len,
2412 freq, hdr, buf, len);
2413 if (!auth)
2414 return;
2415 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2416 wpa_s->dpp_auth = auth;
2417
2418 wpas_dpp_chirp_stop(wpa_s);
2419
2420 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2421 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2422 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2423 wpabuf_head(auth->reconfig_resp_msg),
2424 wpabuf_len(auth->reconfig_resp_msg),
2425 500, wpas_dpp_tx_status, 0) < 0) {
2426 dpp_auth_deinit(wpa_s->dpp_auth);
2427 wpa_s->dpp_auth = NULL;
2428 }
2429}
2430
2431
2432static void
2433wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2434 const u8 *hdr, const u8 *buf, size_t len,
2435 unsigned int freq)
2436{
2437 struct dpp_authentication *auth = wpa_s->dpp_auth;
2438 struct wpabuf *conf;
2439
2440 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2441 MACSTR, MAC2STR(src));
2442
2443 if (!auth || !auth->reconfig || !auth->configurator) {
2444 wpa_printf(MSG_DEBUG,
2445 "DPP: No DPP Reconfig Authentication in progress - drop");
2446 return;
2447 }
2448
2449 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2450 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2451 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2452 return;
2453 }
2454
2455 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2456 if (!conf)
2457 return;
2458
2459 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2460
2461 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2462 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2463 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2464 wpabuf_head(conf), wpabuf_len(conf),
2465 500, wpas_dpp_tx_status, 0) < 0) {
2466 wpabuf_free(conf);
2467 dpp_auth_deinit(wpa_s->dpp_auth);
2468 wpa_s->dpp_auth = NULL;
2469 return;
2470 }
2471 wpabuf_free(conf);
2472
2473 wpas_dpp_start_gas_server(wpa_s);
2474}
2475
2476
2477static void
2478wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2479 const u8 *hdr, const u8 *buf, size_t len,
2480 unsigned int freq)
2481{
2482 struct dpp_authentication *auth = wpa_s->dpp_auth;
2483
2484 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2485 MACSTR, MAC2STR(src));
2486
2487 if (!auth || !auth->reconfig || auth->configurator) {
2488 wpa_printf(MSG_DEBUG,
2489 "DPP: No DPP Reconfig Authentication in progress - drop");
2490 return;
2491 }
2492
2493 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2494 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2495 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2496 return;
2497 }
2498
2499 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2500 return;
2501
2502 wpas_dpp_start_gas_client(wpa_s);
2503}
2504
Hai Shalom021b0b52019-04-10 11:17:58 -07002505#endif /* CONFIG_DPP2 */
2506
2507
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002508static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2509 const u8 *src,
2510 const u8 *buf, size_t len)
2511{
2512 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002513 const u8 *connector, *trans_id, *status;
2514 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002515#ifdef CONFIG_DPP2
2516 const u8 *version;
2517 u16 version_len;
2518#endif /* CONFIG_DPP2 */
2519 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002520 struct dpp_introduction intro;
2521 struct rsn_pmksa_cache_entry *entry;
2522 struct os_time now;
2523 struct os_reltime rnow;
2524 os_time_t expiry;
2525 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002526 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002527
2528 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2529 MAC2STR(src));
2530 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2531 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2532 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2533 MACSTR " - drop", MAC2STR(src));
2534 return;
2535 }
2536 offchannel_send_action_done(wpa_s);
2537
2538 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2539 if (ssid == wpa_s->dpp_intro_network)
2540 break;
2541 }
2542 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2543 !ssid->dpp_csign) {
2544 wpa_printf(MSG_DEBUG,
2545 "DPP: Profile not found for network introduction");
2546 return;
2547 }
2548
2549 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2550 &trans_id_len);
2551 if (!trans_id || trans_id_len != 1) {
2552 wpa_printf(MSG_DEBUG,
2553 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002554 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2555 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002556 goto fail;
2557 }
2558 if (trans_id[0] != TRANSACTION_ID) {
2559 wpa_printf(MSG_DEBUG,
2560 "DPP: Ignore frame with unexpected Transaction ID %u",
2561 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002562 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2563 " fail=transaction_id_mismatch", MAC2STR(src));
2564 goto fail;
2565 }
2566
2567 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2568 if (!status || status_len != 1) {
2569 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2570 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2571 " fail=missing_status", MAC2STR(src));
2572 goto fail;
2573 }
2574 if (status[0] != DPP_STATUS_OK) {
2575 wpa_printf(MSG_DEBUG,
2576 "DPP: Peer rejected network introduction: Status %u",
2577 status[0]);
2578 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2579 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002580#ifdef CONFIG_DPP2
2581 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2582#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002583 goto fail;
2584 }
2585
2586 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2587 if (!connector) {
2588 wpa_printf(MSG_DEBUG,
2589 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002590 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2591 " fail=missing_connector", MAC2STR(src));
2592 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002593 }
2594
Roshan Pius3a1667e2018-07-03 15:17:14 -07002595 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2596 ssid->dpp_netaccesskey,
2597 ssid->dpp_netaccesskey_len,
2598 ssid->dpp_csign,
2599 ssid->dpp_csign_len,
2600 connector, connector_len, &expiry);
2601 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002602 wpa_printf(MSG_INFO,
2603 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002604 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2605 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002606#ifdef CONFIG_DPP2
2607 wpas_dpp_send_conn_status_result(wpa_s, res);
2608#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002609 goto fail;
2610 }
2611
2612 entry = os_zalloc(sizeof(*entry));
2613 if (!entry)
2614 goto fail;
2615 os_memcpy(entry->aa, src, ETH_ALEN);
2616 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2617 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2618 entry->pmk_len = intro.pmk_len;
2619 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002620#ifdef CONFIG_DPP2
2621 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2622 &version_len);
2623 if (version && version_len >= 1)
2624 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002625#ifdef CONFIG_DPP3
2626 if (intro.peer_version && intro.peer_version >= 2 &&
2627 peer_version != intro.peer_version) {
2628 wpa_printf(MSG_INFO,
2629 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2630 intro.peer_version, peer_version);
2631 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2632 goto fail;
2633 }
2634#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002635 entry->dpp_pfs = peer_version >= 2;
2636#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002637 if (expiry) {
2638 os_get_time(&now);
2639 seconds = expiry - now.sec;
2640 } else {
2641 seconds = 86400 * 7;
2642 }
2643 os_get_reltime(&rnow);
2644 entry->expiration = rnow.sec + seconds;
2645 entry->reauth_time = rnow.sec + seconds;
2646 entry->network_ctx = ssid;
2647 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2648
Roshan Pius3a1667e2018-07-03 15:17:14 -07002649 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002650 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002651
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002652 wpa_printf(MSG_DEBUG,
2653 "DPP: Try connection again after successful network introduction");
2654 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2655 wpa_supplicant_cancel_sched_scan(wpa_s);
2656 wpa_supplicant_req_scan(wpa_s, 0, 0);
2657 }
2658fail:
2659 os_memset(&intro, 0, sizeof(intro));
2660}
2661
2662
Roshan Pius3a1667e2018-07-03 15:17:14 -07002663static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2664{
2665 int i, j;
2666
2667 if (!wpa_s->hw.modes)
2668 return -1;
2669
2670 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2671 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2672
2673 for (j = 0; j < mode->num_channels; j++) {
2674 struct hostapd_channel_data *chan = &mode->channels[j];
2675
2676 if (chan->freq != (int) freq)
2677 continue;
2678
2679 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2680 HOSTAPD_CHAN_NO_IR |
2681 HOSTAPD_CHAN_RADAR))
2682 continue;
2683
2684 return 1;
2685 }
2686 }
2687
2688 wpa_printf(MSG_DEBUG,
2689 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2690 freq);
2691
2692 return 0;
2693}
2694
2695
2696static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2697 struct dpp_pkex *pkex)
2698{
2699 if (pkex->freq == 2437)
2700 pkex->freq = 5745;
2701 else if (pkex->freq == 5745)
2702 pkex->freq = 5220;
2703 else if (pkex->freq == 5220)
2704 pkex->freq = 60480;
2705 else
2706 return -1; /* no more channels to try */
2707
2708 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2709 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2710 pkex->freq);
2711 return 0;
2712 }
2713
2714 /* Could not use this channel - try the next one */
2715 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2716}
2717
2718
Hai Shaloma20dcd72022-02-04 13:43:00 -08002719#ifdef CONFIG_DPP2
2720static int wpas_dpp_pkex_done(void *ctx, void *conn,
2721 struct dpp_bootstrap_info *peer_bi)
2722{
2723 struct wpa_supplicant *wpa_s = ctx;
2724 const char *cmd = wpa_s->dpp_pkex_auth_cmd;
2725 const char *pos;
2726 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2727 struct dpp_bootstrap_info *own_bi = NULL;
2728 struct dpp_authentication *auth;
2729
2730 if (!cmd)
2731 cmd = "";
2732 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
2733 cmd);
2734
2735 pos = os_strstr(cmd, " own=");
2736 if (pos) {
2737 pos += 5;
2738 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
2739 if (!own_bi) {
2740 wpa_printf(MSG_INFO,
2741 "DPP: Could not find bootstrapping info for the identified local entry");
2742 return -1;
2743 }
2744
2745 if (peer_bi->curve != own_bi->curve) {
2746 wpa_printf(MSG_INFO,
2747 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
2748 peer_bi->curve->name, own_bi->curve->name);
2749 return -1;
2750 }
2751 }
2752
2753 pos = os_strstr(cmd, " role=");
2754 if (pos) {
2755 pos += 6;
2756 if (os_strncmp(pos, "configurator", 12) == 0)
2757 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2758 else if (os_strncmp(pos, "enrollee", 8) == 0)
2759 allowed_roles = DPP_CAPAB_ENROLLEE;
2760 else if (os_strncmp(pos, "either", 6) == 0)
2761 allowed_roles = DPP_CAPAB_CONFIGURATOR |
2762 DPP_CAPAB_ENROLLEE;
2763 else
2764 return -1;
2765 }
2766
2767 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
2768 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
2769 if (!auth)
2770 return -1;
2771
2772 wpas_dpp_set_testing_options(wpa_s, auth);
2773 if (dpp_set_configurator(auth, cmd) < 0) {
2774 dpp_auth_deinit(auth);
2775 return -1;
2776 }
2777
2778 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
2779 DPP_NETROLE_STA, wpas_dpp_process_conf_obj,
2780 wpas_dpp_tcp_msg_sent);
2781}
2782#endif /* CONFIG_DPP2 */
2783
2784
Hai Shaloma20dcd72022-02-04 13:43:00 -08002785static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07002786 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002787 const struct hostapd_ip_addr *ipaddr,
2788 int tcp_port)
2789{
2790 struct dpp_pkex *pkex;
2791 struct wpabuf *msg;
2792 unsigned int wait_time;
2793 bool v2 = ver != PKEX_VER_ONLY_1;
2794
2795 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
2796 dpp_pkex_free(wpa_s->dpp_pkex);
2797 wpa_s->dpp_pkex = NULL;
2798 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
2799 wpa_s->dpp_pkex_identifier,
2800 wpa_s->dpp_pkex_code, v2);
2801 if (!pkex)
2802 return -1;
2803 pkex->forced_ver = ver != PKEX_VER_AUTO;
2804
2805 if (ipaddr) {
2806#ifdef CONFIG_DPP2
2807 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
2808 wpa_s, wpa_s, wpas_dpp_pkex_done);
2809#else /* CONFIG_DPP2 */
2810 return -1;
2811#endif /* CONFIG_DPP2 */
2812 }
2813
2814 wpa_s->dpp_pkex = pkex;
2815 msg = pkex->exchange_req;
2816 wait_time = wpa_s->max_remain_on_chan;
2817 if (wait_time > 2000)
2818 wait_time = 2000;
2819 pkex->freq = 2437;
2820 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2821 " freq=%u type=%d",
2822 MAC2STR(broadcast), pkex->freq,
2823 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2824 DPP_PA_PKEX_V1_EXCHANGE_REQ);
2825 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2826 wpa_s->own_addr, broadcast,
2827 wpabuf_head(msg), wpabuf_len(msg),
2828 wait_time, wpas_dpp_tx_pkex_status, 0);
2829 if (wait_time == 0)
2830 wait_time = 2000;
2831 pkex->exch_req_wait_time = wait_time;
2832 pkex->exch_req_tries = 1;
2833
2834 return 0;
2835}
2836
2837
Roshan Pius3a1667e2018-07-03 15:17:14 -07002838static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
2839{
2840 struct wpa_supplicant *wpa_s = eloop_ctx;
2841 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2842
2843 if (!pkex || !pkex->exchange_req)
2844 return;
2845 if (pkex->exch_req_tries >= 5) {
2846 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002847#ifdef CONFIG_DPP3
2848 if (pkex->v2 && !pkex->forced_ver) {
2849 wpa_printf(MSG_DEBUG,
2850 "DPP: Fall back to PKEXv1");
2851 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
2852 NULL, 0);
2853 return;
2854 }
2855#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002856 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2857 "No response from PKEX peer");
2858 dpp_pkex_free(pkex);
2859 wpa_s->dpp_pkex = NULL;
2860 return;
2861 }
2862 pkex->exch_req_tries = 0;
2863 }
2864
2865 pkex->exch_req_tries++;
2866 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
2867 pkex->exch_req_tries);
2868 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08002869 MAC2STR(broadcast), pkex->freq,
2870 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2871 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002872 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2873 wpa_s->own_addr, broadcast,
2874 wpabuf_head(pkex->exchange_req),
2875 wpabuf_len(pkex->exchange_req),
2876 pkex->exch_req_wait_time,
2877 wpas_dpp_tx_pkex_status, 0);
2878}
2879
2880
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002881static void
2882wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
2883 unsigned int freq, const u8 *dst,
2884 const u8 *src, const u8 *bssid,
2885 const u8 *data, size_t data_len,
2886 enum offchannel_send_action_result result)
2887{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002888 const char *res_txt;
2889 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2890
2891 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2892 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2893 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002894 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2895 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002896 freq, MAC2STR(dst), res_txt);
2897 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2898 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
2899
2900 if (!pkex) {
2901 wpa_printf(MSG_DEBUG,
2902 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
2903 return;
2904 }
2905
2906 if (pkex->failed) {
2907 wpa_printf(MSG_DEBUG,
2908 "DPP: Terminate PKEX exchange due to an earlier error");
2909 if (pkex->t > pkex->own_bi->pkex_t)
2910 pkex->own_bi->pkex_t = pkex->t;
2911 dpp_pkex_free(pkex);
2912 wpa_s->dpp_pkex = NULL;
2913 return;
2914 }
2915
2916 if (pkex->exch_req_wait_time && pkex->exchange_req) {
2917 /* Wait for PKEX Exchange Response frame and retry request if
2918 * no response is seen. */
2919 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
2920 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
2921 (pkex->exch_req_wait_time % 1000) * 1000,
2922 wpas_dpp_pkex_retry_timeout, wpa_s,
2923 NULL);
2924 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002925}
2926
2927
2928static void
2929wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002930 const u8 *buf, size_t len, unsigned int freq,
2931 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002932{
2933 struct wpabuf *msg;
2934 unsigned int wait_time;
2935
2936 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
2937 MAC2STR(src));
2938
Sunil Ravia04bd252022-05-02 22:54:18 -07002939 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
2940 wpa_printf(MSG_DEBUG,
2941 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
2942 return;
2943 }
2944 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
2945 wpa_printf(MSG_DEBUG,
2946 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
2947 return;
2948 }
2949
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002950 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2951 * values here */
2952
2953 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
2954 wpa_printf(MSG_DEBUG,
2955 "DPP: No PKEX code configured - ignore request");
2956 return;
2957 }
2958
2959 if (wpa_s->dpp_pkex) {
2960 /* TODO: Support parallel operations */
2961 wpa_printf(MSG_DEBUG,
2962 "DPP: Already in PKEX session - ignore new request");
2963 return;
2964 }
2965
Roshan Pius3a1667e2018-07-03 15:17:14 -07002966 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002967 wpa_s->own_addr, src,
2968 wpa_s->dpp_pkex_identifier,
2969 wpa_s->dpp_pkex_code,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002970 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002971 if (!wpa_s->dpp_pkex) {
2972 wpa_printf(MSG_DEBUG,
2973 "DPP: Failed to process the request - ignore it");
2974 return;
2975 }
2976
Sunil Ravia04bd252022-05-02 22:54:18 -07002977 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002978 msg = wpa_s->dpp_pkex->exchange_resp;
2979 wait_time = wpa_s->max_remain_on_chan;
2980 if (wait_time > 2000)
2981 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002982 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2983 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002984 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2985 broadcast,
2986 wpabuf_head(msg), wpabuf_len(msg),
2987 wait_time, wpas_dpp_tx_pkex_status, 0);
2988}
2989
2990
2991static void
2992wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2993 const u8 *buf, size_t len, unsigned int freq)
2994{
2995 struct wpabuf *msg;
2996 unsigned int wait_time;
2997
2998 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2999 MAC2STR(src));
3000
3001 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3002 * values here */
3003
3004 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3005 wpa_s->dpp_pkex->exchange_done) {
3006 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3007 return;
3008 }
3009
Roshan Pius3a1667e2018-07-03 15:17:14 -07003010 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3011 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3012
3013 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003014 if (!msg) {
3015 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3016 return;
3017 }
3018
3019 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3020 MAC2STR(src));
3021
3022 wait_time = wpa_s->max_remain_on_chan;
3023 if (wait_time > 2000)
3024 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003025 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3026 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003027 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3028 broadcast,
3029 wpabuf_head(msg), wpabuf_len(msg),
3030 wait_time, wpas_dpp_tx_pkex_status, 0);
3031 wpabuf_free(msg);
3032}
3033
3034
Roshan Pius3a1667e2018-07-03 15:17:14 -07003035static struct dpp_bootstrap_info *
3036wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3037 unsigned int freq)
3038{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003039 struct dpp_bootstrap_info *bi;
3040
Hai Shalom021b0b52019-04-10 11:17:58 -07003041 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003042 if (!bi)
3043 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003044 wpa_s->dpp_pkex = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003045 return bi;
3046}
3047
3048
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003049static void
3050wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3051 const u8 *hdr, const u8 *buf, size_t len,
3052 unsigned int freq)
3053{
3054 struct wpabuf *msg;
3055 unsigned int wait_time;
3056 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003057
3058 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3059 MAC2STR(src));
3060
3061 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3062 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3063 return;
3064 }
3065
3066 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3067 if (!msg) {
3068 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003069 if (pkex->failed) {
3070 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3071 if (pkex->t > pkex->own_bi->pkex_t)
3072 pkex->own_bi->pkex_t = pkex->t;
3073 dpp_pkex_free(wpa_s->dpp_pkex);
3074 wpa_s->dpp_pkex = NULL;
3075 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003076 return;
3077 }
3078
3079 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3080 MACSTR, MAC2STR(src));
3081
3082 wait_time = wpa_s->max_remain_on_chan;
3083 if (wait_time > 2000)
3084 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003085 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3086 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003087 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3088 broadcast,
3089 wpabuf_head(msg), wpabuf_len(msg),
3090 wait_time, wpas_dpp_tx_pkex_status, 0);
3091 wpabuf_free(msg);
3092
Roshan Pius3a1667e2018-07-03 15:17:14 -07003093 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003094 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003095}
3096
3097
3098static void
3099wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3100 const u8 *hdr, const u8 *buf, size_t len,
3101 unsigned int freq)
3102{
3103 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003104 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003105 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3106 char cmd[500];
3107
3108 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3109 MAC2STR(src));
3110
3111 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3112 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3113 return;
3114 }
3115
3116 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3117 if (res < 0) {
3118 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3119 return;
3120 }
3121
Roshan Pius3a1667e2018-07-03 15:17:14 -07003122 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003123 if (!bi)
3124 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003125
3126 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3127 bi->id,
3128 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3129 wpa_printf(MSG_DEBUG,
3130 "DPP: Start authentication after PKEX with parameters: %s",
3131 cmd);
3132 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3133 wpa_printf(MSG_DEBUG,
3134 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003135 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003136 return;
3137 }
3138}
3139
3140
3141void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
3142 const u8 *buf, size_t len, unsigned int freq)
3143{
3144 u8 crypto_suite;
3145 enum dpp_public_action_frame_type type;
3146 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003147 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003148
3149 if (len < DPP_HDR_LEN)
3150 return;
3151 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
3152 return;
Sunil8cd6f4d2022-06-28 18:40:46 +00003153#ifdef CONFIG_TESTING_OPTIONS
3154 if (wpa_s->dpp_discard_public_action) {
3155 wpa_printf(MSG_DEBUG,
3156 "TESTING: Discard received DPP Public Action frame");
3157 return;
3158 }
3159#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003160 hdr = buf;
3161 buf += 4;
3162 len -= 4;
3163 crypto_suite = *buf++;
3164 type = *buf++;
3165 len -= 2;
3166
3167 wpa_printf(MSG_DEBUG,
3168 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
3169 MACSTR " freq=%u",
3170 crypto_suite, type, MAC2STR(src), freq);
3171 if (crypto_suite != 1) {
3172 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
3173 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003174 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3175 " freq=%u type=%d ignore=unsupported-crypto-suite",
3176 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003177 return;
3178 }
3179 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003180 if (dpp_check_attrs(buf, len) < 0) {
3181 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3182 " freq=%u type=%d ignore=invalid-attributes",
3183 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003184 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003185 }
3186 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
3187 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003188
3189 switch (type) {
3190 case DPP_PA_AUTHENTICATION_REQ:
3191 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
3192 break;
3193 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07003194 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003195 break;
3196 case DPP_PA_AUTHENTICATION_CONF:
3197 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
3198 break;
3199 case DPP_PA_PEER_DISCOVERY_RESP:
3200 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
3201 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003202#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003203 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003204 /* This is for PKEXv2, but for now, process only with
3205 * CONFIG_DPP3 to avoid issues with a capability that has not
3206 * been tested with other implementations. */
3207 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
3208 break;
3209#endif /* CONFIG_DPP3 */
3210 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
3211 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
3212 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003213 break;
3214 case DPP_PA_PKEX_EXCHANGE_RESP:
3215 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
3216 break;
3217 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
3218 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
3219 freq);
3220 break;
3221 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
3222 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
3223 freq);
3224 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003225#ifdef CONFIG_DPP2
3226 case DPP_PA_CONFIGURATION_RESULT:
3227 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
3228 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003229 case DPP_PA_CONNECTION_STATUS_RESULT:
3230 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
3231 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07003232 case DPP_PA_PRESENCE_ANNOUNCEMENT:
3233 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
3234 freq);
3235 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003236 case DPP_PA_RECONFIG_ANNOUNCEMENT:
3237 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
3238 freq);
3239 break;
3240 case DPP_PA_RECONFIG_AUTH_REQ:
3241 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
3242 break;
3243 case DPP_PA_RECONFIG_AUTH_RESP:
3244 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
3245 break;
3246 case DPP_PA_RECONFIG_AUTH_CONF:
3247 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
3248 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003249#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003250 default:
3251 wpa_printf(MSG_DEBUG,
3252 "DPP: Ignored unsupported frame subtype %d", type);
3253 break;
3254 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003255
3256 if (wpa_s->dpp_pkex)
3257 pkex_t = wpa_s->dpp_pkex->t;
3258 else if (wpa_s->dpp_pkex_bi)
3259 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
3260 else
3261 pkex_t = 0;
3262 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
3263 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
3264 wpas_dpp_pkex_remove(wpa_s, "*");
3265 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003266}
3267
3268
Hai Shaloma20dcd72022-02-04 13:43:00 -08003269static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
3270 void *timeout_ctx)
3271{
3272 struct wpa_supplicant *wpa_s = eloop_ctx;
3273 struct dpp_authentication *auth = wpa_s->dpp_auth;
3274
3275 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
3276 return;
3277
3278 wpa_printf(MSG_DEBUG,
3279 "DPP: No configuration available from upper layers - send initial response with comeback delay");
3280 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
3281 500);
3282}
3283
3284
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003285static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07003286wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003287 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003288{
3289 struct wpa_supplicant *wpa_s = ctx;
3290 struct dpp_authentication *auth = wpa_s->dpp_auth;
3291 struct wpabuf *resp;
3292
3293 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
3294 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003295 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003296 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
3297 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
3298 return NULL;
3299 }
Hai Shalomc3565922019-10-28 11:58:20 -07003300
3301 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
3302 wpa_printf(MSG_DEBUG,
3303 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
3304 /* wpas_dpp_auth_success() would normally have been called from
3305 * TX status handler, but since there was no such handler call
3306 * yet, simply send out the event message and proceed with
3307 * exchange. */
3308 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
3309 wpa_s->dpp_auth_ok_on_ack = 0;
3310 }
3311
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003312 wpa_hexdump(MSG_DEBUG,
3313 "DPP: Received Configuration Request (GAS Query Request)",
3314 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003315 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
3316 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003317 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003318
Hai Shaloma20dcd72022-02-04 13:43:00 -08003319 auth->gas_server_ctx = resp_ctx;
3320
Hai Shalom899fcc72020-10-19 14:38:18 -07003321#ifdef CONFIG_DPP2
3322 if (!resp && auth->waiting_cert) {
3323 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003324 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003325 *comeback_delay = 500;
3326 return NULL;
3327 }
3328#endif /* CONFIG_DPP2 */
3329
Hai Shaloma20dcd72022-02-04 13:43:00 -08003330 if (!resp && auth->waiting_config &&
3331 (auth->peer_bi || auth->tmp_peer_bi)) {
3332 char *buf = NULL, *name = "";
3333 char band[200], *pos, *end;
3334 int i, res, *opclass = auth->e_band_support;
3335 char *mud_url = "N/A";
3336
3337 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
3338 auth->config_resp_ctx = resp_ctx;
3339 *comeback_delay = -1;
3340 if (auth->e_name) {
3341 size_t len = os_strlen(auth->e_name);
3342
3343 buf = os_malloc(len * 4 + 1);
3344 if (buf) {
3345 printf_encode(buf, len * 4 + 1,
3346 (const u8 *) auth->e_name, len);
3347 name = buf;
3348 }
3349 }
3350 band[0] = '\0';
3351 pos = band;
3352 end = band + sizeof(band);
3353 for (i = 0; opclass && opclass[i]; i++) {
3354 res = os_snprintf(pos, end - pos, "%s%d",
3355 pos == band ? "" : ",", opclass[i]);
3356 if (os_snprintf_error(end - pos, res)) {
3357 *pos = '\0';
3358 break;
3359 }
3360 pos += res;
3361 }
3362 if (auth->e_mud_url) {
3363 size_t len = os_strlen(auth->e_mud_url);
3364
3365 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
3366 mud_url = auth->e_mud_url;
3367 }
3368 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
3369 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
3370 auth->peer_bi ? auth->peer_bi->id :
3371 auth->tmp_peer_bi->id, MAC2STR(sa),
3372 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
3373 os_free(buf);
3374
3375 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
3376 NULL);
3377 eloop_register_timeout(0, 50000,
3378 wpas_dpp_gas_initial_resp_timeout, wpa_s,
3379 NULL);
3380 return NULL;
3381 }
3382
Sunil Ravia04bd252022-05-02 22:54:18 -07003383 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08003384 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003385 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08003386 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07003387 dpp_auth_deinit(wpa_s->dpp_auth);
3388 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08003389 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003390 return resp;
3391}
3392
3393
3394static void
3395wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
3396{
3397 struct wpa_supplicant *wpa_s = ctx;
3398 struct dpp_authentication *auth = wpa_s->dpp_auth;
3399
3400 if (!auth) {
3401 wpabuf_free(resp);
3402 return;
3403 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003404 if (auth->conf_resp != resp) {
3405 wpa_printf(MSG_DEBUG,
3406 "DPP: Ignore GAS status report (ok=%d) for unknown response",
3407 ok);
3408 wpabuf_free(resp);
3409 return;
3410 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003411
Hai Shalom899fcc72020-10-19 14:38:18 -07003412#ifdef CONFIG_DPP2
3413 if (auth->waiting_csr && ok) {
3414 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
3415 wpabuf_free(resp);
3416 return;
3417 }
3418#endif /* CONFIG_DPP2 */
3419
Sunil Ravia04bd252022-05-02 22:54:18 -07003420#ifdef CONFIG_DPP3
3421 if (auth->waiting_new_key && ok) {
3422 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
3423 wpabuf_free(resp);
3424 return;
3425 }
3426#endif /* CONFIG_DPP3 */
3427
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003428 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
3429 ok);
3430 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003431 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003432 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003433#ifdef CONFIG_DPP2
3434 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08003435 auth->conf_resp_status == DPP_STATUS_OK &&
3436 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003437 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08003438 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003439 auth->waiting_conf_result = 1;
3440 auth->conf_resp = NULL;
3441 wpabuf_free(resp);
3442 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
3443 wpa_s, NULL);
3444 eloop_register_timeout(2, 0,
3445 wpas_dpp_config_result_wait_timeout,
3446 wpa_s, NULL);
3447 return;
3448 }
3449#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003450 offchannel_send_action_done(wpa_s);
3451 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003452 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003453 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08003454 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003455 }
3456 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003457 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08003458 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003459 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003460 dpp_auth_deinit(wpa_s->dpp_auth);
3461 wpa_s->dpp_auth = NULL;
3462 wpabuf_free(resp);
3463}
3464
3465
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003466int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
3467{
3468 struct dpp_authentication *auth;
3469 int ret = -1;
3470 char *curve = NULL;
3471
Hai Shalomfdcde762020-04-02 11:19:20 -07003472 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003473 if (!auth)
3474 return -1;
3475
3476 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08003477 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07003478 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07003479 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07003480 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
3481 &auth->conf_obj[0]);
3482 if (!ret)
3483 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003484
3485 dpp_auth_deinit(auth);
3486 os_free(curve);
3487
3488 return ret;
3489}
3490
3491
3492static void
3493wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
3494 unsigned int freq, const u8 *dst,
3495 const u8 *src, const u8 *bssid,
3496 const u8 *data, size_t data_len,
3497 enum offchannel_send_action_result result)
3498{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003499 const char *res_txt;
3500
3501 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3502 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3503 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003504 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3505 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003506 freq, MAC2STR(dst), res_txt);
3507 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3508 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003509 /* TODO: Time out wait for response more quickly in error cases? */
3510}
3511
3512
3513int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3514 struct wpa_bss *bss)
3515{
3516 struct os_time now;
3517 struct wpabuf *msg;
3518 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07003519 const u8 *rsn;
3520 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003521 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003522
3523 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
3524 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07003525 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3526 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
3527 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
3528 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003529 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
3530 return 0; /* PMKSA exists for DPP AKM - continue */
3531
3532 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3533 !ssid->dpp_csign) {
3534 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
3535 "missing %s",
3536 !ssid->dpp_connector ? "Connector" :
3537 (!ssid->dpp_netaccesskey ? "netAccessKey" :
3538 "C-sign-key"));
3539 return -1;
3540 }
3541
3542 os_get_time(&now);
3543
3544 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07003545 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003546 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
3547 "netAccessKey expired");
3548 return -1;
3549 }
3550
3551 wpa_printf(MSG_DEBUG,
3552 "DPP: Starting network introduction protocol to derive PMKSA for "
3553 MACSTR, MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07003554 if (wpa_s->wpa_state == WPA_SCANNING)
3555 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003556
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003557 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3558#ifdef CONFIG_DPP2
3559 len += 5;
3560#endif /* CONFIG_DPP2 */
3561 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003562 if (!msg)
3563 return -1;
3564
Roshan Pius3a1667e2018-07-03 15:17:14 -07003565#ifdef CONFIG_TESTING_OPTIONS
3566 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
3567 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
3568 goto skip_trans_id;
3569 }
3570 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
3571 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
3572 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3573 wpabuf_put_le16(msg, 0);
3574 goto skip_trans_id;
3575 }
3576#endif /* CONFIG_TESTING_OPTIONS */
3577
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003578 /* Transaction ID */
3579 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3580 wpabuf_put_le16(msg, 1);
3581 wpabuf_put_u8(msg, TRANSACTION_ID);
3582
Roshan Pius3a1667e2018-07-03 15:17:14 -07003583#ifdef CONFIG_TESTING_OPTIONS
3584skip_trans_id:
3585 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
3586 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
3587 goto skip_connector;
3588 }
3589 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
3590 char *connector;
3591
3592 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
3593 connector = dpp_corrupt_connector_signature(
3594 ssid->dpp_connector);
3595 if (!connector) {
3596 wpabuf_free(msg);
3597 return -1;
3598 }
3599 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
3600 wpabuf_put_le16(msg, os_strlen(connector));
3601 wpabuf_put_str(msg, connector);
3602 os_free(connector);
3603 goto skip_connector;
3604 }
3605#endif /* CONFIG_TESTING_OPTIONS */
3606
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003607 /* DPP Connector */
3608 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
3609 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
3610 wpabuf_put_str(msg, ssid->dpp_connector);
3611
Roshan Pius3a1667e2018-07-03 15:17:14 -07003612#ifdef CONFIG_TESTING_OPTIONS
3613skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003614 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
3615 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
3616 goto skip_proto_ver;
3617 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003618#endif /* CONFIG_TESTING_OPTIONS */
3619
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003620#ifdef CONFIG_DPP2
3621 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003622 u8 ver = DPP_VERSION;
3623#ifdef CONFIG_DPP3
3624 int conn_ver;
3625
3626 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3627 if (conn_ver > 0 && ver != conn_ver) {
3628 wpa_printf(MSG_DEBUG,
3629 "DPP: Use Connector version %d instead of current protocol version %d",
3630 conn_ver, ver);
3631 ver = conn_ver;
3632 }
3633#endif /* CONFIG_DPP3 */
3634
3635#ifdef CONFIG_TESTING_OPTIONS
3636 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
3637 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
3638 ver = 1;
3639 }
3640#endif /* CONFIG_TESTING_OPTIONS */
3641
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003642 /* Protocol Version */
3643 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
3644 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003645 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003646 }
3647#endif /* CONFIG_DPP2 */
3648
Hai Shaloma20dcd72022-02-04 13:43:00 -08003649#ifdef CONFIG_TESTING_OPTIONS
3650skip_proto_ver:
3651#endif /* CONFIG_TESTING_OPTIONS */
3652
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003653 /* TODO: Timeout on AP response */
3654 wait_time = wpa_s->max_remain_on_chan;
3655 if (wait_time > 2000)
3656 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003657 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3658 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003659 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
3660 broadcast,
3661 wpabuf_head(msg), wpabuf_len(msg),
3662 wait_time, wpas_dpp_tx_introduction_status, 0);
3663 wpabuf_free(msg);
3664
3665 /* Request this connection attempt to terminate - new one will be
3666 * started when network introduction protocol completes */
3667 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
3668 wpa_s->dpp_intro_network = ssid;
3669 return 1;
3670}
3671
3672
3673int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
3674{
3675 struct dpp_bootstrap_info *own_bi;
3676 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07003677#ifdef CONFIG_DPP3
3678 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
3679#else /* CONFIG_DPP3 */
3680 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
3681#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003682 int tcp_port = DPP_TCP_PORT;
3683 struct hostapd_ip_addr *ipaddr = NULL;
3684#ifdef CONFIG_DPP2
3685 struct hostapd_ip_addr ipaddr_buf;
3686 char *addr;
3687
3688 pos = os_strstr(cmd, " tcp_port=");
3689 if (pos) {
3690 pos += 10;
3691 tcp_port = atoi(pos);
3692 }
3693
3694 addr = get_param(cmd, " tcp_addr=");
3695 if (addr) {
3696 int res;
3697
3698 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
3699 os_free(addr);
3700 if (res)
3701 return -1;
3702 ipaddr = &ipaddr_buf;
3703 }
3704#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003705
3706 pos = os_strstr(cmd, " own=");
3707 if (!pos)
3708 return -1;
3709 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07003710 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003711 if (!own_bi) {
3712 wpa_printf(MSG_DEBUG,
3713 "DPP: Identified bootstrap info not found");
3714 return -1;
3715 }
3716 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
3717 wpa_printf(MSG_DEBUG,
3718 "DPP: Identified bootstrap info not for PKEX");
3719 return -1;
3720 }
3721 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003722 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003723
3724 os_free(wpa_s->dpp_pkex_identifier);
3725 wpa_s->dpp_pkex_identifier = NULL;
3726 pos = os_strstr(cmd, " identifier=");
3727 if (pos) {
3728 pos += 12;
3729 end = os_strchr(pos, ' ');
3730 if (!end)
3731 return -1;
3732 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
3733 if (!wpa_s->dpp_pkex_identifier)
3734 return -1;
3735 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
3736 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
3737 }
3738
3739 pos = os_strstr(cmd, " code=");
3740 if (!pos)
3741 return -1;
3742 os_free(wpa_s->dpp_pkex_code);
3743 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
3744 if (!wpa_s->dpp_pkex_code)
3745 return -1;
3746
Sunil Ravia04bd252022-05-02 22:54:18 -07003747 pos = os_strstr(cmd, " ver=");
3748 if (pos) {
3749 int v;
3750
3751 pos += 5;
3752 v = atoi(pos);
3753 if (v == 1)
3754 ver = PKEX_VER_ONLY_1;
3755 else if (v == 2)
3756 ver = PKEX_VER_ONLY_2;
3757 else
3758 return -1;
3759 }
3760 wpa_s->dpp_pkex_ver = ver;
3761
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003762 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08003763 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003764 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003765 } else {
3766#ifdef CONFIG_DPP2
3767 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
3768 wpa_s->dpp_pkex_code,
3769 wpa_s->dpp_pkex_identifier);
3770#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003771 }
3772
3773 /* TODO: Support multiple PKEX info entries */
3774
3775 os_free(wpa_s->dpp_pkex_auth_cmd);
3776 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
3777
3778 return 1;
3779}
3780
3781
3782int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
3783{
3784 unsigned int id_val;
3785
3786 if (os_strcmp(id, "*") == 0) {
3787 id_val = 0;
3788 } else {
3789 id_val = atoi(id);
3790 if (id_val == 0)
3791 return -1;
3792 }
3793
3794 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
3795 return -1;
3796
3797 /* TODO: Support multiple PKEX entries */
3798 os_free(wpa_s->dpp_pkex_code);
3799 wpa_s->dpp_pkex_code = NULL;
3800 os_free(wpa_s->dpp_pkex_identifier);
3801 wpa_s->dpp_pkex_identifier = NULL;
3802 os_free(wpa_s->dpp_pkex_auth_cmd);
3803 wpa_s->dpp_pkex_auth_cmd = NULL;
3804 wpa_s->dpp_pkex_bi = NULL;
3805 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
3806 dpp_pkex_free(wpa_s->dpp_pkex);
3807 wpa_s->dpp_pkex = NULL;
3808 return 0;
3809}
3810
3811
Roshan Pius3a1667e2018-07-03 15:17:14 -07003812void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
3813{
Sunil Ravia04bd252022-05-02 22:54:18 -07003814 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07003815 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003816 dpp_auth_deinit(wpa_s->dpp_auth);
3817 wpa_s->dpp_auth = NULL;
3818 dpp_pkex_free(wpa_s->dpp_pkex);
3819 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07003820 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003821 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
3822 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
3823}
3824
3825
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003826int wpas_dpp_init(struct wpa_supplicant *wpa_s)
3827{
Hai Shalom81f62d82019-07-22 12:10:00 -07003828 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003829 u8 adv_proto_id[7];
3830
3831 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
3832 adv_proto_id[1] = 5;
3833 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
3834 adv_proto_id[5] = DPP_OUI_TYPE;
3835 adv_proto_id[6] = 0x01;
3836
3837 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
3838 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
3839 wpas_dpp_gas_status_handler, wpa_s) < 0)
3840 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07003841
3842 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07003843 config.cb_ctx = wpa_s;
3844#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003845 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07003846#endif /* CONFIG_DPP2 */
3847 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07003848 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003849}
3850
3851
3852void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
3853{
3854#ifdef CONFIG_TESTING_OPTIONS
3855 os_free(wpa_s->dpp_config_obj_override);
3856 wpa_s->dpp_config_obj_override = NULL;
3857 os_free(wpa_s->dpp_discovery_override);
3858 wpa_s->dpp_discovery_override = NULL;
3859 os_free(wpa_s->dpp_groups_override);
3860 wpa_s->dpp_groups_override = NULL;
3861 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
3862#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07003863 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003864 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003865 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003866 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003867 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003868 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
3869 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08003870 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
3871 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003872#ifdef CONFIG_DPP2
3873 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07003874 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
3875 wpa_s, NULL);
3876 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003877 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
3878 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07003879 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003880 dpp_pfs_free(wpa_s->dpp_pfs);
3881 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07003882 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07003883 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
3884 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07003885#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003886#ifdef CONFIG_DPP3
3887 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
3888#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003889 offchannel_send_action_done(wpa_s);
3890 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003891 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003892 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003893 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
3894 os_free(wpa_s->dpp_configurator_params);
3895 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07003896 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003897}
Hai Shalom81f62d82019-07-22 12:10:00 -07003898
3899
Hai Shaloma20dcd72022-02-04 13:43:00 -08003900static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
3901 struct dpp_authentication *auth, bool tcp)
3902{
3903 struct wpabuf *resp;
3904
3905 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
3906 auth->e_netrole, true);
3907 if (!resp)
3908 return -1;
3909
3910 if (tcp) {
3911 auth->conf_resp_tcp = resp;
3912 return 0;
3913 }
3914
3915 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
3916 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
3917 resp) < 0) {
3918 wpa_printf(MSG_DEBUG,
3919 "DPP: Could not find pending GAS response");
3920 wpabuf_free(resp);
3921 return -1;
3922 }
3923 auth->conf_resp = resp;
3924 return 0;
3925}
3926
3927
3928int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
3929{
3930 int peer;
3931 const char *pos;
3932 struct dpp_authentication *auth = wpa_s->dpp_auth;
3933 bool tcp = false;
3934
3935 pos = os_strstr(cmd, " peer=");
3936 if (!pos)
3937 return -1;
3938 peer = atoi(pos + 6);
3939#ifdef CONFIG_DPP2
3940 if (!auth || !auth->waiting_config ||
3941 (auth->peer_bi &&
3942 (unsigned int) peer != auth->peer_bi->id)) {
3943 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
3944 tcp = true;
3945 }
3946#endif /* CONFIG_DPP2 */
3947
3948 if (!auth || !auth->waiting_config) {
3949 wpa_printf(MSG_DEBUG,
3950 "DPP: No authentication exchange waiting for configuration information");
3951 return -1;
3952 }
3953
3954 if ((!auth->peer_bi ||
3955 (unsigned int) peer != auth->peer_bi->id) &&
3956 (!auth->tmp_peer_bi ||
3957 (unsigned int) peer != auth->tmp_peer_bi->id)) {
3958 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
3959 return -1;
3960 }
3961
3962 pos = os_strstr(cmd, " comeback=");
3963 if (pos) {
3964 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
3965 NULL);
3966 gas_server_set_comeback_delay(wpa_s->gas_server,
3967 auth->config_resp_ctx,
3968 atoi(pos + 10));
3969 return 0;
3970 }
3971
3972 if (dpp_set_configurator(auth, cmd) < 0)
3973 return -1;
3974
3975 auth->use_config_query = false;
3976 auth->waiting_config = false;
3977 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
3978}
3979
3980
Hai Shalom81f62d82019-07-22 12:10:00 -07003981#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003982
Hai Shalom81f62d82019-07-22 12:10:00 -07003983int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
3984{
3985 struct dpp_controller_config config;
3986 const char *pos;
3987
3988 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003989 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07003990 config.netrole = DPP_NETROLE_STA;
3991 config.msg_ctx = wpa_s;
3992 config.cb_ctx = wpa_s;
3993 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003994 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07003995 if (cmd) {
3996 pos = os_strstr(cmd, " tcp_port=");
3997 if (pos) {
3998 pos += 10;
3999 config.tcp_port = atoi(pos);
4000 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004001
4002 pos = os_strstr(cmd, " role=");
4003 if (pos) {
4004 pos += 6;
4005 if (os_strncmp(pos, "configurator", 12) == 0)
4006 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
4007 else if (os_strncmp(pos, "enrollee", 8) == 0)
4008 config.allowed_roles = DPP_CAPAB_ENROLLEE;
4009 else if (os_strncmp(pos, "either", 6) == 0)
4010 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
4011 DPP_CAPAB_ENROLLEE;
4012 else
4013 return -1;
4014 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004015
4016 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07004017 }
4018 config.configurator_params = wpa_s->dpp_configurator_params;
4019 return dpp_controller_start(wpa_s->dpp, &config);
4020}
Hai Shalomfdcde762020-04-02 11:19:20 -07004021
4022
4023static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
4024
4025static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
4026{
4027 struct wpa_supplicant *wpa_s = eloop_ctx;
4028
4029 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
4030 offchannel_send_action_done(wpa_s);
4031 wpas_dpp_chirp_next(wpa_s, NULL);
4032}
4033
4034
4035static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
4036 unsigned int freq, const u8 *dst,
4037 const u8 *src, const u8 *bssid,
4038 const u8 *data, size_t data_len,
4039 enum offchannel_send_action_result result)
4040{
4041 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
4042 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
4043 wpa_s->dpp_chirp_freq);
4044 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
4045 wpa_s, NULL) < 0)
4046 wpas_dpp_chirp_stop(wpa_s);
4047 return;
4048 }
4049
4050 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
4051 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
4052 wpa_s, NULL) < 0)
4053 wpas_dpp_chirp_stop(wpa_s);
4054}
4055
4056
4057static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
4058{
Hai Shalom899fcc72020-10-19 14:38:18 -07004059 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004060 int type;
4061
4062 msg = wpa_s->dpp_presence_announcement;
4063 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
4064 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07004065 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
4066
4067 if (ssid && wpa_s->dpp_reconfig_id &&
4068 wpa_config_get_network(wpa_s->conf,
4069 wpa_s->dpp_reconfig_ssid_id) ==
4070 ssid) {
4071 announce = dpp_build_reconfig_announcement(
4072 ssid->dpp_csign,
4073 ssid->dpp_csign_len,
4074 ssid->dpp_netaccesskey,
4075 ssid->dpp_netaccesskey_len,
4076 wpa_s->dpp_reconfig_id);
4077 msg = announce;
4078 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004079 if (!msg)
4080 return;
4081 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
4082 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004083 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
4084 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004085 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07004086 if (offchannel_send_action(
4087 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
4088 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004089 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07004090 2000, wpas_dpp_chirp_tx_status, 0) < 0)
4091 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004092
4093 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07004094}
4095
4096
4097static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
4098 struct wpa_scan_results *scan_res)
4099{
4100 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
4101 unsigned int i;
4102 struct hostapd_hw_modes *mode;
4103 int c;
4104 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004105 bool chan6 = wpa_s->hw.modes == NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004106
Hai Shalom899fcc72020-10-19 14:38:18 -07004107 if (!bi && !wpa_s->dpp_reconfig_ssid)
Hai Shalomfdcde762020-04-02 11:19:20 -07004108 return;
4109
4110 wpa_s->dpp_chirp_scan_done = 1;
4111
4112 os_free(wpa_s->dpp_chirp_freqs);
4113 wpa_s->dpp_chirp_freqs = NULL;
4114
4115 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004116 if (bi) {
4117 for (i = 0; i < bi->num_freq; i++)
4118 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
4119 bi->freq[i]);
4120 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004121
4122 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07004123 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004124 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07004125 if (mode) {
4126 for (c = 0; c < mode->num_channels; c++) {
4127 struct hostapd_channel_data *chan = &mode->channels[c];
4128
4129 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
4130 chan->freq != 2437)
4131 continue;
4132 chan6 = true;
4133 break;
4134 }
4135 }
4136 if (chan6)
4137 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07004138
4139 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004140 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07004141 if (mode) {
4142 int chan44 = 0, chan149 = 0;
4143
4144 for (c = 0; c < mode->num_channels; c++) {
4145 struct hostapd_channel_data *chan = &mode->channels[c];
4146
4147 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
4148 HOSTAPD_CHAN_RADAR))
4149 continue;
4150 if (chan->freq == 5220)
4151 chan44 = 1;
4152 if (chan->freq == 5745)
4153 chan149 = 1;
4154 }
4155 if (chan149)
4156 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745);
4157 else if (chan44)
4158 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220);
4159 }
4160
4161 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004162 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07004163 if (mode) {
4164 for (c = 0; c < mode->num_channels; c++) {
4165 struct hostapd_channel_data *chan = &mode->channels[c];
4166
4167 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
4168 HOSTAPD_CHAN_RADAR)) ||
4169 chan->freq != 60480)
4170 continue;
4171 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480);
4172 break;
4173 }
4174 }
4175
4176 /* Add channels from scan results for APs that advertise Configurator
4177 * Connectivity element */
4178 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4179 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
4180 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
4181 bss->freq);
4182 }
4183
4184 if (!wpa_s->dpp_chirp_freqs ||
4185 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
4186 wpas_dpp_chirp_stop(wpa_s);
4187}
4188
4189
4190static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
4191{
4192 struct wpa_supplicant *wpa_s = eloop_ctx;
4193 int i;
4194
4195 if (wpa_s->dpp_chirp_listen)
4196 wpas_dpp_listen_stop(wpa_s);
4197
4198 if (wpa_s->dpp_chirp_freq == 0) {
4199 if (wpa_s->dpp_chirp_round % 4 == 0 &&
4200 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08004201 if (wpas_scan_scheduled(wpa_s)) {
4202 wpa_printf(MSG_DEBUG,
4203 "DPP: Deferring chirp scan because another scan is planned already");
4204 if (eloop_register_timeout(1, 0,
4205 wpas_dpp_chirp_next,
4206 wpa_s, NULL) < 0) {
4207 wpas_dpp_chirp_stop(wpa_s);
4208 return;
4209 }
4210 return;
4211 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004212 wpa_printf(MSG_DEBUG,
4213 "DPP: Update channel list for chirping");
4214 wpa_s->scan_req = MANUAL_SCAN_REQ;
4215 wpa_s->scan_res_handler =
4216 wpas_dpp_chirp_scan_res_handler;
4217 wpa_supplicant_req_scan(wpa_s, 0, 0);
4218 return;
4219 }
4220 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
4221 wpa_s->dpp_chirp_round++;
4222 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
4223 wpa_s->dpp_chirp_round);
4224 } else {
4225 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
4226 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
4227 break;
4228 if (!wpa_s->dpp_chirp_freqs[i]) {
4229 wpa_printf(MSG_DEBUG,
4230 "DPP: Previous chirp freq %d not found",
4231 wpa_s->dpp_chirp_freq);
4232 return;
4233 }
4234 i++;
4235 if (wpa_s->dpp_chirp_freqs[i]) {
4236 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
4237 } else {
4238 wpa_s->dpp_chirp_iter--;
4239 if (wpa_s->dpp_chirp_iter <= 0) {
4240 wpa_printf(MSG_DEBUG,
4241 "DPP: Chirping iterations completed");
4242 wpas_dpp_chirp_stop(wpa_s);
4243 return;
4244 }
4245 wpa_s->dpp_chirp_freq = 0;
4246 wpa_s->dpp_chirp_scan_done = 0;
4247 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
4248 wpa_s, NULL) < 0) {
4249 wpas_dpp_chirp_stop(wpa_s);
4250 return;
4251 }
4252 if (wpa_s->dpp_chirp_listen) {
4253 wpa_printf(MSG_DEBUG,
4254 "DPP: Listen on %d MHz during chirp 30 second wait",
4255 wpa_s->dpp_chirp_listen);
4256 wpas_dpp_listen_start(wpa_s,
4257 wpa_s->dpp_chirp_listen);
4258 } else {
4259 wpa_printf(MSG_DEBUG,
4260 "DPP: Wait 30 seconds before starting the next chirping round");
4261 }
4262 return;
4263 }
4264 }
4265
4266 wpas_dpp_chirp_start(wpa_s);
4267}
4268
4269
4270int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
4271{
4272 const char *pos;
4273 int iter = 1, listen_freq = 0;
4274 struct dpp_bootstrap_info *bi;
4275
4276 pos = os_strstr(cmd, " own=");
4277 if (!pos)
4278 return -1;
4279 pos += 5;
4280 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
4281 if (!bi) {
4282 wpa_printf(MSG_DEBUG,
4283 "DPP: Identified bootstrap info not found");
4284 return -1;
4285 }
4286
4287 pos = os_strstr(cmd, " iter=");
4288 if (pos) {
4289 iter = atoi(pos + 6);
4290 if (iter <= 0)
4291 return -1;
4292 }
4293
4294 pos = os_strstr(cmd, " listen=");
4295 if (pos) {
4296 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004297 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07004298 return -1;
4299 }
4300
4301 wpas_dpp_chirp_stop(wpa_s);
4302 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07004303 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07004304 wpa_s->dpp_qr_mutual = 0;
4305 wpa_s->dpp_chirp_bi = bi;
4306 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
4307 if (!wpa_s->dpp_presence_announcement)
4308 return -1;
4309 wpa_s->dpp_chirp_iter = iter;
4310 wpa_s->dpp_chirp_round = 0;
4311 wpa_s->dpp_chirp_scan_done = 0;
4312 wpa_s->dpp_chirp_listen = listen_freq;
4313
4314 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
4315}
4316
4317
4318void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
4319{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004320 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07004321 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004322 offchannel_send_action_done(wpa_s);
4323 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
4324 }
4325 wpa_s->dpp_chirp_bi = NULL;
4326 wpabuf_free(wpa_s->dpp_presence_announcement);
4327 wpa_s->dpp_presence_announcement = NULL;
4328 if (wpa_s->dpp_chirp_listen)
4329 wpas_dpp_listen_stop(wpa_s);
4330 wpa_s->dpp_chirp_listen = 0;
4331 wpa_s->dpp_chirp_freq = 0;
4332 os_free(wpa_s->dpp_chirp_freqs);
4333 wpa_s->dpp_chirp_freqs = NULL;
4334 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
4335 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
4336 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
4337 wpas_abort_ongoing_scan(wpa_s);
4338 wpa_s->scan_res_handler = NULL;
4339 }
4340}
4341
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004342
Hai Shalom899fcc72020-10-19 14:38:18 -07004343int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004344{
Hai Shalom899fcc72020-10-19 14:38:18 -07004345 struct wpa_ssid *ssid;
4346 int iter = 1;
4347 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004348
Hai Shalom899fcc72020-10-19 14:38:18 -07004349 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
4350 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4351 !ssid->dpp_csign) {
4352 wpa_printf(MSG_DEBUG,
4353 "DPP: Not a valid network profile for reconfiguration");
4354 return -1;
4355 }
4356
4357 pos = os_strstr(cmd, " iter=");
4358 if (pos) {
4359 iter = atoi(pos + 6);
4360 if (iter <= 0)
4361 return -1;
4362 }
4363
4364 if (wpa_s->dpp_auth) {
4365 wpa_printf(MSG_DEBUG,
4366 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
4367 return -1;
4368 }
4369
4370 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4371 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
4372 ssid->dpp_csign_len,
4373 ssid->dpp_pp_key,
4374 ssid->dpp_pp_key_len);
4375 if (!wpa_s->dpp_reconfig_id) {
4376 wpa_printf(MSG_DEBUG,
4377 "DPP: Failed to generate E-id for reconfiguration");
4378 return -1;
4379 }
4380 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
4381 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
4382 wpa_s->own_disconnect_req = 1;
4383 wpa_supplicant_deauthenticate(
4384 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
4385 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004386 wpas_dpp_chirp_stop(wpa_s);
4387 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07004388 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004389 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004390 wpa_s->dpp_reconfig_ssid = ssid;
4391 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07004392 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004393 wpa_s->dpp_chirp_round = 0;
4394 wpa_s->dpp_chirp_scan_done = 0;
4395 wpa_s->dpp_chirp_listen = 0;
4396
4397 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
4398}
4399
Hai Shalom899fcc72020-10-19 14:38:18 -07004400
Hai Shalom899fcc72020-10-19 14:38:18 -07004401int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
4402{
4403 int peer = -1;
4404 const char *pos, *value;
4405 struct dpp_authentication *auth = wpa_s->dpp_auth;
4406 u8 *bin;
4407 size_t bin_len;
4408 struct wpabuf *buf;
4409 bool tcp = false;
4410
4411 pos = os_strstr(cmd, " peer=");
4412 if (pos) {
4413 peer = atoi(pos + 6);
4414 if (!auth || !auth->waiting_cert ||
4415 (auth->peer_bi &&
4416 (unsigned int) peer != auth->peer_bi->id)) {
4417 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4418 tcp = true;
4419 }
4420 }
4421
4422 if (!auth || !auth->waiting_cert) {
4423 wpa_printf(MSG_DEBUG,
4424 "DPP: No authentication exchange waiting for certificate information");
4425 return -1;
4426 }
4427
4428 if (peer >= 0 &&
4429 (!auth->peer_bi ||
4430 (unsigned int) peer != auth->peer_bi->id) &&
4431 (!auth->tmp_peer_bi ||
4432 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4433 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4434 return -1;
4435 }
4436
4437 pos = os_strstr(cmd, " value=");
4438 if (!pos)
4439 return -1;
4440 value = pos + 7;
4441
4442 pos = os_strstr(cmd, " name=");
4443 if (!pos)
4444 return -1;
4445 pos += 6;
4446
4447 if (os_strncmp(pos, "status ", 7) == 0) {
4448 auth->force_conf_resp_status = atoi(value);
4449 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4450 }
4451
4452 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
4453 os_free(auth->trusted_eap_server_name);
4454 auth->trusted_eap_server_name = os_strdup(value);
4455 return auth->trusted_eap_server_name ? 0 : -1;
4456 }
4457
4458 bin = base64_decode(value, os_strlen(value), &bin_len);
4459 if (!bin)
4460 return -1;
4461 buf = wpabuf_alloc_copy(bin, bin_len);
4462 os_free(bin);
4463
4464 if (os_strncmp(pos, "caCert ", 7) == 0) {
4465 wpabuf_free(auth->cacert);
4466 auth->cacert = buf;
4467 return 0;
4468 }
4469
4470 if (os_strncmp(pos, "certBag ", 8) == 0) {
4471 wpabuf_free(auth->certbag);
4472 auth->certbag = buf;
4473 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4474 }
4475
4476 wpabuf_free(buf);
4477 return -1;
4478}
4479
Hai Shalom81f62d82019-07-22 12:10:00 -07004480#endif /* CONFIG_DPP2 */