blob: 895d5fa66c267e9c0f8c14f18b9c5491462f032b [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;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001356 if (dpp_akm_psk(conf->akm))
1357 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1358 else
1359 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalomc3565922019-10-28 11:58:20 -07001360 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001361 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001362 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001363 goto fail;
1364 wpa_config_update_psk(ssid);
1365 ssid->export_keys = 1;
1366 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001367 ssid->psk_set = conf->psk_set;
1368 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001369 }
1370 }
1371
Hai Shalom899fcc72020-10-19 14:38:18 -07001372#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1373 if (conf->akm == DPP_AKM_DOT1X) {
1374 int i;
1375 char name[100], blobname[128];
1376 struct wpa_config_blob *blob;
1377
1378 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1379 WPA_KEY_MGMT_IEEE8021X_SHA256 |
1380 WPA_KEY_MGMT_IEEE8021X_SHA256;
1381 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1382
1383 if (conf->cacert) {
1384 /* caCert is DER-encoded X.509v3 certificate for the
1385 * server certificate if that is different from the
1386 * trust root included in certBag. */
1387 /* TODO: ssid->eap.cert.ca_cert */
1388 }
1389
1390 if (conf->certs) {
1391 for (i = 0; ; i++) {
1392 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1393 i);
1394 if (!wpa_config_get_blob(wpa_s->conf, name))
1395 break;
1396 }
1397
1398 blob = os_zalloc(sizeof(*blob));
1399 if (!blob)
1400 goto fail;
1401 blob->len = wpabuf_len(conf->certs);
1402 blob->name = os_strdup(name);
1403 blob->data = os_malloc(blob->len);
1404 if (!blob->name || !blob->data) {
1405 wpa_config_free_blob(blob);
1406 goto fail;
1407 }
1408 os_memcpy(blob->data, wpabuf_head(conf->certs),
1409 blob->len);
1410 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1411 name);
1412 wpa_config_set_blob(wpa_s->conf, blob);
1413 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1414 name);
1415 ssid->eap.cert.client_cert = os_strdup(blobname);
1416 if (!ssid->eap.cert.client_cert)
1417 goto fail;
1418
1419 /* TODO: ssid->eap.identity from own certificate */
1420 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1421 0) < 0)
1422 goto fail;
1423 }
1424
1425 if (auth->priv_key) {
1426 for (i = 0; ; i++) {
1427 os_snprintf(name, sizeof(name), "dpp-key-%d",
1428 i);
1429 if (!wpa_config_get_blob(wpa_s->conf, name))
1430 break;
1431 }
1432
1433 blob = os_zalloc(sizeof(*blob));
1434 if (!blob)
1435 goto fail;
1436 blob->len = wpabuf_len(auth->priv_key);
1437 blob->name = os_strdup(name);
1438 blob->data = os_malloc(blob->len);
1439 if (!blob->name || !blob->data) {
1440 wpa_config_free_blob(blob);
1441 goto fail;
1442 }
1443 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1444 blob->len);
1445 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1446 name);
1447 wpa_config_set_blob(wpa_s->conf, blob);
1448 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1449 name);
1450 ssid->eap.cert.private_key = os_strdup(blobname);
1451 if (!ssid->eap.cert.private_key)
1452 goto fail;
1453 }
1454
1455 if (conf->server_name) {
1456 ssid->eap.cert.domain_suffix_match =
1457 os_strdup(conf->server_name);
1458 if (!ssid->eap.cert.domain_suffix_match)
1459 goto fail;
1460 }
1461
1462 /* TODO: Use entCreds::eapMethods */
1463 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1464 goto fail;
1465 }
1466#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1467
Hai Shalomc3565922019-10-28 11:58:20 -07001468 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1469 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1470
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001471 return ssid;
1472fail:
1473 wpas_notify_network_removed(wpa_s, ssid);
1474 wpa_config_remove_network(wpa_s->conf, ssid->id);
1475 return NULL;
1476}
1477
1478
Hai Shalom021b0b52019-04-10 11:17:58 -07001479static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001480 struct dpp_authentication *auth,
1481 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001482{
1483 struct wpa_ssid *ssid;
1484
1485 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001486 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001487
Hai Shalomc3565922019-10-28 11:58:20 -07001488 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001489 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001490 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001491
1492 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001493
Sunil Ravi546a7b52022-08-26 22:06:04 +00001494 wpas_notify_dpp_config_received(wpa_s, ssid, auth->conn_status_requested ? 1 : 0);
Hai Shalom59532852018-12-07 10:32:58 -08001495
Hai Shalom021b0b52019-04-10 11:17:58 -07001496 if (wpa_s->conf->dpp_config_processing == 2)
1497 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001498
Hai Shalom021b0b52019-04-10 11:17:58 -07001499#ifndef CONFIG_NO_CONFIG_WRITE
1500 if (wpa_s->conf->update_config &&
1501 wpa_config_write(wpa_s->confname, wpa_s->conf))
1502 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1503#endif /* CONFIG_NO_CONFIG_WRITE */
1504
Hai Shalomc3565922019-10-28 11:58:20 -07001505 return 0;
1506}
1507
1508
1509static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1510 struct dpp_authentication *auth)
1511{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001512#ifdef CONFIG_DPP2
1513 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1514 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1515 wpa_s->dpp_reconfig_ssid) {
1516 wpa_printf(MSG_DEBUG,
1517 "DPP: Remove reconfigured network profile");
1518 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1519 wpa_config_remove_network(wpa_s->conf,
1520 wpa_s->dpp_reconfig_ssid_id);
1521 wpa_s->dpp_reconfig_ssid = NULL;
1522 wpa_s->dpp_reconfig_ssid_id = -1;
1523 }
1524#endif /* CONFIG_DPP2 */
1525
Hai Shalom021b0b52019-04-10 11:17:58 -07001526 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001527 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001528
1529#ifdef CONFIG_DPP2
1530 if (auth->peer_version >= 2) {
1531 wpa_printf(MSG_DEBUG,
1532 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1533 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001534 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001535 }
1536#endif /* CONFIG_DPP2 */
1537
1538 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001539}
1540
1541
Hai Shalom021b0b52019-04-10 11:17:58 -07001542static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001543 struct dpp_authentication *auth,
1544 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001545{
1546 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001547 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1548 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001549 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001550 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001551 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001552 if (conf->ssid_charset)
1553 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1554 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001555 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001556 /* TODO: Save the Connector and consider using a command
1557 * to fetch the value instead of sending an event with
1558 * it. The Connector could end up being larger than what
1559 * most clients are ready to receive as an event
1560 * message. */
1561 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001562 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001563 }
Hai Shalom60840252021-02-19 19:02:11 -08001564 if (conf->passphrase[0]) {
1565 char hex[64 * 2 + 1];
1566
1567 wpa_snprintf_hex(hex, sizeof(hex),
1568 (const u8 *) conf->passphrase,
1569 os_strlen(conf->passphrase));
1570 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1571 hex);
1572 } else if (conf->psk_set) {
1573 char hex[PMK_LEN * 2 + 1];
1574
1575 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1576 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1577 hex);
1578 }
Hai Shalomc3565922019-10-28 11:58:20 -07001579 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001580 char *hex;
1581 size_t hexlen;
1582
Hai Shalomc3565922019-10-28 11:58:20 -07001583 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001584 hex = os_malloc(hexlen);
1585 if (hex) {
1586 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001587 wpabuf_head(conf->c_sign_key),
1588 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001589 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1590 hex);
1591 os_free(hex);
1592 }
1593 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001594 if (conf->pp_key) {
1595 char *hex;
1596 size_t hexlen;
1597
1598 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1599 hex = os_malloc(hexlen);
1600 if (hex) {
1601 wpa_snprintf_hex(hex, hexlen,
1602 wpabuf_head(conf->pp_key),
1603 wpabuf_len(conf->pp_key));
1604 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1605 os_free(hex);
1606 }
1607 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001608 if (auth->net_access_key) {
1609 char *hex;
1610 size_t hexlen;
1611
1612 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1613 hex = os_malloc(hexlen);
1614 if (hex) {
1615 wpa_snprintf_hex(hex, hexlen,
1616 wpabuf_head(auth->net_access_key),
1617 wpabuf_len(auth->net_access_key));
1618 if (auth->net_access_key_expiry)
1619 wpa_msg(wpa_s, MSG_INFO,
1620 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1621 (long unsigned)
1622 auth->net_access_key_expiry);
1623 else
1624 wpa_msg(wpa_s, MSG_INFO,
1625 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1626 os_free(hex);
1627 }
1628 }
1629
Hai Shalom899fcc72020-10-19 14:38:18 -07001630#ifdef CONFIG_DPP2
1631 if (conf->certbag) {
1632 char *b64;
1633
1634 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1635 wpabuf_len(conf->certbag), NULL);
1636 if (b64)
1637 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1638 os_free(b64);
1639 }
1640
1641 if (conf->cacert) {
1642 char *b64;
1643
1644 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1645 wpabuf_len(conf->cacert), NULL);
1646 if (b64)
1647 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1648 os_free(b64);
1649 }
1650
1651 if (conf->server_name)
1652 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1653 conf->server_name);
1654#endif /* CONFIG_DPP2 */
1655
Sunil Ravi89eba102022-09-13 21:04:37 -07001656#ifdef CONFIG_DPP3
1657 if (!wpa_s->dpp_pb_result_indicated) {
1658 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "success");
1659 wpa_s->dpp_pb_result_indicated = true;
1660 }
1661
1662#endif /* CONFIG_DPP3 */
1663
Hai Shalomc3565922019-10-28 11:58:20 -07001664 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001665}
1666
1667
Hai Shalomfdcde762020-04-02 11:19:20 -07001668static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1669 struct dpp_asymmetric_key *key)
1670{
1671#ifdef CONFIG_DPP2
1672 int res;
1673
1674 if (!key)
1675 return 0;
1676
1677 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1678 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001679 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001680
1681 while (key) {
1682 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1683 if (res < 0)
1684 return -1;
1685 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1686 res);
1687 key = key->next;
1688 }
1689#endif /* CONFIG_DPP2 */
1690
1691 return 0;
1692}
1693
1694
Hai Shalom899fcc72020-10-19 14:38:18 -07001695#ifdef CONFIG_DPP2
1696static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1697{
1698 struct wpa_supplicant *wpa_s = eloop_ctx;
1699 struct dpp_authentication *auth = wpa_s->dpp_auth;
1700
1701 if (!auth || !auth->csrattrs)
1702 return;
1703
1704 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1705 wpabuf_free(auth->csr);
1706 /* TODO: Additional information needed for CSR based on csrAttrs */
1707 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1708 wpa_s->conf->dpp_name : "Test");
1709 if (!auth->csr) {
1710 dpp_auth_deinit(wpa_s->dpp_auth);
1711 wpa_s->dpp_auth = NULL;
1712 return;
1713 }
1714
1715 wpas_dpp_start_gas_client(wpa_s);
1716}
1717#endif /* CONFIG_DPP2 */
1718
1719
Sunil Ravia04bd252022-05-02 22:54:18 -07001720#ifdef CONFIG_DPP3
1721static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1722{
1723 struct wpa_supplicant *wpa_s = eloop_ctx;
1724 struct dpp_authentication *auth = wpa_s->dpp_auth;
1725
1726 if (!auth || !auth->waiting_new_key)
1727 return;
1728
1729 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1730 wpas_dpp_start_gas_client(wpa_s);
1731}
1732#endif /* CONFIG_DPP3 */
1733
1734
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001735static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1736 enum gas_query_result result,
1737 const struct wpabuf *adv_proto,
1738 const struct wpabuf *resp, u16 status_code)
1739{
1740 struct wpa_supplicant *wpa_s = ctx;
1741 const u8 *pos;
1742 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001743 int res;
1744 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001745 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001746
Hai Shaloma20dcd72022-02-04 13:43:00 -08001747 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001748 wpa_s->dpp_gas_dialog_token = -1;
1749
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001750 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
1751 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001752 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1753 return;
1754 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001755 if (result != GAS_QUERY_SUCCESS ||
1756 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001757 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1758 goto fail;
1759 }
1760
1761 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1762 adv_proto);
1763 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1764 resp);
1765
1766 if (wpabuf_len(adv_proto) != 10 ||
1767 !(pos = wpabuf_head(adv_proto)) ||
1768 pos[0] != WLAN_EID_ADV_PROTO ||
1769 pos[1] != 8 ||
1770 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1771 pos[4] != 5 ||
1772 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1773 pos[8] != 0x1a ||
1774 pos[9] != 1) {
1775 wpa_printf(MSG_DEBUG,
1776 "DPP: Not a DPP Advertisement Protocol ID");
1777 goto fail;
1778 }
1779
Hai Shalom899fcc72020-10-19 14:38:18 -07001780 res = dpp_conf_resp_rx(auth, resp);
1781#ifdef CONFIG_DPP2
1782 if (res == -2) {
1783 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1784 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1785 return;
1786 }
1787#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07001788#ifdef CONFIG_DPP3
1789 if (res == -3) {
1790 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1791 eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
1792 NULL);
1793 return;
1794 }
1795#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -07001796 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001797 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1798 goto fail;
1799 }
1800
Hai Shalom899fcc72020-10-19 14:38:18 -07001801 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001802 for (i = 0; i < auth->num_conf_obj; i++) {
1803 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1804 &auth->conf_obj[i]);
1805 if (res < 0)
1806 goto fail;
1807 }
1808 if (auth->num_conf_obj)
1809 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001810 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1811 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001812
Hai Shalom021b0b52019-04-10 11:17:58 -07001813 status = DPP_STATUS_OK;
1814#ifdef CONFIG_TESTING_OPTIONS
1815 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1816 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1817 status = DPP_STATUS_CONFIG_REJECTED;
1818 }
1819#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001820fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001821 if (status != DPP_STATUS_OK) {
1822 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1823 wpas_notify_dpp_configuration_failure(wpa_s);
1824 }
1825#ifdef CONFIG_DPP2
1826 if (auth->peer_version >= 2 &&
1827 auth->conf_resp_status == DPP_STATUS_OK) {
1828 struct wpabuf *msg;
1829
1830 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1831 msg = dpp_build_conf_result(auth, status);
1832 if (!msg)
1833 goto fail2;
1834
1835 wpa_msg(wpa_s, MSG_INFO,
1836 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1837 MAC2STR(addr), auth->curr_freq,
1838 DPP_PA_CONFIGURATION_RESULT);
1839 offchannel_send_action(wpa_s, auth->curr_freq,
1840 addr, wpa_s->own_addr, broadcast,
1841 wpabuf_head(msg),
1842 wpabuf_len(msg),
1843 500, wpas_dpp_tx_status, 0);
1844 wpabuf_free(msg);
1845
1846 /* This exchange will be terminated in the TX status handler */
Sunil Ravi546a7b52022-08-26 22:06:04 +00001847 if (wpa_s->conf->dpp_config_processing < 1 ||
Hai Shalom899fcc72020-10-19 14:38:18 -07001848 wpa_s->dpp_conf_backup_received)
1849 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001850 return;
1851 }
1852fail2:
1853#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001854 dpp_auth_deinit(wpa_s->dpp_auth);
1855 wpa_s->dpp_auth = NULL;
1856}
1857
1858
Hai Shaloma20dcd72022-02-04 13:43:00 -08001859static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx)
1860{
1861 struct wpa_supplicant *wpa_s = eloop_ctx;
1862 struct dpp_authentication *auth = wpa_s->dpp_auth;
1863
1864 if (!wpa_s->dpp_gas_client || !auth ||
1865 (!auth->auth_success && !auth->reconfig_success))
1866 return;
1867
1868 wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response");
1869 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1870 dpp_auth_deinit(wpa_s->dpp_auth);
1871 wpa_s->dpp_auth = NULL;
1872}
1873
1874
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001875static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1876{
1877 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001878 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001879 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001880 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001881
1882 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001883 offchannel_send_action_done(wpa_s);
1884 wpas_dpp_listen_stop(wpa_s);
1885
Hai Shalomc3565922019-10-28 11:58:20 -07001886 supp_op_classes = wpas_supp_op_classes(wpa_s);
1887 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001888 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001889 wpa_s->conf->dpp_mud_url,
Sunil Ravi89eba102022-09-13 21:04:37 -07001890 supp_op_classes,
1891 wpa_s->conf->dpp_extra_conf_req_name,
1892 wpa_s->conf->dpp_extra_conf_req_value);
Hai Shalomc3565922019-10-28 11:58:20 -07001893 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001894 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001895 wpa_printf(MSG_DEBUG,
1896 "DPP: No configuration request data available");
1897 return;
1898 }
1899
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001900 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1901 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1902
Hai Shaloma20dcd72022-02-04 13:43:00 -08001903 /* Use a 120 second timeout since the gas_query_req() operation could
1904 * remain waiting indefinitely for the response if the Configurator
1905 * keeps sending out comeback responses with additional delay. The
1906 * DPP technical specification expects the Enrollee to continue sending
1907 * out new Config Requests for 60 seconds, so this gives an extra 60
1908 * second time after the last expected new Config Request for the
1909 * Configurator to determine what kind of configuration to provide. */
1910 eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout,
1911 wpa_s, NULL);
1912
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001913 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001914 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001915 if (res < 0) {
1916 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1917 wpabuf_free(buf);
1918 } else {
1919 wpa_printf(MSG_DEBUG,
1920 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001921 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001922 }
1923}
1924
1925
1926static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1927{
1928 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001929 dpp_notify_auth_success(wpa_s->dpp_auth, initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001930 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001931#ifdef CONFIG_TESTING_OPTIONS
1932 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1933 wpa_printf(MSG_INFO,
1934 "DPP: TESTING - stop at Authentication Confirm");
1935 if (wpa_s->dpp_auth->configurator) {
1936 /* Prevent GAS response */
1937 wpa_s->dpp_auth->auth_success = 0;
1938 }
1939 return;
1940 }
1941#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001942
1943 if (wpa_s->dpp_auth->configurator)
1944 wpas_dpp_start_gas_server(wpa_s);
1945 else
1946 wpas_dpp_start_gas_client(wpa_s);
1947}
1948
1949
1950static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001951 const u8 *hdr, const u8 *buf, size_t len,
1952 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001953{
1954 struct dpp_authentication *auth = wpa_s->dpp_auth;
1955 struct wpabuf *msg;
1956
Roshan Pius3a1667e2018-07-03 15:17:14 -07001957 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1958 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001959
1960 if (!auth) {
1961 wpa_printf(MSG_DEBUG,
1962 "DPP: No DPP Authentication in progress - drop");
1963 return;
1964 }
1965
1966 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1967 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1968 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1969 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1970 return;
1971 }
1972
1973 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1974
Roshan Pius3a1667e2018-07-03 15:17:14 -07001975 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1976 wpa_printf(MSG_DEBUG,
1977 "DPP: Responder accepted request for different negotiation channel");
1978 auth->curr_freq = freq;
1979 }
1980
1981 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001982 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1983 if (!msg) {
1984 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1985 wpa_printf(MSG_DEBUG,
1986 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001987 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001988 offchannel_send_action_done(wpa_s);
1989 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1990 return;
1991 }
1992 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1993 return;
1994 }
1995 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1996
Roshan Pius3a1667e2018-07-03 15:17:14 -07001997 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1998 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001999 offchannel_send_action(wpa_s, auth->curr_freq,
2000 src, wpa_s->own_addr, broadcast,
2001 wpabuf_head(msg), wpabuf_len(msg),
2002 500, wpas_dpp_tx_status, 0);
2003 wpabuf_free(msg);
2004 wpa_s->dpp_auth_ok_on_ack = 1;
2005}
2006
2007
2008static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2009 const u8 *hdr, const u8 *buf, size_t len)
2010{
2011 struct dpp_authentication *auth = wpa_s->dpp_auth;
2012
2013 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
2014 MAC2STR(src));
2015
2016 if (!auth) {
2017 wpa_printf(MSG_DEBUG,
2018 "DPP: No DPP Authentication in progress - drop");
2019 return;
2020 }
2021
2022 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2023 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2024 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2025 return;
2026 }
2027
Hai Shalom60840252021-02-19 19:02:11 -08002028 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
2029
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002030 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
2031 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08002032 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002033 return;
2034 }
2035
2036 wpas_dpp_auth_success(wpa_s, 0);
2037}
2038
2039
Hai Shalom021b0b52019-04-10 11:17:58 -07002040#ifdef CONFIG_DPP2
2041
2042static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
2043 void *timeout_ctx)
2044{
2045 struct wpa_supplicant *wpa_s = eloop_ctx;
2046 struct dpp_authentication *auth = wpa_s->dpp_auth;
2047
2048 if (!auth || !auth->waiting_conf_result)
2049 return;
2050
2051 wpa_printf(MSG_DEBUG,
2052 "DPP: Timeout while waiting for Configuration Result");
2053 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002054 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002055 dpp_auth_deinit(auth);
2056 wpa_s->dpp_auth = NULL;
2057}
2058
2059
Hai Shalomc3565922019-10-28 11:58:20 -07002060static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
2061 void *timeout_ctx)
2062{
2063 struct wpa_supplicant *wpa_s = eloop_ctx;
2064 struct dpp_authentication *auth = wpa_s->dpp_auth;
2065
2066 if (!auth || !auth->waiting_conn_status_result)
2067 return;
2068
2069 wpa_printf(MSG_DEBUG,
2070 "DPP: Timeout while waiting for Connection Status Result");
2071 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08002072 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002073 wpas_dpp_listen_stop(wpa_s);
2074 dpp_auth_deinit(auth);
2075 wpa_s->dpp_auth = NULL;
2076}
2077
2078
Sunil Ravi89eba102022-09-13 21:04:37 -07002079#ifdef CONFIG_DPP3
2080
2081static bool wpas_dpp_pb_active(struct wpa_supplicant *wpa_s)
2082{
2083 return (wpa_s->dpp_pb_time.sec || wpa_s->dpp_pb_time.usec) &&
2084 wpa_s->dpp_pb_configurator;
2085}
2086
2087
2088static void wpas_dpp_remove_pb_hash(struct wpa_supplicant *wpa_s)
2089{
2090 int i;
2091
2092 if (!wpa_s->dpp_pb_bi)
2093 return;
2094 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
2095 struct dpp_pb_info *info = &wpa_s->dpp_pb[i];
2096
2097 if (info->rx_time.sec == 0 && info->rx_time.usec == 0)
2098 continue;
2099 if (os_memcmp(info->hash, wpa_s->dpp_pb_resp_hash,
2100 SHA256_MAC_LEN) == 0) {
2101 /* Allow a new push button session to be established
2102 * immediately without the successfully completed
2103 * session triggering session overlap. */
2104 info->rx_time.sec = 0;
2105 info->rx_time.usec = 0;
2106 wpa_printf(MSG_DEBUG,
2107 "DPP: Removed PB hash from session overlap detection due to successfully completed provisioning");
2108 }
2109 }
2110}
2111
2112#endif /* CONFIG_DPP3 */
2113
2114
Hai Shalom021b0b52019-04-10 11:17:58 -07002115static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
2116 const u8 *hdr, const u8 *buf, size_t len)
2117{
2118 struct dpp_authentication *auth = wpa_s->dpp_auth;
2119 enum dpp_status_error status;
2120
2121 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
2122 MAC2STR(src));
2123
2124 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08002125 if (auth &&
2126 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
2127 gas_server_response_sent(wpa_s->gas_server,
2128 auth->gas_server_ctx)) {
2129 /* This could happen if the TX status event gets delayed
2130 * long enough for the Enrollee to have time to send
2131 * the next frame before the TX status gets processed
2132 * locally. */
2133 wpa_printf(MSG_DEBUG,
2134 "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");
2135 auth->waiting_conf_result = 1;
2136 } else {
2137 wpa_printf(MSG_DEBUG,
2138 "DPP: No DPP Configuration waiting for result - drop");
2139 return;
2140 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002141 }
2142
2143 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2144 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2145 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2146 return;
2147 }
2148
2149 status = dpp_conf_result_rx(auth, hdr, buf, len);
2150
Hai Shalomc3565922019-10-28 11:58:20 -07002151 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002152 int freq;
2153
Hai Shalomc3565922019-10-28 11:58:20 -07002154 wpa_msg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07002155 DPP_EVENT_CONF_SENT "wait_conn_status=1 conf_status=%d",
2156 auth->conf_resp_status);
Hai Shalomc3565922019-10-28 11:58:20 -07002157 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08002158 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002159 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2160 wpa_s, NULL);
2161 auth->waiting_conn_status_result = 1;
2162 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2163 wpa_s, NULL);
2164 eloop_register_timeout(16, 0,
2165 wpas_dpp_conn_status_result_wait_timeout,
2166 wpa_s, NULL);
2167 offchannel_send_action_done(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002168 freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq;
2169 if (!wpa_s->dpp_in_response_listen ||
2170 (int) wpa_s->dpp_listen_freq != freq)
2171 wpas_dpp_listen_start(wpa_s, freq);
Hai Shalomc3565922019-10-28 11:58:20 -07002172 return;
2173 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002174 offchannel_send_action_done(wpa_s);
2175 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002176 if (status == DPP_STATUS_OK) {
Sunil Ravi89eba102022-09-13 21:04:37 -07002177 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
2178 auth->conf_resp_status);
Hai Shalome4073332019-11-05 16:20:12 -08002179 wpas_notify_dpp_config_sent(wpa_s);
2180 }
2181 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07002182 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08002183 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08002184 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002185 dpp_auth_deinit(auth);
2186 wpa_s->dpp_auth = NULL;
2187 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07002188#ifdef CONFIG_DPP3
2189 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
2190 if (status == DPP_STATUS_OK)
2191 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2192 "success");
2193 else
2194 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
2195 "no-configuration-available");
2196 wpa_s->dpp_pb_result_indicated = true;
2197 if (status == DPP_STATUS_OK)
2198 wpas_dpp_remove_pb_hash(wpa_s);
2199 wpas_dpp_push_button_stop(wpa_s);
2200 }
2201#endif /* CONFIG_DPP3 */
Hai Shalom021b0b52019-04-10 11:17:58 -07002202}
2203
Hai Shalom81f62d82019-07-22 12:10:00 -07002204
Hai Shalomc3565922019-10-28 11:58:20 -07002205static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
2206 const u8 *src, const u8 *hdr,
2207 const u8 *buf, size_t len)
2208{
2209 struct dpp_authentication *auth = wpa_s->dpp_auth;
2210 enum dpp_status_error status;
2211 u8 ssid[SSID_MAX_LEN];
2212 size_t ssid_len = 0;
2213 char *channel_list = NULL;
2214
2215 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2216
2217 if (!auth || !auth->waiting_conn_status_result) {
2218 wpa_printf(MSG_DEBUG,
2219 "DPP: No DPP Configuration waiting for connection status result - drop");
2220 return;
2221 }
2222
2223 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2224 ssid, &ssid_len, &channel_list);
2225 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2226 "result=%d ssid=%s channel_list=%s",
2227 status, wpa_ssid_txt(ssid, ssid_len),
2228 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002229 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2230 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002231 os_free(channel_list);
2232 offchannel_send_action_done(wpa_s);
2233 wpas_dpp_listen_stop(wpa_s);
2234 dpp_auth_deinit(auth);
2235 wpa_s->dpp_auth = NULL;
2236 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2237 wpa_s, NULL);
2238}
2239
2240
Hai Shalom81f62d82019-07-22 12:10:00 -07002241static int wpas_dpp_process_conf_obj(void *ctx,
2242 struct dpp_authentication *auth)
2243{
2244 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002245 unsigned int i;
2246 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002247
Hai Shalomc3565922019-10-28 11:58:20 -07002248 for (i = 0; i < auth->num_conf_obj; i++) {
2249 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2250 &auth->conf_obj[i]);
2251 if (res)
2252 break;
2253 }
2254 if (!res)
2255 wpas_dpp_post_process_config(wpa_s, auth);
2256
2257 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002258}
2259
Hai Shalomfdcde762020-04-02 11:19:20 -07002260
Hai Shaloma20dcd72022-02-04 13:43:00 -08002261static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
2262{
2263 struct wpa_supplicant *wpa_s = ctx;
2264
2265 wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
2266
2267 if (auth->connect_on_tx_status) {
2268 auth->connect_on_tx_status = 0;
2269 wpa_printf(MSG_DEBUG,
2270 "DPP: Try to connect after completed configuration result");
2271 wpas_dpp_try_to_connect(wpa_s);
2272 if (auth->conn_status_requested) {
2273 wpa_printf(MSG_DEBUG,
2274 "DPP: Start 15 second timeout for reporting connection status result");
2275 eloop_cancel_timeout(
2276 wpas_dpp_conn_status_result_timeout,
2277 wpa_s, NULL);
2278 eloop_register_timeout(
2279 15, 0, wpas_dpp_conn_status_result_timeout,
2280 wpa_s, NULL);
2281 return true;
2282 }
2283 }
2284
2285 return false;
2286}
2287
2288
Hai Shalomfdcde762020-04-02 11:19:20 -07002289static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2290{
2291 struct wpa_supplicant *wpa_s = ctx;
2292
2293 if (bi == wpa_s->dpp_chirp_bi)
2294 wpas_dpp_chirp_stop(wpa_s);
2295}
2296
2297
2298static void
2299wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2300 const u8 *hdr, const u8 *buf, size_t len,
2301 unsigned int freq)
2302{
2303 const u8 *r_bootstrap;
2304 u16 r_bootstrap_len;
2305 struct dpp_bootstrap_info *peer_bi;
2306 struct dpp_authentication *auth;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002307 unsigned int wait_time, max_wait_time;
Hai Shalomfdcde762020-04-02 11:19:20 -07002308
2309 if (!wpa_s->dpp)
2310 return;
2311
2312 if (wpa_s->dpp_auth) {
2313 wpa_printf(MSG_DEBUG,
2314 "DPP: Ignore Presence Announcement during ongoing Authentication");
2315 return;
2316 }
2317
2318 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2319 MAC2STR(src));
2320
2321 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2322 &r_bootstrap_len);
2323 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2324 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2325 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2326 return;
2327 }
2328 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2329 r_bootstrap, r_bootstrap_len);
2330 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002331 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2332 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002333 if (!peer_bi) {
2334 wpa_printf(MSG_DEBUG,
2335 "DPP: No matching bootstrapping information found");
2336 return;
2337 }
2338
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002339 wpa_printf(MSG_DEBUG, "DPP: Start Authentication exchange with " MACSTR
2340 " based on the received Presence Announcement",
2341 MAC2STR(src));
Hai Shalomfdcde762020-04-02 11:19:20 -07002342 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2343 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2344 if (!auth)
2345 return;
2346 wpas_dpp_set_testing_options(wpa_s, auth);
2347 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2348 dpp_auth_deinit(auth);
2349 return;
2350 }
2351
2352 auth->neg_freq = freq;
2353
Hai Shalom60840252021-02-19 19:02:11 -08002354 /* The source address of the Presence Announcement frame overrides any
2355 * MAC address information from the bootstrapping information. */
2356 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002357
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002358 wait_time = wpa_s->max_remain_on_chan;
2359 max_wait_time = wpa_s->dpp_resp_wait_time ?
2360 wpa_s->dpp_resp_wait_time : 2000;
2361 if (wait_time > max_wait_time)
2362 wait_time = max_wait_time;
2363 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2364
Hai Shalomfdcde762020-04-02 11:19:20 -07002365 wpa_s->dpp_auth = auth;
2366 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2367 dpp_auth_deinit(wpa_s->dpp_auth);
2368 wpa_s->dpp_auth = NULL;
2369 }
2370}
2371
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002372
2373static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2374 void *timeout_ctx)
2375{
2376 struct wpa_supplicant *wpa_s = eloop_ctx;
2377 struct dpp_authentication *auth = wpa_s->dpp_auth;
2378
2379 if (!auth)
2380 return;
2381
2382 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2383 offchannel_send_action_done(wpa_s);
2384 wpas_dpp_listen_stop(wpa_s);
2385 dpp_auth_deinit(auth);
2386 wpa_s->dpp_auth = NULL;
2387}
2388
2389
2390static void
2391wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2392 const u8 *hdr, const u8 *buf, size_t len,
2393 unsigned int freq)
2394{
Hai Shalom899fcc72020-10-19 14:38:18 -07002395 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2396 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002397 struct dpp_configurator *conf;
2398 struct dpp_authentication *auth;
2399 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002400 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002401
2402 if (!wpa_s->dpp)
2403 return;
2404
2405 if (wpa_s->dpp_auth) {
2406 wpa_printf(MSG_DEBUG,
2407 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2408 return;
2409 }
2410
2411 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2412 MAC2STR(src));
2413
2414 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2415 &csign_hash_len);
2416 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2417 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2418 "Missing or invalid required Configurator C-sign key Hash attribute");
2419 return;
2420 }
2421 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2422 csign_hash, csign_hash_len);
2423 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2424 if (!conf) {
2425 wpa_printf(MSG_DEBUG,
2426 "DPP: No matching Configurator information found");
2427 return;
2428 }
2429
Hai Shalom899fcc72020-10-19 14:38:18 -07002430 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2431 &fcgroup_len);
2432 if (!fcgroup || fcgroup_len != 2) {
2433 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2434 "Missing or invalid required Finite Cyclic Group attribute");
2435 return;
2436 }
2437 group = WPA_GET_LE16(fcgroup);
2438 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2439
2440 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2441 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2442
2443 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2444 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002445 if (!auth)
2446 return;
2447 wpas_dpp_set_testing_options(wpa_s, auth);
2448 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2449 dpp_auth_deinit(auth);
2450 return;
2451 }
2452
2453 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2454 wpa_s->dpp_auth = auth;
2455
2456 wpa_s->dpp_in_response_listen = 0;
2457 wpa_s->dpp_auth_ok_on_ack = 0;
2458 wait_time = wpa_s->max_remain_on_chan;
2459 max_wait_time = wpa_s->dpp_resp_wait_time ?
2460 wpa_s->dpp_resp_wait_time : 2000;
2461 if (wait_time > max_wait_time)
2462 wait_time = max_wait_time;
2463 wait_time += 10; /* give the driver some extra time to complete */
2464 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2465 wpas_dpp_reconfig_reply_wait_timeout,
2466 wpa_s, NULL);
2467 wait_time -= 10;
2468
2469 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2470
2471 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2472 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2473 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2474 wpabuf_head(auth->reconfig_req_msg),
2475 wpabuf_len(auth->reconfig_req_msg),
2476 wait_time, wpas_dpp_tx_status, 0) < 0) {
2477 dpp_auth_deinit(wpa_s->dpp_auth);
2478 wpa_s->dpp_auth = NULL;
2479 }
2480}
2481
2482
2483static void
2484wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2485 const u8 *hdr, const u8 *buf, size_t len,
2486 unsigned int freq)
2487{
2488 struct wpa_ssid *ssid;
2489 struct dpp_authentication *auth;
2490
2491 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2492 MACSTR, MAC2STR(src));
2493
Hai Shalom899fcc72020-10-19 14:38:18 -07002494 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002495 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002496 if (wpa_s->dpp_auth) {
2497 wpa_printf(MSG_DEBUG,
2498 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2499 return;
2500 }
2501 if (!wpa_s->dpp_reconfig_ssid) {
2502 wpa_printf(MSG_DEBUG,
2503 "DPP: Not ready for reconfiguration - not requested");
2504 return;
2505 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002506 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2507 if (ssid == wpa_s->dpp_reconfig_ssid &&
2508 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2509 break;
2510 }
2511 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002512 !ssid->dpp_csign) {
2513 wpa_printf(MSG_DEBUG,
2514 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002515 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002516 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002517
2518 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2519 ssid->dpp_netaccesskey,
2520 ssid->dpp_netaccesskey_len,
2521 ssid->dpp_csign, ssid->dpp_csign_len,
2522 freq, hdr, buf, len);
2523 if (!auth)
2524 return;
2525 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2526 wpa_s->dpp_auth = auth;
2527
2528 wpas_dpp_chirp_stop(wpa_s);
2529
2530 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2531 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2532 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2533 wpabuf_head(auth->reconfig_resp_msg),
2534 wpabuf_len(auth->reconfig_resp_msg),
2535 500, wpas_dpp_tx_status, 0) < 0) {
2536 dpp_auth_deinit(wpa_s->dpp_auth);
2537 wpa_s->dpp_auth = NULL;
2538 }
2539}
2540
2541
2542static void
2543wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2544 const u8 *hdr, const u8 *buf, size_t len,
2545 unsigned int freq)
2546{
2547 struct dpp_authentication *auth = wpa_s->dpp_auth;
2548 struct wpabuf *conf;
2549
2550 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2551 MACSTR, MAC2STR(src));
2552
2553 if (!auth || !auth->reconfig || !auth->configurator) {
2554 wpa_printf(MSG_DEBUG,
2555 "DPP: No DPP Reconfig Authentication in progress - drop");
2556 return;
2557 }
2558
2559 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2560 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2561 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2562 return;
2563 }
2564
2565 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2566 if (!conf)
2567 return;
2568
2569 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2570
2571 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2572 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2573 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2574 wpabuf_head(conf), wpabuf_len(conf),
2575 500, wpas_dpp_tx_status, 0) < 0) {
2576 wpabuf_free(conf);
2577 dpp_auth_deinit(wpa_s->dpp_auth);
2578 wpa_s->dpp_auth = NULL;
2579 return;
2580 }
2581 wpabuf_free(conf);
2582
2583 wpas_dpp_start_gas_server(wpa_s);
2584}
2585
2586
2587static void
2588wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2589 const u8 *hdr, const u8 *buf, size_t len,
2590 unsigned int freq)
2591{
2592 struct dpp_authentication *auth = wpa_s->dpp_auth;
2593
2594 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2595 MACSTR, MAC2STR(src));
2596
2597 if (!auth || !auth->reconfig || auth->configurator) {
2598 wpa_printf(MSG_DEBUG,
2599 "DPP: No DPP Reconfig Authentication in progress - drop");
2600 return;
2601 }
2602
2603 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2604 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2605 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2606 return;
2607 }
2608
2609 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2610 return;
2611
2612 wpas_dpp_start_gas_client(wpa_s);
2613}
2614
Hai Shalom021b0b52019-04-10 11:17:58 -07002615#endif /* CONFIG_DPP2 */
2616
2617
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002618static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2619 const u8 *src,
2620 const u8 *buf, size_t len)
2621{
2622 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002623 const u8 *connector, *trans_id, *status;
2624 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002625#ifdef CONFIG_DPP2
2626 const u8 *version;
2627 u16 version_len;
2628#endif /* CONFIG_DPP2 */
2629 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002630 struct dpp_introduction intro;
2631 struct rsn_pmksa_cache_entry *entry;
2632 struct os_time now;
2633 struct os_reltime rnow;
2634 os_time_t expiry;
2635 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002636 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002637
2638 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2639 MAC2STR(src));
2640 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2641 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2642 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2643 MACSTR " - drop", MAC2STR(src));
2644 return;
2645 }
2646 offchannel_send_action_done(wpa_s);
2647
2648 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2649 if (ssid == wpa_s->dpp_intro_network)
2650 break;
2651 }
2652 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2653 !ssid->dpp_csign) {
2654 wpa_printf(MSG_DEBUG,
2655 "DPP: Profile not found for network introduction");
2656 return;
2657 }
2658
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002659 os_memset(&intro, 0, sizeof(intro));
2660
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002661 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2662 &trans_id_len);
2663 if (!trans_id || trans_id_len != 1) {
2664 wpa_printf(MSG_DEBUG,
2665 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002666 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2667 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002668 goto fail;
2669 }
2670 if (trans_id[0] != TRANSACTION_ID) {
2671 wpa_printf(MSG_DEBUG,
2672 "DPP: Ignore frame with unexpected Transaction ID %u",
2673 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002674 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2675 " fail=transaction_id_mismatch", MAC2STR(src));
2676 goto fail;
2677 }
2678
2679 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2680 if (!status || status_len != 1) {
2681 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2682 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2683 " fail=missing_status", MAC2STR(src));
2684 goto fail;
2685 }
2686 if (status[0] != DPP_STATUS_OK) {
2687 wpa_printf(MSG_DEBUG,
2688 "DPP: Peer rejected network introduction: Status %u",
2689 status[0]);
2690 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2691 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002692#ifdef CONFIG_DPP2
2693 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2694#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002695 goto fail;
2696 }
2697
2698 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2699 if (!connector) {
2700 wpa_printf(MSG_DEBUG,
2701 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002702 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2703 " fail=missing_connector", MAC2STR(src));
2704 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002705 }
2706
Roshan Pius3a1667e2018-07-03 15:17:14 -07002707 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2708 ssid->dpp_netaccesskey,
2709 ssid->dpp_netaccesskey_len,
2710 ssid->dpp_csign,
2711 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002712 connector, connector_len, &expiry, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002713 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002714 wpa_printf(MSG_INFO,
2715 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002716 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2717 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002718#ifdef CONFIG_DPP2
2719 wpas_dpp_send_conn_status_result(wpa_s, res);
2720#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002721 goto fail;
2722 }
2723
2724 entry = os_zalloc(sizeof(*entry));
2725 if (!entry)
2726 goto fail;
2727 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002728 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002729 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2730 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2731 entry->pmk_len = intro.pmk_len;
2732 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002733#ifdef CONFIG_DPP2
2734 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2735 &version_len);
2736 if (version && version_len >= 1)
2737 peer_version = version[0];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002738#ifdef CONFIG_DPP3
2739 if (intro.peer_version && intro.peer_version >= 2 &&
2740 peer_version != intro.peer_version) {
2741 wpa_printf(MSG_INFO,
2742 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
2743 intro.peer_version, peer_version);
2744 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
2745 goto fail;
2746 }
2747#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002748 entry->dpp_pfs = peer_version >= 2;
2749#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002750 if (expiry) {
2751 os_get_time(&now);
2752 seconds = expiry - now.sec;
2753 } else {
2754 seconds = 86400 * 7;
2755 }
2756 os_get_reltime(&rnow);
2757 entry->expiration = rnow.sec + seconds;
2758 entry->reauth_time = rnow.sec + seconds;
2759 entry->network_ctx = ssid;
2760 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2761
Roshan Pius3a1667e2018-07-03 15:17:14 -07002762 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002763 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002764
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002765 wpa_printf(MSG_DEBUG,
2766 "DPP: Try connection again after successful network introduction");
2767 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2768 wpa_supplicant_cancel_sched_scan(wpa_s);
2769 wpa_supplicant_req_scan(wpa_s, 0, 0);
2770 }
2771fail:
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002772 dpp_peer_intro_deinit(&intro);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002773}
2774
2775
Roshan Pius3a1667e2018-07-03 15:17:14 -07002776static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2777{
2778 int i, j;
2779
2780 if (!wpa_s->hw.modes)
2781 return -1;
2782
2783 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2784 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2785
2786 for (j = 0; j < mode->num_channels; j++) {
2787 struct hostapd_channel_data *chan = &mode->channels[j];
2788
2789 if (chan->freq != (int) freq)
2790 continue;
2791
2792 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2793 HOSTAPD_CHAN_NO_IR |
2794 HOSTAPD_CHAN_RADAR))
2795 continue;
2796
2797 return 1;
2798 }
2799 }
2800
2801 wpa_printf(MSG_DEBUG,
2802 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2803 freq);
2804
2805 return 0;
2806}
2807
2808
2809static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2810 struct dpp_pkex *pkex)
2811{
2812 if (pkex->freq == 2437)
2813 pkex->freq = 5745;
2814 else if (pkex->freq == 5745)
2815 pkex->freq = 5220;
2816 else if (pkex->freq == 5220)
2817 pkex->freq = 60480;
2818 else
2819 return -1; /* no more channels to try */
2820
2821 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2822 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2823 pkex->freq);
2824 return 0;
2825 }
2826
2827 /* Could not use this channel - try the next one */
2828 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2829}
2830
2831
Sunil Ravi89eba102022-09-13 21:04:37 -07002832static void wpas_dpp_pkex_clear_code(struct wpa_supplicant *wpa_s)
2833{
2834 if (!wpa_s->dpp_pkex_code && !wpa_s->dpp_pkex_identifier)
2835 return;
2836
2837 /* Delete PKEX code and identifier on successful completion of
2838 * PKEX. We are not supposed to reuse these without being
2839 * explicitly requested to perform PKEX again. */
2840 wpa_printf(MSG_DEBUG, "DPP: Delete PKEX code/identifier");
2841 os_free(wpa_s->dpp_pkex_code);
2842 wpa_s->dpp_pkex_code = NULL;
2843 os_free(wpa_s->dpp_pkex_identifier);
2844 wpa_s->dpp_pkex_identifier = NULL;
2845
2846}
2847
2848
Hai Shaloma20dcd72022-02-04 13:43:00 -08002849#ifdef CONFIG_DPP2
2850static int wpas_dpp_pkex_done(void *ctx, void *conn,
2851 struct dpp_bootstrap_info *peer_bi)
2852{
2853 struct wpa_supplicant *wpa_s = ctx;
Sunil Ravi89eba102022-09-13 21:04:37 -07002854 char cmd[500];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002855 const char *pos;
2856 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2857 struct dpp_bootstrap_info *own_bi = NULL;
2858 struct dpp_authentication *auth;
2859
Sunil Ravi89eba102022-09-13 21:04:37 -07002860 wpas_dpp_pkex_clear_code(wpa_s);
2861
2862 os_snprintf(cmd, sizeof(cmd), " peer=%u %s", peer_bi->id,
2863 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
Hai Shaloma20dcd72022-02-04 13:43:00 -08002864 wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)",
2865 cmd);
2866
2867 pos = os_strstr(cmd, " own=");
2868 if (pos) {
2869 pos += 5;
2870 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
2871 if (!own_bi) {
2872 wpa_printf(MSG_INFO,
2873 "DPP: Could not find bootstrapping info for the identified local entry");
2874 return -1;
2875 }
2876
2877 if (peer_bi->curve != own_bi->curve) {
2878 wpa_printf(MSG_INFO,
2879 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
2880 peer_bi->curve->name, own_bi->curve->name);
2881 return -1;
2882 }
2883 }
2884
2885 pos = os_strstr(cmd, " role=");
2886 if (pos) {
2887 pos += 6;
2888 if (os_strncmp(pos, "configurator", 12) == 0)
2889 allowed_roles = DPP_CAPAB_CONFIGURATOR;
2890 else if (os_strncmp(pos, "enrollee", 8) == 0)
2891 allowed_roles = DPP_CAPAB_ENROLLEE;
2892 else if (os_strncmp(pos, "either", 6) == 0)
2893 allowed_roles = DPP_CAPAB_CONFIGURATOR |
2894 DPP_CAPAB_ENROLLEE;
2895 else
2896 return -1;
2897 }
2898
2899 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
2900 0, wpa_s->hw.modes, wpa_s->hw.num_modes);
2901 if (!auth)
2902 return -1;
2903
2904 wpas_dpp_set_testing_options(wpa_s, auth);
2905 if (dpp_set_configurator(auth, cmd) < 0) {
2906 dpp_auth_deinit(auth);
2907 return -1;
2908 }
2909
2910 return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
Sunil Ravi89eba102022-09-13 21:04:37 -07002911 DPP_NETROLE_STA,
2912 wpa_s->conf->dpp_mud_url,
2913 wpa_s->conf->dpp_extra_conf_req_name,
2914 wpa_s->conf->dpp_extra_conf_req_value,
2915 wpas_dpp_process_conf_obj,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002916 wpas_dpp_tcp_msg_sent);
2917}
2918#endif /* CONFIG_DPP2 */
2919
2920
Hai Shaloma20dcd72022-02-04 13:43:00 -08002921static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s,
Sunil Ravia04bd252022-05-02 22:54:18 -07002922 enum dpp_pkex_ver ver,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002923 const struct hostapd_ip_addr *ipaddr,
2924 int tcp_port)
2925{
2926 struct dpp_pkex *pkex;
2927 struct wpabuf *msg;
2928 unsigned int wait_time;
2929 bool v2 = ver != PKEX_VER_ONLY_1;
2930
2931 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1);
2932 dpp_pkex_free(wpa_s->dpp_pkex);
2933 wpa_s->dpp_pkex = NULL;
2934 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
2935 wpa_s->dpp_pkex_identifier,
Sunil Ravi89eba102022-09-13 21:04:37 -07002936 wpa_s->dpp_pkex_code, wpa_s->dpp_pkex_code_len,
2937 v2);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002938 if (!pkex)
2939 return -1;
2940 pkex->forced_ver = ver != PKEX_VER_AUTO;
2941
2942 if (ipaddr) {
2943#ifdef CONFIG_DPP2
2944 return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port,
2945 wpa_s, wpa_s, wpas_dpp_pkex_done);
2946#else /* CONFIG_DPP2 */
2947 return -1;
2948#endif /* CONFIG_DPP2 */
2949 }
2950
2951 wpa_s->dpp_pkex = pkex;
2952 msg = pkex->exchange_req;
2953 wait_time = wpa_s->max_remain_on_chan;
2954 if (wait_time > 2000)
2955 wait_time = 2000;
2956 pkex->freq = 2437;
2957 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2958 " freq=%u type=%d",
2959 MAC2STR(broadcast), pkex->freq,
2960 v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
2961 DPP_PA_PKEX_V1_EXCHANGE_REQ);
2962 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2963 wpa_s->own_addr, broadcast,
2964 wpabuf_head(msg), wpabuf_len(msg),
2965 wait_time, wpas_dpp_tx_pkex_status, 0);
2966 if (wait_time == 0)
2967 wait_time = 2000;
2968 pkex->exch_req_wait_time = wait_time;
2969 pkex->exch_req_tries = 1;
2970
2971 return 0;
2972}
2973
2974
Roshan Pius3a1667e2018-07-03 15:17:14 -07002975static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
2976{
2977 struct wpa_supplicant *wpa_s = eloop_ctx;
2978 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2979
2980 if (!pkex || !pkex->exchange_req)
2981 return;
2982 if (pkex->exch_req_tries >= 5) {
2983 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08002984#ifdef CONFIG_DPP3
2985 if (pkex->v2 && !pkex->forced_ver) {
2986 wpa_printf(MSG_DEBUG,
2987 "DPP: Fall back to PKEXv1");
2988 wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1,
2989 NULL, 0);
2990 return;
2991 }
2992#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002993 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2994 "No response from PKEX peer");
2995 dpp_pkex_free(pkex);
2996 wpa_s->dpp_pkex = NULL;
2997 return;
2998 }
2999 pkex->exch_req_tries = 0;
3000 }
3001
3002 pkex->exch_req_tries++;
3003 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
3004 pkex->exch_req_tries);
3005 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shaloma20dcd72022-02-04 13:43:00 -08003006 MAC2STR(broadcast), pkex->freq,
3007 pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
3008 DPP_PA_PKEX_V1_EXCHANGE_REQ);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003009 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3010 wpa_s->own_addr, broadcast,
3011 wpabuf_head(pkex->exchange_req),
3012 wpabuf_len(pkex->exchange_req),
3013 pkex->exch_req_wait_time,
3014 wpas_dpp_tx_pkex_status, 0);
3015}
3016
3017
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003018static void
3019wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
3020 unsigned int freq, const u8 *dst,
3021 const u8 *src, const u8 *bssid,
3022 const u8 *data, size_t data_len,
3023 enum offchannel_send_action_result result)
3024{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003025 const char *res_txt;
3026 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3027
3028 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3029 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3030 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003031 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3032 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003033 freq, MAC2STR(dst), res_txt);
3034 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3035 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3036
3037 if (!pkex) {
3038 wpa_printf(MSG_DEBUG,
3039 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
3040 return;
3041 }
3042
3043 if (pkex->failed) {
3044 wpa_printf(MSG_DEBUG,
3045 "DPP: Terminate PKEX exchange due to an earlier error");
3046 if (pkex->t > pkex->own_bi->pkex_t)
3047 pkex->own_bi->pkex_t = pkex->t;
3048 dpp_pkex_free(pkex);
3049 wpa_s->dpp_pkex = NULL;
3050 return;
3051 }
3052
3053 if (pkex->exch_req_wait_time && pkex->exchange_req) {
3054 /* Wait for PKEX Exchange Response frame and retry request if
3055 * no response is seen. */
3056 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3057 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
3058 (pkex->exch_req_wait_time % 1000) * 1000,
3059 wpas_dpp_pkex_retry_timeout, wpa_s,
3060 NULL);
3061 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003062}
3063
3064
3065static void
3066wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003067 const u8 *buf, size_t len, unsigned int freq,
3068 bool v2)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003069{
3070 struct wpabuf *msg;
3071 unsigned int wait_time;
3072
3073 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
3074 MAC2STR(src));
3075
Sunil Ravia04bd252022-05-02 22:54:18 -07003076 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) {
3077 wpa_printf(MSG_DEBUG,
3078 "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only");
3079 return;
3080 }
3081 if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) {
3082 wpa_printf(MSG_DEBUG,
3083 "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only");
3084 return;
3085 }
3086
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003087 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3088 * values here */
3089
3090 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
3091 wpa_printf(MSG_DEBUG,
3092 "DPP: No PKEX code configured - ignore request");
3093 return;
3094 }
3095
Sunil Ravi89eba102022-09-13 21:04:37 -07003096#ifdef CONFIG_DPP2
3097 if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) {
3098 wpa_printf(MSG_DEBUG,
3099 "DPP: PKEX Exchange Request is from local Controller - ignore request");
3100 return;
3101 }
3102#endif /* CONFIG_DPP2 */
3103
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003104 if (wpa_s->dpp_pkex) {
3105 /* TODO: Support parallel operations */
3106 wpa_printf(MSG_DEBUG,
3107 "DPP: Already in PKEX session - ignore new request");
3108 return;
3109 }
3110
Roshan Pius3a1667e2018-07-03 15:17:14 -07003111 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003112 wpa_s->own_addr, src,
3113 wpa_s->dpp_pkex_identifier,
3114 wpa_s->dpp_pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07003115 wpa_s->dpp_pkex_code_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08003116 buf, len, v2);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003117 if (!wpa_s->dpp_pkex) {
3118 wpa_printf(MSG_DEBUG,
3119 "DPP: Failed to process the request - ignore it");
3120 return;
3121 }
3122
Sunil Ravi89eba102022-09-13 21:04:37 -07003123#ifdef CONFIG_DPP3
3124 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_announcement) {
3125 wpa_printf(MSG_DEBUG,
3126 "DPP: Started PB PKEX (no more PB announcements)");
3127 wpabuf_free(wpa_s->dpp_pb_announcement);
3128 wpa_s->dpp_pb_announcement = NULL;
3129 }
3130#endif /* CONFIG_DPP3 */
Sunil Ravia04bd252022-05-02 22:54:18 -07003131 wpa_s->dpp_pkex_wait_auth_req = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003132 msg = wpa_s->dpp_pkex->exchange_resp;
3133 wait_time = wpa_s->max_remain_on_chan;
3134 if (wait_time > 2000)
3135 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003136 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3137 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003138 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3139 broadcast,
3140 wpabuf_head(msg), wpabuf_len(msg),
3141 wait_time, wpas_dpp_tx_pkex_status, 0);
3142}
3143
3144
3145static void
3146wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3147 const u8 *buf, size_t len, unsigned int freq)
3148{
3149 struct wpabuf *msg;
3150 unsigned int wait_time;
3151
3152 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
3153 MAC2STR(src));
3154
3155 /* TODO: Support multiple PKEX codes by iterating over all the enabled
3156 * values here */
3157
3158 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
3159 wpa_s->dpp_pkex->exchange_done) {
3160 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3161 return;
3162 }
3163
Roshan Pius3a1667e2018-07-03 15:17:14 -07003164 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
3165 wpa_s->dpp_pkex->exch_req_wait_time = 0;
3166
3167 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003168 if (!msg) {
3169 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3170 return;
3171 }
3172
3173 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
3174 MAC2STR(src));
3175
3176 wait_time = wpa_s->max_remain_on_chan;
3177 if (wait_time > 2000)
3178 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003179 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3180 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003181 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3182 broadcast,
3183 wpabuf_head(msg), wpabuf_len(msg),
3184 wait_time, wpas_dpp_tx_pkex_status, 0);
3185 wpabuf_free(msg);
3186}
3187
3188
Roshan Pius3a1667e2018-07-03 15:17:14 -07003189static struct dpp_bootstrap_info *
3190wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
3191 unsigned int freq)
3192{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003193 struct dpp_bootstrap_info *bi;
3194
Sunil Ravi89eba102022-09-13 21:04:37 -07003195 wpas_dpp_pkex_clear_code(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003196 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003197 if (!bi)
3198 return NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003199
Roshan Pius3a1667e2018-07-03 15:17:14 -07003200 wpa_s->dpp_pkex = NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07003201
3202#ifdef CONFIG_DPP3
3203 if (wpa_s->dpp_pb_bi && !wpa_s->dpp_pb_configurator &&
3204 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_init_hash,
3205 SHA256_MAC_LEN) != 0) {
3206 char id[20];
3207
3208 wpa_printf(MSG_INFO,
3209 "DPP: Peer bootstrap key from PKEX does not match PB announcement response hash");
3210 wpa_hexdump(MSG_DEBUG,
3211 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3212 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3213 wpa_hexdump(MSG_DEBUG,
3214 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement response",
3215 wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN);
3216
3217 os_snprintf(id, sizeof(id), "%u", bi->id);
3218 dpp_bootstrap_remove(wpa_s->dpp, id);
3219 wpas_dpp_push_button_stop(wpa_s);
3220 return NULL;
3221 }
3222#endif /* CONFIG_DPP3 */
3223
Roshan Pius3a1667e2018-07-03 15:17:14 -07003224 return bi;
3225}
3226
3227
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003228static void
3229wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
3230 const u8 *hdr, const u8 *buf, size_t len,
3231 unsigned int freq)
3232{
3233 struct wpabuf *msg;
3234 unsigned int wait_time;
3235 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003236
3237 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
3238 MAC2STR(src));
3239
3240 if (!pkex || pkex->initiator || !pkex->exchange_done) {
3241 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3242 return;
3243 }
3244
3245 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
3246 if (!msg) {
3247 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07003248 if (pkex->failed) {
3249 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
3250 if (pkex->t > pkex->own_bi->pkex_t)
3251 pkex->own_bi->pkex_t = pkex->t;
3252 dpp_pkex_free(wpa_s->dpp_pkex);
3253 wpa_s->dpp_pkex = NULL;
3254 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003255 return;
3256 }
3257
3258 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
3259 MACSTR, MAC2STR(src));
3260
3261 wait_time = wpa_s->max_remain_on_chan;
3262 if (wait_time > 2000)
3263 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003264 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3265 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003266 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
3267 broadcast,
3268 wpabuf_head(msg), wpabuf_len(msg),
3269 wait_time, wpas_dpp_tx_pkex_status, 0);
3270 wpabuf_free(msg);
3271
Roshan Pius3a1667e2018-07-03 15:17:14 -07003272 wpas_dpp_pkex_finish(wpa_s, src, freq);
Sunil Ravia04bd252022-05-02 22:54:18 -07003273 wpa_s->dpp_pkex_wait_auth_req = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003274}
3275
3276
3277static void
3278wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
3279 const u8 *hdr, const u8 *buf, size_t len,
3280 unsigned int freq)
3281{
3282 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003283 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003284 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
3285 char cmd[500];
3286
3287 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
3288 MAC2STR(src));
3289
3290 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
3291 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
3292 return;
3293 }
3294
3295 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
3296 if (res < 0) {
3297 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
3298 return;
3299 }
3300
Roshan Pius3a1667e2018-07-03 15:17:14 -07003301 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003302 if (!bi)
3303 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003304
Sunil Ravi89eba102022-09-13 21:04:37 -07003305#ifdef CONFIG_DPP3
3306 if (wpa_s->dpp_pb_bi && wpa_s->dpp_pb_configurator &&
3307 os_memcmp(bi->pubkey_hash_chirp, wpa_s->dpp_pb_resp_hash,
3308 SHA256_MAC_LEN) != 0) {
3309 char id[20];
3310
3311 wpa_printf(MSG_INFO,
3312 "DPP: Peer bootstrap key from PKEX does not match PB announcement hash");
3313 wpa_hexdump(MSG_DEBUG,
3314 "DPP: Peer provided bootstrap key hash(chirp) from PB PKEX",
3315 bi->pubkey_hash_chirp, SHA256_MAC_LEN);
3316 wpa_hexdump(MSG_DEBUG,
3317 "DPP: Peer provided bootstrap key hash(chirp) from PB announcement",
3318 wpa_s->dpp_pb_resp_hash, SHA256_MAC_LEN);
3319
3320 os_snprintf(id, sizeof(id), "%u", bi->id);
3321 dpp_bootstrap_remove(wpa_s->dpp, id);
3322 wpas_dpp_push_button_stop(wpa_s);
3323 return;
3324 }
3325#endif /* CONFIG_DPP3 */
3326
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003327 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
3328 bi->id,
3329 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
3330 wpa_printf(MSG_DEBUG,
3331 "DPP: Start authentication after PKEX with parameters: %s",
3332 cmd);
3333 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
3334 wpa_printf(MSG_DEBUG,
3335 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07003336 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003337 return;
3338 }
3339}
3340
3341
Sunil Ravi89eba102022-09-13 21:04:37 -07003342#ifdef CONFIG_DPP3
3343
3344static void wpas_dpp_pb_pkex_init(struct wpa_supplicant *wpa_s,
3345 unsigned int freq, const u8 *src,
3346 const u8 *r_hash)
3347{
3348 struct dpp_pkex *pkex;
3349 struct wpabuf *msg;
3350 unsigned int wait_time;
3351 size_t len;
3352
3353 if (wpa_s->dpp_pkex) {
3354 wpa_printf(MSG_DEBUG,
3355 "DPP: Sending previously generated PKEX Exchange Request to "
3356 MACSTR, MAC2STR(src));
3357 msg = wpa_s->dpp_pkex->exchange_req;
3358 wait_time = wpa_s->max_remain_on_chan;
3359 if (wait_time > 2000)
3360 wait_time = 2000;
3361 offchannel_send_action(wpa_s, freq, src,
3362 wpa_s->own_addr, broadcast,
3363 wpabuf_head(msg), wpabuf_len(msg),
3364 wait_time, wpas_dpp_tx_pkex_status, 0);
3365 return;
3366 }
3367
3368 wpa_printf(MSG_DEBUG, "DPP: Initiate PKEX for push button with "
3369 MACSTR, MAC2STR(src));
3370
3371 if (!wpa_s->dpp_pb_cmd) {
3372 wpa_printf(MSG_INFO,
3373 "DPP: No configuration to provision as push button Configurator");
3374 wpas_dpp_push_button_stop(wpa_s);
3375 return;
3376 }
3377
3378 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
3379 os_memcpy(wpa_s->dpp_pb_resp_hash, r_hash, SHA256_MAC_LEN);
3380
3381 pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr,
3382 "PBPKEX", (const char *) wpa_s->dpp_pb_c_nonce,
3383 wpa_s->dpp_pb_bi->curve->nonce_len,
3384 true);
3385 if (!pkex) {
3386 wpas_dpp_push_button_stop(wpa_s);
3387 return;
3388 }
3389 pkex->freq = freq;
3390
3391 wpa_s->dpp_pkex = pkex;
3392 msg = wpa_s->dpp_pkex->exchange_req;
3393 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3394 " freq=%u type=%d", MAC2STR(src), freq,
3395 DPP_PA_PKEX_EXCHANGE_REQ);
3396 wait_time = wpa_s->max_remain_on_chan;
3397 if (wait_time > 2000)
3398 wait_time = 2000;
3399 offchannel_send_action(wpa_s, pkex->freq, src,
3400 wpa_s->own_addr, broadcast,
3401 wpabuf_head(msg), wpabuf_len(msg),
3402 wait_time, wpas_dpp_tx_pkex_status, 0);
3403 pkex->exch_req_wait_time = 2000;
3404 pkex->exch_req_tries = 1;
3405
3406 /* Use the externally provided configuration */
3407 os_free(wpa_s->dpp_pkex_auth_cmd);
3408 len = 30 + os_strlen(wpa_s->dpp_pb_cmd);
3409 wpa_s->dpp_pkex_auth_cmd = os_malloc(len);
3410 if (wpa_s->dpp_pkex_auth_cmd)
3411 os_snprintf(wpa_s->dpp_pkex_auth_cmd, len, " own=%d %s",
3412 wpa_s->dpp_pkex_bi->id, wpa_s->dpp_pb_cmd);
3413 else
3414 wpas_dpp_push_button_stop(wpa_s);
3415}
3416
3417
3418static void
3419wpas_dpp_rx_pb_presence_announcement(struct wpa_supplicant *wpa_s,
3420 const u8 *src, const u8 *hdr,
3421 const u8 *buf, size_t len,
3422 unsigned int freq)
3423{
3424 const u8 *r_hash;
3425 u16 r_hash_len;
3426 unsigned int i;
3427 bool found = false;
3428 struct dpp_pb_info *info, *tmp;
3429 struct os_reltime now, age;
3430 struct wpabuf *msg;
3431
3432 os_get_reltime(&now);
3433 wpa_printf(MSG_DEBUG, "DPP: Push Button Presence Announcement from "
3434 MACSTR, MAC2STR(src));
3435
3436 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3437 &r_hash_len);
3438 if (!r_hash || r_hash_len != SHA256_MAC_LEN) {
3439 wpa_printf(MSG_DEBUG,
3440 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
3441 return;
3442 }
3443 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3444 r_hash, r_hash_len);
3445
3446 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3447 info = &wpa_s->dpp_pb[i];
3448 if ((info->rx_time.sec == 0 && info->rx_time.usec == 0) ||
3449 os_memcmp(r_hash, info->hash, SHA256_MAC_LEN) != 0)
3450 continue;
3451 wpa_printf(MSG_DEBUG,
3452 "DPP: Active push button Enrollee already known");
3453 found = true;
3454 info->rx_time = now;
3455 }
3456
3457 if (!found) {
3458 for (i = 0; i < DPP_PB_INFO_COUNT; i++) {
3459 tmp = &wpa_s->dpp_pb[i];
3460 if (tmp->rx_time.sec == 0 && tmp->rx_time.usec == 0)
3461 continue;
3462
3463 if (os_reltime_expired(&now, &tmp->rx_time, 120)) {
3464 wpa_hexdump(MSG_DEBUG,
3465 "DPP: Push button Enrollee hash expired",
3466 tmp->hash, SHA256_MAC_LEN);
3467 tmp->rx_time.sec = 0;
3468 tmp->rx_time.usec = 0;
3469 continue;
3470 }
3471
3472 wpa_hexdump(MSG_DEBUG,
3473 "DPP: Push button session overlap with hash",
3474 tmp->hash, SHA256_MAC_LEN);
3475 if (!wpa_s->dpp_pb_result_indicated &&
3476 wpas_dpp_pb_active(wpa_s)) {
3477 wpa_msg(wpa_s, MSG_INFO,
3478 DPP_EVENT_PB_RESULT "session-overlap");
3479 wpa_s->dpp_pb_result_indicated = true;
3480 }
3481 wpas_dpp_push_button_stop(wpa_s);
3482 return;
3483 }
3484
3485 /* Replace the oldest entry */
3486 info = &wpa_s->dpp_pb[0];
3487 for (i = 1; i < DPP_PB_INFO_COUNT; i++) {
3488 tmp = &wpa_s->dpp_pb[i];
3489 if (os_reltime_before(&tmp->rx_time, &info->rx_time))
3490 info = tmp;
3491 }
3492 wpa_printf(MSG_DEBUG, "DPP: New active push button Enrollee");
3493 os_memcpy(info->hash, r_hash, SHA256_MAC_LEN);
3494 info->rx_time = now;
3495 }
3496
3497 if (!wpas_dpp_pb_active(wpa_s)) {
3498 wpa_printf(MSG_DEBUG,
3499 "DPP: Discard message since own push button has not been pressed");
3500 return;
3501 }
3502
3503 if (wpa_s->dpp_pb_announce_time.sec == 0 &&
3504 wpa_s->dpp_pb_announce_time.usec == 0) {
3505 /* Start a wait before allowing PKEX to be initiated */
3506 wpa_s->dpp_pb_announce_time = now;
3507 }
3508
3509 if (!wpa_s->dpp_pb_bi) {
3510 int res;
3511
3512 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
3513 if (res < 0)
3514 return;
3515 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
3516 if (!wpa_s->dpp_pb_bi)
3517 return;
3518
3519 if (random_get_bytes(wpa_s->dpp_pb_c_nonce,
3520 wpa_s->dpp_pb_bi->curve->nonce_len)) {
3521 wpa_printf(MSG_ERROR,
3522 "DPP: Failed to generate C-nonce");
3523 wpas_dpp_push_button_stop(wpa_s);
3524 return;
3525 }
3526 }
3527
3528 /* Skip the response if one was sent within last 50 ms since the
3529 * Enrollee is going to send out at least three announcement messages.
3530 */
3531 os_reltime_sub(&now, &wpa_s->dpp_pb_last_resp, &age);
3532 if (age.sec == 0 && age.usec < 50000) {
3533 wpa_printf(MSG_DEBUG,
3534 "DPP: Skip Push Button Presence Announcement Response frame immediately after having sent one");
3535 return;
3536 }
3537
3538 msg = dpp_build_pb_announcement_resp(
3539 wpa_s->dpp_pb_bi, r_hash, wpa_s->dpp_pb_c_nonce,
3540 wpa_s->dpp_pb_bi->curve->nonce_len);
3541 if (!msg) {
3542 wpas_dpp_push_button_stop(wpa_s);
3543 return;
3544 }
3545
3546 wpa_printf(MSG_DEBUG,
3547 "DPP: Send Push Button Presence Announcement Response to "
3548 MACSTR, MAC2STR(src));
3549 wpa_s->dpp_pb_last_resp = now;
3550
3551 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3552 MAC2STR(src), freq, DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP);
3553 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
3554 wpabuf_head(msg), wpabuf_len(msg),
3555 0, NULL, 0);
3556 wpabuf_free(msg);
3557
3558 if (os_reltime_expired(&now, &wpa_s->dpp_pb_announce_time, 15))
3559 wpas_dpp_pb_pkex_init(wpa_s, freq, src, r_hash);
3560}
3561
3562
3563static void
3564wpas_dpp_rx_pb_presence_announcement_resp(struct wpa_supplicant *wpa_s,
3565 const u8 *src, const u8 *hdr,
3566 const u8 *buf, size_t len,
3567 unsigned int freq)
3568{
3569 const u8 *i_hash, *r_hash, *c_nonce;
3570 u16 i_hash_len, r_hash_len, c_nonce_len;
3571 bool overlap = false;
3572
3573 if (!wpa_s->dpp_pb_announcement || !wpa_s->dpp_pb_bi ||
3574 wpa_s->dpp_pb_configurator) {
3575 wpa_printf(MSG_INFO,
3576 "DPP: Not in active push button Enrollee mode - discard Push Button Presence Announcement Response from "
3577 MACSTR, MAC2STR(src));
3578 return;
3579 }
3580
3581 wpa_printf(MSG_DEBUG,
3582 "DPP: Push Button Presence Announcement Response from "
3583 MACSTR, MAC2STR(src));
3584
3585 i_hash = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
3586 &i_hash_len);
3587 r_hash = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
3588 &r_hash_len);
3589 c_nonce = dpp_get_attr(buf, len, DPP_ATTR_CONFIGURATOR_NONCE,
3590 &c_nonce_len);
3591 if (!i_hash || i_hash_len != SHA256_MAC_LEN ||
3592 !r_hash || r_hash_len != SHA256_MAC_LEN ||
3593 !c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) {
3594 wpa_printf(MSG_DEBUG,
3595 "DPP: Missing or invalid required attribute");
3596 return;
3597 }
3598 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
3599 i_hash, i_hash_len);
3600 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
3601 r_hash, r_hash_len);
3602 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator Nonce",
3603 c_nonce, c_nonce_len);
3604
3605#ifdef CONFIG_TESTING_OPTIONS
3606 if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_PB_REQ &&
3607 os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3608 SHA256_MAC_LEN - 1) == 0)
3609 goto skip_hash_check;
3610#endif /* CONFIG_TESTING_OPTIONS */
3611 if (os_memcmp(r_hash, wpa_s->dpp_pb_bi->pubkey_hash_chirp,
3612 SHA256_MAC_LEN) != 0) {
3613 wpa_printf(MSG_INFO,
3614 "DPP: Unexpected push button Responder hash - abort");
3615 overlap = true;
3616 }
3617#ifdef CONFIG_TESTING_OPTIONS
3618skip_hash_check:
3619#endif /* CONFIG_TESTING_OPTIONS */
3620
3621 if (wpa_s->dpp_pb_resp_freq &&
3622 os_memcmp(i_hash, wpa_s->dpp_pb_init_hash, SHA256_MAC_LEN) != 0) {
3623 wpa_printf(MSG_INFO,
3624 "DPP: Push button session overlap detected - abort");
3625 overlap = true;
3626 }
3627
3628 if (overlap) {
3629 if (!wpa_s->dpp_pb_result_indicated) {
3630 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
3631 "session-overlap");
3632 wpa_s->dpp_pb_result_indicated = true;
3633 }
3634 wpas_dpp_push_button_stop(wpa_s);
3635 return;
3636 }
3637
3638 if (!wpa_s->dpp_pb_resp_freq) {
3639 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
3640 "discovered push button AP/Configurator " MACSTR,
3641 MAC2STR(src));
3642 wpa_s->dpp_pb_resp_freq = freq;
3643 os_memcpy(wpa_s->dpp_pb_init_hash, i_hash, SHA256_MAC_LEN);
3644 os_memcpy(wpa_s->dpp_pb_c_nonce, c_nonce, c_nonce_len);
3645 wpa_s->dpp_pb_c_nonce_len = c_nonce_len;
3646 /* Stop announcement iterations after at least one more full
3647 * round and one extra round for postponed session overlap
3648 * detection. */
3649 wpa_s->dpp_pb_stop_iter = 3;
3650 }
3651}
3652
3653
3654static void
3655wpas_dpp_tx_priv_intro_status(struct wpa_supplicant *wpa_s,
3656 unsigned int freq, const u8 *dst,
3657 const u8 *src, const u8 *bssid,
3658 const u8 *data, size_t data_len,
3659 enum offchannel_send_action_result result)
3660{
3661 const char *res_txt;
3662
3663 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3664 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3665 "FAILED");
3666 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3667 " result=%s (DPP Private Peer Introduction Update)",
3668 freq, MAC2STR(dst), res_txt);
3669 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3670 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
3671
3672 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR " version=%u",
3673 MAC2STR(src), wpa_s->dpp_intro_peer_version);
3674
3675 wpa_printf(MSG_DEBUG,
3676 "DPP: Try connection again after successful network introduction");
3677 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
3678 wpa_supplicant_cancel_sched_scan(wpa_s);
3679 wpa_supplicant_req_scan(wpa_s, 0, 0);
3680 }
3681}
3682
3683
3684static int
3685wpas_dpp_send_private_peer_intro_update(struct wpa_supplicant *wpa_s,
3686 struct dpp_introduction *intro,
3687 struct wpa_ssid *ssid,
3688 const u8 *dst, unsigned int freq)
3689{
3690 struct wpabuf *pt, *msg, *enc_ct;
3691 size_t len;
3692 u8 ver = DPP_VERSION;
3693 int conn_ver;
3694 const u8 *aad;
3695 size_t aad_len;
3696 unsigned int wait_time;
3697
3698 wpa_printf(MSG_DEBUG, "HPKE(kem_id=%u kdf_id=%u aead_id=%u)",
3699 intro->kem_id, intro->kdf_id, intro->aead_id);
3700
3701 /* Plaintext for HPKE */
3702 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3703 pt = wpabuf_alloc(len);
3704 if (!pt)
3705 return -1;
3706
3707 /* Protocol Version */
3708 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
3709 if (conn_ver > 0 && ver != conn_ver) {
3710 wpa_printf(MSG_DEBUG,
3711 "DPP: Use Connector version %d instead of current protocol version %d",
3712 conn_ver, ver);
3713 ver = conn_ver;
3714 }
3715 wpabuf_put_le16(pt, DPP_ATTR_PROTOCOL_VERSION);
3716 wpabuf_put_le16(pt, 1);
3717 wpabuf_put_u8(pt, ver);
3718
3719 /* Connector */
3720 wpabuf_put_le16(pt, DPP_ATTR_CONNECTOR);
3721 wpabuf_put_le16(pt, os_strlen(ssid->dpp_connector));
3722 wpabuf_put_str(pt, ssid->dpp_connector);
3723 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Plaintext for HPKE", pt);
3724
3725 /* HPKE(pt) using AP's public key (from its Connector) */
3726 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, 0);
3727 if (!msg) {
3728 wpabuf_free(pt);
3729 return -1;
3730 }
3731 aad = wpabuf_head_u8(msg) + 2; /* from the OUI field (inclusive) */
3732 aad_len = DPP_HDR_LEN; /* to the DPP Frame Type field (inclusive) */
3733 wpa_hexdump(MSG_MSGDUMP, "DPP: AAD for HPKE", aad, aad_len);
3734
3735 enc_ct = hpke_base_seal(intro->kem_id, intro->kdf_id, intro->aead_id,
3736 intro->peer_key, NULL, 0, aad, aad_len,
3737 wpabuf_head(pt), wpabuf_len(pt));
3738 wpabuf_free(pt);
3739 wpabuf_free(msg);
3740 if (!enc_ct) {
3741 wpa_printf(MSG_INFO, "DPP: HPKE Seal(Connector) failed");
3742 return -1;
3743 }
3744 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: HPKE enc|ct", enc_ct);
3745
3746 /* HPKE(pt) to generate payload for Wrapped Data */
3747 len = 5 + 4 + wpabuf_len(enc_ct);
3748 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_UPDATE, len);
3749 if (!msg) {
3750 wpabuf_free(enc_ct);
3751 return -1;
3752 }
3753
3754 /* Transaction ID */
3755 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3756 wpabuf_put_le16(msg, 1);
3757 wpabuf_put_u8(msg, TRANSACTION_ID);
3758
3759 /* Wrapped Data */
3760 wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
3761 wpabuf_put_le16(msg, wpabuf_len(enc_ct));
3762 wpabuf_put_buf(msg, enc_ct);
3763 wpabuf_free(enc_ct);
3764
3765 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Update", msg);
3766
3767 /* TODO: Timeout on AP response */
3768 wait_time = wpa_s->max_remain_on_chan;
3769 if (wait_time > 2000)
3770 wait_time = 2000;
3771 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3772 MAC2STR(dst), freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
3773 offchannel_send_action(wpa_s, freq, dst, wpa_s->own_addr, broadcast,
3774 wpabuf_head(msg), wpabuf_len(msg),
3775 wait_time, wpas_dpp_tx_priv_intro_status, 0);
3776 wpabuf_free(msg);
3777
3778 return 0;
3779}
3780
3781
3782static void
3783wpas_dpp_rx_priv_peer_intro_notify(struct wpa_supplicant *wpa_s,
3784 const u8 *src, const u8 *hdr,
3785 const u8 *buf, size_t len,
3786 unsigned int freq)
3787{
3788 struct wpa_ssid *ssid;
3789 const u8 *connector, *trans_id, *version;
3790 u16 connector_len, trans_id_len, version_len;
3791 u8 peer_version = 1;
3792 struct dpp_introduction intro;
3793 struct rsn_pmksa_cache_entry *entry;
3794 struct os_time now;
3795 struct os_reltime rnow;
3796 os_time_t expiry;
3797 unsigned int seconds;
3798 enum dpp_status_error res;
3799
3800 os_memset(&intro, 0, sizeof(intro));
3801
3802 wpa_printf(MSG_DEBUG, "DPP: Private Peer Introduction Notify from "
3803 MACSTR, MAC2STR(src));
3804 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
3805 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
3806 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
3807 MACSTR " - drop", MAC2STR(src));
3808 return;
3809 }
3810 offchannel_send_action_done(wpa_s);
3811
3812 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
3813 if (ssid == wpa_s->dpp_intro_network)
3814 break;
3815 }
3816 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3817 !ssid->dpp_csign) {
3818 wpa_printf(MSG_DEBUG,
3819 "DPP: Profile not found for network introduction");
3820 return;
3821 }
3822
3823 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
3824 &trans_id_len);
3825 if (!trans_id || trans_id_len != 1) {
3826 wpa_printf(MSG_DEBUG,
3827 "DPP: Peer did not include Transaction ID");
3828 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3829 " fail=missing_transaction_id", MAC2STR(src));
3830 goto fail;
3831 }
3832 if (trans_id[0] != TRANSACTION_ID) {
3833 wpa_printf(MSG_DEBUG,
3834 "DPP: Ignore frame with unexpected Transaction ID %u",
3835 trans_id[0]);
3836 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3837 " fail=transaction_id_mismatch", MAC2STR(src));
3838 goto fail;
3839 }
3840
3841 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
3842 if (!connector) {
3843 wpa_printf(MSG_DEBUG,
3844 "DPP: Peer did not include its Connector");
3845 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3846 " fail=missing_connector", MAC2STR(src));
3847 goto fail;
3848 }
3849
3850 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
3851 &version_len);
3852 if (!version || version_len < 1) {
3853 wpa_printf(MSG_DEBUG,
3854 "DPP: Peer did not include valid Version");
3855 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3856 " fail=missing_version", MAC2STR(src));
3857 goto fail;
3858 }
3859
3860 res = dpp_peer_intro(&intro, ssid->dpp_connector,
3861 ssid->dpp_netaccesskey,
3862 ssid->dpp_netaccesskey_len,
3863 ssid->dpp_csign,
3864 ssid->dpp_csign_len,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003865 connector, connector_len, &expiry, NULL);
Sunil Ravi89eba102022-09-13 21:04:37 -07003866 if (res != DPP_STATUS_OK) {
3867 wpa_printf(MSG_INFO,
3868 "DPP: Network Introduction protocol resulted in failure");
3869 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
3870 " fail=peer_connector_validation_failed", MAC2STR(src));
3871 wpas_dpp_send_conn_status_result(wpa_s, res);
3872 goto fail;
3873 }
3874
3875 peer_version = version[0];
3876 if (intro.peer_version && intro.peer_version >= 2 &&
3877 peer_version != intro.peer_version) {
3878 wpa_printf(MSG_INFO,
3879 "DPP: Protocol version mismatch (Connector: %d Attribute: %d",
3880 intro.peer_version, peer_version);
3881 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH);
3882 goto fail;
3883 }
3884 wpa_s->dpp_intro_peer_version = peer_version;
3885
3886 entry = os_zalloc(sizeof(*entry));
3887 if (!entry)
3888 goto fail;
3889 entry->dpp_pfs = peer_version >= 2;
3890 os_memcpy(entry->aa, src, ETH_ALEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003891 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN);
Sunil Ravi89eba102022-09-13 21:04:37 -07003892 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
3893 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
3894 entry->pmk_len = intro.pmk_len;
3895 entry->akmp = WPA_KEY_MGMT_DPP;
3896 if (expiry) {
3897 os_get_time(&now);
3898 seconds = expiry - now.sec;
3899 } else {
3900 seconds = 86400 * 7;
3901 }
3902
3903 if (wpas_dpp_send_private_peer_intro_update(wpa_s, &intro, ssid, src,
3904 freq) < 0) {
3905 os_free(entry);
3906 goto fail;
3907 }
3908
3909 os_get_reltime(&rnow);
3910 entry->expiration = rnow.sec + seconds;
3911 entry->reauth_time = rnow.sec + seconds;
3912 entry->network_ctx = ssid;
3913 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
3914
3915 /* Association will be initiated from TX status handler for the Private
3916 * Peer Intro Update: wpas_dpp_tx_priv_intro_status() */
3917
3918fail:
3919 dpp_peer_intro_deinit(&intro);
3920}
3921
3922#endif /* CONFIG_DPP3 */
3923
3924
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003925void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
3926 const u8 *buf, size_t len, unsigned int freq)
3927{
3928 u8 crypto_suite;
3929 enum dpp_public_action_frame_type type;
3930 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003931 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003932
3933 if (len < DPP_HDR_LEN)
3934 return;
3935 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
3936 return;
3937 hdr = buf;
3938 buf += 4;
3939 len -= 4;
3940 crypto_suite = *buf++;
3941 type = *buf++;
3942 len -= 2;
3943
3944 wpa_printf(MSG_DEBUG,
3945 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
3946 MACSTR " freq=%u",
3947 crypto_suite, type, MAC2STR(src), freq);
Sunil Ravi89eba102022-09-13 21:04:37 -07003948#ifdef CONFIG_TESTING_OPTIONS
3949 if (wpa_s->dpp_discard_public_action &&
3950 type != DPP_PA_PEER_DISCOVERY_RESP &&
3951 type != DPP_PA_PRIV_PEER_INTRO_NOTIFY) {
3952 wpa_printf(MSG_DEBUG,
3953 "TESTING: Discard received DPP Public Action frame");
3954 return;
3955 }
3956#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003957 if (crypto_suite != 1) {
3958 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
3959 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003960 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3961 " freq=%u type=%d ignore=unsupported-crypto-suite",
3962 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003963 return;
3964 }
3965 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003966 if (dpp_check_attrs(buf, len) < 0) {
3967 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
3968 " freq=%u type=%d ignore=invalid-attributes",
3969 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003970 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003971 }
3972 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
3973 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003974
3975 switch (type) {
3976 case DPP_PA_AUTHENTICATION_REQ:
3977 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
3978 break;
3979 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07003980 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003981 break;
3982 case DPP_PA_AUTHENTICATION_CONF:
3983 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
3984 break;
3985 case DPP_PA_PEER_DISCOVERY_RESP:
3986 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
3987 break;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003988#ifdef CONFIG_DPP3
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003989 case DPP_PA_PKEX_EXCHANGE_REQ:
Hai Shaloma20dcd72022-02-04 13:43:00 -08003990 /* This is for PKEXv2, but for now, process only with
3991 * CONFIG_DPP3 to avoid issues with a capability that has not
3992 * been tested with other implementations. */
3993 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true);
3994 break;
3995#endif /* CONFIG_DPP3 */
3996 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
3997 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq,
3998 false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003999 break;
4000 case DPP_PA_PKEX_EXCHANGE_RESP:
4001 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
4002 break;
4003 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
4004 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
4005 freq);
4006 break;
4007 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
4008 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
4009 freq);
4010 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004011#ifdef CONFIG_DPP2
4012 case DPP_PA_CONFIGURATION_RESULT:
4013 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
4014 break;
Hai Shalomc3565922019-10-28 11:58:20 -07004015 case DPP_PA_CONNECTION_STATUS_RESULT:
4016 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
4017 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07004018 case DPP_PA_PRESENCE_ANNOUNCEMENT:
4019 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
4020 freq);
4021 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004022 case DPP_PA_RECONFIG_ANNOUNCEMENT:
4023 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
4024 freq);
4025 break;
4026 case DPP_PA_RECONFIG_AUTH_REQ:
4027 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
4028 break;
4029 case DPP_PA_RECONFIG_AUTH_RESP:
4030 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
4031 break;
4032 case DPP_PA_RECONFIG_AUTH_CONF:
4033 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
4034 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07004035#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07004036#ifdef CONFIG_DPP3
4037 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT:
4038 wpas_dpp_rx_pb_presence_announcement(wpa_s, src, hdr,
4039 buf, len, freq);
4040 break;
4041 case DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP:
4042 wpas_dpp_rx_pb_presence_announcement_resp(wpa_s, src, hdr,
4043 buf, len, freq);
4044 break;
4045 case DPP_PA_PRIV_PEER_INTRO_NOTIFY:
4046 wpas_dpp_rx_priv_peer_intro_notify(wpa_s, src, hdr,
4047 buf, len, freq);
4048 break;
4049#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004050 default:
4051 wpa_printf(MSG_DEBUG,
4052 "DPP: Ignored unsupported frame subtype %d", type);
4053 break;
4054 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004055
4056 if (wpa_s->dpp_pkex)
4057 pkex_t = wpa_s->dpp_pkex->t;
4058 else if (wpa_s->dpp_pkex_bi)
4059 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
4060 else
4061 pkex_t = 0;
4062 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
4063 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
4064 wpas_dpp_pkex_remove(wpa_s, "*");
4065 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004066}
4067
4068
Hai Shaloma20dcd72022-02-04 13:43:00 -08004069static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx,
4070 void *timeout_ctx)
4071{
4072 struct wpa_supplicant *wpa_s = eloop_ctx;
4073 struct dpp_authentication *auth = wpa_s->dpp_auth;
4074
4075 if (!auth || !auth->waiting_config || !auth->config_resp_ctx)
4076 return;
4077
4078 wpa_printf(MSG_DEBUG,
4079 "DPP: No configuration available from upper layers - send initial response with comeback delay");
4080 gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx,
4081 500);
4082}
4083
4084
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004085static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07004086wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
Hai Shaloma20dcd72022-02-04 13:43:00 -08004087 const u8 *query, size_t query_len, int *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004088{
4089 struct wpa_supplicant *wpa_s = ctx;
4090 struct dpp_authentication *auth = wpa_s->dpp_auth;
4091 struct wpabuf *resp;
4092
4093 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
4094 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004095 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004096 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
4097 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
4098 return NULL;
4099 }
Hai Shalomc3565922019-10-28 11:58:20 -07004100
4101 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
4102 wpa_printf(MSG_DEBUG,
4103 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
4104 /* wpas_dpp_auth_success() would normally have been called from
4105 * TX status handler, but since there was no such handler call
4106 * yet, simply send out the event message and proceed with
4107 * exchange. */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004108 dpp_notify_auth_success(auth, 1);
Hai Shalomc3565922019-10-28 11:58:20 -07004109 wpa_s->dpp_auth_ok_on_ack = 0;
4110 }
4111
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004112 wpa_hexdump(MSG_DEBUG,
4113 "DPP: Received Configuration Request (GAS Query Request)",
4114 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004115 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
4116 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004117 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004118
Hai Shaloma20dcd72022-02-04 13:43:00 -08004119 auth->gas_server_ctx = resp_ctx;
4120
Hai Shalom899fcc72020-10-19 14:38:18 -07004121#ifdef CONFIG_DPP2
4122 if (!resp && auth->waiting_cert) {
4123 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
Hai Shaloma20dcd72022-02-04 13:43:00 -08004124 auth->config_resp_ctx = resp_ctx;
Hai Shalom899fcc72020-10-19 14:38:18 -07004125 *comeback_delay = 500;
4126 return NULL;
4127 }
4128#endif /* CONFIG_DPP2 */
4129
Hai Shaloma20dcd72022-02-04 13:43:00 -08004130 if (!resp && auth->waiting_config &&
4131 (auth->peer_bi || auth->tmp_peer_bi)) {
4132 char *buf = NULL, *name = "";
4133 char band[200], *pos, *end;
4134 int i, res, *opclass = auth->e_band_support;
4135 char *mud_url = "N/A";
4136
4137 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
4138 auth->config_resp_ctx = resp_ctx;
4139 *comeback_delay = -1;
4140 if (auth->e_name) {
4141 size_t len = os_strlen(auth->e_name);
4142
4143 buf = os_malloc(len * 4 + 1);
4144 if (buf) {
4145 printf_encode(buf, len * 4 + 1,
4146 (const u8 *) auth->e_name, len);
4147 name = buf;
4148 }
4149 }
4150 band[0] = '\0';
4151 pos = band;
4152 end = band + sizeof(band);
4153 for (i = 0; opclass && opclass[i]; i++) {
4154 res = os_snprintf(pos, end - pos, "%s%d",
4155 pos == band ? "" : ",", opclass[i]);
4156 if (os_snprintf_error(end - pos, res)) {
4157 *pos = '\0';
4158 break;
4159 }
4160 pos += res;
4161 }
4162 if (auth->e_mud_url) {
4163 size_t len = os_strlen(auth->e_mud_url);
4164
4165 if (!has_ctrl_char((const u8 *) auth->e_mud_url, len))
4166 mud_url = auth->e_mud_url;
4167 }
4168 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src="
4169 MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s",
4170 auth->peer_bi ? auth->peer_bi->id :
4171 auth->tmp_peer_bi->id, MAC2STR(sa),
4172 dpp_netrole_str(auth->e_netrole), name, band, mud_url);
4173 os_free(buf);
4174
4175 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4176 NULL);
4177 eloop_register_timeout(0, 50000,
4178 wpas_dpp_gas_initial_resp_timeout, wpa_s,
4179 NULL);
4180 return NULL;
4181 }
4182
Sunil Ravia04bd252022-05-02 22:54:18 -07004183 auth->conf_resp = resp;
Hai Shalom59532852018-12-07 10:32:58 -08004184 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004185 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004186 wpas_notify_dpp_configuration_failure(wpa_s);
Sunil Ravia04bd252022-05-02 22:54:18 -07004187 dpp_auth_deinit(wpa_s->dpp_auth);
4188 wpa_s->dpp_auth = NULL;
Hai Shalom59532852018-12-07 10:32:58 -08004189 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004190 return resp;
4191}
4192
4193
4194static void
4195wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
4196{
4197 struct wpa_supplicant *wpa_s = ctx;
4198 struct dpp_authentication *auth = wpa_s->dpp_auth;
4199
4200 if (!auth) {
4201 wpabuf_free(resp);
4202 return;
4203 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004204 if (auth->conf_resp != resp) {
4205 wpa_printf(MSG_DEBUG,
4206 "DPP: Ignore GAS status report (ok=%d) for unknown response",
4207 ok);
4208 wpabuf_free(resp);
4209 return;
4210 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004211
Hai Shalom899fcc72020-10-19 14:38:18 -07004212#ifdef CONFIG_DPP2
4213 if (auth->waiting_csr && ok) {
4214 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
4215 wpabuf_free(resp);
4216 return;
4217 }
4218#endif /* CONFIG_DPP2 */
4219
Sunil Ravia04bd252022-05-02 22:54:18 -07004220#ifdef CONFIG_DPP3
4221 if (auth->waiting_new_key && ok) {
4222 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
4223 wpabuf_free(resp);
4224 return;
4225 }
4226#endif /* CONFIG_DPP3 */
4227
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004228 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
4229 ok);
4230 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004231 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004232 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004233#ifdef CONFIG_DPP2
4234 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08004235 auth->conf_resp_status == DPP_STATUS_OK &&
4236 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07004237 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08004238 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07004239 auth->waiting_conf_result = 1;
4240 auth->conf_resp = NULL;
4241 wpabuf_free(resp);
4242 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
4243 wpa_s, NULL);
4244 eloop_register_timeout(2, 0,
4245 wpas_dpp_config_result_wait_timeout,
4246 wpa_s, NULL);
4247 return;
4248 }
4249#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004250 offchannel_send_action_done(wpa_s);
4251 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004252 if (ok) {
Sunil Ravi89eba102022-09-13 21:04:37 -07004253 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
4254 auth->conf_resp_status);
Hai Shalom706f99b2019-01-08 16:23:37 -08004255 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004256 }
4257 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004258 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08004259 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08004260 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004261 dpp_auth_deinit(wpa_s->dpp_auth);
4262 wpa_s->dpp_auth = NULL;
4263 wpabuf_free(resp);
Sunil Ravi89eba102022-09-13 21:04:37 -07004264#ifdef CONFIG_DPP3
4265 if (!wpa_s->dpp_pb_result_indicated && wpas_dpp_pb_active(wpa_s)) {
4266 if (ok)
4267 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4268 "success");
4269 else
4270 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT
4271 "could-not-connect");
4272 wpa_s->dpp_pb_result_indicated = true;
4273 if (ok)
4274 wpas_dpp_remove_pb_hash(wpa_s);
4275 wpas_dpp_push_button_stop(wpa_s);
4276 }
4277#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004278}
4279
4280
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004281int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
4282{
4283 struct dpp_authentication *auth;
4284 int ret = -1;
4285 char *curve = NULL;
4286
Hai Shalomfdcde762020-04-02 11:19:20 -07004287 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004288 if (!auth)
4289 return -1;
4290
4291 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08004292 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07004293 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07004294 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07004295 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
4296 &auth->conf_obj[0]);
4297 if (!ret)
4298 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004299
4300 dpp_auth_deinit(auth);
4301 os_free(curve);
4302
4303 return ret;
4304}
4305
4306
4307static void
4308wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
4309 unsigned int freq, const u8 *dst,
4310 const u8 *src, const u8 *bssid,
4311 const u8 *data, size_t data_len,
4312 enum offchannel_send_action_result result)
4313{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004314 const char *res_txt;
4315
4316 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
4317 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
4318 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004319 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
4320 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07004321 freq, MAC2STR(dst), res_txt);
4322 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
4323 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004324 /* TODO: Time out wait for response more quickly in error cases? */
4325}
4326
4327
Sunil Ravi89eba102022-09-13 21:04:37 -07004328#ifdef CONFIG_DPP3
4329static int wpas_dpp_start_private_peer_intro(struct wpa_supplicant *wpa_s,
4330 struct wpa_ssid *ssid,
4331 struct wpa_bss *bss)
4332{
4333 struct wpabuf *msg;
4334 unsigned int wait_time;
4335 size_t len;
4336 u8 ver = DPP_VERSION;
4337 int conn_ver;
4338
4339 len = 5 + 5;
4340 msg = dpp_alloc_msg(DPP_PA_PRIV_PEER_INTRO_QUERY, len);
4341 if (!msg)
4342 return -1;
4343
4344 /* Transaction ID */
4345 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4346 wpabuf_put_le16(msg, 1);
4347 wpabuf_put_u8(msg, TRANSACTION_ID);
4348
4349 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4350 if (conn_ver > 0 && ver != conn_ver) {
4351 wpa_printf(MSG_DEBUG,
4352 "DPP: Use Connector version %d instead of current protocol version %d",
4353 conn_ver, ver);
4354 ver = conn_ver;
4355 }
4356
4357 /* Protocol Version */
4358 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4359 wpabuf_put_le16(msg, 1);
4360 wpabuf_put_u8(msg, ver);
4361
4362 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Private Peer Intro Query", msg);
4363
4364 /* TODO: Timeout on AP response */
4365 wait_time = wpa_s->max_remain_on_chan;
4366 if (wait_time > 2000)
4367 wait_time = 2000;
4368 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4369 MAC2STR(bss->bssid), bss->freq, DPP_PA_PRIV_PEER_INTRO_QUERY);
4370 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4371 broadcast,
4372 wpabuf_head(msg), wpabuf_len(msg),
4373 wait_time, wpas_dpp_tx_introduction_status, 0);
4374 wpabuf_free(msg);
4375
4376 /* Request this connection attempt to terminate - new one will be
4377 * started when network introduction protocol completes */
4378 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4379 wpa_s->dpp_intro_network = ssid;
4380 return 1;
4381}
4382#endif /* CONFIG_DPP3 */
4383
4384
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004385int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
4386 struct wpa_bss *bss)
4387{
4388 struct os_time now;
4389 struct wpabuf *msg;
4390 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07004391 const u8 *rsn;
4392 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004393 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004394
4395 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
4396 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07004397 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4398 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
4399 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
4400 return 0; /* AP does not support DPP AKM - continue */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004401 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, wpa_s->own_addr, ssid))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004402 return 0; /* PMKSA exists for DPP AKM - continue */
4403
4404 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
4405 !ssid->dpp_csign) {
4406 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4407 "missing %s",
4408 !ssid->dpp_connector ? "Connector" :
4409 (!ssid->dpp_netaccesskey ? "netAccessKey" :
4410 "C-sign-key"));
4411 return -1;
4412 }
4413
4414 os_get_time(&now);
4415
4416 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07004417 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004418 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
4419 "netAccessKey expired");
4420 return -1;
4421 }
4422
4423 wpa_printf(MSG_DEBUG,
Sunil Ravi89eba102022-09-13 21:04:37 -07004424 "DPP: Starting %snetwork introduction protocol to derive PMKSA for "
4425 MACSTR,
4426 ssid->dpp_connector_privacy ? "private " : "",
4427 MAC2STR(bss->bssid));
Sunil Ravia04bd252022-05-02 22:54:18 -07004428 if (wpa_s->wpa_state == WPA_SCANNING)
4429 wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004430
Sunil Ravi89eba102022-09-13 21:04:37 -07004431#ifdef CONFIG_DPP3
4432 if (ssid->dpp_connector_privacy)
4433 return wpas_dpp_start_private_peer_intro(wpa_s, ssid, bss);
4434#endif /* CONFIG_DPP3 */
4435
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004436 len = 5 + 4 + os_strlen(ssid->dpp_connector);
4437#ifdef CONFIG_DPP2
4438 len += 5;
4439#endif /* CONFIG_DPP2 */
4440 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004441 if (!msg)
4442 return -1;
4443
Roshan Pius3a1667e2018-07-03 15:17:14 -07004444#ifdef CONFIG_TESTING_OPTIONS
4445 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
4446 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
4447 goto skip_trans_id;
4448 }
4449 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
4450 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
4451 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4452 wpabuf_put_le16(msg, 0);
4453 goto skip_trans_id;
4454 }
4455#endif /* CONFIG_TESTING_OPTIONS */
4456
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004457 /* Transaction ID */
4458 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
4459 wpabuf_put_le16(msg, 1);
4460 wpabuf_put_u8(msg, TRANSACTION_ID);
4461
Roshan Pius3a1667e2018-07-03 15:17:14 -07004462#ifdef CONFIG_TESTING_OPTIONS
4463skip_trans_id:
4464 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
4465 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
4466 goto skip_connector;
4467 }
4468 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
4469 char *connector;
4470
4471 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
4472 connector = dpp_corrupt_connector_signature(
4473 ssid->dpp_connector);
4474 if (!connector) {
4475 wpabuf_free(msg);
4476 return -1;
4477 }
4478 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4479 wpabuf_put_le16(msg, os_strlen(connector));
4480 wpabuf_put_str(msg, connector);
4481 os_free(connector);
4482 goto skip_connector;
4483 }
4484#endif /* CONFIG_TESTING_OPTIONS */
4485
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004486 /* DPP Connector */
4487 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
4488 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
4489 wpabuf_put_str(msg, ssid->dpp_connector);
4490
Roshan Pius3a1667e2018-07-03 15:17:14 -07004491#ifdef CONFIG_TESTING_OPTIONS
4492skip_connector:
Hai Shaloma20dcd72022-02-04 13:43:00 -08004493 if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) {
4494 wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version");
4495 goto skip_proto_ver;
4496 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07004497#endif /* CONFIG_TESTING_OPTIONS */
4498
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004499#ifdef CONFIG_DPP2
4500 if (DPP_VERSION > 1) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004501 u8 ver = DPP_VERSION;
4502#ifdef CONFIG_DPP3
4503 int conn_ver;
4504
4505 conn_ver = dpp_get_connector_version(ssid->dpp_connector);
4506 if (conn_ver > 0 && ver != conn_ver) {
4507 wpa_printf(MSG_DEBUG,
4508 "DPP: Use Connector version %d instead of current protocol version %d",
4509 conn_ver, ver);
4510 ver = conn_ver;
4511 }
4512#endif /* CONFIG_DPP3 */
4513
4514#ifdef CONFIG_TESTING_OPTIONS
4515 if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) {
4516 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version");
4517 ver = 1;
4518 }
4519#endif /* CONFIG_TESTING_OPTIONS */
4520
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004521 /* Protocol Version */
4522 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
4523 wpabuf_put_le16(msg, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004524 wpabuf_put_u8(msg, ver);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004525 }
4526#endif /* CONFIG_DPP2 */
4527
Hai Shaloma20dcd72022-02-04 13:43:00 -08004528#ifdef CONFIG_TESTING_OPTIONS
4529skip_proto_ver:
4530#endif /* CONFIG_TESTING_OPTIONS */
4531
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004532 /* TODO: Timeout on AP response */
4533 wait_time = wpa_s->max_remain_on_chan;
4534 if (wait_time > 2000)
4535 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004536 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
4537 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004538 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
4539 broadcast,
4540 wpabuf_head(msg), wpabuf_len(msg),
4541 wait_time, wpas_dpp_tx_introduction_status, 0);
4542 wpabuf_free(msg);
4543
4544 /* Request this connection attempt to terminate - new one will be
4545 * started when network introduction protocol completes */
4546 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
4547 wpa_s->dpp_intro_network = ssid;
4548 return 1;
4549}
4550
4551
4552int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
4553{
4554 struct dpp_bootstrap_info *own_bi;
4555 const char *pos, *end;
Sunil Ravia04bd252022-05-02 22:54:18 -07004556#ifdef CONFIG_DPP3
4557 enum dpp_pkex_ver ver = PKEX_VER_AUTO;
4558#else /* CONFIG_DPP3 */
4559 enum dpp_pkex_ver ver = PKEX_VER_ONLY_1;
4560#endif /* CONFIG_DPP3 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004561 int tcp_port = DPP_TCP_PORT;
4562 struct hostapd_ip_addr *ipaddr = NULL;
4563#ifdef CONFIG_DPP2
4564 struct hostapd_ip_addr ipaddr_buf;
4565 char *addr;
4566
4567 pos = os_strstr(cmd, " tcp_port=");
4568 if (pos) {
4569 pos += 10;
4570 tcp_port = atoi(pos);
4571 }
4572
4573 addr = get_param(cmd, " tcp_addr=");
4574 if (addr) {
4575 int res;
4576
4577 res = hostapd_parse_ip_addr(addr, &ipaddr_buf);
4578 os_free(addr);
4579 if (res)
4580 return -1;
4581 ipaddr = &ipaddr_buf;
4582 }
4583#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004584
4585 pos = os_strstr(cmd, " own=");
4586 if (!pos)
4587 return -1;
4588 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07004589 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004590 if (!own_bi) {
4591 wpa_printf(MSG_DEBUG,
4592 "DPP: Identified bootstrap info not found");
4593 return -1;
4594 }
4595 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
4596 wpa_printf(MSG_DEBUG,
4597 "DPP: Identified bootstrap info not for PKEX");
4598 return -1;
4599 }
4600 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004601 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004602
4603 os_free(wpa_s->dpp_pkex_identifier);
4604 wpa_s->dpp_pkex_identifier = NULL;
4605 pos = os_strstr(cmd, " identifier=");
4606 if (pos) {
4607 pos += 12;
4608 end = os_strchr(pos, ' ');
4609 if (!end)
4610 return -1;
4611 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
4612 if (!wpa_s->dpp_pkex_identifier)
4613 return -1;
4614 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
4615 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
4616 }
4617
4618 pos = os_strstr(cmd, " code=");
4619 if (!pos)
4620 return -1;
4621 os_free(wpa_s->dpp_pkex_code);
4622 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
4623 if (!wpa_s->dpp_pkex_code)
4624 return -1;
Sunil Ravi89eba102022-09-13 21:04:37 -07004625 wpa_s->dpp_pkex_code_len = os_strlen(wpa_s->dpp_pkex_code);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004626
Sunil Ravia04bd252022-05-02 22:54:18 -07004627 pos = os_strstr(cmd, " ver=");
4628 if (pos) {
4629 int v;
4630
4631 pos += 5;
4632 v = atoi(pos);
4633 if (v == 1)
4634 ver = PKEX_VER_ONLY_1;
4635 else if (v == 2)
4636 ver = PKEX_VER_ONLY_2;
4637 else
4638 return -1;
4639 }
4640 wpa_s->dpp_pkex_ver = ver;
4641
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004642 if (os_strstr(cmd, " init=1")) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08004643 if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004644 return -1;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004645 } else {
4646#ifdef CONFIG_DPP2
4647 dpp_controller_pkex_add(wpa_s->dpp, own_bi,
4648 wpa_s->dpp_pkex_code,
4649 wpa_s->dpp_pkex_identifier);
4650#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004651 }
4652
4653 /* TODO: Support multiple PKEX info entries */
4654
4655 os_free(wpa_s->dpp_pkex_auth_cmd);
4656 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
4657
4658 return 1;
4659}
4660
4661
4662int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
4663{
4664 unsigned int id_val;
4665
4666 if (os_strcmp(id, "*") == 0) {
4667 id_val = 0;
4668 } else {
4669 id_val = atoi(id);
4670 if (id_val == 0)
4671 return -1;
4672 }
4673
Sunil Ravi89eba102022-09-13 21:04:37 -07004674 if ((id_val != 0 && id_val != 1))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004675 return -1;
4676
4677 /* TODO: Support multiple PKEX entries */
4678 os_free(wpa_s->dpp_pkex_code);
4679 wpa_s->dpp_pkex_code = NULL;
4680 os_free(wpa_s->dpp_pkex_identifier);
4681 wpa_s->dpp_pkex_identifier = NULL;
4682 os_free(wpa_s->dpp_pkex_auth_cmd);
4683 wpa_s->dpp_pkex_auth_cmd = NULL;
4684 wpa_s->dpp_pkex_bi = NULL;
4685 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
4686 dpp_pkex_free(wpa_s->dpp_pkex);
4687 wpa_s->dpp_pkex = NULL;
4688 return 0;
4689}
4690
4691
Roshan Pius3a1667e2018-07-03 15:17:14 -07004692void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
4693{
Sunil Ravia04bd252022-05-02 22:54:18 -07004694 if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req)
Hai Shalomfdcde762020-04-02 11:19:20 -07004695 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004696 dpp_auth_deinit(wpa_s->dpp_auth);
4697 wpa_s->dpp_auth = NULL;
4698 dpp_pkex_free(wpa_s->dpp_pkex);
4699 wpa_s->dpp_pkex = NULL;
Sunil Ravia04bd252022-05-02 22:54:18 -07004700 wpa_s->dpp_pkex_wait_auth_req = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004701 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
4702 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
Sunil Ravi89eba102022-09-13 21:04:37 -07004703#ifdef CONFIG_DPP3
4704 wpas_dpp_push_button_stop(wpa_s);
4705#endif /* CONFIG_DPP3 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004706}
4707
4708
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004709int wpas_dpp_init(struct wpa_supplicant *wpa_s)
4710{
Hai Shalom81f62d82019-07-22 12:10:00 -07004711 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004712 u8 adv_proto_id[7];
4713
4714 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
4715 adv_proto_id[1] = 5;
4716 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
4717 adv_proto_id[5] = DPP_OUI_TYPE;
4718 adv_proto_id[6] = 0x01;
4719
4720 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
4721 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
4722 wpas_dpp_gas_status_handler, wpa_s) < 0)
4723 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07004724
4725 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07004726 config.cb_ctx = wpa_s;
4727#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004728 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07004729#endif /* CONFIG_DPP2 */
4730 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07004731 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004732}
4733
4734
4735void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
4736{
4737#ifdef CONFIG_TESTING_OPTIONS
4738 os_free(wpa_s->dpp_config_obj_override);
4739 wpa_s->dpp_config_obj_override = NULL;
4740 os_free(wpa_s->dpp_discovery_override);
4741 wpa_s->dpp_discovery_override = NULL;
4742 os_free(wpa_s->dpp_groups_override);
4743 wpa_s->dpp_groups_override = NULL;
4744 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
4745#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07004746 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004747 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004748 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004749 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08004750 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004751 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
4752 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08004753 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4754 eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004755#ifdef CONFIG_DPP2
4756 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07004757 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
4758 wpa_s, NULL);
4759 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004760 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
4761 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07004762 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07004763 dpp_pfs_free(wpa_s->dpp_pfs);
4764 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004765 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004766 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
4767 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07004768#endif /* CONFIG_DPP2 */
Sunil Ravia04bd252022-05-02 22:54:18 -07004769#ifdef CONFIG_DPP3
4770 eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
4771#endif /* CONFIG_DPP3 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004772 offchannel_send_action_done(wpa_s);
4773 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07004774 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004775 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004776 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
4777 os_free(wpa_s->dpp_configurator_params);
4778 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07004779 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004780}
Hai Shalom81f62d82019-07-22 12:10:00 -07004781
4782
Hai Shaloma20dcd72022-02-04 13:43:00 -08004783static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
4784 struct dpp_authentication *auth, bool tcp)
4785{
4786 struct wpabuf *resp;
4787
4788 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
4789 auth->e_netrole, true);
4790 if (!resp)
4791 return -1;
4792
4793 if (tcp) {
4794 auth->conf_resp_tcp = resp;
4795 return 0;
4796 }
4797
4798 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL);
4799 if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx,
4800 resp) < 0) {
4801 wpa_printf(MSG_DEBUG,
4802 "DPP: Could not find pending GAS response");
4803 wpabuf_free(resp);
4804 return -1;
4805 }
4806 auth->conf_resp = resp;
4807 return 0;
4808}
4809
4810
4811int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd)
4812{
4813 int peer;
4814 const char *pos;
4815 struct dpp_authentication *auth = wpa_s->dpp_auth;
4816 bool tcp = false;
4817
4818 pos = os_strstr(cmd, " peer=");
4819 if (!pos)
4820 return -1;
4821 peer = atoi(pos + 6);
4822#ifdef CONFIG_DPP2
4823 if (!auth || !auth->waiting_config ||
4824 (auth->peer_bi &&
4825 (unsigned int) peer != auth->peer_bi->id)) {
4826 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
4827 tcp = true;
4828 }
4829#endif /* CONFIG_DPP2 */
4830
4831 if (!auth || !auth->waiting_config) {
4832 wpa_printf(MSG_DEBUG,
4833 "DPP: No authentication exchange waiting for configuration information");
4834 return -1;
4835 }
4836
4837 if ((!auth->peer_bi ||
4838 (unsigned int) peer != auth->peer_bi->id) &&
4839 (!auth->tmp_peer_bi ||
4840 (unsigned int) peer != auth->tmp_peer_bi->id)) {
4841 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
4842 return -1;
4843 }
4844
4845 pos = os_strstr(cmd, " comeback=");
4846 if (pos) {
4847 eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s,
4848 NULL);
4849 gas_server_set_comeback_delay(wpa_s->gas_server,
4850 auth->config_resp_ctx,
4851 atoi(pos + 10));
4852 return 0;
4853 }
4854
4855 if (dpp_set_configurator(auth, cmd) < 0)
4856 return -1;
4857
4858 auth->use_config_query = false;
4859 auth->waiting_config = false;
4860 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
4861}
4862
4863
Hai Shalom81f62d82019-07-22 12:10:00 -07004864#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07004865
Hai Shalom81f62d82019-07-22 12:10:00 -07004866int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
4867{
4868 struct dpp_controller_config config;
4869 const char *pos;
4870
4871 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004872 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07004873 config.netrole = DPP_NETROLE_STA;
4874 config.msg_ctx = wpa_s;
4875 config.cb_ctx = wpa_s;
4876 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004877 config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
Hai Shalom81f62d82019-07-22 12:10:00 -07004878 if (cmd) {
4879 pos = os_strstr(cmd, " tcp_port=");
4880 if (pos) {
4881 pos += 10;
4882 config.tcp_port = atoi(pos);
4883 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004884
4885 pos = os_strstr(cmd, " role=");
4886 if (pos) {
4887 pos += 6;
4888 if (os_strncmp(pos, "configurator", 12) == 0)
4889 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
4890 else if (os_strncmp(pos, "enrollee", 8) == 0)
4891 config.allowed_roles = DPP_CAPAB_ENROLLEE;
4892 else if (os_strncmp(pos, "either", 6) == 0)
4893 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
4894 DPP_CAPAB_ENROLLEE;
4895 else
4896 return -1;
4897 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004898
4899 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07004900 }
4901 config.configurator_params = wpa_s->dpp_configurator_params;
4902 return dpp_controller_start(wpa_s->dpp, &config);
4903}
Hai Shalomfdcde762020-04-02 11:19:20 -07004904
4905
4906static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
4907
4908static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
4909{
4910 struct wpa_supplicant *wpa_s = eloop_ctx;
4911
4912 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
4913 offchannel_send_action_done(wpa_s);
4914 wpas_dpp_chirp_next(wpa_s, NULL);
4915}
4916
4917
4918static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
4919 unsigned int freq, const u8 *dst,
4920 const u8 *src, const u8 *bssid,
4921 const u8 *data, size_t data_len,
4922 enum offchannel_send_action_result result)
4923{
4924 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
4925 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
4926 wpa_s->dpp_chirp_freq);
4927 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
4928 wpa_s, NULL) < 0)
4929 wpas_dpp_chirp_stop(wpa_s);
4930 return;
4931 }
4932
4933 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
4934 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
4935 wpa_s, NULL) < 0)
4936 wpas_dpp_chirp_stop(wpa_s);
4937}
4938
4939
4940static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
4941{
Hai Shalom899fcc72020-10-19 14:38:18 -07004942 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004943 int type;
4944
4945 msg = wpa_s->dpp_presence_announcement;
4946 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
4947 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07004948 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
4949
4950 if (ssid && wpa_s->dpp_reconfig_id &&
4951 wpa_config_get_network(wpa_s->conf,
4952 wpa_s->dpp_reconfig_ssid_id) ==
4953 ssid) {
4954 announce = dpp_build_reconfig_announcement(
4955 ssid->dpp_csign,
4956 ssid->dpp_csign_len,
4957 ssid->dpp_netaccesskey,
4958 ssid->dpp_netaccesskey_len,
4959 wpa_s->dpp_reconfig_id);
4960 msg = announce;
4961 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004962 if (!msg)
4963 return;
4964 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
4965 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004966 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
4967 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004968 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07004969 if (offchannel_send_action(
4970 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
4971 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004972 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07004973 2000, wpas_dpp_chirp_tx_status, 0) < 0)
4974 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07004975
4976 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07004977}
4978
4979
Sunil Ravi89eba102022-09-13 21:04:37 -07004980static int * wpas_dpp_presence_ann_channels(struct wpa_supplicant *wpa_s,
4981 struct dpp_bootstrap_info *bi)
Hai Shalomfdcde762020-04-02 11:19:20 -07004982{
Hai Shalomfdcde762020-04-02 11:19:20 -07004983 unsigned int i;
4984 struct hostapd_hw_modes *mode;
4985 int c;
4986 struct wpa_bss *bss;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004987 bool chan6 = wpa_s->hw.modes == NULL;
Sunil Ravi89eba102022-09-13 21:04:37 -07004988 int *freqs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004989
4990 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004991 if (bi) {
4992 for (i = 0; i < bi->num_freq; i++)
Sunil Ravi89eba102022-09-13 21:04:37 -07004993 int_array_add_unique(&freqs, bi->freq[i]);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004994 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004995
4996 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07004997 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08004998 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07004999 if (mode) {
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 chan->freq != 2437)
5005 continue;
5006 chan6 = true;
5007 break;
5008 }
5009 }
5010 if (chan6)
Sunil Ravi89eba102022-09-13 21:04:37 -07005011 int_array_add_unique(&freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07005012
5013 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005014 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005015 if (mode) {
5016 int chan44 = 0, chan149 = 0;
5017
5018 for (c = 0; c < mode->num_channels; c++) {
5019 struct hostapd_channel_data *chan = &mode->channels[c];
5020
5021 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
5022 HOSTAPD_CHAN_RADAR))
5023 continue;
5024 if (chan->freq == 5220)
5025 chan44 = 1;
5026 if (chan->freq == 5745)
5027 chan149 = 1;
5028 }
5029 if (chan149)
Sunil Ravi89eba102022-09-13 21:04:37 -07005030 int_array_add_unique(&freqs, 5745);
Hai Shalomfdcde762020-04-02 11:19:20 -07005031 else if (chan44)
Sunil Ravi89eba102022-09-13 21:04:37 -07005032 int_array_add_unique(&freqs, 5220);
Hai Shalomfdcde762020-04-02 11:19:20 -07005033 }
5034
5035 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08005036 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07005037 if (mode) {
5038 for (c = 0; c < mode->num_channels; c++) {
5039 struct hostapd_channel_data *chan = &mode->channels[c];
5040
5041 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
5042 HOSTAPD_CHAN_RADAR)) ||
5043 chan->freq != 60480)
5044 continue;
Sunil Ravi89eba102022-09-13 21:04:37 -07005045 int_array_add_unique(&freqs, 60480);
Hai Shalomfdcde762020-04-02 11:19:20 -07005046 break;
5047 }
5048 }
5049
5050 /* Add channels from scan results for APs that advertise Configurator
5051 * Connectivity element */
5052 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
5053 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
Sunil Ravi89eba102022-09-13 21:04:37 -07005054 int_array_add_unique(&freqs, bss->freq);
Hai Shalomfdcde762020-04-02 11:19:20 -07005055 }
5056
Sunil Ravi89eba102022-09-13 21:04:37 -07005057 return freqs;
5058}
5059
5060
5061static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
5062 struct wpa_scan_results *scan_res)
5063{
5064 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
5065
5066 if (!bi && !wpa_s->dpp_reconfig_ssid)
5067 return;
5068
5069 wpa_s->dpp_chirp_scan_done = 1;
5070
5071 os_free(wpa_s->dpp_chirp_freqs);
5072 wpa_s->dpp_chirp_freqs = wpas_dpp_presence_ann_channels(wpa_s, bi);
5073
Hai Shalomfdcde762020-04-02 11:19:20 -07005074 if (!wpa_s->dpp_chirp_freqs ||
5075 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
5076 wpas_dpp_chirp_stop(wpa_s);
5077}
5078
5079
5080static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
5081{
5082 struct wpa_supplicant *wpa_s = eloop_ctx;
5083 int i;
5084
5085 if (wpa_s->dpp_chirp_listen)
5086 wpas_dpp_listen_stop(wpa_s);
5087
5088 if (wpa_s->dpp_chirp_freq == 0) {
5089 if (wpa_s->dpp_chirp_round % 4 == 0 &&
5090 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08005091 if (wpas_scan_scheduled(wpa_s)) {
5092 wpa_printf(MSG_DEBUG,
5093 "DPP: Deferring chirp scan because another scan is planned already");
5094 if (eloop_register_timeout(1, 0,
5095 wpas_dpp_chirp_next,
5096 wpa_s, NULL) < 0) {
5097 wpas_dpp_chirp_stop(wpa_s);
5098 return;
5099 }
5100 return;
5101 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005102 wpa_printf(MSG_DEBUG,
5103 "DPP: Update channel list for chirping");
5104 wpa_s->scan_req = MANUAL_SCAN_REQ;
5105 wpa_s->scan_res_handler =
5106 wpas_dpp_chirp_scan_res_handler;
5107 wpa_supplicant_req_scan(wpa_s, 0, 0);
5108 return;
5109 }
5110 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
5111 wpa_s->dpp_chirp_round++;
5112 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
5113 wpa_s->dpp_chirp_round);
5114 } else {
5115 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
5116 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
5117 break;
5118 if (!wpa_s->dpp_chirp_freqs[i]) {
5119 wpa_printf(MSG_DEBUG,
5120 "DPP: Previous chirp freq %d not found",
5121 wpa_s->dpp_chirp_freq);
5122 return;
5123 }
5124 i++;
5125 if (wpa_s->dpp_chirp_freqs[i]) {
5126 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
5127 } else {
5128 wpa_s->dpp_chirp_iter--;
5129 if (wpa_s->dpp_chirp_iter <= 0) {
5130 wpa_printf(MSG_DEBUG,
5131 "DPP: Chirping iterations completed");
5132 wpas_dpp_chirp_stop(wpa_s);
5133 return;
5134 }
5135 wpa_s->dpp_chirp_freq = 0;
5136 wpa_s->dpp_chirp_scan_done = 0;
5137 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
5138 wpa_s, NULL) < 0) {
5139 wpas_dpp_chirp_stop(wpa_s);
5140 return;
5141 }
5142 if (wpa_s->dpp_chirp_listen) {
5143 wpa_printf(MSG_DEBUG,
5144 "DPP: Listen on %d MHz during chirp 30 second wait",
5145 wpa_s->dpp_chirp_listen);
5146 wpas_dpp_listen_start(wpa_s,
5147 wpa_s->dpp_chirp_listen);
5148 } else {
5149 wpa_printf(MSG_DEBUG,
5150 "DPP: Wait 30 seconds before starting the next chirping round");
5151 }
5152 return;
5153 }
5154 }
5155
5156 wpas_dpp_chirp_start(wpa_s);
5157}
5158
5159
5160int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
5161{
5162 const char *pos;
5163 int iter = 1, listen_freq = 0;
5164 struct dpp_bootstrap_info *bi;
5165
5166 pos = os_strstr(cmd, " own=");
5167 if (!pos)
5168 return -1;
5169 pos += 5;
5170 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
5171 if (!bi) {
5172 wpa_printf(MSG_DEBUG,
5173 "DPP: Identified bootstrap info not found");
5174 return -1;
5175 }
5176
5177 pos = os_strstr(cmd, " iter=");
5178 if (pos) {
5179 iter = atoi(pos + 6);
5180 if (iter <= 0)
5181 return -1;
5182 }
5183
5184 pos = os_strstr(cmd, " listen=");
5185 if (pos) {
5186 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005187 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005188 return -1;
5189 }
5190
5191 wpas_dpp_chirp_stop(wpa_s);
5192 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005193 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -07005194 wpa_s->dpp_qr_mutual = 0;
5195 wpa_s->dpp_chirp_bi = bi;
5196 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
5197 if (!wpa_s->dpp_presence_announcement)
5198 return -1;
5199 wpa_s->dpp_chirp_iter = iter;
5200 wpa_s->dpp_chirp_round = 0;
5201 wpa_s->dpp_chirp_scan_done = 0;
5202 wpa_s->dpp_chirp_listen = listen_freq;
5203
5204 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5205}
5206
5207
5208void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
5209{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005210 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07005211 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005212 offchannel_send_action_done(wpa_s);
5213 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
5214 }
5215 wpa_s->dpp_chirp_bi = NULL;
5216 wpabuf_free(wpa_s->dpp_presence_announcement);
5217 wpa_s->dpp_presence_announcement = NULL;
5218 if (wpa_s->dpp_chirp_listen)
5219 wpas_dpp_listen_stop(wpa_s);
5220 wpa_s->dpp_chirp_listen = 0;
5221 wpa_s->dpp_chirp_freq = 0;
5222 os_free(wpa_s->dpp_chirp_freqs);
5223 wpa_s->dpp_chirp_freqs = NULL;
5224 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
5225 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
5226 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
5227 wpas_abort_ongoing_scan(wpa_s);
5228 wpa_s->scan_res_handler = NULL;
5229 }
5230}
5231
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005232
Hai Shalom899fcc72020-10-19 14:38:18 -07005233int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005234{
Hai Shalom899fcc72020-10-19 14:38:18 -07005235 struct wpa_ssid *ssid;
5236 int iter = 1;
5237 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005238
Hai Shalom899fcc72020-10-19 14:38:18 -07005239 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
5240 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
5241 !ssid->dpp_csign) {
5242 wpa_printf(MSG_DEBUG,
5243 "DPP: Not a valid network profile for reconfiguration");
5244 return -1;
5245 }
5246
5247 pos = os_strstr(cmd, " iter=");
5248 if (pos) {
5249 iter = atoi(pos + 6);
5250 if (iter <= 0)
5251 return -1;
5252 }
5253
5254 if (wpa_s->dpp_auth) {
5255 wpa_printf(MSG_DEBUG,
5256 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
5257 return -1;
5258 }
5259
5260 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
5261 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
5262 ssid->dpp_csign_len,
5263 ssid->dpp_pp_key,
5264 ssid->dpp_pp_key_len);
5265 if (!wpa_s->dpp_reconfig_id) {
5266 wpa_printf(MSG_DEBUG,
5267 "DPP: Failed to generate E-id for reconfiguration");
5268 return -1;
5269 }
5270 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
5271 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
5272 wpa_s->own_disconnect_req = 1;
5273 wpa_supplicant_deauthenticate(
5274 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5275 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005276 wpas_dpp_chirp_stop(wpa_s);
5277 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
Sunil Ravia04bd252022-05-02 22:54:18 -07005278 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005279 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005280 wpa_s->dpp_reconfig_ssid = ssid;
5281 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07005282 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005283 wpa_s->dpp_chirp_round = 0;
5284 wpa_s->dpp_chirp_scan_done = 0;
5285 wpa_s->dpp_chirp_listen = 0;
5286
5287 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
5288}
5289
Hai Shalom899fcc72020-10-19 14:38:18 -07005290
Hai Shalom899fcc72020-10-19 14:38:18 -07005291int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
5292{
5293 int peer = -1;
5294 const char *pos, *value;
5295 struct dpp_authentication *auth = wpa_s->dpp_auth;
5296 u8 *bin;
5297 size_t bin_len;
5298 struct wpabuf *buf;
5299 bool tcp = false;
5300
5301 pos = os_strstr(cmd, " peer=");
5302 if (pos) {
5303 peer = atoi(pos + 6);
5304 if (!auth || !auth->waiting_cert ||
5305 (auth->peer_bi &&
5306 (unsigned int) peer != auth->peer_bi->id)) {
5307 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
5308 tcp = true;
5309 }
5310 }
5311
5312 if (!auth || !auth->waiting_cert) {
5313 wpa_printf(MSG_DEBUG,
5314 "DPP: No authentication exchange waiting for certificate information");
5315 return -1;
5316 }
5317
5318 if (peer >= 0 &&
5319 (!auth->peer_bi ||
5320 (unsigned int) peer != auth->peer_bi->id) &&
5321 (!auth->tmp_peer_bi ||
5322 (unsigned int) peer != auth->tmp_peer_bi->id)) {
5323 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
5324 return -1;
5325 }
5326
5327 pos = os_strstr(cmd, " value=");
5328 if (!pos)
5329 return -1;
5330 value = pos + 7;
5331
5332 pos = os_strstr(cmd, " name=");
5333 if (!pos)
5334 return -1;
5335 pos += 6;
5336
5337 if (os_strncmp(pos, "status ", 7) == 0) {
5338 auth->force_conf_resp_status = atoi(value);
5339 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5340 }
5341
5342 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
5343 os_free(auth->trusted_eap_server_name);
5344 auth->trusted_eap_server_name = os_strdup(value);
5345 return auth->trusted_eap_server_name ? 0 : -1;
5346 }
5347
5348 bin = base64_decode(value, os_strlen(value), &bin_len);
5349 if (!bin)
5350 return -1;
5351 buf = wpabuf_alloc_copy(bin, bin_len);
5352 os_free(bin);
5353
5354 if (os_strncmp(pos, "caCert ", 7) == 0) {
5355 wpabuf_free(auth->cacert);
5356 auth->cacert = buf;
5357 return 0;
5358 }
5359
5360 if (os_strncmp(pos, "certBag ", 8) == 0) {
5361 wpabuf_free(auth->certbag);
5362 auth->certbag = buf;
5363 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
5364 }
5365
5366 wpabuf_free(buf);
5367 return -1;
5368}
5369
Hai Shalom81f62d82019-07-22 12:10:00 -07005370#endif /* CONFIG_DPP2 */
Sunil Ravi89eba102022-09-13 21:04:37 -07005371
5372
5373#ifdef CONFIG_DPP3
5374
5375#define DPP_PB_ANNOUNCE_PER_CHAN 3
5376
5377static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq);
5378static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx);
5379
5380
5381static void wpas_dpp_pb_tx_status(struct wpa_supplicant *wpa_s,
5382 unsigned int freq, const u8 *dst,
5383 const u8 *src, const u8 *bssid,
5384 const u8 *data, size_t data_len,
5385 enum offchannel_send_action_result result)
5386{
5387 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
5388 wpa_printf(MSG_DEBUG,
5389 "DPP: Failed to send push button announcement on %d MHz",
5390 freq);
5391 if (eloop_register_timeout(0, 0, wpas_dpp_pb_next,
5392 wpa_s, NULL) < 0)
5393 wpas_dpp_push_button_stop(wpa_s);
5394 return;
5395 }
5396
5397 wpa_printf(MSG_DEBUG, "DPP: Push button announcement on %d MHz sent",
5398 freq);
5399 if (wpa_s->dpp_pb_discovery_done) {
5400 wpa_s->dpp_pb_announce_count = 0;
5401 wpa_printf(MSG_DEBUG,
5402 "DPP: Wait for push button announcement response and PKEX on %d MHz",
5403 freq);
5404 if (eloop_register_timeout(0, 500000, wpas_dpp_pb_next,
5405 wpa_s, NULL) < 0)
5406 wpas_dpp_push_button_stop(wpa_s);
5407 return;
5408 } else if (wpa_s->dpp_pb_announce_count >= DPP_PB_ANNOUNCE_PER_CHAN) {
5409 wpa_printf(MSG_DEBUG,
5410 "DPP: Wait for push button announcement response on %d MHz",
5411 freq);
5412 if (eloop_register_timeout(0, 50000, wpas_dpp_pb_next,
5413 wpa_s, NULL) < 0)
5414 wpas_dpp_push_button_stop(wpa_s);
5415 return;
5416 }
5417
5418 if (wpas_dpp_pb_announce(wpa_s, freq) < 0)
5419 wpas_dpp_push_button_stop(wpa_s);
5420}
5421
5422
5423static int wpas_dpp_pb_announce(struct wpa_supplicant *wpa_s, int freq)
5424{
5425 struct wpabuf *msg;
5426 int type;
5427
5428 msg = wpa_s->dpp_pb_announcement;
5429 if (!msg)
5430 return -1;
5431
5432 wpa_s->dpp_pb_announce_count++;
5433 wpa_printf(MSG_DEBUG,
5434 "DPP: Send push button announcement %d/%d (%d MHz)",
5435 wpa_s->dpp_pb_announce_count, DPP_PB_ANNOUNCE_PER_CHAN,
5436 freq);
5437
5438 type = DPP_PA_PB_PRESENCE_ANNOUNCEMENT;
5439 if (wpa_s->dpp_pb_announce_count == 1)
5440 wpa_msg(wpa_s, MSG_INFO,
5441 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
5442 MAC2STR(broadcast), freq, type);
5443 if (offchannel_send_action(
5444 wpa_s, freq, broadcast, wpa_s->own_addr, broadcast,
5445 wpabuf_head(msg), wpabuf_len(msg),
5446 1000, wpas_dpp_pb_tx_status, 0) < 0)
5447 return -1;
5448
5449 return 0;
5450}
5451
5452
5453static void wpas_dpp_pb_next(void *eloop_ctx, void *timeout_ctx)
5454{
5455 struct wpa_supplicant *wpa_s = eloop_ctx;
5456 struct os_reltime now;
5457 int freq;
5458
5459 if (!wpa_s->dpp_pb_freqs)
5460 return;
5461
5462 os_get_reltime(&now);
5463 offchannel_send_action_done(wpa_s);
5464
5465 if (os_reltime_expired(&now, &wpa_s->dpp_pb_time, 100)) {
5466 wpa_printf(MSG_DEBUG, "DPP: Push button wait time expired");
5467 wpas_dpp_push_button_stop(wpa_s);
5468 return;
5469 }
5470
5471 if (wpa_s->dpp_pb_freq_idx >= int_array_len(wpa_s->dpp_pb_freqs)) {
5472 wpa_printf(MSG_DEBUG,
5473 "DPP: Completed push button announcement round");
5474 wpa_s->dpp_pb_freq_idx = 0;
5475 if (wpa_s->dpp_pb_stop_iter > 0) {
5476 wpa_s->dpp_pb_stop_iter--;
5477
5478 if (wpa_s->dpp_pb_stop_iter == 1) {
5479 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5480 "wait for AP/Configurator to allow PKEX to be initiated");
5481 if (eloop_register_timeout(10, 0,
5482 wpas_dpp_pb_next,
5483 wpa_s, NULL) < 0) {
5484 wpas_dpp_push_button_stop(wpa_s);
5485 return;
5486 }
5487 return;
5488 }
5489
5490 if (wpa_s->dpp_pb_stop_iter == 0) {
5491 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_STATUS
5492 "start push button PKEX responder on the discovered channel (%d MHz)",
5493 wpa_s->dpp_pb_resp_freq);
5494 wpa_s->dpp_pb_discovery_done = true;
5495
5496 wpa_s->dpp_pkex_bi = wpa_s->dpp_pb_bi;
5497
5498 os_free(wpa_s->dpp_pkex_code);
5499 wpa_s->dpp_pkex_code = os_memdup(
5500 wpa_s->dpp_pb_c_nonce,
5501 wpa_s->dpp_pb_c_nonce_len);
5502 wpa_s->dpp_pkex_code_len =
5503 wpa_s->dpp_pb_c_nonce_len;
5504
5505 os_free(wpa_s->dpp_pkex_identifier);
5506 wpa_s->dpp_pkex_identifier =
5507 os_strdup("PBPKEX");
5508
5509 if (!wpa_s->dpp_pkex_code ||
5510 !wpa_s->dpp_pkex_identifier) {
5511 wpas_dpp_push_button_stop(wpa_s);
5512 return;
5513 }
5514
5515 wpa_s->dpp_pkex_ver = PKEX_VER_ONLY_2;
5516
5517 os_free(wpa_s->dpp_pkex_auth_cmd);
5518 wpa_s->dpp_pkex_auth_cmd = NULL;
5519 }
5520 }
5521 }
5522
5523 if (wpa_s->dpp_pb_discovery_done)
5524 freq = wpa_s->dpp_pb_resp_freq;
5525 else
5526 freq = wpa_s->dpp_pb_freqs[wpa_s->dpp_pb_freq_idx++];
5527 wpa_s->dpp_pb_announce_count = 0;
5528 if (!wpa_s->dpp_pb_announcement) {
5529 wpa_printf(MSG_DEBUG, "DPP: Push button announcements stopped");
5530 return;
5531 }
5532 if (wpas_dpp_pb_announce(wpa_s, freq) < 0) {
5533 wpas_dpp_push_button_stop(wpa_s);
5534 return;
5535 }
5536}
5537
5538
5539static void wpas_dpp_push_button_expire(void *eloop_ctx, void *timeout_ctx)
5540{
5541 struct wpa_supplicant *wpa_s = eloop_ctx;
5542
5543 wpa_printf(MSG_DEBUG,
5544 "DPP: Active push button Configurator mode expired");
5545 wpas_dpp_push_button_stop(wpa_s);
5546}
5547
5548
5549static int wpas_dpp_push_button_configurator(struct wpa_supplicant *wpa_s,
5550 const char *cmd)
5551{
5552 wpa_s->dpp_pb_configurator = true;
5553 wpa_s->dpp_pb_announce_time.sec = 0;
5554 wpa_s->dpp_pb_announce_time.usec = 0;
5555 str_clear_free(wpa_s->dpp_pb_cmd);
5556 wpa_s->dpp_pb_cmd = NULL;
5557 if (cmd) {
5558 wpa_s->dpp_pb_cmd = os_strdup(cmd);
5559 if (!wpa_s->dpp_pb_cmd)
5560 return -1;
5561 }
5562 eloop_register_timeout(100, 0, wpas_dpp_push_button_expire,
5563 wpa_s, NULL);
5564
5565 return 0;
5566}
5567
5568
5569static void wpas_dpp_pb_scan_res_handler(struct wpa_supplicant *wpa_s,
5570 struct wpa_scan_results *scan_res)
5571{
5572 if (!wpa_s->dpp_pb_time.sec && !wpa_s->dpp_pb_time.usec)
5573 return;
5574
5575 os_free(wpa_s->dpp_pb_freqs);
5576 wpa_s->dpp_pb_freqs = wpas_dpp_presence_ann_channels(wpa_s, NULL);
5577
5578 wpa_printf(MSG_DEBUG, "DPP: Scan completed for PB discovery");
5579 if (!wpa_s->dpp_pb_freqs ||
5580 eloop_register_timeout(0, 0, wpas_dpp_pb_next, wpa_s, NULL) < 0)
5581 wpas_dpp_push_button_stop(wpa_s);
5582}
5583
5584
5585int wpas_dpp_push_button(struct wpa_supplicant *wpa_s, const char *cmd)
5586{
5587 int res;
5588
5589 if (!wpa_s->dpp)
5590 return -1;
5591 wpas_dpp_push_button_stop(wpa_s);
5592 wpas_dpp_stop(wpa_s);
5593 wpas_dpp_chirp_stop(wpa_s);
5594
5595 os_get_reltime(&wpa_s->dpp_pb_time);
5596
5597 if (cmd &&
5598 (os_strstr(cmd, " role=configurator") ||
5599 os_strstr(cmd, " conf=")))
5600 return wpas_dpp_push_button_configurator(wpa_s, cmd);
5601
5602 wpa_s->dpp_pb_configurator = false;
5603
5604 wpa_s->dpp_pb_freq_idx = 0;
5605
5606 res = dpp_bootstrap_gen(wpa_s->dpp, "type=pkex");
5607 if (res < 0)
5608 return -1;
5609 wpa_s->dpp_pb_bi = dpp_bootstrap_get_id(wpa_s->dpp, res);
5610 if (!wpa_s->dpp_pb_bi)
5611 return -1;
5612
5613 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
5614 wpa_s->dpp_netrole = DPP_NETROLE_STA;
5615 wpa_s->dpp_qr_mutual = 0;
5616 wpa_s->dpp_pb_announcement =
5617 dpp_build_pb_announcement(wpa_s->dpp_pb_bi);
5618 if (!wpa_s->dpp_pb_announcement)
5619 return -1;
5620
5621 wpa_printf(MSG_DEBUG,
5622 "DPP: Scan to create channel list for PB discovery");
5623 wpa_s->scan_req = MANUAL_SCAN_REQ;
5624 wpa_s->scan_res_handler = wpas_dpp_pb_scan_res_handler;
5625 wpa_supplicant_req_scan(wpa_s, 0, 0);
5626 return 0;
5627}
5628
5629
5630void wpas_dpp_push_button_stop(struct wpa_supplicant *wpa_s)
5631{
5632 if (!wpa_s->dpp)
5633 return;
5634 os_free(wpa_s->dpp_pb_freqs);
5635 wpa_s->dpp_pb_freqs = NULL;
5636 wpabuf_free(wpa_s->dpp_pb_announcement);
5637 wpa_s->dpp_pb_announcement = NULL;
5638 if (wpa_s->dpp_pb_bi) {
5639 char id[20];
5640
5641 os_snprintf(id, sizeof(id), "%u", wpa_s->dpp_pb_bi->id);
5642 dpp_bootstrap_remove(wpa_s->dpp, id);
5643 wpa_s->dpp_pb_bi = NULL;
5644 if (!wpa_s->dpp_pb_result_indicated) {
5645 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5646 wpa_s->dpp_pb_result_indicated = true;
5647 }
5648 }
5649
5650 wpa_s->dpp_pb_resp_freq = 0;
5651 wpa_s->dpp_pb_stop_iter = 0;
5652 wpa_s->dpp_pb_discovery_done = false;
5653 os_free(wpa_s->dpp_pb_cmd);
5654 wpa_s->dpp_pb_cmd = NULL;
5655
5656 eloop_cancel_timeout(wpas_dpp_pb_next, wpa_s, NULL);
5657 eloop_cancel_timeout(wpas_dpp_push_button_expire, wpa_s, NULL);
5658 if (wpas_dpp_pb_active(wpa_s)) {
5659 wpa_printf(MSG_DEBUG, "DPP: Stop active push button mode");
5660 if (!wpa_s->dpp_pb_result_indicated)
5661 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PB_RESULT "failed");
5662 }
5663 wpa_s->dpp_pb_time.sec = 0;
5664 wpa_s->dpp_pb_time.usec = 0;
5665 dpp_pkex_free(wpa_s->dpp_pkex);
5666 wpa_s->dpp_pkex = NULL;
5667 os_free(wpa_s->dpp_pkex_auth_cmd);
5668 wpa_s->dpp_pkex_auth_cmd = NULL;
5669
5670 wpa_s->dpp_pb_result_indicated = false;
5671
5672 str_clear_free(wpa_s->dpp_pb_cmd);
5673 wpa_s->dpp_pb_cmd = NULL;
5674
5675 if (wpa_s->scan_res_handler == wpas_dpp_pb_scan_res_handler) {
5676 wpas_abort_ongoing_scan(wpa_s);
5677 wpa_s->scan_res_handler = NULL;
5678 }
5679}
5680
5681#endif /* CONFIG_DPP3 */