blob: 73649c230d02c80c74be1f6c652ce0e1a83f84b3 [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * wpa_supplicant - DPP
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
Hai Shalom021b0b52019-04-10 11:17:58 -07004 * Copyright (c) 2018-2019, 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);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070049
50static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
51
52/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
53 * a single transaction in progress at any point in time. */
54static const u8 TRANSACTION_ID = 1;
55
56
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070057/**
58 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
59 * @wpa_s: Pointer to wpa_supplicant data
60 * @cmd: DPP URI read from a QR Code
61 * Returns: Identifier of the stored info or -1 on failure
62 */
63int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
64{
65 struct dpp_bootstrap_info *bi;
66 struct dpp_authentication *auth = wpa_s->dpp_auth;
67
Hai Shalom021b0b52019-04-10 11:17:58 -070068 bi = dpp_add_qr_code(wpa_s->dpp, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070069 if (!bi)
70 return -1;
71
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070072 if (auth && auth->response_pending &&
73 dpp_notify_new_qr_code(auth, bi) == 1) {
74 wpa_printf(MSG_DEBUG,
75 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070076 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
77 " freq=%u type=%d",
78 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
79 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070080 offchannel_send_action(wpa_s, auth->curr_freq,
81 auth->peer_mac_addr, wpa_s->own_addr,
82 broadcast,
83 wpabuf_head(auth->resp_msg),
84 wpabuf_len(auth->resp_msg),
85 500, wpas_dpp_tx_status, 0);
86 }
87
88 return bi->id;
89}
90
91
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080092/**
93 * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
94 * @wpa_s: Pointer to wpa_supplicant data
95 * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
96 * Returns: Identifier of the stored info or -1 on failure
97 */
98int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
99{
100 struct dpp_bootstrap_info *bi;
101
102 bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
103 if (!bi)
104 return -1;
105
106 return bi->id;
107}
108
109
Roshan Pius3a1667e2018-07-03 15:17:14 -0700110static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
111{
112 struct wpa_supplicant *wpa_s = eloop_ctx;
113 struct dpp_authentication *auth = wpa_s->dpp_auth;
114
115 if (!auth || !auth->resp_msg)
116 return;
117
118 wpa_printf(MSG_DEBUG,
119 "DPP: Retry Authentication Response after timeout");
120 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
121 " freq=%u type=%d",
122 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
123 DPP_PA_AUTHENTICATION_RESP);
124 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
125 wpa_s->own_addr, broadcast,
126 wpabuf_head(auth->resp_msg),
127 wpabuf_len(auth->resp_msg),
128 500, wpas_dpp_tx_status, 0);
129}
130
131
132static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
133{
134 struct dpp_authentication *auth = wpa_s->dpp_auth;
135 unsigned int wait_time, max_tries;
136
137 if (!auth || !auth->resp_msg)
138 return;
139
140 if (wpa_s->dpp_resp_max_tries)
141 max_tries = wpa_s->dpp_resp_max_tries;
142 else
143 max_tries = 5;
144 auth->auth_resp_tries++;
145 if (auth->auth_resp_tries >= max_tries) {
146 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
147 offchannel_send_action_done(wpa_s);
148 dpp_auth_deinit(wpa_s->dpp_auth);
149 wpa_s->dpp_auth = NULL;
150 return;
151 }
152
153 if (wpa_s->dpp_resp_retry_time)
154 wait_time = wpa_s->dpp_resp_retry_time;
155 else
156 wait_time = 1000;
157 wpa_printf(MSG_DEBUG,
158 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
159 wait_time);
160 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
161 eloop_register_timeout(wait_time / 1000,
162 (wait_time % 1000) * 1000,
163 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
164}
165
166
Hai Shalom021b0b52019-04-10 11:17:58 -0700167static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
168{
169 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700170 wpa_s->suitable_network = 0;
171 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700172 wpa_s->disconnected = 0;
173 wpa_s->reassociate = 1;
174 wpa_s->scan_runs = 0;
175 wpa_s->normal_scans = 0;
176 wpa_supplicant_cancel_sched_scan(wpa_s);
177 wpa_supplicant_req_scan(wpa_s, 0, 0);
178}
179
180
Hai Shalomc3565922019-10-28 11:58:20 -0700181#ifdef CONFIG_DPP2
182
183static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
184 void *timeout_ctx)
185{
186 struct wpa_supplicant *wpa_s = eloop_ctx;
187 struct dpp_authentication *auth = wpa_s->dpp_auth;
188 enum dpp_status_error result;
189
190 if (!auth || !auth->conn_status_requested)
191 return;
192
193 wpa_printf(MSG_DEBUG,
194 "DPP: Connection timeout - report Connection Status Result");
195 if (wpa_s->suitable_network)
196 result = DPP_STATUS_AUTH_FAILURE;
197 else if (wpa_s->no_suitable_network)
198 result = DPP_STATUS_NO_AP;
199 else
200 result = 255; /* What to report here for unexpected state? */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800201 if (wpa_s->wpa_state == WPA_SCANNING)
202 wpas_abort_ongoing_scan(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700203 wpas_dpp_send_conn_status_result(wpa_s, result);
204}
205
206
207static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
208{
209 char *str, *end, *pos;
210 size_t len;
211 unsigned int i;
212 u8 last_op_class = 0;
213 int res;
214
215 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
216 return NULL;
217
218 len = wpa_s->num_last_scan_freqs * 8;
219 str = os_zalloc(len);
220 if (!str)
221 return NULL;
222 end = str + len;
223 pos = str;
224
225 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
226 enum hostapd_hw_mode mode;
227 u8 op_class, channel;
228
229 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
230 0, 0, &op_class, &channel);
231 if (mode == NUM_HOSTAPD_MODES)
232 continue;
233 if (op_class == last_op_class)
234 res = os_snprintf(pos, end - pos, ",%d", channel);
235 else
236 res = os_snprintf(pos, end - pos, "%s%d/%d",
237 pos == str ? "" : ",",
238 op_class, channel);
239 if (os_snprintf_error(end - pos, res)) {
240 *pos = '\0';
241 break;
242 }
243 pos += res;
244 last_op_class = op_class;
245 }
246
247 if (pos == str) {
248 os_free(str);
249 str = NULL;
250 }
251 return str;
252}
253
254
255void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
256 enum dpp_status_error result)
257{
258 struct wpabuf *msg;
259 const char *channel_list = NULL;
260 char *channel_list_buf = NULL;
261 struct wpa_ssid *ssid = wpa_s->current_ssid;
262 struct dpp_authentication *auth = wpa_s->dpp_auth;
263
264 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
265
266 if (!auth || !auth->conn_status_requested)
267 return;
268 auth->conn_status_requested = 0;
269 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
270 result);
271
272 if (result == DPP_STATUS_NO_AP) {
273 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
274 channel_list = channel_list_buf;
275 }
276
277 msg = dpp_build_conn_status_result(auth, result,
278 ssid ? ssid->ssid :
279 wpa_s->dpp_last_ssid,
280 ssid ? ssid->ssid_len :
281 wpa_s->dpp_last_ssid_len,
282 channel_list);
283 os_free(channel_list_buf);
284 if (!msg) {
285 dpp_auth_deinit(wpa_s->dpp_auth);
286 wpa_s->dpp_auth = NULL;
287 return;
288 }
289
290 wpa_msg(wpa_s, MSG_INFO,
291 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
292 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
293 DPP_PA_CONNECTION_STATUS_RESULT);
294 offchannel_send_action(wpa_s, auth->curr_freq,
295 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
296 wpabuf_head(msg), wpabuf_len(msg),
297 500, wpas_dpp_tx_status, 0);
298 wpabuf_free(msg);
299
300 /* This exchange will be terminated in the TX status handler */
301 auth->remove_on_tx_status = 1;
302
303 return;
304}
305
306
307void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
308{
309 struct dpp_authentication *auth = wpa_s->dpp_auth;
310
311 if (auth && auth->conn_status_requested)
312 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
313}
314
315#endif /* CONFIG_DPP2 */
316
317
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700318static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
319 unsigned int freq, const u8 *dst,
320 const u8 *src, const u8 *bssid,
321 const u8 *data, size_t data_len,
322 enum offchannel_send_action_result result)
323{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700324 const char *res_txt;
325 struct dpp_authentication *auth = wpa_s->dpp_auth;
326
327 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
328 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
329 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700330 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700331 " result=%s", freq, MAC2STR(dst), res_txt);
332 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
333 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700334
335 if (!wpa_s->dpp_auth) {
336 wpa_printf(MSG_DEBUG,
337 "DPP: Ignore TX status since there is no ongoing authentication exchange");
338 return;
339 }
340
Hai Shalom021b0b52019-04-10 11:17:58 -0700341#ifdef CONFIG_DPP2
342 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700343 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700344 wpa_printf(MSG_DEBUG,
345 "DPP: Try to connect after completed configuration result");
346 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700347 if (auth->conn_status_requested) {
348 wpa_printf(MSG_DEBUG,
349 "DPP: Start 15 second timeout for reporting connection status result");
350 eloop_cancel_timeout(
351 wpas_dpp_conn_status_result_timeout,
352 wpa_s, NULL);
353 eloop_register_timeout(
354 15, 0, wpas_dpp_conn_status_result_timeout,
355 wpa_s, NULL);
356 } else {
357 dpp_auth_deinit(wpa_s->dpp_auth);
358 wpa_s->dpp_auth = NULL;
359 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700360 return;
361 }
362#endif /* CONFIG_DPP2 */
363
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700364 if (wpa_s->dpp_auth->remove_on_tx_status) {
365 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700366 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700367 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700368 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700369 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
370 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700371 offchannel_send_action_done(wpa_s);
372 dpp_auth_deinit(wpa_s->dpp_auth);
373 wpa_s->dpp_auth = NULL;
374 return;
375 }
376
377 if (wpa_s->dpp_auth_ok_on_ack)
378 wpas_dpp_auth_success(wpa_s, 1);
379
380 if (!is_broadcast_ether_addr(dst) &&
381 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
382 wpa_printf(MSG_DEBUG,
383 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700384 if (auth->waiting_auth_resp) {
385 /* In case of DPP Authentication Request frame, move to
386 * the next channel immediately. */
387 offchannel_send_action_done(wpa_s);
388 wpas_dpp_auth_init_next(wpa_s);
389 return;
390 }
391 if (auth->waiting_auth_conf) {
392 wpas_dpp_auth_resp_retry(wpa_s);
393 return;
394 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700395 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700396
397 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
398 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
399 /* Allow timeout handling to stop iteration if no response is
400 * received from a peer that has ACKed a request. */
401 auth->auth_req_ack = 1;
402 }
403
404 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
405 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
406 wpa_printf(MSG_DEBUG,
407 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
408 wpa_s->dpp_auth->curr_freq,
409 wpa_s->dpp_auth->neg_freq);
410 offchannel_send_action_done(wpa_s);
411 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
412 }
413
414 if (wpa_s->dpp_auth_ok_on_ack)
415 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700416}
417
418
419static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
420{
421 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700422 struct dpp_authentication *auth = wpa_s->dpp_auth;
423 unsigned int freq;
424 struct os_reltime now, diff;
425 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700426
Roshan Pius3a1667e2018-07-03 15:17:14 -0700427 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700428 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700429
430 wait_time = wpa_s->dpp_resp_wait_time ?
431 wpa_s->dpp_resp_wait_time : 2000;
432 os_get_reltime(&now);
433 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
434 diff_ms = diff.sec * 1000 + diff.usec / 1000;
435 wpa_printf(MSG_DEBUG,
436 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
437 wait_time, diff_ms);
438
439 if (auth->auth_req_ack && diff_ms >= wait_time) {
440 /* Peer ACK'ed Authentication Request frame, but did not reply
441 * with Authentication Response frame within two seconds. */
442 wpa_printf(MSG_INFO,
443 "DPP: No response received from responder - stopping initiation attempt");
444 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800445 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700446 offchannel_send_action_done(wpa_s);
447 wpas_dpp_listen_stop(wpa_s);
448 dpp_auth_deinit(auth);
449 wpa_s->dpp_auth = NULL;
450 return;
451 }
452
453 if (diff_ms >= wait_time) {
454 /* Authentication Request frame was not ACK'ed and no reply
455 * was receiving within two seconds. */
456 wpa_printf(MSG_DEBUG,
457 "DPP: Continue Initiator channel iteration");
458 offchannel_send_action_done(wpa_s);
459 wpas_dpp_listen_stop(wpa_s);
460 wpas_dpp_auth_init_next(wpa_s);
461 return;
462 }
463
464 /* Driver did not support 2000 ms long wait_time with TX command, so
465 * schedule listen operation to continue waiting for the response.
466 *
467 * DPP listen operations continue until stopped, so simply schedule a
468 * new call to this function at the point when the two second reply
469 * wait has expired. */
470 wait_time -= diff_ms;
471
472 freq = auth->curr_freq;
473 if (auth->neg_freq > 0)
474 freq = auth->neg_freq;
475 wpa_printf(MSG_DEBUG,
476 "DPP: Continue reply wait on channel %u MHz for %u ms",
477 freq, wait_time);
478 wpa_s->dpp_in_response_listen = 1;
479 wpas_dpp_listen_start(wpa_s, freq);
480
481 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
482 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700483}
484
485
486static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
487 struct dpp_authentication *auth)
488{
489#ifdef CONFIG_TESTING_OPTIONS
490 if (wpa_s->dpp_config_obj_override)
491 auth->config_obj_override =
492 os_strdup(wpa_s->dpp_config_obj_override);
493 if (wpa_s->dpp_discovery_override)
494 auth->discovery_override =
495 os_strdup(wpa_s->dpp_discovery_override);
496 if (wpa_s->dpp_groups_override)
497 auth->groups_override =
498 os_strdup(wpa_s->dpp_groups_override);
499 auth->ignore_netaccesskey_mismatch =
500 wpa_s->dpp_ignore_netaccesskey_mismatch;
501#endif /* CONFIG_TESTING_OPTIONS */
502}
503
504
Roshan Pius3a1667e2018-07-03 15:17:14 -0700505static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
506{
507 struct wpa_supplicant *wpa_s = eloop_ctx;
508
509 if (!wpa_s->dpp_auth)
510 return;
511 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
512 wpas_dpp_auth_init_next(wpa_s);
513}
514
515
516static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
517{
518 struct dpp_authentication *auth = wpa_s->dpp_auth;
519 const u8 *dst;
520 unsigned int wait_time, max_wait_time, freq, max_tries, used;
521 struct os_reltime now, diff;
522
523 wpa_s->dpp_in_response_listen = 0;
524 if (!auth)
525 return -1;
526
527 if (auth->freq_idx == 0)
528 os_get_reltime(&wpa_s->dpp_init_iter_start);
529
530 if (auth->freq_idx >= auth->num_freq) {
531 auth->num_freq_iters++;
532 if (wpa_s->dpp_init_max_tries)
533 max_tries = wpa_s->dpp_init_max_tries;
534 else
535 max_tries = 5;
536 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
537 wpa_printf(MSG_INFO,
538 "DPP: No response received from responder - stopping initiation attempt");
539 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800540 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700541 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
542 wpa_s, NULL);
543 offchannel_send_action_done(wpa_s);
544 dpp_auth_deinit(wpa_s->dpp_auth);
545 wpa_s->dpp_auth = NULL;
546 return -1;
547 }
548 auth->freq_idx = 0;
549 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
550 if (wpa_s->dpp_init_retry_time)
551 wait_time = wpa_s->dpp_init_retry_time;
552 else
553 wait_time = 10000;
554 os_get_reltime(&now);
555 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
556 used = diff.sec * 1000 + diff.usec / 1000;
557 if (used > wait_time)
558 wait_time = 0;
559 else
560 wait_time -= used;
561 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
562 wait_time);
563 eloop_register_timeout(wait_time / 1000,
564 (wait_time % 1000) * 1000,
565 wpas_dpp_init_timeout, wpa_s,
566 NULL);
567 return 0;
568 }
569 freq = auth->freq[auth->freq_idx++];
570 auth->curr_freq = freq;
571
572 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
573 dst = broadcast;
574 else
575 dst = auth->peer_bi->mac_addr;
576 wpa_s->dpp_auth_ok_on_ack = 0;
577 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
578 wait_time = wpa_s->max_remain_on_chan;
579 max_wait_time = wpa_s->dpp_resp_wait_time ?
580 wpa_s->dpp_resp_wait_time : 2000;
581 if (wait_time > max_wait_time)
582 wait_time = max_wait_time;
583 wait_time += 10; /* give the driver some extra time to complete */
584 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
585 wpas_dpp_reply_wait_timeout,
586 wpa_s, NULL);
587 wait_time -= 10;
588 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
589 wpa_printf(MSG_DEBUG,
590 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
591 freq, auth->neg_freq);
592 }
593 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
594 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
595 auth->auth_req_ack = 0;
596 os_get_reltime(&wpa_s->dpp_last_init);
597 return offchannel_send_action(wpa_s, freq, dst,
598 wpa_s->own_addr, broadcast,
599 wpabuf_head(auth->req_msg),
600 wpabuf_len(auth->req_msg),
601 wait_time, wpas_dpp_tx_status, 0);
602}
603
604
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700605int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
606{
607 const char *pos;
608 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700609 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700610 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
611 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700612 int tcp = 0;
613#ifdef CONFIG_DPP2
614 int tcp_port = DPP_TCP_PORT;
615 struct hostapd_ip_addr ipaddr;
616 char *addr;
617#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700618
619 wpa_s->dpp_gas_client = 0;
620
621 pos = os_strstr(cmd, " peer=");
622 if (!pos)
623 return -1;
624 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700625 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700626 if (!peer_bi) {
627 wpa_printf(MSG_INFO,
628 "DPP: Could not find bootstrapping info for the identified peer");
629 return -1;
630 }
631
Hai Shalom81f62d82019-07-22 12:10:00 -0700632#ifdef CONFIG_DPP2
633 pos = os_strstr(cmd, " tcp_port=");
634 if (pos) {
635 pos += 10;
636 tcp_port = atoi(pos);
637 }
638
639 addr = get_param(cmd, " tcp_addr=");
640 if (addr) {
641 int res;
642
643 res = hostapd_parse_ip_addr(addr, &ipaddr);
644 os_free(addr);
645 if (res)
646 return -1;
647 tcp = 1;
648 }
649#endif /* CONFIG_DPP2 */
650
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700651 pos = os_strstr(cmd, " own=");
652 if (pos) {
653 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700654 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700655 if (!own_bi) {
656 wpa_printf(MSG_INFO,
657 "DPP: Could not find bootstrapping info for the identified local entry");
658 return -1;
659 }
660
661 if (peer_bi->curve != own_bi->curve) {
662 wpa_printf(MSG_INFO,
663 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
664 peer_bi->curve->name, own_bi->curve->name);
665 return -1;
666 }
667 }
668
669 pos = os_strstr(cmd, " role=");
670 if (pos) {
671 pos += 6;
672 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700673 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700674 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700675 allowed_roles = DPP_CAPAB_ENROLLEE;
676 else if (os_strncmp(pos, "either", 6) == 0)
677 allowed_roles = DPP_CAPAB_CONFIGURATOR |
678 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700679 else
680 goto fail;
681 }
682
683 pos = os_strstr(cmd, " netrole=");
684 if (pos) {
685 pos += 9;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800686 if (os_strncmp(pos, "ap", 2) == 0)
687 wpa_s->dpp_netrole = DPP_NETROLE_AP;
688 else if (os_strncmp(pos, "configurator", 12) == 0)
689 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
690 else
691 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700692 }
693
Roshan Pius3a1667e2018-07-03 15:17:14 -0700694 pos = os_strstr(cmd, " neg_freq=");
695 if (pos)
696 neg_freq = atoi(pos + 10);
697
Hai Shalom81f62d82019-07-22 12:10:00 -0700698 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700699 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700700 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700701 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
702 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700703 offchannel_send_action_done(wpa_s);
704 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800705 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700706 }
707
708 auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles, neg_freq,
709 wpa_s->hw.modes, wpa_s->hw.num_modes);
710 if (!auth)
711 goto fail;
712 wpas_dpp_set_testing_options(wpa_s, auth);
713 if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) < 0) {
714 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800715 goto fail;
716 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700717
Hai Shalom81f62d82019-07-22 12:10:00 -0700718 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700719
Roshan Pius3a1667e2018-07-03 15:17:14 -0700720 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700721 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700722
Hai Shalom81f62d82019-07-22 12:10:00 -0700723#ifdef CONFIG_DPP2
724 if (tcp)
725 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port);
726#endif /* CONFIG_DPP2 */
727
728 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700729 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700730fail:
731 return -1;
732}
733
734
735struct wpas_dpp_listen_work {
736 unsigned int freq;
737 unsigned int duration;
738 struct wpabuf *probe_resp_ie;
739};
740
741
742static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
743{
744 if (!lwork)
745 return;
746 os_free(lwork);
747}
748
749
750static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
751{
752 struct wpas_dpp_listen_work *lwork;
753
754 if (!wpa_s->dpp_listen_work)
755 return;
756
757 lwork = wpa_s->dpp_listen_work->ctx;
758 wpas_dpp_listen_work_free(lwork);
759 radio_work_done(wpa_s->dpp_listen_work);
760 wpa_s->dpp_listen_work = NULL;
761}
762
763
764static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
765{
766 struct wpa_supplicant *wpa_s = work->wpa_s;
767 struct wpas_dpp_listen_work *lwork = work->ctx;
768
769 if (deinit) {
770 if (work->started) {
771 wpa_s->dpp_listen_work = NULL;
772 wpas_dpp_listen_stop(wpa_s);
773 }
774 wpas_dpp_listen_work_free(lwork);
775 return;
776 }
777
778 wpa_s->dpp_listen_work = work;
779
780 wpa_s->dpp_pending_listen_freq = lwork->freq;
781
782 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
783 wpa_s->max_remain_on_chan) < 0) {
784 wpa_printf(MSG_DEBUG,
785 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
786 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800787 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700788 wpas_dpp_listen_work_done(wpa_s);
789 wpa_s->dpp_pending_listen_freq = 0;
790 return;
791 }
792 wpa_s->off_channel_freq = 0;
793 wpa_s->roc_waiting_drv_freq = lwork->freq;
794}
795
796
797static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
798 unsigned int freq)
799{
800 struct wpas_dpp_listen_work *lwork;
801
802 if (wpa_s->dpp_listen_work) {
803 wpa_printf(MSG_DEBUG,
804 "DPP: Reject start_listen since dpp_listen_work already exists");
805 return -1;
806 }
807
808 if (wpa_s->dpp_listen_freq)
809 wpas_dpp_listen_stop(wpa_s);
810 wpa_s->dpp_listen_freq = freq;
811
812 lwork = os_zalloc(sizeof(*lwork));
813 if (!lwork)
814 return -1;
815 lwork->freq = freq;
816
817 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
818 lwork) < 0) {
819 wpas_dpp_listen_work_free(lwork);
820 return -1;
821 }
822
823 return 0;
824}
825
826
827int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
828{
829 int freq;
830
831 freq = atoi(cmd);
832 if (freq <= 0)
833 return -1;
834
835 if (os_strstr(cmd, " role=configurator"))
836 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
837 else if (os_strstr(cmd, " role=enrollee"))
838 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
839 else
840 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
841 DPP_CAPAB_ENROLLEE;
842 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800843 if (os_strstr(cmd, " netrole=ap"))
844 wpa_s->dpp_netrole = DPP_NETROLE_AP;
845 else if (os_strstr(cmd, " netrole=configurator"))
846 wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
847 else
848 wpa_s->dpp_netrole = DPP_NETROLE_STA;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700849 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
850 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
851 freq);
852 return 0;
853 }
854
855 return wpas_dpp_listen_start(wpa_s, freq);
856}
857
858
859void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
860{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700861 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700862 if (!wpa_s->dpp_listen_freq)
863 return;
864
865 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
866 wpa_s->dpp_listen_freq);
867 wpa_drv_cancel_remain_on_channel(wpa_s);
868 wpa_s->dpp_listen_freq = 0;
869 wpas_dpp_listen_work_done(wpa_s);
870}
871
872
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700873void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
874 unsigned int freq)
875{
876 wpas_dpp_listen_work_done(wpa_s);
877
Roshan Pius3a1667e2018-07-03 15:17:14 -0700878 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
879 unsigned int new_freq;
880
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700881 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700882 if (wpa_s->dpp_auth->neg_freq > 0)
883 new_freq = wpa_s->dpp_auth->neg_freq;
884 else
885 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700886 wpa_printf(MSG_DEBUG,
887 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -0700888 new_freq);
889 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700890 return;
891 }
892
893 if (wpa_s->dpp_listen_freq) {
894 /* Continue listen with a new remain-on-channel */
895 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
896 }
897}
898
899
900static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
901 const u8 *hdr, const u8 *buf, size_t len,
902 unsigned int freq)
903{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700904 const u8 *r_bootstrap, *i_bootstrap;
905 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700906 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
907
908 if (!wpa_s->dpp)
909 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700910
911 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
912 MAC2STR(src));
913
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700914 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
915 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700916 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
917 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
918 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700919 return;
920 }
921 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
922 r_bootstrap, r_bootstrap_len);
923
924 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
925 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700926 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
927 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
928 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700929 return;
930 }
931 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
932 i_bootstrap, i_bootstrap_len);
933
934 /* Try to find own and peer bootstrapping key matches based on the
935 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -0700936 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
937 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700938 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700939 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
940 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700941 return;
942 }
943
944 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700945 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
946 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700947 return;
948 }
949
950 wpa_s->dpp_gas_client = 0;
951 wpa_s->dpp_auth_ok_on_ack = 0;
952 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles,
953 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700954 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700955 if (!wpa_s->dpp_auth) {
956 wpa_printf(MSG_DEBUG, "DPP: No response generated");
957 return;
958 }
959 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalom021b0b52019-04-10 11:17:58 -0700960 if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth,
961 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800962 dpp_auth_deinit(wpa_s->dpp_auth);
963 wpa_s->dpp_auth = NULL;
964 return;
965 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700966 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
967
Roshan Pius3a1667e2018-07-03 15:17:14 -0700968 if (wpa_s->dpp_listen_freq &&
969 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
970 wpa_printf(MSG_DEBUG,
971 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
972 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
973 wpas_dpp_listen_stop(wpa_s);
974 }
975
976 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
977 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
978 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700979 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
980 src, wpa_s->own_addr, broadcast,
981 wpabuf_head(wpa_s->dpp_auth->resp_msg),
982 wpabuf_len(wpa_s->dpp_auth->resp_msg),
983 500, wpas_dpp_tx_status, 0);
984}
985
986
987static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
988{
989 /* TODO: stop wait and start ROC */
990}
991
992
993static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -0700994 struct dpp_authentication *auth,
995 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700996{
997 struct wpa_ssid *ssid;
998
Hai Shalom021b0b52019-04-10 11:17:58 -0700999#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -07001000 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001001#ifdef CONFIG_SAE
1002 struct wpa_driver_capa capa;
1003 int res;
1004
1005 res = wpa_drv_get_capa(wpa_s, &capa);
1006 if (res == 0 &&
1007 !(capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
1008 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
1009 wpa_printf(MSG_DEBUG,
1010 "DPP: SAE not supported by the driver");
1011 return NULL;
1012 }
1013#else /* CONFIG_SAE */
1014 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
1015 return NULL;
1016#endif /* CONFIG_SAE */
1017 }
1018#endif /* CONFIG_DPP2 */
1019
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001020 ssid = wpa_config_add_network(wpa_s->conf);
1021 if (!ssid)
1022 return NULL;
1023 wpas_notify_network_added(wpa_s, ssid);
1024 wpa_config_set_network_defaults(ssid);
1025 ssid->disabled = 1;
1026
Hai Shalomc3565922019-10-28 11:58:20 -07001027 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001028 if (!ssid->ssid)
1029 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001030 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1031 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001032
Hai Shalomc3565922019-10-28 11:58:20 -07001033 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001034 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001035 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalomc3565922019-10-28 11:58:20 -07001036 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001037 if (!ssid->dpp_connector)
1038 goto fail;
1039 }
1040
Hai Shalomc3565922019-10-28 11:58:20 -07001041 if (conf->c_sign_key) {
1042 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001043 if (!ssid->dpp_csign)
1044 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001045 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1046 wpabuf_len(conf->c_sign_key));
1047 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001048 }
1049
1050 if (auth->net_access_key) {
1051 ssid->dpp_netaccesskey =
1052 os_malloc(wpabuf_len(auth->net_access_key));
1053 if (!ssid->dpp_netaccesskey)
1054 goto fail;
1055 os_memcpy(ssid->dpp_netaccesskey,
1056 wpabuf_head(auth->net_access_key),
1057 wpabuf_len(auth->net_access_key));
1058 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1059 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1060 }
1061
Hai Shalomc3565922019-10-28 11:58:20 -07001062 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1063 dpp_akm_sae(conf->akm)) {
1064 if (!conf->connector)
Hai Shalom021b0b52019-04-10 11:17:58 -07001065 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001066 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001067 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1068 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001069 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001070 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1071 WPA_KEY_MGMT_FT_SAE;
1072 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001073 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001074 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001075 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001076 goto fail;
1077 wpa_config_update_psk(ssid);
1078 ssid->export_keys = 1;
1079 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001080 ssid->psk_set = conf->psk_set;
1081 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001082 }
1083 }
1084
Hai Shalomc3565922019-10-28 11:58:20 -07001085 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1086 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1087
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001088 return ssid;
1089fail:
1090 wpas_notify_network_removed(wpa_s, ssid);
1091 wpa_config_remove_network(wpa_s->conf, ssid->id);
1092 return NULL;
1093}
1094
1095
Hai Shalom021b0b52019-04-10 11:17:58 -07001096static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001097 struct dpp_authentication *auth,
1098 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001099{
1100 struct wpa_ssid *ssid;
1101
1102 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001103 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001104
Hai Shalomc3565922019-10-28 11:58:20 -07001105 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001106 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001107 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001108
1109 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001110
Hai Shalom706f99b2019-01-08 16:23:37 -08001111 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001112
Hai Shalom021b0b52019-04-10 11:17:58 -07001113 if (wpa_s->conf->dpp_config_processing == 2)
1114 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001115
Hai Shalom021b0b52019-04-10 11:17:58 -07001116#ifndef CONFIG_NO_CONFIG_WRITE
1117 if (wpa_s->conf->update_config &&
1118 wpa_config_write(wpa_s->confname, wpa_s->conf))
1119 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1120#endif /* CONFIG_NO_CONFIG_WRITE */
1121
Hai Shalomc3565922019-10-28 11:58:20 -07001122 return 0;
1123}
1124
1125
1126static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1127 struct dpp_authentication *auth)
1128{
Hai Shalom021b0b52019-04-10 11:17:58 -07001129 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001130 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001131
1132#ifdef CONFIG_DPP2
1133 if (auth->peer_version >= 2) {
1134 wpa_printf(MSG_DEBUG,
1135 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1136 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001137 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001138 }
1139#endif /* CONFIG_DPP2 */
1140
1141 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001142}
1143
1144
Hai Shalom021b0b52019-04-10 11:17:58 -07001145static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001146 struct dpp_authentication *auth,
1147 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001148{
1149 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalomc3565922019-10-28 11:58:20 -07001150 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001151 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001152 wpa_ssid_txt(conf->ssid, conf->ssid_len));
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001153 if (conf->ssid_charset)
1154 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
1155 conf->ssid_charset);
Hai Shalomc3565922019-10-28 11:58:20 -07001156 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001157 /* TODO: Save the Connector and consider using a command
1158 * to fetch the value instead of sending an event with
1159 * it. The Connector could end up being larger than what
1160 * most clients are ready to receive as an event
1161 * message. */
1162 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001163 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001164 }
Hai Shalomc3565922019-10-28 11:58:20 -07001165 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001166 char *hex;
1167 size_t hexlen;
1168
Hai Shalomc3565922019-10-28 11:58:20 -07001169 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001170 hex = os_malloc(hexlen);
1171 if (hex) {
1172 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001173 wpabuf_head(conf->c_sign_key),
1174 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001175 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1176 hex);
1177 os_free(hex);
1178 }
1179 }
1180 if (auth->net_access_key) {
1181 char *hex;
1182 size_t hexlen;
1183
1184 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1185 hex = os_malloc(hexlen);
1186 if (hex) {
1187 wpa_snprintf_hex(hex, hexlen,
1188 wpabuf_head(auth->net_access_key),
1189 wpabuf_len(auth->net_access_key));
1190 if (auth->net_access_key_expiry)
1191 wpa_msg(wpa_s, MSG_INFO,
1192 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1193 (long unsigned)
1194 auth->net_access_key_expiry);
1195 else
1196 wpa_msg(wpa_s, MSG_INFO,
1197 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1198 os_free(hex);
1199 }
1200 }
1201
Hai Shalomc3565922019-10-28 11:58:20 -07001202 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001203}
1204
1205
1206static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1207 enum gas_query_result result,
1208 const struct wpabuf *adv_proto,
1209 const struct wpabuf *resp, u16 status_code)
1210{
1211 struct wpa_supplicant *wpa_s = ctx;
1212 const u8 *pos;
1213 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001214 int res;
1215 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001216 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001217
Roshan Pius3a1667e2018-07-03 15:17:14 -07001218 wpa_s->dpp_gas_dialog_token = -1;
1219
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001220 if (!auth || !auth->auth_success) {
1221 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1222 return;
1223 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001224 if (result != GAS_QUERY_SUCCESS ||
1225 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001226 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1227 goto fail;
1228 }
1229
1230 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1231 adv_proto);
1232 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1233 resp);
1234
1235 if (wpabuf_len(adv_proto) != 10 ||
1236 !(pos = wpabuf_head(adv_proto)) ||
1237 pos[0] != WLAN_EID_ADV_PROTO ||
1238 pos[1] != 8 ||
1239 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1240 pos[4] != 5 ||
1241 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1242 pos[8] != 0x1a ||
1243 pos[9] != 1) {
1244 wpa_printf(MSG_DEBUG,
1245 "DPP: Not a DPP Advertisement Protocol ID");
1246 goto fail;
1247 }
1248
1249 if (dpp_conf_resp_rx(auth, resp) < 0) {
1250 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1251 goto fail;
1252 }
1253
Hai Shalomc3565922019-10-28 11:58:20 -07001254 for (i = 0; i < auth->num_conf_obj; i++) {
1255 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1256 &auth->conf_obj[i]);
1257 if (res < 0)
1258 goto fail;
1259 }
1260 if (auth->num_conf_obj)
1261 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001262
Hai Shalom021b0b52019-04-10 11:17:58 -07001263 status = DPP_STATUS_OK;
1264#ifdef CONFIG_TESTING_OPTIONS
1265 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1266 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1267 status = DPP_STATUS_CONFIG_REJECTED;
1268 }
1269#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001270fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001271 if (status != DPP_STATUS_OK) {
1272 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1273 wpas_notify_dpp_configuration_failure(wpa_s);
1274 }
1275#ifdef CONFIG_DPP2
1276 if (auth->peer_version >= 2 &&
1277 auth->conf_resp_status == DPP_STATUS_OK) {
1278 struct wpabuf *msg;
1279
1280 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1281 msg = dpp_build_conf_result(auth, status);
1282 if (!msg)
1283 goto fail2;
1284
1285 wpa_msg(wpa_s, MSG_INFO,
1286 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1287 MAC2STR(addr), auth->curr_freq,
1288 DPP_PA_CONFIGURATION_RESULT);
1289 offchannel_send_action(wpa_s, auth->curr_freq,
1290 addr, wpa_s->own_addr, broadcast,
1291 wpabuf_head(msg),
1292 wpabuf_len(msg),
1293 500, wpas_dpp_tx_status, 0);
1294 wpabuf_free(msg);
1295
1296 /* This exchange will be terminated in the TX status handler */
1297 return;
1298 }
1299fail2:
1300#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001301 dpp_auth_deinit(wpa_s->dpp_auth);
1302 wpa_s->dpp_auth = NULL;
1303}
1304
1305
1306static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1307{
1308 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001309 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001310 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001311 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001312
1313 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001314 offchannel_send_action_done(wpa_s);
1315 wpas_dpp_listen_stop(wpa_s);
1316
Hai Shalomc3565922019-10-28 11:58:20 -07001317 supp_op_classes = wpas_supp_op_classes(wpa_s);
1318 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001319 wpa_s->dpp_netrole,
Hai Shalomc3565922019-10-28 11:58:20 -07001320 wpa_s->conf->dpp_mud_url,
1321 supp_op_classes);
1322 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001323 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001324 wpa_printf(MSG_DEBUG,
1325 "DPP: No configuration request data available");
1326 return;
1327 }
1328
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001329 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1330 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1331
1332 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001333 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001334 if (res < 0) {
1335 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1336 wpabuf_free(buf);
1337 } else {
1338 wpa_printf(MSG_DEBUG,
1339 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001340 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001341 }
1342}
1343
1344
1345static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1346{
1347 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1348 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001349 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001350#ifdef CONFIG_TESTING_OPTIONS
1351 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1352 wpa_printf(MSG_INFO,
1353 "DPP: TESTING - stop at Authentication Confirm");
1354 if (wpa_s->dpp_auth->configurator) {
1355 /* Prevent GAS response */
1356 wpa_s->dpp_auth->auth_success = 0;
1357 }
1358 return;
1359 }
1360#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001361
1362 if (wpa_s->dpp_auth->configurator)
1363 wpas_dpp_start_gas_server(wpa_s);
1364 else
1365 wpas_dpp_start_gas_client(wpa_s);
1366}
1367
1368
1369static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001370 const u8 *hdr, const u8 *buf, size_t len,
1371 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001372{
1373 struct dpp_authentication *auth = wpa_s->dpp_auth;
1374 struct wpabuf *msg;
1375
Roshan Pius3a1667e2018-07-03 15:17:14 -07001376 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1377 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001378
1379 if (!auth) {
1380 wpa_printf(MSG_DEBUG,
1381 "DPP: No DPP Authentication in progress - drop");
1382 return;
1383 }
1384
1385 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1386 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1387 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1388 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1389 return;
1390 }
1391
1392 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1393
Roshan Pius3a1667e2018-07-03 15:17:14 -07001394 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1395 wpa_printf(MSG_DEBUG,
1396 "DPP: Responder accepted request for different negotiation channel");
1397 auth->curr_freq = freq;
1398 }
1399
1400 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001401 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1402 if (!msg) {
1403 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1404 wpa_printf(MSG_DEBUG,
1405 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001406 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001407 offchannel_send_action_done(wpa_s);
1408 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1409 return;
1410 }
1411 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1412 return;
1413 }
1414 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1415
Roshan Pius3a1667e2018-07-03 15:17:14 -07001416 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1417 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001418 offchannel_send_action(wpa_s, auth->curr_freq,
1419 src, wpa_s->own_addr, broadcast,
1420 wpabuf_head(msg), wpabuf_len(msg),
1421 500, wpas_dpp_tx_status, 0);
1422 wpabuf_free(msg);
1423 wpa_s->dpp_auth_ok_on_ack = 1;
1424}
1425
1426
1427static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1428 const u8 *hdr, const u8 *buf, size_t len)
1429{
1430 struct dpp_authentication *auth = wpa_s->dpp_auth;
1431
1432 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1433 MAC2STR(src));
1434
1435 if (!auth) {
1436 wpa_printf(MSG_DEBUG,
1437 "DPP: No DPP Authentication in progress - drop");
1438 return;
1439 }
1440
1441 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1442 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1443 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1444 return;
1445 }
1446
1447 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1448 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001449 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001450 return;
1451 }
1452
1453 wpas_dpp_auth_success(wpa_s, 0);
1454}
1455
1456
Hai Shalom021b0b52019-04-10 11:17:58 -07001457#ifdef CONFIG_DPP2
1458
1459static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
1460 void *timeout_ctx)
1461{
1462 struct wpa_supplicant *wpa_s = eloop_ctx;
1463 struct dpp_authentication *auth = wpa_s->dpp_auth;
1464
1465 if (!auth || !auth->waiting_conf_result)
1466 return;
1467
1468 wpa_printf(MSG_DEBUG,
1469 "DPP: Timeout while waiting for Configuration Result");
1470 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001471 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07001472 dpp_auth_deinit(auth);
1473 wpa_s->dpp_auth = NULL;
1474}
1475
1476
Hai Shalomc3565922019-10-28 11:58:20 -07001477static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1478 void *timeout_ctx)
1479{
1480 struct wpa_supplicant *wpa_s = eloop_ctx;
1481 struct dpp_authentication *auth = wpa_s->dpp_auth;
1482
1483 if (!auth || !auth->waiting_conn_status_result)
1484 return;
1485
1486 wpa_printf(MSG_DEBUG,
1487 "DPP: Timeout while waiting for Connection Status Result");
1488 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08001489 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001490 wpas_dpp_listen_stop(wpa_s);
1491 dpp_auth_deinit(auth);
1492 wpa_s->dpp_auth = NULL;
1493}
1494
1495
Hai Shalom021b0b52019-04-10 11:17:58 -07001496static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
1497 const u8 *hdr, const u8 *buf, size_t len)
1498{
1499 struct dpp_authentication *auth = wpa_s->dpp_auth;
1500 enum dpp_status_error status;
1501
1502 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1503 MAC2STR(src));
1504
1505 if (!auth || !auth->waiting_conf_result) {
1506 wpa_printf(MSG_DEBUG,
1507 "DPP: No DPP Configuration waiting for result - drop");
1508 return;
1509 }
1510
1511 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1512 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1513 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1514 return;
1515 }
1516
1517 status = dpp_conf_result_rx(auth, hdr, buf, len);
1518
Hai Shalomc3565922019-10-28 11:58:20 -07001519 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1520 wpa_msg(wpa_s, MSG_INFO,
1521 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1522 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08001523 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001524 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
1525 wpa_s, NULL);
1526 auth->waiting_conn_status_result = 1;
1527 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1528 wpa_s, NULL);
1529 eloop_register_timeout(16, 0,
1530 wpas_dpp_conn_status_result_wait_timeout,
1531 wpa_s, NULL);
1532 offchannel_send_action_done(wpa_s);
1533 wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq :
1534 auth->curr_freq);
1535 return;
1536 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001537 offchannel_send_action_done(wpa_s);
1538 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001539 if (status == DPP_STATUS_OK) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001540 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalome4073332019-11-05 16:20:12 -08001541 wpas_notify_dpp_config_sent(wpa_s);
1542 }
1543 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07001544 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001545 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001546 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001547 dpp_auth_deinit(auth);
1548 wpa_s->dpp_auth = NULL;
1549 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
1550}
1551
Hai Shalom81f62d82019-07-22 12:10:00 -07001552
Hai Shalomc3565922019-10-28 11:58:20 -07001553static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
1554 const u8 *src, const u8 *hdr,
1555 const u8 *buf, size_t len)
1556{
1557 struct dpp_authentication *auth = wpa_s->dpp_auth;
1558 enum dpp_status_error status;
1559 u8 ssid[SSID_MAX_LEN];
1560 size_t ssid_len = 0;
1561 char *channel_list = NULL;
1562
1563 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1564
1565 if (!auth || !auth->waiting_conn_status_result) {
1566 wpa_printf(MSG_DEBUG,
1567 "DPP: No DPP Configuration waiting for connection status result - drop");
1568 return;
1569 }
1570
1571 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1572 ssid, &ssid_len, &channel_list);
1573 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1574 "result=%d ssid=%s channel_list=%s",
1575 status, wpa_ssid_txt(ssid, ssid_len),
1576 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08001577 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
1578 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07001579 os_free(channel_list);
1580 offchannel_send_action_done(wpa_s);
1581 wpas_dpp_listen_stop(wpa_s);
1582 dpp_auth_deinit(auth);
1583 wpa_s->dpp_auth = NULL;
1584 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1585 wpa_s, NULL);
1586}
1587
1588
Hai Shalom81f62d82019-07-22 12:10:00 -07001589static int wpas_dpp_process_conf_obj(void *ctx,
1590 struct dpp_authentication *auth)
1591{
1592 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07001593 unsigned int i;
1594 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001595
Hai Shalomc3565922019-10-28 11:58:20 -07001596 for (i = 0; i < auth->num_conf_obj; i++) {
1597 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1598 &auth->conf_obj[i]);
1599 if (res)
1600 break;
1601 }
1602 if (!res)
1603 wpas_dpp_post_process_config(wpa_s, auth);
1604
1605 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07001606}
1607
Hai Shalom021b0b52019-04-10 11:17:58 -07001608#endif /* CONFIG_DPP2 */
1609
1610
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001611static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
1612 const u8 *src,
1613 const u8 *buf, size_t len)
1614{
1615 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001616 const u8 *connector, *trans_id, *status;
1617 u16 connector_len, trans_id_len, status_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001618 struct dpp_introduction intro;
1619 struct rsn_pmksa_cache_entry *entry;
1620 struct os_time now;
1621 struct os_reltime rnow;
1622 os_time_t expiry;
1623 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001624 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001625
1626 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
1627 MAC2STR(src));
1628 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
1629 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
1630 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
1631 MACSTR " - drop", MAC2STR(src));
1632 return;
1633 }
1634 offchannel_send_action_done(wpa_s);
1635
1636 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1637 if (ssid == wpa_s->dpp_intro_network)
1638 break;
1639 }
1640 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
1641 !ssid->dpp_csign) {
1642 wpa_printf(MSG_DEBUG,
1643 "DPP: Profile not found for network introduction");
1644 return;
1645 }
1646
1647 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1648 &trans_id_len);
1649 if (!trans_id || trans_id_len != 1) {
1650 wpa_printf(MSG_DEBUG,
1651 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001652 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1653 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001654 goto fail;
1655 }
1656 if (trans_id[0] != TRANSACTION_ID) {
1657 wpa_printf(MSG_DEBUG,
1658 "DPP: Ignore frame with unexpected Transaction ID %u",
1659 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001660 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1661 " fail=transaction_id_mismatch", MAC2STR(src));
1662 goto fail;
1663 }
1664
1665 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
1666 if (!status || status_len != 1) {
1667 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
1668 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1669 " fail=missing_status", MAC2STR(src));
1670 goto fail;
1671 }
1672 if (status[0] != DPP_STATUS_OK) {
1673 wpa_printf(MSG_DEBUG,
1674 "DPP: Peer rejected network introduction: Status %u",
1675 status[0]);
1676 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1677 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07001678#ifdef CONFIG_DPP2
1679 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
1680#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001681 goto fail;
1682 }
1683
1684 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1685 if (!connector) {
1686 wpa_printf(MSG_DEBUG,
1687 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001688 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1689 " fail=missing_connector", MAC2STR(src));
1690 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001691 }
1692
Roshan Pius3a1667e2018-07-03 15:17:14 -07001693 res = dpp_peer_intro(&intro, ssid->dpp_connector,
1694 ssid->dpp_netaccesskey,
1695 ssid->dpp_netaccesskey_len,
1696 ssid->dpp_csign,
1697 ssid->dpp_csign_len,
1698 connector, connector_len, &expiry);
1699 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001700 wpa_printf(MSG_INFO,
1701 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001702 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1703 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07001704#ifdef CONFIG_DPP2
1705 wpas_dpp_send_conn_status_result(wpa_s, res);
1706#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001707 goto fail;
1708 }
1709
1710 entry = os_zalloc(sizeof(*entry));
1711 if (!entry)
1712 goto fail;
1713 os_memcpy(entry->aa, src, ETH_ALEN);
1714 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
1715 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
1716 entry->pmk_len = intro.pmk_len;
1717 entry->akmp = WPA_KEY_MGMT_DPP;
1718 if (expiry) {
1719 os_get_time(&now);
1720 seconds = expiry - now.sec;
1721 } else {
1722 seconds = 86400 * 7;
1723 }
1724 os_get_reltime(&rnow);
1725 entry->expiration = rnow.sec + seconds;
1726 entry->reauth_time = rnow.sec + seconds;
1727 entry->network_ctx = ssid;
1728 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
1729
Roshan Pius3a1667e2018-07-03 15:17:14 -07001730 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1731 " status=%u", MAC2STR(src), status[0]);
1732
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001733 wpa_printf(MSG_DEBUG,
1734 "DPP: Try connection again after successful network introduction");
1735 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
1736 wpa_supplicant_cancel_sched_scan(wpa_s);
1737 wpa_supplicant_req_scan(wpa_s, 0, 0);
1738 }
1739fail:
1740 os_memset(&intro, 0, sizeof(intro));
1741}
1742
1743
Roshan Pius3a1667e2018-07-03 15:17:14 -07001744static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
1745{
1746 int i, j;
1747
1748 if (!wpa_s->hw.modes)
1749 return -1;
1750
1751 for (i = 0; i < wpa_s->hw.num_modes; i++) {
1752 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
1753
1754 for (j = 0; j < mode->num_channels; j++) {
1755 struct hostapd_channel_data *chan = &mode->channels[j];
1756
1757 if (chan->freq != (int) freq)
1758 continue;
1759
1760 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
1761 HOSTAPD_CHAN_NO_IR |
1762 HOSTAPD_CHAN_RADAR))
1763 continue;
1764
1765 return 1;
1766 }
1767 }
1768
1769 wpa_printf(MSG_DEBUG,
1770 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
1771 freq);
1772
1773 return 0;
1774}
1775
1776
1777static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
1778 struct dpp_pkex *pkex)
1779{
1780 if (pkex->freq == 2437)
1781 pkex->freq = 5745;
1782 else if (pkex->freq == 5745)
1783 pkex->freq = 5220;
1784 else if (pkex->freq == 5220)
1785 pkex->freq = 60480;
1786 else
1787 return -1; /* no more channels to try */
1788
1789 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
1790 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
1791 pkex->freq);
1792 return 0;
1793 }
1794
1795 /* Could not use this channel - try the next one */
1796 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
1797}
1798
1799
1800static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
1801{
1802 struct wpa_supplicant *wpa_s = eloop_ctx;
1803 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1804
1805 if (!pkex || !pkex->exchange_req)
1806 return;
1807 if (pkex->exch_req_tries >= 5) {
1808 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
1809 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1810 "No response from PKEX peer");
1811 dpp_pkex_free(pkex);
1812 wpa_s->dpp_pkex = NULL;
1813 return;
1814 }
1815 pkex->exch_req_tries = 0;
1816 }
1817
1818 pkex->exch_req_tries++;
1819 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
1820 pkex->exch_req_tries);
1821 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1822 MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
1823 offchannel_send_action(wpa_s, pkex->freq, broadcast,
1824 wpa_s->own_addr, broadcast,
1825 wpabuf_head(pkex->exchange_req),
1826 wpabuf_len(pkex->exchange_req),
1827 pkex->exch_req_wait_time,
1828 wpas_dpp_tx_pkex_status, 0);
1829}
1830
1831
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001832static void
1833wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
1834 unsigned int freq, const u8 *dst,
1835 const u8 *src, const u8 *bssid,
1836 const u8 *data, size_t data_len,
1837 enum offchannel_send_action_result result)
1838{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001839 const char *res_txt;
1840 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1841
1842 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
1843 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
1844 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001845 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
1846 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001847 freq, MAC2STR(dst), res_txt);
1848 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
1849 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
1850
1851 if (!pkex) {
1852 wpa_printf(MSG_DEBUG,
1853 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
1854 return;
1855 }
1856
1857 if (pkex->failed) {
1858 wpa_printf(MSG_DEBUG,
1859 "DPP: Terminate PKEX exchange due to an earlier error");
1860 if (pkex->t > pkex->own_bi->pkex_t)
1861 pkex->own_bi->pkex_t = pkex->t;
1862 dpp_pkex_free(pkex);
1863 wpa_s->dpp_pkex = NULL;
1864 return;
1865 }
1866
1867 if (pkex->exch_req_wait_time && pkex->exchange_req) {
1868 /* Wait for PKEX Exchange Response frame and retry request if
1869 * no response is seen. */
1870 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1871 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
1872 (pkex->exch_req_wait_time % 1000) * 1000,
1873 wpas_dpp_pkex_retry_timeout, wpa_s,
1874 NULL);
1875 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001876}
1877
1878
1879static void
1880wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
1881 const u8 *buf, size_t len, unsigned int freq)
1882{
1883 struct wpabuf *msg;
1884 unsigned int wait_time;
1885
1886 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1887 MAC2STR(src));
1888
1889 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1890 * values here */
1891
1892 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
1893 wpa_printf(MSG_DEBUG,
1894 "DPP: No PKEX code configured - ignore request");
1895 return;
1896 }
1897
1898 if (wpa_s->dpp_pkex) {
1899 /* TODO: Support parallel operations */
1900 wpa_printf(MSG_DEBUG,
1901 "DPP: Already in PKEX session - ignore new request");
1902 return;
1903 }
1904
Roshan Pius3a1667e2018-07-03 15:17:14 -07001905 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001906 wpa_s->own_addr, src,
1907 wpa_s->dpp_pkex_identifier,
1908 wpa_s->dpp_pkex_code,
1909 buf, len);
1910 if (!wpa_s->dpp_pkex) {
1911 wpa_printf(MSG_DEBUG,
1912 "DPP: Failed to process the request - ignore it");
1913 return;
1914 }
1915
1916 msg = wpa_s->dpp_pkex->exchange_resp;
1917 wait_time = wpa_s->max_remain_on_chan;
1918 if (wait_time > 2000)
1919 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001920 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1921 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001922 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1923 broadcast,
1924 wpabuf_head(msg), wpabuf_len(msg),
1925 wait_time, wpas_dpp_tx_pkex_status, 0);
1926}
1927
1928
1929static void
1930wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
1931 const u8 *buf, size_t len, unsigned int freq)
1932{
1933 struct wpabuf *msg;
1934 unsigned int wait_time;
1935
1936 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1937 MAC2STR(src));
1938
1939 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1940 * values here */
1941
1942 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
1943 wpa_s->dpp_pkex->exchange_done) {
1944 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1945 return;
1946 }
1947
Roshan Pius3a1667e2018-07-03 15:17:14 -07001948 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1949 wpa_s->dpp_pkex->exch_req_wait_time = 0;
1950
1951 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001952 if (!msg) {
1953 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1954 return;
1955 }
1956
1957 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1958 MAC2STR(src));
1959
1960 wait_time = wpa_s->max_remain_on_chan;
1961 if (wait_time > 2000)
1962 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001963 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1964 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001965 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1966 broadcast,
1967 wpabuf_head(msg), wpabuf_len(msg),
1968 wait_time, wpas_dpp_tx_pkex_status, 0);
1969 wpabuf_free(msg);
1970}
1971
1972
Roshan Pius3a1667e2018-07-03 15:17:14 -07001973static struct dpp_bootstrap_info *
1974wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
1975 unsigned int freq)
1976{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001977 struct dpp_bootstrap_info *bi;
1978
Hai Shalom021b0b52019-04-10 11:17:58 -07001979 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001980 if (!bi)
1981 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001982 wpa_s->dpp_pkex = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001983 return bi;
1984}
1985
1986
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001987static void
1988wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
1989 const u8 *hdr, const u8 *buf, size_t len,
1990 unsigned int freq)
1991{
1992 struct wpabuf *msg;
1993 unsigned int wait_time;
1994 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001995
1996 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1997 MAC2STR(src));
1998
1999 if (!pkex || pkex->initiator || !pkex->exchange_done) {
2000 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2001 return;
2002 }
2003
2004 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
2005 if (!msg) {
2006 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07002007 if (pkex->failed) {
2008 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
2009 if (pkex->t > pkex->own_bi->pkex_t)
2010 pkex->own_bi->pkex_t = pkex->t;
2011 dpp_pkex_free(wpa_s->dpp_pkex);
2012 wpa_s->dpp_pkex = NULL;
2013 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002014 return;
2015 }
2016
2017 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
2018 MACSTR, MAC2STR(src));
2019
2020 wait_time = wpa_s->max_remain_on_chan;
2021 if (wait_time > 2000)
2022 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002023 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2024 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002025 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2026 broadcast,
2027 wpabuf_head(msg), wpabuf_len(msg),
2028 wait_time, wpas_dpp_tx_pkex_status, 0);
2029 wpabuf_free(msg);
2030
Roshan Pius3a1667e2018-07-03 15:17:14 -07002031 wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002032}
2033
2034
2035static void
2036wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2037 const u8 *hdr, const u8 *buf, size_t len,
2038 unsigned int freq)
2039{
2040 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002041 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002042 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2043 char cmd[500];
2044
2045 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2046 MAC2STR(src));
2047
2048 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2049 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2050 return;
2051 }
2052
2053 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2054 if (res < 0) {
2055 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2056 return;
2057 }
2058
Roshan Pius3a1667e2018-07-03 15:17:14 -07002059 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002060 if (!bi)
2061 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002062
2063 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2064 bi->id,
2065 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
2066 wpa_printf(MSG_DEBUG,
2067 "DPP: Start authentication after PKEX with parameters: %s",
2068 cmd);
2069 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
2070 wpa_printf(MSG_DEBUG,
2071 "DPP: Authentication initialization failed");
2072 return;
2073 }
2074}
2075
2076
2077void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
2078 const u8 *buf, size_t len, unsigned int freq)
2079{
2080 u8 crypto_suite;
2081 enum dpp_public_action_frame_type type;
2082 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002083 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002084
2085 if (len < DPP_HDR_LEN)
2086 return;
2087 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2088 return;
2089 hdr = buf;
2090 buf += 4;
2091 len -= 4;
2092 crypto_suite = *buf++;
2093 type = *buf++;
2094 len -= 2;
2095
2096 wpa_printf(MSG_DEBUG,
2097 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2098 MACSTR " freq=%u",
2099 crypto_suite, type, MAC2STR(src), freq);
2100 if (crypto_suite != 1) {
2101 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2102 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002103 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2104 " freq=%u type=%d ignore=unsupported-crypto-suite",
2105 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002106 return;
2107 }
2108 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002109 if (dpp_check_attrs(buf, len) < 0) {
2110 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2111 " freq=%u type=%d ignore=invalid-attributes",
2112 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002113 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002114 }
2115 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
2116 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002117
2118 switch (type) {
2119 case DPP_PA_AUTHENTICATION_REQ:
2120 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
2121 break;
2122 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002123 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002124 break;
2125 case DPP_PA_AUTHENTICATION_CONF:
2126 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
2127 break;
2128 case DPP_PA_PEER_DISCOVERY_RESP:
2129 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
2130 break;
2131 case DPP_PA_PKEX_EXCHANGE_REQ:
2132 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
2133 break;
2134 case DPP_PA_PKEX_EXCHANGE_RESP:
2135 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
2136 break;
2137 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2138 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
2139 freq);
2140 break;
2141 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2142 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
2143 freq);
2144 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002145#ifdef CONFIG_DPP2
2146 case DPP_PA_CONFIGURATION_RESULT:
2147 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
2148 break;
Hai Shalomc3565922019-10-28 11:58:20 -07002149 case DPP_PA_CONNECTION_STATUS_RESULT:
2150 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
2151 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002152#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002153 default:
2154 wpa_printf(MSG_DEBUG,
2155 "DPP: Ignored unsupported frame subtype %d", type);
2156 break;
2157 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002158
2159 if (wpa_s->dpp_pkex)
2160 pkex_t = wpa_s->dpp_pkex->t;
2161 else if (wpa_s->dpp_pkex_bi)
2162 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
2163 else
2164 pkex_t = 0;
2165 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2166 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2167 wpas_dpp_pkex_remove(wpa_s, "*");
2168 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002169}
2170
2171
2172static struct wpabuf *
2173wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query,
2174 size_t query_len)
2175{
2176 struct wpa_supplicant *wpa_s = ctx;
2177 struct dpp_authentication *auth = wpa_s->dpp_auth;
2178 struct wpabuf *resp;
2179
2180 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
2181 MAC2STR(sa));
2182 if (!auth || !auth->auth_success ||
2183 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
2184 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2185 return NULL;
2186 }
Hai Shalomc3565922019-10-28 11:58:20 -07002187
2188 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
2189 wpa_printf(MSG_DEBUG,
2190 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
2191 /* wpas_dpp_auth_success() would normally have been called from
2192 * TX status handler, but since there was no such handler call
2193 * yet, simply send out the event message and proceed with
2194 * exchange. */
2195 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
2196 wpa_s->dpp_auth_ok_on_ack = 0;
2197 }
2198
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002199 wpa_hexdump(MSG_DEBUG,
2200 "DPP: Received Configuration Request (GAS Query Request)",
2201 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002202 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2203 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002204 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom59532852018-12-07 10:32:58 -08002205 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002206 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002207 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002208 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002209 auth->conf_resp = resp;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002210 return resp;
2211}
2212
2213
2214static void
2215wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
2216{
2217 struct wpa_supplicant *wpa_s = ctx;
2218 struct dpp_authentication *auth = wpa_s->dpp_auth;
2219
2220 if (!auth) {
2221 wpabuf_free(resp);
2222 return;
2223 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002224 if (auth->conf_resp != resp) {
2225 wpa_printf(MSG_DEBUG,
2226 "DPP: Ignore GAS status report (ok=%d) for unknown response",
2227 ok);
2228 wpabuf_free(resp);
2229 return;
2230 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002231
2232 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2233 ok);
2234 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002235 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002236#ifdef CONFIG_DPP2
2237 if (ok && auth->peer_version >= 2 &&
2238 auth->conf_resp_status == DPP_STATUS_OK) {
2239 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08002240 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002241 auth->waiting_conf_result = 1;
2242 auth->conf_resp = NULL;
2243 wpabuf_free(resp);
2244 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2245 wpa_s, NULL);
2246 eloop_register_timeout(2, 0,
2247 wpas_dpp_config_result_wait_timeout,
2248 wpa_s, NULL);
2249 return;
2250 }
2251#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002252 offchannel_send_action_done(wpa_s);
2253 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002254 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002255 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08002256 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002257 }
2258 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002259 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002260 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002261 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002262 dpp_auth_deinit(wpa_s->dpp_auth);
2263 wpa_s->dpp_auth = NULL;
2264 wpabuf_free(resp);
2265}
2266
2267
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002268int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
2269{
2270 struct dpp_authentication *auth;
2271 int ret = -1;
2272 char *curve = NULL;
2273
2274 auth = os_zalloc(sizeof(*auth));
2275 if (!auth)
2276 return -1;
2277
2278 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08002279 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalom021b0b52019-04-10 11:17:58 -07002280 if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 &&
2281 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002282 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
2283 &auth->conf_obj[0]);
2284 if (!ret)
2285 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002286
2287 dpp_auth_deinit(auth);
2288 os_free(curve);
2289
2290 return ret;
2291}
2292
2293
2294static void
2295wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
2296 unsigned int freq, const u8 *dst,
2297 const u8 *src, const u8 *bssid,
2298 const u8 *data, size_t data_len,
2299 enum offchannel_send_action_result result)
2300{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002301 const char *res_txt;
2302
2303 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2304 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2305 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002306 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2307 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002308 freq, MAC2STR(dst), res_txt);
2309 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2310 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002311 /* TODO: Time out wait for response more quickly in error cases? */
2312}
2313
2314
2315int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2316 struct wpa_bss *bss)
2317{
2318 struct os_time now;
2319 struct wpabuf *msg;
2320 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07002321 const u8 *rsn;
2322 struct wpa_ie_data ied;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002323
2324 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
2325 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07002326 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2327 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
2328 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
2329 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002330 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
2331 return 0; /* PMKSA exists for DPP AKM - continue */
2332
2333 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2334 !ssid->dpp_csign) {
2335 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2336 "missing %s",
2337 !ssid->dpp_connector ? "Connector" :
2338 (!ssid->dpp_netaccesskey ? "netAccessKey" :
2339 "C-sign-key"));
2340 return -1;
2341 }
2342
2343 os_get_time(&now);
2344
2345 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002346 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002347 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2348 "netAccessKey expired");
2349 return -1;
2350 }
2351
2352 wpa_printf(MSG_DEBUG,
2353 "DPP: Starting network introduction protocol to derive PMKSA for "
2354 MACSTR, MAC2STR(bss->bssid));
2355
2356 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ,
2357 5 + 4 + os_strlen(ssid->dpp_connector));
2358 if (!msg)
2359 return -1;
2360
Roshan Pius3a1667e2018-07-03 15:17:14 -07002361#ifdef CONFIG_TESTING_OPTIONS
2362 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
2363 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
2364 goto skip_trans_id;
2365 }
2366 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
2367 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
2368 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2369 wpabuf_put_le16(msg, 0);
2370 goto skip_trans_id;
2371 }
2372#endif /* CONFIG_TESTING_OPTIONS */
2373
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002374 /* Transaction ID */
2375 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2376 wpabuf_put_le16(msg, 1);
2377 wpabuf_put_u8(msg, TRANSACTION_ID);
2378
Roshan Pius3a1667e2018-07-03 15:17:14 -07002379#ifdef CONFIG_TESTING_OPTIONS
2380skip_trans_id:
2381 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
2382 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
2383 goto skip_connector;
2384 }
2385 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
2386 char *connector;
2387
2388 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
2389 connector = dpp_corrupt_connector_signature(
2390 ssid->dpp_connector);
2391 if (!connector) {
2392 wpabuf_free(msg);
2393 return -1;
2394 }
2395 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2396 wpabuf_put_le16(msg, os_strlen(connector));
2397 wpabuf_put_str(msg, connector);
2398 os_free(connector);
2399 goto skip_connector;
2400 }
2401#endif /* CONFIG_TESTING_OPTIONS */
2402
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002403 /* DPP Connector */
2404 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2405 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
2406 wpabuf_put_str(msg, ssid->dpp_connector);
2407
Roshan Pius3a1667e2018-07-03 15:17:14 -07002408#ifdef CONFIG_TESTING_OPTIONS
2409skip_connector:
2410#endif /* CONFIG_TESTING_OPTIONS */
2411
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002412 /* TODO: Timeout on AP response */
2413 wait_time = wpa_s->max_remain_on_chan;
2414 if (wait_time > 2000)
2415 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002416 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2417 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002418 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
2419 broadcast,
2420 wpabuf_head(msg), wpabuf_len(msg),
2421 wait_time, wpas_dpp_tx_introduction_status, 0);
2422 wpabuf_free(msg);
2423
2424 /* Request this connection attempt to terminate - new one will be
2425 * started when network introduction protocol completes */
2426 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
2427 wpa_s->dpp_intro_network = ssid;
2428 return 1;
2429}
2430
2431
2432int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
2433{
2434 struct dpp_bootstrap_info *own_bi;
2435 const char *pos, *end;
2436 unsigned int wait_time;
2437
2438 pos = os_strstr(cmd, " own=");
2439 if (!pos)
2440 return -1;
2441 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07002442 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002443 if (!own_bi) {
2444 wpa_printf(MSG_DEBUG,
2445 "DPP: Identified bootstrap info not found");
2446 return -1;
2447 }
2448 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2449 wpa_printf(MSG_DEBUG,
2450 "DPP: Identified bootstrap info not for PKEX");
2451 return -1;
2452 }
2453 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002454 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002455
2456 os_free(wpa_s->dpp_pkex_identifier);
2457 wpa_s->dpp_pkex_identifier = NULL;
2458 pos = os_strstr(cmd, " identifier=");
2459 if (pos) {
2460 pos += 12;
2461 end = os_strchr(pos, ' ');
2462 if (!end)
2463 return -1;
2464 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
2465 if (!wpa_s->dpp_pkex_identifier)
2466 return -1;
2467 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
2468 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
2469 }
2470
2471 pos = os_strstr(cmd, " code=");
2472 if (!pos)
2473 return -1;
2474 os_free(wpa_s->dpp_pkex_code);
2475 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
2476 if (!wpa_s->dpp_pkex_code)
2477 return -1;
2478
2479 if (os_strstr(cmd, " init=1")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002480 struct dpp_pkex *pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002481 struct wpabuf *msg;
2482
2483 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
2484 dpp_pkex_free(wpa_s->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002485 wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002486 wpa_s->dpp_pkex_identifier,
2487 wpa_s->dpp_pkex_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002488 pkex = wpa_s->dpp_pkex;
2489 if (!pkex)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002490 return -1;
2491
Roshan Pius3a1667e2018-07-03 15:17:14 -07002492 msg = pkex->exchange_req;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002493 wait_time = wpa_s->max_remain_on_chan;
2494 if (wait_time > 2000)
2495 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002496 pkex->freq = 2437;
2497 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2498 " freq=%u type=%d",
2499 MAC2STR(broadcast), pkex->freq,
2500 DPP_PA_PKEX_EXCHANGE_REQ);
2501 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2502 wpa_s->own_addr, broadcast,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002503 wpabuf_head(msg), wpabuf_len(msg),
2504 wait_time, wpas_dpp_tx_pkex_status, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002505 if (wait_time == 0)
2506 wait_time = 2000;
2507 pkex->exch_req_wait_time = wait_time;
2508 pkex->exch_req_tries = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002509 }
2510
2511 /* TODO: Support multiple PKEX info entries */
2512
2513 os_free(wpa_s->dpp_pkex_auth_cmd);
2514 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
2515
2516 return 1;
2517}
2518
2519
2520int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
2521{
2522 unsigned int id_val;
2523
2524 if (os_strcmp(id, "*") == 0) {
2525 id_val = 0;
2526 } else {
2527 id_val = atoi(id);
2528 if (id_val == 0)
2529 return -1;
2530 }
2531
2532 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
2533 return -1;
2534
2535 /* TODO: Support multiple PKEX entries */
2536 os_free(wpa_s->dpp_pkex_code);
2537 wpa_s->dpp_pkex_code = NULL;
2538 os_free(wpa_s->dpp_pkex_identifier);
2539 wpa_s->dpp_pkex_identifier = NULL;
2540 os_free(wpa_s->dpp_pkex_auth_cmd);
2541 wpa_s->dpp_pkex_auth_cmd = NULL;
2542 wpa_s->dpp_pkex_bi = NULL;
2543 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2544 dpp_pkex_free(wpa_s->dpp_pkex);
2545 wpa_s->dpp_pkex = NULL;
2546 return 0;
2547}
2548
2549
Roshan Pius3a1667e2018-07-03 15:17:14 -07002550void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
2551{
2552 dpp_auth_deinit(wpa_s->dpp_auth);
2553 wpa_s->dpp_auth = NULL;
2554 dpp_pkex_free(wpa_s->dpp_pkex);
2555 wpa_s->dpp_pkex = NULL;
2556 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
2557 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
2558}
2559
2560
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002561int wpas_dpp_init(struct wpa_supplicant *wpa_s)
2562{
Hai Shalom81f62d82019-07-22 12:10:00 -07002563 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002564 u8 adv_proto_id[7];
2565
2566 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
2567 adv_proto_id[1] = 5;
2568 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
2569 adv_proto_id[5] = DPP_OUI_TYPE;
2570 adv_proto_id[6] = 0x01;
2571
2572 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
2573 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
2574 wpas_dpp_gas_status_handler, wpa_s) < 0)
2575 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002576
2577 os_memset(&config, 0, sizeof(config));
2578 config.msg_ctx = wpa_s;
2579 config.cb_ctx = wpa_s;
2580#ifdef CONFIG_DPP2
2581 config.process_conf_obj = wpas_dpp_process_conf_obj;
2582#endif /* CONFIG_DPP2 */
2583 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07002584 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002585}
2586
2587
2588void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
2589{
2590#ifdef CONFIG_TESTING_OPTIONS
2591 os_free(wpa_s->dpp_config_obj_override);
2592 wpa_s->dpp_config_obj_override = NULL;
2593 os_free(wpa_s->dpp_discovery_override);
2594 wpa_s->dpp_discovery_override = NULL;
2595 os_free(wpa_s->dpp_groups_override);
2596 wpa_s->dpp_groups_override = NULL;
2597 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
2598#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07002599 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002600 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07002601 dpp_global_clear(wpa_s->dpp);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002602 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002603 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002604 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
2605 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002606#ifdef CONFIG_DPP2
2607 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07002608 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2609 wpa_s, NULL);
2610 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002611 dpp_pfs_free(wpa_s->dpp_pfs);
2612 wpa_s->dpp_pfs = NULL;
2613#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002614 offchannel_send_action_done(wpa_s);
2615 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002616 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002617 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002618 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
2619 os_free(wpa_s->dpp_configurator_params);
2620 wpa_s->dpp_configurator_params = NULL;
2621}
Hai Shalom81f62d82019-07-22 12:10:00 -07002622
2623
2624#ifdef CONFIG_DPP2
2625int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
2626{
2627 struct dpp_controller_config config;
2628 const char *pos;
2629
2630 os_memset(&config, 0, sizeof(config));
2631 if (cmd) {
2632 pos = os_strstr(cmd, " tcp_port=");
2633 if (pos) {
2634 pos += 10;
2635 config.tcp_port = atoi(pos);
2636 }
2637 }
2638 config.configurator_params = wpa_s->dpp_configurator_params;
2639 return dpp_controller_start(wpa_s->dpp, &config);
2640}
2641#endif /* CONFIG_DPP2 */