blob: d13a8d05a2ca09a2c9bd17ea717939c87594846c [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * wpa_supplicant - DPP
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
Hai Shalomfdcde762020-04-02 11:19:20 -07004 * Copyright (c) 2018-2020, The Linux Foundation
Hai Shaloma20dcd72022-02-04 13:43:00 -08005 * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "utils/includes.h"
12
13#include "utils/common.h"
14#include "utils/eloop.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070015#include "utils/ip_addr.h"
Hai Shalom899fcc72020-10-19 14:38:18 -070016#include "utils/base64.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070017#include "common/dpp.h"
18#include "common/gas.h"
19#include "common/gas_server.h"
Sunil Ravi89eba102022-09-13 21:04:37 -070020#include "crypto/random.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070021#include "rsn_supp/wpa.h"
22#include "rsn_supp/pmksa_cache.h"
23#include "wpa_supplicant_i.h"
24#include "config.h"
25#include "driver_i.h"
26#include "offchannel.h"
27#include "gas_query.h"
28#include "bss.h"
29#include "scan.h"
30#include "notify.h"
31#include "dpp_supplicant.h"
Shivani Baranwalc58b6092022-12-01 11:17:24 +053032#include "aidl/aidl.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070033
34
35static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
36 unsigned int freq);
37static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom60840252021-02-19 19:02:11 -080038static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070039static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
40static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
41 unsigned int freq, const u8 *dst,
42 const u8 *src, const u8 *bssid,
43 const u8 *data, size_t data_len,
44 enum offchannel_send_action_result result);
Roshan Pius3a1667e2018-07-03 15:17:14 -070045static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
46static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
47static void
48wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
49 unsigned int freq, const u8 *dst,
50 const u8 *src, const u8 *bssid,
51 const u8 *data, size_t data_len,
52 enum offchannel_send_action_result result);
Hai Shaloma20dcd72022-02-04 13:43:00 -080053static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070054#ifdef CONFIG_DPP2
55static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
56 void *timeout_ctx);
Hai Shalom899fcc72020-10-19 14:38:18 -070057static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s);
58static int wpas_dpp_process_conf_obj(void *ctx,
59 struct dpp_authentication *auth);
Hai Shaloma20dcd72022-02-04 13:43:00 -080060static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070061#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070062
63static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
64
65/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
66 * a single transaction in progress at any point in time. */
67static const u8 TRANSACTION_ID = 1;
68
69
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070070/**
71 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
72 * @wpa_s: Pointer to wpa_supplicant data
73 * @cmd: DPP URI read from a QR Code
74 * Returns: Identifier of the stored info or -1 on failure
75 */
76int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
77{
78 struct dpp_bootstrap_info *bi;
79 struct dpp_authentication *auth = wpa_s->dpp_auth;
80
Hai Shalom021b0b52019-04-10 11:17:58 -070081 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070082 if (!bi)
83 return -1;
84
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070085 if (auth && auth->response_pending &&
86 dpp_notify_new_qr_code(auth, bi) == 1) {
87 wpa_printf(MSG_DEBUG,
88 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070089 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
90 " freq=%u type=%d",
91 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
92 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070093 offchannel_send_action(wpa_s, auth->curr_freq,
94 auth->peer_mac_addr, wpa_s->own_addr,
95 broadcast,
96 wpabuf_head(auth->resp_msg),
97 wpabuf_len(auth->resp_msg),
98 500, wpas_dpp_tx_status, 0);
99 }
100
Hai Shalom899fcc72020-10-19 14:38:18 -0700101#ifdef CONFIG_DPP2
102 dpp_controller_new_qr_code(wpa_s->dpp, bi);
103#endif /* CONFIG_DPP2 */
104
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700105 return bi->id;
106}
107
108
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800109/**
110 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
111 * @wpa_s: Pointer to wpa_supplicant data
112 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
113 * Returns: Identifier of the stored info or -1 on failure
114 */
115int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
116{
117 struct dpp_bootstrap_info *bi;
118
119 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
120 if (!bi)
121 return -1;
122
123 return bi->id;
124}
125
126
Hai Shalomfdcde762020-04-02 11:19:20 -0700127int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd)
128{
129 const char *pos;
130 struct dpp_bootstrap_info *peer_bi, *own_bi;
131
132 pos = os_strstr(cmd, " own=");
133 if (!pos)
134 return -1;
135 pos += 5;
136 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
137 if (!own_bi)
138 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700139 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700140
141 pos = os_strstr(cmd, " uri=");
142 if (!pos)
143 return -1;
144 pos += 5;
145 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
146 if (!peer_bi) {
147 wpa_printf(MSG_INFO,
148 "DPP: Failed to parse URI from NFC Handover Request");
149 return -1;
150 }
151
152 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
153 return -1;
154
155 return peer_bi->id;
156}
157
158
159int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd)
160{
161 const char *pos;
162 struct dpp_bootstrap_info *peer_bi, *own_bi;
163
164 pos = os_strstr(cmd, " own=");
165 if (!pos)
166 return -1;
167 pos += 5;
168 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
169 if (!own_bi)
170 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700171 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700172
173 pos = os_strstr(cmd, " uri=");
174 if (!pos)
175 return -1;
176 pos += 5;
177 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
178 if (!peer_bi) {
179 wpa_printf(MSG_INFO,
180 "DPP: Failed to parse URI from NFC Handover Select");
181 return -1;
182 }
183
184 if (peer_bi->curve != own_bi->curve) {
185 wpa_printf(MSG_INFO,
186 "DPP: Peer (NFC Handover Selector) used different curve");
187 return -1;
188 }
189
190 return peer_bi->id;
191}
192
193
Roshan Pius3a1667e2018-07-03 15:17:14 -0700194static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
195{
196 struct wpa_supplicant *wpa_s = eloop_ctx;
197 struct dpp_authentication *auth = wpa_s->dpp_auth;
198
199 if (!auth || !auth->resp_msg)
200 return;
201
202 wpa_printf(MSG_DEBUG,
203 "DPP: Retry Authentication Response after timeout");
204 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
205 " freq=%u type=%d",
206 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
207 DPP_PA_AUTHENTICATION_RESP);
208 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
209 wpa_s->own_addr, broadcast,
210 wpabuf_head(auth->resp_msg),
211 wpabuf_len(auth->resp_msg),
212 500, wpas_dpp_tx_status, 0);
213}
214
215
216static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
217{
218 struct dpp_authentication *auth = wpa_s->dpp_auth;
219 unsigned int wait_time, max_tries;
220
221 if (!auth || !auth->resp_msg)
222 return;
223
224 if (wpa_s->dpp_resp_max_tries)
225 max_tries = wpa_s->dpp_resp_max_tries;
226 else
227 max_tries = 5;
228 auth->auth_resp_tries++;
229 if (auth->auth_resp_tries >= max_tries) {
230 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
231 offchannel_send_action_done(wpa_s);
232 dpp_auth_deinit(wpa_s->dpp_auth);
233 wpa_s->dpp_auth = NULL;
234 return;
235 }
236
237 if (wpa_s->dpp_resp_retry_time)
238 wait_time = wpa_s->dpp_resp_retry_time;
239 else
240 wait_time = 1000;
241 wpa_printf(MSG_DEBUG,
242 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
243 wait_time);
244 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
245 eloop_register_timeout(wait_time / 1000,
246 (wait_time % 1000) * 1000,
247 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
248}
249
250
Hai Shalom021b0b52019-04-10 11:17:58 -0700251static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
252{
253 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700254 wpa_s->suitable_network = 0;
255 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700256 wpa_s->disconnected = 0;
257 wpa_s->reassociate = 1;
258 wpa_s->scan_runs = 0;
259 wpa_s->normal_scans = 0;
260 wpa_supplicant_cancel_sched_scan(wpa_s);
261 wpa_supplicant_req_scan(wpa_s, 0, 0);
262}
263
264
Hai Shalomc3565922019-10-28 11:58:20 -0700265#ifdef CONFIG_DPP2
266
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700267static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s,
268 unsigned int freq,
269 unsigned int wait_time)
270{
271 struct os_reltime now, res;
272 unsigned int remaining;
273
274 if (!wpa_s->dpp_listen_freq)
275 return;
276
277 os_get_reltime(&now);
278 if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) {
279 os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res);
280 remaining = res.sec * 1000 + res.usec / 1000;
281 } else {
282 remaining = 0;
283 }
284 if (wpa_s->dpp_listen_freq == freq && remaining > wait_time)
285 return;
286
287 wpa_printf(MSG_DEBUG,
288 "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms",
289 wpa_s->dpp_listen_freq, remaining, freq, wait_time);
290 wpas_dpp_listen_stop(wpa_s);
291
292 /* TODO: Restart listen in some cases after TX? */
293}
294
295
Hai Shalomc3565922019-10-28 11:58:20 -0700296static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
297 void *timeout_ctx)
298{
299 struct wpa_supplicant *wpa_s = eloop_ctx;
300 struct dpp_authentication *auth = wpa_s->dpp_auth;
301 enum dpp_status_error result;
302
Hai Shaloma20dcd72022-02-04 13:43:00 -0800303 if ((!auth || !auth->conn_status_requested) &&
304 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700305 return;
306
307 wpa_printf(MSG_DEBUG,
308 "DPP: Connection timeout - report Connection Status Result");
309 if (wpa_s->suitable_network)
310 result = DPP_STATUS_AUTH_FAILURE;
311 else if (wpa_s->no_suitable_network)
312 result = DPP_STATUS_NO_AP;
313 else
314 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800315 if (wpa_s->wpa_state == WPA_SCANNING)
316 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700317 wpas_dpp_send_conn_status_result(wpa_s, result);
318}
319
320
321static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
322{
323 char *str, *end, *pos;
324 size_t len;
325 unsigned int i;
326 u8 last_op_class = 0;
327 int res;
328
329 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
330 return NULL;
331
332 len = wpa_s->num_last_scan_freqs * 8;
333 str = os_zalloc(len);
334 if (!str)
335 return NULL;
336 end = str + len;
337 pos = str;
338
339 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
340 enum hostapd_hw_mode mode;
341 u8 op_class, channel;
342
343 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
344 0, 0, &op_class, &channel);
345 if (mode == NUM_HOSTAPD_MODES)
346 continue;
347 if (op_class == last_op_class)
348 res = os_snprintf(pos, end - pos, ",%d", channel);
349 else
350 res = os_snprintf(pos, end - pos, "%s%d/%d",
351 pos == str ? "" : ",",
352 op_class, channel);
353 if (os_snprintf_error(end - pos, res)) {
354 *pos = '\0';
355 break;
356 }
357 pos += res;
358 last_op_class = op_class;
359 }
360
361 if (pos == str) {
362 os_free(str);
363 str = NULL;
364 }
365 return str;
366}
367
368
369void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
370 enum dpp_status_error result)
371{
372 struct wpabuf *msg;
373 const char *channel_list = NULL;
374 char *channel_list_buf = NULL;
375 struct wpa_ssid *ssid = wpa_s->current_ssid;
376 struct dpp_authentication *auth = wpa_s->dpp_auth;
377
378 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
379
Hai Shaloma20dcd72022-02-04 13:43:00 -0800380 if ((!auth || !auth->conn_status_requested) &&
381 !dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700382 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800383
Hai Shalomc3565922019-10-28 11:58:20 -0700384 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
385 result);
386
387 if (result == DPP_STATUS_NO_AP) {
388 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
389 channel_list = channel_list_buf;
390 }
391
Hai Shaloma20dcd72022-02-04 13:43:00 -0800392 if (!auth || !auth->conn_status_requested) {
393 dpp_tcp_send_conn_status(wpa_s->dpp, result,
394 ssid ? ssid->ssid :
395 wpa_s->dpp_last_ssid,
396 ssid ? ssid->ssid_len :
397 wpa_s->dpp_last_ssid_len,
398 channel_list);
399 os_free(channel_list_buf);
400 return;
401 }
402
403 auth->conn_status_requested = 0;
404
Hai Shalomc3565922019-10-28 11:58:20 -0700405 msg = dpp_build_conn_status_result(auth, result,
406 ssid ? ssid->ssid :
407 wpa_s->dpp_last_ssid,
408 ssid ? ssid->ssid_len :
409 wpa_s->dpp_last_ssid_len,
410 channel_list);
411 os_free(channel_list_buf);
412 if (!msg) {
413 dpp_auth_deinit(wpa_s->dpp_auth);
414 wpa_s->dpp_auth = NULL;
415 return;
416 }
417
418 wpa_msg(wpa_s, MSG_INFO,
419 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
420 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
421 DPP_PA_CONNECTION_STATUS_RESULT);
Sunil Ravi546a7b52022-08-26 22:06:04 +0000422 if (offchannel_send_action(wpa_s, auth->curr_freq,
423 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
424 wpabuf_head(msg), wpabuf_len(msg),
425 500, wpas_dpp_tx_status, 0) < 0) {
426 wpas_notify_dpp_connection_status_sent(wpa_s, result);
427 wpabuf_free(msg);
428 dpp_auth_deinit(wpa_s->dpp_auth);
429 wpa_s->dpp_auth = NULL;
430 return;
431 }
432
Hai Shalomc3565922019-10-28 11:58:20 -0700433 wpabuf_free(msg);
434
Sunil Ravi546a7b52022-08-26 22:06:04 +0000435 auth->conn_result_status = result;
436 auth->tx_conn_status_result_started = 1;
Hai Shalomc3565922019-10-28 11:58:20 -0700437 /* This exchange will be terminated in the TX status handler */
438 auth->remove_on_tx_status = 1;
439
440 return;
441}
442
443
444void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
445{
446 struct dpp_authentication *auth = wpa_s->dpp_auth;
447
Hai Shaloma20dcd72022-02-04 13:43:00 -0800448 if ((auth && auth->conn_status_requested) ||
449 dpp_tcp_conn_status_requested(wpa_s->dpp))
Hai Shalomc3565922019-10-28 11:58:20 -0700450 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
451}
452
453#endif /* CONFIG_DPP2 */
454
455
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700456static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
457 unsigned int freq, const u8 *dst,
458 const u8 *src, const u8 *bssid,
459 const u8 *data, size_t data_len,
460 enum offchannel_send_action_result result)
461{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700462 const char *res_txt;
463 struct dpp_authentication *auth = wpa_s->dpp_auth;
464
465 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
466 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
467 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700468 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700469 " result=%s", freq, MAC2STR(dst), res_txt);
470 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
471 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700472
473 if (!wpa_s->dpp_auth) {
474 wpa_printf(MSG_DEBUG,
475 "DPP: Ignore TX status since there is no ongoing authentication exchange");
476 return;
477 }
478
Hai Shalom021b0b52019-04-10 11:17:58 -0700479#ifdef CONFIG_DPP2
480 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700481 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700482 wpa_printf(MSG_DEBUG,
483 "DPP: Try to connect after completed configuration result");
484 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700485 if (auth->conn_status_requested) {
486 wpa_printf(MSG_DEBUG,
487 "DPP: Start 15 second timeout for reporting connection status result");
488 eloop_cancel_timeout(
489 wpas_dpp_conn_status_result_timeout,
490 wpa_s, NULL);
491 eloop_register_timeout(
492 15, 0, wpas_dpp_conn_status_result_timeout,
493 wpa_s, NULL);
494 } else {
495 dpp_auth_deinit(wpa_s->dpp_auth);
496 wpa_s->dpp_auth = NULL;
497 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700498 return;
499 }
500#endif /* CONFIG_DPP2 */
501
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700502 if (wpa_s->dpp_auth->remove_on_tx_status) {
Sunil Ravi546a7b52022-08-26 22:06:04 +0000503 if (auth->tx_conn_status_result_started) {
504 wpas_notify_dpp_connection_status_sent(wpa_s, auth->conn_result_status);
505 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700506 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700507 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700508 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700509 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800510 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
511 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700512 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
513 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700514#ifdef CONFIG_DPP2
515 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
516 wpa_s, NULL);
517#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700518 offchannel_send_action_done(wpa_s);
519 dpp_auth_deinit(wpa_s->dpp_auth);
520 wpa_s->dpp_auth = NULL;
521 return;
522 }
523
524 if (wpa_s->dpp_auth_ok_on_ack)
525 wpas_dpp_auth_success(wpa_s, 1);
526
527 if (!is_broadcast_ether_addr(dst) &&
528 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
529 wpa_printf(MSG_DEBUG,
530 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700531 if (auth->waiting_auth_resp) {
532 /* In case of DPP Authentication Request frame, move to
533 * the next channel immediately. */
534 offchannel_send_action_done(wpa_s);
535 wpas_dpp_auth_init_next(wpa_s);
536 return;
537 }
538 if (auth->waiting_auth_conf) {
539 wpas_dpp_auth_resp_retry(wpa_s);
540 return;
541 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700542 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700543
Hai Shalom60840252021-02-19 19:02:11 -0800544 if (auth->waiting_auth_conf &&
545 auth->auth_resp_status == DPP_STATUS_OK) {
546 /* Make sure we do not get stuck waiting for Auth Confirm
547 * indefinitely after successfully transmitted Auth Response to
548 * allow new authentication exchanges to be started. */
549 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
550 NULL);
551 eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
552 wpa_s, NULL);
553 }
554
Roshan Pius3a1667e2018-07-03 15:17:14 -0700555 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
556 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
557 /* Allow timeout handling to stop iteration if no response is
558 * received from a peer that has ACKed a request. */
559 auth->auth_req_ack = 1;
560 }
561
562 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
563 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
564 wpa_printf(MSG_DEBUG,
565 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
566 wpa_s->dpp_auth->curr_freq,
567 wpa_s->dpp_auth->neg_freq);
568 offchannel_send_action_done(wpa_s);
569 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
570 }
571
572 if (wpa_s->dpp_auth_ok_on_ack)
573 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700574}
575
576
577static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
578{
579 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700580 struct dpp_authentication *auth = wpa_s->dpp_auth;
581 unsigned int freq;
582 struct os_reltime now, diff;
583 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700584
Roshan Pius3a1667e2018-07-03 15:17:14 -0700585 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700586 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700587
588 wait_time = wpa_s->dpp_resp_wait_time ?
589 wpa_s->dpp_resp_wait_time : 2000;
590 os_get_reltime(&now);
591 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
592 diff_ms = diff.sec * 1000 + diff.usec / 1000;
593 wpa_printf(MSG_DEBUG,
594 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
595 wait_time, diff_ms);
596
597 if (auth->auth_req_ack && diff_ms >= wait_time) {
598 /* Peer ACK'ed Authentication Request frame, but did not reply
599 * with Authentication Response frame within two seconds. */
600 wpa_printf(MSG_INFO,
601 "DPP: No response received from responder - stopping initiation attempt");
602 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800603 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700604 offchannel_send_action_done(wpa_s);
605 wpas_dpp_listen_stop(wpa_s);
606 dpp_auth_deinit(auth);
607 wpa_s->dpp_auth = NULL;
608 return;
609 }
610
611 if (diff_ms >= wait_time) {
612 /* Authentication Request frame was not ACK'ed and no reply
613 * was receiving within two seconds. */
614 wpa_printf(MSG_DEBUG,
615 "DPP: Continue Initiator channel iteration");
616 offchannel_send_action_done(wpa_s);
617 wpas_dpp_listen_stop(wpa_s);
618 wpas_dpp_auth_init_next(wpa_s);
619 return;
620 }
621
622 /* Driver did not support 2000 ms long wait_time with TX command, so
623 * schedule listen operation to continue waiting for the response.
624 *
625 * DPP listen operations continue until stopped, so simply schedule a
626 * new call to this function at the point when the two second reply
627 * wait has expired. */
628 wait_time -= diff_ms;
629
630 freq = auth->curr_freq;
631 if (auth->neg_freq > 0)
632 freq = auth->neg_freq;
633 wpa_printf(MSG_DEBUG,
634 "DPP: Continue reply wait on channel %u MHz for %u ms",
635 freq, wait_time);
636 wpa_s->dpp_in_response_listen = 1;
637 wpas_dpp_listen_start(wpa_s, freq);
638
639 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
640 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700641}
642
643
Hai Shalom60840252021-02-19 19:02:11 -0800644static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
645{
646 struct wpa_supplicant *wpa_s = eloop_ctx;
647 struct dpp_authentication *auth = wpa_s->dpp_auth;
648
649 if (!auth || !auth->waiting_auth_conf)
650 return;
651
652 wpa_printf(MSG_DEBUG,
653 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
654 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
655 offchannel_send_action_done(wpa_s);
656 dpp_auth_deinit(auth);
657 wpa_s->dpp_auth = NULL;
658}
659
660
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700661static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
662 struct dpp_authentication *auth)
663{
664#ifdef CONFIG_TESTING_OPTIONS
665 if (wpa_s->dpp_config_obj_override)
666 auth->config_obj_override =
667 os_strdup(wpa_s->dpp_config_obj_override);
668 if (wpa_s->dpp_discovery_override)
669 auth->discovery_override =
670 os_strdup(wpa_s->dpp_discovery_override);
671 if (wpa_s->dpp_groups_override)
672 auth->groups_override =
673 os_strdup(wpa_s->dpp_groups_override);
674 auth->ignore_netaccesskey_mismatch =
675 wpa_s->dpp_ignore_netaccesskey_mismatch;
676#endif /* CONFIG_TESTING_OPTIONS */
677}
678
679
Roshan Pius3a1667e2018-07-03 15:17:14 -0700680static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
681{
682 struct wpa_supplicant *wpa_s = eloop_ctx;
683
684 if (!wpa_s->dpp_auth)
685 return;
686 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
687 wpas_dpp_auth_init_next(wpa_s);
688}
689
690
691static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
692{
693 struct dpp_authentication *auth = wpa_s->dpp_auth;
694 const u8 *dst;
695 unsigned int wait_time, max_wait_time, freq, max_tries, used;
696 struct os_reltime now, diff;
697
698 wpa_s->dpp_in_response_listen = 0;
699 if (!auth)
700 return -1;
701
702 if (auth->freq_idx == 0)
703 os_get_reltime(&wpa_s->dpp_init_iter_start);
704
705 if (auth->freq_idx >= auth->num_freq) {
706 auth->num_freq_iters++;
707 if (wpa_s->dpp_init_max_tries)
708 max_tries = wpa_s->dpp_init_max_tries;
709 else
710 max_tries = 5;
711 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
712 wpa_printf(MSG_INFO,
713 "DPP: No response received from responder - stopping initiation attempt");
714 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800715 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700716 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
717 wpa_s, NULL);
718 offchannel_send_action_done(wpa_s);
719 dpp_auth_deinit(wpa_s->dpp_auth);
720 wpa_s->dpp_auth = NULL;
721 return -1;
722 }
723 auth->freq_idx = 0;
724 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
725 if (wpa_s->dpp_init_retry_time)
726 wait_time = wpa_s->dpp_init_retry_time;
727 else
728 wait_time = 10000;
729 os_get_reltime(&now);
730 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
731 used = diff.sec * 1000 + diff.usec / 1000;
732 if (used > wait_time)
733 wait_time = 0;
734 else
735 wait_time -= used;
736 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
737 wait_time);
738 eloop_register_timeout(wait_time / 1000,
739 (wait_time % 1000) * 1000,
740 wpas_dpp_init_timeout, wpa_s,
741 NULL);
742 return 0;
743 }
744 freq = auth->freq[auth->freq_idx++];
745 auth->curr_freq = freq;
746
Hai Shalom60840252021-02-19 19:02:11 -0800747 if (!is_zero_ether_addr(auth->peer_mac_addr))
748 dst = auth->peer_mac_addr;
749 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700750 dst = broadcast;
751 else
752 dst = auth->peer_bi->mac_addr;
753 wpa_s->dpp_auth_ok_on_ack = 0;
754 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
755 wait_time = wpa_s->max_remain_on_chan;
756 max_wait_time = wpa_s->dpp_resp_wait_time ?
757 wpa_s->dpp_resp_wait_time : 2000;
758 if (wait_time > max_wait_time)
759 wait_time = max_wait_time;
760 wait_time += 10; /* give the driver some extra time to complete */
761 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
762 wpas_dpp_reply_wait_timeout,
763 wpa_s, NULL);
764 wait_time -= 10;
765 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
766 wpa_printf(MSG_DEBUG,
767 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
768 freq, auth->neg_freq);
769 }
770 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
771 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
772 auth->auth_req_ack = 0;
773 os_get_reltime(&wpa_s->dpp_last_init);
774 return offchannel_send_action(wpa_s, freq, dst,
775 wpa_s->own_addr, broadcast,
776 wpabuf_head(auth->req_msg),
777 wpabuf_len(auth->req_msg),
778 wait_time, wpas_dpp_tx_status, 0);
779}
780
781
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700782int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
783{
784 const char *pos;
785 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700786 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700787 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
788 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700789 int tcp = 0;
790#ifdef CONFIG_DPP2
791 int tcp_port = DPP_TCP_PORT;
792 struct hostapd_ip_addr ipaddr;
793 char *addr;
794#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700795
796 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800797 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700798
799 pos = os_strstr(cmd, " peer=");
800 if (!pos)
801 return -1;
802 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700803 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700804 if (!peer_bi) {
805 wpa_printf(MSG_INFO,
806 "DPP: Could not find bootstrapping info for the identified peer");
807 return -1;
808 }
809
Hai Shalom81f62d82019-07-22 12:10:00 -0700810#ifdef CONFIG_DPP2
811 pos = os_strstr(cmd, " tcp_port=");
812 if (pos) {
813 pos += 10;
814 tcp_port = atoi(pos);
815 }
816
817 addr = get_param(cmd, " tcp_addr=");
Sunil8cd6f4d2022-06-28 18:40:46 +0000818 if (addr && os_strcmp(addr, "from-uri") == 0) {
819 os_free(addr);
820 if (!peer_bi->host) {
821 wpa_printf(MSG_INFO,
822 "DPP: TCP address not available in peer URI");
823 return -1;
824 }
825 tcp = 1;
826 os_memcpy(&ipaddr, peer_bi->host, sizeof(ipaddr));
827 tcp_port = peer_bi->port;
828 } else if (addr) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700829 int res;
830
831 res = hostapd_parse_ip_addr(addr, &ipaddr);
832 os_free(addr);
833 if (res)
834 return -1;
835 tcp = 1;
836 }
837#endif /* CONFIG_DPP2 */
838
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700839 pos = os_strstr(cmd, " own=");
840 if (pos) {
841 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700842 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700843 if (!own_bi) {
844 wpa_printf(MSG_INFO,
845 "DPP: Could not find bootstrapping info for the identified local entry");
846 return -1;
847 }
848
849 if (peer_bi->curve != own_bi->curve) {
850 wpa_printf(MSG_INFO,
851 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
852 peer_bi->curve->name, own_bi->curve->name);
853 return -1;
854 }
855 }
856
857 pos = os_strstr(cmd, " role=");
858 if (pos) {
859 pos += 6;
860 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700861 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700862 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700863 allowed_roles = DPP_CAPAB_ENROLLEE;
864 else if (os_strncmp(pos, "either", 6) == 0)
865 allowed_roles = DPP_CAPAB_CONFIGURATOR |
866 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700867 else
868 goto fail;
869 }
870
871 pos = os_strstr(cmd, " netrole=");
872 if (pos) {
873 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800874 if (os_strncmp(pos, "ap", 2) == 0)
875 wpa_s->dpp_netrole = DPP_NETROLE_AP;
876 else if (os_strncmp(pos, "configurator", 12) == 0)
877 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
878 else
879 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700880 } else {
881 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700882 }
883
Roshan Pius3a1667e2018-07-03 15:17:14 -0700884 pos = os_strstr(cmd, " neg_freq=");
885 if (pos)
886 neg_freq = atoi(pos + 10);
887
Hai Shalom81f62d82019-07-22 12:10:00 -0700888 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700889 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700890 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800891 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
892 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700893 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
894 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700895#ifdef CONFIG_DPP2
896 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
897 wpa_s, NULL);
898#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700899 offchannel_send_action_done(wpa_s);
900 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800901 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700902 }
903
Hai Shalomfdcde762020-04-02 11:19:20 -0700904 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
905 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700906 if (!auth)
907 goto fail;
908 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700909 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700910 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800911 goto fail;
912 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700913
Hai Shalom81f62d82019-07-22 12:10:00 -0700914 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700915
Roshan Pius3a1667e2018-07-03 15:17:14 -0700916 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700917 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700918
Hai Shalom81f62d82019-07-22 12:10:00 -0700919#ifdef CONFIG_DPP2
920 if (tcp)
Hai Shalom899fcc72020-10-19 14:38:18 -0700921 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
922 wpa_s->conf->dpp_name, DPP_NETROLE_STA,
Sunil Ravi89eba102022-09-13 21:04:37 -0700923 wpa_s->conf->dpp_mud_url,
924 wpa_s->conf->dpp_extra_conf_req_name,
925 wpa_s->conf->dpp_extra_conf_req_value,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800926 wpa_s, wpa_s, wpas_dpp_process_conf_obj,
927 wpas_dpp_tcp_msg_sent);
Hai Shalom81f62d82019-07-22 12:10:00 -0700928#endif /* CONFIG_DPP2 */
929
930 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700931 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700932fail:
933 return -1;
934}
935
936
937struct wpas_dpp_listen_work {
938 unsigned int freq;
939 unsigned int duration;
940 struct wpabuf *probe_resp_ie;
941};
942
943
944static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
945{
946 if (!lwork)
947 return;
948 os_free(lwork);
949}
950
951
952static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
953{
954 struct wpas_dpp_listen_work *lwork;
955
956 if (!wpa_s->dpp_listen_work)
957 return;
958
959 lwork = wpa_s->dpp_listen_work->ctx;
960 wpas_dpp_listen_work_free(lwork);
961 radio_work_done(wpa_s->dpp_listen_work);
962 wpa_s->dpp_listen_work = NULL;
963}
964
965
966static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
967{
968 struct wpa_supplicant *wpa_s = work->wpa_s;
969 struct wpas_dpp_listen_work *lwork = work->ctx;
970
971 if (deinit) {
972 if (work->started) {
973 wpa_s->dpp_listen_work = NULL;
974 wpas_dpp_listen_stop(wpa_s);
975 }
976 wpas_dpp_listen_work_free(lwork);
977 return;
978 }
979
980 wpa_s->dpp_listen_work = work;
981
982 wpa_s->dpp_pending_listen_freq = lwork->freq;
983
984 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
985 wpa_s->max_remain_on_chan) < 0) {
986 wpa_printf(MSG_DEBUG,
987 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
988 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800989 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700990 wpas_dpp_listen_work_done(wpa_s);
991 wpa_s->dpp_pending_listen_freq = 0;
992 return;
993 }
994 wpa_s->off_channel_freq = 0;
995 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700996 wpa_drv_dpp_listen(wpa_s, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700997}
998
999
1000static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
1001 unsigned int freq)
1002{
1003 struct wpas_dpp_listen_work *lwork;
1004
1005 if (wpa_s->dpp_listen_work) {
1006 wpa_printf(MSG_DEBUG,
1007 "DPP: Reject start_listen since dpp_listen_work already exists");
1008 return -1;
1009 }
1010
1011 if (wpa_s->dpp_listen_freq)
1012 wpas_dpp_listen_stop(wpa_s);
1013 wpa_s->dpp_listen_freq = freq;
1014
1015 lwork = os_zalloc(sizeof(*lwork));
1016 if (!lwork)
1017 return -1;
1018 lwork->freq = freq;
1019
1020 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
1021 lwork) < 0) {
1022 wpas_dpp_listen_work_free(lwork);
1023 return -1;
1024 }
1025
1026 return 0;
1027}
1028
1029
1030int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
1031{
1032 int freq;
1033
1034 freq = atoi(cmd);
1035 if (freq <= 0)
1036 return -1;
1037
1038 if (os_strstr(cmd, " role=configurator"))
1039 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
1040 else if (os_strstr(cmd, " role=enrollee"))
1041 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
1042 else
1043 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
1044 DPP_CAPAB_ENROLLEE;
1045 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001046 if (os_strstr(cmd, " netrole=ap"))
1047 wpa_s->dpp_netrole = DPP_NETROLE_AP;
1048 else if (os_strstr(cmd, " netrole=configurator"))
1049 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
1050 else
1051 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001052 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1053 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1054 freq);
1055 return 0;
1056 }
1057
1058 return wpas_dpp_listen_start(wpa_s, freq);
1059}
1060
1061
1062void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1063{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001064 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001065 if (!wpa_s->dpp_listen_freq)
1066 return;
1067
1068 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1069 wpa_s->dpp_listen_freq);
1070 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001071 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001072 wpa_s->dpp_listen_freq = 0;
1073 wpas_dpp_listen_work_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001074 radio_remove_works(wpa_s, "dpp-listen", 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001075}
1076
1077
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001078void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1079 unsigned int freq, unsigned int duration)
1080{
1081 if (wpa_s->dpp_listen_freq != freq)
1082 return;
1083
1084 wpa_printf(MSG_DEBUG,
1085 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
1086 freq, duration);
1087 os_get_reltime(&wpa_s->dpp_listen_end);
1088 wpa_s->dpp_listen_end.usec += duration * 1000;
1089 while (wpa_s->dpp_listen_end.usec >= 1000000) {
1090 wpa_s->dpp_listen_end.sec++;
1091 wpa_s->dpp_listen_end.usec -= 1000000;
1092 }
1093}
1094
1095
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001096void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1097 unsigned int freq)
1098{
1099 wpas_dpp_listen_work_done(wpa_s);
1100
Roshan Pius3a1667e2018-07-03 15:17:14 -07001101 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1102 unsigned int new_freq;
1103
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001104 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001105 if (wpa_s->dpp_auth->neg_freq > 0)
1106 new_freq = wpa_s->dpp_auth->neg_freq;
1107 else
1108 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001109 wpa_printf(MSG_DEBUG,
1110 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001111 new_freq);
1112 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001113 return;
1114 }
1115
1116 if (wpa_s->dpp_listen_freq) {
1117 /* Continue listen with a new remain-on-channel */
1118 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1119 }
1120}
1121
1122
1123static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1124 const u8 *hdr, const u8 *buf, size_t len,
1125 unsigned int freq)
1126{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001127 const u8 *r_bootstrap, *i_bootstrap;
1128 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001129 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1130
1131 if (!wpa_s->dpp)
1132 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001133
1134 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1135 MAC2STR(src));
1136
Hai Shalomfdcde762020-04-02 11:19:20 -07001137#ifdef CONFIG_DPP2
1138 wpas_dpp_chirp_stop(wpa_s);
1139#endif /* CONFIG_DPP2 */
1140
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001141 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1142 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001143 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1144 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1145 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001146 return;
1147 }
1148 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1149 r_bootstrap, r_bootstrap_len);
1150
1151 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1152 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001153 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1154 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1155 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001156 return;
1157 }
1158 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1159 i_bootstrap, i_bootstrap_len);
1160
1161 /* Try to find own and peer bootstrapping key matches based on the
1162 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001163 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1164 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001165 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001166 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1167 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001168 return;
1169 }
1170
Sunil Ravi89eba102022-09-13 21:04:37 -07001171 if (own_bi->type == DPP_BOOTSTRAP_PKEX) {
1172 if (!peer_bi || peer_bi->type != DPP_BOOTSTRAP_PKEX) {
1173 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1174 "No matching peer bootstrapping key found for PKEX - ignore message");
1175 return;
1176 }
1177
1178 if (os_memcmp(peer_bi->pubkey_hash, own_bi->peer_pubkey_hash,
1179 SHA256_MAC_LEN) != 0) {
1180 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1181 "Mismatching peer PKEX bootstrapping key - ignore message");
1182 return;
1183 }
1184 }
1185
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001186 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001187 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1188 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001189 return;
1190 }
1191
Sunil Ravia04bd252022-05-02 22:54:18 -07001192 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001193 wpa_s->dpp_gas_client = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001194 wpa_s->dpp_gas_server = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001195 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001196 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1197 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001198 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001199 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001200 if (!wpa_s->dpp_auth) {
1201 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1202 return;
1203 }
1204 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001205 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001206 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001207 dpp_auth_deinit(wpa_s->dpp_auth);
1208 wpa_s->dpp_auth = NULL;
1209 return;
1210 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001211 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1212
Roshan Pius3a1667e2018-07-03 15:17:14 -07001213 if (wpa_s->dpp_listen_freq &&
1214 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1215 wpa_printf(MSG_DEBUG,
1216 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1217 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1218 wpas_dpp_listen_stop(wpa_s);
1219 }
1220
1221 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1222 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1223 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001224 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1225 src, wpa_s->own_addr, broadcast,
1226 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1227 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1228 500, wpas_dpp_tx_status, 0);
1229}
1230
1231
Hai Shaloma20dcd72022-02-04 13:43:00 -08001232void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s)
1233{
1234 struct dpp_authentication *auth = wpa_s->dpp_auth;
1235 int freq;
1236
1237 if (!wpa_s->dpp_gas_server || !auth)
1238 return;
1239
1240 freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq;
1241 if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq)
1242 return; /* listen state is already in progress */
1243
1244 wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq);
1245 wpa_s->dpp_in_response_listen = 1;
1246 wpas_dpp_listen_start(wpa_s, freq);
1247}
1248
1249
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001250static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1251{
Hai Shaloma20dcd72022-02-04 13:43:00 -08001252 struct dpp_authentication *auth = wpa_s->dpp_auth;
1253
1254 wpa_printf(MSG_DEBUG,
1255 "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)",
1256 auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq,
1257 !!wpa_s->dpp_listen_work);
1258 wpa_s->dpp_gas_server = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001259}
1260
1261
1262static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001263 struct dpp_authentication *auth,
1264 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001265{
1266 struct wpa_ssid *ssid;
1267
Hai Shalom021b0b52019-04-10 11:17:58 -07001268#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001269 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001270#ifdef CONFIG_SAE
1271 struct wpa_driver_capa capa;
1272 int res;
1273
1274 res = wpa_drv_get_capa(wpa_s, &capa);
1275 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001276 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1277 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001278 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1279 wpa_printf(MSG_DEBUG,
1280 "DPP: SAE not supported by the driver");
1281 return NULL;
1282 }
1283#else /* CONFIG_SAE */
1284 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1285 return NULL;
1286#endif /* CONFIG_SAE */
1287 }
1288#endif /* CONFIG_DPP2 */
1289
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001290 ssid = wpa_config_add_network(wpa_s->conf);
1291 if (!ssid)
1292 return NULL;
1293 wpas_notify_network_added(wpa_s, ssid);
1294 wpa_config_set_network_defaults(ssid);
1295 ssid->disabled = 1;
1296
Hai Shalomc3565922019-10-28 11:58:20 -07001297 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001298 if (!ssid->ssid)
1299 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001300 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1301 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001302
Hai Shalomc3565922019-10-28 11:58:20 -07001303 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001304 if (dpp_akm_dpp(conf->akm)) {
1305 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1306 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1307 }
Hai Shalomc3565922019-10-28 11:58:20 -07001308 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001309 if (!ssid->dpp_connector)
1310 goto fail;
Sunil Ravi89eba102022-09-13 21:04:37 -07001311
1312 ssid->dpp_connector_privacy =
1313 wpa_s->conf->dpp_connector_privacy_default;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001314 }
1315
Hai Shalomc3565922019-10-28 11:58:20 -07001316 if (conf->c_sign_key) {
1317 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001318 if (!ssid->dpp_csign)
1319 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001320 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1321 wpabuf_len(conf->c_sign_key));
1322 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001323 }
1324
Hai Shalom899fcc72020-10-19 14:38:18 -07001325 if (conf->pp_key) {
1326 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1327 if (!ssid->dpp_pp_key)
1328 goto fail;
1329 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1330 wpabuf_len(conf->pp_key));
1331 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1332 }
1333
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001334 if (auth->net_access_key) {
1335 ssid->dpp_netaccesskey =
1336 os_malloc(wpabuf_len(auth->net_access_key));
1337 if (!ssid->dpp_netaccesskey)
1338 goto fail;
1339 os_memcpy(ssid->dpp_netaccesskey,
1340 wpabuf_head(auth->net_access_key),
1341 wpabuf_len(auth->net_access_key));
1342 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1343 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1344 }
1345
Hai Shalomc3565922019-10-28 11:58:20 -07001346 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1347 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001348 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001349 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001350 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001351 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1352 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001353 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001354 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1355 WPA_KEY_MGMT_FT_SAE;
1356 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001357 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001358 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001359 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001360 goto fail;
1361 wpa_config_update_psk(ssid);
1362 ssid->export_keys = 1;
1363 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001364 ssid->psk_set = conf->psk_set;
1365 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001366 }
1367 }
1368
Hai Shalom899fcc72020-10-19 14:38:18 -07001369#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1370 if (conf->akm == DPP_AKM_DOT1X) {
1371 int i;
1372 char name[100], blobname[128];
1373 struct wpa_config_blob *blob;
1374
1375 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1376 WPA_KEY_MGMT_IEEE8021X_SHA256 |
1377 WPA_KEY_MGMT_IEEE8021X_SHA256;
1378 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1379
1380 if (conf->cacert) {
1381 /* caCert is DER-encoded X.509v3 certificate for the
1382 * server certificate if that is different from the
1383 * trust root included in certBag. */
1384 /* TODO: ssid->eap.cert.ca_cert */
1385 }
1386
1387 if (conf->certs) {
1388 for (i = 0; ; i++) {
1389 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1390 i);
1391 if (!wpa_config_get_blob(wpa_s->conf, name))
1392 break;
1393 }
1394
1395 blob = os_zalloc(sizeof(*blob));
1396 if (!blob)
1397 goto fail;
1398 blob->len = wpabuf_len(conf->certs);
1399 blob->name = os_strdup(name);
1400 blob->data = os_malloc(blob->len);
1401 if (!blob->name || !blob->data) {
1402 wpa_config_free_blob(blob);
1403 goto fail;
1404 }
1405 os_memcpy(blob->data, wpabuf_head(conf->certs),
1406 blob->len);
1407 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1408 name);
1409 wpa_config_set_blob(wpa_s->conf, blob);
1410 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1411 name);
1412 ssid->eap.cert.client_cert = os_strdup(blobname);
1413 if (!ssid->eap.cert.client_cert)
1414 goto fail;
1415
1416 /* TODO: ssid->eap.identity from own certificate */
1417 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1418 0) < 0)
1419 goto fail;
1420 }
1421
1422 if (auth->priv_key) {
1423 for (i = 0; ; i++) {
1424 os_snprintf(name, sizeof(name), "dpp-key-%d",
1425 i);
1426 if (!wpa_config_get_blob(wpa_s->conf, name))
1427 break;
1428 }
1429
1430 blob = os_zalloc(sizeof(*blob));
1431 if (!blob)
1432 goto fail;
1433 blob->len = wpabuf_len(auth->priv_key);
1434 blob->name = os_strdup(name);
1435 blob->data = os_malloc(blob->len);
1436 if (!blob->name || !blob->data) {
1437 wpa_config_free_blob(blob);
1438 goto fail;
1439 }
1440 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1441 blob->len);
1442 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1443 name);
1444 wpa_config_set_blob(wpa_s->conf, blob);
1445 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1446 name);
1447 ssid->eap.cert.private_key = os_strdup(blobname);
1448 if (!ssid->eap.cert.private_key)
1449 goto fail;
1450 }
1451
1452 if (conf->server_name) {
1453 ssid->eap.cert.domain_suffix_match =
1454 os_strdup(conf->server_name);
1455 if (!ssid->eap.cert.domain_suffix_match)
1456 goto fail;
1457 }
1458
1459 /* TODO: Use entCreds::eapMethods */
1460 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1461 goto fail;
1462 }
1463#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1464
Hai Shalomc3565922019-10-28 11:58:20 -07001465 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1466 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1467
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001468 return ssid;
1469fail:
1470 wpas_notify_network_removed(wpa_s, ssid);
1471 wpa_config_remove_network(wpa_s->conf, ssid->id);
1472 return NULL;
1473}
1474
1475
Hai Shalom021b0b52019-04-10 11:17:58 -07001476static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001477 struct dpp_authentication *auth,
1478 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001479{
1480 struct wpa_ssid *ssid;
1481
1482 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001483 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001484
Hai Shalomc3565922019-10-28 11:58:20 -07001485 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001486 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001487 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001488
1489 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001490
Sunil Ravi546a7b52022-08-26 22:06:04 +00001491 wpas_notify_dpp_config_received(wpa_s, ssid, auth->conn_status_requested ? 1 : 0);
Hai Shalom59532852018-12-07 10:32:58 -08001492
Hai Shalom021b0b52019-04-10 11:17:58 -07001493 if (wpa_s->conf->dpp_config_processing == 2)
1494 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001495
Hai Shalom021b0b52019-04-10 11:17:58 -07001496#ifndef CONFIG_NO_CONFIG_WRITE
1497 if (wpa_s->conf->update_config &&
1498 wpa_config_write(wpa_s->confname, wpa_s->conf))
1499 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1500#endif /* CONFIG_NO_CONFIG_WRITE */
1501
Hai Shalomc3565922019-10-28 11:58:20 -07001502 return 0;
1503}
1504
1505
1506static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1507 struct dpp_authentication *auth)
1508{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001509#ifdef CONFIG_DPP2
1510 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1511 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1512 wpa_s->dpp_reconfig_ssid) {
1513 wpa_printf(MSG_DEBUG,
1514 "DPP: Remove reconfigured network profile");
1515 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1516 wpa_config_remove_network(wpa_s->conf,
1517 wpa_s->dpp_reconfig_ssid_id);
1518 wpa_s->dpp_reconfig_ssid = NULL;
1519 wpa_s->dpp_reconfig_ssid_id = -1;
1520 }
1521#endif /* CONFIG_DPP2 */
1522
Hai Shalom021b0b52019-04-10 11:17:58 -07001523 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001524 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001525
1526#ifdef CONFIG_DPP2
1527 if (auth->peer_version >= 2) {
1528 wpa_printf(MSG_DEBUG,
1529 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1530 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001531 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001532 }
1533#endif /* CONFIG_DPP2 */
1534
1535 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001536}
1537
1538
Hai Shalom021b0b52019-04-10 11:17:58 -07001539static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001540 struct dpp_authentication *auth,
1541 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001542{
1543 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001544 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1545 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001546 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001547 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001548 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001549 if (conf->ssid_charset)
1550 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1551 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001552 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001553 /* TODO: Save the Connector and consider using a command
1554 * to fetch the value instead of sending an event with
1555 * it. The Connector could end up being larger than what
1556 * most clients are ready to receive as an event
1557 * message. */
1558 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001559 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001560 }
Hai Shalom60840252021-02-19 19:02:11 -08001561 if (conf->passphrase[0]) {
1562 char hex[64 * 2 + 1];
1563
1564 wpa_snprintf_hex(hex, sizeof(hex),
1565 (const u8 *) conf->passphrase,
1566 os_strlen(conf->passphrase));
1567 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1568 hex);
1569 } else if (conf->psk_set) {
1570 char hex[PMK_LEN * 2 + 1];
1571
1572 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1573 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1574 hex);
1575 }
Hai Shalomc3565922019-10-28 11:58:20 -07001576 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001577 char *hex;
1578 size_t hexlen;
1579
Hai Shalomc3565922019-10-28 11:58:20 -07001580 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001581 hex = os_malloc(hexlen);
1582 if (hex) {
1583 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001584 wpabuf_head(conf->c_sign_key),
1585 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001586 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1587 hex);
1588 os_free(hex);
1589 }
1590 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001591 if (conf->pp_key) {
1592 char *hex;
1593 size_t hexlen;
1594
1595 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1596 hex = os_malloc(hexlen);
1597 if (hex) {
1598 wpa_snprintf_hex(hex, hexlen,
1599 wpabuf_head(conf->pp_key),
1600 wpabuf_len(conf->pp_key));
1601 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1602 os_free(hex);
1603 }
1604 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001605 if (auth->net_access_key) {
1606 char *hex;
1607 size_t hexlen;
1608
1609 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1610 hex = os_malloc(hexlen);
1611 if (hex) {
1612 wpa_snprintf_hex(hex, hexlen,
1613 wpabuf_head(auth->net_access_key),
1614 wpabuf_len(auth->net_access_key));
1615 if (auth->net_access_key_expiry)
1616 wpa_msg(wpa_s, MSG_INFO,
1617 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1618 (long unsigned)
1619 auth->net_access_key_expiry);
1620 else
1621 wpa_msg(wpa_s, MSG_INFO,
1622 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1623 os_free(hex);
1624 }
1625 }
1626
Hai Shalom899fcc72020-10-19 14:38:18 -07001627#ifdef CONFIG_DPP2
1628 if (conf->certbag) {
1629 char *b64;
1630
1631 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1632 wpabuf_len(conf->certbag), NULL);
1633 if (b64)
1634 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1635 os_free(b64);
1636 }
1637
1638 if (conf->cacert) {
1639 char *b64;
1640
1641 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1642 wpabuf_len(conf->cacert), NULL);
1643 if (b64)
1644 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1645 os_free(b64);
1646 }
1647
1648 if (conf->server_name)
1649 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1650 conf->server_name);
1651#endif /* CONFIG_DPP2 */
1652
Sunil Ravi89eba102022-09-13 21:04:37 -07001653#ifdef CONFIG_DPP3
1654 if (!wpa_s->dpp_pb_result_indicated) {
1655 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "success");
1656 wpa_s->dpp_pb_result_indicated = true;
1657 }
1658
1659#endif /* CONFIG_DPP3 */
1660
Hai Shalomc3565922019-10-28 11:58:20 -07001661 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001662}
1663
1664
Hai Shalomfdcde762020-04-02 11:19:20 -07001665static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1666 struct dpp_asymmetric_key *key)
1667{
1668#ifdef CONFIG_DPP2
1669 int res;
1670
1671 if (!key)
1672 return 0;
1673
1674 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1675 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001676 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001677
1678 while (key) {
1679 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1680 if (res < 0)
1681 return -1;
1682 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1683 res);
1684 key = key->next;
1685 }
1686#endif /* CONFIG_DPP2 */
1687
1688 return 0;
1689}
1690
1691
Hai Shalom899fcc72020-10-19 14:38:18 -07001692#ifdef CONFIG_DPP2
1693static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1694{
1695 struct wpa_supplicant *wpa_s = eloop_ctx;
1696 struct dpp_authentication *auth = wpa_s->dpp_auth;
1697
1698 if (!auth || !auth->csrattrs)
1699 return;
1700
1701 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1702 wpabuf_free(auth->csr);
1703 /* TODO: Additional information needed for CSR based on csrAttrs */
1704 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1705 wpa_s->conf->dpp_name : "Test");
1706 if (!auth->csr) {
1707 dpp_auth_deinit(wpa_s->dpp_auth);
1708 wpa_s->dpp_auth = NULL;
1709 return;
1710 }
1711
1712 wpas_dpp_start_gas_client(wpa_s);
1713}
1714#endif /* CONFIG_DPP2 */
1715
1716
Sunil Ravia04bd252022-05-02 22:54:18 -07001717#ifdef CONFIG_DPP3
1718static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1719{
1720 struct wpa_supplicant *wpa_s = eloop_ctx;
1721 struct dpp_authentication *auth = wpa_s->dpp_auth;
1722
1723 if (!auth || !auth->waiting_new_key)
1724 return;
1725
1726 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1727 wpas_dpp_start_gas_client(wpa_s);
1728}
1729#endif /* CONFIG_DPP3 */
1730
1731
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001732static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1733 enum gas_query_result result,
1734 const struct wpabuf *adv_proto,
1735 const struct wpabuf *resp, u16 status_code)
1736{
1737 struct wpa_supplicant *wpa_s = ctx;
1738 const u8 *pos;
1739 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001740 int res;
1741 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001742 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001743
Hai Shaloma20dcd72022-02-04 13:43:00 -08001744 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001745 wpa_s->dpp_gas_dialog_token = -1;
1746
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001747 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
1748 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001749 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1750 return;
1751 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001752 if (result != GAS_QUERY_SUCCESS ||
1753 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001754 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1755 goto fail;
1756 }
1757
1758 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1759 adv_proto);
1760 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1761 resp);
1762
1763 if (wpabuf_len(adv_proto) != 10 ||
1764 !(pos = wpabuf_head(adv_proto)) ||
1765 pos[0] != WLAN_EID_ADV_PROTO ||
1766 pos[1] != 8 ||
1767 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1768 pos[4] != 5 ||
1769 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1770 pos[8] != 0x1a ||
1771 pos[9] != 1) {
1772 wpa_printf(MSG_DEBUG,
1773 "DPP: Not a DPP Advertisement Protocol ID");
1774 goto fail;
1775 }
1776
Hai Shalom899fcc72020-10-19 14:38:18 -07001777 res = dpp_conf_resp_rx(auth, resp);
1778#ifdef CONFIG_DPP2
1779 if (res == -2) {
1780 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1781 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1782 return;
1783 }
1784#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001785#ifdef CONFIG_DPP3
1786 if (res == -3) {
1787 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1788 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1789 NULL);
1790 return;
1791 }
1792#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001793 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001794 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1795 goto fail;
1796 }
1797
Hai Shalom899fcc72020-10-19 14:38:18 -07001798 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001799 for (i = 0; i < auth->num_conf_obj; i++) {
1800 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1801 &auth->conf_obj[i]);
1802 if (res < 0)
1803 goto fail;
1804 }
1805 if (auth->num_conf_obj)
1806 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001807 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1808 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001809
Hai Shalom021b0b52019-04-10 11:17:58 -07001810 status = DPP_STATUS_OK;
1811#ifdef CONFIG_TESTING_OPTIONS
1812 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1813 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1814 status = DPP_STATUS_CONFIG_REJECTED;
1815 }
1816#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001817fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001818 if (status != DPP_STATUS_OK) {
1819 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1820 wpas_notify_dpp_configuration_failure(wpa_s);
1821 }
1822#ifdef CONFIG_DPP2
1823 if (auth->peer_version >= 2 &&
1824 auth->conf_resp_status == DPP_STATUS_OK) {
1825 struct wpabuf *msg;
1826
1827 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1828 msg = dpp_build_conf_result(auth, status);
1829 if (!msg)
1830 goto fail2;
1831
1832 wpa_msg(wpa_s, MSG_INFO,
1833 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1834 MAC2STR(addr), auth->curr_freq,
1835 DPP_PA_CONFIGURATION_RESULT);
1836 offchannel_send_action(wpa_s, auth->curr_freq,
1837 addr, wpa_s->own_addr, broadcast,
1838 wpabuf_head(msg),
1839 wpabuf_len(msg),
1840 500, wpas_dpp_tx_status, 0);
1841 wpabuf_free(msg);
1842
1843 /* This exchange will be terminated in the TX status handler */
Sunil Ravi546a7b52022-08-26 22:06:04 +00001844 if (wpa_s->conf->dpp_config_processing < 1 ||
Hai Shalom899fcc72020-10-19 14:38:18 -07001845 wpa_s->dpp_conf_backup_received)
1846 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001847 return;
1848 }
1849fail2:
1850#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001851 dpp_auth_deinit(wpa_s->dpp_auth);
1852 wpa_s->dpp_auth = NULL;
1853}
1854
1855
Hai Shaloma20dcd72022-02-04 13:43:00 -08001856static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
1857{
1858 struct wpa_supplicant *wpa_s = eloop_ctx;
1859 struct dpp_authentication *auth = wpa_s->dpp_auth;
1860
1861 if (!wpa_s->dpp_gas_client || !auth ||
1862 (!auth->auth_success && !auth->reconfig_success))
1863 return;
1864
1865 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
1866 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1867 dpp_auth_deinit(wpa_s->dpp_auth);
1868 wpa_s->dpp_auth = NULL;
1869}
1870
1871
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001872static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1873{
1874 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001875 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001876 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001877 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001878
1879 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001880 offchannel_send_action_done(wpa_s);
1881 wpas_dpp_listen_stop(wpa_s);
1882
Hai Shalomc3565922019-10-28 11:58:20 -07001883 supp_op_classes = wpas_supp_op_classes(wpa_s);
1884 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001885 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001886 wpa_s->conf->dpp_mud_url,
Sunil Ravi89eba102022-09-13 21:04:37 -07001887 supp_op_classes,
1888 wpa_s->conf->dpp_extra_conf_req_name,
1889 wpa_s->conf->dpp_extra_conf_req_value);
Hai Shalomc3565922019-10-28 11:58:20 -07001890 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001891 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001892 wpa_printf(MSG_DEBUG,
1893 "DPP: No configuration request data available");
1894 return;
1895 }
1896
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001897 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1898 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1899
Hai Shaloma20dcd72022-02-04 13:43:00 -08001900 /* Use a 120 second timeout since the gas_query_req() operation could
1901 * remain waiting indefinitely for the response if the Configurator
1902 * keeps sending out comeback responses with additional delay. The
1903 * DPP technical specification expects the Enrollee to continue sending
1904 * out new Config Requests for 60 seconds, so this gives an extra 60
1905 * second time after the last expected new Config Request for the
1906 * Configurator to determine what kind of configuration to provide. */
1907 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
1908 wpa_s, NULL);
1909
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001910 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001911 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001912 if (res < 0) {
1913 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1914 wpabuf_free(buf);
1915 } else {
1916 wpa_printf(MSG_DEBUG,
1917 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001918 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001919 }
1920}
1921
1922
1923static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1924{
1925 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1926 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001927 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001928#ifdef CONFIG_TESTING_OPTIONS
1929 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1930 wpa_printf(MSG_INFO,
1931 "DPP: TESTING - stop at Authentication Confirm");
1932 if (wpa_s->dpp_auth->configurator) {
1933 /* Prevent GAS response */
1934 wpa_s->dpp_auth->auth_success = 0;
1935 }
1936 return;
1937 }
1938#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001939
1940 if (wpa_s->dpp_auth->configurator)
1941 wpas_dpp_start_gas_server(wpa_s);
1942 else
1943 wpas_dpp_start_gas_client(wpa_s);
1944}
1945
1946
1947static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001948 const u8 *hdr, const u8 *buf, size_t len,
1949 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001950{
1951 struct dpp_authentication *auth = wpa_s->dpp_auth;
1952 struct wpabuf *msg;
1953
Roshan Pius3a1667e2018-07-03 15:17:14 -07001954 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1955 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001956
1957 if (!auth) {
1958 wpa_printf(MSG_DEBUG,
1959 "DPP: No DPP Authentication in progress - drop");
1960 return;
1961 }
1962
1963 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1964 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1965 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1966 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1967 return;
1968 }
1969
1970 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1971
Roshan Pius3a1667e2018-07-03 15:17:14 -07001972 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1973 wpa_printf(MSG_DEBUG,
1974 "DPP: Responder accepted request for different negotiation channel");
1975 auth->curr_freq = freq;
1976 }
1977
1978 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001979 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1980 if (!msg) {
1981 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1982 wpa_printf(MSG_DEBUG,
1983 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001984 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001985 offchannel_send_action_done(wpa_s);
1986 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1987 return;
1988 }
1989 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1990 return;
1991 }
1992 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1993
Roshan Pius3a1667e2018-07-03 15:17:14 -07001994 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1995 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001996 offchannel_send_action(wpa_s, auth->curr_freq,
1997 src, wpa_s->own_addr, broadcast,
1998 wpabuf_head(msg), wpabuf_len(msg),
1999 500, wpas_dpp_tx_status, 0);
2000 wpabuf_free(msg);
2001 wpa_s->dpp_auth_ok_on_ack = 1;
2002}
2003
2004
2005static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2006 const u8 *hdr, const u8 *buf, size_t len)
2007{
2008 struct dpp_authentication *auth = wpa_s->dpp_auth;
2009
2010 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
2011 MAC2STR(src));
2012
2013 if (!auth) {
2014 wpa_printf(MSG_DEBUG,
2015 "DPP: No DPP Authentication in progress - drop");
2016 return;
2017 }
2018
2019 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2020 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2021 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2022 return;
2023 }
2024
Hai Shalom60840252021-02-19 19:02:11 -08002025 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
2026
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002027 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
2028 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08002029 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002030 return;
2031 }
2032
2033 wpas_dpp_auth_success(wpa_s, 0);
2034}
2035
2036
Hai Shalom021b0b52019-04-10 11:17:58 -07002037#ifdef CONFIG_DPP2
2038
2039static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
2040 void *timeout_ctx)
2041{
2042 struct wpa_supplicant *wpa_s = eloop_ctx;
2043 struct dpp_authentication *auth = wpa_s->dpp_auth;
2044
2045 if (!auth || !auth->waiting_conf_result)
2046 return;
2047
2048 wpa_printf(MSG_DEBUG,
2049 "DPP: Timeout while waiting for Configuration Result");
2050 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002051 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002052 dpp_auth_deinit(auth);
2053 wpa_s->dpp_auth = NULL;
2054}
2055
2056
Hai Shalomc3565922019-10-28 11:58:20 -07002057static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2058 void *timeout_ctx)
2059{
2060 struct wpa_supplicant *wpa_s = eloop_ctx;
2061 struct dpp_authentication *auth = wpa_s->dpp_auth;
2062
2063 if (!auth || !auth->waiting_conn_status_result)
2064 return;
2065
2066 wpa_printf(MSG_DEBUG,
2067 "DPP: Timeout while waiting for Connection Status Result");
2068 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002069 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002070 wpas_dpp_listen_stop(wpa_s);
2071 dpp_auth_deinit(auth);
2072 wpa_s->dpp_auth = NULL;
2073}
2074
2075
Sunil Ravi89eba102022-09-13 21:04:37 -07002076#ifdef CONFIG_DPP3
2077
2078static bool wpas_dpp_pb_active(struct wpa_supplicant *wpa_s)
2079{
2080 return (wpa_s->dpp_pb_time.sec || wpa_s->dpp_pb_time.usec) &&
2081 wpa_s->dpp_pb_configurator;
2082}
2083
2084
2085static void wpas_dpp_remove_pb_hash(struct wpa_supplicant *wpa_s)
2086{
2087 int i;
2088
2089 if (!wpa_s->dpp_pb_bi)
2090 return;
2091 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2092 struct dpp_pb_info *info = &wpa_s->dpp_pb[i];
2093
2094 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
2095 continue;
2096 if (os_memcmp(info->hash, wpa_s->dpp_pb_resp_hash,
2097 SHA256_MAC_LEN) == 0) {
2098 /* Allow a new push button session to be established
2099 * immediately without the successfully completed
2100 * session triggering session overlap. */
2101 info->rx_time.sec = 0;
2102 info->rx_time.usec = 0;
2103 wpa_printf(MSG_DEBUG,
2104 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
2105 }
2106 }
2107}
2108
2109#endif /* CONFIG_DPP3 */
2110
2111
Hai Shalom021b0b52019-04-10 11:17:58 -07002112static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2113 const u8 *hdr, const u8 *buf, size_t len)
2114{
2115 struct dpp_authentication *auth = wpa_s->dpp_auth;
2116 enum dpp_status_error status;
2117
2118 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2119 MAC2STR(src));
2120
2121 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002122 if (auth &&
2123 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
2124 gas_server_response_sent(wpa_s->gas_server,
2125 auth->gas_server_ctx)) {
2126 /* This could happen if the TX status event gets delayed
2127 * long enough for the Enrollee to have time to send
2128 * the next frame before the TX status gets processed
2129 * locally. */
2130 wpa_printf(MSG_DEBUG,
2131 "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");
2132 auth->waiting_conf_result = 1;
2133 } else {
2134 wpa_printf(MSG_DEBUG,
2135 "DPP: No DPP Configuration waiting for result - drop");
2136 return;
2137 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002138 }
2139
2140 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2141 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2142 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2143 return;
2144 }
2145
2146 status = dpp_conf_result_rx(auth, hdr, buf, len);
2147
Hai Shalomc3565922019-10-28 11:58:20 -07002148 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002149 int freq;
2150
Hai Shalomc3565922019-10-28 11:58:20 -07002151 wpa_msg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07002152 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
2153 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07002154 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002155 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002156 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2157 wpa_s, NULL);
2158 auth->waiting_conn_status_result = 1;
2159 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2160 wpa_s, NULL);
2161 eloop_register_timeout(16, 0,
2162 wpas_dpp_conn_status_result_wait_timeout,
2163 wpa_s, NULL);
2164 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002165 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2166 if (!wpa_s->dpp_in_response_listen ||
2167 (int) wpa_s->dpp_listen_freq != freq)
2168 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002169 return;
2170 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002171 offchannel_send_action_done(wpa_s);
2172 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002173 if (status == DPP_STATUS_OK) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002174 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
2175 auth->conf_resp_status);
Hai Shalome4073332019-11-05 16:20:12 -08002176 wpas_notify_dpp_config_sent(wpa_s);
2177 }
2178 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002179 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002180 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002181 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002182 dpp_auth_deinit(auth);
2183 wpa_s->dpp_auth = NULL;
2184 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07002185#ifdef CONFIG_DPP3
2186 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
2187 if (status == DPP_STATUS_OK)
2188 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2189 "success");
2190 else
2191 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2192 "no-configuration-available");
2193 wpa_s->dpp_pb_result_indicated = true;
2194 if (status == DPP_STATUS_OK)
2195 wpas_dpp_remove_pb_hash(wpa_s);
2196 wpas_dpp_push_button_stop(wpa_s);
2197 }
2198#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002199}
2200
Hai Shalom81f62d82019-07-22 12:10:00 -07002201
Hai Shalomc3565922019-10-28 11:58:20 -07002202static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2203 const u8 *src, const u8 *hdr,
2204 const u8 *buf, size_t len)
2205{
2206 struct dpp_authentication *auth = wpa_s->dpp_auth;
2207 enum dpp_status_error status;
2208 u8 ssid[SSID_MAX_LEN];
2209 size_t ssid_len = 0;
2210 char *channel_list = NULL;
2211
2212 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2213
2214 if (!auth || !auth->waiting_conn_status_result) {
2215 wpa_printf(MSG_DEBUG,
2216 "DPP: No DPP Configuration waiting for connection status result - drop");
2217 return;
2218 }
2219
2220 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2221 ssid, &ssid_len, &channel_list);
2222 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2223 "result=%d ssid=%s channel_list=%s",
2224 status, wpa_ssid_txt(ssid, ssid_len),
2225 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002226 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2227 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002228 os_free(channel_list);
2229 offchannel_send_action_done(wpa_s);
2230 wpas_dpp_listen_stop(wpa_s);
2231 dpp_auth_deinit(auth);
2232 wpa_s->dpp_auth = NULL;
2233 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2234 wpa_s, NULL);
2235}
2236
2237
Hai Shalom81f62d82019-07-22 12:10:00 -07002238static int wpas_dpp_process_conf_obj(void *ctx,
2239 struct dpp_authentication *auth)
2240{
2241 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002242 unsigned int i;
2243 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002244
Hai Shalomc3565922019-10-28 11:58:20 -07002245 for (i = 0; i < auth->num_conf_obj; i++) {
2246 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2247 &auth->conf_obj[i]);
2248 if (res)
2249 break;
2250 }
2251 if (!res)
2252 wpas_dpp_post_process_config(wpa_s, auth);
2253
2254 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002255}
2256
Hai Shalomfdcde762020-04-02 11:19:20 -07002257
Hai Shaloma20dcd72022-02-04 13:43:00 -08002258static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2259{
2260 struct wpa_supplicant *wpa_s = ctx;
2261
2262 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2263
2264 if (auth->connect_on_tx_status) {
2265 auth->connect_on_tx_status = 0;
2266 wpa_printf(MSG_DEBUG,
2267 "DPP: Try to connect after completed configuration result");
2268 wpas_dpp_try_to_connect(wpa_s);
2269 if (auth->conn_status_requested) {
2270 wpa_printf(MSG_DEBUG,
2271 "DPP: Start 15 second timeout for reporting connection status result");
2272 eloop_cancel_timeout(
2273 wpas_dpp_conn_status_result_timeout,
2274 wpa_s, NULL);
2275 eloop_register_timeout(
2276 15, 0, wpas_dpp_conn_status_result_timeout,
2277 wpa_s, NULL);
2278 return true;
2279 }
2280 }
2281
2282 return false;
2283}
2284
2285
Hai Shalomfdcde762020-04-02 11:19:20 -07002286static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2287{
2288 struct wpa_supplicant *wpa_s = ctx;
2289
2290 if (bi == wpa_s->dpp_chirp_bi)
2291 wpas_dpp_chirp_stop(wpa_s);
2292}
2293
2294
2295static void
2296wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2297 const u8 *hdr, const u8 *buf, size_t len,
2298 unsigned int freq)
2299{
2300 const u8 *r_bootstrap;
2301 u16 r_bootstrap_len;
2302 struct dpp_bootstrap_info *peer_bi;
2303 struct dpp_authentication *auth;
2304
2305 if (!wpa_s->dpp)
2306 return;
2307
2308 if (wpa_s->dpp_auth) {
2309 wpa_printf(MSG_DEBUG,
2310 "DPP: Ignore Presence Announcement during ongoing Authentication");
2311 return;
2312 }
2313
2314 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2315 MAC2STR(src));
2316
2317 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2318 &r_bootstrap_len);
2319 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2320 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2321 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2322 return;
2323 }
2324 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2325 r_bootstrap, r_bootstrap_len);
2326 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002327 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2328 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002329 if (!peer_bi) {
2330 wpa_printf(MSG_DEBUG,
2331 "DPP: No matching bootstrapping information found");
2332 return;
2333 }
2334
2335 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2336 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2337 if (!auth)
2338 return;
2339 wpas_dpp_set_testing_options(wpa_s, auth);
2340 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2341 dpp_auth_deinit(auth);
2342 return;
2343 }
2344
2345 auth->neg_freq = freq;
2346
Hai Shalom60840252021-02-19 19:02:11 -08002347 /* The source address of the Presence Announcement frame overrides any
2348 * MAC address information from the bootstrapping information. */
2349 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002350
2351 wpa_s->dpp_auth = auth;
2352 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2353 dpp_auth_deinit(wpa_s->dpp_auth);
2354 wpa_s->dpp_auth = NULL;
2355 }
2356}
2357
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002358
2359static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2360 void *timeout_ctx)
2361{
2362 struct wpa_supplicant *wpa_s = eloop_ctx;
2363 struct dpp_authentication *auth = wpa_s->dpp_auth;
2364
2365 if (!auth)
2366 return;
2367
2368 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2369 offchannel_send_action_done(wpa_s);
2370 wpas_dpp_listen_stop(wpa_s);
2371 dpp_auth_deinit(auth);
2372 wpa_s->dpp_auth = NULL;
2373}
2374
2375
2376static void
2377wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2378 const u8 *hdr, const u8 *buf, size_t len,
2379 unsigned int freq)
2380{
Hai Shalom899fcc72020-10-19 14:38:18 -07002381 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2382 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002383 struct dpp_configurator *conf;
2384 struct dpp_authentication *auth;
2385 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002386 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002387
2388 if (!wpa_s->dpp)
2389 return;
2390
2391 if (wpa_s->dpp_auth) {
2392 wpa_printf(MSG_DEBUG,
2393 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2394 return;
2395 }
2396
2397 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2398 MAC2STR(src));
2399
2400 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2401 &csign_hash_len);
2402 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2403 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2404 "Missing or invalid required Configurator C-sign key Hash attribute");
2405 return;
2406 }
2407 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2408 csign_hash, csign_hash_len);
2409 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2410 if (!conf) {
2411 wpa_printf(MSG_DEBUG,
2412 "DPP: No matching Configurator information found");
2413 return;
2414 }
2415
Hai Shalom899fcc72020-10-19 14:38:18 -07002416 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2417 &fcgroup_len);
2418 if (!fcgroup || fcgroup_len != 2) {
2419 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2420 "Missing or invalid required Finite Cyclic Group attribute");
2421 return;
2422 }
2423 group = WPA_GET_LE16(fcgroup);
2424 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2425
2426 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2427 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2428
2429 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2430 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002431 if (!auth)
2432 return;
2433 wpas_dpp_set_testing_options(wpa_s, auth);
2434 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2435 dpp_auth_deinit(auth);
2436 return;
2437 }
2438
2439 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2440 wpa_s->dpp_auth = auth;
2441
2442 wpa_s->dpp_in_response_listen = 0;
2443 wpa_s->dpp_auth_ok_on_ack = 0;
2444 wait_time = wpa_s->max_remain_on_chan;
2445 max_wait_time = wpa_s->dpp_resp_wait_time ?
2446 wpa_s->dpp_resp_wait_time : 2000;
2447 if (wait_time > max_wait_time)
2448 wait_time = max_wait_time;
2449 wait_time += 10; /* give the driver some extra time to complete */
2450 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2451 wpas_dpp_reconfig_reply_wait_timeout,
2452 wpa_s, NULL);
2453 wait_time -= 10;
2454
2455 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2456
2457 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2458 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2459 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2460 wpabuf_head(auth->reconfig_req_msg),
2461 wpabuf_len(auth->reconfig_req_msg),
2462 wait_time, wpas_dpp_tx_status, 0) < 0) {
2463 dpp_auth_deinit(wpa_s->dpp_auth);
2464 wpa_s->dpp_auth = NULL;
2465 }
2466}
2467
2468
2469static void
2470wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2471 const u8 *hdr, const u8 *buf, size_t len,
2472 unsigned int freq)
2473{
2474 struct wpa_ssid *ssid;
2475 struct dpp_authentication *auth;
2476
2477 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2478 MACSTR, MAC2STR(src));
2479
Hai Shalom899fcc72020-10-19 14:38:18 -07002480 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002481 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002482 if (wpa_s->dpp_auth) {
2483 wpa_printf(MSG_DEBUG,
2484 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2485 return;
2486 }
2487 if (!wpa_s->dpp_reconfig_ssid) {
2488 wpa_printf(MSG_DEBUG,
2489 "DPP: Not ready for reconfiguration - not requested");
2490 return;
2491 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002492 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2493 if (ssid == wpa_s->dpp_reconfig_ssid &&
2494 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2495 break;
2496 }
2497 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002498 !ssid->dpp_csign) {
2499 wpa_printf(MSG_DEBUG,
2500 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002501 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002502 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002503
2504 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2505 ssid->dpp_netaccesskey,
2506 ssid->dpp_netaccesskey_len,
2507 ssid->dpp_csign, ssid->dpp_csign_len,
2508 freq, hdr, buf, len);
2509 if (!auth)
2510 return;
2511 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2512 wpa_s->dpp_auth = auth;
2513
2514 wpas_dpp_chirp_stop(wpa_s);
2515
2516 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2517 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2518 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2519 wpabuf_head(auth->reconfig_resp_msg),
2520 wpabuf_len(auth->reconfig_resp_msg),
2521 500, wpas_dpp_tx_status, 0) < 0) {
2522 dpp_auth_deinit(wpa_s->dpp_auth);
2523 wpa_s->dpp_auth = NULL;
2524 }
2525}
2526
2527
2528static void
2529wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2530 const u8 *hdr, const u8 *buf, size_t len,
2531 unsigned int freq)
2532{
2533 struct dpp_authentication *auth = wpa_s->dpp_auth;
2534 struct wpabuf *conf;
2535
2536 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2537 MACSTR, MAC2STR(src));
2538
2539 if (!auth || !auth->reconfig || !auth->configurator) {
2540 wpa_printf(MSG_DEBUG,
2541 "DPP: No DPP Reconfig Authentication in progress - drop");
2542 return;
2543 }
2544
2545 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2546 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2547 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2548 return;
2549 }
2550
2551 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2552 if (!conf)
2553 return;
2554
2555 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2556
2557 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2558 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2559 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2560 wpabuf_head(conf), wpabuf_len(conf),
2561 500, wpas_dpp_tx_status, 0) < 0) {
2562 wpabuf_free(conf);
2563 dpp_auth_deinit(wpa_s->dpp_auth);
2564 wpa_s->dpp_auth = NULL;
2565 return;
2566 }
2567 wpabuf_free(conf);
2568
2569 wpas_dpp_start_gas_server(wpa_s);
2570}
2571
2572
2573static void
2574wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2575 const u8 *hdr, const u8 *buf, size_t len,
2576 unsigned int freq)
2577{
2578 struct dpp_authentication *auth = wpa_s->dpp_auth;
2579
2580 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2581 MACSTR, MAC2STR(src));
2582
2583 if (!auth || !auth->reconfig || auth->configurator) {
2584 wpa_printf(MSG_DEBUG,
2585 "DPP: No DPP Reconfig Authentication in progress - drop");
2586 return;
2587 }
2588
2589 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2590 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2591 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2592 return;
2593 }
2594
2595 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2596 return;
2597
2598 wpas_dpp_start_gas_client(wpa_s);
2599}
2600
Hai Shalom021b0b52019-04-10 11:17:58 -07002601#endif /* CONFIG_DPP2 */
2602
2603
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002604static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2605 const u8 *src,
2606 const u8 *buf, size_t len)
2607{
2608 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002609 const u8 *connector, *trans_id, *status;
2610 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002611#ifdef CONFIG_DPP2
2612 const u8 *version;
2613 u16 version_len;
2614#endif /* CONFIG_DPP2 */
2615 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002616 struct dpp_introduction intro;
2617 struct rsn_pmksa_cache_entry *entry;
2618 struct os_time now;
2619 struct os_reltime rnow;
2620 os_time_t expiry;
2621 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002622 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002623
2624 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2625 MAC2STR(src));
2626 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2627 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2628 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2629 MACSTR " - drop", MAC2STR(src));
2630 return;
2631 }
2632 offchannel_send_action_done(wpa_s);
2633
2634 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2635 if (ssid == wpa_s->dpp_intro_network)
2636 break;
2637 }
2638 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2639 !ssid->dpp_csign) {
2640 wpa_printf(MSG_DEBUG,
2641 "DPP: Profile not found for network introduction");
2642 return;
2643 }
2644
2645 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2646 &trans_id_len);
2647 if (!trans_id || trans_id_len != 1) {
2648 wpa_printf(MSG_DEBUG,
2649 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002650 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2651 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002652 goto fail;
2653 }
2654 if (trans_id[0] != TRANSACTION_ID) {
2655 wpa_printf(MSG_DEBUG,
2656 "DPP: Ignore frame with unexpected Transaction ID %u",
2657 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002658 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2659 " fail=transaction_id_mismatch", MAC2STR(src));
2660 goto fail;
2661 }
2662
2663 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2664 if (!status || status_len != 1) {
2665 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2666 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2667 " fail=missing_status", MAC2STR(src));
2668 goto fail;
2669 }
2670 if (status[0] != DPP_STATUS_OK) {
2671 wpa_printf(MSG_DEBUG,
2672 "DPP: Peer rejected network introduction: Status %u",
2673 status[0]);
2674 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2675 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002676#ifdef CONFIG_DPP2
2677 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2678#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002679 goto fail;
2680 }
2681
2682 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2683 if (!connector) {
2684 wpa_printf(MSG_DEBUG,
2685 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002686 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2687 " fail=missing_connector", MAC2STR(src));
2688 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002689 }
2690
Roshan Pius3a1667e2018-07-03 15:17:14 -07002691 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2692 ssid->dpp_netaccesskey,
2693 ssid->dpp_netaccesskey_len,
2694 ssid->dpp_csign,
2695 ssid->dpp_csign_len,
2696 connector, connector_len, &expiry);
2697 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002698 wpa_printf(MSG_INFO,
2699 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002700 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2701 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002702#ifdef CONFIG_DPP2
2703 wpas_dpp_send_conn_status_result(wpa_s, res);
2704#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002705 goto fail;
2706 }
2707
2708 entry = os_zalloc(sizeof(*entry));
2709 if (!entry)
2710 goto fail;
2711 os_memcpy(entry->aa, src, ETH_ALEN);
2712 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2713 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2714 entry->pmk_len = intro.pmk_len;
2715 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002716#ifdef CONFIG_DPP2
2717 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2718 &version_len);
2719 if (version && version_len >= 1)
2720 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002721#ifdef CONFIG_DPP3
2722 if (intro.peer_version && intro.peer_version >= 2 &&
2723 peer_version != intro.peer_version) {
2724 wpa_printf(MSG_INFO,
2725 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2726 intro.peer_version, peer_version);
2727 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2728 goto fail;
2729 }
2730#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002731 entry->dpp_pfs = peer_version >= 2;
2732#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002733 if (expiry) {
2734 os_get_time(&now);
2735 seconds = expiry - now.sec;
2736 } else {
2737 seconds = 86400 * 7;
2738 }
2739 os_get_reltime(&rnow);
2740 entry->expiration = rnow.sec + seconds;
2741 entry->reauth_time = rnow.sec + seconds;
2742 entry->network_ctx = ssid;
2743 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2744
Roshan Pius3a1667e2018-07-03 15:17:14 -07002745 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002746 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002747
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002748 wpa_printf(MSG_DEBUG,
2749 "DPP: Try connection again after successful network introduction");
2750 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2751 wpa_supplicant_cancel_sched_scan(wpa_s);
2752 wpa_supplicant_req_scan(wpa_s, 0, 0);
2753 }
2754fail:
2755 os_memset(&intro, 0, sizeof(intro));
2756}
2757
2758
Roshan Pius3a1667e2018-07-03 15:17:14 -07002759static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2760{
2761 int i, j;
2762
2763 if (!wpa_s->hw.modes)
2764 return -1;
2765
2766 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2767 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2768
2769 for (j = 0; j < mode->num_channels; j++) {
2770 struct hostapd_channel_data *chan = &mode->channels[j];
2771
2772 if (chan->freq != (int) freq)
2773 continue;
2774
2775 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2776 HOSTAPD_CHAN_NO_IR |
2777 HOSTAPD_CHAN_RADAR))
2778 continue;
2779
2780 return 1;
2781 }
2782 }
2783
2784 wpa_printf(MSG_DEBUG,
2785 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2786 freq);
2787
2788 return 0;
2789}
2790
2791
2792static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2793 struct dpp_pkex *pkex)
2794{
2795 if (pkex->freq == 2437)
2796 pkex->freq = 5745;
2797 else if (pkex->freq == 5745)
2798 pkex->freq = 5220;
2799 else if (pkex->freq == 5220)
2800 pkex->freq = 60480;
2801 else
2802 return -1; /* no more channels to try */
2803
2804 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2805 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2806 pkex->freq);
2807 return 0;
2808 }
2809
2810 /* Could not use this channel - try the next one */
2811 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2812}
2813
2814
Sunil Ravi89eba102022-09-13 21:04:37 -07002815static void wpas_dpp_pkex_clear_code(struct wpa_supplicant *wpa_s)
2816{
2817 if (!wpa_s->dpp_pkex_code && !wpa_s->dpp_pkex_identifier)
2818 return;
2819
2820 /* Delete PKEX code and identifier on successful completion of
2821 * PKEX. We are not supposed to reuse these without being
2822 * explicitly requested to perform PKEX again. */
2823 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
2824 os_free(wpa_s->dpp_pkex_code);
2825 wpa_s->dpp_pkex_code = NULL;
2826 os_free(wpa_s->dpp_pkex_identifier);
2827 wpa_s->dpp_pkex_identifier = NULL;
2828
2829}
2830
2831
Hai Shaloma20dcd72022-02-04 13:43:00 -08002832#ifdef CONFIG_DPP2
2833static int wpas_dpp_pkex_done(void *ctx, void *conn,
2834 struct dpp_bootstrap_info *peer_bi)
2835{
2836 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -07002837 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002838 const char *pos;
2839 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2840 struct dpp_bootstrap_info *own_bi = NULL;
2841 struct dpp_authentication *auth;
2842
Sunil Ravi89eba102022-09-13 21:04:37 -07002843 wpas_dpp_pkex_clear_code(wpa_s);
2844
2845 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
2846 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002847 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
2848 cmd);
2849
2850 pos = os_strstr(cmd, " own=");
2851 if (pos) {
2852 pos += 5;
2853 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
2854 if (!own_bi) {
2855 wpa_printf(MSG_INFO,
2856 "DPP: Could not find bootstrapping info for the identified local entry");
2857 return -1;
2858 }
2859
2860 if (peer_bi->curve != own_bi->curve) {
2861 wpa_printf(MSG_INFO,
2862 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
2863 peer_bi->curve->name, own_bi->curve->name);
2864 return -1;
2865 }
2866 }
2867
2868 pos = os_strstr(cmd, " role=");
2869 if (pos) {
2870 pos += 6;
2871 if (os_strncmp(pos, "configurator", 12) == 0)
2872 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2873 else if (os_strncmp(pos, "enrollee", 8) == 0)
2874 allowed_roles = DPP_CAPAB_ENROLLEE;
2875 else if (os_strncmp(pos, "either", 6) == 0)
2876 allowed_roles = DPP_CAPAB_CONFIGURATOR |
2877 DPP_CAPAB_ENROLLEE;
2878 else
2879 return -1;
2880 }
2881
2882 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
2883 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
2884 if (!auth)
2885 return -1;
2886
2887 wpas_dpp_set_testing_options(wpa_s, auth);
2888 if (dpp_set_configurator(auth, cmd) < 0) {
2889 dpp_auth_deinit(auth);
2890 return -1;
2891 }
2892
2893 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -07002894 DPP_NETROLE_STA,
2895 wpa_s->conf->dpp_mud_url,
2896 wpa_s->conf->dpp_extra_conf_req_name,
2897 wpa_s->conf->dpp_extra_conf_req_value,
2898 wpas_dpp_process_conf_obj,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002899 wpas_dpp_tcp_msg_sent);
2900}
2901#endif /* CONFIG_DPP2 */
2902
2903
Hai Shaloma20dcd72022-02-04 13:43:00 -08002904static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07002905 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002906 const struct hostapd_ip_addr *ipaddr,
2907 int tcp_port)
2908{
2909 struct dpp_pkex *pkex;
2910 struct wpabuf *msg;
2911 unsigned int wait_time;
2912 bool v2 = ver != PKEX_VER_ONLY_1;
2913
2914 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
2915 dpp_pkex_free(wpa_s->dpp_pkex);
2916 wpa_s->dpp_pkex = NULL;
2917 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
2918 wpa_s->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -07002919 wpa_s->dpp_pkex_code, wpa_s->dpp_pkex_code_len,
2920 v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002921 if (!pkex)
2922 return -1;
2923 pkex->forced_ver = ver != PKEX_VER_AUTO;
2924
2925 if (ipaddr) {
2926#ifdef CONFIG_DPP2
2927 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
2928 wpa_s, wpa_s, wpas_dpp_pkex_done);
2929#else /* CONFIG_DPP2 */
2930 return -1;
2931#endif /* CONFIG_DPP2 */
2932 }
2933
2934 wpa_s->dpp_pkex = pkex;
2935 msg = pkex->exchange_req;
2936 wait_time = wpa_s->max_remain_on_chan;
2937 if (wait_time > 2000)
2938 wait_time = 2000;
2939 pkex->freq = 2437;
2940 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2941 " freq=%u type=%d",
2942 MAC2STR(broadcast), pkex->freq,
2943 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2944 DPP_PA_PKEX_V1_EXCHANGE_REQ);
2945 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2946 wpa_s->own_addr, broadcast,
2947 wpabuf_head(msg), wpabuf_len(msg),
2948 wait_time, wpas_dpp_tx_pkex_status, 0);
2949 if (wait_time == 0)
2950 wait_time = 2000;
2951 pkex->exch_req_wait_time = wait_time;
2952 pkex->exch_req_tries = 1;
2953
2954 return 0;
2955}
2956
2957
Roshan Pius3a1667e2018-07-03 15:17:14 -07002958static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
2959{
2960 struct wpa_supplicant *wpa_s = eloop_ctx;
2961 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2962
2963 if (!pkex || !pkex->exchange_req)
2964 return;
2965 if (pkex->exch_req_tries >= 5) {
2966 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002967#ifdef CONFIG_DPP3
2968 if (pkex->v2 && !pkex->forced_ver) {
2969 wpa_printf(MSG_DEBUG,
2970 "DPP: Fall back to PKEXv1");
2971 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
2972 NULL, 0);
2973 return;
2974 }
2975#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002976 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2977 "No response from PKEX peer");
2978 dpp_pkex_free(pkex);
2979 wpa_s->dpp_pkex = NULL;
2980 return;
2981 }
2982 pkex->exch_req_tries = 0;
2983 }
2984
2985 pkex->exch_req_tries++;
2986 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
2987 pkex->exch_req_tries);
2988 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08002989 MAC2STR(broadcast), pkex->freq,
2990 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2991 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002992 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2993 wpa_s->own_addr, broadcast,
2994 wpabuf_head(pkex->exchange_req),
2995 wpabuf_len(pkex->exchange_req),
2996 pkex->exch_req_wait_time,
2997 wpas_dpp_tx_pkex_status, 0);
2998}
2999
3000
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003001static void
3002wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
3003 unsigned int freq, const u8 *dst,
3004 const u8 *src, const u8 *bssid,
3005 const u8 *data, size_t data_len,
3006 enum offchannel_send_action_result result)
3007{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003008 const char *res_txt;
3009 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3010
3011 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3012 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3013 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003014 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3015 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003016 freq, MAC2STR(dst), res_txt);
3017 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3018 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3019
3020 if (!pkex) {
3021 wpa_printf(MSG_DEBUG,
3022 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
3023 return;
3024 }
3025
3026 if (pkex->failed) {
3027 wpa_printf(MSG_DEBUG,
3028 "DPP: Terminate PKEX exchange due to an earlier error");
3029 if (pkex->t > pkex->own_bi->pkex_t)
3030 pkex->own_bi->pkex_t = pkex->t;
3031 dpp_pkex_free(pkex);
3032 wpa_s->dpp_pkex = NULL;
3033 return;
3034 }
3035
3036 if (pkex->exch_req_wait_time && pkex->exchange_req) {
3037 /* Wait for PKEX Exchange Response frame and retry request if
3038 * no response is seen. */
3039 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3040 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
3041 (pkex->exch_req_wait_time % 1000) * 1000,
3042 wpas_dpp_pkex_retry_timeout, wpa_s,
3043 NULL);
3044 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003045}
3046
3047
3048static void
3049wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003050 const u8 *buf, size_t len, unsigned int freq,
3051 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003052{
3053 struct wpabuf *msg;
3054 unsigned int wait_time;
3055
3056 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
3057 MAC2STR(src));
3058
Sunil Ravia04bd252022-05-02 22:54:18 -07003059 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
3060 wpa_printf(MSG_DEBUG,
3061 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
3062 return;
3063 }
3064 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
3065 wpa_printf(MSG_DEBUG,
3066 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
3067 return;
3068 }
3069
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003070 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3071 * values here */
3072
3073 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
3074 wpa_printf(MSG_DEBUG,
3075 "DPP: No PKEX code configured - ignore request");
3076 return;
3077 }
3078
Sunil Ravi89eba102022-09-13 21:04:37 -07003079#ifdef CONFIG_DPP2
3080 if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) {
3081 wpa_printf(MSG_DEBUG,
3082 "DPP: PKEX Exchange Request is from local Controller - ignore request");
3083 return;
3084 }
3085#endif /* CONFIG_DPP2 */
3086
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003087 if (wpa_s->dpp_pkex) {
3088 /* TODO: Support parallel operations */
3089 wpa_printf(MSG_DEBUG,
3090 "DPP: Already in PKEX session - ignore new request");
3091 return;
3092 }
3093
Roshan Pius3a1667e2018-07-03 15:17:14 -07003094 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003095 wpa_s->own_addr, src,
3096 wpa_s->dpp_pkex_identifier,
3097 wpa_s->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07003098 wpa_s->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003099 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003100 if (!wpa_s->dpp_pkex) {
3101 wpa_printf(MSG_DEBUG,
3102 "DPP: Failed to process the request - ignore it");
3103 return;
3104 }
3105
Sunil Ravi89eba102022-09-13 21:04:37 -07003106#ifdef CONFIG_DPP3
3107 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_announcement) {
3108 wpa_printf(MSG_DEBUG,
3109 "DPP: Started PB PKEX (no more PB announcements)");
3110 wpabuf_free(wpa_s->dpp_pb_announcement);
3111 wpa_s->dpp_pb_announcement = NULL;
3112 }
3113#endif /* CONFIG_DPP3 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003114 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003115 msg = wpa_s->dpp_pkex->exchange_resp;
3116 wait_time = wpa_s->max_remain_on_chan;
3117 if (wait_time > 2000)
3118 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003119 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3120 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003121 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3122 broadcast,
3123 wpabuf_head(msg), wpabuf_len(msg),
3124 wait_time, wpas_dpp_tx_pkex_status, 0);
3125}
3126
3127
3128static void
3129wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3130 const u8 *buf, size_t len, unsigned int freq)
3131{
3132 struct wpabuf *msg;
3133 unsigned int wait_time;
3134
3135 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
3136 MAC2STR(src));
3137
3138 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3139 * values here */
3140
3141 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3142 wpa_s->dpp_pkex->exchange_done) {
3143 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3144 return;
3145 }
3146
Roshan Pius3a1667e2018-07-03 15:17:14 -07003147 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3148 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3149
3150 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003151 if (!msg) {
3152 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3153 return;
3154 }
3155
3156 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3157 MAC2STR(src));
3158
3159 wait_time = wpa_s->max_remain_on_chan;
3160 if (wait_time > 2000)
3161 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003162 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3163 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003164 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3165 broadcast,
3166 wpabuf_head(msg), wpabuf_len(msg),
3167 wait_time, wpas_dpp_tx_pkex_status, 0);
3168 wpabuf_free(msg);
3169}
3170
3171
Roshan Pius3a1667e2018-07-03 15:17:14 -07003172static struct dpp_bootstrap_info *
3173wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3174 unsigned int freq)
3175{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003176 struct dpp_bootstrap_info *bi;
3177
Sunil Ravi89eba102022-09-13 21:04:37 -07003178 wpas_dpp_pkex_clear_code(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003179 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003180 if (!bi)
3181 return NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003182
Roshan Pius3a1667e2018-07-03 15:17:14 -07003183 wpa_s->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003184
3185#ifdef CONFIG_DPP3
3186 if (wpa_s->dpp_pb_bi && !wpa_s->dpp_pb_configurator &&
3187 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_init_hash,
3188 SHA256_MAC_LEN) != 0) {
3189 char id[20];
3190
3191 wpa_printf(MSG_INFO,
3192 "DPP: Peer bootstrap key from PKEX does not match PB announcement response hash");
3193 wpa_hexdump(MSG_DEBUG,
3194 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3195 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3196 wpa_hexdump(MSG_DEBUG,
3197 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement response",
3198 wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN);
3199
3200 os_snprintf(id, sizeof(id), "%u", bi->id);
3201 dpp_bootstrap_remove(wpa_s->dpp, id);
3202 wpas_dpp_push_button_stop(wpa_s);
3203 return NULL;
3204 }
3205#endif /* CONFIG_DPP3 */
3206
Roshan Pius3a1667e2018-07-03 15:17:14 -07003207 return bi;
3208}
3209
3210
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003211static void
3212wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3213 const u8 *hdr, const u8 *buf, size_t len,
3214 unsigned int freq)
3215{
3216 struct wpabuf *msg;
3217 unsigned int wait_time;
3218 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003219
3220 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3221 MAC2STR(src));
3222
3223 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3224 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3225 return;
3226 }
3227
3228 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3229 if (!msg) {
3230 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003231 if (pkex->failed) {
3232 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3233 if (pkex->t > pkex->own_bi->pkex_t)
3234 pkex->own_bi->pkex_t = pkex->t;
3235 dpp_pkex_free(wpa_s->dpp_pkex);
3236 wpa_s->dpp_pkex = NULL;
3237 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003238 return;
3239 }
3240
3241 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3242 MACSTR, MAC2STR(src));
3243
3244 wait_time = wpa_s->max_remain_on_chan;
3245 if (wait_time > 2000)
3246 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003247 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3248 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003249 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3250 broadcast,
3251 wpabuf_head(msg), wpabuf_len(msg),
3252 wait_time, wpas_dpp_tx_pkex_status, 0);
3253 wpabuf_free(msg);
3254
Roshan Pius3a1667e2018-07-03 15:17:14 -07003255 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003256 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003257}
3258
3259
3260static void
3261wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3262 const u8 *hdr, const u8 *buf, size_t len,
3263 unsigned int freq)
3264{
3265 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003266 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003267 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3268 char cmd[500];
3269
3270 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3271 MAC2STR(src));
3272
3273 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3274 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3275 return;
3276 }
3277
3278 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3279 if (res < 0) {
3280 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3281 return;
3282 }
3283
Roshan Pius3a1667e2018-07-03 15:17:14 -07003284 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003285 if (!bi)
3286 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003287
Sunil Ravi89eba102022-09-13 21:04:37 -07003288#ifdef CONFIG_DPP3
3289 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_configurator &&
3290 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_resp_hash,
3291 SHA256_MAC_LEN) != 0) {
3292 char id[20];
3293
3294 wpa_printf(MSG_INFO,
3295 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
3296 wpa_hexdump(MSG_DEBUG,
3297 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3298 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3299 wpa_hexdump(MSG_DEBUG,
3300 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
3301 wpa_s->dpp_pb_resp_hash, SHA256_MAC_LEN);
3302
3303 os_snprintf(id, sizeof(id), "%u", bi->id);
3304 dpp_bootstrap_remove(wpa_s->dpp, id);
3305 wpas_dpp_push_button_stop(wpa_s);
3306 return;
3307 }
3308#endif /* CONFIG_DPP3 */
3309
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003310 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3311 bi->id,
3312 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3313 wpa_printf(MSG_DEBUG,
3314 "DPP: Start authentication after PKEX with parameters: %s",
3315 cmd);
3316 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3317 wpa_printf(MSG_DEBUG,
3318 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003319 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003320 return;
3321 }
3322}
3323
3324
Sunil Ravi89eba102022-09-13 21:04:37 -07003325#ifdef CONFIG_DPP3
3326
3327static void wpas_dpp_pb_pkex_init(struct wpa_supplicant *wpa_s,
3328 unsigned int freq, const u8 *src,
3329 const u8 *r_hash)
3330{
3331 struct dpp_pkex *pkex;
3332 struct wpabuf *msg;
3333 unsigned int wait_time;
3334 size_t len;
3335
3336 if (wpa_s->dpp_pkex) {
3337 wpa_printf(MSG_DEBUG,
3338 "DPP: Sending previously generated PKEX Exchange Request to "
3339 MACSTR, MAC2STR(src));
3340 msg = wpa_s->dpp_pkex->exchange_req;
3341 wait_time = wpa_s->max_remain_on_chan;
3342 if (wait_time > 2000)
3343 wait_time = 2000;
3344 offchannel_send_action(wpa_s, freq, src,
3345 wpa_s->own_addr, broadcast,
3346 wpabuf_head(msg), wpabuf_len(msg),
3347 wait_time, wpas_dpp_tx_pkex_status, 0);
3348 return;
3349 }
3350
3351 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
3352 MACSTR, MAC2STR(src));
3353
3354 if (!wpa_s->dpp_pb_cmd) {
3355 wpa_printf(MSG_INFO,
3356 "DPP: No configuration to provision as push button Configurator");
3357 wpas_dpp_push_button_stop(wpa_s);
3358 return;
3359 }
3360
3361 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
3362 os_memcpy(wpa_s->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
3363
3364 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3365 "PBPKEX", (const char *) wpa_s->dpp_pb_c_nonce,
3366 wpa_s->dpp_pb_bi->curve->nonce_len,
3367 true);
3368 if (!pkex) {
3369 wpas_dpp_push_button_stop(wpa_s);
3370 return;
3371 }
3372 pkex->freq = freq;
3373
3374 wpa_s->dpp_pkex = pkex;
3375 msg = wpa_s->dpp_pkex->exchange_req;
3376 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3377 " freq=%u type=%d", MAC2STR(src), freq,
3378 DPP_PA_PKEX_EXCHANGE_REQ);
3379 wait_time = wpa_s->max_remain_on_chan;
3380 if (wait_time > 2000)
3381 wait_time = 2000;
3382 offchannel_send_action(wpa_s, pkex->freq, src,
3383 wpa_s->own_addr, broadcast,
3384 wpabuf_head(msg), wpabuf_len(msg),
3385 wait_time, wpas_dpp_tx_pkex_status, 0);
3386 pkex->exch_req_wait_time = 2000;
3387 pkex->exch_req_tries = 1;
3388
3389 /* Use the externally provided configuration */
3390 os_free(wpa_s->dpp_pkex_auth_cmd);
3391 len = 30 + os_strlen(wpa_s->dpp_pb_cmd);
3392 wpa_s->dpp_pkex_auth_cmd = os_malloc(len);
3393 if (wpa_s->dpp_pkex_auth_cmd)
3394 os_snprintf(wpa_s->dpp_pkex_auth_cmd, len, " own=%d %s",
3395 wpa_s->dpp_pkex_bi->id, wpa_s->dpp_pb_cmd);
3396 else
3397 wpas_dpp_push_button_stop(wpa_s);
3398}
3399
3400
3401static void
3402wpas_dpp_rx_pb_presence_announcement(struct wpa_supplicant *wpa_s,
3403 const u8 *src, const u8 *hdr,
3404 const u8 *buf, size_t len,
3405 unsigned int freq)
3406{
3407 const u8 *r_hash;
3408 u16 r_hash_len;
3409 unsigned int i;
3410 bool found = false;
3411 struct dpp_pb_info *info, *tmp;
3412 struct os_reltime now, age;
3413 struct wpabuf *msg;
3414
3415 os_get_reltime(&now);
3416 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
3417 MACSTR, MAC2STR(src));
3418
3419 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3420 &r_hash_len);
3421 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
3422 wpa_printf(MSG_DEBUG,
3423 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
3424 return;
3425 }
3426 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3427 r_hash, r_hash_len);
3428
3429 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3430 info = &wpa_s->dpp_pb[i];
3431 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
3432 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
3433 continue;
3434 wpa_printf(MSG_DEBUG,
3435 "DPP: Active push button Enrollee already known");
3436 found = true;
3437 info->rx_time = now;
3438 }
3439
3440 if (!found) {
3441 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3442 tmp = &wpa_s->dpp_pb[i];
3443 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
3444 continue;
3445
3446 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
3447 wpa_hexdump(MSG_DEBUG,
3448 "DPP: Push button Enrollee hash expired",
3449 tmp->hash, SHA256_MAC_LEN);
3450 tmp->rx_time.sec = 0;
3451 tmp->rx_time.usec = 0;
3452 continue;
3453 }
3454
3455 wpa_hexdump(MSG_DEBUG,
3456 "DPP: Push button session overlap with hash",
3457 tmp->hash, SHA256_MAC_LEN);
3458 if (!wpa_s->dpp_pb_result_indicated &&
3459 wpas_dpp_pb_active(wpa_s)) {
3460 wpa_msg(wpa_s, MSG_INFO,
3461 DPP_EVENT_PB_RESULT "session-overlap");
3462 wpa_s->dpp_pb_result_indicated = true;
3463 }
3464 wpas_dpp_push_button_stop(wpa_s);
3465 return;
3466 }
3467
3468 /* Replace the oldest entry */
3469 info = &wpa_s->dpp_pb[0];
3470 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
3471 tmp = &wpa_s->dpp_pb[i];
3472 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
3473 info = tmp;
3474 }
3475 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
3476 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
3477 info->rx_time = now;
3478 }
3479
3480 if (!wpas_dpp_pb_active(wpa_s)) {
3481 wpa_printf(MSG_DEBUG,
3482 "DPP: Discard message since own push button has not been pressed");
3483 return;
3484 }
3485
3486 if (wpa_s->dpp_pb_announce_time.sec == 0 &&
3487 wpa_s->dpp_pb_announce_time.usec == 0) {
3488 /* Start a wait before allowing PKEX to be initiated */
3489 wpa_s->dpp_pb_announce_time = now;
3490 }
3491
3492 if (!wpa_s->dpp_pb_bi) {
3493 int res;
3494
3495 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
3496 if (res < 0)
3497 return;
3498 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
3499 if (!wpa_s->dpp_pb_bi)
3500 return;
3501
3502 if (random_get_bytes(wpa_s->dpp_pb_c_nonce,
3503 wpa_s->dpp_pb_bi->curve->nonce_len)) {
3504 wpa_printf(MSG_ERROR,
3505 "DPP: Failed to generate C-nonce");
3506 wpas_dpp_push_button_stop(wpa_s);
3507 return;
3508 }
3509 }
3510
3511 /* Skip the response if one was sent within last 50 ms since the
3512 * Enrollee is going to send out at least three announcement messages.
3513 */
3514 os_reltime_sub(&now, &wpa_s->dpp_pb_last_resp, &age);
3515 if (age.sec == 0 && age.usec < 50000) {
3516 wpa_printf(MSG_DEBUG,
3517 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
3518 return;
3519 }
3520
3521 msg = dpp_build_pb_announcement_resp(
3522 wpa_s->dpp_pb_bi, r_hash, wpa_s->dpp_pb_c_nonce,
3523 wpa_s->dpp_pb_bi->curve->nonce_len);
3524 if (!msg) {
3525 wpas_dpp_push_button_stop(wpa_s);
3526 return;
3527 }
3528
3529 wpa_printf(MSG_DEBUG,
3530 "DPP: Send Push Button Presence Announcement Response to "
3531 MACSTR, MAC2STR(src));
3532 wpa_s->dpp_pb_last_resp = now;
3533
3534 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3535 MAC2STR(src), freq, DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
3536 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
3537 wpabuf_head(msg), wpabuf_len(msg),
3538 0, NULL, 0);
3539 wpabuf_free(msg);
3540
3541 if (os_reltime_expired(&now, &wpa_s->dpp_pb_announce_time, 15))
3542 wpas_dpp_pb_pkex_init(wpa_s, freq, src, r_hash);
3543}
3544
3545
3546static void
3547wpas_dpp_rx_pb_presence_announcement_resp(struct wpa_supplicant *wpa_s,
3548 const u8 *src, const u8 *hdr,
3549 const u8 *buf, size_t len,
3550 unsigned int freq)
3551{
3552 const u8 *i_hash, *r_hash, *c_nonce;
3553 u16 i_hash_len, r_hash_len, c_nonce_len;
3554 bool overlap = false;
3555
3556 if (!wpa_s->dpp_pb_announcement || !wpa_s->dpp_pb_bi ||
3557 wpa_s->dpp_pb_configurator) {
3558 wpa_printf(MSG_INFO,
3559 "DPP: Not in active push button Enrollee mode - discard Push Button Presence Announcement Response from "
3560 MACSTR, MAC2STR(src));
3561 return;
3562 }
3563
3564 wpa_printf(MSG_DEBUG,
3565 "DPP: Push Button Presence Announcement Response from "
3566 MACSTR, MAC2STR(src));
3567
3568 i_hash = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3569 &i_hash_len);
3570 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3571 &r_hash_len);
3572 c_nonce = dpp_get_attr(buf, len, DPP_ATTR_CONFIGURATOR_NONCE,
3573 &c_nonce_len);
3574 if (!i_hash || i_hash_len != SHA256_MAC_LEN ||
3575 !r_hash || r_hash_len != SHA256_MAC_LEN ||
3576 !c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
3577 wpa_printf(MSG_DEBUG,
3578 "DPP: Missing or invalid required attribute");
3579 return;
3580 }
3581 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
3582 i_hash, i_hash_len);
3583 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3584 r_hash, r_hash_len);
3585 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator Nonce",
3586 c_nonce, c_nonce_len);
3587
3588#ifdef CONFIG_TESTING_OPTIONS
3589 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ &&
3590 os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3591 SHA256_MAC_LEN - 1) == 0)
3592 goto skip_hash_check;
3593#endif /* CONFIG_TESTING_OPTIONS */
3594 if (os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3595 SHA256_MAC_LEN) != 0) {
3596 wpa_printf(MSG_INFO,
3597 "DPP: Unexpected push button Responder hash - abort");
3598 overlap = true;
3599 }
3600#ifdef CONFIG_TESTING_OPTIONS
3601skip_hash_check:
3602#endif /* CONFIG_TESTING_OPTIONS */
3603
3604 if (wpa_s->dpp_pb_resp_freq &&
3605 os_memcmp(i_hash, wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN) != 0) {
3606 wpa_printf(MSG_INFO,
3607 "DPP: Push button session overlap detected - abort");
3608 overlap = true;
3609 }
3610
3611 if (overlap) {
3612 if (!wpa_s->dpp_pb_result_indicated) {
3613 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
3614 "session-overlap");
3615 wpa_s->dpp_pb_result_indicated = true;
3616 }
3617 wpas_dpp_push_button_stop(wpa_s);
3618 return;
3619 }
3620
3621 if (!wpa_s->dpp_pb_resp_freq) {
3622 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
3623 "discovered push button AP/Configurator " MACSTR,
3624 MAC2STR(src));
3625 wpa_s->dpp_pb_resp_freq = freq;
3626 os_memcpy(wpa_s->dpp_pb_init_hash, i_hash, SHA256_MAC_LEN);
3627 os_memcpy(wpa_s->dpp_pb_c_nonce, c_nonce, c_nonce_len);
3628 wpa_s->dpp_pb_c_nonce_len = c_nonce_len;
3629 /* Stop announcement iterations after at least one more full
3630 * round and one extra round for postponed session overlap
3631 * detection. */
3632 wpa_s->dpp_pb_stop_iter = 3;
3633 }
3634}
3635
3636
3637static void
3638wpas_dpp_tx_priv_intro_status(struct wpa_supplicant *wpa_s,
3639 unsigned int freq, const u8 *dst,
3640 const u8 *src, const u8 *bssid,
3641 const u8 *data, size_t data_len,
3642 enum offchannel_send_action_result result)
3643{
3644 const char *res_txt;
3645
3646 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3647 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3648 "FAILED");
3649 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3650 " result=%s (DPP Private Peer Introduction Update)",
3651 freq, MAC2STR(dst), res_txt);
3652 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3653 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3654
3655 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR " version=%u",
3656 MAC2STR(src), wpa_s->dpp_intro_peer_version);
3657
3658 wpa_printf(MSG_DEBUG,
3659 "DPP: Try connection again after successful network introduction");
3660 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3661 wpa_supplicant_cancel_sched_scan(wpa_s);
3662 wpa_supplicant_req_scan(wpa_s, 0, 0);
3663 }
3664}
3665
3666
3667static int
3668wpas_dpp_send_private_peer_intro_update(struct wpa_supplicant *wpa_s,
3669 struct dpp_introduction *intro,
3670 struct wpa_ssid *ssid,
3671 const u8 *dst, unsigned int freq)
3672{
3673 struct wpabuf *pt, *msg, *enc_ct;
3674 size_t len;
3675 u8 ver = DPP_VERSION;
3676 int conn_ver;
3677 const u8 *aad;
3678 size_t aad_len;
3679 unsigned int wait_time;
3680
3681 wpa_printf(MSG_DEBUG, "HPKE(kem_id=%u kdf_id=%u aead_id=%u)",
3682 intro->kem_id, intro->kdf_id, intro->aead_id);
3683
3684 /* Plaintext for HPKE */
3685 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3686 pt = wpabuf_alloc(len);
3687 if (!pt)
3688 return -1;
3689
3690 /* Protocol Version */
3691 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3692 if (conn_ver > 0 && ver != conn_ver) {
3693 wpa_printf(MSG_DEBUG,
3694 "DPP: Use Connector version %d instead of current protocol version %d",
3695 conn_ver, ver);
3696 ver = conn_ver;
3697 }
3698 wpabuf_put_le16(pt, DPP_ATTR_PROTOCOL_VERSION);
3699 wpabuf_put_le16(pt, 1);
3700 wpabuf_put_u8(pt, ver);
3701
3702 /* Connector */
3703 wpabuf_put_le16(pt, DPP_ATTR_CONNECTOR);
3704 wpabuf_put_le16(pt, os_strlen(ssid->dpp_connector));
3705 wpabuf_put_str(pt, ssid->dpp_connector);
3706 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Plaintext for HPKE", pt);
3707
3708 /* HPKE(pt) using AP's public key (from its Connector) */
3709 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, 0);
3710 if (!msg) {
3711 wpabuf_free(pt);
3712 return -1;
3713 }
3714 aad = wpabuf_head_u8(msg) + 2; /* from the OUI field (inclusive) */
3715 aad_len = DPP_HDR_LEN; /* to the DPP Frame Type field (inclusive) */
3716 wpa_hexdump(MSG_MSGDUMP, "DPP: AAD for HPKE", aad, aad_len);
3717
3718 enc_ct = hpke_base_seal(intro->kem_id, intro->kdf_id, intro->aead_id,
3719 intro->peer_key, NULL, 0, aad, aad_len,
3720 wpabuf_head(pt), wpabuf_len(pt));
3721 wpabuf_free(pt);
3722 wpabuf_free(msg);
3723 if (!enc_ct) {
3724 wpa_printf(MSG_INFO, "DPP: HPKE Seal(Connector) failed");
3725 return -1;
3726 }
3727 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE enc|ct", enc_ct);
3728
3729 /* HPKE(pt) to generate payload for Wrapped Data */
3730 len = 5 + 4 + wpabuf_len(enc_ct);
3731 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, len);
3732 if (!msg) {
3733 wpabuf_free(enc_ct);
3734 return -1;
3735 }
3736
3737 /* Transaction ID */
3738 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3739 wpabuf_put_le16(msg, 1);
3740 wpabuf_put_u8(msg, TRANSACTION_ID);
3741
3742 /* Wrapped Data */
3743 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3744 wpabuf_put_le16(msg, wpabuf_len(enc_ct));
3745 wpabuf_put_buf(msg, enc_ct);
3746 wpabuf_free(enc_ct);
3747
3748 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Update", msg);
3749
3750 /* TODO: Timeout on AP response */
3751 wait_time = wpa_s->max_remain_on_chan;
3752 if (wait_time > 2000)
3753 wait_time = 2000;
3754 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3755 MAC2STR(dst), freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
3756 offchannel_send_action(wpa_s, freq, dst, wpa_s->own_addr, broadcast,
3757 wpabuf_head(msg), wpabuf_len(msg),
3758 wait_time, wpas_dpp_tx_priv_intro_status, 0);
3759 wpabuf_free(msg);
3760
3761 return 0;
3762}
3763
3764
3765static void
3766wpas_dpp_rx_priv_peer_intro_notify(struct wpa_supplicant *wpa_s,
3767 const u8 *src, const u8 *hdr,
3768 const u8 *buf, size_t len,
3769 unsigned int freq)
3770{
3771 struct wpa_ssid *ssid;
3772 const u8 *connector, *trans_id, *version;
3773 u16 connector_len, trans_id_len, version_len;
3774 u8 peer_version = 1;
3775 struct dpp_introduction intro;
3776 struct rsn_pmksa_cache_entry *entry;
3777 struct os_time now;
3778 struct os_reltime rnow;
3779 os_time_t expiry;
3780 unsigned int seconds;
3781 enum dpp_status_error res;
3782
3783 os_memset(&intro, 0, sizeof(intro));
3784
3785 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
3786 MACSTR, MAC2STR(src));
3787 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
3788 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
3789 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
3790 MACSTR " - drop", MAC2STR(src));
3791 return;
3792 }
3793 offchannel_send_action_done(wpa_s);
3794
3795 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3796 if (ssid == wpa_s->dpp_intro_network)
3797 break;
3798 }
3799 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3800 !ssid->dpp_csign) {
3801 wpa_printf(MSG_DEBUG,
3802 "DPP: Profile not found for network introduction");
3803 return;
3804 }
3805
3806 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
3807 &trans_id_len);
3808 if (!trans_id || trans_id_len != 1) {
3809 wpa_printf(MSG_DEBUG,
3810 "DPP: Peer did not include Transaction ID");
3811 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3812 " fail=missing_transaction_id", MAC2STR(src));
3813 goto fail;
3814 }
3815 if (trans_id[0] != TRANSACTION_ID) {
3816 wpa_printf(MSG_DEBUG,
3817 "DPP: Ignore frame with unexpected Transaction ID %u",
3818 trans_id[0]);
3819 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3820 " fail=transaction_id_mismatch", MAC2STR(src));
3821 goto fail;
3822 }
3823
3824 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
3825 if (!connector) {
3826 wpa_printf(MSG_DEBUG,
3827 "DPP: Peer did not include its Connector");
3828 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3829 " fail=missing_connector", MAC2STR(src));
3830 goto fail;
3831 }
3832
3833 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
3834 &version_len);
3835 if (!version || version_len < 1) {
3836 wpa_printf(MSG_DEBUG,
3837 "DPP: Peer did not include valid Version");
3838 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3839 " fail=missing_version", MAC2STR(src));
3840 goto fail;
3841 }
3842
3843 res = dpp_peer_intro(&intro, ssid->dpp_connector,
3844 ssid->dpp_netaccesskey,
3845 ssid->dpp_netaccesskey_len,
3846 ssid->dpp_csign,
3847 ssid->dpp_csign_len,
3848 connector, connector_len, &expiry);
3849 if (res != DPP_STATUS_OK) {
3850 wpa_printf(MSG_INFO,
3851 "DPP: Network Introduction protocol resulted in failure");
3852 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3853 " fail=peer_connector_validation_failed", MAC2STR(src));
3854 wpas_dpp_send_conn_status_result(wpa_s, res);
3855 goto fail;
3856 }
3857
3858 peer_version = version[0];
3859 if (intro.peer_version && intro.peer_version >= 2 &&
3860 peer_version != intro.peer_version) {
3861 wpa_printf(MSG_INFO,
3862 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
3863 intro.peer_version, peer_version);
3864 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
3865 goto fail;
3866 }
3867 wpa_s->dpp_intro_peer_version = peer_version;
3868
3869 entry = os_zalloc(sizeof(*entry));
3870 if (!entry)
3871 goto fail;
3872 entry->dpp_pfs = peer_version >= 2;
3873 os_memcpy(entry->aa, src, ETH_ALEN);
3874 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
3875 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
3876 entry->pmk_len = intro.pmk_len;
3877 entry->akmp = WPA_KEY_MGMT_DPP;
3878 if (expiry) {
3879 os_get_time(&now);
3880 seconds = expiry - now.sec;
3881 } else {
3882 seconds = 86400 * 7;
3883 }
3884
3885 if (wpas_dpp_send_private_peer_intro_update(wpa_s, &intro, ssid, src,
3886 freq) < 0) {
3887 os_free(entry);
3888 goto fail;
3889 }
3890
3891 os_get_reltime(&rnow);
3892 entry->expiration = rnow.sec + seconds;
3893 entry->reauth_time = rnow.sec + seconds;
3894 entry->network_ctx = ssid;
3895 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
3896
3897 /* Association will be initiated from TX status handler for the Private
3898 * Peer Intro Update: wpas_dpp_tx_priv_intro_status() */
3899
3900fail:
3901 dpp_peer_intro_deinit(&intro);
3902}
3903
3904#endif /* CONFIG_DPP3 */
3905
3906
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003907void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
3908 const u8 *buf, size_t len, unsigned int freq)
3909{
3910 u8 crypto_suite;
3911 enum dpp_public_action_frame_type type;
3912 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003913 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003914
3915 if (len < DPP_HDR_LEN)
3916 return;
3917 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
3918 return;
3919 hdr = buf;
3920 buf += 4;
3921 len -= 4;
3922 crypto_suite = *buf++;
3923 type = *buf++;
3924 len -= 2;
3925
3926 wpa_printf(MSG_DEBUG,
3927 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
3928 MACSTR " freq=%u",
3929 crypto_suite, type, MAC2STR(src), freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07003930#ifdef CONFIG_TESTING_OPTIONS
3931 if (wpa_s->dpp_discard_public_action &&
3932 type != DPP_PA_PEER_DISCOVERY_RESP &&
3933 type != DPP_PA_PRIV_PEER_INTRO_NOTIFY) {
3934 wpa_printf(MSG_DEBUG,
3935 "TESTING: Discard received DPP Public Action frame");
3936 return;
3937 }
3938#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003939 if (crypto_suite != 1) {
3940 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
3941 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003942 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3943 " freq=%u type=%d ignore=unsupported-crypto-suite",
3944 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003945 return;
3946 }
3947 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003948 if (dpp_check_attrs(buf, len) < 0) {
3949 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3950 " freq=%u type=%d ignore=invalid-attributes",
3951 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003952 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003953 }
3954 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
3955 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003956
3957 switch (type) {
3958 case DPP_PA_AUTHENTICATION_REQ:
3959 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
3960 break;
3961 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07003962 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003963 break;
3964 case DPP_PA_AUTHENTICATION_CONF:
3965 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
3966 break;
3967 case DPP_PA_PEER_DISCOVERY_RESP:
3968 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
3969 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003970#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003971 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003972 /* This is for PKEXv2, but for now, process only with
3973 * CONFIG_DPP3 to avoid issues with a capability that has not
3974 * been tested with other implementations. */
3975 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
3976 break;
3977#endif /* CONFIG_DPP3 */
3978 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
3979 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
3980 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003981 break;
3982 case DPP_PA_PKEX_EXCHANGE_RESP:
3983 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
3984 break;
3985 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
3986 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
3987 freq);
3988 break;
3989 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
3990 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
3991 freq);
3992 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07003993#ifdef CONFIG_DPP2
3994 case DPP_PA_CONFIGURATION_RESULT:
3995 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
3996 break;
Hai Shalomc3565922019-10-28 11:58:20 -07003997 case DPP_PA_CONNECTION_STATUS_RESULT:
3998 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
3999 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07004000 case DPP_PA_PRESENCE_ANNOUNCEMENT:
4001 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
4002 freq);
4003 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004004 case DPP_PA_RECONFIG_ANNOUNCEMENT:
4005 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
4006 freq);
4007 break;
4008 case DPP_PA_RECONFIG_AUTH_REQ:
4009 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
4010 break;
4011 case DPP_PA_RECONFIG_AUTH_RESP:
4012 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
4013 break;
4014 case DPP_PA_RECONFIG_AUTH_CONF:
4015 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
4016 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004017#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07004018#ifdef CONFIG_DPP3
4019 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
4020 wpas_dpp_rx_pb_presence_announcement(wpa_s, src, hdr,
4021 buf, len, freq);
4022 break;
4023 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP:
4024 wpas_dpp_rx_pb_presence_announcement_resp(wpa_s, src, hdr,
4025 buf, len, freq);
4026 break;
4027 case DPP_PA_PRIV_PEER_INTRO_NOTIFY:
4028 wpas_dpp_rx_priv_peer_intro_notify(wpa_s, src, hdr,
4029 buf, len, freq);
4030 break;
4031#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004032 default:
4033 wpa_printf(MSG_DEBUG,
4034 "DPP: Ignored unsupported frame subtype %d", type);
4035 break;
4036 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004037
4038 if (wpa_s->dpp_pkex)
4039 pkex_t = wpa_s->dpp_pkex->t;
4040 else if (wpa_s->dpp_pkex_bi)
4041 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
4042 else
4043 pkex_t = 0;
4044 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
4045 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
4046 wpas_dpp_pkex_remove(wpa_s, "*");
4047 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004048}
4049
4050
Hai Shaloma20dcd72022-02-04 13:43:00 -08004051static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
4052 void *timeout_ctx)
4053{
4054 struct wpa_supplicant *wpa_s = eloop_ctx;
4055 struct dpp_authentication *auth = wpa_s->dpp_auth;
4056
4057 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
4058 return;
4059
4060 wpa_printf(MSG_DEBUG,
4061 "DPP: No configuration available from upper layers - send initial response with comeback delay");
4062 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
4063 500);
4064}
4065
4066
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004067static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07004068wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08004069 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004070{
4071 struct wpa_supplicant *wpa_s = ctx;
4072 struct dpp_authentication *auth = wpa_s->dpp_auth;
4073 struct wpabuf *resp;
4074
4075 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
4076 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004077 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004078 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
4079 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
4080 return NULL;
4081 }
Hai Shalomc3565922019-10-28 11:58:20 -07004082
4083 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
4084 wpa_printf(MSG_DEBUG,
4085 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
4086 /* wpas_dpp_auth_success() would normally have been called from
4087 * TX status handler, but since there was no such handler call
4088 * yet, simply send out the event message and proceed with
4089 * exchange. */
4090 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
4091 wpa_s->dpp_auth_ok_on_ack = 0;
4092 }
4093
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004094 wpa_hexdump(MSG_DEBUG,
4095 "DPP: Received Configuration Request (GAS Query Request)",
4096 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004097 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
4098 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004099 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004100
Hai Shaloma20dcd72022-02-04 13:43:00 -08004101 auth->gas_server_ctx = resp_ctx;
4102
Hai Shalom899fcc72020-10-19 14:38:18 -07004103#ifdef CONFIG_DPP2
4104 if (!resp && auth->waiting_cert) {
4105 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08004106 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07004107 *comeback_delay = 500;
4108 return NULL;
4109 }
4110#endif /* CONFIG_DPP2 */
4111
Hai Shaloma20dcd72022-02-04 13:43:00 -08004112 if (!resp && auth->waiting_config &&
4113 (auth->peer_bi || auth->tmp_peer_bi)) {
4114 char *buf = NULL, *name = "";
4115 char band[200], *pos, *end;
4116 int i, res, *opclass = auth->e_band_support;
4117 char *mud_url = "N/A";
4118
4119 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
4120 auth->config_resp_ctx = resp_ctx;
4121 *comeback_delay = -1;
4122 if (auth->e_name) {
4123 size_t len = os_strlen(auth->e_name);
4124
4125 buf = os_malloc(len * 4 + 1);
4126 if (buf) {
4127 printf_encode(buf, len * 4 + 1,
4128 (const u8 *) auth->e_name, len);
4129 name = buf;
4130 }
4131 }
4132 band[0] = '\0';
4133 pos = band;
4134 end = band + sizeof(band);
4135 for (i = 0; opclass && opclass[i]; i++) {
4136 res = os_snprintf(pos, end - pos, "%s%d",
4137 pos == band ? "" : ",", opclass[i]);
4138 if (os_snprintf_error(end - pos, res)) {
4139 *pos = '\0';
4140 break;
4141 }
4142 pos += res;
4143 }
4144 if (auth->e_mud_url) {
4145 size_t len = os_strlen(auth->e_mud_url);
4146
4147 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
4148 mud_url = auth->e_mud_url;
4149 }
4150 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
4151 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
4152 auth->peer_bi ? auth->peer_bi->id :
4153 auth->tmp_peer_bi->id, MAC2STR(sa),
4154 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
4155 os_free(buf);
4156
4157 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4158 NULL);
4159 eloop_register_timeout(0, 50000,
4160 wpas_dpp_gas_initial_resp_timeout, wpa_s,
4161 NULL);
4162 return NULL;
4163 }
4164
Sunil Ravia04bd252022-05-02 22:54:18 -07004165 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08004166 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004167 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004168 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07004169 dpp_auth_deinit(wpa_s->dpp_auth);
4170 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08004171 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004172 return resp;
4173}
4174
4175
4176static void
4177wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
4178{
4179 struct wpa_supplicant *wpa_s = ctx;
4180 struct dpp_authentication *auth = wpa_s->dpp_auth;
4181
4182 if (!auth) {
4183 wpabuf_free(resp);
4184 return;
4185 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004186 if (auth->conf_resp != resp) {
4187 wpa_printf(MSG_DEBUG,
4188 "DPP: Ignore GAS status report (ok=%d) for unknown response",
4189 ok);
4190 wpabuf_free(resp);
4191 return;
4192 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004193
Hai Shalom899fcc72020-10-19 14:38:18 -07004194#ifdef CONFIG_DPP2
4195 if (auth->waiting_csr && ok) {
4196 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
4197 wpabuf_free(resp);
4198 return;
4199 }
4200#endif /* CONFIG_DPP2 */
4201
Sunil Ravia04bd252022-05-02 22:54:18 -07004202#ifdef CONFIG_DPP3
4203 if (auth->waiting_new_key && ok) {
4204 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
4205 wpabuf_free(resp);
4206 return;
4207 }
4208#endif /* CONFIG_DPP3 */
4209
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004210 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
4211 ok);
4212 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004213 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004214 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004215#ifdef CONFIG_DPP2
4216 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08004217 auth->conf_resp_status == DPP_STATUS_OK &&
4218 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07004219 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08004220 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07004221 auth->waiting_conf_result = 1;
4222 auth->conf_resp = NULL;
4223 wpabuf_free(resp);
4224 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
4225 wpa_s, NULL);
4226 eloop_register_timeout(2, 0,
4227 wpas_dpp_config_result_wait_timeout,
4228 wpa_s, NULL);
4229 return;
4230 }
4231#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004232 offchannel_send_action_done(wpa_s);
4233 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004234 if (ok) {
Sunil Ravi89eba102022-09-13 21:04:37 -07004235 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
4236 auth->conf_resp_status);
Hai Shalom706f99b2019-01-08 16:23:37 -08004237 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004238 }
4239 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004240 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004241 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004242 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004243 dpp_auth_deinit(wpa_s->dpp_auth);
4244 wpa_s->dpp_auth = NULL;
4245 wpabuf_free(resp);
Sunil Ravi89eba102022-09-13 21:04:37 -07004246#ifdef CONFIG_DPP3
4247 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
4248 if (ok)
4249 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4250 "success");
4251 else
4252 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4253 "could-not-connect");
4254 wpa_s->dpp_pb_result_indicated = true;
4255 if (ok)
4256 wpas_dpp_remove_pb_hash(wpa_s);
4257 wpas_dpp_push_button_stop(wpa_s);
4258 }
4259#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004260}
4261
4262
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004263int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
4264{
4265 struct dpp_authentication *auth;
4266 int ret = -1;
4267 char *curve = NULL;
4268
Hai Shalomfdcde762020-04-02 11:19:20 -07004269 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004270 if (!auth)
4271 return -1;
4272
4273 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08004274 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07004275 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004276 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07004277 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
4278 &auth->conf_obj[0]);
4279 if (!ret)
4280 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004281
4282 dpp_auth_deinit(auth);
4283 os_free(curve);
4284
4285 return ret;
4286}
4287
4288
4289static void
4290wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
4291 unsigned int freq, const u8 *dst,
4292 const u8 *src, const u8 *bssid,
4293 const u8 *data, size_t data_len,
4294 enum offchannel_send_action_result result)
4295{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004296 const char *res_txt;
4297
4298 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
4299 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
4300 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004301 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
4302 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07004303 freq, MAC2STR(dst), res_txt);
4304 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
4305 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004306 /* TODO: Time out wait for response more quickly in error cases? */
4307}
4308
4309
Sunil Ravi89eba102022-09-13 21:04:37 -07004310#ifdef CONFIG_DPP3
4311static int wpas_dpp_start_private_peer_intro(struct wpa_supplicant *wpa_s,
4312 struct wpa_ssid *ssid,
4313 struct wpa_bss *bss)
4314{
4315 struct wpabuf *msg;
4316 unsigned int wait_time;
4317 size_t len;
4318 u8 ver = DPP_VERSION;
4319 int conn_ver;
4320
4321 len = 5 + 5;
4322 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_QUERY, len);
4323 if (!msg)
4324 return -1;
4325
4326 /* Transaction ID */
4327 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4328 wpabuf_put_le16(msg, 1);
4329 wpabuf_put_u8(msg, TRANSACTION_ID);
4330
4331 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4332 if (conn_ver > 0 && ver != conn_ver) {
4333 wpa_printf(MSG_DEBUG,
4334 "DPP: Use Connector version %d instead of current protocol version %d",
4335 conn_ver, ver);
4336 ver = conn_ver;
4337 }
4338
4339 /* Protocol Version */
4340 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4341 wpabuf_put_le16(msg, 1);
4342 wpabuf_put_u8(msg, ver);
4343
4344 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Query", msg);
4345
4346 /* TODO: Timeout on AP response */
4347 wait_time = wpa_s->max_remain_on_chan;
4348 if (wait_time > 2000)
4349 wait_time = 2000;
4350 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4351 MAC2STR(bss->bssid), bss->freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
4352 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4353 broadcast,
4354 wpabuf_head(msg), wpabuf_len(msg),
4355 wait_time, wpas_dpp_tx_introduction_status, 0);
4356 wpabuf_free(msg);
4357
4358 /* Request this connection attempt to terminate - new one will be
4359 * started when network introduction protocol completes */
4360 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4361 wpa_s->dpp_intro_network = ssid;
4362 return 1;
4363}
4364#endif /* CONFIG_DPP3 */
4365
4366
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004367int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4368 struct wpa_bss *bss)
4369{
4370 struct os_time now;
4371 struct wpabuf *msg;
4372 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07004373 const u8 *rsn;
4374 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004375 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004376
4377 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
4378 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07004379 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4380 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
4381 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
4382 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004383 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
4384 return 0; /* PMKSA exists for DPP AKM - continue */
4385
4386 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4387 !ssid->dpp_csign) {
4388 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4389 "missing %s",
4390 !ssid->dpp_connector ? "Connector" :
4391 (!ssid->dpp_netaccesskey ? "netAccessKey" :
4392 "C-sign-key"));
4393 return -1;
4394 }
4395
4396 os_get_time(&now);
4397
4398 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07004399 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004400 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4401 "netAccessKey expired");
4402 return -1;
4403 }
4404
4405 wpa_printf(MSG_DEBUG,
Sunil Ravi89eba102022-09-13 21:04:37 -07004406 "DPP: Starting %snetwork introduction protocol to derive PMKSA for "
4407 MACSTR,
4408 ssid->dpp_connector_privacy ? "private " : "",
4409 MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07004410 if (wpa_s->wpa_state == WPA_SCANNING)
4411 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004412
Sunil Ravi89eba102022-09-13 21:04:37 -07004413#ifdef CONFIG_DPP3
4414 if (ssid->dpp_connector_privacy)
4415 return wpas_dpp_start_private_peer_intro(wpa_s, ssid, bss);
4416#endif /* CONFIG_DPP3 */
4417
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004418 len = 5 + 4 + os_strlen(ssid->dpp_connector);
4419#ifdef CONFIG_DPP2
4420 len += 5;
4421#endif /* CONFIG_DPP2 */
4422 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004423 if (!msg)
4424 return -1;
4425
Roshan Pius3a1667e2018-07-03 15:17:14 -07004426#ifdef CONFIG_TESTING_OPTIONS
4427 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
4428 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
4429 goto skip_trans_id;
4430 }
4431 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
4432 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
4433 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4434 wpabuf_put_le16(msg, 0);
4435 goto skip_trans_id;
4436 }
4437#endif /* CONFIG_TESTING_OPTIONS */
4438
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004439 /* Transaction ID */
4440 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4441 wpabuf_put_le16(msg, 1);
4442 wpabuf_put_u8(msg, TRANSACTION_ID);
4443
Roshan Pius3a1667e2018-07-03 15:17:14 -07004444#ifdef CONFIG_TESTING_OPTIONS
4445skip_trans_id:
4446 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
4447 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
4448 goto skip_connector;
4449 }
4450 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
4451 char *connector;
4452
4453 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
4454 connector = dpp_corrupt_connector_signature(
4455 ssid->dpp_connector);
4456 if (!connector) {
4457 wpabuf_free(msg);
4458 return -1;
4459 }
4460 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4461 wpabuf_put_le16(msg, os_strlen(connector));
4462 wpabuf_put_str(msg, connector);
4463 os_free(connector);
4464 goto skip_connector;
4465 }
4466#endif /* CONFIG_TESTING_OPTIONS */
4467
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004468 /* DPP Connector */
4469 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4470 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
4471 wpabuf_put_str(msg, ssid->dpp_connector);
4472
Roshan Pius3a1667e2018-07-03 15:17:14 -07004473#ifdef CONFIG_TESTING_OPTIONS
4474skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004475 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
4476 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
4477 goto skip_proto_ver;
4478 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004479#endif /* CONFIG_TESTING_OPTIONS */
4480
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004481#ifdef CONFIG_DPP2
4482 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004483 u8 ver = DPP_VERSION;
4484#ifdef CONFIG_DPP3
4485 int conn_ver;
4486
4487 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4488 if (conn_ver > 0 && ver != conn_ver) {
4489 wpa_printf(MSG_DEBUG,
4490 "DPP: Use Connector version %d instead of current protocol version %d",
4491 conn_ver, ver);
4492 ver = conn_ver;
4493 }
4494#endif /* CONFIG_DPP3 */
4495
4496#ifdef CONFIG_TESTING_OPTIONS
4497 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
4498 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
4499 ver = 1;
4500 }
4501#endif /* CONFIG_TESTING_OPTIONS */
4502
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004503 /* Protocol Version */
4504 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4505 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004506 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004507 }
4508#endif /* CONFIG_DPP2 */
4509
Hai Shaloma20dcd72022-02-04 13:43:00 -08004510#ifdef CONFIG_TESTING_OPTIONS
4511skip_proto_ver:
4512#endif /* CONFIG_TESTING_OPTIONS */
4513
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004514 /* TODO: Timeout on AP response */
4515 wait_time = wpa_s->max_remain_on_chan;
4516 if (wait_time > 2000)
4517 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004518 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4519 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004520 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4521 broadcast,
4522 wpabuf_head(msg), wpabuf_len(msg),
4523 wait_time, wpas_dpp_tx_introduction_status, 0);
4524 wpabuf_free(msg);
4525
4526 /* Request this connection attempt to terminate - new one will be
4527 * started when network introduction protocol completes */
4528 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4529 wpa_s->dpp_intro_network = ssid;
4530 return 1;
4531}
4532
4533
4534int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
4535{
4536 struct dpp_bootstrap_info *own_bi;
4537 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07004538#ifdef CONFIG_DPP3
4539 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
4540#else /* CONFIG_DPP3 */
4541 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
4542#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004543 int tcp_port = DPP_TCP_PORT;
4544 struct hostapd_ip_addr *ipaddr = NULL;
4545#ifdef CONFIG_DPP2
4546 struct hostapd_ip_addr ipaddr_buf;
4547 char *addr;
4548
4549 pos = os_strstr(cmd, " tcp_port=");
4550 if (pos) {
4551 pos += 10;
4552 tcp_port = atoi(pos);
4553 }
4554
4555 addr = get_param(cmd, " tcp_addr=");
4556 if (addr) {
4557 int res;
4558
4559 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
4560 os_free(addr);
4561 if (res)
4562 return -1;
4563 ipaddr = &ipaddr_buf;
4564 }
4565#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004566
4567 pos = os_strstr(cmd, " own=");
4568 if (!pos)
4569 return -1;
4570 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07004571 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004572 if (!own_bi) {
4573 wpa_printf(MSG_DEBUG,
4574 "DPP: Identified bootstrap info not found");
4575 return -1;
4576 }
4577 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
4578 wpa_printf(MSG_DEBUG,
4579 "DPP: Identified bootstrap info not for PKEX");
4580 return -1;
4581 }
4582 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004583 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004584
4585 os_free(wpa_s->dpp_pkex_identifier);
4586 wpa_s->dpp_pkex_identifier = NULL;
4587 pos = os_strstr(cmd, " identifier=");
4588 if (pos) {
4589 pos += 12;
4590 end = os_strchr(pos, ' ');
4591 if (!end)
4592 return -1;
4593 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
4594 if (!wpa_s->dpp_pkex_identifier)
4595 return -1;
4596 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
4597 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
4598 }
4599
4600 pos = os_strstr(cmd, " code=");
4601 if (!pos)
4602 return -1;
4603 os_free(wpa_s->dpp_pkex_code);
4604 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
4605 if (!wpa_s->dpp_pkex_code)
4606 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004607 wpa_s->dpp_pkex_code_len = os_strlen(wpa_s->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004608
Sunil Ravia04bd252022-05-02 22:54:18 -07004609 pos = os_strstr(cmd, " ver=");
4610 if (pos) {
4611 int v;
4612
4613 pos += 5;
4614 v = atoi(pos);
4615 if (v == 1)
4616 ver = PKEX_VER_ONLY_1;
4617 else if (v == 2)
4618 ver = PKEX_VER_ONLY_2;
4619 else
4620 return -1;
4621 }
4622 wpa_s->dpp_pkex_ver = ver;
4623
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004624 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004625 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004626 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004627 } else {
4628#ifdef CONFIG_DPP2
4629 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
4630 wpa_s->dpp_pkex_code,
4631 wpa_s->dpp_pkex_identifier);
4632#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004633 }
4634
4635 /* TODO: Support multiple PKEX info entries */
4636
4637 os_free(wpa_s->dpp_pkex_auth_cmd);
4638 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
4639
4640 return 1;
4641}
4642
4643
4644int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
4645{
4646 unsigned int id_val;
4647
4648 if (os_strcmp(id, "*") == 0) {
4649 id_val = 0;
4650 } else {
4651 id_val = atoi(id);
4652 if (id_val == 0)
4653 return -1;
4654 }
4655
Sunil Ravi89eba102022-09-13 21:04:37 -07004656 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004657 return -1;
4658
4659 /* TODO: Support multiple PKEX entries */
4660 os_free(wpa_s->dpp_pkex_code);
4661 wpa_s->dpp_pkex_code = NULL;
4662 os_free(wpa_s->dpp_pkex_identifier);
4663 wpa_s->dpp_pkex_identifier = NULL;
4664 os_free(wpa_s->dpp_pkex_auth_cmd);
4665 wpa_s->dpp_pkex_auth_cmd = NULL;
4666 wpa_s->dpp_pkex_bi = NULL;
4667 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
4668 dpp_pkex_free(wpa_s->dpp_pkex);
4669 wpa_s->dpp_pkex = NULL;
4670 return 0;
4671}
4672
4673
Roshan Pius3a1667e2018-07-03 15:17:14 -07004674void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
4675{
Sunil Ravia04bd252022-05-02 22:54:18 -07004676 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07004677 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004678 dpp_auth_deinit(wpa_s->dpp_auth);
4679 wpa_s->dpp_auth = NULL;
4680 dpp_pkex_free(wpa_s->dpp_pkex);
4681 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004682 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004683 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
4684 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
Sunil Ravi89eba102022-09-13 21:04:37 -07004685#ifdef CONFIG_DPP3
4686 wpas_dpp_push_button_stop(wpa_s);
4687#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004688}
4689
4690
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004691int wpas_dpp_init(struct wpa_supplicant *wpa_s)
4692{
Hai Shalom81f62d82019-07-22 12:10:00 -07004693 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004694 u8 adv_proto_id[7];
4695
4696 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
4697 adv_proto_id[1] = 5;
4698 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
4699 adv_proto_id[5] = DPP_OUI_TYPE;
4700 adv_proto_id[6] = 0x01;
4701
4702 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
4703 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
4704 wpas_dpp_gas_status_handler, wpa_s) < 0)
4705 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004706
4707 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07004708 config.cb_ctx = wpa_s;
4709#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004710 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07004711#endif /* CONFIG_DPP2 */
4712 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07004713 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004714}
4715
4716
4717void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
4718{
4719#ifdef CONFIG_TESTING_OPTIONS
4720 os_free(wpa_s->dpp_config_obj_override);
4721 wpa_s->dpp_config_obj_override = NULL;
4722 os_free(wpa_s->dpp_discovery_override);
4723 wpa_s->dpp_discovery_override = NULL;
4724 os_free(wpa_s->dpp_groups_override);
4725 wpa_s->dpp_groups_override = NULL;
4726 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
4727#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07004728 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004729 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004730 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004731 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004732 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004733 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
4734 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004735 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4736 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004737#ifdef CONFIG_DPP2
4738 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07004739 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
4740 wpa_s, NULL);
4741 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004742 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
4743 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004744 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004745 dpp_pfs_free(wpa_s->dpp_pfs);
4746 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004747 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004748 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4749 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07004750#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07004751#ifdef CONFIG_DPP3
4752 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
4753#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004754 offchannel_send_action_done(wpa_s);
4755 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004756 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004757 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004758 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
4759 os_free(wpa_s->dpp_configurator_params);
4760 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07004761 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004762}
Hai Shalom81f62d82019-07-22 12:10:00 -07004763
4764
Hai Shaloma20dcd72022-02-04 13:43:00 -08004765static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
4766 struct dpp_authentication *auth, bool tcp)
4767{
4768 struct wpabuf *resp;
4769
4770 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
4771 auth->e_netrole, true);
4772 if (!resp)
4773 return -1;
4774
4775 if (tcp) {
4776 auth->conf_resp_tcp = resp;
4777 return 0;
4778 }
4779
4780 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4781 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
4782 resp) < 0) {
4783 wpa_printf(MSG_DEBUG,
4784 "DPP: Could not find pending GAS response");
4785 wpabuf_free(resp);
4786 return -1;
4787 }
4788 auth->conf_resp = resp;
4789 return 0;
4790}
4791
4792
4793int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
4794{
4795 int peer;
4796 const char *pos;
4797 struct dpp_authentication *auth = wpa_s->dpp_auth;
4798 bool tcp = false;
4799
4800 pos = os_strstr(cmd, " peer=");
4801 if (!pos)
4802 return -1;
4803 peer = atoi(pos + 6);
4804#ifdef CONFIG_DPP2
4805 if (!auth || !auth->waiting_config ||
4806 (auth->peer_bi &&
4807 (unsigned int) peer != auth->peer_bi->id)) {
4808 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4809 tcp = true;
4810 }
4811#endif /* CONFIG_DPP2 */
4812
4813 if (!auth || !auth->waiting_config) {
4814 wpa_printf(MSG_DEBUG,
4815 "DPP: No authentication exchange waiting for configuration information");
4816 return -1;
4817 }
4818
4819 if ((!auth->peer_bi ||
4820 (unsigned int) peer != auth->peer_bi->id) &&
4821 (!auth->tmp_peer_bi ||
4822 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4823 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4824 return -1;
4825 }
4826
4827 pos = os_strstr(cmd, " comeback=");
4828 if (pos) {
4829 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4830 NULL);
4831 gas_server_set_comeback_delay(wpa_s->gas_server,
4832 auth->config_resp_ctx,
4833 atoi(pos + 10));
4834 return 0;
4835 }
4836
4837 if (dpp_set_configurator(auth, cmd) < 0)
4838 return -1;
4839
4840 auth->use_config_query = false;
4841 auth->waiting_config = false;
4842 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4843}
4844
4845
Hai Shalom81f62d82019-07-22 12:10:00 -07004846#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004847
Hai Shalom81f62d82019-07-22 12:10:00 -07004848int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
4849{
4850 struct dpp_controller_config config;
4851 const char *pos;
4852
4853 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004854 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07004855 config.netrole = DPP_NETROLE_STA;
4856 config.msg_ctx = wpa_s;
4857 config.cb_ctx = wpa_s;
4858 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004859 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07004860 if (cmd) {
4861 pos = os_strstr(cmd, " tcp_port=");
4862 if (pos) {
4863 pos += 10;
4864 config.tcp_port = atoi(pos);
4865 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004866
4867 pos = os_strstr(cmd, " role=");
4868 if (pos) {
4869 pos += 6;
4870 if (os_strncmp(pos, "configurator", 12) == 0)
4871 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
4872 else if (os_strncmp(pos, "enrollee", 8) == 0)
4873 config.allowed_roles = DPP_CAPAB_ENROLLEE;
4874 else if (os_strncmp(pos, "either", 6) == 0)
4875 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
4876 DPP_CAPAB_ENROLLEE;
4877 else
4878 return -1;
4879 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004880
4881 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07004882 }
4883 config.configurator_params = wpa_s->dpp_configurator_params;
4884 return dpp_controller_start(wpa_s->dpp, &config);
4885}
Hai Shalomfdcde762020-04-02 11:19:20 -07004886
4887
4888static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
4889
4890static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
4891{
4892 struct wpa_supplicant *wpa_s = eloop_ctx;
4893
4894 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
4895 offchannel_send_action_done(wpa_s);
4896 wpas_dpp_chirp_next(wpa_s, NULL);
4897}
4898
4899
4900static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
4901 unsigned int freq, const u8 *dst,
4902 const u8 *src, const u8 *bssid,
4903 const u8 *data, size_t data_len,
4904 enum offchannel_send_action_result result)
4905{
4906 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
4907 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
4908 wpa_s->dpp_chirp_freq);
4909 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
4910 wpa_s, NULL) < 0)
4911 wpas_dpp_chirp_stop(wpa_s);
4912 return;
4913 }
4914
4915 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
4916 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
4917 wpa_s, NULL) < 0)
4918 wpas_dpp_chirp_stop(wpa_s);
4919}
4920
4921
4922static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
4923{
Hai Shalom899fcc72020-10-19 14:38:18 -07004924 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004925 int type;
4926
4927 msg = wpa_s->dpp_presence_announcement;
4928 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
4929 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07004930 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
4931
4932 if (ssid && wpa_s->dpp_reconfig_id &&
4933 wpa_config_get_network(wpa_s->conf,
4934 wpa_s->dpp_reconfig_ssid_id) ==
4935 ssid) {
4936 announce = dpp_build_reconfig_announcement(
4937 ssid->dpp_csign,
4938 ssid->dpp_csign_len,
4939 ssid->dpp_netaccesskey,
4940 ssid->dpp_netaccesskey_len,
4941 wpa_s->dpp_reconfig_id);
4942 msg = announce;
4943 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004944 if (!msg)
4945 return;
4946 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
4947 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004948 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
4949 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004950 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07004951 if (offchannel_send_action(
4952 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
4953 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004954 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07004955 2000, wpas_dpp_chirp_tx_status, 0) < 0)
4956 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004957
4958 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07004959}
4960
4961
Sunil Ravi89eba102022-09-13 21:04:37 -07004962static int * wpas_dpp_presence_ann_channels(struct wpa_supplicant *wpa_s,
4963 struct dpp_bootstrap_info *bi)
Hai Shalomfdcde762020-04-02 11:19:20 -07004964{
Hai Shalomfdcde762020-04-02 11:19:20 -07004965 unsigned int i;
4966 struct hostapd_hw_modes *mode;
4967 int c;
4968 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004969 bool chan6 = wpa_s->hw.modes == NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07004970 int *freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004971
4972 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004973 if (bi) {
4974 for (i = 0; i < bi->num_freq; i++)
Sunil Ravi89eba102022-09-13 21:04:37 -07004975 int_array_add_unique(&freqs, bi->freq[i]);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004976 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004977
4978 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07004979 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004980 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07004981 if (mode) {
4982 for (c = 0; c < mode->num_channels; c++) {
4983 struct hostapd_channel_data *chan = &mode->channels[c];
4984
4985 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
4986 chan->freq != 2437)
4987 continue;
4988 chan6 = true;
4989 break;
4990 }
4991 }
4992 if (chan6)
Sunil Ravi89eba102022-09-13 21:04:37 -07004993 int_array_add_unique(&freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07004994
4995 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004996 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07004997 if (mode) {
4998 int chan44 = 0, chan149 = 0;
4999
5000 for (c = 0; c < mode->num_channels; c++) {
5001 struct hostapd_channel_data *chan = &mode->channels[c];
5002
5003 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
5004 HOSTAPD_CHAN_RADAR))
5005 continue;
5006 if (chan->freq == 5220)
5007 chan44 = 1;
5008 if (chan->freq == 5745)
5009 chan149 = 1;
5010 }
5011 if (chan149)
Sunil Ravi89eba102022-09-13 21:04:37 -07005012 int_array_add_unique(&freqs, 5745);
Hai Shalomfdcde762020-04-02 11:19:20 -07005013 else if (chan44)
Sunil Ravi89eba102022-09-13 21:04:37 -07005014 int_array_add_unique(&freqs, 5220);
Hai Shalomfdcde762020-04-02 11:19:20 -07005015 }
5016
5017 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005018 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005019 if (mode) {
5020 for (c = 0; c < mode->num_channels; c++) {
5021 struct hostapd_channel_data *chan = &mode->channels[c];
5022
5023 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
5024 HOSTAPD_CHAN_RADAR)) ||
5025 chan->freq != 60480)
5026 continue;
Sunil Ravi89eba102022-09-13 21:04:37 -07005027 int_array_add_unique(&freqs, 60480);
Hai Shalomfdcde762020-04-02 11:19:20 -07005028 break;
5029 }
5030 }
5031
5032 /* Add channels from scan results for APs that advertise Configurator
5033 * Connectivity element */
5034 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5035 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
Sunil Ravi89eba102022-09-13 21:04:37 -07005036 int_array_add_unique(&freqs, bss->freq);
Hai Shalomfdcde762020-04-02 11:19:20 -07005037 }
5038
Sunil Ravi89eba102022-09-13 21:04:37 -07005039 return freqs;
5040}
5041
5042
5043static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
5044 struct wpa_scan_results *scan_res)
5045{
5046 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
5047
5048 if (!bi && !wpa_s->dpp_reconfig_ssid)
5049 return;
5050
5051 wpa_s->dpp_chirp_scan_done = 1;
5052
5053 os_free(wpa_s->dpp_chirp_freqs);
5054 wpa_s->dpp_chirp_freqs = wpas_dpp_presence_ann_channels(wpa_s, bi);
5055
Hai Shalomfdcde762020-04-02 11:19:20 -07005056 if (!wpa_s->dpp_chirp_freqs ||
5057 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
5058 wpas_dpp_chirp_stop(wpa_s);
5059}
5060
5061
5062static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
5063{
5064 struct wpa_supplicant *wpa_s = eloop_ctx;
5065 int i;
5066
5067 if (wpa_s->dpp_chirp_listen)
5068 wpas_dpp_listen_stop(wpa_s);
5069
5070 if (wpa_s->dpp_chirp_freq == 0) {
5071 if (wpa_s->dpp_chirp_round % 4 == 0 &&
5072 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08005073 if (wpas_scan_scheduled(wpa_s)) {
5074 wpa_printf(MSG_DEBUG,
5075 "DPP: Deferring chirp scan because another scan is planned already");
5076 if (eloop_register_timeout(1, 0,
5077 wpas_dpp_chirp_next,
5078 wpa_s, NULL) < 0) {
5079 wpas_dpp_chirp_stop(wpa_s);
5080 return;
5081 }
5082 return;
5083 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005084 wpa_printf(MSG_DEBUG,
5085 "DPP: Update channel list for chirping");
5086 wpa_s->scan_req = MANUAL_SCAN_REQ;
5087 wpa_s->scan_res_handler =
5088 wpas_dpp_chirp_scan_res_handler;
5089 wpa_supplicant_req_scan(wpa_s, 0, 0);
5090 return;
5091 }
5092 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
5093 wpa_s->dpp_chirp_round++;
5094 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
5095 wpa_s->dpp_chirp_round);
5096 } else {
5097 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
5098 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
5099 break;
5100 if (!wpa_s->dpp_chirp_freqs[i]) {
5101 wpa_printf(MSG_DEBUG,
5102 "DPP: Previous chirp freq %d not found",
5103 wpa_s->dpp_chirp_freq);
5104 return;
5105 }
5106 i++;
5107 if (wpa_s->dpp_chirp_freqs[i]) {
5108 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
5109 } else {
5110 wpa_s->dpp_chirp_iter--;
5111 if (wpa_s->dpp_chirp_iter <= 0) {
5112 wpa_printf(MSG_DEBUG,
5113 "DPP: Chirping iterations completed");
5114 wpas_dpp_chirp_stop(wpa_s);
5115 return;
5116 }
5117 wpa_s->dpp_chirp_freq = 0;
5118 wpa_s->dpp_chirp_scan_done = 0;
5119 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
5120 wpa_s, NULL) < 0) {
5121 wpas_dpp_chirp_stop(wpa_s);
5122 return;
5123 }
5124 if (wpa_s->dpp_chirp_listen) {
5125 wpa_printf(MSG_DEBUG,
5126 "DPP: Listen on %d MHz during chirp 30 second wait",
5127 wpa_s->dpp_chirp_listen);
5128 wpas_dpp_listen_start(wpa_s,
5129 wpa_s->dpp_chirp_listen);
5130 } else {
5131 wpa_printf(MSG_DEBUG,
5132 "DPP: Wait 30 seconds before starting the next chirping round");
5133 }
5134 return;
5135 }
5136 }
5137
5138 wpas_dpp_chirp_start(wpa_s);
5139}
5140
5141
5142int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
5143{
5144 const char *pos;
5145 int iter = 1, listen_freq = 0;
5146 struct dpp_bootstrap_info *bi;
5147
5148 pos = os_strstr(cmd, " own=");
5149 if (!pos)
5150 return -1;
5151 pos += 5;
5152 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
5153 if (!bi) {
5154 wpa_printf(MSG_DEBUG,
5155 "DPP: Identified bootstrap info not found");
5156 return -1;
5157 }
5158
5159 pos = os_strstr(cmd, " iter=");
5160 if (pos) {
5161 iter = atoi(pos + 6);
5162 if (iter <= 0)
5163 return -1;
5164 }
5165
5166 pos = os_strstr(cmd, " listen=");
5167 if (pos) {
5168 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005169 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005170 return -1;
5171 }
5172
5173 wpas_dpp_chirp_stop(wpa_s);
5174 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005175 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07005176 wpa_s->dpp_qr_mutual = 0;
5177 wpa_s->dpp_chirp_bi = bi;
5178 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
5179 if (!wpa_s->dpp_presence_announcement)
5180 return -1;
5181 wpa_s->dpp_chirp_iter = iter;
5182 wpa_s->dpp_chirp_round = 0;
5183 wpa_s->dpp_chirp_scan_done = 0;
5184 wpa_s->dpp_chirp_listen = listen_freq;
5185
5186 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5187}
5188
5189
5190void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
5191{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005192 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07005193 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005194 offchannel_send_action_done(wpa_s);
5195 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
5196 }
5197 wpa_s->dpp_chirp_bi = NULL;
5198 wpabuf_free(wpa_s->dpp_presence_announcement);
5199 wpa_s->dpp_presence_announcement = NULL;
5200 if (wpa_s->dpp_chirp_listen)
5201 wpas_dpp_listen_stop(wpa_s);
5202 wpa_s->dpp_chirp_listen = 0;
5203 wpa_s->dpp_chirp_freq = 0;
5204 os_free(wpa_s->dpp_chirp_freqs);
5205 wpa_s->dpp_chirp_freqs = NULL;
5206 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
5207 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
5208 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
5209 wpas_abort_ongoing_scan(wpa_s);
5210 wpa_s->scan_res_handler = NULL;
5211 }
5212}
5213
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005214
Hai Shalom899fcc72020-10-19 14:38:18 -07005215int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005216{
Hai Shalom899fcc72020-10-19 14:38:18 -07005217 struct wpa_ssid *ssid;
5218 int iter = 1;
5219 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005220
Hai Shalom899fcc72020-10-19 14:38:18 -07005221 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
5222 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
5223 !ssid->dpp_csign) {
5224 wpa_printf(MSG_DEBUG,
5225 "DPP: Not a valid network profile for reconfiguration");
5226 return -1;
5227 }
5228
5229 pos = os_strstr(cmd, " iter=");
5230 if (pos) {
5231 iter = atoi(pos + 6);
5232 if (iter <= 0)
5233 return -1;
5234 }
5235
5236 if (wpa_s->dpp_auth) {
5237 wpa_printf(MSG_DEBUG,
5238 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
5239 return -1;
5240 }
5241
5242 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
5243 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
5244 ssid->dpp_csign_len,
5245 ssid->dpp_pp_key,
5246 ssid->dpp_pp_key_len);
5247 if (!wpa_s->dpp_reconfig_id) {
5248 wpa_printf(MSG_DEBUG,
5249 "DPP: Failed to generate E-id for reconfiguration");
5250 return -1;
5251 }
5252 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
5253 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
5254 wpa_s->own_disconnect_req = 1;
5255 wpa_supplicant_deauthenticate(
5256 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5257 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005258 wpas_dpp_chirp_stop(wpa_s);
5259 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005260 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005261 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005262 wpa_s->dpp_reconfig_ssid = ssid;
5263 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07005264 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005265 wpa_s->dpp_chirp_round = 0;
5266 wpa_s->dpp_chirp_scan_done = 0;
5267 wpa_s->dpp_chirp_listen = 0;
5268
5269 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5270}
5271
Hai Shalom899fcc72020-10-19 14:38:18 -07005272
Hai Shalom899fcc72020-10-19 14:38:18 -07005273int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
5274{
5275 int peer = -1;
5276 const char *pos, *value;
5277 struct dpp_authentication *auth = wpa_s->dpp_auth;
5278 u8 *bin;
5279 size_t bin_len;
5280 struct wpabuf *buf;
5281 bool tcp = false;
5282
5283 pos = os_strstr(cmd, " peer=");
5284 if (pos) {
5285 peer = atoi(pos + 6);
5286 if (!auth || !auth->waiting_cert ||
5287 (auth->peer_bi &&
5288 (unsigned int) peer != auth->peer_bi->id)) {
5289 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5290 tcp = true;
5291 }
5292 }
5293
5294 if (!auth || !auth->waiting_cert) {
5295 wpa_printf(MSG_DEBUG,
5296 "DPP: No authentication exchange waiting for certificate information");
5297 return -1;
5298 }
5299
5300 if (peer >= 0 &&
5301 (!auth->peer_bi ||
5302 (unsigned int) peer != auth->peer_bi->id) &&
5303 (!auth->tmp_peer_bi ||
5304 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5305 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5306 return -1;
5307 }
5308
5309 pos = os_strstr(cmd, " value=");
5310 if (!pos)
5311 return -1;
5312 value = pos + 7;
5313
5314 pos = os_strstr(cmd, " name=");
5315 if (!pos)
5316 return -1;
5317 pos += 6;
5318
5319 if (os_strncmp(pos, "status ", 7) == 0) {
5320 auth->force_conf_resp_status = atoi(value);
5321 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5322 }
5323
5324 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
5325 os_free(auth->trusted_eap_server_name);
5326 auth->trusted_eap_server_name = os_strdup(value);
5327 return auth->trusted_eap_server_name ? 0 : -1;
5328 }
5329
5330 bin = base64_decode(value, os_strlen(value), &bin_len);
5331 if (!bin)
5332 return -1;
5333 buf = wpabuf_alloc_copy(bin, bin_len);
5334 os_free(bin);
5335
5336 if (os_strncmp(pos, "caCert ", 7) == 0) {
5337 wpabuf_free(auth->cacert);
5338 auth->cacert = buf;
5339 return 0;
5340 }
5341
5342 if (os_strncmp(pos, "certBag ", 8) == 0) {
5343 wpabuf_free(auth->certbag);
5344 auth->certbag = buf;
5345 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5346 }
5347
5348 wpabuf_free(buf);
5349 return -1;
5350}
5351
Hai Shalom81f62d82019-07-22 12:10:00 -07005352#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07005353
5354
5355#ifdef CONFIG_DPP3
5356
5357#define DPP_PB_ANNOUNCE_PER_CHAN 3
5358
5359static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
5360static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
5361
5362
5363static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
5364 unsigned int freq, const u8 *dst,
5365 const u8 *src, const u8 *bssid,
5366 const u8 *data, size_t data_len,
5367 enum offchannel_send_action_result result)
5368{
5369 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5370 wpa_printf(MSG_DEBUG,
5371 "DPP: Failed to send push button announcement on %d MHz",
5372 freq);
5373 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
5374 wpa_s, NULL) < 0)
5375 wpas_dpp_push_button_stop(wpa_s);
5376 return;
5377 }
5378
5379 wpa_printf(MSG_DEBUG, "DPP: Push button announcement on %d MHz sent",
5380 freq);
5381 if (wpa_s->dpp_pb_discovery_done) {
5382 wpa_s->dpp_pb_announce_count = 0;
5383 wpa_printf(MSG_DEBUG,
5384 "DPP: Wait for push button announcement response and PKEX on %d MHz",
5385 freq);
5386 if (eloop_register_timeout(0, 500000, wpas_dpp_pb_next,
5387 wpa_s, NULL) < 0)
5388 wpas_dpp_push_button_stop(wpa_s);
5389 return;
5390 } else if (wpa_s->dpp_pb_announce_count >= DPP_PB_ANNOUNCE_PER_CHAN) {
5391 wpa_printf(MSG_DEBUG,
5392 "DPP: Wait for push button announcement response on %d MHz",
5393 freq);
5394 if (eloop_register_timeout(0, 50000, wpas_dpp_pb_next,
5395 wpa_s, NULL) < 0)
5396 wpas_dpp_push_button_stop(wpa_s);
5397 return;
5398 }
5399
5400 if (wpas_dpp_pb_announce(wpa_s, freq) < 0)
5401 wpas_dpp_push_button_stop(wpa_s);
5402}
5403
5404
5405static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq)
5406{
5407 struct wpabuf *msg;
5408 int type;
5409
5410 msg = wpa_s->dpp_pb_announcement;
5411 if (!msg)
5412 return -1;
5413
5414 wpa_s->dpp_pb_announce_count++;
5415 wpa_printf(MSG_DEBUG,
5416 "DPP: Send push button announcement %d/%d (%d MHz)",
5417 wpa_s->dpp_pb_announce_count, DPP_PB_ANNOUNCE_PER_CHAN,
5418 freq);
5419
5420 type = DPP_PA_PB_PRESENCE_ANNOUNCEMENT;
5421 if (wpa_s->dpp_pb_announce_count == 1)
5422 wpa_msg(wpa_s, MSG_INFO,
5423 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
5424 MAC2STR(broadcast), freq, type);
5425 if (offchannel_send_action(
5426 wpa_s, freq, broadcast, wpa_s->own_addr, broadcast,
5427 wpabuf_head(msg), wpabuf_len(msg),
5428 1000, wpas_dpp_pb_tx_status, 0) < 0)
5429 return -1;
5430
5431 return 0;
5432}
5433
5434
5435static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx)
5436{
5437 struct wpa_supplicant *wpa_s = eloop_ctx;
5438 struct os_reltime now;
5439 int freq;
5440
5441 if (!wpa_s->dpp_pb_freqs)
5442 return;
5443
5444 os_get_reltime(&now);
5445 offchannel_send_action_done(wpa_s);
5446
5447 if (os_reltime_expired(&now, &wpa_s->dpp_pb_time, 100)) {
5448 wpa_printf(MSG_DEBUG, "DPP: Push button wait time expired");
5449 wpas_dpp_push_button_stop(wpa_s);
5450 return;
5451 }
5452
5453 if (wpa_s->dpp_pb_freq_idx >= int_array_len(wpa_s->dpp_pb_freqs)) {
5454 wpa_printf(MSG_DEBUG,
5455 "DPP: Completed push button announcement round");
5456 wpa_s->dpp_pb_freq_idx = 0;
5457 if (wpa_s->dpp_pb_stop_iter > 0) {
5458 wpa_s->dpp_pb_stop_iter--;
5459
5460 if (wpa_s->dpp_pb_stop_iter == 1) {
5461 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5462 "wait for AP/Configurator to allow PKEX to be initiated");
5463 if (eloop_register_timeout(10, 0,
5464 wpas_dpp_pb_next,
5465 wpa_s, NULL) < 0) {
5466 wpas_dpp_push_button_stop(wpa_s);
5467 return;
5468 }
5469 return;
5470 }
5471
5472 if (wpa_s->dpp_pb_stop_iter == 0) {
5473 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5474 "start push button PKEX responder on the discovered channel (%d MHz)",
5475 wpa_s->dpp_pb_resp_freq);
5476 wpa_s->dpp_pb_discovery_done = true;
5477
5478 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
5479
5480 os_free(wpa_s->dpp_pkex_code);
5481 wpa_s->dpp_pkex_code = os_memdup(
5482 wpa_s->dpp_pb_c_nonce,
5483 wpa_s->dpp_pb_c_nonce_len);
5484 wpa_s->dpp_pkex_code_len =
5485 wpa_s->dpp_pb_c_nonce_len;
5486
5487 os_free(wpa_s->dpp_pkex_identifier);
5488 wpa_s->dpp_pkex_identifier =
5489 os_strdup("PBPKEX");
5490
5491 if (!wpa_s->dpp_pkex_code ||
5492 !wpa_s->dpp_pkex_identifier) {
5493 wpas_dpp_push_button_stop(wpa_s);
5494 return;
5495 }
5496
5497 wpa_s->dpp_pkex_ver = PKEX_VER_ONLY_2;
5498
5499 os_free(wpa_s->dpp_pkex_auth_cmd);
5500 wpa_s->dpp_pkex_auth_cmd = NULL;
5501 }
5502 }
5503 }
5504
5505 if (wpa_s->dpp_pb_discovery_done)
5506 freq = wpa_s->dpp_pb_resp_freq;
5507 else
5508 freq = wpa_s->dpp_pb_freqs[wpa_s->dpp_pb_freq_idx++];
5509 wpa_s->dpp_pb_announce_count = 0;
5510 if (!wpa_s->dpp_pb_announcement) {
5511 wpa_printf(MSG_DEBUG, "DPP: Push button announcements stopped");
5512 return;
5513 }
5514 if (wpas_dpp_pb_announce(wpa_s, freq) < 0) {
5515 wpas_dpp_push_button_stop(wpa_s);
5516 return;
5517 }
5518}
5519
5520
5521static void wpas_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
5522{
5523 struct wpa_supplicant *wpa_s = eloop_ctx;
5524
5525 wpa_printf(MSG_DEBUG,
5526 "DPP: Active push button Configurator mode expired");
5527 wpas_dpp_push_button_stop(wpa_s);
5528}
5529
5530
5531static int wpas_dpp_push_button_configurator(struct wpa_supplicant *wpa_s,
5532 const char *cmd)
5533{
5534 wpa_s->dpp_pb_configurator = true;
5535 wpa_s->dpp_pb_announce_time.sec = 0;
5536 wpa_s->dpp_pb_announce_time.usec = 0;
5537 str_clear_free(wpa_s->dpp_pb_cmd);
5538 wpa_s->dpp_pb_cmd = NULL;
5539 if (cmd) {
5540 wpa_s->dpp_pb_cmd = os_strdup(cmd);
5541 if (!wpa_s->dpp_pb_cmd)
5542 return -1;
5543 }
5544 eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
5545 wpa_s, NULL);
5546
5547 return 0;
5548}
5549
5550
5551static void wpas_dpp_pb_scan_res_handler(struct wpa_supplicant *wpa_s,
5552 struct wpa_scan_results *scan_res)
5553{
5554 if (!wpa_s->dpp_pb_time.sec && !wpa_s->dpp_pb_time.usec)
5555 return;
5556
5557 os_free(wpa_s->dpp_pb_freqs);
5558 wpa_s->dpp_pb_freqs = wpas_dpp_presence_ann_channels(wpa_s, NULL);
5559
5560 wpa_printf(MSG_DEBUG, "DPP: Scan completed for PB discovery");
5561 if (!wpa_s->dpp_pb_freqs ||
5562 eloop_register_timeout(0, 0, wpas_dpp_pb_next, wpa_s, NULL) < 0)
5563 wpas_dpp_push_button_stop(wpa_s);
5564}
5565
5566
5567int wpas_dpp_push_button(struct wpa_supplicant *wpa_s, const char *cmd)
5568{
5569 int res;
5570
5571 if (!wpa_s->dpp)
5572 return -1;
5573 wpas_dpp_push_button_stop(wpa_s);
5574 wpas_dpp_stop(wpa_s);
5575 wpas_dpp_chirp_stop(wpa_s);
5576
5577 os_get_reltime(&wpa_s->dpp_pb_time);
5578
5579 if (cmd &&
5580 (os_strstr(cmd, " role=configurator") ||
5581 os_strstr(cmd, " conf=")))
5582 return wpas_dpp_push_button_configurator(wpa_s, cmd);
5583
5584 wpa_s->dpp_pb_configurator = false;
5585
5586 wpa_s->dpp_pb_freq_idx = 0;
5587
5588 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
5589 if (res < 0)
5590 return -1;
5591 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
5592 if (!wpa_s->dpp_pb_bi)
5593 return -1;
5594
5595 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
5596 wpa_s->dpp_netrole = DPP_NETROLE_STA;
5597 wpa_s->dpp_qr_mutual = 0;
5598 wpa_s->dpp_pb_announcement =
5599 dpp_build_pb_announcement(wpa_s->dpp_pb_bi);
5600 if (!wpa_s->dpp_pb_announcement)
5601 return -1;
5602
5603 wpa_printf(MSG_DEBUG,
5604 "DPP: Scan to create channel list for PB discovery");
5605 wpa_s->scan_req = MANUAL_SCAN_REQ;
5606 wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
5607 wpa_supplicant_req_scan(wpa_s, 0, 0);
5608 return 0;
5609}
5610
5611
5612void wpas_dpp_push_button_stop(struct wpa_supplicant *wpa_s)
5613{
5614 if (!wpa_s->dpp)
5615 return;
5616 os_free(wpa_s->dpp_pb_freqs);
5617 wpa_s->dpp_pb_freqs = NULL;
5618 wpabuf_free(wpa_s->dpp_pb_announcement);
5619 wpa_s->dpp_pb_announcement = NULL;
5620 if (wpa_s->dpp_pb_bi) {
5621 char id[20];
5622
5623 os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
5624 dpp_bootstrap_remove(wpa_s->dpp, id);
5625 wpa_s->dpp_pb_bi = NULL;
5626 if (!wpa_s->dpp_pb_result_indicated) {
5627 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5628 wpa_s->dpp_pb_result_indicated = true;
5629 }
5630 }
5631
5632 wpa_s->dpp_pb_resp_freq = 0;
5633 wpa_s->dpp_pb_stop_iter = 0;
5634 wpa_s->dpp_pb_discovery_done = false;
5635 os_free(wpa_s->dpp_pb_cmd);
5636 wpa_s->dpp_pb_cmd = NULL;
5637
5638 eloop_cancel_timeout(wpas_dpp_pb_next, wpa_s, NULL);
5639 eloop_cancel_timeout(wpas_dpp_push_button_expire, wpa_s, NULL);
5640 if (wpas_dpp_pb_active(wpa_s)) {
5641 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
5642 if (!wpa_s->dpp_pb_result_indicated)
5643 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5644 }
5645 wpa_s->dpp_pb_time.sec = 0;
5646 wpa_s->dpp_pb_time.usec = 0;
5647 dpp_pkex_free(wpa_s->dpp_pkex);
5648 wpa_s->dpp_pkex = NULL;
5649 os_free(wpa_s->dpp_pkex_auth_cmd);
5650 wpa_s->dpp_pkex_auth_cmd = NULL;
5651
5652 wpa_s->dpp_pb_result_indicated = false;
5653
5654 str_clear_free(wpa_s->dpp_pb_cmd);
5655 wpa_s->dpp_pb_cmd = NULL;
5656
5657 if (wpa_s->scan_res_handler == wpas_dpp_pb_scan_res_handler) {
5658 wpas_abort_ongoing_scan(wpa_s);
5659 wpa_s->scan_res_handler = NULL;
5660 }
5661}
5662
5663#endif /* CONFIG_DPP3 */