blob: 3e4363504bd003d6ba929bebc88240590c8f1842 [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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10#include "utils/includes.h"
11
12#include "utils/common.h"
13#include "utils/eloop.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070014#include "utils/ip_addr.h"
Hai Shalom899fcc72020-10-19 14:38:18 -070015#include "utils/base64.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070016#include "common/dpp.h"
17#include "common/gas.h"
18#include "common/gas_server.h"
19#include "rsn_supp/wpa.h"
20#include "rsn_supp/pmksa_cache.h"
21#include "wpa_supplicant_i.h"
22#include "config.h"
23#include "driver_i.h"
24#include "offchannel.h"
25#include "gas_query.h"
26#include "bss.h"
27#include "scan.h"
28#include "notify.h"
29#include "dpp_supplicant.h"
Gabriel Biren57ededa2021-09-03 16:08:50 +000030#include "aidl.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070031
32
33static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
34 unsigned int freq);
35static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom60840252021-02-19 19:02:11 -080036static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070037static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
38static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
39 unsigned int freq, const u8 *dst,
40 const u8 *src, const u8 *bssid,
41 const u8 *data, size_t data_len,
42 enum offchannel_send_action_result result);
Roshan Pius3a1667e2018-07-03 15:17:14 -070043static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
44static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
45static void
46wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
47 unsigned int freq, const u8 *dst,
48 const u8 *src, const u8 *bssid,
49 const u8 *data, size_t data_len,
50 enum offchannel_send_action_result result);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070051#ifdef CONFIG_DPP2
52static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
53 void *timeout_ctx);
Hai Shalom899fcc72020-10-19 14:38:18 -070054static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s);
55static int wpas_dpp_process_conf_obj(void *ctx,
56 struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070057#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070058
59static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
60
61/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
62 * a single transaction in progress at any point in time. */
63static const u8 TRANSACTION_ID = 1;
64
65
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070066/**
67 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
68 * @wpa_s: Pointer to wpa_supplicant data
69 * @cmd: DPP URI read from a QR Code
70 * Returns: Identifier of the stored info or -1 on failure
71 */
72int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
73{
74 struct dpp_bootstrap_info *bi;
75 struct dpp_authentication *auth = wpa_s->dpp_auth;
76
Hai Shalom021b0b52019-04-10 11:17:58 -070077 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070078 if (!bi)
79 return -1;
80
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070081 if (auth && auth->response_pending &&
82 dpp_notify_new_qr_code(auth, bi) == 1) {
83 wpa_printf(MSG_DEBUG,
84 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070085 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
86 " freq=%u type=%d",
87 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
88 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070089 offchannel_send_action(wpa_s, auth->curr_freq,
90 auth->peer_mac_addr, wpa_s->own_addr,
91 broadcast,
92 wpabuf_head(auth->resp_msg),
93 wpabuf_len(auth->resp_msg),
94 500, wpas_dpp_tx_status, 0);
95 }
96
Hai Shalom899fcc72020-10-19 14:38:18 -070097#ifdef CONFIG_DPP2
98 dpp_controller_new_qr_code(wpa_s->dpp, bi);
99#endif /* CONFIG_DPP2 */
100
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700101 return bi->id;
102}
103
104
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800105/**
106 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
107 * @wpa_s: Pointer to wpa_supplicant data
108 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
109 * Returns: Identifier of the stored info or -1 on failure
110 */
111int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
112{
113 struct dpp_bootstrap_info *bi;
114
115 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
116 if (!bi)
117 return -1;
118
119 return bi->id;
120}
121
122
Hai Shalomfdcde762020-04-02 11:19:20 -0700123int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd)
124{
125 const char *pos;
126 struct dpp_bootstrap_info *peer_bi, *own_bi;
127
128 pos = os_strstr(cmd, " own=");
129 if (!pos)
130 return -1;
131 pos += 5;
132 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
133 if (!own_bi)
134 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700135 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700136
137 pos = os_strstr(cmd, " uri=");
138 if (!pos)
139 return -1;
140 pos += 5;
141 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
142 if (!peer_bi) {
143 wpa_printf(MSG_INFO,
144 "DPP: Failed to parse URI from NFC Handover Request");
145 return -1;
146 }
147
148 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
149 return -1;
150
151 return peer_bi->id;
152}
153
154
155int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd)
156{
157 const char *pos;
158 struct dpp_bootstrap_info *peer_bi, *own_bi;
159
160 pos = os_strstr(cmd, " own=");
161 if (!pos)
162 return -1;
163 pos += 5;
164 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
165 if (!own_bi)
166 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700167 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700168
169 pos = os_strstr(cmd, " uri=");
170 if (!pos)
171 return -1;
172 pos += 5;
173 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
174 if (!peer_bi) {
175 wpa_printf(MSG_INFO,
176 "DPP: Failed to parse URI from NFC Handover Select");
177 return -1;
178 }
179
180 if (peer_bi->curve != own_bi->curve) {
181 wpa_printf(MSG_INFO,
182 "DPP: Peer (NFC Handover Selector) used different curve");
183 return -1;
184 }
185
186 return peer_bi->id;
187}
188
189
Roshan Pius3a1667e2018-07-03 15:17:14 -0700190static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
191{
192 struct wpa_supplicant *wpa_s = eloop_ctx;
193 struct dpp_authentication *auth = wpa_s->dpp_auth;
194
195 if (!auth || !auth->resp_msg)
196 return;
197
198 wpa_printf(MSG_DEBUG,
199 "DPP: Retry Authentication Response after timeout");
200 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
201 " freq=%u type=%d",
202 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
203 DPP_PA_AUTHENTICATION_RESP);
204 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
205 wpa_s->own_addr, broadcast,
206 wpabuf_head(auth->resp_msg),
207 wpabuf_len(auth->resp_msg),
208 500, wpas_dpp_tx_status, 0);
209}
210
211
212static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
213{
214 struct dpp_authentication *auth = wpa_s->dpp_auth;
215 unsigned int wait_time, max_tries;
216
217 if (!auth || !auth->resp_msg)
218 return;
219
220 if (wpa_s->dpp_resp_max_tries)
221 max_tries = wpa_s->dpp_resp_max_tries;
222 else
223 max_tries = 5;
224 auth->auth_resp_tries++;
225 if (auth->auth_resp_tries >= max_tries) {
226 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
227 offchannel_send_action_done(wpa_s);
228 dpp_auth_deinit(wpa_s->dpp_auth);
229 wpa_s->dpp_auth = NULL;
230 return;
231 }
232
233 if (wpa_s->dpp_resp_retry_time)
234 wait_time = wpa_s->dpp_resp_retry_time;
235 else
236 wait_time = 1000;
237 wpa_printf(MSG_DEBUG,
238 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
239 wait_time);
240 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
241 eloop_register_timeout(wait_time / 1000,
242 (wait_time % 1000) * 1000,
243 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
244}
245
246
Hai Shalom021b0b52019-04-10 11:17:58 -0700247static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
248{
249 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700250 wpa_s->suitable_network = 0;
251 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700252 wpa_s->disconnected = 0;
253 wpa_s->reassociate = 1;
254 wpa_s->scan_runs = 0;
255 wpa_s->normal_scans = 0;
256 wpa_supplicant_cancel_sched_scan(wpa_s);
257 wpa_supplicant_req_scan(wpa_s, 0, 0);
258}
259
260
Hai Shalomc3565922019-10-28 11:58:20 -0700261#ifdef CONFIG_DPP2
262
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700263static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s,
264 unsigned int freq,
265 unsigned int wait_time)
266{
267 struct os_reltime now, res;
268 unsigned int remaining;
269
270 if (!wpa_s->dpp_listen_freq)
271 return;
272
273 os_get_reltime(&now);
274 if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) {
275 os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res);
276 remaining = res.sec * 1000 + res.usec / 1000;
277 } else {
278 remaining = 0;
279 }
280 if (wpa_s->dpp_listen_freq == freq && remaining > wait_time)
281 return;
282
283 wpa_printf(MSG_DEBUG,
284 "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms",
285 wpa_s->dpp_listen_freq, remaining, freq, wait_time);
286 wpas_dpp_listen_stop(wpa_s);
287
288 /* TODO: Restart listen in some cases after TX? */
289}
290
291
Hai Shalomc3565922019-10-28 11:58:20 -0700292static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
293 void *timeout_ctx)
294{
295 struct wpa_supplicant *wpa_s = eloop_ctx;
296 struct dpp_authentication *auth = wpa_s->dpp_auth;
297 enum dpp_status_error result;
298
299 if (!auth || !auth->conn_status_requested)
300 return;
301
302 wpa_printf(MSG_DEBUG,
303 "DPP: Connection timeout - report Connection Status Result");
304 if (wpa_s->suitable_network)
305 result = DPP_STATUS_AUTH_FAILURE;
306 else if (wpa_s->no_suitable_network)
307 result = DPP_STATUS_NO_AP;
308 else
309 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800310 if (wpa_s->wpa_state == WPA_SCANNING)
311 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700312 wpas_dpp_send_conn_status_result(wpa_s, result);
313}
314
315
316static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
317{
318 char *str, *end, *pos;
319 size_t len;
320 unsigned int i;
321 u8 last_op_class = 0;
322 int res;
323
324 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
325 return NULL;
326
327 len = wpa_s->num_last_scan_freqs * 8;
328 str = os_zalloc(len);
329 if (!str)
330 return NULL;
331 end = str + len;
332 pos = str;
333
334 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
335 enum hostapd_hw_mode mode;
336 u8 op_class, channel;
337
338 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
339 0, 0, &op_class, &channel);
340 if (mode == NUM_HOSTAPD_MODES)
341 continue;
342 if (op_class == last_op_class)
343 res = os_snprintf(pos, end - pos, ",%d", channel);
344 else
345 res = os_snprintf(pos, end - pos, "%s%d/%d",
346 pos == str ? "" : ",",
347 op_class, channel);
348 if (os_snprintf_error(end - pos, res)) {
349 *pos = '\0';
350 break;
351 }
352 pos += res;
353 last_op_class = op_class;
354 }
355
356 if (pos == str) {
357 os_free(str);
358 str = NULL;
359 }
360 return str;
361}
362
363
364void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
365 enum dpp_status_error result)
366{
367 struct wpabuf *msg;
368 const char *channel_list = NULL;
369 char *channel_list_buf = NULL;
370 struct wpa_ssid *ssid = wpa_s->current_ssid;
371 struct dpp_authentication *auth = wpa_s->dpp_auth;
372
373 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
374
375 if (!auth || !auth->conn_status_requested)
376 return;
377 auth->conn_status_requested = 0;
378 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
379 result);
380
381 if (result == DPP_STATUS_NO_AP) {
382 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
383 channel_list = channel_list_buf;
384 }
385
386 msg = dpp_build_conn_status_result(auth, result,
387 ssid ? ssid->ssid :
388 wpa_s->dpp_last_ssid,
389 ssid ? ssid->ssid_len :
390 wpa_s->dpp_last_ssid_len,
391 channel_list);
392 os_free(channel_list_buf);
393 if (!msg) {
394 dpp_auth_deinit(wpa_s->dpp_auth);
395 wpa_s->dpp_auth = NULL;
396 return;
397 }
398
399 wpa_msg(wpa_s, MSG_INFO,
400 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
401 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
402 DPP_PA_CONNECTION_STATUS_RESULT);
403 offchannel_send_action(wpa_s, auth->curr_freq,
404 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
405 wpabuf_head(msg), wpabuf_len(msg),
406 500, wpas_dpp_tx_status, 0);
407 wpabuf_free(msg);
408
409 /* This exchange will be terminated in the TX status handler */
410 auth->remove_on_tx_status = 1;
411
412 return;
413}
414
415
416void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
417{
418 struct dpp_authentication *auth = wpa_s->dpp_auth;
419
420 if (auth && auth->conn_status_requested)
421 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
422}
423
424#endif /* CONFIG_DPP2 */
425
426
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700427static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
428 unsigned int freq, const u8 *dst,
429 const u8 *src, const u8 *bssid,
430 const u8 *data, size_t data_len,
431 enum offchannel_send_action_result result)
432{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700433 const char *res_txt;
434 struct dpp_authentication *auth = wpa_s->dpp_auth;
435
436 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
437 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
438 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700439 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700440 " result=%s", freq, MAC2STR(dst), res_txt);
441 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
442 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700443
444 if (!wpa_s->dpp_auth) {
445 wpa_printf(MSG_DEBUG,
446 "DPP: Ignore TX status since there is no ongoing authentication exchange");
447 return;
448 }
449
Hai Shalom021b0b52019-04-10 11:17:58 -0700450#ifdef CONFIG_DPP2
451 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700452 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700453 wpa_printf(MSG_DEBUG,
454 "DPP: Try to connect after completed configuration result");
455 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700456 if (auth->conn_status_requested) {
457 wpa_printf(MSG_DEBUG,
458 "DPP: Start 15 second timeout for reporting connection status result");
459 eloop_cancel_timeout(
460 wpas_dpp_conn_status_result_timeout,
461 wpa_s, NULL);
462 eloop_register_timeout(
463 15, 0, wpas_dpp_conn_status_result_timeout,
464 wpa_s, NULL);
465 } else {
466 dpp_auth_deinit(wpa_s->dpp_auth);
467 wpa_s->dpp_auth = NULL;
468 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700469 return;
470 }
471#endif /* CONFIG_DPP2 */
472
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700473 if (wpa_s->dpp_auth->remove_on_tx_status) {
474 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700475 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700476 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700477 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800478 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
479 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700480 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
481 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700482#ifdef CONFIG_DPP2
483 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
484 wpa_s, NULL);
485#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700486 offchannel_send_action_done(wpa_s);
487 dpp_auth_deinit(wpa_s->dpp_auth);
488 wpa_s->dpp_auth = NULL;
489 return;
490 }
491
492 if (wpa_s->dpp_auth_ok_on_ack)
493 wpas_dpp_auth_success(wpa_s, 1);
494
495 if (!is_broadcast_ether_addr(dst) &&
496 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
497 wpa_printf(MSG_DEBUG,
498 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700499 if (auth->waiting_auth_resp) {
500 /* In case of DPP Authentication Request frame, move to
501 * the next channel immediately. */
502 offchannel_send_action_done(wpa_s);
503 wpas_dpp_auth_init_next(wpa_s);
504 return;
505 }
506 if (auth->waiting_auth_conf) {
507 wpas_dpp_auth_resp_retry(wpa_s);
508 return;
509 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700510 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700511
Hai Shalom60840252021-02-19 19:02:11 -0800512 if (auth->waiting_auth_conf &&
513 auth->auth_resp_status == DPP_STATUS_OK) {
514 /* Make sure we do not get stuck waiting for Auth Confirm
515 * indefinitely after successfully transmitted Auth Response to
516 * allow new authentication exchanges to be started. */
517 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
518 NULL);
519 eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
520 wpa_s, NULL);
521 }
522
Roshan Pius3a1667e2018-07-03 15:17:14 -0700523 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
524 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
525 /* Allow timeout handling to stop iteration if no response is
526 * received from a peer that has ACKed a request. */
527 auth->auth_req_ack = 1;
528 }
529
530 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
531 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
532 wpa_printf(MSG_DEBUG,
533 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
534 wpa_s->dpp_auth->curr_freq,
535 wpa_s->dpp_auth->neg_freq);
536 offchannel_send_action_done(wpa_s);
537 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
538 }
539
540 if (wpa_s->dpp_auth_ok_on_ack)
541 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700542}
543
544
545static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
546{
547 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700548 struct dpp_authentication *auth = wpa_s->dpp_auth;
549 unsigned int freq;
550 struct os_reltime now, diff;
551 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700552
Roshan Pius3a1667e2018-07-03 15:17:14 -0700553 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700554 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700555
556 wait_time = wpa_s->dpp_resp_wait_time ?
557 wpa_s->dpp_resp_wait_time : 2000;
558 os_get_reltime(&now);
559 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
560 diff_ms = diff.sec * 1000 + diff.usec / 1000;
561 wpa_printf(MSG_DEBUG,
562 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
563 wait_time, diff_ms);
564
565 if (auth->auth_req_ack && diff_ms >= wait_time) {
566 /* Peer ACK'ed Authentication Request frame, but did not reply
567 * with Authentication Response frame within two seconds. */
568 wpa_printf(MSG_INFO,
569 "DPP: No response received from responder - stopping initiation attempt");
570 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800571 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700572 offchannel_send_action_done(wpa_s);
573 wpas_dpp_listen_stop(wpa_s);
574 dpp_auth_deinit(auth);
575 wpa_s->dpp_auth = NULL;
576 return;
577 }
578
579 if (diff_ms >= wait_time) {
580 /* Authentication Request frame was not ACK'ed and no reply
581 * was receiving within two seconds. */
582 wpa_printf(MSG_DEBUG,
583 "DPP: Continue Initiator channel iteration");
584 offchannel_send_action_done(wpa_s);
585 wpas_dpp_listen_stop(wpa_s);
586 wpas_dpp_auth_init_next(wpa_s);
587 return;
588 }
589
590 /* Driver did not support 2000 ms long wait_time with TX command, so
591 * schedule listen operation to continue waiting for the response.
592 *
593 * DPP listen operations continue until stopped, so simply schedule a
594 * new call to this function at the point when the two second reply
595 * wait has expired. */
596 wait_time -= diff_ms;
597
598 freq = auth->curr_freq;
599 if (auth->neg_freq > 0)
600 freq = auth->neg_freq;
601 wpa_printf(MSG_DEBUG,
602 "DPP: Continue reply wait on channel %u MHz for %u ms",
603 freq, wait_time);
604 wpa_s->dpp_in_response_listen = 1;
605 wpas_dpp_listen_start(wpa_s, freq);
606
607 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
608 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700609}
610
611
Hai Shalom60840252021-02-19 19:02:11 -0800612static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
613{
614 struct wpa_supplicant *wpa_s = eloop_ctx;
615 struct dpp_authentication *auth = wpa_s->dpp_auth;
616
617 if (!auth || !auth->waiting_auth_conf)
618 return;
619
620 wpa_printf(MSG_DEBUG,
621 "DPP: Terminate authentication exchange due to Auth Confirm timeout");
622 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
623 offchannel_send_action_done(wpa_s);
624 dpp_auth_deinit(auth);
625 wpa_s->dpp_auth = NULL;
626}
627
628
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700629static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
630 struct dpp_authentication *auth)
631{
632#ifdef CONFIG_TESTING_OPTIONS
633 if (wpa_s->dpp_config_obj_override)
634 auth->config_obj_override =
635 os_strdup(wpa_s->dpp_config_obj_override);
636 if (wpa_s->dpp_discovery_override)
637 auth->discovery_override =
638 os_strdup(wpa_s->dpp_discovery_override);
639 if (wpa_s->dpp_groups_override)
640 auth->groups_override =
641 os_strdup(wpa_s->dpp_groups_override);
642 auth->ignore_netaccesskey_mismatch =
643 wpa_s->dpp_ignore_netaccesskey_mismatch;
644#endif /* CONFIG_TESTING_OPTIONS */
645}
646
647
Roshan Pius3a1667e2018-07-03 15:17:14 -0700648static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
649{
650 struct wpa_supplicant *wpa_s = eloop_ctx;
651
652 if (!wpa_s->dpp_auth)
653 return;
654 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
655 wpas_dpp_auth_init_next(wpa_s);
656}
657
658
659static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
660{
661 struct dpp_authentication *auth = wpa_s->dpp_auth;
662 const u8 *dst;
663 unsigned int wait_time, max_wait_time, freq, max_tries, used;
664 struct os_reltime now, diff;
665
666 wpa_s->dpp_in_response_listen = 0;
667 if (!auth)
668 return -1;
669
670 if (auth->freq_idx == 0)
671 os_get_reltime(&wpa_s->dpp_init_iter_start);
672
673 if (auth->freq_idx >= auth->num_freq) {
674 auth->num_freq_iters++;
675 if (wpa_s->dpp_init_max_tries)
676 max_tries = wpa_s->dpp_init_max_tries;
677 else
678 max_tries = 5;
679 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
680 wpa_printf(MSG_INFO,
681 "DPP: No response received from responder - stopping initiation attempt");
682 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800683 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700684 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
685 wpa_s, NULL);
686 offchannel_send_action_done(wpa_s);
687 dpp_auth_deinit(wpa_s->dpp_auth);
688 wpa_s->dpp_auth = NULL;
689 return -1;
690 }
691 auth->freq_idx = 0;
692 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
693 if (wpa_s->dpp_init_retry_time)
694 wait_time = wpa_s->dpp_init_retry_time;
695 else
696 wait_time = 10000;
697 os_get_reltime(&now);
698 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
699 used = diff.sec * 1000 + diff.usec / 1000;
700 if (used > wait_time)
701 wait_time = 0;
702 else
703 wait_time -= used;
704 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
705 wait_time);
706 eloop_register_timeout(wait_time / 1000,
707 (wait_time % 1000) * 1000,
708 wpas_dpp_init_timeout, wpa_s,
709 NULL);
710 return 0;
711 }
712 freq = auth->freq[auth->freq_idx++];
713 auth->curr_freq = freq;
714
Hai Shalom60840252021-02-19 19:02:11 -0800715 if (!is_zero_ether_addr(auth->peer_mac_addr))
716 dst = auth->peer_mac_addr;
717 else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
Roshan Pius3a1667e2018-07-03 15:17:14 -0700718 dst = broadcast;
719 else
720 dst = auth->peer_bi->mac_addr;
721 wpa_s->dpp_auth_ok_on_ack = 0;
722 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
723 wait_time = wpa_s->max_remain_on_chan;
724 max_wait_time = wpa_s->dpp_resp_wait_time ?
725 wpa_s->dpp_resp_wait_time : 2000;
726 if (wait_time > max_wait_time)
727 wait_time = max_wait_time;
728 wait_time += 10; /* give the driver some extra time to complete */
729 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
730 wpas_dpp_reply_wait_timeout,
731 wpa_s, NULL);
732 wait_time -= 10;
733 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
734 wpa_printf(MSG_DEBUG,
735 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
736 freq, auth->neg_freq);
737 }
738 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
739 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
740 auth->auth_req_ack = 0;
741 os_get_reltime(&wpa_s->dpp_last_init);
742 return offchannel_send_action(wpa_s, freq, dst,
743 wpa_s->own_addr, broadcast,
744 wpabuf_head(auth->req_msg),
745 wpabuf_len(auth->req_msg),
746 wait_time, wpas_dpp_tx_status, 0);
747}
748
749
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700750int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
751{
752 const char *pos;
753 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700754 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700755 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
756 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700757 int tcp = 0;
758#ifdef CONFIG_DPP2
759 int tcp_port = DPP_TCP_PORT;
760 struct hostapd_ip_addr ipaddr;
761 char *addr;
762#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700763
764 wpa_s->dpp_gas_client = 0;
765
766 pos = os_strstr(cmd, " peer=");
767 if (!pos)
768 return -1;
769 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700770 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700771 if (!peer_bi) {
772 wpa_printf(MSG_INFO,
773 "DPP: Could not find bootstrapping info for the identified peer");
774 return -1;
775 }
776
Hai Shalom81f62d82019-07-22 12:10:00 -0700777#ifdef CONFIG_DPP2
778 pos = os_strstr(cmd, " tcp_port=");
779 if (pos) {
780 pos += 10;
781 tcp_port = atoi(pos);
782 }
783
784 addr = get_param(cmd, " tcp_addr=");
785 if (addr) {
786 int res;
787
788 res = hostapd_parse_ip_addr(addr, &ipaddr);
789 os_free(addr);
790 if (res)
791 return -1;
792 tcp = 1;
793 }
794#endif /* CONFIG_DPP2 */
795
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700796 pos = os_strstr(cmd, " own=");
797 if (pos) {
798 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700799 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700800 if (!own_bi) {
801 wpa_printf(MSG_INFO,
802 "DPP: Could not find bootstrapping info for the identified local entry");
803 return -1;
804 }
805
806 if (peer_bi->curve != own_bi->curve) {
807 wpa_printf(MSG_INFO,
808 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
809 peer_bi->curve->name, own_bi->curve->name);
810 return -1;
811 }
812 }
813
814 pos = os_strstr(cmd, " role=");
815 if (pos) {
816 pos += 6;
817 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700818 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700819 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700820 allowed_roles = DPP_CAPAB_ENROLLEE;
821 else if (os_strncmp(pos, "either", 6) == 0)
822 allowed_roles = DPP_CAPAB_CONFIGURATOR |
823 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700824 else
825 goto fail;
826 }
827
828 pos = os_strstr(cmd, " netrole=");
829 if (pos) {
830 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800831 if (os_strncmp(pos, "ap", 2) == 0)
832 wpa_s->dpp_netrole = DPP_NETROLE_AP;
833 else if (os_strncmp(pos, "configurator", 12) == 0)
834 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
835 else
836 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700837 } else {
838 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700839 }
840
Roshan Pius3a1667e2018-07-03 15:17:14 -0700841 pos = os_strstr(cmd, " neg_freq=");
842 if (pos)
843 neg_freq = atoi(pos + 10);
844
Hai Shalom81f62d82019-07-22 12:10:00 -0700845 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700846 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700847 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800848 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
849 NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700850 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
851 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700852#ifdef CONFIG_DPP2
853 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
854 wpa_s, NULL);
855#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700856 offchannel_send_action_done(wpa_s);
857 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800858 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700859 }
860
Hai Shalomfdcde762020-04-02 11:19:20 -0700861 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
862 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700863 if (!auth)
864 goto fail;
865 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700866 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700867 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800868 goto fail;
869 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700870
Hai Shalom81f62d82019-07-22 12:10:00 -0700871 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700872
Roshan Pius3a1667e2018-07-03 15:17:14 -0700873 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700874 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700875
Hai Shalom81f62d82019-07-22 12:10:00 -0700876#ifdef CONFIG_DPP2
877 if (tcp)
Hai Shalom899fcc72020-10-19 14:38:18 -0700878 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
879 wpa_s->conf->dpp_name, DPP_NETROLE_STA,
880 wpa_s, wpa_s, wpas_dpp_process_conf_obj);
Hai Shalom81f62d82019-07-22 12:10:00 -0700881#endif /* CONFIG_DPP2 */
882
883 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700884 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700885fail:
886 return -1;
887}
888
889
890struct wpas_dpp_listen_work {
891 unsigned int freq;
892 unsigned int duration;
893 struct wpabuf *probe_resp_ie;
894};
895
896
897static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
898{
899 if (!lwork)
900 return;
901 os_free(lwork);
902}
903
904
905static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
906{
907 struct wpas_dpp_listen_work *lwork;
908
909 if (!wpa_s->dpp_listen_work)
910 return;
911
912 lwork = wpa_s->dpp_listen_work->ctx;
913 wpas_dpp_listen_work_free(lwork);
914 radio_work_done(wpa_s->dpp_listen_work);
915 wpa_s->dpp_listen_work = NULL;
916}
917
918
919static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
920{
921 struct wpa_supplicant *wpa_s = work->wpa_s;
922 struct wpas_dpp_listen_work *lwork = work->ctx;
923
924 if (deinit) {
925 if (work->started) {
926 wpa_s->dpp_listen_work = NULL;
927 wpas_dpp_listen_stop(wpa_s);
928 }
929 wpas_dpp_listen_work_free(lwork);
930 return;
931 }
932
933 wpa_s->dpp_listen_work = work;
934
935 wpa_s->dpp_pending_listen_freq = lwork->freq;
936
937 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
938 wpa_s->max_remain_on_chan) < 0) {
939 wpa_printf(MSG_DEBUG,
940 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
941 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800942 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700943 wpas_dpp_listen_work_done(wpa_s);
944 wpa_s->dpp_pending_listen_freq = 0;
945 return;
946 }
947 wpa_s->off_channel_freq = 0;
948 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700949 wpa_drv_dpp_listen(wpa_s, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700950}
951
952
953static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
954 unsigned int freq)
955{
956 struct wpas_dpp_listen_work *lwork;
957
958 if (wpa_s->dpp_listen_work) {
959 wpa_printf(MSG_DEBUG,
960 "DPP: Reject start_listen since dpp_listen_work already exists");
961 return -1;
962 }
963
964 if (wpa_s->dpp_listen_freq)
965 wpas_dpp_listen_stop(wpa_s);
966 wpa_s->dpp_listen_freq = freq;
967
968 lwork = os_zalloc(sizeof(*lwork));
969 if (!lwork)
970 return -1;
971 lwork->freq = freq;
972
973 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
974 lwork) < 0) {
975 wpas_dpp_listen_work_free(lwork);
976 return -1;
977 }
978
979 return 0;
980}
981
982
983int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
984{
985 int freq;
986
987 freq = atoi(cmd);
988 if (freq <= 0)
989 return -1;
990
991 if (os_strstr(cmd, " role=configurator"))
992 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
993 else if (os_strstr(cmd, " role=enrollee"))
994 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
995 else
996 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
997 DPP_CAPAB_ENROLLEE;
998 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800999 if (os_strstr(cmd, " netrole=ap"))
1000 wpa_s->dpp_netrole = DPP_NETROLE_AP;
1001 else if (os_strstr(cmd, " netrole=configurator"))
1002 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
1003 else
1004 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001005 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1006 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1007 freq);
1008 return 0;
1009 }
1010
1011 return wpas_dpp_listen_start(wpa_s, freq);
1012}
1013
1014
1015void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1016{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001017 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001018 if (!wpa_s->dpp_listen_freq)
1019 return;
1020
1021 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1022 wpa_s->dpp_listen_freq);
1023 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -07001024 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001025 wpa_s->dpp_listen_freq = 0;
1026 wpas_dpp_listen_work_done(wpa_s);
1027}
1028
1029
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001030void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1031 unsigned int freq, unsigned int duration)
1032{
1033 if (wpa_s->dpp_listen_freq != freq)
1034 return;
1035
1036 wpa_printf(MSG_DEBUG,
1037 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
1038 freq, duration);
1039 os_get_reltime(&wpa_s->dpp_listen_end);
1040 wpa_s->dpp_listen_end.usec += duration * 1000;
1041 while (wpa_s->dpp_listen_end.usec >= 1000000) {
1042 wpa_s->dpp_listen_end.sec++;
1043 wpa_s->dpp_listen_end.usec -= 1000000;
1044 }
1045}
1046
1047
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001048void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1049 unsigned int freq)
1050{
1051 wpas_dpp_listen_work_done(wpa_s);
1052
Roshan Pius3a1667e2018-07-03 15:17:14 -07001053 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1054 unsigned int new_freq;
1055
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001056 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001057 if (wpa_s->dpp_auth->neg_freq > 0)
1058 new_freq = wpa_s->dpp_auth->neg_freq;
1059 else
1060 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001061 wpa_printf(MSG_DEBUG,
1062 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001063 new_freq);
1064 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001065 return;
1066 }
1067
1068 if (wpa_s->dpp_listen_freq) {
1069 /* Continue listen with a new remain-on-channel */
1070 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1071 }
1072}
1073
1074
1075static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1076 const u8 *hdr, const u8 *buf, size_t len,
1077 unsigned int freq)
1078{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001079 const u8 *r_bootstrap, *i_bootstrap;
1080 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001081 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1082
1083 if (!wpa_s->dpp)
1084 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001085
1086 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1087 MAC2STR(src));
1088
Hai Shalomfdcde762020-04-02 11:19:20 -07001089#ifdef CONFIG_DPP2
1090 wpas_dpp_chirp_stop(wpa_s);
1091#endif /* CONFIG_DPP2 */
1092
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001093 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1094 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001095 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1096 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1097 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001098 return;
1099 }
1100 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1101 r_bootstrap, r_bootstrap_len);
1102
1103 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1104 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001105 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1106 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1107 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001108 return;
1109 }
1110 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1111 i_bootstrap, i_bootstrap_len);
1112
1113 /* Try to find own and peer bootstrapping key matches based on the
1114 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001115 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1116 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001117 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001118 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1119 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001120 return;
1121 }
1122
1123 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001124 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1125 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001126 return;
1127 }
1128
1129 wpa_s->dpp_gas_client = 0;
1130 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001131 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1132 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001133 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001134 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001135 if (!wpa_s->dpp_auth) {
1136 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1137 return;
1138 }
1139 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001140 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001141 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001142 dpp_auth_deinit(wpa_s->dpp_auth);
1143 wpa_s->dpp_auth = NULL;
1144 return;
1145 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001146 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1147
Roshan Pius3a1667e2018-07-03 15:17:14 -07001148 if (wpa_s->dpp_listen_freq &&
1149 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1150 wpa_printf(MSG_DEBUG,
1151 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1152 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1153 wpas_dpp_listen_stop(wpa_s);
1154 }
1155
1156 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1157 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1158 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001159 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1160 src, wpa_s->own_addr, broadcast,
1161 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1162 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1163 500, wpas_dpp_tx_status, 0);
1164}
1165
1166
1167static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1168{
1169 /* TODO: stop wait and start ROC */
1170}
1171
1172
1173static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001174 struct dpp_authentication *auth,
1175 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001176{
1177 struct wpa_ssid *ssid;
1178
Hai Shalom021b0b52019-04-10 11:17:58 -07001179#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001180 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001181#ifdef CONFIG_SAE
1182 struct wpa_driver_capa capa;
1183 int res;
1184
1185 res = wpa_drv_get_capa(wpa_s, &capa);
1186 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001187 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1188 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001189 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1190 wpa_printf(MSG_DEBUG,
1191 "DPP: SAE not supported by the driver");
1192 return NULL;
1193 }
1194#else /* CONFIG_SAE */
1195 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1196 return NULL;
1197#endif /* CONFIG_SAE */
1198 }
1199#endif /* CONFIG_DPP2 */
1200
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001201 ssid = wpa_config_add_network(wpa_s->conf);
1202 if (!ssid)
1203 return NULL;
1204 wpas_notify_network_added(wpa_s, ssid);
1205 wpa_config_set_network_defaults(ssid);
1206 ssid->disabled = 1;
1207
Hai Shalomc3565922019-10-28 11:58:20 -07001208 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001209 if (!ssid->ssid)
1210 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001211 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1212 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001213
Hai Shalomc3565922019-10-28 11:58:20 -07001214 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001215 if (dpp_akm_dpp(conf->akm)) {
1216 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1217 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1218 }
Hai Shalomc3565922019-10-28 11:58:20 -07001219 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001220 if (!ssid->dpp_connector)
1221 goto fail;
1222 }
1223
Hai Shalomc3565922019-10-28 11:58:20 -07001224 if (conf->c_sign_key) {
1225 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001226 if (!ssid->dpp_csign)
1227 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001228 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1229 wpabuf_len(conf->c_sign_key));
1230 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001231 }
1232
Hai Shalom899fcc72020-10-19 14:38:18 -07001233 if (conf->pp_key) {
1234 ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key));
1235 if (!ssid->dpp_pp_key)
1236 goto fail;
1237 os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key),
1238 wpabuf_len(conf->pp_key));
1239 ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key);
1240 }
1241
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001242 if (auth->net_access_key) {
1243 ssid->dpp_netaccesskey =
1244 os_malloc(wpabuf_len(auth->net_access_key));
1245 if (!ssid->dpp_netaccesskey)
1246 goto fail;
1247 os_memcpy(ssid->dpp_netaccesskey,
1248 wpabuf_head(auth->net_access_key),
1249 wpabuf_len(auth->net_access_key));
1250 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1251 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1252 }
1253
Hai Shalomc3565922019-10-28 11:58:20 -07001254 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1255 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001256 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001257 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001258 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001259 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1260 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001261 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001262 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1263 WPA_KEY_MGMT_FT_SAE;
1264 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001265 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001266 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001267 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001268 goto fail;
1269 wpa_config_update_psk(ssid);
1270 ssid->export_keys = 1;
1271 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001272 ssid->psk_set = conf->psk_set;
1273 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001274 }
1275 }
1276
Hai Shalom899fcc72020-10-19 14:38:18 -07001277#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL)
1278 if (conf->akm == DPP_AKM_DOT1X) {
1279 int i;
1280 char name[100], blobname[128];
1281 struct wpa_config_blob *blob;
1282
1283 ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
1284 WPA_KEY_MGMT_IEEE8021X_SHA256 |
1285 WPA_KEY_MGMT_IEEE8021X_SHA256;
1286 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
1287
1288 if (conf->cacert) {
1289 /* caCert is DER-encoded X.509v3 certificate for the
1290 * server certificate if that is different from the
1291 * trust root included in certBag. */
1292 /* TODO: ssid->eap.cert.ca_cert */
1293 }
1294
1295 if (conf->certs) {
1296 for (i = 0; ; i++) {
1297 os_snprintf(name, sizeof(name), "dpp-certs-%d",
1298 i);
1299 if (!wpa_config_get_blob(wpa_s->conf, name))
1300 break;
1301 }
1302
1303 blob = os_zalloc(sizeof(*blob));
1304 if (!blob)
1305 goto fail;
1306 blob->len = wpabuf_len(conf->certs);
1307 blob->name = os_strdup(name);
1308 blob->data = os_malloc(blob->len);
1309 if (!blob->name || !blob->data) {
1310 wpa_config_free_blob(blob);
1311 goto fail;
1312 }
1313 os_memcpy(blob->data, wpabuf_head(conf->certs),
1314 blob->len);
1315 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1316 name);
1317 wpa_config_set_blob(wpa_s->conf, blob);
1318 wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
1319 name);
1320 ssid->eap.cert.client_cert = os_strdup(blobname);
1321 if (!ssid->eap.cert.client_cert)
1322 goto fail;
1323
1324 /* TODO: ssid->eap.identity from own certificate */
1325 if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
1326 0) < 0)
1327 goto fail;
1328 }
1329
1330 if (auth->priv_key) {
1331 for (i = 0; ; i++) {
1332 os_snprintf(name, sizeof(name), "dpp-key-%d",
1333 i);
1334 if (!wpa_config_get_blob(wpa_s->conf, name))
1335 break;
1336 }
1337
1338 blob = os_zalloc(sizeof(*blob));
1339 if (!blob)
1340 goto fail;
1341 blob->len = wpabuf_len(auth->priv_key);
1342 blob->name = os_strdup(name);
1343 blob->data = os_malloc(blob->len);
1344 if (!blob->name || !blob->data) {
1345 wpa_config_free_blob(blob);
1346 goto fail;
1347 }
1348 os_memcpy(blob->data, wpabuf_head(auth->priv_key),
1349 blob->len);
1350 os_snprintf(blobname, sizeof(blobname), "blob://%s",
1351 name);
1352 wpa_config_set_blob(wpa_s->conf, blob);
1353 wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
1354 name);
1355 ssid->eap.cert.private_key = os_strdup(blobname);
1356 if (!ssid->eap.cert.private_key)
1357 goto fail;
1358 }
1359
1360 if (conf->server_name) {
1361 ssid->eap.cert.domain_suffix_match =
1362 os_strdup(conf->server_name);
1363 if (!ssid->eap.cert.domain_suffix_match)
1364 goto fail;
1365 }
1366
1367 /* TODO: Use entCreds::eapMethods */
1368 if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
1369 goto fail;
1370 }
1371#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */
1372
Hai Shalomc3565922019-10-28 11:58:20 -07001373 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1374 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1375
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001376 return ssid;
1377fail:
1378 wpas_notify_network_removed(wpa_s, ssid);
1379 wpa_config_remove_network(wpa_s->conf, ssid->id);
1380 return NULL;
1381}
1382
1383
Hai Shalom021b0b52019-04-10 11:17:58 -07001384static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001385 struct dpp_authentication *auth,
1386 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001387{
1388 struct wpa_ssid *ssid;
1389
1390 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001391 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001392
Hai Shalomc3565922019-10-28 11:58:20 -07001393 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001394 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001395 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001396
1397 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001398
Hai Shalom706f99b2019-01-08 16:23:37 -08001399 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001400
Hai Shalom021b0b52019-04-10 11:17:58 -07001401 if (wpa_s->conf->dpp_config_processing == 2)
1402 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001403
Hai Shalom021b0b52019-04-10 11:17:58 -07001404#ifndef CONFIG_NO_CONFIG_WRITE
1405 if (wpa_s->conf->update_config &&
1406 wpa_config_write(wpa_s->confname, wpa_s->conf))
1407 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1408#endif /* CONFIG_NO_CONFIG_WRITE */
1409
Hai Shalomc3565922019-10-28 11:58:20 -07001410 return 0;
1411}
1412
1413
1414static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1415 struct dpp_authentication *auth)
1416{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001417#ifdef CONFIG_DPP2
1418 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1419 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1420 wpa_s->dpp_reconfig_ssid) {
1421 wpa_printf(MSG_DEBUG,
1422 "DPP: Remove reconfigured network profile");
1423 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1424 wpa_config_remove_network(wpa_s->conf,
1425 wpa_s->dpp_reconfig_ssid_id);
1426 wpa_s->dpp_reconfig_ssid = NULL;
1427 wpa_s->dpp_reconfig_ssid_id = -1;
1428 }
1429#endif /* CONFIG_DPP2 */
1430
Hai Shalom021b0b52019-04-10 11:17:58 -07001431 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001432 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001433
1434#ifdef CONFIG_DPP2
1435 if (auth->peer_version >= 2) {
1436 wpa_printf(MSG_DEBUG,
1437 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1438 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001439 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001440 }
1441#endif /* CONFIG_DPP2 */
1442
1443 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001444}
1445
1446
Hai Shalom021b0b52019-04-10 11:17:58 -07001447static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001448 struct dpp_authentication *auth,
1449 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001450{
1451 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom60840252021-02-19 19:02:11 -08001452 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1453 dpp_akm_str(conf->akm));
Hai Shalomc3565922019-10-28 11:58:20 -07001454 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001455 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001456 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001457 if (conf->ssid_charset)
1458 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1459 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001460 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001461 /* TODO: Save the Connector and consider using a command
1462 * to fetch the value instead of sending an event with
1463 * it. The Connector could end up being larger than what
1464 * most clients are ready to receive as an event
1465 * message. */
1466 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001467 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001468 }
Hai Shalom60840252021-02-19 19:02:11 -08001469 if (conf->passphrase[0]) {
1470 char hex[64 * 2 + 1];
1471
1472 wpa_snprintf_hex(hex, sizeof(hex),
1473 (const u8 *) conf->passphrase,
1474 os_strlen(conf->passphrase));
1475 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1476 hex);
1477 } else if (conf->psk_set) {
1478 char hex[PMK_LEN * 2 + 1];
1479
1480 wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
1481 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1482 hex);
1483 }
Hai Shalomc3565922019-10-28 11:58:20 -07001484 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001485 char *hex;
1486 size_t hexlen;
1487
Hai Shalomc3565922019-10-28 11:58:20 -07001488 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001489 hex = os_malloc(hexlen);
1490 if (hex) {
1491 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001492 wpabuf_head(conf->c_sign_key),
1493 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001494 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1495 hex);
1496 os_free(hex);
1497 }
1498 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001499 if (conf->pp_key) {
1500 char *hex;
1501 size_t hexlen;
1502
1503 hexlen = 2 * wpabuf_len(conf->pp_key) + 1;
1504 hex = os_malloc(hexlen);
1505 if (hex) {
1506 wpa_snprintf_hex(hex, hexlen,
1507 wpabuf_head(conf->pp_key),
1508 wpabuf_len(conf->pp_key));
1509 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex);
1510 os_free(hex);
1511 }
1512 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001513 if (auth->net_access_key) {
1514 char *hex;
1515 size_t hexlen;
1516
1517 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1518 hex = os_malloc(hexlen);
1519 if (hex) {
1520 wpa_snprintf_hex(hex, hexlen,
1521 wpabuf_head(auth->net_access_key),
1522 wpabuf_len(auth->net_access_key));
1523 if (auth->net_access_key_expiry)
1524 wpa_msg(wpa_s, MSG_INFO,
1525 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1526 (long unsigned)
1527 auth->net_access_key_expiry);
1528 else
1529 wpa_msg(wpa_s, MSG_INFO,
1530 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1531 os_free(hex);
1532 }
1533 }
1534
Hai Shalom899fcc72020-10-19 14:38:18 -07001535#ifdef CONFIG_DPP2
1536 if (conf->certbag) {
1537 char *b64;
1538
1539 b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
1540 wpabuf_len(conf->certbag), NULL);
1541 if (b64)
1542 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
1543 os_free(b64);
1544 }
1545
1546 if (conf->cacert) {
1547 char *b64;
1548
1549 b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
1550 wpabuf_len(conf->cacert), NULL);
1551 if (b64)
1552 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
1553 os_free(b64);
1554 }
1555
1556 if (conf->server_name)
1557 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
1558 conf->server_name);
1559#endif /* CONFIG_DPP2 */
1560
Hai Shalomc3565922019-10-28 11:58:20 -07001561 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001562}
1563
1564
Hai Shalomfdcde762020-04-02 11:19:20 -07001565static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1566 struct dpp_asymmetric_key *key)
1567{
1568#ifdef CONFIG_DPP2
1569 int res;
1570
1571 if (!key)
1572 return 0;
1573
1574 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1575 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalom899fcc72020-10-19 14:38:18 -07001576 wpa_s->dpp_conf_backup_received = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001577
1578 while (key) {
1579 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1580 if (res < 0)
1581 return -1;
1582 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1583 res);
1584 key = key->next;
1585 }
1586#endif /* CONFIG_DPP2 */
1587
1588 return 0;
1589}
1590
1591
Hai Shalom899fcc72020-10-19 14:38:18 -07001592#ifdef CONFIG_DPP2
1593static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
1594{
1595 struct wpa_supplicant *wpa_s = eloop_ctx;
1596 struct dpp_authentication *auth = wpa_s->dpp_auth;
1597
1598 if (!auth || !auth->csrattrs)
1599 return;
1600
1601 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1602 wpabuf_free(auth->csr);
1603 /* TODO: Additional information needed for CSR based on csrAttrs */
1604 auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ?
1605 wpa_s->conf->dpp_name : "Test");
1606 if (!auth->csr) {
1607 dpp_auth_deinit(wpa_s->dpp_auth);
1608 wpa_s->dpp_auth = NULL;
1609 return;
1610 }
1611
1612 wpas_dpp_start_gas_client(wpa_s);
1613}
1614#endif /* CONFIG_DPP2 */
1615
1616
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001617static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1618 enum gas_query_result result,
1619 const struct wpabuf *adv_proto,
1620 const struct wpabuf *resp, u16 status_code)
1621{
1622 struct wpa_supplicant *wpa_s = ctx;
1623 const u8 *pos;
1624 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001625 int res;
1626 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001627 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001628
Roshan Pius3a1667e2018-07-03 15:17:14 -07001629 wpa_s->dpp_gas_dialog_token = -1;
1630
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001631 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
1632 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001633 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1634 return;
1635 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001636 if (result != GAS_QUERY_SUCCESS ||
1637 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001638 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1639 goto fail;
1640 }
1641
1642 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1643 adv_proto);
1644 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1645 resp);
1646
1647 if (wpabuf_len(adv_proto) != 10 ||
1648 !(pos = wpabuf_head(adv_proto)) ||
1649 pos[0] != WLAN_EID_ADV_PROTO ||
1650 pos[1] != 8 ||
1651 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1652 pos[4] != 5 ||
1653 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1654 pos[8] != 0x1a ||
1655 pos[9] != 1) {
1656 wpa_printf(MSG_DEBUG,
1657 "DPP: Not a DPP Advertisement Protocol ID");
1658 goto fail;
1659 }
1660
Hai Shalom899fcc72020-10-19 14:38:18 -07001661 res = dpp_conf_resp_rx(auth, resp);
1662#ifdef CONFIG_DPP2
1663 if (res == -2) {
1664 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1665 eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
1666 return;
1667 }
1668#endif /* CONFIG_DPP2 */
1669 if (res < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001670 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1671 goto fail;
1672 }
1673
Hai Shalom899fcc72020-10-19 14:38:18 -07001674 wpa_s->dpp_conf_backup_received = false;
Hai Shalomc3565922019-10-28 11:58:20 -07001675 for (i = 0; i < auth->num_conf_obj; i++) {
1676 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1677 &auth->conf_obj[i]);
1678 if (res < 0)
1679 goto fail;
1680 }
1681 if (auth->num_conf_obj)
1682 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001683 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1684 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001685
Hai Shalom021b0b52019-04-10 11:17:58 -07001686 status = DPP_STATUS_OK;
1687#ifdef CONFIG_TESTING_OPTIONS
1688 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1689 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1690 status = DPP_STATUS_CONFIG_REJECTED;
1691 }
1692#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001693fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001694 if (status != DPP_STATUS_OK) {
1695 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1696 wpas_notify_dpp_configuration_failure(wpa_s);
1697 }
1698#ifdef CONFIG_DPP2
1699 if (auth->peer_version >= 2 &&
1700 auth->conf_resp_status == DPP_STATUS_OK) {
1701 struct wpabuf *msg;
1702
1703 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1704 msg = dpp_build_conf_result(auth, status);
1705 if (!msg)
1706 goto fail2;
1707
1708 wpa_msg(wpa_s, MSG_INFO,
1709 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1710 MAC2STR(addr), auth->curr_freq,
1711 DPP_PA_CONFIGURATION_RESULT);
1712 offchannel_send_action(wpa_s, auth->curr_freq,
1713 addr, wpa_s->own_addr, broadcast,
1714 wpabuf_head(msg),
1715 wpabuf_len(msg),
1716 500, wpas_dpp_tx_status, 0);
1717 wpabuf_free(msg);
1718
1719 /* This exchange will be terminated in the TX status handler */
Hai Shalom899fcc72020-10-19 14:38:18 -07001720 if (wpa_s->conf->dpp_config_processing < 2 ||
1721 wpa_s->dpp_conf_backup_received)
1722 auth->remove_on_tx_status = 1;
Hai Shalom021b0b52019-04-10 11:17:58 -07001723 return;
1724 }
1725fail2:
1726#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001727 dpp_auth_deinit(wpa_s->dpp_auth);
1728 wpa_s->dpp_auth = NULL;
1729}
1730
1731
1732static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1733{
1734 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001735 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001736 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001737 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001738
1739 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001740 offchannel_send_action_done(wpa_s);
1741 wpas_dpp_listen_stop(wpa_s);
1742
Hai Shalomc3565922019-10-28 11:58:20 -07001743 supp_op_classes = wpas_supp_op_classes(wpa_s);
1744 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001745 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001746 wpa_s->conf->dpp_mud_url,
1747 supp_op_classes);
1748 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001749 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001750 wpa_printf(MSG_DEBUG,
1751 "DPP: No configuration request data available");
1752 return;
1753 }
1754
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001755 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1756 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1757
1758 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001759 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001760 if (res < 0) {
1761 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1762 wpabuf_free(buf);
1763 } else {
1764 wpa_printf(MSG_DEBUG,
1765 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001766 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001767 }
1768}
1769
1770
1771static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1772{
1773 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1774 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001775 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001776#ifdef CONFIG_TESTING_OPTIONS
1777 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1778 wpa_printf(MSG_INFO,
1779 "DPP: TESTING - stop at Authentication Confirm");
1780 if (wpa_s->dpp_auth->configurator) {
1781 /* Prevent GAS response */
1782 wpa_s->dpp_auth->auth_success = 0;
1783 }
1784 return;
1785 }
1786#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001787
1788 if (wpa_s->dpp_auth->configurator)
1789 wpas_dpp_start_gas_server(wpa_s);
1790 else
1791 wpas_dpp_start_gas_client(wpa_s);
1792}
1793
1794
1795static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001796 const u8 *hdr, const u8 *buf, size_t len,
1797 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001798{
1799 struct dpp_authentication *auth = wpa_s->dpp_auth;
1800 struct wpabuf *msg;
1801
Roshan Pius3a1667e2018-07-03 15:17:14 -07001802 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1803 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001804
1805 if (!auth) {
1806 wpa_printf(MSG_DEBUG,
1807 "DPP: No DPP Authentication in progress - drop");
1808 return;
1809 }
1810
1811 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1812 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1813 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1814 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1815 return;
1816 }
1817
1818 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1819
Roshan Pius3a1667e2018-07-03 15:17:14 -07001820 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1821 wpa_printf(MSG_DEBUG,
1822 "DPP: Responder accepted request for different negotiation channel");
1823 auth->curr_freq = freq;
1824 }
1825
1826 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001827 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1828 if (!msg) {
1829 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1830 wpa_printf(MSG_DEBUG,
1831 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001832 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001833 offchannel_send_action_done(wpa_s);
1834 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1835 return;
1836 }
1837 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1838 return;
1839 }
1840 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1841
Roshan Pius3a1667e2018-07-03 15:17:14 -07001842 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1843 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001844 offchannel_send_action(wpa_s, auth->curr_freq,
1845 src, wpa_s->own_addr, broadcast,
1846 wpabuf_head(msg), wpabuf_len(msg),
1847 500, wpas_dpp_tx_status, 0);
1848 wpabuf_free(msg);
1849 wpa_s->dpp_auth_ok_on_ack = 1;
1850}
1851
1852
1853static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1854 const u8 *hdr, const u8 *buf, size_t len)
1855{
1856 struct dpp_authentication *auth = wpa_s->dpp_auth;
1857
1858 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1859 MAC2STR(src));
1860
1861 if (!auth) {
1862 wpa_printf(MSG_DEBUG,
1863 "DPP: No DPP Authentication in progress - drop");
1864 return;
1865 }
1866
1867 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1868 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1869 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1870 return;
1871 }
1872
Hai Shalom60840252021-02-19 19:02:11 -08001873 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
1874
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001875 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1876 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001877 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001878 return;
1879 }
1880
1881 wpas_dpp_auth_success(wpa_s, 0);
1882}
1883
1884
Hai Shalom021b0b52019-04-10 11:17:58 -07001885#ifdef CONFIG_DPP2
1886
1887static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
1888 void *timeout_ctx)
1889{
1890 struct wpa_supplicant *wpa_s = eloop_ctx;
1891 struct dpp_authentication *auth = wpa_s->dpp_auth;
1892
1893 if (!auth || !auth->waiting_conf_result)
1894 return;
1895
1896 wpa_printf(MSG_DEBUG,
1897 "DPP: Timeout while waiting for Configuration Result");
1898 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001899 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07001900 dpp_auth_deinit(auth);
1901 wpa_s->dpp_auth = NULL;
1902}
1903
1904
Hai Shalomc3565922019-10-28 11:58:20 -07001905static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1906 void *timeout_ctx)
1907{
1908 struct wpa_supplicant *wpa_s = eloop_ctx;
1909 struct dpp_authentication *auth = wpa_s->dpp_auth;
1910
1911 if (!auth || !auth->waiting_conn_status_result)
1912 return;
1913
1914 wpa_printf(MSG_DEBUG,
1915 "DPP: Timeout while waiting for Connection Status Result");
1916 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08001917 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001918 wpas_dpp_listen_stop(wpa_s);
1919 dpp_auth_deinit(auth);
1920 wpa_s->dpp_auth = NULL;
1921}
1922
1923
Hai Shalom021b0b52019-04-10 11:17:58 -07001924static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
1925 const u8 *hdr, const u8 *buf, size_t len)
1926{
1927 struct dpp_authentication *auth = wpa_s->dpp_auth;
1928 enum dpp_status_error status;
1929
1930 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1931 MAC2STR(src));
1932
1933 if (!auth || !auth->waiting_conf_result) {
Hai Shalom60840252021-02-19 19:02:11 -08001934 if (auth &&
1935 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
1936 gas_server_response_sent(wpa_s->gas_server,
1937 auth->gas_server_ctx)) {
1938 /* This could happen if the TX status event gets delayed
1939 * long enough for the Enrollee to have time to send
1940 * the next frame before the TX status gets processed
1941 * locally. */
1942 wpa_printf(MSG_DEBUG,
1943 "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");
1944 auth->waiting_conf_result = 1;
1945 } else {
1946 wpa_printf(MSG_DEBUG,
1947 "DPP: No DPP Configuration waiting for result - drop");
1948 return;
1949 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001950 }
1951
1952 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1953 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1954 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1955 return;
1956 }
1957
1958 status = dpp_conf_result_rx(auth, hdr, buf, len);
1959
Hai Shalomc3565922019-10-28 11:58:20 -07001960 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1961 wpa_msg(wpa_s, MSG_INFO,
1962 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1963 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08001964 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001965 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
1966 wpa_s, NULL);
1967 auth->waiting_conn_status_result = 1;
1968 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1969 wpa_s, NULL);
1970 eloop_register_timeout(16, 0,
1971 wpas_dpp_conn_status_result_wait_timeout,
1972 wpa_s, NULL);
1973 offchannel_send_action_done(wpa_s);
1974 wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq :
1975 auth->curr_freq);
1976 return;
1977 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001978 offchannel_send_action_done(wpa_s);
1979 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001980 if (status == DPP_STATUS_OK) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001981 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalome4073332019-11-05 16:20:12 -08001982 wpas_notify_dpp_config_sent(wpa_s);
1983 }
1984 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07001985 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001986 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001987 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001988 dpp_auth_deinit(auth);
1989 wpa_s->dpp_auth = NULL;
1990 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
1991}
1992
Hai Shalom81f62d82019-07-22 12:10:00 -07001993
Hai Shalomc3565922019-10-28 11:58:20 -07001994static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
1995 const u8 *src, const u8 *hdr,
1996 const u8 *buf, size_t len)
1997{
1998 struct dpp_authentication *auth = wpa_s->dpp_auth;
1999 enum dpp_status_error status;
2000 u8 ssid[SSID_MAX_LEN];
2001 size_t ssid_len = 0;
2002 char *channel_list = NULL;
2003
2004 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
2005
2006 if (!auth || !auth->waiting_conn_status_result) {
2007 wpa_printf(MSG_DEBUG,
2008 "DPP: No DPP Configuration waiting for connection status result - drop");
2009 return;
2010 }
2011
2012 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
2013 ssid, &ssid_len, &channel_list);
2014 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
2015 "result=%d ssid=%s channel_list=%s",
2016 status, wpa_ssid_txt(ssid, ssid_len),
2017 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08002018 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
2019 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07002020 os_free(channel_list);
2021 offchannel_send_action_done(wpa_s);
2022 wpas_dpp_listen_stop(wpa_s);
2023 dpp_auth_deinit(auth);
2024 wpa_s->dpp_auth = NULL;
2025 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2026 wpa_s, NULL);
2027}
2028
2029
Hai Shalom81f62d82019-07-22 12:10:00 -07002030static int wpas_dpp_process_conf_obj(void *ctx,
2031 struct dpp_authentication *auth)
2032{
2033 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07002034 unsigned int i;
2035 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002036
Hai Shalomc3565922019-10-28 11:58:20 -07002037 for (i = 0; i < auth->num_conf_obj; i++) {
2038 res = wpas_dpp_handle_config_obj(wpa_s, auth,
2039 &auth->conf_obj[i]);
2040 if (res)
2041 break;
2042 }
2043 if (!res)
2044 wpas_dpp_post_process_config(wpa_s, auth);
2045
2046 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07002047}
2048
Hai Shalomfdcde762020-04-02 11:19:20 -07002049
2050static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
2051{
2052 struct wpa_supplicant *wpa_s = ctx;
2053
2054 if (bi == wpa_s->dpp_chirp_bi)
2055 wpas_dpp_chirp_stop(wpa_s);
2056}
2057
2058
2059static void
2060wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2061 const u8 *hdr, const u8 *buf, size_t len,
2062 unsigned int freq)
2063{
2064 const u8 *r_bootstrap;
2065 u16 r_bootstrap_len;
2066 struct dpp_bootstrap_info *peer_bi;
2067 struct dpp_authentication *auth;
2068
2069 if (!wpa_s->dpp)
2070 return;
2071
2072 if (wpa_s->dpp_auth) {
2073 wpa_printf(MSG_DEBUG,
2074 "DPP: Ignore Presence Announcement during ongoing Authentication");
2075 return;
2076 }
2077
2078 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
2079 MAC2STR(src));
2080
2081 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
2082 &r_bootstrap_len);
2083 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
2084 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2085 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
2086 return;
2087 }
2088 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
2089 r_bootstrap, r_bootstrap_len);
2090 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
Hai Shalom899fcc72020-10-19 14:38:18 -07002091 dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src,
2092 freq, r_bootstrap);
Hai Shalomfdcde762020-04-02 11:19:20 -07002093 if (!peer_bi) {
2094 wpa_printf(MSG_DEBUG,
2095 "DPP: No matching bootstrapping information found");
2096 return;
2097 }
2098
2099 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
2100 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
2101 if (!auth)
2102 return;
2103 wpas_dpp_set_testing_options(wpa_s, auth);
2104 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2105 dpp_auth_deinit(auth);
2106 return;
2107 }
2108
2109 auth->neg_freq = freq;
2110
Hai Shalom60840252021-02-19 19:02:11 -08002111 /* The source address of the Presence Announcement frame overrides any
2112 * MAC address information from the bootstrapping information. */
2113 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
Hai Shalomfdcde762020-04-02 11:19:20 -07002114
2115 wpa_s->dpp_auth = auth;
2116 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
2117 dpp_auth_deinit(wpa_s->dpp_auth);
2118 wpa_s->dpp_auth = NULL;
2119 }
2120}
2121
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002122
2123static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
2124 void *timeout_ctx)
2125{
2126 struct wpa_supplicant *wpa_s = eloop_ctx;
2127 struct dpp_authentication *auth = wpa_s->dpp_auth;
2128
2129 if (!auth)
2130 return;
2131
2132 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
2133 offchannel_send_action_done(wpa_s);
2134 wpas_dpp_listen_stop(wpa_s);
2135 dpp_auth_deinit(auth);
2136 wpa_s->dpp_auth = NULL;
2137}
2138
2139
2140static void
2141wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
2142 const u8 *hdr, const u8 *buf, size_t len,
2143 unsigned int freq)
2144{
Hai Shalom899fcc72020-10-19 14:38:18 -07002145 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
2146 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002147 struct dpp_configurator *conf;
2148 struct dpp_authentication *auth;
2149 unsigned int wait_time, max_wait_time;
Hai Shalom899fcc72020-10-19 14:38:18 -07002150 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002151
2152 if (!wpa_s->dpp)
2153 return;
2154
2155 if (wpa_s->dpp_auth) {
2156 wpa_printf(MSG_DEBUG,
2157 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
2158 return;
2159 }
2160
2161 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
2162 MAC2STR(src));
2163
2164 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
2165 &csign_hash_len);
2166 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
2167 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2168 "Missing or invalid required Configurator C-sign key Hash attribute");
2169 return;
2170 }
2171 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
2172 csign_hash, csign_hash_len);
2173 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
2174 if (!conf) {
2175 wpa_printf(MSG_DEBUG,
2176 "DPP: No matching Configurator information found");
2177 return;
2178 }
2179
Hai Shalom899fcc72020-10-19 14:38:18 -07002180 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
2181 &fcgroup_len);
2182 if (!fcgroup || fcgroup_len != 2) {
2183 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2184 "Missing or invalid required Finite Cyclic Group attribute");
2185 return;
2186 }
2187 group = WPA_GET_LE16(fcgroup);
2188 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
2189
2190 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
2191 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
2192
2193 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
2194 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002195 if (!auth)
2196 return;
2197 wpas_dpp_set_testing_options(wpa_s, auth);
2198 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
2199 dpp_auth_deinit(auth);
2200 return;
2201 }
2202
2203 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2204 wpa_s->dpp_auth = auth;
2205
2206 wpa_s->dpp_in_response_listen = 0;
2207 wpa_s->dpp_auth_ok_on_ack = 0;
2208 wait_time = wpa_s->max_remain_on_chan;
2209 max_wait_time = wpa_s->dpp_resp_wait_time ?
2210 wpa_s->dpp_resp_wait_time : 2000;
2211 if (wait_time > max_wait_time)
2212 wait_time = max_wait_time;
2213 wait_time += 10; /* give the driver some extra time to complete */
2214 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
2215 wpas_dpp_reconfig_reply_wait_timeout,
2216 wpa_s, NULL);
2217 wait_time -= 10;
2218
2219 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
2220
2221 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2222 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
2223 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2224 wpabuf_head(auth->reconfig_req_msg),
2225 wpabuf_len(auth->reconfig_req_msg),
2226 wait_time, wpas_dpp_tx_status, 0) < 0) {
2227 dpp_auth_deinit(wpa_s->dpp_auth);
2228 wpa_s->dpp_auth = NULL;
2229 }
2230}
2231
2232
2233static void
2234wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
2235 const u8 *hdr, const u8 *buf, size_t len,
2236 unsigned int freq)
2237{
2238 struct wpa_ssid *ssid;
2239 struct dpp_authentication *auth;
2240
2241 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
2242 MACSTR, MAC2STR(src));
2243
Hai Shalom899fcc72020-10-19 14:38:18 -07002244 if (!wpa_s->dpp)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002245 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002246 if (wpa_s->dpp_auth) {
2247 wpa_printf(MSG_DEBUG,
2248 "DPP: Not ready for reconfiguration - pending authentication exchange in progress");
2249 return;
2250 }
2251 if (!wpa_s->dpp_reconfig_ssid) {
2252 wpa_printf(MSG_DEBUG,
2253 "DPP: Not ready for reconfiguration - not requested");
2254 return;
2255 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002256 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2257 if (ssid == wpa_s->dpp_reconfig_ssid &&
2258 ssid->id == wpa_s->dpp_reconfig_ssid_id)
2259 break;
2260 }
2261 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
Hai Shalom899fcc72020-10-19 14:38:18 -07002262 !ssid->dpp_csign) {
2263 wpa_printf(MSG_DEBUG,
2264 "DPP: Not ready for reconfiguration - no matching network profile with Connector found");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002265 return;
Hai Shalom899fcc72020-10-19 14:38:18 -07002266 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002267
2268 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
2269 ssid->dpp_netaccesskey,
2270 ssid->dpp_netaccesskey_len,
2271 ssid->dpp_csign, ssid->dpp_csign_len,
2272 freq, hdr, buf, len);
2273 if (!auth)
2274 return;
2275 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
2276 wpa_s->dpp_auth = auth;
2277
2278 wpas_dpp_chirp_stop(wpa_s);
2279
2280 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2281 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
2282 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2283 wpabuf_head(auth->reconfig_resp_msg),
2284 wpabuf_len(auth->reconfig_resp_msg),
2285 500, wpas_dpp_tx_status, 0) < 0) {
2286 dpp_auth_deinit(wpa_s->dpp_auth);
2287 wpa_s->dpp_auth = NULL;
2288 }
2289}
2290
2291
2292static void
2293wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2294 const u8 *hdr, const u8 *buf, size_t len,
2295 unsigned int freq)
2296{
2297 struct dpp_authentication *auth = wpa_s->dpp_auth;
2298 struct wpabuf *conf;
2299
2300 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2301 MACSTR, MAC2STR(src));
2302
2303 if (!auth || !auth->reconfig || !auth->configurator) {
2304 wpa_printf(MSG_DEBUG,
2305 "DPP: No DPP Reconfig Authentication in progress - drop");
2306 return;
2307 }
2308
2309 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2310 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2311 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2312 return;
2313 }
2314
2315 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2316 if (!conf)
2317 return;
2318
2319 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2320
2321 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2322 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2323 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2324 wpabuf_head(conf), wpabuf_len(conf),
2325 500, wpas_dpp_tx_status, 0) < 0) {
2326 wpabuf_free(conf);
2327 dpp_auth_deinit(wpa_s->dpp_auth);
2328 wpa_s->dpp_auth = NULL;
2329 return;
2330 }
2331 wpabuf_free(conf);
2332
2333 wpas_dpp_start_gas_server(wpa_s);
2334}
2335
2336
2337static void
2338wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2339 const u8 *hdr, const u8 *buf, size_t len,
2340 unsigned int freq)
2341{
2342 struct dpp_authentication *auth = wpa_s->dpp_auth;
2343
2344 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2345 MACSTR, MAC2STR(src));
2346
2347 if (!auth || !auth->reconfig || auth->configurator) {
2348 wpa_printf(MSG_DEBUG,
2349 "DPP: No DPP Reconfig Authentication in progress - drop");
2350 return;
2351 }
2352
2353 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2354 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2355 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2356 return;
2357 }
2358
2359 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2360 return;
2361
2362 wpas_dpp_start_gas_client(wpa_s);
2363}
2364
Hai Shalom021b0b52019-04-10 11:17:58 -07002365#endif /* CONFIG_DPP2 */
2366
2367
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002368static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2369 const u8 *src,
2370 const u8 *buf, size_t len)
2371{
2372 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002373 const u8 *connector, *trans_id, *status;
2374 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002375#ifdef CONFIG_DPP2
2376 const u8 *version;
2377 u16 version_len;
2378#endif /* CONFIG_DPP2 */
2379 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002380 struct dpp_introduction intro;
2381 struct rsn_pmksa_cache_entry *entry;
2382 struct os_time now;
2383 struct os_reltime rnow;
2384 os_time_t expiry;
2385 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002386 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002387
2388 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2389 MAC2STR(src));
2390 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2391 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2392 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2393 MACSTR " - drop", MAC2STR(src));
2394 return;
2395 }
2396 offchannel_send_action_done(wpa_s);
2397
2398 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2399 if (ssid == wpa_s->dpp_intro_network)
2400 break;
2401 }
2402 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2403 !ssid->dpp_csign) {
2404 wpa_printf(MSG_DEBUG,
2405 "DPP: Profile not found for network introduction");
2406 return;
2407 }
2408
2409 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2410 &trans_id_len);
2411 if (!trans_id || trans_id_len != 1) {
2412 wpa_printf(MSG_DEBUG,
2413 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002414 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2415 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002416 goto fail;
2417 }
2418 if (trans_id[0] != TRANSACTION_ID) {
2419 wpa_printf(MSG_DEBUG,
2420 "DPP: Ignore frame with unexpected Transaction ID %u",
2421 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002422 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2423 " fail=transaction_id_mismatch", MAC2STR(src));
2424 goto fail;
2425 }
2426
2427 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2428 if (!status || status_len != 1) {
2429 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2430 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2431 " fail=missing_status", MAC2STR(src));
2432 goto fail;
2433 }
2434 if (status[0] != DPP_STATUS_OK) {
2435 wpa_printf(MSG_DEBUG,
2436 "DPP: Peer rejected network introduction: Status %u",
2437 status[0]);
2438 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2439 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002440#ifdef CONFIG_DPP2
2441 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2442#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002443 goto fail;
2444 }
2445
2446 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2447 if (!connector) {
2448 wpa_printf(MSG_DEBUG,
2449 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002450 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2451 " fail=missing_connector", MAC2STR(src));
2452 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002453 }
2454
Roshan Pius3a1667e2018-07-03 15:17:14 -07002455 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2456 ssid->dpp_netaccesskey,
2457 ssid->dpp_netaccesskey_len,
2458 ssid->dpp_csign,
2459 ssid->dpp_csign_len,
2460 connector, connector_len, &expiry);
2461 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002462 wpa_printf(MSG_INFO,
2463 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002464 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2465 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002466#ifdef CONFIG_DPP2
2467 wpas_dpp_send_conn_status_result(wpa_s, res);
2468#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002469 goto fail;
2470 }
2471
2472 entry = os_zalloc(sizeof(*entry));
2473 if (!entry)
2474 goto fail;
2475 os_memcpy(entry->aa, src, ETH_ALEN);
2476 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2477 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2478 entry->pmk_len = intro.pmk_len;
2479 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002480#ifdef CONFIG_DPP2
2481 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2482 &version_len);
2483 if (version && version_len >= 1)
2484 peer_version = version[0];
2485 entry->dpp_pfs = peer_version >= 2;
2486#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002487 if (expiry) {
2488 os_get_time(&now);
2489 seconds = expiry - now.sec;
2490 } else {
2491 seconds = 86400 * 7;
2492 }
2493 os_get_reltime(&rnow);
2494 entry->expiration = rnow.sec + seconds;
2495 entry->reauth_time = rnow.sec + seconds;
2496 entry->network_ctx = ssid;
2497 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2498
Roshan Pius3a1667e2018-07-03 15:17:14 -07002499 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002500 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002501
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002502 wpa_printf(MSG_DEBUG,
2503 "DPP: Try connection again after successful network introduction");
2504 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2505 wpa_supplicant_cancel_sched_scan(wpa_s);
2506 wpa_supplicant_req_scan(wpa_s, 0, 0);
2507 }
2508fail:
2509 os_memset(&intro, 0, sizeof(intro));
2510}
2511
2512
Roshan Pius3a1667e2018-07-03 15:17:14 -07002513static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2514{
2515 int i, j;
2516
2517 if (!wpa_s->hw.modes)
2518 return -1;
2519
2520 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2521 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2522
2523 for (j = 0; j < mode->num_channels; j++) {
2524 struct hostapd_channel_data *chan = &mode->channels[j];
2525
2526 if (chan->freq != (int) freq)
2527 continue;
2528
2529 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2530 HOSTAPD_CHAN_NO_IR |
2531 HOSTAPD_CHAN_RADAR))
2532 continue;
2533
2534 return 1;
2535 }
2536 }
2537
2538 wpa_printf(MSG_DEBUG,
2539 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2540 freq);
2541
2542 return 0;
2543}
2544
2545
2546static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2547 struct dpp_pkex *pkex)
2548{
2549 if (pkex->freq == 2437)
2550 pkex->freq = 5745;
2551 else if (pkex->freq == 5745)
2552 pkex->freq = 5220;
2553 else if (pkex->freq == 5220)
2554 pkex->freq = 60480;
2555 else
2556 return -1; /* no more channels to try */
2557
2558 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2559 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2560 pkex->freq);
2561 return 0;
2562 }
2563
2564 /* Could not use this channel - try the next one */
2565 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2566}
2567
2568
2569static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
2570{
2571 struct wpa_supplicant *wpa_s = eloop_ctx;
2572 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2573
2574 if (!pkex || !pkex->exchange_req)
2575 return;
2576 if (pkex->exch_req_tries >= 5) {
2577 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
2578 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2579 "No response from PKEX peer");
2580 dpp_pkex_free(pkex);
2581 wpa_s->dpp_pkex = NULL;
2582 return;
2583 }
2584 pkex->exch_req_tries = 0;
2585 }
2586
2587 pkex->exch_req_tries++;
2588 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
2589 pkex->exch_req_tries);
2590 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2591 MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
2592 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2593 wpa_s->own_addr, broadcast,
2594 wpabuf_head(pkex->exchange_req),
2595 wpabuf_len(pkex->exchange_req),
2596 pkex->exch_req_wait_time,
2597 wpas_dpp_tx_pkex_status, 0);
2598}
2599
2600
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002601static void
2602wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
2603 unsigned int freq, const u8 *dst,
2604 const u8 *src, const u8 *bssid,
2605 const u8 *data, size_t data_len,
2606 enum offchannel_send_action_result result)
2607{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002608 const char *res_txt;
2609 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2610
2611 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2612 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2613 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002614 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2615 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002616 freq, MAC2STR(dst), res_txt);
2617 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2618 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
2619
2620 if (!pkex) {
2621 wpa_printf(MSG_DEBUG,
2622 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
2623 return;
2624 }
2625
2626 if (pkex->failed) {
2627 wpa_printf(MSG_DEBUG,
2628 "DPP: Terminate PKEX exchange due to an earlier error");
2629 if (pkex->t > pkex->own_bi->pkex_t)
2630 pkex->own_bi->pkex_t = pkex->t;
2631 dpp_pkex_free(pkex);
2632 wpa_s->dpp_pkex = NULL;
2633 return;
2634 }
2635
2636 if (pkex->exch_req_wait_time && pkex->exchange_req) {
2637 /* Wait for PKEX Exchange Response frame and retry request if
2638 * no response is seen. */
2639 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
2640 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
2641 (pkex->exch_req_wait_time % 1000) * 1000,
2642 wpas_dpp_pkex_retry_timeout, wpa_s,
2643 NULL);
2644 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002645}
2646
2647
2648static void
2649wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
2650 const u8 *buf, size_t len, unsigned int freq)
2651{
2652 struct wpabuf *msg;
2653 unsigned int wait_time;
2654
2655 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
2656 MAC2STR(src));
2657
2658 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2659 * values here */
2660
2661 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
2662 wpa_printf(MSG_DEBUG,
2663 "DPP: No PKEX code configured - ignore request");
2664 return;
2665 }
2666
2667 if (wpa_s->dpp_pkex) {
2668 /* TODO: Support parallel operations */
2669 wpa_printf(MSG_DEBUG,
2670 "DPP: Already in PKEX session - ignore new request");
2671 return;
2672 }
2673
Roshan Pius3a1667e2018-07-03 15:17:14 -07002674 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002675 wpa_s->own_addr, src,
2676 wpa_s->dpp_pkex_identifier,
2677 wpa_s->dpp_pkex_code,
2678 buf, len);
2679 if (!wpa_s->dpp_pkex) {
2680 wpa_printf(MSG_DEBUG,
2681 "DPP: Failed to process the request - ignore it");
2682 return;
2683 }
2684
2685 msg = wpa_s->dpp_pkex->exchange_resp;
2686 wait_time = wpa_s->max_remain_on_chan;
2687 if (wait_time > 2000)
2688 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002689 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2690 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002691 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2692 broadcast,
2693 wpabuf_head(msg), wpabuf_len(msg),
2694 wait_time, wpas_dpp_tx_pkex_status, 0);
2695}
2696
2697
2698static void
2699wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2700 const u8 *buf, size_t len, unsigned int freq)
2701{
2702 struct wpabuf *msg;
2703 unsigned int wait_time;
2704
2705 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2706 MAC2STR(src));
2707
2708 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2709 * values here */
2710
2711 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
2712 wpa_s->dpp_pkex->exchange_done) {
2713 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2714 return;
2715 }
2716
Roshan Pius3a1667e2018-07-03 15:17:14 -07002717 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
2718 wpa_s->dpp_pkex->exch_req_wait_time = 0;
2719
2720 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002721 if (!msg) {
2722 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2723 return;
2724 }
2725
2726 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
2727 MAC2STR(src));
2728
2729 wait_time = wpa_s->max_remain_on_chan;
2730 if (wait_time > 2000)
2731 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002732 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2733 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002734 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2735 broadcast,
2736 wpabuf_head(msg), wpabuf_len(msg),
2737 wait_time, wpas_dpp_tx_pkex_status, 0);
2738 wpabuf_free(msg);
2739}
2740
2741
Roshan Pius3a1667e2018-07-03 15:17:14 -07002742static struct dpp_bootstrap_info *
2743wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
2744 unsigned int freq)
2745{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002746 struct dpp_bootstrap_info *bi;
2747
Hai Shalom021b0b52019-04-10 11:17:58 -07002748 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002749 if (!bi)
2750 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002751 wpa_s->dpp_pkex = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002752 return bi;
2753}
2754
2755
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002756static void
2757wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
2758 const u8 *hdr, const u8 *buf, size_t len,
2759 unsigned int freq)
2760{
2761 struct wpabuf *msg;
2762 unsigned int wait_time;
2763 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002764
2765 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
2766 MAC2STR(src));
2767
2768 if (!pkex || pkex->initiator || !pkex->exchange_done) {
2769 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2770 return;
2771 }
2772
2773 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
2774 if (!msg) {
2775 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002776 if (pkex->failed) {
2777 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
2778 if (pkex->t > pkex->own_bi->pkex_t)
2779 pkex->own_bi->pkex_t = pkex->t;
2780 dpp_pkex_free(wpa_s->dpp_pkex);
2781 wpa_s->dpp_pkex = NULL;
2782 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002783 return;
2784 }
2785
2786 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
2787 MACSTR, MAC2STR(src));
2788
2789 wait_time = wpa_s->max_remain_on_chan;
2790 if (wait_time > 2000)
2791 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002792 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2793 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002794 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2795 broadcast,
2796 wpabuf_head(msg), wpabuf_len(msg),
2797 wait_time, wpas_dpp_tx_pkex_status, 0);
2798 wpabuf_free(msg);
2799
Roshan Pius3a1667e2018-07-03 15:17:14 -07002800 wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002801}
2802
2803
2804static void
2805wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2806 const u8 *hdr, const u8 *buf, size_t len,
2807 unsigned int freq)
2808{
2809 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002810 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002811 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2812 char cmd[500];
2813
2814 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2815 MAC2STR(src));
2816
2817 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2818 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2819 return;
2820 }
2821
2822 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2823 if (res < 0) {
2824 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2825 return;
2826 }
2827
Roshan Pius3a1667e2018-07-03 15:17:14 -07002828 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002829 if (!bi)
2830 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002831
2832 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2833 bi->id,
2834 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
2835 wpa_printf(MSG_DEBUG,
2836 "DPP: Start authentication after PKEX with parameters: %s",
2837 cmd);
2838 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
2839 wpa_printf(MSG_DEBUG,
2840 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07002841 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002842 return;
2843 }
2844}
2845
2846
2847void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
2848 const u8 *buf, size_t len, unsigned int freq)
2849{
2850 u8 crypto_suite;
2851 enum dpp_public_action_frame_type type;
2852 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002853 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002854
2855 if (len < DPP_HDR_LEN)
2856 return;
2857 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2858 return;
2859 hdr = buf;
2860 buf += 4;
2861 len -= 4;
2862 crypto_suite = *buf++;
2863 type = *buf++;
2864 len -= 2;
2865
2866 wpa_printf(MSG_DEBUG,
2867 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2868 MACSTR " freq=%u",
2869 crypto_suite, type, MAC2STR(src), freq);
2870 if (crypto_suite != 1) {
2871 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2872 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002873 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2874 " freq=%u type=%d ignore=unsupported-crypto-suite",
2875 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002876 return;
2877 }
2878 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002879 if (dpp_check_attrs(buf, len) < 0) {
2880 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2881 " freq=%u type=%d ignore=invalid-attributes",
2882 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002883 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002884 }
2885 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
2886 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002887
2888 switch (type) {
2889 case DPP_PA_AUTHENTICATION_REQ:
2890 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
2891 break;
2892 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002893 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002894 break;
2895 case DPP_PA_AUTHENTICATION_CONF:
2896 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
2897 break;
2898 case DPP_PA_PEER_DISCOVERY_RESP:
2899 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
2900 break;
2901 case DPP_PA_PKEX_EXCHANGE_REQ:
2902 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
2903 break;
2904 case DPP_PA_PKEX_EXCHANGE_RESP:
2905 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
2906 break;
2907 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2908 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
2909 freq);
2910 break;
2911 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2912 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
2913 freq);
2914 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002915#ifdef CONFIG_DPP2
2916 case DPP_PA_CONFIGURATION_RESULT:
2917 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
2918 break;
Hai Shalomc3565922019-10-28 11:58:20 -07002919 case DPP_PA_CONNECTION_STATUS_RESULT:
2920 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
2921 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07002922 case DPP_PA_PRESENCE_ANNOUNCEMENT:
2923 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
2924 freq);
2925 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002926 case DPP_PA_RECONFIG_ANNOUNCEMENT:
2927 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
2928 freq);
2929 break;
2930 case DPP_PA_RECONFIG_AUTH_REQ:
2931 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
2932 break;
2933 case DPP_PA_RECONFIG_AUTH_RESP:
2934 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
2935 break;
2936 case DPP_PA_RECONFIG_AUTH_CONF:
2937 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
2938 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002939#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002940 default:
2941 wpa_printf(MSG_DEBUG,
2942 "DPP: Ignored unsupported frame subtype %d", type);
2943 break;
2944 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002945
2946 if (wpa_s->dpp_pkex)
2947 pkex_t = wpa_s->dpp_pkex->t;
2948 else if (wpa_s->dpp_pkex_bi)
2949 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
2950 else
2951 pkex_t = 0;
2952 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2953 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2954 wpas_dpp_pkex_remove(wpa_s, "*");
2955 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002956}
2957
2958
2959static struct wpabuf *
Hai Shalom899fcc72020-10-19 14:38:18 -07002960wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
2961 const u8 *query, size_t query_len, u16 *comeback_delay)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002962{
2963 struct wpa_supplicant *wpa_s = ctx;
2964 struct dpp_authentication *auth = wpa_s->dpp_auth;
2965 struct wpabuf *resp;
2966
2967 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
2968 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002969 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002970 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
2971 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2972 return NULL;
2973 }
Hai Shalomc3565922019-10-28 11:58:20 -07002974
2975 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
2976 wpa_printf(MSG_DEBUG,
2977 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
2978 /* wpas_dpp_auth_success() would normally have been called from
2979 * TX status handler, but since there was no such handler call
2980 * yet, simply send out the event message and proceed with
2981 * exchange. */
2982 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
2983 wpa_s->dpp_auth_ok_on_ack = 0;
2984 }
2985
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002986 wpa_hexdump(MSG_DEBUG,
2987 "DPP: Received Configuration Request (GAS Query Request)",
2988 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002989 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2990 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002991 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07002992
2993#ifdef CONFIG_DPP2
2994 if (!resp && auth->waiting_cert) {
2995 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
2996 auth->cert_resp_ctx = resp_ctx;
2997 *comeback_delay = 500;
2998 return NULL;
2999 }
3000#endif /* CONFIG_DPP2 */
3001
Hai Shalom59532852018-12-07 10:32:58 -08003002 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003003 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08003004 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003005 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003006 auth->conf_resp = resp;
Hai Shalom60840252021-02-19 19:02:11 -08003007 auth->gas_server_ctx = resp_ctx;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003008 return resp;
3009}
3010
3011
3012static void
3013wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
3014{
3015 struct wpa_supplicant *wpa_s = ctx;
3016 struct dpp_authentication *auth = wpa_s->dpp_auth;
3017
3018 if (!auth) {
3019 wpabuf_free(resp);
3020 return;
3021 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003022 if (auth->conf_resp != resp) {
3023 wpa_printf(MSG_DEBUG,
3024 "DPP: Ignore GAS status report (ok=%d) for unknown response",
3025 ok);
3026 wpabuf_free(resp);
3027 return;
3028 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003029
Hai Shalom899fcc72020-10-19 14:38:18 -07003030#ifdef CONFIG_DPP2
3031 if (auth->waiting_csr && ok) {
3032 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
3033 wpabuf_free(resp);
3034 return;
3035 }
3036#endif /* CONFIG_DPP2 */
3037
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003038 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
3039 ok);
3040 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003041 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003042 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003043#ifdef CONFIG_DPP2
3044 if (ok && auth->peer_version >= 2 &&
Hai Shalom60840252021-02-19 19:02:11 -08003045 auth->conf_resp_status == DPP_STATUS_OK &&
3046 !auth->waiting_conf_result) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003047 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08003048 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003049 auth->waiting_conf_result = 1;
3050 auth->conf_resp = NULL;
3051 wpabuf_free(resp);
3052 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
3053 wpa_s, NULL);
3054 eloop_register_timeout(2, 0,
3055 wpas_dpp_config_result_wait_timeout,
3056 wpa_s, NULL);
3057 return;
3058 }
3059#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003060 offchannel_send_action_done(wpa_s);
3061 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003062 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003063 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08003064 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003065 }
3066 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003067 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08003068 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08003069 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003070 dpp_auth_deinit(wpa_s->dpp_auth);
3071 wpa_s->dpp_auth = NULL;
3072 wpabuf_free(resp);
3073}
3074
3075
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003076int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
3077{
3078 struct dpp_authentication *auth;
3079 int ret = -1;
3080 char *curve = NULL;
3081
Hai Shalomfdcde762020-04-02 11:19:20 -07003082 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003083 if (!auth)
3084 return -1;
3085
3086 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08003087 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07003088 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07003089 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07003090 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
3091 &auth->conf_obj[0]);
3092 if (!ret)
3093 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003094
3095 dpp_auth_deinit(auth);
3096 os_free(curve);
3097
3098 return ret;
3099}
3100
3101
3102static void
3103wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
3104 unsigned int freq, const u8 *dst,
3105 const u8 *src, const u8 *bssid,
3106 const u8 *data, size_t data_len,
3107 enum offchannel_send_action_result result)
3108{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003109 const char *res_txt;
3110
3111 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
3112 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
3113 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003114 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
3115 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07003116 freq, MAC2STR(dst), res_txt);
3117 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
3118 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003119 /* TODO: Time out wait for response more quickly in error cases? */
3120}
3121
3122
3123int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
3124 struct wpa_bss *bss)
3125{
3126 struct os_time now;
3127 struct wpabuf *msg;
3128 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07003129 const u8 *rsn;
3130 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003131 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003132
3133 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
3134 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07003135 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
3136 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
3137 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
3138 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003139 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
3140 return 0; /* PMKSA exists for DPP AKM - continue */
3141
3142 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3143 !ssid->dpp_csign) {
3144 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
3145 "missing %s",
3146 !ssid->dpp_connector ? "Connector" :
3147 (!ssid->dpp_netaccesskey ? "netAccessKey" :
3148 "C-sign-key"));
3149 return -1;
3150 }
3151
3152 os_get_time(&now);
3153
3154 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07003155 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003156 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
3157 "netAccessKey expired");
3158 return -1;
3159 }
3160
3161 wpa_printf(MSG_DEBUG,
3162 "DPP: Starting network introduction protocol to derive PMKSA for "
3163 MACSTR, MAC2STR(bss->bssid));
3164
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003165 len = 5 + 4 + os_strlen(ssid->dpp_connector);
3166#ifdef CONFIG_DPP2
3167 len += 5;
3168#endif /* CONFIG_DPP2 */
3169 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003170 if (!msg)
3171 return -1;
3172
Roshan Pius3a1667e2018-07-03 15:17:14 -07003173#ifdef CONFIG_TESTING_OPTIONS
3174 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
3175 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
3176 goto skip_trans_id;
3177 }
3178 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
3179 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
3180 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3181 wpabuf_put_le16(msg, 0);
3182 goto skip_trans_id;
3183 }
3184#endif /* CONFIG_TESTING_OPTIONS */
3185
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003186 /* Transaction ID */
3187 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
3188 wpabuf_put_le16(msg, 1);
3189 wpabuf_put_u8(msg, TRANSACTION_ID);
3190
Roshan Pius3a1667e2018-07-03 15:17:14 -07003191#ifdef CONFIG_TESTING_OPTIONS
3192skip_trans_id:
3193 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
3194 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
3195 goto skip_connector;
3196 }
3197 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
3198 char *connector;
3199
3200 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
3201 connector = dpp_corrupt_connector_signature(
3202 ssid->dpp_connector);
3203 if (!connector) {
3204 wpabuf_free(msg);
3205 return -1;
3206 }
3207 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
3208 wpabuf_put_le16(msg, os_strlen(connector));
3209 wpabuf_put_str(msg, connector);
3210 os_free(connector);
3211 goto skip_connector;
3212 }
3213#endif /* CONFIG_TESTING_OPTIONS */
3214
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003215 /* DPP Connector */
3216 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
3217 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
3218 wpabuf_put_str(msg, ssid->dpp_connector);
3219
Roshan Pius3a1667e2018-07-03 15:17:14 -07003220#ifdef CONFIG_TESTING_OPTIONS
3221skip_connector:
3222#endif /* CONFIG_TESTING_OPTIONS */
3223
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003224#ifdef CONFIG_DPP2
3225 if (DPP_VERSION > 1) {
3226 /* Protocol Version */
3227 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
3228 wpabuf_put_le16(msg, 1);
3229 wpabuf_put_u8(msg, DPP_VERSION);
3230 }
3231#endif /* CONFIG_DPP2 */
3232
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003233 /* TODO: Timeout on AP response */
3234 wait_time = wpa_s->max_remain_on_chan;
3235 if (wait_time > 2000)
3236 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003237 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
3238 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003239 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
3240 broadcast,
3241 wpabuf_head(msg), wpabuf_len(msg),
3242 wait_time, wpas_dpp_tx_introduction_status, 0);
3243 wpabuf_free(msg);
3244
3245 /* Request this connection attempt to terminate - new one will be
3246 * started when network introduction protocol completes */
3247 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
3248 wpa_s->dpp_intro_network = ssid;
3249 return 1;
3250}
3251
3252
3253int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
3254{
3255 struct dpp_bootstrap_info *own_bi;
3256 const char *pos, *end;
3257 unsigned int wait_time;
3258
3259 pos = os_strstr(cmd, " own=");
3260 if (!pos)
3261 return -1;
3262 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07003263 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003264 if (!own_bi) {
3265 wpa_printf(MSG_DEBUG,
3266 "DPP: Identified bootstrap info not found");
3267 return -1;
3268 }
3269 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
3270 wpa_printf(MSG_DEBUG,
3271 "DPP: Identified bootstrap info not for PKEX");
3272 return -1;
3273 }
3274 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003275 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003276
3277 os_free(wpa_s->dpp_pkex_identifier);
3278 wpa_s->dpp_pkex_identifier = NULL;
3279 pos = os_strstr(cmd, " identifier=");
3280 if (pos) {
3281 pos += 12;
3282 end = os_strchr(pos, ' ');
3283 if (!end)
3284 return -1;
3285 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
3286 if (!wpa_s->dpp_pkex_identifier)
3287 return -1;
3288 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
3289 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
3290 }
3291
3292 pos = os_strstr(cmd, " code=");
3293 if (!pos)
3294 return -1;
3295 os_free(wpa_s->dpp_pkex_code);
3296 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
3297 if (!wpa_s->dpp_pkex_code)
3298 return -1;
3299
3300 if (os_strstr(cmd, " init=1")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003301 struct dpp_pkex *pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003302 struct wpabuf *msg;
3303
3304 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
3305 dpp_pkex_free(wpa_s->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003306 wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003307 wpa_s->dpp_pkex_identifier,
3308 wpa_s->dpp_pkex_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003309 pkex = wpa_s->dpp_pkex;
3310 if (!pkex)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003311 return -1;
3312
Roshan Pius3a1667e2018-07-03 15:17:14 -07003313 msg = pkex->exchange_req;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003314 wait_time = wpa_s->max_remain_on_chan;
3315 if (wait_time > 2000)
3316 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003317 pkex->freq = 2437;
3318 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3319 " freq=%u type=%d",
3320 MAC2STR(broadcast), pkex->freq,
3321 DPP_PA_PKEX_EXCHANGE_REQ);
3322 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3323 wpa_s->own_addr, broadcast,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003324 wpabuf_head(msg), wpabuf_len(msg),
3325 wait_time, wpas_dpp_tx_pkex_status, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003326 if (wait_time == 0)
3327 wait_time = 2000;
3328 pkex->exch_req_wait_time = wait_time;
3329 pkex->exch_req_tries = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003330 }
3331
3332 /* TODO: Support multiple PKEX info entries */
3333
3334 os_free(wpa_s->dpp_pkex_auth_cmd);
3335 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
3336
3337 return 1;
3338}
3339
3340
3341int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
3342{
3343 unsigned int id_val;
3344
3345 if (os_strcmp(id, "*") == 0) {
3346 id_val = 0;
3347 } else {
3348 id_val = atoi(id);
3349 if (id_val == 0)
3350 return -1;
3351 }
3352
3353 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
3354 return -1;
3355
3356 /* TODO: Support multiple PKEX entries */
3357 os_free(wpa_s->dpp_pkex_code);
3358 wpa_s->dpp_pkex_code = NULL;
3359 os_free(wpa_s->dpp_pkex_identifier);
3360 wpa_s->dpp_pkex_identifier = NULL;
3361 os_free(wpa_s->dpp_pkex_auth_cmd);
3362 wpa_s->dpp_pkex_auth_cmd = NULL;
3363 wpa_s->dpp_pkex_bi = NULL;
3364 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
3365 dpp_pkex_free(wpa_s->dpp_pkex);
3366 wpa_s->dpp_pkex = NULL;
3367 return 0;
3368}
3369
3370
Roshan Pius3a1667e2018-07-03 15:17:14 -07003371void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
3372{
Hai Shalomfdcde762020-04-02 11:19:20 -07003373 if (wpa_s->dpp_auth || wpa_s->dpp_pkex)
3374 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003375 dpp_auth_deinit(wpa_s->dpp_auth);
3376 wpa_s->dpp_auth = NULL;
3377 dpp_pkex_free(wpa_s->dpp_pkex);
3378 wpa_s->dpp_pkex = NULL;
3379 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
3380 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
3381}
3382
3383
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003384int wpas_dpp_init(struct wpa_supplicant *wpa_s)
3385{
Hai Shalom81f62d82019-07-22 12:10:00 -07003386 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003387 u8 adv_proto_id[7];
3388
3389 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
3390 adv_proto_id[1] = 5;
3391 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
3392 adv_proto_id[5] = DPP_OUI_TYPE;
3393 adv_proto_id[6] = 0x01;
3394
3395 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
3396 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
3397 wpas_dpp_gas_status_handler, wpa_s) < 0)
3398 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07003399
3400 os_memset(&config, 0, sizeof(config));
Hai Shalom81f62d82019-07-22 12:10:00 -07003401 config.cb_ctx = wpa_s;
3402#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003403 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07003404#endif /* CONFIG_DPP2 */
3405 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07003406 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003407}
3408
3409
3410void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
3411{
3412#ifdef CONFIG_TESTING_OPTIONS
3413 os_free(wpa_s->dpp_config_obj_override);
3414 wpa_s->dpp_config_obj_override = NULL;
3415 os_free(wpa_s->dpp_discovery_override);
3416 wpa_s->dpp_discovery_override = NULL;
3417 os_free(wpa_s->dpp_groups_override);
3418 wpa_s->dpp_groups_override = NULL;
3419 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
3420#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07003421 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003422 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003423 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003424 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Hai Shalom60840252021-02-19 19:02:11 -08003425 eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003426 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
3427 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003428#ifdef CONFIG_DPP2
3429 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07003430 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
3431 wpa_s, NULL);
3432 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003433 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
3434 wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07003435 eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003436 dpp_pfs_free(wpa_s->dpp_pfs);
3437 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07003438 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07003439 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
3440 wpa_s->dpp_reconfig_id = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07003441#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003442 offchannel_send_action_done(wpa_s);
3443 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003444 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003445 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003446 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
3447 os_free(wpa_s->dpp_configurator_params);
3448 wpa_s->dpp_configurator_params = NULL;
Hai Shalom899fcc72020-10-19 14:38:18 -07003449 dpp_global_clear(wpa_s->dpp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003450}
Hai Shalom81f62d82019-07-22 12:10:00 -07003451
3452
3453#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003454
Hai Shalom81f62d82019-07-22 12:10:00 -07003455int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
3456{
3457 struct dpp_controller_config config;
3458 const char *pos;
3459
3460 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003461 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom899fcc72020-10-19 14:38:18 -07003462 config.netrole = DPP_NETROLE_STA;
3463 config.msg_ctx = wpa_s;
3464 config.cb_ctx = wpa_s;
3465 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shalom81f62d82019-07-22 12:10:00 -07003466 if (cmd) {
3467 pos = os_strstr(cmd, " tcp_port=");
3468 if (pos) {
3469 pos += 10;
3470 config.tcp_port = atoi(pos);
3471 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003472
3473 pos = os_strstr(cmd, " role=");
3474 if (pos) {
3475 pos += 6;
3476 if (os_strncmp(pos, "configurator", 12) == 0)
3477 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
3478 else if (os_strncmp(pos, "enrollee", 8) == 0)
3479 config.allowed_roles = DPP_CAPAB_ENROLLEE;
3480 else if (os_strncmp(pos, "either", 6) == 0)
3481 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
3482 DPP_CAPAB_ENROLLEE;
3483 else
3484 return -1;
3485 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003486
3487 config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07003488 }
3489 config.configurator_params = wpa_s->dpp_configurator_params;
3490 return dpp_controller_start(wpa_s->dpp, &config);
3491}
Hai Shalomfdcde762020-04-02 11:19:20 -07003492
3493
3494static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
3495
3496static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
3497{
3498 struct wpa_supplicant *wpa_s = eloop_ctx;
3499
3500 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
3501 offchannel_send_action_done(wpa_s);
3502 wpas_dpp_chirp_next(wpa_s, NULL);
3503}
3504
3505
3506static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
3507 unsigned int freq, const u8 *dst,
3508 const u8 *src, const u8 *bssid,
3509 const u8 *data, size_t data_len,
3510 enum offchannel_send_action_result result)
3511{
3512 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
3513 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
3514 wpa_s->dpp_chirp_freq);
3515 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
3516 wpa_s, NULL) < 0)
3517 wpas_dpp_chirp_stop(wpa_s);
3518 return;
3519 }
3520
3521 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
3522 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
3523 wpa_s, NULL) < 0)
3524 wpas_dpp_chirp_stop(wpa_s);
3525}
3526
3527
3528static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
3529{
Hai Shalom899fcc72020-10-19 14:38:18 -07003530 struct wpabuf *msg, *announce = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003531 int type;
3532
3533 msg = wpa_s->dpp_presence_announcement;
3534 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
3535 if (!msg) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003536 struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid;
3537
3538 if (ssid && wpa_s->dpp_reconfig_id &&
3539 wpa_config_get_network(wpa_s->conf,
3540 wpa_s->dpp_reconfig_ssid_id) ==
3541 ssid) {
3542 announce = dpp_build_reconfig_announcement(
3543 ssid->dpp_csign,
3544 ssid->dpp_csign_len,
3545 ssid->dpp_netaccesskey,
3546 ssid->dpp_netaccesskey_len,
3547 wpa_s->dpp_reconfig_id);
3548 msg = announce;
3549 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003550 if (!msg)
3551 return;
3552 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
3553 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003554 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
3555 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003556 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07003557 if (offchannel_send_action(
3558 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
3559 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003560 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07003561 2000, wpas_dpp_chirp_tx_status, 0) < 0)
3562 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07003563
3564 wpabuf_free(announce);
Hai Shalomfdcde762020-04-02 11:19:20 -07003565}
3566
3567
3568static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
3569 struct wpa_scan_results *scan_res)
3570{
3571 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
3572 unsigned int i;
3573 struct hostapd_hw_modes *mode;
3574 int c;
3575 struct wpa_bss *bss;
Hai Shalom899fcc72020-10-19 14:38:18 -07003576 bool chan6;
Hai Shalomfdcde762020-04-02 11:19:20 -07003577
Hai Shalom899fcc72020-10-19 14:38:18 -07003578 if (!bi && !wpa_s->dpp_reconfig_ssid)
Hai Shalomfdcde762020-04-02 11:19:20 -07003579 return;
3580
3581 wpa_s->dpp_chirp_scan_done = 1;
3582
3583 os_free(wpa_s->dpp_chirp_freqs);
3584 wpa_s->dpp_chirp_freqs = NULL;
3585
3586 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003587 if (bi) {
3588 for (i = 0; i < bi->num_freq; i++)
3589 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
3590 bi->freq[i]);
3591 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003592
3593 /* Preferred chirping channels */
Hai Shalom899fcc72020-10-19 14:38:18 -07003594 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08003595 HOSTAPD_MODE_IEEE80211G, false);
Hai Shalom899fcc72020-10-19 14:38:18 -07003596 chan6 = mode == NULL;
3597 if (mode) {
3598 for (c = 0; c < mode->num_channels; c++) {
3599 struct hostapd_channel_data *chan = &mode->channels[c];
3600
3601 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
3602 chan->freq != 2437)
3603 continue;
3604 chan6 = true;
3605 break;
3606 }
3607 }
3608 if (chan6)
3609 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
Hai Shalomfdcde762020-04-02 11:19:20 -07003610
3611 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08003612 HOSTAPD_MODE_IEEE80211A, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07003613 if (mode) {
3614 int chan44 = 0, chan149 = 0;
3615
3616 for (c = 0; c < mode->num_channels; c++) {
3617 struct hostapd_channel_data *chan = &mode->channels[c];
3618
3619 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3620 HOSTAPD_CHAN_RADAR))
3621 continue;
3622 if (chan->freq == 5220)
3623 chan44 = 1;
3624 if (chan->freq == 5745)
3625 chan149 = 1;
3626 }
3627 if (chan149)
3628 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745);
3629 else if (chan44)
3630 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220);
3631 }
3632
3633 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08003634 HOSTAPD_MODE_IEEE80211AD, false);
Hai Shalomfdcde762020-04-02 11:19:20 -07003635 if (mode) {
3636 for (c = 0; c < mode->num_channels; c++) {
3637 struct hostapd_channel_data *chan = &mode->channels[c];
3638
3639 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
3640 HOSTAPD_CHAN_RADAR)) ||
3641 chan->freq != 60480)
3642 continue;
3643 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480);
3644 break;
3645 }
3646 }
3647
3648 /* Add channels from scan results for APs that advertise Configurator
3649 * Connectivity element */
3650 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3651 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
3652 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
3653 bss->freq);
3654 }
3655
3656 if (!wpa_s->dpp_chirp_freqs ||
3657 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
3658 wpas_dpp_chirp_stop(wpa_s);
3659}
3660
3661
3662static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
3663{
3664 struct wpa_supplicant *wpa_s = eloop_ctx;
3665 int i;
3666
3667 if (wpa_s->dpp_chirp_listen)
3668 wpas_dpp_listen_stop(wpa_s);
3669
3670 if (wpa_s->dpp_chirp_freq == 0) {
3671 if (wpa_s->dpp_chirp_round % 4 == 0 &&
3672 !wpa_s->dpp_chirp_scan_done) {
Hai Shalom60840252021-02-19 19:02:11 -08003673 if (wpas_scan_scheduled(wpa_s)) {
3674 wpa_printf(MSG_DEBUG,
3675 "DPP: Deferring chirp scan because another scan is planned already");
3676 if (eloop_register_timeout(1, 0,
3677 wpas_dpp_chirp_next,
3678 wpa_s, NULL) < 0) {
3679 wpas_dpp_chirp_stop(wpa_s);
3680 return;
3681 }
3682 return;
3683 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003684 wpa_printf(MSG_DEBUG,
3685 "DPP: Update channel list for chirping");
3686 wpa_s->scan_req = MANUAL_SCAN_REQ;
3687 wpa_s->scan_res_handler =
3688 wpas_dpp_chirp_scan_res_handler;
3689 wpa_supplicant_req_scan(wpa_s, 0, 0);
3690 return;
3691 }
3692 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
3693 wpa_s->dpp_chirp_round++;
3694 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
3695 wpa_s->dpp_chirp_round);
3696 } else {
3697 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
3698 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
3699 break;
3700 if (!wpa_s->dpp_chirp_freqs[i]) {
3701 wpa_printf(MSG_DEBUG,
3702 "DPP: Previous chirp freq %d not found",
3703 wpa_s->dpp_chirp_freq);
3704 return;
3705 }
3706 i++;
3707 if (wpa_s->dpp_chirp_freqs[i]) {
3708 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
3709 } else {
3710 wpa_s->dpp_chirp_iter--;
3711 if (wpa_s->dpp_chirp_iter <= 0) {
3712 wpa_printf(MSG_DEBUG,
3713 "DPP: Chirping iterations completed");
3714 wpas_dpp_chirp_stop(wpa_s);
3715 return;
3716 }
3717 wpa_s->dpp_chirp_freq = 0;
3718 wpa_s->dpp_chirp_scan_done = 0;
3719 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
3720 wpa_s, NULL) < 0) {
3721 wpas_dpp_chirp_stop(wpa_s);
3722 return;
3723 }
3724 if (wpa_s->dpp_chirp_listen) {
3725 wpa_printf(MSG_DEBUG,
3726 "DPP: Listen on %d MHz during chirp 30 second wait",
3727 wpa_s->dpp_chirp_listen);
3728 wpas_dpp_listen_start(wpa_s,
3729 wpa_s->dpp_chirp_listen);
3730 } else {
3731 wpa_printf(MSG_DEBUG,
3732 "DPP: Wait 30 seconds before starting the next chirping round");
3733 }
3734 return;
3735 }
3736 }
3737
3738 wpas_dpp_chirp_start(wpa_s);
3739}
3740
3741
3742int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
3743{
3744 const char *pos;
3745 int iter = 1, listen_freq = 0;
3746 struct dpp_bootstrap_info *bi;
3747
3748 pos = os_strstr(cmd, " own=");
3749 if (!pos)
3750 return -1;
3751 pos += 5;
3752 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
3753 if (!bi) {
3754 wpa_printf(MSG_DEBUG,
3755 "DPP: Identified bootstrap info not found");
3756 return -1;
3757 }
3758
3759 pos = os_strstr(cmd, " iter=");
3760 if (pos) {
3761 iter = atoi(pos + 6);
3762 if (iter <= 0)
3763 return -1;
3764 }
3765
3766 pos = os_strstr(cmd, " listen=");
3767 if (pos) {
3768 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003769 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07003770 return -1;
3771 }
3772
3773 wpas_dpp_chirp_stop(wpa_s);
3774 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
3775 wpa_s->dpp_qr_mutual = 0;
3776 wpa_s->dpp_chirp_bi = bi;
3777 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
3778 if (!wpa_s->dpp_presence_announcement)
3779 return -1;
3780 wpa_s->dpp_chirp_iter = iter;
3781 wpa_s->dpp_chirp_round = 0;
3782 wpa_s->dpp_chirp_scan_done = 0;
3783 wpa_s->dpp_chirp_listen = listen_freq;
3784
3785 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
3786}
3787
3788
3789void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
3790{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003791 if (wpa_s->dpp_presence_announcement ||
Hai Shalom899fcc72020-10-19 14:38:18 -07003792 wpa_s->dpp_reconfig_ssid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003793 offchannel_send_action_done(wpa_s);
3794 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
3795 }
3796 wpa_s->dpp_chirp_bi = NULL;
3797 wpabuf_free(wpa_s->dpp_presence_announcement);
3798 wpa_s->dpp_presence_announcement = NULL;
3799 if (wpa_s->dpp_chirp_listen)
3800 wpas_dpp_listen_stop(wpa_s);
3801 wpa_s->dpp_chirp_listen = 0;
3802 wpa_s->dpp_chirp_freq = 0;
3803 os_free(wpa_s->dpp_chirp_freqs);
3804 wpa_s->dpp_chirp_freqs = NULL;
3805 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
3806 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
3807 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
3808 wpas_abort_ongoing_scan(wpa_s);
3809 wpa_s->scan_res_handler = NULL;
3810 }
3811}
3812
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003813
Hai Shalom899fcc72020-10-19 14:38:18 -07003814int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003815{
Hai Shalom899fcc72020-10-19 14:38:18 -07003816 struct wpa_ssid *ssid;
3817 int iter = 1;
3818 const char *pos;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003819
Hai Shalom899fcc72020-10-19 14:38:18 -07003820 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd));
3821 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3822 !ssid->dpp_csign) {
3823 wpa_printf(MSG_DEBUG,
3824 "DPP: Not a valid network profile for reconfiguration");
3825 return -1;
3826 }
3827
3828 pos = os_strstr(cmd, " iter=");
3829 if (pos) {
3830 iter = atoi(pos + 6);
3831 if (iter <= 0)
3832 return -1;
3833 }
3834
3835 if (wpa_s->dpp_auth) {
3836 wpa_printf(MSG_DEBUG,
3837 "DPP: Not ready to start reconfiguration - pending authentication exchange in progress");
3838 return -1;
3839 }
3840
3841 dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
3842 wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
3843 ssid->dpp_csign_len,
3844 ssid->dpp_pp_key,
3845 ssid->dpp_pp_key_len);
3846 if (!wpa_s->dpp_reconfig_id) {
3847 wpa_printf(MSG_DEBUG,
3848 "DPP: Failed to generate E-id for reconfiguration");
3849 return -1;
3850 }
3851 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
3852 wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration");
3853 wpa_s->own_disconnect_req = 1;
3854 wpa_supplicant_deauthenticate(
3855 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
3856 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003857 wpas_dpp_chirp_stop(wpa_s);
3858 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
3859 wpa_s->dpp_qr_mutual = 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003860 wpa_s->dpp_reconfig_ssid = ssid;
3861 wpa_s->dpp_reconfig_ssid_id = ssid->id;
Hai Shalom899fcc72020-10-19 14:38:18 -07003862 wpa_s->dpp_chirp_iter = iter;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003863 wpa_s->dpp_chirp_round = 0;
3864 wpa_s->dpp_chirp_scan_done = 0;
3865 wpa_s->dpp_chirp_listen = 0;
3866
3867 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
3868}
3869
Hai Shalom899fcc72020-10-19 14:38:18 -07003870
3871static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
3872 struct dpp_authentication *auth, bool tcp)
3873{
3874 struct wpabuf *resp;
3875
3876 resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len,
3877 auth->e_netrole, true);
3878 if (!resp)
3879 return -1;
3880
3881 if (tcp) {
3882 auth->conf_resp_tcp = resp;
3883 return 0;
3884 }
3885
3886 if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx,
3887 resp) < 0) {
3888 wpa_printf(MSG_DEBUG,
3889 "DPP: Could not find pending GAS response");
3890 wpabuf_free(resp);
3891 return -1;
3892 }
3893 auth->conf_resp = resp;
3894 return 0;
3895}
3896
3897
3898int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
3899{
3900 int peer = -1;
3901 const char *pos, *value;
3902 struct dpp_authentication *auth = wpa_s->dpp_auth;
3903 u8 *bin;
3904 size_t bin_len;
3905 struct wpabuf *buf;
3906 bool tcp = false;
3907
3908 pos = os_strstr(cmd, " peer=");
3909 if (pos) {
3910 peer = atoi(pos + 6);
3911 if (!auth || !auth->waiting_cert ||
3912 (auth->peer_bi &&
3913 (unsigned int) peer != auth->peer_bi->id)) {
3914 auth = dpp_controller_get_auth(wpa_s->dpp, peer);
3915 tcp = true;
3916 }
3917 }
3918
3919 if (!auth || !auth->waiting_cert) {
3920 wpa_printf(MSG_DEBUG,
3921 "DPP: No authentication exchange waiting for certificate information");
3922 return -1;
3923 }
3924
3925 if (peer >= 0 &&
3926 (!auth->peer_bi ||
3927 (unsigned int) peer != auth->peer_bi->id) &&
3928 (!auth->tmp_peer_bi ||
3929 (unsigned int) peer != auth->tmp_peer_bi->id)) {
3930 wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
3931 return -1;
3932 }
3933
3934 pos = os_strstr(cmd, " value=");
3935 if (!pos)
3936 return -1;
3937 value = pos + 7;
3938
3939 pos = os_strstr(cmd, " name=");
3940 if (!pos)
3941 return -1;
3942 pos += 6;
3943
3944 if (os_strncmp(pos, "status ", 7) == 0) {
3945 auth->force_conf_resp_status = atoi(value);
3946 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
3947 }
3948
3949 if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
3950 os_free(auth->trusted_eap_server_name);
3951 auth->trusted_eap_server_name = os_strdup(value);
3952 return auth->trusted_eap_server_name ? 0 : -1;
3953 }
3954
3955 bin = base64_decode(value, os_strlen(value), &bin_len);
3956 if (!bin)
3957 return -1;
3958 buf = wpabuf_alloc_copy(bin, bin_len);
3959 os_free(bin);
3960
3961 if (os_strncmp(pos, "caCert ", 7) == 0) {
3962 wpabuf_free(auth->cacert);
3963 auth->cacert = buf;
3964 return 0;
3965 }
3966
3967 if (os_strncmp(pos, "certBag ", 8) == 0) {
3968 wpabuf_free(auth->certbag);
3969 auth->certbag = buf;
3970 return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
3971 }
3972
3973 wpabuf_free(buf);
3974 return -1;
3975}
3976
Hai Shalom81f62d82019-07-22 12:10:00 -07003977#endif /* CONFIG_DPP2 */