blob: 8c2e302ca2beec8abec515bc36a5bb1be8534471 [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"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070015#include "common/dpp.h"
16#include "common/gas.h"
17#include "common/gas_server.h"
18#include "rsn_supp/wpa.h"
19#include "rsn_supp/pmksa_cache.h"
20#include "wpa_supplicant_i.h"
21#include "config.h"
22#include "driver_i.h"
23#include "offchannel.h"
24#include "gas_query.h"
25#include "bss.h"
26#include "scan.h"
27#include "notify.h"
28#include "dpp_supplicant.h"
Hai Shalom59532852018-12-07 10:32:58 -080029#include "hidl.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070030
31
32static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
33 unsigned int freq);
34static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
35static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
36static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
37 unsigned int freq, const u8 *dst,
38 const u8 *src, const u8 *bssid,
39 const u8 *data, size_t data_len,
40 enum offchannel_send_action_result result);
Roshan Pius3a1667e2018-07-03 15:17:14 -070041static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
42static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
43static void
44wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
45 unsigned int freq, const u8 *dst,
46 const u8 *src, const u8 *bssid,
47 const u8 *data, size_t data_len,
48 enum offchannel_send_action_result result);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070049#ifdef CONFIG_DPP2
50static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
51 void *timeout_ctx);
52#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070053
54static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
55
56/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
57 * a single transaction in progress at any point in time. */
58static const u8 TRANSACTION_ID = 1;
59
60
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070061/**
62 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
63 * @wpa_s: Pointer to wpa_supplicant data
64 * @cmd: DPP URI read from a QR Code
65 * Returns: Identifier of the stored info or -1 on failure
66 */
67int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
68{
69 struct dpp_bootstrap_info *bi;
70 struct dpp_authentication *auth = wpa_s->dpp_auth;
71
Hai Shalom021b0b52019-04-10 11:17:58 -070072 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070073 if (!bi)
74 return -1;
75
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070076 if (auth && auth->response_pending &&
77 dpp_notify_new_qr_code(auth, bi) == 1) {
78 wpa_printf(MSG_DEBUG,
79 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070080 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
81 " freq=%u type=%d",
82 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
83 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070084 offchannel_send_action(wpa_s, auth->curr_freq,
85 auth->peer_mac_addr, wpa_s->own_addr,
86 broadcast,
87 wpabuf_head(auth->resp_msg),
88 wpabuf_len(auth->resp_msg),
89 500, wpas_dpp_tx_status, 0);
90 }
91
92 return bi->id;
93}
94
95
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080096/**
97 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
98 * @wpa_s: Pointer to wpa_supplicant data
99 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
100 * Returns: Identifier of the stored info or -1 on failure
101 */
102int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
103{
104 struct dpp_bootstrap_info *bi;
105
106 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
107 if (!bi)
108 return -1;
109
110 return bi->id;
111}
112
113
Hai Shalomfdcde762020-04-02 11:19:20 -0700114int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd)
115{
116 const char *pos;
117 struct dpp_bootstrap_info *peer_bi, *own_bi;
118
119 pos = os_strstr(cmd, " own=");
120 if (!pos)
121 return -1;
122 pos += 5;
123 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
124 if (!own_bi)
125 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700126 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700127
128 pos = os_strstr(cmd, " uri=");
129 if (!pos)
130 return -1;
131 pos += 5;
132 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
133 if (!peer_bi) {
134 wpa_printf(MSG_INFO,
135 "DPP: Failed to parse URI from NFC Handover Request");
136 return -1;
137 }
138
139 if (dpp_nfc_update_bi(own_bi, peer_bi) < 0)
140 return -1;
141
142 return peer_bi->id;
143}
144
145
146int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd)
147{
148 const char *pos;
149 struct dpp_bootstrap_info *peer_bi, *own_bi;
150
151 pos = os_strstr(cmd, " own=");
152 if (!pos)
153 return -1;
154 pos += 5;
155 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
156 if (!own_bi)
157 return -1;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700158 own_bi->nfc_negotiated = 1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700159
160 pos = os_strstr(cmd, " uri=");
161 if (!pos)
162 return -1;
163 pos += 5;
164 peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos);
165 if (!peer_bi) {
166 wpa_printf(MSG_INFO,
167 "DPP: Failed to parse URI from NFC Handover Select");
168 return -1;
169 }
170
171 if (peer_bi->curve != own_bi->curve) {
172 wpa_printf(MSG_INFO,
173 "DPP: Peer (NFC Handover Selector) used different curve");
174 return -1;
175 }
176
177 return peer_bi->id;
178}
179
180
Roshan Pius3a1667e2018-07-03 15:17:14 -0700181static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
182{
183 struct wpa_supplicant *wpa_s = eloop_ctx;
184 struct dpp_authentication *auth = wpa_s->dpp_auth;
185
186 if (!auth || !auth->resp_msg)
187 return;
188
189 wpa_printf(MSG_DEBUG,
190 "DPP: Retry Authentication Response after timeout");
191 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
192 " freq=%u type=%d",
193 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
194 DPP_PA_AUTHENTICATION_RESP);
195 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
196 wpa_s->own_addr, broadcast,
197 wpabuf_head(auth->resp_msg),
198 wpabuf_len(auth->resp_msg),
199 500, wpas_dpp_tx_status, 0);
200}
201
202
203static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
204{
205 struct dpp_authentication *auth = wpa_s->dpp_auth;
206 unsigned int wait_time, max_tries;
207
208 if (!auth || !auth->resp_msg)
209 return;
210
211 if (wpa_s->dpp_resp_max_tries)
212 max_tries = wpa_s->dpp_resp_max_tries;
213 else
214 max_tries = 5;
215 auth->auth_resp_tries++;
216 if (auth->auth_resp_tries >= max_tries) {
217 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
218 offchannel_send_action_done(wpa_s);
219 dpp_auth_deinit(wpa_s->dpp_auth);
220 wpa_s->dpp_auth = NULL;
221 return;
222 }
223
224 if (wpa_s->dpp_resp_retry_time)
225 wait_time = wpa_s->dpp_resp_retry_time;
226 else
227 wait_time = 1000;
228 wpa_printf(MSG_DEBUG,
229 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
230 wait_time);
231 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
232 eloop_register_timeout(wait_time / 1000,
233 (wait_time % 1000) * 1000,
234 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
235}
236
237
Hai Shalom021b0b52019-04-10 11:17:58 -0700238static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
239{
240 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700241 wpa_s->suitable_network = 0;
242 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700243 wpa_s->disconnected = 0;
244 wpa_s->reassociate = 1;
245 wpa_s->scan_runs = 0;
246 wpa_s->normal_scans = 0;
247 wpa_supplicant_cancel_sched_scan(wpa_s);
248 wpa_supplicant_req_scan(wpa_s, 0, 0);
249}
250
251
Hai Shalomc3565922019-10-28 11:58:20 -0700252#ifdef CONFIG_DPP2
253
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700254static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s,
255 unsigned int freq,
256 unsigned int wait_time)
257{
258 struct os_reltime now, res;
259 unsigned int remaining;
260
261 if (!wpa_s->dpp_listen_freq)
262 return;
263
264 os_get_reltime(&now);
265 if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) {
266 os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res);
267 remaining = res.sec * 1000 + res.usec / 1000;
268 } else {
269 remaining = 0;
270 }
271 if (wpa_s->dpp_listen_freq == freq && remaining > wait_time)
272 return;
273
274 wpa_printf(MSG_DEBUG,
275 "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms",
276 wpa_s->dpp_listen_freq, remaining, freq, wait_time);
277 wpas_dpp_listen_stop(wpa_s);
278
279 /* TODO: Restart listen in some cases after TX? */
280}
281
282
Hai Shalomc3565922019-10-28 11:58:20 -0700283static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
284 void *timeout_ctx)
285{
286 struct wpa_supplicant *wpa_s = eloop_ctx;
287 struct dpp_authentication *auth = wpa_s->dpp_auth;
288 enum dpp_status_error result;
289
290 if (!auth || !auth->conn_status_requested)
291 return;
292
293 wpa_printf(MSG_DEBUG,
294 "DPP: Connection timeout - report Connection Status Result");
295 if (wpa_s->suitable_network)
296 result = DPP_STATUS_AUTH_FAILURE;
297 else if (wpa_s->no_suitable_network)
298 result = DPP_STATUS_NO_AP;
299 else
300 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800301 if (wpa_s->wpa_state == WPA_SCANNING)
302 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700303 wpas_dpp_send_conn_status_result(wpa_s, result);
304}
305
306
307static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
308{
309 char *str, *end, *pos;
310 size_t len;
311 unsigned int i;
312 u8 last_op_class = 0;
313 int res;
314
315 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
316 return NULL;
317
318 len = wpa_s->num_last_scan_freqs * 8;
319 str = os_zalloc(len);
320 if (!str)
321 return NULL;
322 end = str + len;
323 pos = str;
324
325 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
326 enum hostapd_hw_mode mode;
327 u8 op_class, channel;
328
329 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
330 0, 0, &op_class, &channel);
331 if (mode == NUM_HOSTAPD_MODES)
332 continue;
333 if (op_class == last_op_class)
334 res = os_snprintf(pos, end - pos, ",%d", channel);
335 else
336 res = os_snprintf(pos, end - pos, "%s%d/%d",
337 pos == str ? "" : ",",
338 op_class, channel);
339 if (os_snprintf_error(end - pos, res)) {
340 *pos = '\0';
341 break;
342 }
343 pos += res;
344 last_op_class = op_class;
345 }
346
347 if (pos == str) {
348 os_free(str);
349 str = NULL;
350 }
351 return str;
352}
353
354
355void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
356 enum dpp_status_error result)
357{
358 struct wpabuf *msg;
359 const char *channel_list = NULL;
360 char *channel_list_buf = NULL;
361 struct wpa_ssid *ssid = wpa_s->current_ssid;
362 struct dpp_authentication *auth = wpa_s->dpp_auth;
363
364 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
365
366 if (!auth || !auth->conn_status_requested)
367 return;
368 auth->conn_status_requested = 0;
369 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
370 result);
371
372 if (result == DPP_STATUS_NO_AP) {
373 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
374 channel_list = channel_list_buf;
375 }
376
377 msg = dpp_build_conn_status_result(auth, result,
378 ssid ? ssid->ssid :
379 wpa_s->dpp_last_ssid,
380 ssid ? ssid->ssid_len :
381 wpa_s->dpp_last_ssid_len,
382 channel_list);
383 os_free(channel_list_buf);
384 if (!msg) {
385 dpp_auth_deinit(wpa_s->dpp_auth);
386 wpa_s->dpp_auth = NULL;
387 return;
388 }
389
390 wpa_msg(wpa_s, MSG_INFO,
391 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
392 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
393 DPP_PA_CONNECTION_STATUS_RESULT);
394 offchannel_send_action(wpa_s, auth->curr_freq,
395 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
396 wpabuf_head(msg), wpabuf_len(msg),
397 500, wpas_dpp_tx_status, 0);
398 wpabuf_free(msg);
399
400 /* This exchange will be terminated in the TX status handler */
401 auth->remove_on_tx_status = 1;
402
403 return;
404}
405
406
407void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
408{
409 struct dpp_authentication *auth = wpa_s->dpp_auth;
410
411 if (auth && auth->conn_status_requested)
412 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
413}
414
415#endif /* CONFIG_DPP2 */
416
417
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700418static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
419 unsigned int freq, const u8 *dst,
420 const u8 *src, const u8 *bssid,
421 const u8 *data, size_t data_len,
422 enum offchannel_send_action_result result)
423{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700424 const char *res_txt;
425 struct dpp_authentication *auth = wpa_s->dpp_auth;
426
427 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
428 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
429 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700430 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700431 " result=%s", freq, MAC2STR(dst), res_txt);
432 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
433 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700434
435 if (!wpa_s->dpp_auth) {
436 wpa_printf(MSG_DEBUG,
437 "DPP: Ignore TX status since there is no ongoing authentication exchange");
438 return;
439 }
440
Hai Shalom021b0b52019-04-10 11:17:58 -0700441#ifdef CONFIG_DPP2
442 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700443 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700444 wpa_printf(MSG_DEBUG,
445 "DPP: Try to connect after completed configuration result");
446 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700447 if (auth->conn_status_requested) {
448 wpa_printf(MSG_DEBUG,
449 "DPP: Start 15 second timeout for reporting connection status result");
450 eloop_cancel_timeout(
451 wpas_dpp_conn_status_result_timeout,
452 wpa_s, NULL);
453 eloop_register_timeout(
454 15, 0, wpas_dpp_conn_status_result_timeout,
455 wpa_s, NULL);
456 } else {
457 dpp_auth_deinit(wpa_s->dpp_auth);
458 wpa_s->dpp_auth = NULL;
459 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700460 return;
461 }
462#endif /* CONFIG_DPP2 */
463
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700464 if (wpa_s->dpp_auth->remove_on_tx_status) {
465 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700466 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700467 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700468 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700469 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
470 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700471#ifdef CONFIG_DPP2
472 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
473 wpa_s, NULL);
474#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700475 offchannel_send_action_done(wpa_s);
476 dpp_auth_deinit(wpa_s->dpp_auth);
477 wpa_s->dpp_auth = NULL;
478 return;
479 }
480
481 if (wpa_s->dpp_auth_ok_on_ack)
482 wpas_dpp_auth_success(wpa_s, 1);
483
484 if (!is_broadcast_ether_addr(dst) &&
485 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
486 wpa_printf(MSG_DEBUG,
487 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700488 if (auth->waiting_auth_resp) {
489 /* In case of DPP Authentication Request frame, move to
490 * the next channel immediately. */
491 offchannel_send_action_done(wpa_s);
492 wpas_dpp_auth_init_next(wpa_s);
493 return;
494 }
495 if (auth->waiting_auth_conf) {
496 wpas_dpp_auth_resp_retry(wpa_s);
497 return;
498 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700499 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700500
501 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
502 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
503 /* Allow timeout handling to stop iteration if no response is
504 * received from a peer that has ACKed a request. */
505 auth->auth_req_ack = 1;
506 }
507
508 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
509 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
510 wpa_printf(MSG_DEBUG,
511 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
512 wpa_s->dpp_auth->curr_freq,
513 wpa_s->dpp_auth->neg_freq);
514 offchannel_send_action_done(wpa_s);
515 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
516 }
517
518 if (wpa_s->dpp_auth_ok_on_ack)
519 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700520}
521
522
523static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
524{
525 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700526 struct dpp_authentication *auth = wpa_s->dpp_auth;
527 unsigned int freq;
528 struct os_reltime now, diff;
529 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700530
Roshan Pius3a1667e2018-07-03 15:17:14 -0700531 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700532 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700533
534 wait_time = wpa_s->dpp_resp_wait_time ?
535 wpa_s->dpp_resp_wait_time : 2000;
536 os_get_reltime(&now);
537 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
538 diff_ms = diff.sec * 1000 + diff.usec / 1000;
539 wpa_printf(MSG_DEBUG,
540 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
541 wait_time, diff_ms);
542
543 if (auth->auth_req_ack && diff_ms >= wait_time) {
544 /* Peer ACK'ed Authentication Request frame, but did not reply
545 * with Authentication Response frame within two seconds. */
546 wpa_printf(MSG_INFO,
547 "DPP: No response received from responder - stopping initiation attempt");
548 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800549 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700550 offchannel_send_action_done(wpa_s);
551 wpas_dpp_listen_stop(wpa_s);
552 dpp_auth_deinit(auth);
553 wpa_s->dpp_auth = NULL;
554 return;
555 }
556
557 if (diff_ms >= wait_time) {
558 /* Authentication Request frame was not ACK'ed and no reply
559 * was receiving within two seconds. */
560 wpa_printf(MSG_DEBUG,
561 "DPP: Continue Initiator channel iteration");
562 offchannel_send_action_done(wpa_s);
563 wpas_dpp_listen_stop(wpa_s);
564 wpas_dpp_auth_init_next(wpa_s);
565 return;
566 }
567
568 /* Driver did not support 2000 ms long wait_time with TX command, so
569 * schedule listen operation to continue waiting for the response.
570 *
571 * DPP listen operations continue until stopped, so simply schedule a
572 * new call to this function at the point when the two second reply
573 * wait has expired. */
574 wait_time -= diff_ms;
575
576 freq = auth->curr_freq;
577 if (auth->neg_freq > 0)
578 freq = auth->neg_freq;
579 wpa_printf(MSG_DEBUG,
580 "DPP: Continue reply wait on channel %u MHz for %u ms",
581 freq, wait_time);
582 wpa_s->dpp_in_response_listen = 1;
583 wpas_dpp_listen_start(wpa_s, freq);
584
585 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
586 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700587}
588
589
590static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
591 struct dpp_authentication *auth)
592{
593#ifdef CONFIG_TESTING_OPTIONS
594 if (wpa_s->dpp_config_obj_override)
595 auth->config_obj_override =
596 os_strdup(wpa_s->dpp_config_obj_override);
597 if (wpa_s->dpp_discovery_override)
598 auth->discovery_override =
599 os_strdup(wpa_s->dpp_discovery_override);
600 if (wpa_s->dpp_groups_override)
601 auth->groups_override =
602 os_strdup(wpa_s->dpp_groups_override);
603 auth->ignore_netaccesskey_mismatch =
604 wpa_s->dpp_ignore_netaccesskey_mismatch;
605#endif /* CONFIG_TESTING_OPTIONS */
606}
607
608
Roshan Pius3a1667e2018-07-03 15:17:14 -0700609static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
610{
611 struct wpa_supplicant *wpa_s = eloop_ctx;
612
613 if (!wpa_s->dpp_auth)
614 return;
615 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
616 wpas_dpp_auth_init_next(wpa_s);
617}
618
619
620static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
621{
622 struct dpp_authentication *auth = wpa_s->dpp_auth;
623 const u8 *dst;
624 unsigned int wait_time, max_wait_time, freq, max_tries, used;
625 struct os_reltime now, diff;
626
627 wpa_s->dpp_in_response_listen = 0;
628 if (!auth)
629 return -1;
630
631 if (auth->freq_idx == 0)
632 os_get_reltime(&wpa_s->dpp_init_iter_start);
633
634 if (auth->freq_idx >= auth->num_freq) {
635 auth->num_freq_iters++;
636 if (wpa_s->dpp_init_max_tries)
637 max_tries = wpa_s->dpp_init_max_tries;
638 else
639 max_tries = 5;
640 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
641 wpa_printf(MSG_INFO,
642 "DPP: No response received from responder - stopping initiation attempt");
643 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800644 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700645 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
646 wpa_s, NULL);
647 offchannel_send_action_done(wpa_s);
648 dpp_auth_deinit(wpa_s->dpp_auth);
649 wpa_s->dpp_auth = NULL;
650 return -1;
651 }
652 auth->freq_idx = 0;
653 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
654 if (wpa_s->dpp_init_retry_time)
655 wait_time = wpa_s->dpp_init_retry_time;
656 else
657 wait_time = 10000;
658 os_get_reltime(&now);
659 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
660 used = diff.sec * 1000 + diff.usec / 1000;
661 if (used > wait_time)
662 wait_time = 0;
663 else
664 wait_time -= used;
665 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
666 wait_time);
667 eloop_register_timeout(wait_time / 1000,
668 (wait_time % 1000) * 1000,
669 wpas_dpp_init_timeout, wpa_s,
670 NULL);
671 return 0;
672 }
673 freq = auth->freq[auth->freq_idx++];
674 auth->curr_freq = freq;
675
676 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
677 dst = broadcast;
678 else
679 dst = auth->peer_bi->mac_addr;
680 wpa_s->dpp_auth_ok_on_ack = 0;
681 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
682 wait_time = wpa_s->max_remain_on_chan;
683 max_wait_time = wpa_s->dpp_resp_wait_time ?
684 wpa_s->dpp_resp_wait_time : 2000;
685 if (wait_time > max_wait_time)
686 wait_time = max_wait_time;
687 wait_time += 10; /* give the driver some extra time to complete */
688 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
689 wpas_dpp_reply_wait_timeout,
690 wpa_s, NULL);
691 wait_time -= 10;
692 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
693 wpa_printf(MSG_DEBUG,
694 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
695 freq, auth->neg_freq);
696 }
697 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
698 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
699 auth->auth_req_ack = 0;
700 os_get_reltime(&wpa_s->dpp_last_init);
701 return offchannel_send_action(wpa_s, freq, dst,
702 wpa_s->own_addr, broadcast,
703 wpabuf_head(auth->req_msg),
704 wpabuf_len(auth->req_msg),
705 wait_time, wpas_dpp_tx_status, 0);
706}
707
708
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700709int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
710{
711 const char *pos;
712 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700713 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700714 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
715 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700716 int tcp = 0;
717#ifdef CONFIG_DPP2
718 int tcp_port = DPP_TCP_PORT;
719 struct hostapd_ip_addr ipaddr;
720 char *addr;
721#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700722
723 wpa_s->dpp_gas_client = 0;
724
725 pos = os_strstr(cmd, " peer=");
726 if (!pos)
727 return -1;
728 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700729 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700730 if (!peer_bi) {
731 wpa_printf(MSG_INFO,
732 "DPP: Could not find bootstrapping info for the identified peer");
733 return -1;
734 }
735
Hai Shalom81f62d82019-07-22 12:10:00 -0700736#ifdef CONFIG_DPP2
737 pos = os_strstr(cmd, " tcp_port=");
738 if (pos) {
739 pos += 10;
740 tcp_port = atoi(pos);
741 }
742
743 addr = get_param(cmd, " tcp_addr=");
744 if (addr) {
745 int res;
746
747 res = hostapd_parse_ip_addr(addr, &ipaddr);
748 os_free(addr);
749 if (res)
750 return -1;
751 tcp = 1;
752 }
753#endif /* CONFIG_DPP2 */
754
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700755 pos = os_strstr(cmd, " own=");
756 if (pos) {
757 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700758 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700759 if (!own_bi) {
760 wpa_printf(MSG_INFO,
761 "DPP: Could not find bootstrapping info for the identified local entry");
762 return -1;
763 }
764
765 if (peer_bi->curve != own_bi->curve) {
766 wpa_printf(MSG_INFO,
767 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
768 peer_bi->curve->name, own_bi->curve->name);
769 return -1;
770 }
771 }
772
773 pos = os_strstr(cmd, " role=");
774 if (pos) {
775 pos += 6;
776 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700777 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700778 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700779 allowed_roles = DPP_CAPAB_ENROLLEE;
780 else if (os_strncmp(pos, "either", 6) == 0)
781 allowed_roles = DPP_CAPAB_CONFIGURATOR |
782 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700783 else
784 goto fail;
785 }
786
787 pos = os_strstr(cmd, " netrole=");
788 if (pos) {
789 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800790 if (os_strncmp(pos, "ap", 2) == 0)
791 wpa_s->dpp_netrole = DPP_NETROLE_AP;
792 else if (os_strncmp(pos, "configurator", 12) == 0)
793 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
794 else
795 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Hai Shalomfdcde762020-04-02 11:19:20 -0700796 } else {
797 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700798 }
799
Roshan Pius3a1667e2018-07-03 15:17:14 -0700800 pos = os_strstr(cmd, " neg_freq=");
801 if (pos)
802 neg_freq = atoi(pos + 10);
803
Hai Shalom81f62d82019-07-22 12:10:00 -0700804 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700805 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700806 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700807 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
808 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700809#ifdef CONFIG_DPP2
810 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
811 wpa_s, NULL);
812#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700813 offchannel_send_action_done(wpa_s);
814 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800815 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700816 }
817
Hai Shalomfdcde762020-04-02 11:19:20 -0700818 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles,
819 neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Hai Shalom81f62d82019-07-22 12:10:00 -0700820 if (!auth)
821 goto fail;
822 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700823 if (dpp_set_configurator(auth, cmd) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -0700824 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800825 goto fail;
826 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700827
Hai Shalom81f62d82019-07-22 12:10:00 -0700828 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700829
Roshan Pius3a1667e2018-07-03 15:17:14 -0700830 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700831 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700832
Hai Shalom81f62d82019-07-22 12:10:00 -0700833#ifdef CONFIG_DPP2
834 if (tcp)
835 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port);
836#endif /* CONFIG_DPP2 */
837
838 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700839 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700840fail:
841 return -1;
842}
843
844
845struct wpas_dpp_listen_work {
846 unsigned int freq;
847 unsigned int duration;
848 struct wpabuf *probe_resp_ie;
849};
850
851
852static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
853{
854 if (!lwork)
855 return;
856 os_free(lwork);
857}
858
859
860static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
861{
862 struct wpas_dpp_listen_work *lwork;
863
864 if (!wpa_s->dpp_listen_work)
865 return;
866
867 lwork = wpa_s->dpp_listen_work->ctx;
868 wpas_dpp_listen_work_free(lwork);
869 radio_work_done(wpa_s->dpp_listen_work);
870 wpa_s->dpp_listen_work = NULL;
871}
872
873
874static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
875{
876 struct wpa_supplicant *wpa_s = work->wpa_s;
877 struct wpas_dpp_listen_work *lwork = work->ctx;
878
879 if (deinit) {
880 if (work->started) {
881 wpa_s->dpp_listen_work = NULL;
882 wpas_dpp_listen_stop(wpa_s);
883 }
884 wpas_dpp_listen_work_free(lwork);
885 return;
886 }
887
888 wpa_s->dpp_listen_work = work;
889
890 wpa_s->dpp_pending_listen_freq = lwork->freq;
891
892 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
893 wpa_s->max_remain_on_chan) < 0) {
894 wpa_printf(MSG_DEBUG,
895 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
896 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800897 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700898 wpas_dpp_listen_work_done(wpa_s);
899 wpa_s->dpp_pending_listen_freq = 0;
900 return;
901 }
902 wpa_s->off_channel_freq = 0;
903 wpa_s->roc_waiting_drv_freq = lwork->freq;
Hai Shalomb755a2a2020-04-23 21:49:02 -0700904 wpa_drv_dpp_listen(wpa_s, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700905}
906
907
908static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
909 unsigned int freq)
910{
911 struct wpas_dpp_listen_work *lwork;
912
913 if (wpa_s->dpp_listen_work) {
914 wpa_printf(MSG_DEBUG,
915 "DPP: Reject start_listen since dpp_listen_work already exists");
916 return -1;
917 }
918
919 if (wpa_s->dpp_listen_freq)
920 wpas_dpp_listen_stop(wpa_s);
921 wpa_s->dpp_listen_freq = freq;
922
923 lwork = os_zalloc(sizeof(*lwork));
924 if (!lwork)
925 return -1;
926 lwork->freq = freq;
927
928 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
929 lwork) < 0) {
930 wpas_dpp_listen_work_free(lwork);
931 return -1;
932 }
933
934 return 0;
935}
936
937
938int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
939{
940 int freq;
941
942 freq = atoi(cmd);
943 if (freq <= 0)
944 return -1;
945
946 if (os_strstr(cmd, " role=configurator"))
947 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
948 else if (os_strstr(cmd, " role=enrollee"))
949 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
950 else
951 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
952 DPP_CAPAB_ENROLLEE;
953 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800954 if (os_strstr(cmd, " netrole=ap"))
955 wpa_s->dpp_netrole = DPP_NETROLE_AP;
956 else if (os_strstr(cmd, " netrole=configurator"))
957 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
958 else
959 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700960 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
961 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
962 freq);
963 return 0;
964 }
965
966 return wpas_dpp_listen_start(wpa_s, freq);
967}
968
969
970void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
971{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700972 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700973 if (!wpa_s->dpp_listen_freq)
974 return;
975
976 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
977 wpa_s->dpp_listen_freq);
978 wpa_drv_cancel_remain_on_channel(wpa_s);
Hai Shalomb755a2a2020-04-23 21:49:02 -0700979 wpa_drv_dpp_listen(wpa_s, false);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700980 wpa_s->dpp_listen_freq = 0;
981 wpas_dpp_listen_work_done(wpa_s);
982}
983
984
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700985void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
986 unsigned int freq, unsigned int duration)
987{
988 if (wpa_s->dpp_listen_freq != freq)
989 return;
990
991 wpa_printf(MSG_DEBUG,
992 "DPP: Remain-on-channel started for listen on %u MHz for %u ms",
993 freq, duration);
994 os_get_reltime(&wpa_s->dpp_listen_end);
995 wpa_s->dpp_listen_end.usec += duration * 1000;
996 while (wpa_s->dpp_listen_end.usec >= 1000000) {
997 wpa_s->dpp_listen_end.sec++;
998 wpa_s->dpp_listen_end.usec -= 1000000;
999 }
1000}
1001
1002
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001003void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1004 unsigned int freq)
1005{
1006 wpas_dpp_listen_work_done(wpa_s);
1007
Roshan Pius3a1667e2018-07-03 15:17:14 -07001008 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1009 unsigned int new_freq;
1010
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001011 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001012 if (wpa_s->dpp_auth->neg_freq > 0)
1013 new_freq = wpa_s->dpp_auth->neg_freq;
1014 else
1015 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001016 wpa_printf(MSG_DEBUG,
1017 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001018 new_freq);
1019 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001020 return;
1021 }
1022
1023 if (wpa_s->dpp_listen_freq) {
1024 /* Continue listen with a new remain-on-channel */
1025 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1026 }
1027}
1028
1029
1030static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1031 const u8 *hdr, const u8 *buf, size_t len,
1032 unsigned int freq)
1033{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001034 const u8 *r_bootstrap, *i_bootstrap;
1035 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001036 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
1037
1038 if (!wpa_s->dpp)
1039 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001040
1041 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1042 MAC2STR(src));
1043
Hai Shalomfdcde762020-04-02 11:19:20 -07001044#ifdef CONFIG_DPP2
1045 wpas_dpp_chirp_stop(wpa_s);
1046#endif /* CONFIG_DPP2 */
1047
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001048 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1049 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001050 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1051 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1052 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001053 return;
1054 }
1055 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1056 r_bootstrap, r_bootstrap_len);
1057
1058 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1059 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001060 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1061 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1062 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001063 return;
1064 }
1065 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1066 i_bootstrap, i_bootstrap_len);
1067
1068 /* Try to find own and peer bootstrapping key matches based on the
1069 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -07001070 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
1071 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001072 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001073 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1074 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001075 return;
1076 }
1077
1078 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001079 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1080 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001081 return;
1082 }
1083
1084 wpa_s->dpp_gas_client = 0;
1085 wpa_s->dpp_auth_ok_on_ack = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07001086 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s,
1087 wpa_s->dpp_allowed_roles,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001088 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001089 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001090 if (!wpa_s->dpp_auth) {
1091 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1092 return;
1093 }
1094 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001095 if (dpp_set_configurator(wpa_s->dpp_auth,
Hai Shalom021b0b52019-04-10 11:17:58 -07001096 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001097 dpp_auth_deinit(wpa_s->dpp_auth);
1098 wpa_s->dpp_auth = NULL;
1099 return;
1100 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001101 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1102
Roshan Pius3a1667e2018-07-03 15:17:14 -07001103 if (wpa_s->dpp_listen_freq &&
1104 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1105 wpa_printf(MSG_DEBUG,
1106 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1107 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1108 wpas_dpp_listen_stop(wpa_s);
1109 }
1110
1111 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1112 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1113 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001114 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1115 src, wpa_s->own_addr, broadcast,
1116 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1117 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1118 500, wpas_dpp_tx_status, 0);
1119}
1120
1121
1122static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1123{
1124 /* TODO: stop wait and start ROC */
1125}
1126
1127
1128static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001129 struct dpp_authentication *auth,
1130 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001131{
1132 struct wpa_ssid *ssid;
1133
Hai Shalom021b0b52019-04-10 11:17:58 -07001134#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001135 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001136#ifdef CONFIG_SAE
1137 struct wpa_driver_capa capa;
1138 int res;
1139
1140 res = wpa_drv_get_capa(wpa_s, &capa);
1141 if (res == 0 &&
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001142 !(capa.key_mgmt_iftype[WPA_IF_STATION] &
1143 WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001144 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1145 wpa_printf(MSG_DEBUG,
1146 "DPP: SAE not supported by the driver");
1147 return NULL;
1148 }
1149#else /* CONFIG_SAE */
1150 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1151 return NULL;
1152#endif /* CONFIG_SAE */
1153 }
1154#endif /* CONFIG_DPP2 */
1155
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001156 ssid = wpa_config_add_network(wpa_s->conf);
1157 if (!ssid)
1158 return NULL;
1159 wpas_notify_network_added(wpa_s, ssid);
1160 wpa_config_set_network_defaults(ssid);
1161 ssid->disabled = 1;
1162
Hai Shalomc3565922019-10-28 11:58:20 -07001163 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001164 if (!ssid->ssid)
1165 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001166 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1167 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001168
Hai Shalomc3565922019-10-28 11:58:20 -07001169 if (conf->connector) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001170 if (dpp_akm_dpp(conf->akm)) {
1171 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
1172 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
1173 }
Hai Shalomc3565922019-10-28 11:58:20 -07001174 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001175 if (!ssid->dpp_connector)
1176 goto fail;
1177 }
1178
Hai Shalomc3565922019-10-28 11:58:20 -07001179 if (conf->c_sign_key) {
1180 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001181 if (!ssid->dpp_csign)
1182 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001183 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1184 wpabuf_len(conf->c_sign_key));
1185 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001186 }
1187
1188 if (auth->net_access_key) {
1189 ssid->dpp_netaccesskey =
1190 os_malloc(wpabuf_len(auth->net_access_key));
1191 if (!ssid->dpp_netaccesskey)
1192 goto fail;
1193 os_memcpy(ssid->dpp_netaccesskey,
1194 wpabuf_head(auth->net_access_key),
1195 wpabuf_len(auth->net_access_key));
1196 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1197 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1198 }
1199
Hai Shalomc3565922019-10-28 11:58:20 -07001200 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1201 dpp_akm_sae(conf->akm)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001202 if (!conf->connector || !dpp_akm_dpp(conf->akm))
Hai Shalom021b0b52019-04-10 11:17:58 -07001203 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001204 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001205 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1206 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001207 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001208 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1209 WPA_KEY_MGMT_FT_SAE;
1210 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001211 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001212 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001213 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001214 goto fail;
1215 wpa_config_update_psk(ssid);
1216 ssid->export_keys = 1;
1217 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001218 ssid->psk_set = conf->psk_set;
1219 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001220 }
1221 }
1222
Hai Shalomc3565922019-10-28 11:58:20 -07001223 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1224 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1225
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001226 return ssid;
1227fail:
1228 wpas_notify_network_removed(wpa_s, ssid);
1229 wpa_config_remove_network(wpa_s->conf, ssid->id);
1230 return NULL;
1231}
1232
1233
Hai Shalom021b0b52019-04-10 11:17:58 -07001234static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001235 struct dpp_authentication *auth,
1236 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001237{
1238 struct wpa_ssid *ssid;
1239
1240 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001241 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001242
Hai Shalomc3565922019-10-28 11:58:20 -07001243 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001244 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001245 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001246
1247 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001248
Hai Shalom706f99b2019-01-08 16:23:37 -08001249 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001250
Hai Shalom021b0b52019-04-10 11:17:58 -07001251 if (wpa_s->conf->dpp_config_processing == 2)
1252 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001253
Hai Shalom021b0b52019-04-10 11:17:58 -07001254#ifndef CONFIG_NO_CONFIG_WRITE
1255 if (wpa_s->conf->update_config &&
1256 wpa_config_write(wpa_s->confname, wpa_s->conf))
1257 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1258#endif /* CONFIG_NO_CONFIG_WRITE */
1259
Hai Shalomc3565922019-10-28 11:58:20 -07001260 return 0;
1261}
1262
1263
1264static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1265 struct dpp_authentication *auth)
1266{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001267#ifdef CONFIG_DPP2
1268 if (auth->reconfig && wpa_s->dpp_reconfig_ssid &&
1269 wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) ==
1270 wpa_s->dpp_reconfig_ssid) {
1271 wpa_printf(MSG_DEBUG,
1272 "DPP: Remove reconfigured network profile");
1273 wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid);
1274 wpa_config_remove_network(wpa_s->conf,
1275 wpa_s->dpp_reconfig_ssid_id);
1276 wpa_s->dpp_reconfig_ssid = NULL;
1277 wpa_s->dpp_reconfig_ssid_id = -1;
1278 }
1279#endif /* CONFIG_DPP2 */
1280
Hai Shalom021b0b52019-04-10 11:17:58 -07001281 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001282 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001283
1284#ifdef CONFIG_DPP2
1285 if (auth->peer_version >= 2) {
1286 wpa_printf(MSG_DEBUG,
1287 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1288 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001289 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001290 }
1291#endif /* CONFIG_DPP2 */
1292
1293 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001294}
1295
1296
Hai Shalom021b0b52019-04-10 11:17:58 -07001297static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001298 struct dpp_authentication *auth,
1299 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001300{
1301 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalomc3565922019-10-28 11:58:20 -07001302 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001303 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001304 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001305 if (conf->ssid_charset)
1306 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1307 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001308 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001309 /* TODO: Save the Connector and consider using a command
1310 * to fetch the value instead of sending an event with
1311 * it. The Connector could end up being larger than what
1312 * most clients are ready to receive as an event
1313 * message. */
1314 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001315 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001316 }
Hai Shalomc3565922019-10-28 11:58:20 -07001317 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001318 char *hex;
1319 size_t hexlen;
1320
Hai Shalomc3565922019-10-28 11:58:20 -07001321 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001322 hex = os_malloc(hexlen);
1323 if (hex) {
1324 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001325 wpabuf_head(conf->c_sign_key),
1326 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001327 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1328 hex);
1329 os_free(hex);
1330 }
1331 }
1332 if (auth->net_access_key) {
1333 char *hex;
1334 size_t hexlen;
1335
1336 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1337 hex = os_malloc(hexlen);
1338 if (hex) {
1339 wpa_snprintf_hex(hex, hexlen,
1340 wpabuf_head(auth->net_access_key),
1341 wpabuf_len(auth->net_access_key));
1342 if (auth->net_access_key_expiry)
1343 wpa_msg(wpa_s, MSG_INFO,
1344 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1345 (long unsigned)
1346 auth->net_access_key_expiry);
1347 else
1348 wpa_msg(wpa_s, MSG_INFO,
1349 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1350 os_free(hex);
1351 }
1352 }
1353
Hai Shalomc3565922019-10-28 11:58:20 -07001354 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001355}
1356
1357
Hai Shalomfdcde762020-04-02 11:19:20 -07001358static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
1359 struct dpp_asymmetric_key *key)
1360{
1361#ifdef CONFIG_DPP2
1362 int res;
1363
1364 if (!key)
1365 return 0;
1366
1367 wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup");
1368 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
1369
1370 while (key) {
1371 res = dpp_configurator_from_backup(wpa_s->dpp, key);
1372 if (res < 0)
1373 return -1;
1374 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d",
1375 res);
1376 key = key->next;
1377 }
1378#endif /* CONFIG_DPP2 */
1379
1380 return 0;
1381}
1382
1383
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001384static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1385 enum gas_query_result result,
1386 const struct wpabuf *adv_proto,
1387 const struct wpabuf *resp, u16 status_code)
1388{
1389 struct wpa_supplicant *wpa_s = ctx;
1390 const u8 *pos;
1391 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001392 int res;
1393 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001394 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001395
Roshan Pius3a1667e2018-07-03 15:17:14 -07001396 wpa_s->dpp_gas_dialog_token = -1;
1397
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001398 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
1399 os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001400 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1401 return;
1402 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001403 if (result != GAS_QUERY_SUCCESS ||
1404 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001405 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1406 goto fail;
1407 }
1408
1409 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1410 adv_proto);
1411 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1412 resp);
1413
1414 if (wpabuf_len(adv_proto) != 10 ||
1415 !(pos = wpabuf_head(adv_proto)) ||
1416 pos[0] != WLAN_EID_ADV_PROTO ||
1417 pos[1] != 8 ||
1418 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1419 pos[4] != 5 ||
1420 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1421 pos[8] != 0x1a ||
1422 pos[9] != 1) {
1423 wpa_printf(MSG_DEBUG,
1424 "DPP: Not a DPP Advertisement Protocol ID");
1425 goto fail;
1426 }
1427
1428 if (dpp_conf_resp_rx(auth, resp) < 0) {
1429 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1430 goto fail;
1431 }
1432
Hai Shalomc3565922019-10-28 11:58:20 -07001433 for (i = 0; i < auth->num_conf_obj; i++) {
1434 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1435 &auth->conf_obj[i]);
1436 if (res < 0)
1437 goto fail;
1438 }
1439 if (auth->num_conf_obj)
1440 wpas_dpp_post_process_config(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07001441 if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0)
1442 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001443
Hai Shalom021b0b52019-04-10 11:17:58 -07001444 status = DPP_STATUS_OK;
1445#ifdef CONFIG_TESTING_OPTIONS
1446 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1447 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1448 status = DPP_STATUS_CONFIG_REJECTED;
1449 }
1450#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001451fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001452 if (status != DPP_STATUS_OK) {
1453 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1454 wpas_notify_dpp_configuration_failure(wpa_s);
1455 }
1456#ifdef CONFIG_DPP2
1457 if (auth->peer_version >= 2 &&
1458 auth->conf_resp_status == DPP_STATUS_OK) {
1459 struct wpabuf *msg;
1460
1461 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1462 msg = dpp_build_conf_result(auth, status);
1463 if (!msg)
1464 goto fail2;
1465
1466 wpa_msg(wpa_s, MSG_INFO,
1467 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1468 MAC2STR(addr), auth->curr_freq,
1469 DPP_PA_CONFIGURATION_RESULT);
1470 offchannel_send_action(wpa_s, auth->curr_freq,
1471 addr, wpa_s->own_addr, broadcast,
1472 wpabuf_head(msg),
1473 wpabuf_len(msg),
1474 500, wpas_dpp_tx_status, 0);
1475 wpabuf_free(msg);
1476
1477 /* This exchange will be terminated in the TX status handler */
1478 return;
1479 }
1480fail2:
1481#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001482 dpp_auth_deinit(wpa_s->dpp_auth);
1483 wpa_s->dpp_auth = NULL;
1484}
1485
1486
1487static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1488{
1489 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001490 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001491 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001492 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001493
1494 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001495 offchannel_send_action_done(wpa_s);
1496 wpas_dpp_listen_stop(wpa_s);
1497
Hai Shalomc3565922019-10-28 11:58:20 -07001498 supp_op_classes = wpas_supp_op_classes(wpa_s);
1499 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001500 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001501 wpa_s->conf->dpp_mud_url,
1502 supp_op_classes);
1503 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001504 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001505 wpa_printf(MSG_DEBUG,
1506 "DPP: No configuration request data available");
1507 return;
1508 }
1509
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001510 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1511 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1512
1513 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Hai Shalomb755a2a2020-04-23 21:49:02 -07001514 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001515 if (res < 0) {
1516 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1517 wpabuf_free(buf);
1518 } else {
1519 wpa_printf(MSG_DEBUG,
1520 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001521 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001522 }
1523}
1524
1525
1526static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1527{
1528 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1529 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001530 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001531#ifdef CONFIG_TESTING_OPTIONS
1532 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1533 wpa_printf(MSG_INFO,
1534 "DPP: TESTING - stop at Authentication Confirm");
1535 if (wpa_s->dpp_auth->configurator) {
1536 /* Prevent GAS response */
1537 wpa_s->dpp_auth->auth_success = 0;
1538 }
1539 return;
1540 }
1541#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001542
1543 if (wpa_s->dpp_auth->configurator)
1544 wpas_dpp_start_gas_server(wpa_s);
1545 else
1546 wpas_dpp_start_gas_client(wpa_s);
1547}
1548
1549
1550static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001551 const u8 *hdr, const u8 *buf, size_t len,
1552 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001553{
1554 struct dpp_authentication *auth = wpa_s->dpp_auth;
1555 struct wpabuf *msg;
1556
Roshan Pius3a1667e2018-07-03 15:17:14 -07001557 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1558 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001559
1560 if (!auth) {
1561 wpa_printf(MSG_DEBUG,
1562 "DPP: No DPP Authentication in progress - drop");
1563 return;
1564 }
1565
1566 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1567 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1568 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1569 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1570 return;
1571 }
1572
1573 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1574
Roshan Pius3a1667e2018-07-03 15:17:14 -07001575 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1576 wpa_printf(MSG_DEBUG,
1577 "DPP: Responder accepted request for different negotiation channel");
1578 auth->curr_freq = freq;
1579 }
1580
1581 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001582 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1583 if (!msg) {
1584 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1585 wpa_printf(MSG_DEBUG,
1586 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001587 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001588 offchannel_send_action_done(wpa_s);
1589 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1590 return;
1591 }
1592 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1593 return;
1594 }
1595 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1596
Roshan Pius3a1667e2018-07-03 15:17:14 -07001597 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1598 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001599 offchannel_send_action(wpa_s, auth->curr_freq,
1600 src, wpa_s->own_addr, broadcast,
1601 wpabuf_head(msg), wpabuf_len(msg),
1602 500, wpas_dpp_tx_status, 0);
1603 wpabuf_free(msg);
1604 wpa_s->dpp_auth_ok_on_ack = 1;
1605}
1606
1607
1608static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1609 const u8 *hdr, const u8 *buf, size_t len)
1610{
1611 struct dpp_authentication *auth = wpa_s->dpp_auth;
1612
1613 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1614 MAC2STR(src));
1615
1616 if (!auth) {
1617 wpa_printf(MSG_DEBUG,
1618 "DPP: No DPP Authentication in progress - drop");
1619 return;
1620 }
1621
1622 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1623 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1624 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1625 return;
1626 }
1627
1628 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1629 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001630 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001631 return;
1632 }
1633
1634 wpas_dpp_auth_success(wpa_s, 0);
1635}
1636
1637
Hai Shalom021b0b52019-04-10 11:17:58 -07001638#ifdef CONFIG_DPP2
1639
1640static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
1641 void *timeout_ctx)
1642{
1643 struct wpa_supplicant *wpa_s = eloop_ctx;
1644 struct dpp_authentication *auth = wpa_s->dpp_auth;
1645
1646 if (!auth || !auth->waiting_conf_result)
1647 return;
1648
1649 wpa_printf(MSG_DEBUG,
1650 "DPP: Timeout while waiting for Configuration Result");
1651 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001652 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07001653 dpp_auth_deinit(auth);
1654 wpa_s->dpp_auth = NULL;
1655}
1656
1657
Hai Shalomc3565922019-10-28 11:58:20 -07001658static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1659 void *timeout_ctx)
1660{
1661 struct wpa_supplicant *wpa_s = eloop_ctx;
1662 struct dpp_authentication *auth = wpa_s->dpp_auth;
1663
1664 if (!auth || !auth->waiting_conn_status_result)
1665 return;
1666
1667 wpa_printf(MSG_DEBUG,
1668 "DPP: Timeout while waiting for Connection Status Result");
1669 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08001670 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001671 wpas_dpp_listen_stop(wpa_s);
1672 dpp_auth_deinit(auth);
1673 wpa_s->dpp_auth = NULL;
1674}
1675
1676
Hai Shalom021b0b52019-04-10 11:17:58 -07001677static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
1678 const u8 *hdr, const u8 *buf, size_t len)
1679{
1680 struct dpp_authentication *auth = wpa_s->dpp_auth;
1681 enum dpp_status_error status;
1682
1683 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1684 MAC2STR(src));
1685
1686 if (!auth || !auth->waiting_conf_result) {
1687 wpa_printf(MSG_DEBUG,
1688 "DPP: No DPP Configuration waiting for result - drop");
1689 return;
1690 }
1691
1692 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1693 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1694 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1695 return;
1696 }
1697
1698 status = dpp_conf_result_rx(auth, hdr, buf, len);
1699
Hai Shalomc3565922019-10-28 11:58:20 -07001700 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1701 wpa_msg(wpa_s, MSG_INFO,
1702 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1703 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08001704 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001705 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
1706 wpa_s, NULL);
1707 auth->waiting_conn_status_result = 1;
1708 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1709 wpa_s, NULL);
1710 eloop_register_timeout(16, 0,
1711 wpas_dpp_conn_status_result_wait_timeout,
1712 wpa_s, NULL);
1713 offchannel_send_action_done(wpa_s);
1714 wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq :
1715 auth->curr_freq);
1716 return;
1717 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001718 offchannel_send_action_done(wpa_s);
1719 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001720 if (status == DPP_STATUS_OK) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001721 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalome4073332019-11-05 16:20:12 -08001722 wpas_notify_dpp_config_sent(wpa_s);
1723 }
1724 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07001725 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001726 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001727 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001728 dpp_auth_deinit(auth);
1729 wpa_s->dpp_auth = NULL;
1730 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
1731}
1732
Hai Shalom81f62d82019-07-22 12:10:00 -07001733
Hai Shalomc3565922019-10-28 11:58:20 -07001734static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
1735 const u8 *src, const u8 *hdr,
1736 const u8 *buf, size_t len)
1737{
1738 struct dpp_authentication *auth = wpa_s->dpp_auth;
1739 enum dpp_status_error status;
1740 u8 ssid[SSID_MAX_LEN];
1741 size_t ssid_len = 0;
1742 char *channel_list = NULL;
1743
1744 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1745
1746 if (!auth || !auth->waiting_conn_status_result) {
1747 wpa_printf(MSG_DEBUG,
1748 "DPP: No DPP Configuration waiting for connection status result - drop");
1749 return;
1750 }
1751
1752 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1753 ssid, &ssid_len, &channel_list);
1754 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1755 "result=%d ssid=%s channel_list=%s",
1756 status, wpa_ssid_txt(ssid, ssid_len),
1757 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08001758 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
1759 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07001760 os_free(channel_list);
1761 offchannel_send_action_done(wpa_s);
1762 wpas_dpp_listen_stop(wpa_s);
1763 dpp_auth_deinit(auth);
1764 wpa_s->dpp_auth = NULL;
1765 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1766 wpa_s, NULL);
1767}
1768
1769
Hai Shalom81f62d82019-07-22 12:10:00 -07001770static int wpas_dpp_process_conf_obj(void *ctx,
1771 struct dpp_authentication *auth)
1772{
1773 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07001774 unsigned int i;
1775 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001776
Hai Shalomc3565922019-10-28 11:58:20 -07001777 for (i = 0; i < auth->num_conf_obj; i++) {
1778 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1779 &auth->conf_obj[i]);
1780 if (res)
1781 break;
1782 }
1783 if (!res)
1784 wpas_dpp_post_process_config(wpa_s, auth);
1785
1786 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07001787}
1788
Hai Shalomfdcde762020-04-02 11:19:20 -07001789
1790static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
1791{
1792 struct wpa_supplicant *wpa_s = ctx;
1793
1794 if (bi == wpa_s->dpp_chirp_bi)
1795 wpas_dpp_chirp_stop(wpa_s);
1796}
1797
1798
1799static void
1800wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
1801 const u8 *hdr, const u8 *buf, size_t len,
1802 unsigned int freq)
1803{
1804 const u8 *r_bootstrap;
1805 u16 r_bootstrap_len;
1806 struct dpp_bootstrap_info *peer_bi;
1807 struct dpp_authentication *auth;
1808
1809 if (!wpa_s->dpp)
1810 return;
1811
1812 if (wpa_s->dpp_auth) {
1813 wpa_printf(MSG_DEBUG,
1814 "DPP: Ignore Presence Announcement during ongoing Authentication");
1815 return;
1816 }
1817
1818 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR,
1819 MAC2STR(src));
1820
1821 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1822 &r_bootstrap_len);
1823 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1824 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1825 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
1826 return;
1827 }
1828 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1829 r_bootstrap, r_bootstrap_len);
1830 peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap);
1831 if (!peer_bi) {
1832 wpa_printf(MSG_DEBUG,
1833 "DPP: No matching bootstrapping information found");
1834 return;
1835 }
1836
1837 auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL,
1838 DPP_CAPAB_CONFIGURATOR, freq, NULL, 0);
1839 if (!auth)
1840 return;
1841 wpas_dpp_set_testing_options(wpa_s, auth);
1842 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
1843 dpp_auth_deinit(auth);
1844 return;
1845 }
1846
1847 auth->neg_freq = freq;
1848
1849 if (!is_zero_ether_addr(peer_bi->mac_addr))
1850 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
1851
1852 wpa_s->dpp_auth = auth;
1853 if (wpas_dpp_auth_init_next(wpa_s) < 0) {
1854 dpp_auth_deinit(wpa_s->dpp_auth);
1855 wpa_s->dpp_auth = NULL;
1856 }
1857}
1858
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001859
1860static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
1861 void *timeout_ctx)
1862{
1863 struct wpa_supplicant *wpa_s = eloop_ctx;
1864 struct dpp_authentication *auth = wpa_s->dpp_auth;
1865
1866 if (!auth)
1867 return;
1868
1869 wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout");
1870 offchannel_send_action_done(wpa_s);
1871 wpas_dpp_listen_stop(wpa_s);
1872 dpp_auth_deinit(auth);
1873 wpa_s->dpp_auth = NULL;
1874}
1875
1876
1877static void
1878wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
1879 const u8 *hdr, const u8 *buf, size_t len,
1880 unsigned int freq)
1881{
1882 const u8 *csign_hash;
1883 u16 csign_hash_len;
1884 struct dpp_configurator *conf;
1885 struct dpp_authentication *auth;
1886 unsigned int wait_time, max_wait_time;
1887
1888 if (!wpa_s->dpp)
1889 return;
1890
1891 if (wpa_s->dpp_auth) {
1892 wpa_printf(MSG_DEBUG,
1893 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1894 return;
1895 }
1896
1897 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR,
1898 MAC2STR(src));
1899
1900 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1901 &csign_hash_len);
1902 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
1903 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1904 "Missing or invalid required Configurator C-sign key Hash attribute");
1905 return;
1906 }
1907 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1908 csign_hash, csign_hash_len);
1909 conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash);
1910 if (!conf) {
1911 wpa_printf(MSG_DEBUG,
1912 "DPP: No matching Configurator information found");
1913 return;
1914 }
1915
1916 auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq);
1917 if (!auth)
1918 return;
1919 wpas_dpp_set_testing_options(wpa_s, auth);
1920 if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) {
1921 dpp_auth_deinit(auth);
1922 return;
1923 }
1924
1925 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1926 wpa_s->dpp_auth = auth;
1927
1928 wpa_s->dpp_in_response_listen = 0;
1929 wpa_s->dpp_auth_ok_on_ack = 0;
1930 wait_time = wpa_s->max_remain_on_chan;
1931 max_wait_time = wpa_s->dpp_resp_wait_time ?
1932 wpa_s->dpp_resp_wait_time : 2000;
1933 if (wait_time > max_wait_time)
1934 wait_time = max_wait_time;
1935 wait_time += 10; /* give the driver some extra time to complete */
1936 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
1937 wpas_dpp_reconfig_reply_wait_timeout,
1938 wpa_s, NULL);
1939 wait_time -= 10;
1940
1941 wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time);
1942
1943 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1944 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ);
1945 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
1946 wpabuf_head(auth->reconfig_req_msg),
1947 wpabuf_len(auth->reconfig_req_msg),
1948 wait_time, wpas_dpp_tx_status, 0) < 0) {
1949 dpp_auth_deinit(wpa_s->dpp_auth);
1950 wpa_s->dpp_auth = NULL;
1951 }
1952}
1953
1954
1955static void
1956wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1957 const u8 *hdr, const u8 *buf, size_t len,
1958 unsigned int freq)
1959{
1960 struct wpa_ssid *ssid;
1961 struct dpp_authentication *auth;
1962
1963 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from "
1964 MACSTR, MAC2STR(src));
1965
1966 if (!wpa_s->dpp || wpa_s->dpp_auth ||
1967 !wpa_s->dpp_reconfig_announcement || !wpa_s->dpp_reconfig_ssid)
1968 return;
1969 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1970 if (ssid == wpa_s->dpp_reconfig_ssid &&
1971 ssid->id == wpa_s->dpp_reconfig_ssid_id)
1972 break;
1973 }
1974 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
1975 !ssid->dpp_csign)
1976 return;
1977
1978 auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector,
1979 ssid->dpp_netaccesskey,
1980 ssid->dpp_netaccesskey_len,
1981 ssid->dpp_csign, ssid->dpp_csign_len,
1982 freq, hdr, buf, len);
1983 if (!auth)
1984 return;
1985 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1986 wpa_s->dpp_auth = auth;
1987
1988 wpas_dpp_chirp_stop(wpa_s);
1989
1990 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1991 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP);
1992 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
1993 wpabuf_head(auth->reconfig_resp_msg),
1994 wpabuf_len(auth->reconfig_resp_msg),
1995 500, wpas_dpp_tx_status, 0) < 0) {
1996 dpp_auth_deinit(wpa_s->dpp_auth);
1997 wpa_s->dpp_auth = NULL;
1998 }
1999}
2000
2001
2002static void
2003wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2004 const u8 *hdr, const u8 *buf, size_t len,
2005 unsigned int freq)
2006{
2007 struct dpp_authentication *auth = wpa_s->dpp_auth;
2008 struct wpabuf *conf;
2009
2010 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from "
2011 MACSTR, MAC2STR(src));
2012
2013 if (!auth || !auth->reconfig || !auth->configurator) {
2014 wpa_printf(MSG_DEBUG,
2015 "DPP: No DPP Reconfig Authentication in progress - drop");
2016 return;
2017 }
2018
2019 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2020 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2021 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2022 return;
2023 }
2024
2025 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
2026 if (!conf)
2027 return;
2028
2029 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL);
2030
2031 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2032 MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF);
2033 if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast,
2034 wpabuf_head(conf), wpabuf_len(conf),
2035 500, wpas_dpp_tx_status, 0) < 0) {
2036 wpabuf_free(conf);
2037 dpp_auth_deinit(wpa_s->dpp_auth);
2038 wpa_s->dpp_auth = NULL;
2039 return;
2040 }
2041 wpabuf_free(conf);
2042
2043 wpas_dpp_start_gas_server(wpa_s);
2044}
2045
2046
2047static void
2048wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
2049 const u8 *hdr, const u8 *buf, size_t len,
2050 unsigned int freq)
2051{
2052 struct dpp_authentication *auth = wpa_s->dpp_auth;
2053
2054 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from "
2055 MACSTR, MAC2STR(src));
2056
2057 if (!auth || !auth->reconfig || auth->configurator) {
2058 wpa_printf(MSG_DEBUG,
2059 "DPP: No DPP Reconfig Authentication in progress - drop");
2060 return;
2061 }
2062
2063 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
2064 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
2065 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
2066 return;
2067 }
2068
2069 if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0)
2070 return;
2071
2072 wpas_dpp_start_gas_client(wpa_s);
2073}
2074
Hai Shalom021b0b52019-04-10 11:17:58 -07002075#endif /* CONFIG_DPP2 */
2076
2077
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002078static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
2079 const u8 *src,
2080 const u8 *buf, size_t len)
2081{
2082 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002083 const u8 *connector, *trans_id, *status;
2084 u16 connector_len, trans_id_len, status_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002085#ifdef CONFIG_DPP2
2086 const u8 *version;
2087 u16 version_len;
2088#endif /* CONFIG_DPP2 */
2089 u8 peer_version = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002090 struct dpp_introduction intro;
2091 struct rsn_pmksa_cache_entry *entry;
2092 struct os_time now;
2093 struct os_reltime rnow;
2094 os_time_t expiry;
2095 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002096 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002097
2098 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
2099 MAC2STR(src));
2100 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
2101 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
2102 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
2103 MACSTR " - drop", MAC2STR(src));
2104 return;
2105 }
2106 offchannel_send_action_done(wpa_s);
2107
2108 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2109 if (ssid == wpa_s->dpp_intro_network)
2110 break;
2111 }
2112 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2113 !ssid->dpp_csign) {
2114 wpa_printf(MSG_DEBUG,
2115 "DPP: Profile not found for network introduction");
2116 return;
2117 }
2118
2119 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
2120 &trans_id_len);
2121 if (!trans_id || trans_id_len != 1) {
2122 wpa_printf(MSG_DEBUG,
2123 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002124 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2125 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002126 goto fail;
2127 }
2128 if (trans_id[0] != TRANSACTION_ID) {
2129 wpa_printf(MSG_DEBUG,
2130 "DPP: Ignore frame with unexpected Transaction ID %u",
2131 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002132 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2133 " fail=transaction_id_mismatch", MAC2STR(src));
2134 goto fail;
2135 }
2136
2137 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
2138 if (!status || status_len != 1) {
2139 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
2140 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2141 " fail=missing_status", MAC2STR(src));
2142 goto fail;
2143 }
2144 if (status[0] != DPP_STATUS_OK) {
2145 wpa_printf(MSG_DEBUG,
2146 "DPP: Peer rejected network introduction: Status %u",
2147 status[0]);
2148 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2149 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07002150#ifdef CONFIG_DPP2
2151 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
2152#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002153 goto fail;
2154 }
2155
2156 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
2157 if (!connector) {
2158 wpa_printf(MSG_DEBUG,
2159 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002160 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2161 " fail=missing_connector", MAC2STR(src));
2162 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002163 }
2164
Roshan Pius3a1667e2018-07-03 15:17:14 -07002165 res = dpp_peer_intro(&intro, ssid->dpp_connector,
2166 ssid->dpp_netaccesskey,
2167 ssid->dpp_netaccesskey_len,
2168 ssid->dpp_csign,
2169 ssid->dpp_csign_len,
2170 connector, connector_len, &expiry);
2171 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002172 wpa_printf(MSG_INFO,
2173 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002174 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
2175 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07002176#ifdef CONFIG_DPP2
2177 wpas_dpp_send_conn_status_result(wpa_s, res);
2178#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002179 goto fail;
2180 }
2181
2182 entry = os_zalloc(sizeof(*entry));
2183 if (!entry)
2184 goto fail;
2185 os_memcpy(entry->aa, src, ETH_ALEN);
2186 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
2187 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
2188 entry->pmk_len = intro.pmk_len;
2189 entry->akmp = WPA_KEY_MGMT_DPP;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002190#ifdef CONFIG_DPP2
2191 version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
2192 &version_len);
2193 if (version && version_len >= 1)
2194 peer_version = version[0];
2195 entry->dpp_pfs = peer_version >= 2;
2196#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002197 if (expiry) {
2198 os_get_time(&now);
2199 seconds = expiry - now.sec;
2200 } else {
2201 seconds = 86400 * 7;
2202 }
2203 os_get_reltime(&rnow);
2204 entry->expiration = rnow.sec + seconds;
2205 entry->reauth_time = rnow.sec + seconds;
2206 entry->network_ctx = ssid;
2207 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
2208
Roshan Pius3a1667e2018-07-03 15:17:14 -07002209 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002210 " status=%u version=%u", MAC2STR(src), status[0], peer_version);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002211
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002212 wpa_printf(MSG_DEBUG,
2213 "DPP: Try connection again after successful network introduction");
2214 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
2215 wpa_supplicant_cancel_sched_scan(wpa_s);
2216 wpa_supplicant_req_scan(wpa_s, 0, 0);
2217 }
2218fail:
2219 os_memset(&intro, 0, sizeof(intro));
2220}
2221
2222
Roshan Pius3a1667e2018-07-03 15:17:14 -07002223static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
2224{
2225 int i, j;
2226
2227 if (!wpa_s->hw.modes)
2228 return -1;
2229
2230 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2231 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
2232
2233 for (j = 0; j < mode->num_channels; j++) {
2234 struct hostapd_channel_data *chan = &mode->channels[j];
2235
2236 if (chan->freq != (int) freq)
2237 continue;
2238
2239 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
2240 HOSTAPD_CHAN_NO_IR |
2241 HOSTAPD_CHAN_RADAR))
2242 continue;
2243
2244 return 1;
2245 }
2246 }
2247
2248 wpa_printf(MSG_DEBUG,
2249 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
2250 freq);
2251
2252 return 0;
2253}
2254
2255
2256static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
2257 struct dpp_pkex *pkex)
2258{
2259 if (pkex->freq == 2437)
2260 pkex->freq = 5745;
2261 else if (pkex->freq == 5745)
2262 pkex->freq = 5220;
2263 else if (pkex->freq == 5220)
2264 pkex->freq = 60480;
2265 else
2266 return -1; /* no more channels to try */
2267
2268 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
2269 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
2270 pkex->freq);
2271 return 0;
2272 }
2273
2274 /* Could not use this channel - try the next one */
2275 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
2276}
2277
2278
2279static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
2280{
2281 struct wpa_supplicant *wpa_s = eloop_ctx;
2282 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2283
2284 if (!pkex || !pkex->exchange_req)
2285 return;
2286 if (pkex->exch_req_tries >= 5) {
2287 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
2288 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
2289 "No response from PKEX peer");
2290 dpp_pkex_free(pkex);
2291 wpa_s->dpp_pkex = NULL;
2292 return;
2293 }
2294 pkex->exch_req_tries = 0;
2295 }
2296
2297 pkex->exch_req_tries++;
2298 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
2299 pkex->exch_req_tries);
2300 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2301 MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
2302 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2303 wpa_s->own_addr, broadcast,
2304 wpabuf_head(pkex->exchange_req),
2305 wpabuf_len(pkex->exchange_req),
2306 pkex->exch_req_wait_time,
2307 wpas_dpp_tx_pkex_status, 0);
2308}
2309
2310
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002311static void
2312wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
2313 unsigned int freq, const u8 *dst,
2314 const u8 *src, const u8 *bssid,
2315 const u8 *data, size_t data_len,
2316 enum offchannel_send_action_result result)
2317{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002318 const char *res_txt;
2319 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2320
2321 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2322 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2323 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002324 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2325 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002326 freq, MAC2STR(dst), res_txt);
2327 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2328 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
2329
2330 if (!pkex) {
2331 wpa_printf(MSG_DEBUG,
2332 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
2333 return;
2334 }
2335
2336 if (pkex->failed) {
2337 wpa_printf(MSG_DEBUG,
2338 "DPP: Terminate PKEX exchange due to an earlier error");
2339 if (pkex->t > pkex->own_bi->pkex_t)
2340 pkex->own_bi->pkex_t = pkex->t;
2341 dpp_pkex_free(pkex);
2342 wpa_s->dpp_pkex = NULL;
2343 return;
2344 }
2345
2346 if (pkex->exch_req_wait_time && pkex->exchange_req) {
2347 /* Wait for PKEX Exchange Response frame and retry request if
2348 * no response is seen. */
2349 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
2350 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
2351 (pkex->exch_req_wait_time % 1000) * 1000,
2352 wpas_dpp_pkex_retry_timeout, wpa_s,
2353 NULL);
2354 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002355}
2356
2357
2358static void
2359wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
2360 const u8 *buf, size_t len, unsigned int freq)
2361{
2362 struct wpabuf *msg;
2363 unsigned int wait_time;
2364
2365 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
2366 MAC2STR(src));
2367
2368 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2369 * values here */
2370
2371 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
2372 wpa_printf(MSG_DEBUG,
2373 "DPP: No PKEX code configured - ignore request");
2374 return;
2375 }
2376
2377 if (wpa_s->dpp_pkex) {
2378 /* TODO: Support parallel operations */
2379 wpa_printf(MSG_DEBUG,
2380 "DPP: Already in PKEX session - ignore new request");
2381 return;
2382 }
2383
Roshan Pius3a1667e2018-07-03 15:17:14 -07002384 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002385 wpa_s->own_addr, src,
2386 wpa_s->dpp_pkex_identifier,
2387 wpa_s->dpp_pkex_code,
2388 buf, len);
2389 if (!wpa_s->dpp_pkex) {
2390 wpa_printf(MSG_DEBUG,
2391 "DPP: Failed to process the request - ignore it");
2392 return;
2393 }
2394
2395 msg = wpa_s->dpp_pkex->exchange_resp;
2396 wait_time = wpa_s->max_remain_on_chan;
2397 if (wait_time > 2000)
2398 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002399 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2400 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002401 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2402 broadcast,
2403 wpabuf_head(msg), wpabuf_len(msg),
2404 wait_time, wpas_dpp_tx_pkex_status, 0);
2405}
2406
2407
2408static void
2409wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2410 const u8 *buf, size_t len, unsigned int freq)
2411{
2412 struct wpabuf *msg;
2413 unsigned int wait_time;
2414
2415 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
2416 MAC2STR(src));
2417
2418 /* TODO: Support multiple PKEX codes by iterating over all the enabled
2419 * values here */
2420
2421 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
2422 wpa_s->dpp_pkex->exchange_done) {
2423 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2424 return;
2425 }
2426
Roshan Pius3a1667e2018-07-03 15:17:14 -07002427 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
2428 wpa_s->dpp_pkex->exch_req_wait_time = 0;
2429
2430 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002431 if (!msg) {
2432 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2433 return;
2434 }
2435
2436 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
2437 MAC2STR(src));
2438
2439 wait_time = wpa_s->max_remain_on_chan;
2440 if (wait_time > 2000)
2441 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002442 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2443 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002444 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2445 broadcast,
2446 wpabuf_head(msg), wpabuf_len(msg),
2447 wait_time, wpas_dpp_tx_pkex_status, 0);
2448 wpabuf_free(msg);
2449}
2450
2451
Roshan Pius3a1667e2018-07-03 15:17:14 -07002452static struct dpp_bootstrap_info *
2453wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
2454 unsigned int freq)
2455{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002456 struct dpp_bootstrap_info *bi;
2457
Hai Shalom021b0b52019-04-10 11:17:58 -07002458 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002459 if (!bi)
2460 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002461 wpa_s->dpp_pkex = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002462 return bi;
2463}
2464
2465
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002466static void
2467wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
2468 const u8 *hdr, const u8 *buf, size_t len,
2469 unsigned int freq)
2470{
2471 struct wpabuf *msg;
2472 unsigned int wait_time;
2473 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002474
2475 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
2476 MAC2STR(src));
2477
2478 if (!pkex || pkex->initiator || !pkex->exchange_done) {
2479 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2480 return;
2481 }
2482
2483 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
2484 if (!msg) {
2485 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002486 if (pkex->failed) {
2487 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
2488 if (pkex->t > pkex->own_bi->pkex_t)
2489 pkex->own_bi->pkex_t = pkex->t;
2490 dpp_pkex_free(wpa_s->dpp_pkex);
2491 wpa_s->dpp_pkex = NULL;
2492 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002493 return;
2494 }
2495
2496 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
2497 MACSTR, MAC2STR(src));
2498
2499 wait_time = wpa_s->max_remain_on_chan;
2500 if (wait_time > 2000)
2501 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002502 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2503 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002504 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2505 broadcast,
2506 wpabuf_head(msg), wpabuf_len(msg),
2507 wait_time, wpas_dpp_tx_pkex_status, 0);
2508 wpabuf_free(msg);
2509
Roshan Pius3a1667e2018-07-03 15:17:14 -07002510 wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002511}
2512
2513
2514static void
2515wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2516 const u8 *hdr, const u8 *buf, size_t len,
2517 unsigned int freq)
2518{
2519 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002520 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002521 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2522 char cmd[500];
2523
2524 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2525 MAC2STR(src));
2526
2527 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2528 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2529 return;
2530 }
2531
2532 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2533 if (res < 0) {
2534 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2535 return;
2536 }
2537
Roshan Pius3a1667e2018-07-03 15:17:14 -07002538 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002539 if (!bi)
2540 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002541
2542 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2543 bi->id,
2544 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
2545 wpa_printf(MSG_DEBUG,
2546 "DPP: Start authentication after PKEX with parameters: %s",
2547 cmd);
2548 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
2549 wpa_printf(MSG_DEBUG,
2550 "DPP: Authentication initialization failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07002551 offchannel_send_action_done(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002552 return;
2553 }
2554}
2555
2556
2557void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
2558 const u8 *buf, size_t len, unsigned int freq)
2559{
2560 u8 crypto_suite;
2561 enum dpp_public_action_frame_type type;
2562 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002563 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002564
2565 if (len < DPP_HDR_LEN)
2566 return;
2567 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2568 return;
2569 hdr = buf;
2570 buf += 4;
2571 len -= 4;
2572 crypto_suite = *buf++;
2573 type = *buf++;
2574 len -= 2;
2575
2576 wpa_printf(MSG_DEBUG,
2577 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2578 MACSTR " freq=%u",
2579 crypto_suite, type, MAC2STR(src), freq);
2580 if (crypto_suite != 1) {
2581 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2582 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002583 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2584 " freq=%u type=%d ignore=unsupported-crypto-suite",
2585 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002586 return;
2587 }
2588 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002589 if (dpp_check_attrs(buf, len) < 0) {
2590 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2591 " freq=%u type=%d ignore=invalid-attributes",
2592 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002593 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002594 }
2595 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
2596 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002597
2598 switch (type) {
2599 case DPP_PA_AUTHENTICATION_REQ:
2600 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
2601 break;
2602 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002603 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002604 break;
2605 case DPP_PA_AUTHENTICATION_CONF:
2606 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
2607 break;
2608 case DPP_PA_PEER_DISCOVERY_RESP:
2609 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
2610 break;
2611 case DPP_PA_PKEX_EXCHANGE_REQ:
2612 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
2613 break;
2614 case DPP_PA_PKEX_EXCHANGE_RESP:
2615 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
2616 break;
2617 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2618 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
2619 freq);
2620 break;
2621 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2622 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
2623 freq);
2624 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002625#ifdef CONFIG_DPP2
2626 case DPP_PA_CONFIGURATION_RESULT:
2627 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
2628 break;
Hai Shalomc3565922019-10-28 11:58:20 -07002629 case DPP_PA_CONNECTION_STATUS_RESULT:
2630 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
2631 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07002632 case DPP_PA_PRESENCE_ANNOUNCEMENT:
2633 wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len,
2634 freq);
2635 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002636 case DPP_PA_RECONFIG_ANNOUNCEMENT:
2637 wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len,
2638 freq);
2639 break;
2640 case DPP_PA_RECONFIG_AUTH_REQ:
2641 wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq);
2642 break;
2643 case DPP_PA_RECONFIG_AUTH_RESP:
2644 wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq);
2645 break;
2646 case DPP_PA_RECONFIG_AUTH_CONF:
2647 wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq);
2648 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002649#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002650 default:
2651 wpa_printf(MSG_DEBUG,
2652 "DPP: Ignored unsupported frame subtype %d", type);
2653 break;
2654 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002655
2656 if (wpa_s->dpp_pkex)
2657 pkex_t = wpa_s->dpp_pkex->t;
2658 else if (wpa_s->dpp_pkex_bi)
2659 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
2660 else
2661 pkex_t = 0;
2662 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2663 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2664 wpas_dpp_pkex_remove(wpa_s, "*");
2665 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002666}
2667
2668
2669static struct wpabuf *
2670wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query,
2671 size_t query_len)
2672{
2673 struct wpa_supplicant *wpa_s = ctx;
2674 struct dpp_authentication *auth = wpa_s->dpp_auth;
2675 struct wpabuf *resp;
2676
2677 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
2678 MAC2STR(sa));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002679 if (!auth || (!auth->auth_success && !auth->reconfig_success) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002680 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
2681 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2682 return NULL;
2683 }
Hai Shalomc3565922019-10-28 11:58:20 -07002684
2685 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
2686 wpa_printf(MSG_DEBUG,
2687 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
2688 /* wpas_dpp_auth_success() would normally have been called from
2689 * TX status handler, but since there was no such handler call
2690 * yet, simply send out the event message and proceed with
2691 * exchange. */
2692 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
2693 wpa_s->dpp_auth_ok_on_ack = 0;
2694 }
2695
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002696 wpa_hexdump(MSG_DEBUG,
2697 "DPP: Received Configuration Request (GAS Query Request)",
2698 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002699 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2700 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002701 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom59532852018-12-07 10:32:58 -08002702 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002703 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002704 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002705 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002706 auth->conf_resp = resp;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002707 return resp;
2708}
2709
2710
2711static void
2712wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
2713{
2714 struct wpa_supplicant *wpa_s = ctx;
2715 struct dpp_authentication *auth = wpa_s->dpp_auth;
2716
2717 if (!auth) {
2718 wpabuf_free(resp);
2719 return;
2720 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002721 if (auth->conf_resp != resp) {
2722 wpa_printf(MSG_DEBUG,
2723 "DPP: Ignore GAS status report (ok=%d) for unknown response",
2724 ok);
2725 wpabuf_free(resp);
2726 return;
2727 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002728
2729 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2730 ok);
2731 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002732 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002733#ifdef CONFIG_DPP2
2734 if (ok && auth->peer_version >= 2 &&
2735 auth->conf_resp_status == DPP_STATUS_OK) {
2736 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08002737 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002738 auth->waiting_conf_result = 1;
2739 auth->conf_resp = NULL;
2740 wpabuf_free(resp);
2741 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2742 wpa_s, NULL);
2743 eloop_register_timeout(2, 0,
2744 wpas_dpp_config_result_wait_timeout,
2745 wpa_s, NULL);
2746 return;
2747 }
2748#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002749 offchannel_send_action_done(wpa_s);
2750 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002751 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002752 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08002753 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002754 }
2755 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002756 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002757 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002758 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002759 dpp_auth_deinit(wpa_s->dpp_auth);
2760 wpa_s->dpp_auth = NULL;
2761 wpabuf_free(resp);
2762}
2763
2764
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002765int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
2766{
2767 struct dpp_authentication *auth;
2768 int ret = -1;
2769 char *curve = NULL;
2770
Hai Shalomfdcde762020-04-02 11:19:20 -07002771 auth = dpp_alloc_auth(wpa_s->dpp, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002772 if (!auth)
2773 return -1;
2774
2775 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08002776 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalomfdcde762020-04-02 11:19:20 -07002777 if (dpp_set_configurator(auth, cmd) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07002778 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002779 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
2780 &auth->conf_obj[0]);
2781 if (!ret)
2782 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002783
2784 dpp_auth_deinit(auth);
2785 os_free(curve);
2786
2787 return ret;
2788}
2789
2790
2791static void
2792wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
2793 unsigned int freq, const u8 *dst,
2794 const u8 *src, const u8 *bssid,
2795 const u8 *data, size_t data_len,
2796 enum offchannel_send_action_result result)
2797{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002798 const char *res_txt;
2799
2800 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2801 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2802 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002803 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2804 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002805 freq, MAC2STR(dst), res_txt);
2806 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2807 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002808 /* TODO: Time out wait for response more quickly in error cases? */
2809}
2810
2811
2812int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2813 struct wpa_bss *bss)
2814{
2815 struct os_time now;
2816 struct wpabuf *msg;
2817 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07002818 const u8 *rsn;
2819 struct wpa_ie_data ied;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002820 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002821
2822 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
2823 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07002824 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2825 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
2826 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
2827 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002828 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
2829 return 0; /* PMKSA exists for DPP AKM - continue */
2830
2831 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2832 !ssid->dpp_csign) {
2833 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2834 "missing %s",
2835 !ssid->dpp_connector ? "Connector" :
2836 (!ssid->dpp_netaccesskey ? "netAccessKey" :
2837 "C-sign-key"));
2838 return -1;
2839 }
2840
2841 os_get_time(&now);
2842
2843 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002844 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002845 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2846 "netAccessKey expired");
2847 return -1;
2848 }
2849
2850 wpa_printf(MSG_DEBUG,
2851 "DPP: Starting network introduction protocol to derive PMKSA for "
2852 MACSTR, MAC2STR(bss->bssid));
2853
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002854 len = 5 + 4 + os_strlen(ssid->dpp_connector);
2855#ifdef CONFIG_DPP2
2856 len += 5;
2857#endif /* CONFIG_DPP2 */
2858 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002859 if (!msg)
2860 return -1;
2861
Roshan Pius3a1667e2018-07-03 15:17:14 -07002862#ifdef CONFIG_TESTING_OPTIONS
2863 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
2864 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
2865 goto skip_trans_id;
2866 }
2867 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
2868 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
2869 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2870 wpabuf_put_le16(msg, 0);
2871 goto skip_trans_id;
2872 }
2873#endif /* CONFIG_TESTING_OPTIONS */
2874
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002875 /* Transaction ID */
2876 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2877 wpabuf_put_le16(msg, 1);
2878 wpabuf_put_u8(msg, TRANSACTION_ID);
2879
Roshan Pius3a1667e2018-07-03 15:17:14 -07002880#ifdef CONFIG_TESTING_OPTIONS
2881skip_trans_id:
2882 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
2883 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
2884 goto skip_connector;
2885 }
2886 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
2887 char *connector;
2888
2889 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
2890 connector = dpp_corrupt_connector_signature(
2891 ssid->dpp_connector);
2892 if (!connector) {
2893 wpabuf_free(msg);
2894 return -1;
2895 }
2896 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2897 wpabuf_put_le16(msg, os_strlen(connector));
2898 wpabuf_put_str(msg, connector);
2899 os_free(connector);
2900 goto skip_connector;
2901 }
2902#endif /* CONFIG_TESTING_OPTIONS */
2903
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002904 /* DPP Connector */
2905 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2906 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
2907 wpabuf_put_str(msg, ssid->dpp_connector);
2908
Roshan Pius3a1667e2018-07-03 15:17:14 -07002909#ifdef CONFIG_TESTING_OPTIONS
2910skip_connector:
2911#endif /* CONFIG_TESTING_OPTIONS */
2912
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002913#ifdef CONFIG_DPP2
2914 if (DPP_VERSION > 1) {
2915 /* Protocol Version */
2916 wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
2917 wpabuf_put_le16(msg, 1);
2918 wpabuf_put_u8(msg, DPP_VERSION);
2919 }
2920#endif /* CONFIG_DPP2 */
2921
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002922 /* TODO: Timeout on AP response */
2923 wait_time = wpa_s->max_remain_on_chan;
2924 if (wait_time > 2000)
2925 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002926 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2927 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002928 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
2929 broadcast,
2930 wpabuf_head(msg), wpabuf_len(msg),
2931 wait_time, wpas_dpp_tx_introduction_status, 0);
2932 wpabuf_free(msg);
2933
2934 /* Request this connection attempt to terminate - new one will be
2935 * started when network introduction protocol completes */
2936 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
2937 wpa_s->dpp_intro_network = ssid;
2938 return 1;
2939}
2940
2941
2942int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
2943{
2944 struct dpp_bootstrap_info *own_bi;
2945 const char *pos, *end;
2946 unsigned int wait_time;
2947
2948 pos = os_strstr(cmd, " own=");
2949 if (!pos)
2950 return -1;
2951 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07002952 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002953 if (!own_bi) {
2954 wpa_printf(MSG_DEBUG,
2955 "DPP: Identified bootstrap info not found");
2956 return -1;
2957 }
2958 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2959 wpa_printf(MSG_DEBUG,
2960 "DPP: Identified bootstrap info not for PKEX");
2961 return -1;
2962 }
2963 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002964 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002965
2966 os_free(wpa_s->dpp_pkex_identifier);
2967 wpa_s->dpp_pkex_identifier = NULL;
2968 pos = os_strstr(cmd, " identifier=");
2969 if (pos) {
2970 pos += 12;
2971 end = os_strchr(pos, ' ');
2972 if (!end)
2973 return -1;
2974 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
2975 if (!wpa_s->dpp_pkex_identifier)
2976 return -1;
2977 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
2978 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
2979 }
2980
2981 pos = os_strstr(cmd, " code=");
2982 if (!pos)
2983 return -1;
2984 os_free(wpa_s->dpp_pkex_code);
2985 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
2986 if (!wpa_s->dpp_pkex_code)
2987 return -1;
2988
2989 if (os_strstr(cmd, " init=1")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002990 struct dpp_pkex *pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002991 struct wpabuf *msg;
2992
2993 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
2994 dpp_pkex_free(wpa_s->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002995 wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002996 wpa_s->dpp_pkex_identifier,
2997 wpa_s->dpp_pkex_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002998 pkex = wpa_s->dpp_pkex;
2999 if (!pkex)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003000 return -1;
3001
Roshan Pius3a1667e2018-07-03 15:17:14 -07003002 msg = pkex->exchange_req;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003003 wait_time = wpa_s->max_remain_on_chan;
3004 if (wait_time > 2000)
3005 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003006 pkex->freq = 2437;
3007 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
3008 " freq=%u type=%d",
3009 MAC2STR(broadcast), pkex->freq,
3010 DPP_PA_PKEX_EXCHANGE_REQ);
3011 offchannel_send_action(wpa_s, pkex->freq, broadcast,
3012 wpa_s->own_addr, broadcast,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003013 wpabuf_head(msg), wpabuf_len(msg),
3014 wait_time, wpas_dpp_tx_pkex_status, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003015 if (wait_time == 0)
3016 wait_time = 2000;
3017 pkex->exch_req_wait_time = wait_time;
3018 pkex->exch_req_tries = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003019 }
3020
3021 /* TODO: Support multiple PKEX info entries */
3022
3023 os_free(wpa_s->dpp_pkex_auth_cmd);
3024 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
3025
3026 return 1;
3027}
3028
3029
3030int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
3031{
3032 unsigned int id_val;
3033
3034 if (os_strcmp(id, "*") == 0) {
3035 id_val = 0;
3036 } else {
3037 id_val = atoi(id);
3038 if (id_val == 0)
3039 return -1;
3040 }
3041
3042 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
3043 return -1;
3044
3045 /* TODO: Support multiple PKEX entries */
3046 os_free(wpa_s->dpp_pkex_code);
3047 wpa_s->dpp_pkex_code = NULL;
3048 os_free(wpa_s->dpp_pkex_identifier);
3049 wpa_s->dpp_pkex_identifier = NULL;
3050 os_free(wpa_s->dpp_pkex_auth_cmd);
3051 wpa_s->dpp_pkex_auth_cmd = NULL;
3052 wpa_s->dpp_pkex_bi = NULL;
3053 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
3054 dpp_pkex_free(wpa_s->dpp_pkex);
3055 wpa_s->dpp_pkex = NULL;
3056 return 0;
3057}
3058
3059
Roshan Pius3a1667e2018-07-03 15:17:14 -07003060void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
3061{
Hai Shalomfdcde762020-04-02 11:19:20 -07003062 if (wpa_s->dpp_auth || wpa_s->dpp_pkex)
3063 offchannel_send_action_done(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003064 dpp_auth_deinit(wpa_s->dpp_auth);
3065 wpa_s->dpp_auth = NULL;
3066 dpp_pkex_free(wpa_s->dpp_pkex);
3067 wpa_s->dpp_pkex = NULL;
3068 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
3069 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
3070}
3071
3072
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003073int wpas_dpp_init(struct wpa_supplicant *wpa_s)
3074{
Hai Shalom81f62d82019-07-22 12:10:00 -07003075 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003076 u8 adv_proto_id[7];
3077
3078 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
3079 adv_proto_id[1] = 5;
3080 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
3081 adv_proto_id[5] = DPP_OUI_TYPE;
3082 adv_proto_id[6] = 0x01;
3083
3084 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
3085 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
3086 wpas_dpp_gas_status_handler, wpa_s) < 0)
3087 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07003088
3089 os_memset(&config, 0, sizeof(config));
3090 config.msg_ctx = wpa_s;
3091 config.cb_ctx = wpa_s;
3092#ifdef CONFIG_DPP2
3093 config.process_conf_obj = wpas_dpp_process_conf_obj;
Hai Shalomfdcde762020-04-02 11:19:20 -07003094 config.remove_bi = wpas_dpp_remove_bi;
Hai Shalom81f62d82019-07-22 12:10:00 -07003095#endif /* CONFIG_DPP2 */
3096 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07003097 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003098}
3099
3100
3101void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
3102{
3103#ifdef CONFIG_TESTING_OPTIONS
3104 os_free(wpa_s->dpp_config_obj_override);
3105 wpa_s->dpp_config_obj_override = NULL;
3106 os_free(wpa_s->dpp_discovery_override);
3107 wpa_s->dpp_discovery_override = NULL;
3108 os_free(wpa_s->dpp_groups_override);
3109 wpa_s->dpp_groups_override = NULL;
3110 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
3111#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07003112 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003113 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07003114 dpp_global_clear(wpa_s->dpp);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003115 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003116 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003117 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
3118 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003119#ifdef CONFIG_DPP2
3120 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07003121 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
3122 wpa_s, NULL);
3123 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003124 eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
3125 wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07003126 dpp_pfs_free(wpa_s->dpp_pfs);
3127 wpa_s->dpp_pfs = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07003128 wpas_dpp_chirp_stop(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07003129#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003130 offchannel_send_action_done(wpa_s);
3131 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003132 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003133 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003134 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
3135 os_free(wpa_s->dpp_configurator_params);
3136 wpa_s->dpp_configurator_params = NULL;
3137}
Hai Shalom81f62d82019-07-22 12:10:00 -07003138
3139
3140#ifdef CONFIG_DPP2
Hai Shalomfdcde762020-04-02 11:19:20 -07003141
Hai Shalom81f62d82019-07-22 12:10:00 -07003142int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
3143{
3144 struct dpp_controller_config config;
3145 const char *pos;
3146
3147 os_memset(&config, 0, sizeof(config));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003148 config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
Hai Shalom81f62d82019-07-22 12:10:00 -07003149 if (cmd) {
3150 pos = os_strstr(cmd, " tcp_port=");
3151 if (pos) {
3152 pos += 10;
3153 config.tcp_port = atoi(pos);
3154 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003155
3156 pos = os_strstr(cmd, " role=");
3157 if (pos) {
3158 pos += 6;
3159 if (os_strncmp(pos, "configurator", 12) == 0)
3160 config.allowed_roles = DPP_CAPAB_CONFIGURATOR;
3161 else if (os_strncmp(pos, "enrollee", 8) == 0)
3162 config.allowed_roles = DPP_CAPAB_ENROLLEE;
3163 else if (os_strncmp(pos, "either", 6) == 0)
3164 config.allowed_roles = DPP_CAPAB_CONFIGURATOR |
3165 DPP_CAPAB_ENROLLEE;
3166 else
3167 return -1;
3168 }
Hai Shalom81f62d82019-07-22 12:10:00 -07003169 }
3170 config.configurator_params = wpa_s->dpp_configurator_params;
3171 return dpp_controller_start(wpa_s->dpp, &config);
3172}
Hai Shalomfdcde762020-04-02 11:19:20 -07003173
3174
3175static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx);
3176
3177static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx)
3178{
3179 struct wpa_supplicant *wpa_s = eloop_ctx;
3180
3181 wpa_printf(MSG_DEBUG, "DPP: No chirp response received");
3182 offchannel_send_action_done(wpa_s);
3183 wpas_dpp_chirp_next(wpa_s, NULL);
3184}
3185
3186
3187static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s,
3188 unsigned int freq, const u8 *dst,
3189 const u8 *src, const u8 *bssid,
3190 const u8 *data, size_t data_len,
3191 enum offchannel_send_action_result result)
3192{
3193 if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
3194 wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz",
3195 wpa_s->dpp_chirp_freq);
3196 if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next,
3197 wpa_s, NULL) < 0)
3198 wpas_dpp_chirp_stop(wpa_s);
3199 return;
3200 }
3201
3202 wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response");
3203 if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout,
3204 wpa_s, NULL) < 0)
3205 wpas_dpp_chirp_stop(wpa_s);
3206}
3207
3208
3209static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s)
3210{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003211 struct wpabuf *msg;
3212 int type;
3213
3214 msg = wpa_s->dpp_presence_announcement;
3215 type = DPP_PA_PRESENCE_ANNOUNCEMENT;
3216 if (!msg) {
3217 msg = wpa_s->dpp_reconfig_announcement;
3218 if (!msg)
3219 return;
3220 type = DPP_PA_RECONFIG_ANNOUNCEMENT;
3221 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003222 wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq);
3223 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003224 MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type);
Hai Shalomfdcde762020-04-02 11:19:20 -07003225 if (offchannel_send_action(
3226 wpa_s, wpa_s->dpp_chirp_freq, broadcast,
3227 wpa_s->own_addr, broadcast,
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003228 wpabuf_head(msg), wpabuf_len(msg),
Hai Shalomfdcde762020-04-02 11:19:20 -07003229 2000, wpas_dpp_chirp_tx_status, 0) < 0)
3230 wpas_dpp_chirp_stop(wpa_s);
3231}
3232
3233
3234static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
3235 struct wpa_scan_results *scan_res)
3236{
3237 struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi;
3238 unsigned int i;
3239 struct hostapd_hw_modes *mode;
3240 int c;
3241 struct wpa_bss *bss;
3242
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003243 if (!bi && !wpa_s->dpp_reconfig_announcement)
Hai Shalomfdcde762020-04-02 11:19:20 -07003244 return;
3245
3246 wpa_s->dpp_chirp_scan_done = 1;
3247
3248 os_free(wpa_s->dpp_chirp_freqs);
3249 wpa_s->dpp_chirp_freqs = NULL;
3250
3251 /* Channels from own bootstrapping info */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003252 if (bi) {
3253 for (i = 0; i < bi->num_freq; i++)
3254 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
3255 bi->freq[i]);
3256 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003257
3258 /* Preferred chirping channels */
3259 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
3260
3261 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
3262 HOSTAPD_MODE_IEEE80211A, 0);
3263 if (mode) {
3264 int chan44 = 0, chan149 = 0;
3265
3266 for (c = 0; c < mode->num_channels; c++) {
3267 struct hostapd_channel_data *chan = &mode->channels[c];
3268
3269 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
3270 HOSTAPD_CHAN_RADAR))
3271 continue;
3272 if (chan->freq == 5220)
3273 chan44 = 1;
3274 if (chan->freq == 5745)
3275 chan149 = 1;
3276 }
3277 if (chan149)
3278 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745);
3279 else if (chan44)
3280 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220);
3281 }
3282
3283 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
3284 HOSTAPD_MODE_IEEE80211AD, 0);
3285 if (mode) {
3286 for (c = 0; c < mode->num_channels; c++) {
3287 struct hostapd_channel_data *chan = &mode->channels[c];
3288
3289 if ((chan->flag & (HOSTAPD_CHAN_DISABLED |
3290 HOSTAPD_CHAN_RADAR)) ||
3291 chan->freq != 60480)
3292 continue;
3293 int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480);
3294 break;
3295 }
3296 }
3297
3298 /* Add channels from scan results for APs that advertise Configurator
3299 * Connectivity element */
3300 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3301 if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE))
3302 int_array_add_unique(&wpa_s->dpp_chirp_freqs,
3303 bss->freq);
3304 }
3305
3306 if (!wpa_s->dpp_chirp_freqs ||
3307 eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0)
3308 wpas_dpp_chirp_stop(wpa_s);
3309}
3310
3311
3312static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
3313{
3314 struct wpa_supplicant *wpa_s = eloop_ctx;
3315 int i;
3316
3317 if (wpa_s->dpp_chirp_listen)
3318 wpas_dpp_listen_stop(wpa_s);
3319
3320 if (wpa_s->dpp_chirp_freq == 0) {
3321 if (wpa_s->dpp_chirp_round % 4 == 0 &&
3322 !wpa_s->dpp_chirp_scan_done) {
3323 wpa_printf(MSG_DEBUG,
3324 "DPP: Update channel list for chirping");
3325 wpa_s->scan_req = MANUAL_SCAN_REQ;
3326 wpa_s->scan_res_handler =
3327 wpas_dpp_chirp_scan_res_handler;
3328 wpa_supplicant_req_scan(wpa_s, 0, 0);
3329 return;
3330 }
3331 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0];
3332 wpa_s->dpp_chirp_round++;
3333 wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d",
3334 wpa_s->dpp_chirp_round);
3335 } else {
3336 for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++)
3337 if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq)
3338 break;
3339 if (!wpa_s->dpp_chirp_freqs[i]) {
3340 wpa_printf(MSG_DEBUG,
3341 "DPP: Previous chirp freq %d not found",
3342 wpa_s->dpp_chirp_freq);
3343 return;
3344 }
3345 i++;
3346 if (wpa_s->dpp_chirp_freqs[i]) {
3347 wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i];
3348 } else {
3349 wpa_s->dpp_chirp_iter--;
3350 if (wpa_s->dpp_chirp_iter <= 0) {
3351 wpa_printf(MSG_DEBUG,
3352 "DPP: Chirping iterations completed");
3353 wpas_dpp_chirp_stop(wpa_s);
3354 return;
3355 }
3356 wpa_s->dpp_chirp_freq = 0;
3357 wpa_s->dpp_chirp_scan_done = 0;
3358 if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next,
3359 wpa_s, NULL) < 0) {
3360 wpas_dpp_chirp_stop(wpa_s);
3361 return;
3362 }
3363 if (wpa_s->dpp_chirp_listen) {
3364 wpa_printf(MSG_DEBUG,
3365 "DPP: Listen on %d MHz during chirp 30 second wait",
3366 wpa_s->dpp_chirp_listen);
3367 wpas_dpp_listen_start(wpa_s,
3368 wpa_s->dpp_chirp_listen);
3369 } else {
3370 wpa_printf(MSG_DEBUG,
3371 "DPP: Wait 30 seconds before starting the next chirping round");
3372 }
3373 return;
3374 }
3375 }
3376
3377 wpas_dpp_chirp_start(wpa_s);
3378}
3379
3380
3381int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd)
3382{
3383 const char *pos;
3384 int iter = 1, listen_freq = 0;
3385 struct dpp_bootstrap_info *bi;
3386
3387 pos = os_strstr(cmd, " own=");
3388 if (!pos)
3389 return -1;
3390 pos += 5;
3391 bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
3392 if (!bi) {
3393 wpa_printf(MSG_DEBUG,
3394 "DPP: Identified bootstrap info not found");
3395 return -1;
3396 }
3397
3398 pos = os_strstr(cmd, " iter=");
3399 if (pos) {
3400 iter = atoi(pos + 6);
3401 if (iter <= 0)
3402 return -1;
3403 }
3404
3405 pos = os_strstr(cmd, " listen=");
3406 if (pos) {
3407 listen_freq = atoi(pos + 8);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003408 if (listen_freq <= 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07003409 return -1;
3410 }
3411
3412 wpas_dpp_chirp_stop(wpa_s);
3413 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
3414 wpa_s->dpp_qr_mutual = 0;
3415 wpa_s->dpp_chirp_bi = bi;
3416 wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi);
3417 if (!wpa_s->dpp_presence_announcement)
3418 return -1;
3419 wpa_s->dpp_chirp_iter = iter;
3420 wpa_s->dpp_chirp_round = 0;
3421 wpa_s->dpp_chirp_scan_done = 0;
3422 wpa_s->dpp_chirp_listen = listen_freq;
3423
3424 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
3425}
3426
3427
3428void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s)
3429{
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003430 if (wpa_s->dpp_presence_announcement ||
3431 wpa_s->dpp_reconfig_announcement) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003432 offchannel_send_action_done(wpa_s);
3433 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED);
3434 }
3435 wpa_s->dpp_chirp_bi = NULL;
3436 wpabuf_free(wpa_s->dpp_presence_announcement);
3437 wpa_s->dpp_presence_announcement = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003438 wpabuf_free(wpa_s->dpp_reconfig_announcement);
3439 wpa_s->dpp_reconfig_announcement = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07003440 if (wpa_s->dpp_chirp_listen)
3441 wpas_dpp_listen_stop(wpa_s);
3442 wpa_s->dpp_chirp_listen = 0;
3443 wpa_s->dpp_chirp_freq = 0;
3444 os_free(wpa_s->dpp_chirp_freqs);
3445 wpa_s->dpp_chirp_freqs = NULL;
3446 eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL);
3447 eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL);
3448 if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) {
3449 wpas_abort_ongoing_scan(wpa_s);
3450 wpa_s->scan_res_handler = NULL;
3451 }
3452}
3453
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003454
3455int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
3456{
3457 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
3458 !ssid->dpp_csign)
3459 return -1;
3460
3461 wpas_dpp_chirp_stop(wpa_s);
3462 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
3463 wpa_s->dpp_qr_mutual = 0;
3464 wpa_s->dpp_reconfig_announcement =
3465 dpp_build_reconfig_announcement(ssid->dpp_csign,
3466 ssid->dpp_csign_len);
3467 if (!wpa_s->dpp_reconfig_announcement)
3468 return -1;
3469 wpa_s->dpp_reconfig_ssid = ssid;
3470 wpa_s->dpp_reconfig_ssid_id = ssid->id;
3471 wpa_s->dpp_chirp_iter = 1;
3472 wpa_s->dpp_chirp_round = 0;
3473 wpa_s->dpp_chirp_scan_done = 0;
3474 wpa_s->dpp_chirp_listen = 0;
3475
3476 return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL);
3477}
3478
Hai Shalom81f62d82019-07-22 12:10:00 -07003479#endif /* CONFIG_DPP2 */