blob: dee8e28af6018cba3a9498f4ea2a5cac5fa7439a [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
Roshan Pius3a1667e2018-07-03 15:17:14 -070092static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
93{
94 struct wpa_supplicant *wpa_s = eloop_ctx;
95 struct dpp_authentication *auth = wpa_s->dpp_auth;
96
97 if (!auth || !auth->resp_msg)
98 return;
99
100 wpa_printf(MSG_DEBUG,
101 "DPP: Retry Authentication Response after timeout");
102 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
103 " freq=%u type=%d",
104 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
105 DPP_PA_AUTHENTICATION_RESP);
106 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
107 wpa_s->own_addr, broadcast,
108 wpabuf_head(auth->resp_msg),
109 wpabuf_len(auth->resp_msg),
110 500, wpas_dpp_tx_status, 0);
111}
112
113
114static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
115{
116 struct dpp_authentication *auth = wpa_s->dpp_auth;
117 unsigned int wait_time, max_tries;
118
119 if (!auth || !auth->resp_msg)
120 return;
121
122 if (wpa_s->dpp_resp_max_tries)
123 max_tries = wpa_s->dpp_resp_max_tries;
124 else
125 max_tries = 5;
126 auth->auth_resp_tries++;
127 if (auth->auth_resp_tries >= max_tries) {
128 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
129 offchannel_send_action_done(wpa_s);
130 dpp_auth_deinit(wpa_s->dpp_auth);
131 wpa_s->dpp_auth = NULL;
132 return;
133 }
134
135 if (wpa_s->dpp_resp_retry_time)
136 wait_time = wpa_s->dpp_resp_retry_time;
137 else
138 wait_time = 1000;
139 wpa_printf(MSG_DEBUG,
140 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
141 wait_time);
142 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
143 eloop_register_timeout(wait_time / 1000,
144 (wait_time % 1000) * 1000,
145 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
146}
147
148
Hai Shalom021b0b52019-04-10 11:17:58 -0700149static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
150{
151 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
Hai Shalomc3565922019-10-28 11:58:20 -0700152 wpa_s->suitable_network = 0;
153 wpa_s->no_suitable_network = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700154 wpa_s->disconnected = 0;
155 wpa_s->reassociate = 1;
156 wpa_s->scan_runs = 0;
157 wpa_s->normal_scans = 0;
158 wpa_supplicant_cancel_sched_scan(wpa_s);
159 wpa_supplicant_req_scan(wpa_s, 0, 0);
160}
161
162
Hai Shalomc3565922019-10-28 11:58:20 -0700163#ifdef CONFIG_DPP2
164
165static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
166 void *timeout_ctx)
167{
168 struct wpa_supplicant *wpa_s = eloop_ctx;
169 struct dpp_authentication *auth = wpa_s->dpp_auth;
170 enum dpp_status_error result;
171
172 if (!auth || !auth->conn_status_requested)
173 return;
174
175 wpa_printf(MSG_DEBUG,
176 "DPP: Connection timeout - report Connection Status Result");
177 if (wpa_s->suitable_network)
178 result = DPP_STATUS_AUTH_FAILURE;
179 else if (wpa_s->no_suitable_network)
180 result = DPP_STATUS_NO_AP;
181 else
182 result = 255; /* What to report here for unexpected state? */
183 wpas_dpp_send_conn_status_result(wpa_s, result);
184}
185
186
187static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s)
188{
189 char *str, *end, *pos;
190 size_t len;
191 unsigned int i;
192 u8 last_op_class = 0;
193 int res;
194
195 if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs)
196 return NULL;
197
198 len = wpa_s->num_last_scan_freqs * 8;
199 str = os_zalloc(len);
200 if (!str)
201 return NULL;
202 end = str + len;
203 pos = str;
204
205 for (i = 0; i < wpa_s->num_last_scan_freqs; i++) {
206 enum hostapd_hw_mode mode;
207 u8 op_class, channel;
208
209 mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i],
210 0, 0, &op_class, &channel);
211 if (mode == NUM_HOSTAPD_MODES)
212 continue;
213 if (op_class == last_op_class)
214 res = os_snprintf(pos, end - pos, ",%d", channel);
215 else
216 res = os_snprintf(pos, end - pos, "%s%d/%d",
217 pos == str ? "" : ",",
218 op_class, channel);
219 if (os_snprintf_error(end - pos, res)) {
220 *pos = '\0';
221 break;
222 }
223 pos += res;
224 last_op_class = op_class;
225 }
226
227 if (pos == str) {
228 os_free(str);
229 str = NULL;
230 }
231 return str;
232}
233
234
235void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
236 enum dpp_status_error result)
237{
238 struct wpabuf *msg;
239 const char *channel_list = NULL;
240 char *channel_list_buf = NULL;
241 struct wpa_ssid *ssid = wpa_s->current_ssid;
242 struct dpp_authentication *auth = wpa_s->dpp_auth;
243
244 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
245
246 if (!auth || !auth->conn_status_requested)
247 return;
248 auth->conn_status_requested = 0;
249 wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
250 result);
251
252 if (result == DPP_STATUS_NO_AP) {
253 channel_list_buf = wpas_dpp_scan_channel_list(wpa_s);
254 channel_list = channel_list_buf;
255 }
256
257 msg = dpp_build_conn_status_result(auth, result,
258 ssid ? ssid->ssid :
259 wpa_s->dpp_last_ssid,
260 ssid ? ssid->ssid_len :
261 wpa_s->dpp_last_ssid_len,
262 channel_list);
263 os_free(channel_list_buf);
264 if (!msg) {
265 dpp_auth_deinit(wpa_s->dpp_auth);
266 wpa_s->dpp_auth = NULL;
267 return;
268 }
269
270 wpa_msg(wpa_s, MSG_INFO,
271 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
272 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
273 DPP_PA_CONNECTION_STATUS_RESULT);
274 offchannel_send_action(wpa_s, auth->curr_freq,
275 auth->peer_mac_addr, wpa_s->own_addr, broadcast,
276 wpabuf_head(msg), wpabuf_len(msg),
277 500, wpas_dpp_tx_status, 0);
278 wpabuf_free(msg);
279
280 /* This exchange will be terminated in the TX status handler */
281 auth->remove_on_tx_status = 1;
282
283 return;
284}
285
286
287void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
288{
289 struct dpp_authentication *auth = wpa_s->dpp_auth;
290
291 if (auth && auth->conn_status_requested)
292 wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
293}
294
295#endif /* CONFIG_DPP2 */
296
297
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700298static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
299 unsigned int freq, const u8 *dst,
300 const u8 *src, const u8 *bssid,
301 const u8 *data, size_t data_len,
302 enum offchannel_send_action_result result)
303{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700304 const char *res_txt;
305 struct dpp_authentication *auth = wpa_s->dpp_auth;
306
307 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
308 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
309 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700310 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700311 " result=%s", freq, MAC2STR(dst), res_txt);
312 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
313 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700314
315 if (!wpa_s->dpp_auth) {
316 wpa_printf(MSG_DEBUG,
317 "DPP: Ignore TX status since there is no ongoing authentication exchange");
318 return;
319 }
320
Hai Shalom021b0b52019-04-10 11:17:58 -0700321#ifdef CONFIG_DPP2
322 if (auth->connect_on_tx_status) {
Hai Shalomc3565922019-10-28 11:58:20 -0700323 auth->connect_on_tx_status = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700324 wpa_printf(MSG_DEBUG,
325 "DPP: Try to connect after completed configuration result");
326 wpas_dpp_try_to_connect(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -0700327 if (auth->conn_status_requested) {
328 wpa_printf(MSG_DEBUG,
329 "DPP: Start 15 second timeout for reporting connection status result");
330 eloop_cancel_timeout(
331 wpas_dpp_conn_status_result_timeout,
332 wpa_s, NULL);
333 eloop_register_timeout(
334 15, 0, wpas_dpp_conn_status_result_timeout,
335 wpa_s, NULL);
336 } else {
337 dpp_auth_deinit(wpa_s->dpp_auth);
338 wpa_s->dpp_auth = NULL;
339 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700340 return;
341 }
342#endif /* CONFIG_DPP2 */
343
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700344 if (wpa_s->dpp_auth->remove_on_tx_status) {
345 wpa_printf(MSG_DEBUG,
Hai Shalomc3565922019-10-28 11:58:20 -0700346 "DPP: Terminate authentication exchange due to a request to do so on TX status");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700347 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700348 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700349 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
350 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700351 offchannel_send_action_done(wpa_s);
352 dpp_auth_deinit(wpa_s->dpp_auth);
353 wpa_s->dpp_auth = NULL;
354 return;
355 }
356
357 if (wpa_s->dpp_auth_ok_on_ack)
358 wpas_dpp_auth_success(wpa_s, 1);
359
360 if (!is_broadcast_ether_addr(dst) &&
361 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
362 wpa_printf(MSG_DEBUG,
363 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700364 if (auth->waiting_auth_resp) {
365 /* In case of DPP Authentication Request frame, move to
366 * the next channel immediately. */
367 offchannel_send_action_done(wpa_s);
368 wpas_dpp_auth_init_next(wpa_s);
369 return;
370 }
371 if (auth->waiting_auth_conf) {
372 wpas_dpp_auth_resp_retry(wpa_s);
373 return;
374 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700375 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700376
377 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
378 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
379 /* Allow timeout handling to stop iteration if no response is
380 * received from a peer that has ACKed a request. */
381 auth->auth_req_ack = 1;
382 }
383
384 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
385 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
386 wpa_printf(MSG_DEBUG,
387 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
388 wpa_s->dpp_auth->curr_freq,
389 wpa_s->dpp_auth->neg_freq);
390 offchannel_send_action_done(wpa_s);
391 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
392 }
393
394 if (wpa_s->dpp_auth_ok_on_ack)
395 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700396}
397
398
399static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
400{
401 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700402 struct dpp_authentication *auth = wpa_s->dpp_auth;
403 unsigned int freq;
404 struct os_reltime now, diff;
405 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700406
Roshan Pius3a1667e2018-07-03 15:17:14 -0700407 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700408 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700409
410 wait_time = wpa_s->dpp_resp_wait_time ?
411 wpa_s->dpp_resp_wait_time : 2000;
412 os_get_reltime(&now);
413 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
414 diff_ms = diff.sec * 1000 + diff.usec / 1000;
415 wpa_printf(MSG_DEBUG,
416 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
417 wait_time, diff_ms);
418
419 if (auth->auth_req_ack && diff_ms >= wait_time) {
420 /* Peer ACK'ed Authentication Request frame, but did not reply
421 * with Authentication Response frame within two seconds. */
422 wpa_printf(MSG_INFO,
423 "DPP: No response received from responder - stopping initiation attempt");
424 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800425 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700426 offchannel_send_action_done(wpa_s);
427 wpas_dpp_listen_stop(wpa_s);
428 dpp_auth_deinit(auth);
429 wpa_s->dpp_auth = NULL;
430 return;
431 }
432
433 if (diff_ms >= wait_time) {
434 /* Authentication Request frame was not ACK'ed and no reply
435 * was receiving within two seconds. */
436 wpa_printf(MSG_DEBUG,
437 "DPP: Continue Initiator channel iteration");
438 offchannel_send_action_done(wpa_s);
439 wpas_dpp_listen_stop(wpa_s);
440 wpas_dpp_auth_init_next(wpa_s);
441 return;
442 }
443
444 /* Driver did not support 2000 ms long wait_time with TX command, so
445 * schedule listen operation to continue waiting for the response.
446 *
447 * DPP listen operations continue until stopped, so simply schedule a
448 * new call to this function at the point when the two second reply
449 * wait has expired. */
450 wait_time -= diff_ms;
451
452 freq = auth->curr_freq;
453 if (auth->neg_freq > 0)
454 freq = auth->neg_freq;
455 wpa_printf(MSG_DEBUG,
456 "DPP: Continue reply wait on channel %u MHz for %u ms",
457 freq, wait_time);
458 wpa_s->dpp_in_response_listen = 1;
459 wpas_dpp_listen_start(wpa_s, freq);
460
461 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
462 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700463}
464
465
466static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
467 struct dpp_authentication *auth)
468{
469#ifdef CONFIG_TESTING_OPTIONS
470 if (wpa_s->dpp_config_obj_override)
471 auth->config_obj_override =
472 os_strdup(wpa_s->dpp_config_obj_override);
473 if (wpa_s->dpp_discovery_override)
474 auth->discovery_override =
475 os_strdup(wpa_s->dpp_discovery_override);
476 if (wpa_s->dpp_groups_override)
477 auth->groups_override =
478 os_strdup(wpa_s->dpp_groups_override);
479 auth->ignore_netaccesskey_mismatch =
480 wpa_s->dpp_ignore_netaccesskey_mismatch;
481#endif /* CONFIG_TESTING_OPTIONS */
482}
483
484
Roshan Pius3a1667e2018-07-03 15:17:14 -0700485static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
486{
487 struct wpa_supplicant *wpa_s = eloop_ctx;
488
489 if (!wpa_s->dpp_auth)
490 return;
491 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
492 wpas_dpp_auth_init_next(wpa_s);
493}
494
495
496static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
497{
498 struct dpp_authentication *auth = wpa_s->dpp_auth;
499 const u8 *dst;
500 unsigned int wait_time, max_wait_time, freq, max_tries, used;
501 struct os_reltime now, diff;
502
503 wpa_s->dpp_in_response_listen = 0;
504 if (!auth)
505 return -1;
506
507 if (auth->freq_idx == 0)
508 os_get_reltime(&wpa_s->dpp_init_iter_start);
509
510 if (auth->freq_idx >= auth->num_freq) {
511 auth->num_freq_iters++;
512 if (wpa_s->dpp_init_max_tries)
513 max_tries = wpa_s->dpp_init_max_tries;
514 else
515 max_tries = 5;
516 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
517 wpa_printf(MSG_INFO,
518 "DPP: No response received from responder - stopping initiation attempt");
519 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800520 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700521 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
522 wpa_s, NULL);
523 offchannel_send_action_done(wpa_s);
524 dpp_auth_deinit(wpa_s->dpp_auth);
525 wpa_s->dpp_auth = NULL;
526 return -1;
527 }
528 auth->freq_idx = 0;
529 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
530 if (wpa_s->dpp_init_retry_time)
531 wait_time = wpa_s->dpp_init_retry_time;
532 else
533 wait_time = 10000;
534 os_get_reltime(&now);
535 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
536 used = diff.sec * 1000 + diff.usec / 1000;
537 if (used > wait_time)
538 wait_time = 0;
539 else
540 wait_time -= used;
541 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
542 wait_time);
543 eloop_register_timeout(wait_time / 1000,
544 (wait_time % 1000) * 1000,
545 wpas_dpp_init_timeout, wpa_s,
546 NULL);
547 return 0;
548 }
549 freq = auth->freq[auth->freq_idx++];
550 auth->curr_freq = freq;
551
552 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
553 dst = broadcast;
554 else
555 dst = auth->peer_bi->mac_addr;
556 wpa_s->dpp_auth_ok_on_ack = 0;
557 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
558 wait_time = wpa_s->max_remain_on_chan;
559 max_wait_time = wpa_s->dpp_resp_wait_time ?
560 wpa_s->dpp_resp_wait_time : 2000;
561 if (wait_time > max_wait_time)
562 wait_time = max_wait_time;
563 wait_time += 10; /* give the driver some extra time to complete */
564 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
565 wpas_dpp_reply_wait_timeout,
566 wpa_s, NULL);
567 wait_time -= 10;
568 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
569 wpa_printf(MSG_DEBUG,
570 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
571 freq, auth->neg_freq);
572 }
573 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
574 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
575 auth->auth_req_ack = 0;
576 os_get_reltime(&wpa_s->dpp_last_init);
577 return offchannel_send_action(wpa_s, freq, dst,
578 wpa_s->own_addr, broadcast,
579 wpabuf_head(auth->req_msg),
580 wpabuf_len(auth->req_msg),
581 wait_time, wpas_dpp_tx_status, 0);
582}
583
584
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700585int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
586{
587 const char *pos;
588 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700589 struct dpp_authentication *auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700590 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
591 unsigned int neg_freq = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -0700592 int tcp = 0;
593#ifdef CONFIG_DPP2
594 int tcp_port = DPP_TCP_PORT;
595 struct hostapd_ip_addr ipaddr;
596 char *addr;
597#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700598
599 wpa_s->dpp_gas_client = 0;
600
601 pos = os_strstr(cmd, " peer=");
602 if (!pos)
603 return -1;
604 pos += 6;
Hai Shalom021b0b52019-04-10 11:17:58 -0700605 peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700606 if (!peer_bi) {
607 wpa_printf(MSG_INFO,
608 "DPP: Could not find bootstrapping info for the identified peer");
609 return -1;
610 }
611
Hai Shalom81f62d82019-07-22 12:10:00 -0700612#ifdef CONFIG_DPP2
613 pos = os_strstr(cmd, " tcp_port=");
614 if (pos) {
615 pos += 10;
616 tcp_port = atoi(pos);
617 }
618
619 addr = get_param(cmd, " tcp_addr=");
620 if (addr) {
621 int res;
622
623 res = hostapd_parse_ip_addr(addr, &ipaddr);
624 os_free(addr);
625 if (res)
626 return -1;
627 tcp = 1;
628 }
629#endif /* CONFIG_DPP2 */
630
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700631 pos = os_strstr(cmd, " own=");
632 if (pos) {
633 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -0700634 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700635 if (!own_bi) {
636 wpa_printf(MSG_INFO,
637 "DPP: Could not find bootstrapping info for the identified local entry");
638 return -1;
639 }
640
641 if (peer_bi->curve != own_bi->curve) {
642 wpa_printf(MSG_INFO,
643 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
644 peer_bi->curve->name, own_bi->curve->name);
645 return -1;
646 }
647 }
648
649 pos = os_strstr(cmd, " role=");
650 if (pos) {
651 pos += 6;
652 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700653 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700654 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700655 allowed_roles = DPP_CAPAB_ENROLLEE;
656 else if (os_strncmp(pos, "either", 6) == 0)
657 allowed_roles = DPP_CAPAB_CONFIGURATOR |
658 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700659 else
660 goto fail;
661 }
662
663 pos = os_strstr(cmd, " netrole=");
664 if (pos) {
665 pos += 9;
666 wpa_s->dpp_netrole_ap = os_strncmp(pos, "ap", 2) == 0;
667 }
668
Roshan Pius3a1667e2018-07-03 15:17:14 -0700669 pos = os_strstr(cmd, " neg_freq=");
670 if (pos)
671 neg_freq = atoi(pos + 10);
672
Hai Shalom81f62d82019-07-22 12:10:00 -0700673 if (!tcp && wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700674 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700675 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700676 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
677 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700678 offchannel_send_action_done(wpa_s);
679 dpp_auth_deinit(wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800680 wpa_s->dpp_auth = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -0700681 }
682
683 auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles, neg_freq,
684 wpa_s->hw.modes, wpa_s->hw.num_modes);
685 if (!auth)
686 goto fail;
687 wpas_dpp_set_testing_options(wpa_s, auth);
688 if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) < 0) {
689 dpp_auth_deinit(auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800690 goto fail;
691 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700692
Hai Shalom81f62d82019-07-22 12:10:00 -0700693 auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700694
Roshan Pius3a1667e2018-07-03 15:17:14 -0700695 if (!is_zero_ether_addr(peer_bi->mac_addr))
Hai Shalom81f62d82019-07-22 12:10:00 -0700696 os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700697
Hai Shalom81f62d82019-07-22 12:10:00 -0700698#ifdef CONFIG_DPP2
699 if (tcp)
700 return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port);
701#endif /* CONFIG_DPP2 */
702
703 wpa_s->dpp_auth = auth;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700704 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700705fail:
706 return -1;
707}
708
709
710struct wpas_dpp_listen_work {
711 unsigned int freq;
712 unsigned int duration;
713 struct wpabuf *probe_resp_ie;
714};
715
716
717static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
718{
719 if (!lwork)
720 return;
721 os_free(lwork);
722}
723
724
725static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
726{
727 struct wpas_dpp_listen_work *lwork;
728
729 if (!wpa_s->dpp_listen_work)
730 return;
731
732 lwork = wpa_s->dpp_listen_work->ctx;
733 wpas_dpp_listen_work_free(lwork);
734 radio_work_done(wpa_s->dpp_listen_work);
735 wpa_s->dpp_listen_work = NULL;
736}
737
738
739static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
740{
741 struct wpa_supplicant *wpa_s = work->wpa_s;
742 struct wpas_dpp_listen_work *lwork = work->ctx;
743
744 if (deinit) {
745 if (work->started) {
746 wpa_s->dpp_listen_work = NULL;
747 wpas_dpp_listen_stop(wpa_s);
748 }
749 wpas_dpp_listen_work_free(lwork);
750 return;
751 }
752
753 wpa_s->dpp_listen_work = work;
754
755 wpa_s->dpp_pending_listen_freq = lwork->freq;
756
757 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
758 wpa_s->max_remain_on_chan) < 0) {
759 wpa_printf(MSG_DEBUG,
760 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
761 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800762 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700763 wpas_dpp_listen_work_done(wpa_s);
764 wpa_s->dpp_pending_listen_freq = 0;
765 return;
766 }
767 wpa_s->off_channel_freq = 0;
768 wpa_s->roc_waiting_drv_freq = lwork->freq;
769}
770
771
772static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
773 unsigned int freq)
774{
775 struct wpas_dpp_listen_work *lwork;
776
777 if (wpa_s->dpp_listen_work) {
778 wpa_printf(MSG_DEBUG,
779 "DPP: Reject start_listen since dpp_listen_work already exists");
780 return -1;
781 }
782
783 if (wpa_s->dpp_listen_freq)
784 wpas_dpp_listen_stop(wpa_s);
785 wpa_s->dpp_listen_freq = freq;
786
787 lwork = os_zalloc(sizeof(*lwork));
788 if (!lwork)
789 return -1;
790 lwork->freq = freq;
791
792 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
793 lwork) < 0) {
794 wpas_dpp_listen_work_free(lwork);
795 return -1;
796 }
797
798 return 0;
799}
800
801
802int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
803{
804 int freq;
805
806 freq = atoi(cmd);
807 if (freq <= 0)
808 return -1;
809
810 if (os_strstr(cmd, " role=configurator"))
811 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
812 else if (os_strstr(cmd, " role=enrollee"))
813 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
814 else
815 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
816 DPP_CAPAB_ENROLLEE;
817 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
818 wpa_s->dpp_netrole_ap = os_strstr(cmd, " netrole=ap") != NULL;
819 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
820 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
821 freq);
822 return 0;
823 }
824
825 return wpas_dpp_listen_start(wpa_s, freq);
826}
827
828
829void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
830{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700831 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700832 if (!wpa_s->dpp_listen_freq)
833 return;
834
835 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
836 wpa_s->dpp_listen_freq);
837 wpa_drv_cancel_remain_on_channel(wpa_s);
838 wpa_s->dpp_listen_freq = 0;
839 wpas_dpp_listen_work_done(wpa_s);
840}
841
842
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700843void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
844 unsigned int freq)
845{
846 wpas_dpp_listen_work_done(wpa_s);
847
Roshan Pius3a1667e2018-07-03 15:17:14 -0700848 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
849 unsigned int new_freq;
850
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700851 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700852 if (wpa_s->dpp_auth->neg_freq > 0)
853 new_freq = wpa_s->dpp_auth->neg_freq;
854 else
855 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700856 wpa_printf(MSG_DEBUG,
857 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -0700858 new_freq);
859 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700860 return;
861 }
862
863 if (wpa_s->dpp_listen_freq) {
864 /* Continue listen with a new remain-on-channel */
865 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
866 }
867}
868
869
870static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
871 const u8 *hdr, const u8 *buf, size_t len,
872 unsigned int freq)
873{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700874 const u8 *r_bootstrap, *i_bootstrap;
875 u16 r_bootstrap_len, i_bootstrap_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700876 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
877
878 if (!wpa_s->dpp)
879 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700880
881 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
882 MAC2STR(src));
883
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700884 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
885 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700886 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
887 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
888 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700889 return;
890 }
891 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
892 r_bootstrap, r_bootstrap_len);
893
894 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
895 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700896 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
897 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
898 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700899 return;
900 }
901 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
902 i_bootstrap, i_bootstrap_len);
903
904 /* Try to find own and peer bootstrapping key matches based on the
905 * received hash values */
Hai Shalom021b0b52019-04-10 11:17:58 -0700906 dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap,
907 &own_bi, &peer_bi);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700908 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700909 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
910 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700911 return;
912 }
913
914 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700915 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
916 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700917 return;
918 }
919
920 wpa_s->dpp_gas_client = 0;
921 wpa_s->dpp_auth_ok_on_ack = 0;
922 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles,
923 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700924 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700925 if (!wpa_s->dpp_auth) {
926 wpa_printf(MSG_DEBUG, "DPP: No response generated");
927 return;
928 }
929 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalom021b0b52019-04-10 11:17:58 -0700930 if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth,
931 wpa_s->dpp_configurator_params) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800932 dpp_auth_deinit(wpa_s->dpp_auth);
933 wpa_s->dpp_auth = NULL;
934 return;
935 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700936 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
937
Roshan Pius3a1667e2018-07-03 15:17:14 -0700938 if (wpa_s->dpp_listen_freq &&
939 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
940 wpa_printf(MSG_DEBUG,
941 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
942 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
943 wpas_dpp_listen_stop(wpa_s);
944 }
945
946 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
947 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
948 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700949 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
950 src, wpa_s->own_addr, broadcast,
951 wpabuf_head(wpa_s->dpp_auth->resp_msg),
952 wpabuf_len(wpa_s->dpp_auth->resp_msg),
953 500, wpas_dpp_tx_status, 0);
954}
955
956
957static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
958{
959 /* TODO: stop wait and start ROC */
960}
961
962
963static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -0700964 struct dpp_authentication *auth,
965 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700966{
967 struct wpa_ssid *ssid;
968
Hai Shalom021b0b52019-04-10 11:17:58 -0700969#ifdef CONFIG_DPP2
Hai Shalomc3565922019-10-28 11:58:20 -0700970 if (conf->akm == DPP_AKM_SAE) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700971#ifdef CONFIG_SAE
972 struct wpa_driver_capa capa;
973 int res;
974
975 res = wpa_drv_get_capa(wpa_s, &capa);
976 if (res == 0 &&
977 !(capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
978 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
979 wpa_printf(MSG_DEBUG,
980 "DPP: SAE not supported by the driver");
981 return NULL;
982 }
983#else /* CONFIG_SAE */
984 wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
985 return NULL;
986#endif /* CONFIG_SAE */
987 }
988#endif /* CONFIG_DPP2 */
989
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700990 ssid = wpa_config_add_network(wpa_s->conf);
991 if (!ssid)
992 return NULL;
993 wpas_notify_network_added(wpa_s, ssid);
994 wpa_config_set_network_defaults(ssid);
995 ssid->disabled = 1;
996
Hai Shalomc3565922019-10-28 11:58:20 -0700997 ssid->ssid = os_malloc(conf->ssid_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700998 if (!ssid->ssid)
999 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001000 os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len);
1001 ssid->ssid_len = conf->ssid_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001002
Hai Shalomc3565922019-10-28 11:58:20 -07001003 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001004 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001005 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Hai Shalomc3565922019-10-28 11:58:20 -07001006 ssid->dpp_connector = os_strdup(conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001007 if (!ssid->dpp_connector)
1008 goto fail;
1009 }
1010
Hai Shalomc3565922019-10-28 11:58:20 -07001011 if (conf->c_sign_key) {
1012 ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001013 if (!ssid->dpp_csign)
1014 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -07001015 os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key),
1016 wpabuf_len(conf->c_sign_key));
1017 ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001018 }
1019
1020 if (auth->net_access_key) {
1021 ssid->dpp_netaccesskey =
1022 os_malloc(wpabuf_len(auth->net_access_key));
1023 if (!ssid->dpp_netaccesskey)
1024 goto fail;
1025 os_memcpy(ssid->dpp_netaccesskey,
1026 wpabuf_head(auth->net_access_key),
1027 wpabuf_len(auth->net_access_key));
1028 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1029 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1030 }
1031
Hai Shalomc3565922019-10-28 11:58:20 -07001032 if (!conf->connector || dpp_akm_psk(conf->akm) ||
1033 dpp_akm_sae(conf->akm)) {
1034 if (!conf->connector)
Hai Shalom021b0b52019-04-10 11:17:58 -07001035 ssid->key_mgmt = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07001036 if (dpp_akm_psk(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001037 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1038 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
Hai Shalomc3565922019-10-28 11:58:20 -07001039 if (dpp_akm_sae(conf->akm))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001040 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1041 WPA_KEY_MGMT_FT_SAE;
1042 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Hai Shalomc3565922019-10-28 11:58:20 -07001043 if (conf->passphrase[0]) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001044 if (wpa_config_set_quoted(ssid, "psk",
Hai Shalomc3565922019-10-28 11:58:20 -07001045 conf->passphrase) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001046 goto fail;
1047 wpa_config_update_psk(ssid);
1048 ssid->export_keys = 1;
1049 } else {
Hai Shalomc3565922019-10-28 11:58:20 -07001050 ssid->psk_set = conf->psk_set;
1051 os_memcpy(ssid->psk, conf->psk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001052 }
1053 }
1054
Hai Shalomc3565922019-10-28 11:58:20 -07001055 os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
1056 wpa_s->dpp_last_ssid_len = conf->ssid_len;
1057
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001058 return ssid;
1059fail:
1060 wpas_notify_network_removed(wpa_s, ssid);
1061 wpa_config_remove_network(wpa_s->conf, ssid->id);
1062 return NULL;
1063}
1064
1065
Hai Shalom021b0b52019-04-10 11:17:58 -07001066static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001067 struct dpp_authentication *auth,
1068 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001069{
1070 struct wpa_ssid *ssid;
1071
1072 if (wpa_s->conf->dpp_config_processing < 1)
Hai Shalom021b0b52019-04-10 11:17:58 -07001073 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001074
Hai Shalomc3565922019-10-28 11:58:20 -07001075 ssid = wpas_dpp_add_network(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001076 if (!ssid)
Hai Shalom021b0b52019-04-10 11:17:58 -07001077 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001078
1079 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001080
Hai Shalom706f99b2019-01-08 16:23:37 -08001081 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001082
Hai Shalom021b0b52019-04-10 11:17:58 -07001083 if (wpa_s->conf->dpp_config_processing == 2)
1084 ssid->disabled = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001085
Hai Shalom021b0b52019-04-10 11:17:58 -07001086#ifndef CONFIG_NO_CONFIG_WRITE
1087 if (wpa_s->conf->update_config &&
1088 wpa_config_write(wpa_s->confname, wpa_s->conf))
1089 wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration");
1090#endif /* CONFIG_NO_CONFIG_WRITE */
1091
Hai Shalomc3565922019-10-28 11:58:20 -07001092 return 0;
1093}
1094
1095
1096static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s,
1097 struct dpp_authentication *auth)
1098{
Hai Shalom021b0b52019-04-10 11:17:58 -07001099 if (wpa_s->conf->dpp_config_processing < 2)
Hai Shalomc3565922019-10-28 11:58:20 -07001100 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001101
1102#ifdef CONFIG_DPP2
1103 if (auth->peer_version >= 2) {
1104 wpa_printf(MSG_DEBUG,
1105 "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
1106 auth->connect_on_tx_status = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07001107 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07001108 }
1109#endif /* CONFIG_DPP2 */
1110
1111 wpas_dpp_try_to_connect(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001112}
1113
1114
Hai Shalom021b0b52019-04-10 11:17:58 -07001115static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
Hai Shalomc3565922019-10-28 11:58:20 -07001116 struct dpp_authentication *auth,
1117 struct dpp_config_obj *conf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001118{
1119 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Hai Shalomc3565922019-10-28 11:58:20 -07001120 if (conf->ssid_len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001121 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001122 wpa_ssid_txt(conf->ssid, conf->ssid_len));
1123 if (conf->connector) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001124 /* TODO: Save the Connector and consider using a command
1125 * to fetch the value instead of sending an event with
1126 * it. The Connector could end up being larger than what
1127 * most clients are ready to receive as an event
1128 * message. */
1129 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
Hai Shalomc3565922019-10-28 11:58:20 -07001130 conf->connector);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001131 }
Hai Shalomc3565922019-10-28 11:58:20 -07001132 if (conf->c_sign_key) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001133 char *hex;
1134 size_t hexlen;
1135
Hai Shalomc3565922019-10-28 11:58:20 -07001136 hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001137 hex = os_malloc(hexlen);
1138 if (hex) {
1139 wpa_snprintf_hex(hex, hexlen,
Hai Shalomc3565922019-10-28 11:58:20 -07001140 wpabuf_head(conf->c_sign_key),
1141 wpabuf_len(conf->c_sign_key));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001142 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1143 hex);
1144 os_free(hex);
1145 }
1146 }
1147 if (auth->net_access_key) {
1148 char *hex;
1149 size_t hexlen;
1150
1151 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1152 hex = os_malloc(hexlen);
1153 if (hex) {
1154 wpa_snprintf_hex(hex, hexlen,
1155 wpabuf_head(auth->net_access_key),
1156 wpabuf_len(auth->net_access_key));
1157 if (auth->net_access_key_expiry)
1158 wpa_msg(wpa_s, MSG_INFO,
1159 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1160 (long unsigned)
1161 auth->net_access_key_expiry);
1162 else
1163 wpa_msg(wpa_s, MSG_INFO,
1164 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1165 os_free(hex);
1166 }
1167 }
1168
Hai Shalomc3565922019-10-28 11:58:20 -07001169 return wpas_dpp_process_config(wpa_s, auth, conf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001170}
1171
1172
1173static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1174 enum gas_query_result result,
1175 const struct wpabuf *adv_proto,
1176 const struct wpabuf *resp, u16 status_code)
1177{
1178 struct wpa_supplicant *wpa_s = ctx;
1179 const u8 *pos;
1180 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001181 int res;
1182 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
Hai Shalomc3565922019-10-28 11:58:20 -07001183 unsigned int i;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001184
Roshan Pius3a1667e2018-07-03 15:17:14 -07001185 wpa_s->dpp_gas_dialog_token = -1;
1186
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001187 if (!auth || !auth->auth_success) {
1188 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1189 return;
1190 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001191 if (result != GAS_QUERY_SUCCESS ||
1192 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001193 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1194 goto fail;
1195 }
1196
1197 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1198 adv_proto);
1199 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1200 resp);
1201
1202 if (wpabuf_len(adv_proto) != 10 ||
1203 !(pos = wpabuf_head(adv_proto)) ||
1204 pos[0] != WLAN_EID_ADV_PROTO ||
1205 pos[1] != 8 ||
1206 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1207 pos[4] != 5 ||
1208 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1209 pos[8] != 0x1a ||
1210 pos[9] != 1) {
1211 wpa_printf(MSG_DEBUG,
1212 "DPP: Not a DPP Advertisement Protocol ID");
1213 goto fail;
1214 }
1215
1216 if (dpp_conf_resp_rx(auth, resp) < 0) {
1217 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1218 goto fail;
1219 }
1220
Hai Shalomc3565922019-10-28 11:58:20 -07001221 for (i = 0; i < auth->num_conf_obj; i++) {
1222 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1223 &auth->conf_obj[i]);
1224 if (res < 0)
1225 goto fail;
1226 }
1227 if (auth->num_conf_obj)
1228 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001229
Hai Shalom021b0b52019-04-10 11:17:58 -07001230 status = DPP_STATUS_OK;
1231#ifdef CONFIG_TESTING_OPTIONS
1232 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
1233 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
1234 status = DPP_STATUS_CONFIG_REJECTED;
1235 }
1236#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001237fail:
Hai Shalom021b0b52019-04-10 11:17:58 -07001238 if (status != DPP_STATUS_OK) {
1239 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1240 wpas_notify_dpp_configuration_failure(wpa_s);
1241 }
1242#ifdef CONFIG_DPP2
1243 if (auth->peer_version >= 2 &&
1244 auth->conf_resp_status == DPP_STATUS_OK) {
1245 struct wpabuf *msg;
1246
1247 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1248 msg = dpp_build_conf_result(auth, status);
1249 if (!msg)
1250 goto fail2;
1251
1252 wpa_msg(wpa_s, MSG_INFO,
1253 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1254 MAC2STR(addr), auth->curr_freq,
1255 DPP_PA_CONFIGURATION_RESULT);
1256 offchannel_send_action(wpa_s, auth->curr_freq,
1257 addr, wpa_s->own_addr, broadcast,
1258 wpabuf_head(msg),
1259 wpabuf_len(msg),
1260 500, wpas_dpp_tx_status, 0);
1261 wpabuf_free(msg);
1262
1263 /* This exchange will be terminated in the TX status handler */
1264 return;
1265 }
1266fail2:
1267#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001268 dpp_auth_deinit(wpa_s->dpp_auth);
1269 wpa_s->dpp_auth = NULL;
1270}
1271
1272
1273static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1274{
1275 struct dpp_authentication *auth = wpa_s->dpp_auth;
Hai Shalom021b0b52019-04-10 11:17:58 -07001276 struct wpabuf *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001277 int res;
Hai Shalomc3565922019-10-28 11:58:20 -07001278 int *supp_op_classes;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001279
1280 wpa_s->dpp_gas_client = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001281 offchannel_send_action_done(wpa_s);
1282 wpas_dpp_listen_stop(wpa_s);
1283
Hai Shalomc3565922019-10-28 11:58:20 -07001284 supp_op_classes = wpas_supp_op_classes(wpa_s);
1285 buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
1286 wpa_s->dpp_netrole_ap,
1287 wpa_s->conf->dpp_mud_url,
1288 supp_op_classes);
1289 os_free(supp_op_classes);
Hai Shalom021b0b52019-04-10 11:17:58 -07001290 if (!buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001291 wpa_printf(MSG_DEBUG,
1292 "DPP: No configuration request data available");
1293 return;
1294 }
1295
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001296 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1297 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1298
1299 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001300 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001301 if (res < 0) {
1302 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1303 wpabuf_free(buf);
1304 } else {
1305 wpa_printf(MSG_DEBUG,
1306 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001307 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001308 }
1309}
1310
1311
1312static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1313{
1314 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1315 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001316 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001317#ifdef CONFIG_TESTING_OPTIONS
1318 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1319 wpa_printf(MSG_INFO,
1320 "DPP: TESTING - stop at Authentication Confirm");
1321 if (wpa_s->dpp_auth->configurator) {
1322 /* Prevent GAS response */
1323 wpa_s->dpp_auth->auth_success = 0;
1324 }
1325 return;
1326 }
1327#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001328
1329 if (wpa_s->dpp_auth->configurator)
1330 wpas_dpp_start_gas_server(wpa_s);
1331 else
1332 wpas_dpp_start_gas_client(wpa_s);
1333}
1334
1335
1336static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001337 const u8 *hdr, const u8 *buf, size_t len,
1338 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001339{
1340 struct dpp_authentication *auth = wpa_s->dpp_auth;
1341 struct wpabuf *msg;
1342
Roshan Pius3a1667e2018-07-03 15:17:14 -07001343 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1344 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001345
1346 if (!auth) {
1347 wpa_printf(MSG_DEBUG,
1348 "DPP: No DPP Authentication in progress - drop");
1349 return;
1350 }
1351
1352 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1353 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1354 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1355 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1356 return;
1357 }
1358
1359 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1360
Roshan Pius3a1667e2018-07-03 15:17:14 -07001361 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1362 wpa_printf(MSG_DEBUG,
1363 "DPP: Responder accepted request for different negotiation channel");
1364 auth->curr_freq = freq;
1365 }
1366
1367 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001368 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1369 if (!msg) {
1370 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1371 wpa_printf(MSG_DEBUG,
1372 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001373 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001374 offchannel_send_action_done(wpa_s);
1375 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1376 return;
1377 }
1378 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1379 return;
1380 }
1381 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1382
Roshan Pius3a1667e2018-07-03 15:17:14 -07001383 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1384 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001385 offchannel_send_action(wpa_s, auth->curr_freq,
1386 src, wpa_s->own_addr, broadcast,
1387 wpabuf_head(msg), wpabuf_len(msg),
1388 500, wpas_dpp_tx_status, 0);
1389 wpabuf_free(msg);
1390 wpa_s->dpp_auth_ok_on_ack = 1;
1391}
1392
1393
1394static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1395 const u8 *hdr, const u8 *buf, size_t len)
1396{
1397 struct dpp_authentication *auth = wpa_s->dpp_auth;
1398
1399 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1400 MAC2STR(src));
1401
1402 if (!auth) {
1403 wpa_printf(MSG_DEBUG,
1404 "DPP: No DPP Authentication in progress - drop");
1405 return;
1406 }
1407
1408 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1409 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1410 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1411 return;
1412 }
1413
1414 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1415 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001416 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001417 return;
1418 }
1419
1420 wpas_dpp_auth_success(wpa_s, 0);
1421}
1422
1423
Hai Shalom021b0b52019-04-10 11:17:58 -07001424#ifdef CONFIG_DPP2
1425
1426static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
1427 void *timeout_ctx)
1428{
1429 struct wpa_supplicant *wpa_s = eloop_ctx;
1430 struct dpp_authentication *auth = wpa_s->dpp_auth;
1431
1432 if (!auth || !auth->waiting_conf_result)
1433 return;
1434
1435 wpa_printf(MSG_DEBUG,
1436 "DPP: Timeout while waiting for Configuration Result");
1437 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
1438 dpp_auth_deinit(auth);
1439 wpa_s->dpp_auth = NULL;
1440}
1441
1442
Hai Shalomc3565922019-10-28 11:58:20 -07001443static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1444 void *timeout_ctx)
1445{
1446 struct wpa_supplicant *wpa_s = eloop_ctx;
1447 struct dpp_authentication *auth = wpa_s->dpp_auth;
1448
1449 if (!auth || !auth->waiting_conn_status_result)
1450 return;
1451
1452 wpa_printf(MSG_DEBUG,
1453 "DPP: Timeout while waiting for Connection Status Result");
1454 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
1455 wpas_dpp_listen_stop(wpa_s);
1456 dpp_auth_deinit(auth);
1457 wpa_s->dpp_auth = NULL;
1458}
1459
1460
Hai Shalom021b0b52019-04-10 11:17:58 -07001461static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
1462 const u8 *hdr, const u8 *buf, size_t len)
1463{
1464 struct dpp_authentication *auth = wpa_s->dpp_auth;
1465 enum dpp_status_error status;
1466
1467 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1468 MAC2STR(src));
1469
1470 if (!auth || !auth->waiting_conf_result) {
1471 wpa_printf(MSG_DEBUG,
1472 "DPP: No DPP Configuration waiting for result - drop");
1473 return;
1474 }
1475
1476 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1477 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1478 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1479 return;
1480 }
1481
1482 status = dpp_conf_result_rx(auth, hdr, buf, len);
1483
Hai Shalomc3565922019-10-28 11:58:20 -07001484 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1485 wpa_msg(wpa_s, MSG_INFO,
1486 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1487 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
1488 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
1489 wpa_s, NULL);
1490 auth->waiting_conn_status_result = 1;
1491 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1492 wpa_s, NULL);
1493 eloop_register_timeout(16, 0,
1494 wpas_dpp_conn_status_result_wait_timeout,
1495 wpa_s, NULL);
1496 offchannel_send_action_done(wpa_s);
1497 wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq :
1498 auth->curr_freq);
1499 return;
1500 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001501 offchannel_send_action_done(wpa_s);
1502 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001503 if (status == DPP_STATUS_OK) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001504 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalome4073332019-11-05 16:20:12 -08001505 wpas_notify_dpp_config_sent(wpa_s);
1506 }
1507 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07001508 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalome4073332019-11-05 16:20:12 -08001509 wpas_notify_dpp_configuration_failure(wpa_s);
1510 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001511 dpp_auth_deinit(auth);
1512 wpa_s->dpp_auth = NULL;
1513 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
1514}
1515
Hai Shalom81f62d82019-07-22 12:10:00 -07001516
Hai Shalomc3565922019-10-28 11:58:20 -07001517static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
1518 const u8 *src, const u8 *hdr,
1519 const u8 *buf, size_t len)
1520{
1521 struct dpp_authentication *auth = wpa_s->dpp_auth;
1522 enum dpp_status_error status;
1523 u8 ssid[SSID_MAX_LEN];
1524 size_t ssid_len = 0;
1525 char *channel_list = NULL;
1526
1527 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1528
1529 if (!auth || !auth->waiting_conn_status_result) {
1530 wpa_printf(MSG_DEBUG,
1531 "DPP: No DPP Configuration waiting for connection status result - drop");
1532 return;
1533 }
1534
1535 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1536 ssid, &ssid_len, &channel_list);
1537 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1538 "result=%d ssid=%s channel_list=%s",
1539 status, wpa_ssid_txt(ssid, ssid_len),
1540 channel_list ? channel_list : "N/A");
1541 os_free(channel_list);
1542 offchannel_send_action_done(wpa_s);
1543 wpas_dpp_listen_stop(wpa_s);
1544 dpp_auth_deinit(auth);
1545 wpa_s->dpp_auth = NULL;
1546 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1547 wpa_s, NULL);
1548}
1549
1550
Hai Shalom81f62d82019-07-22 12:10:00 -07001551static int wpas_dpp_process_conf_obj(void *ctx,
1552 struct dpp_authentication *auth)
1553{
1554 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07001555 unsigned int i;
1556 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001557
Hai Shalomc3565922019-10-28 11:58:20 -07001558 for (i = 0; i < auth->num_conf_obj; i++) {
1559 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1560 &auth->conf_obj[i]);
1561 if (res)
1562 break;
1563 }
1564 if (!res)
1565 wpas_dpp_post_process_config(wpa_s, auth);
1566
1567 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07001568}
1569
Hai Shalom021b0b52019-04-10 11:17:58 -07001570#endif /* CONFIG_DPP2 */
1571
1572
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001573static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
1574 const u8 *src,
1575 const u8 *buf, size_t len)
1576{
1577 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001578 const u8 *connector, *trans_id, *status;
1579 u16 connector_len, trans_id_len, status_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001580 struct dpp_introduction intro;
1581 struct rsn_pmksa_cache_entry *entry;
1582 struct os_time now;
1583 struct os_reltime rnow;
1584 os_time_t expiry;
1585 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001586 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001587
1588 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
1589 MAC2STR(src));
1590 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
1591 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
1592 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
1593 MACSTR " - drop", MAC2STR(src));
1594 return;
1595 }
1596 offchannel_send_action_done(wpa_s);
1597
1598 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1599 if (ssid == wpa_s->dpp_intro_network)
1600 break;
1601 }
1602 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
1603 !ssid->dpp_csign) {
1604 wpa_printf(MSG_DEBUG,
1605 "DPP: Profile not found for network introduction");
1606 return;
1607 }
1608
1609 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1610 &trans_id_len);
1611 if (!trans_id || trans_id_len != 1) {
1612 wpa_printf(MSG_DEBUG,
1613 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001614 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1615 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001616 goto fail;
1617 }
1618 if (trans_id[0] != TRANSACTION_ID) {
1619 wpa_printf(MSG_DEBUG,
1620 "DPP: Ignore frame with unexpected Transaction ID %u",
1621 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001622 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1623 " fail=transaction_id_mismatch", MAC2STR(src));
1624 goto fail;
1625 }
1626
1627 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
1628 if (!status || status_len != 1) {
1629 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
1630 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1631 " fail=missing_status", MAC2STR(src));
1632 goto fail;
1633 }
1634 if (status[0] != DPP_STATUS_OK) {
1635 wpa_printf(MSG_DEBUG,
1636 "DPP: Peer rejected network introduction: Status %u",
1637 status[0]);
1638 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1639 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07001640#ifdef CONFIG_DPP2
1641 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
1642#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001643 goto fail;
1644 }
1645
1646 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1647 if (!connector) {
1648 wpa_printf(MSG_DEBUG,
1649 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001650 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1651 " fail=missing_connector", MAC2STR(src));
1652 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001653 }
1654
Roshan Pius3a1667e2018-07-03 15:17:14 -07001655 res = dpp_peer_intro(&intro, ssid->dpp_connector,
1656 ssid->dpp_netaccesskey,
1657 ssid->dpp_netaccesskey_len,
1658 ssid->dpp_csign,
1659 ssid->dpp_csign_len,
1660 connector, connector_len, &expiry);
1661 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001662 wpa_printf(MSG_INFO,
1663 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001664 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1665 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07001666#ifdef CONFIG_DPP2
1667 wpas_dpp_send_conn_status_result(wpa_s, res);
1668#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001669 goto fail;
1670 }
1671
1672 entry = os_zalloc(sizeof(*entry));
1673 if (!entry)
1674 goto fail;
1675 os_memcpy(entry->aa, src, ETH_ALEN);
1676 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
1677 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
1678 entry->pmk_len = intro.pmk_len;
1679 entry->akmp = WPA_KEY_MGMT_DPP;
1680 if (expiry) {
1681 os_get_time(&now);
1682 seconds = expiry - now.sec;
1683 } else {
1684 seconds = 86400 * 7;
1685 }
1686 os_get_reltime(&rnow);
1687 entry->expiration = rnow.sec + seconds;
1688 entry->reauth_time = rnow.sec + seconds;
1689 entry->network_ctx = ssid;
1690 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
1691
Roshan Pius3a1667e2018-07-03 15:17:14 -07001692 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1693 " status=%u", MAC2STR(src), status[0]);
1694
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001695 wpa_printf(MSG_DEBUG,
1696 "DPP: Try connection again after successful network introduction");
1697 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
1698 wpa_supplicant_cancel_sched_scan(wpa_s);
1699 wpa_supplicant_req_scan(wpa_s, 0, 0);
1700 }
1701fail:
1702 os_memset(&intro, 0, sizeof(intro));
1703}
1704
1705
Roshan Pius3a1667e2018-07-03 15:17:14 -07001706static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
1707{
1708 int i, j;
1709
1710 if (!wpa_s->hw.modes)
1711 return -1;
1712
1713 for (i = 0; i < wpa_s->hw.num_modes; i++) {
1714 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
1715
1716 for (j = 0; j < mode->num_channels; j++) {
1717 struct hostapd_channel_data *chan = &mode->channels[j];
1718
1719 if (chan->freq != (int) freq)
1720 continue;
1721
1722 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
1723 HOSTAPD_CHAN_NO_IR |
1724 HOSTAPD_CHAN_RADAR))
1725 continue;
1726
1727 return 1;
1728 }
1729 }
1730
1731 wpa_printf(MSG_DEBUG,
1732 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
1733 freq);
1734
1735 return 0;
1736}
1737
1738
1739static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
1740 struct dpp_pkex *pkex)
1741{
1742 if (pkex->freq == 2437)
1743 pkex->freq = 5745;
1744 else if (pkex->freq == 5745)
1745 pkex->freq = 5220;
1746 else if (pkex->freq == 5220)
1747 pkex->freq = 60480;
1748 else
1749 return -1; /* no more channels to try */
1750
1751 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
1752 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
1753 pkex->freq);
1754 return 0;
1755 }
1756
1757 /* Could not use this channel - try the next one */
1758 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
1759}
1760
1761
1762static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
1763{
1764 struct wpa_supplicant *wpa_s = eloop_ctx;
1765 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1766
1767 if (!pkex || !pkex->exchange_req)
1768 return;
1769 if (pkex->exch_req_tries >= 5) {
1770 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
1771 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1772 "No response from PKEX peer");
1773 dpp_pkex_free(pkex);
1774 wpa_s->dpp_pkex = NULL;
1775 return;
1776 }
1777 pkex->exch_req_tries = 0;
1778 }
1779
1780 pkex->exch_req_tries++;
1781 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
1782 pkex->exch_req_tries);
1783 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1784 MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
1785 offchannel_send_action(wpa_s, pkex->freq, broadcast,
1786 wpa_s->own_addr, broadcast,
1787 wpabuf_head(pkex->exchange_req),
1788 wpabuf_len(pkex->exchange_req),
1789 pkex->exch_req_wait_time,
1790 wpas_dpp_tx_pkex_status, 0);
1791}
1792
1793
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001794static void
1795wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
1796 unsigned int freq, const u8 *dst,
1797 const u8 *src, const u8 *bssid,
1798 const u8 *data, size_t data_len,
1799 enum offchannel_send_action_result result)
1800{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001801 const char *res_txt;
1802 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1803
1804 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
1805 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
1806 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001807 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
1808 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001809 freq, MAC2STR(dst), res_txt);
1810 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
1811 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
1812
1813 if (!pkex) {
1814 wpa_printf(MSG_DEBUG,
1815 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
1816 return;
1817 }
1818
1819 if (pkex->failed) {
1820 wpa_printf(MSG_DEBUG,
1821 "DPP: Terminate PKEX exchange due to an earlier error");
1822 if (pkex->t > pkex->own_bi->pkex_t)
1823 pkex->own_bi->pkex_t = pkex->t;
1824 dpp_pkex_free(pkex);
1825 wpa_s->dpp_pkex = NULL;
1826 return;
1827 }
1828
1829 if (pkex->exch_req_wait_time && pkex->exchange_req) {
1830 /* Wait for PKEX Exchange Response frame and retry request if
1831 * no response is seen. */
1832 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1833 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
1834 (pkex->exch_req_wait_time % 1000) * 1000,
1835 wpas_dpp_pkex_retry_timeout, wpa_s,
1836 NULL);
1837 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001838}
1839
1840
1841static void
1842wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
1843 const u8 *buf, size_t len, unsigned int freq)
1844{
1845 struct wpabuf *msg;
1846 unsigned int wait_time;
1847
1848 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1849 MAC2STR(src));
1850
1851 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1852 * values here */
1853
1854 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
1855 wpa_printf(MSG_DEBUG,
1856 "DPP: No PKEX code configured - ignore request");
1857 return;
1858 }
1859
1860 if (wpa_s->dpp_pkex) {
1861 /* TODO: Support parallel operations */
1862 wpa_printf(MSG_DEBUG,
1863 "DPP: Already in PKEX session - ignore new request");
1864 return;
1865 }
1866
Roshan Pius3a1667e2018-07-03 15:17:14 -07001867 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001868 wpa_s->own_addr, src,
1869 wpa_s->dpp_pkex_identifier,
1870 wpa_s->dpp_pkex_code,
1871 buf, len);
1872 if (!wpa_s->dpp_pkex) {
1873 wpa_printf(MSG_DEBUG,
1874 "DPP: Failed to process the request - ignore it");
1875 return;
1876 }
1877
1878 msg = wpa_s->dpp_pkex->exchange_resp;
1879 wait_time = wpa_s->max_remain_on_chan;
1880 if (wait_time > 2000)
1881 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001882 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1883 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001884 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1885 broadcast,
1886 wpabuf_head(msg), wpabuf_len(msg),
1887 wait_time, wpas_dpp_tx_pkex_status, 0);
1888}
1889
1890
1891static void
1892wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
1893 const u8 *buf, size_t len, unsigned int freq)
1894{
1895 struct wpabuf *msg;
1896 unsigned int wait_time;
1897
1898 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1899 MAC2STR(src));
1900
1901 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1902 * values here */
1903
1904 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
1905 wpa_s->dpp_pkex->exchange_done) {
1906 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1907 return;
1908 }
1909
Roshan Pius3a1667e2018-07-03 15:17:14 -07001910 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1911 wpa_s->dpp_pkex->exch_req_wait_time = 0;
1912
1913 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001914 if (!msg) {
1915 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1916 return;
1917 }
1918
1919 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1920 MAC2STR(src));
1921
1922 wait_time = wpa_s->max_remain_on_chan;
1923 if (wait_time > 2000)
1924 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001925 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1926 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001927 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1928 broadcast,
1929 wpabuf_head(msg), wpabuf_len(msg),
1930 wait_time, wpas_dpp_tx_pkex_status, 0);
1931 wpabuf_free(msg);
1932}
1933
1934
Roshan Pius3a1667e2018-07-03 15:17:14 -07001935static struct dpp_bootstrap_info *
1936wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
1937 unsigned int freq)
1938{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001939 struct dpp_bootstrap_info *bi;
1940
Hai Shalom021b0b52019-04-10 11:17:58 -07001941 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001942 if (!bi)
1943 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001944 wpa_s->dpp_pkex = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001945 return bi;
1946}
1947
1948
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001949static void
1950wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
1951 const u8 *hdr, const u8 *buf, size_t len,
1952 unsigned int freq)
1953{
1954 struct wpabuf *msg;
1955 unsigned int wait_time;
1956 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001957
1958 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1959 MAC2STR(src));
1960
1961 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1962 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1963 return;
1964 }
1965
1966 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1967 if (!msg) {
1968 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001969 if (pkex->failed) {
1970 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1971 if (pkex->t > pkex->own_bi->pkex_t)
1972 pkex->own_bi->pkex_t = pkex->t;
1973 dpp_pkex_free(wpa_s->dpp_pkex);
1974 wpa_s->dpp_pkex = NULL;
1975 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001976 return;
1977 }
1978
1979 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1980 MACSTR, MAC2STR(src));
1981
1982 wait_time = wpa_s->max_remain_on_chan;
1983 if (wait_time > 2000)
1984 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001985 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1986 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001987 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1988 broadcast,
1989 wpabuf_head(msg), wpabuf_len(msg),
1990 wait_time, wpas_dpp_tx_pkex_status, 0);
1991 wpabuf_free(msg);
1992
Roshan Pius3a1667e2018-07-03 15:17:14 -07001993 wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001994}
1995
1996
1997static void
1998wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
1999 const u8 *hdr, const u8 *buf, size_t len,
2000 unsigned int freq)
2001{
2002 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002003 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002004 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2005 char cmd[500];
2006
2007 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2008 MAC2STR(src));
2009
2010 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2011 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2012 return;
2013 }
2014
2015 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2016 if (res < 0) {
2017 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2018 return;
2019 }
2020
Roshan Pius3a1667e2018-07-03 15:17:14 -07002021 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002022 if (!bi)
2023 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002024
2025 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2026 bi->id,
2027 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
2028 wpa_printf(MSG_DEBUG,
2029 "DPP: Start authentication after PKEX with parameters: %s",
2030 cmd);
2031 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
2032 wpa_printf(MSG_DEBUG,
2033 "DPP: Authentication initialization failed");
2034 return;
2035 }
2036}
2037
2038
2039void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
2040 const u8 *buf, size_t len, unsigned int freq)
2041{
2042 u8 crypto_suite;
2043 enum dpp_public_action_frame_type type;
2044 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002045 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002046
2047 if (len < DPP_HDR_LEN)
2048 return;
2049 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2050 return;
2051 hdr = buf;
2052 buf += 4;
2053 len -= 4;
2054 crypto_suite = *buf++;
2055 type = *buf++;
2056 len -= 2;
2057
2058 wpa_printf(MSG_DEBUG,
2059 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2060 MACSTR " freq=%u",
2061 crypto_suite, type, MAC2STR(src), freq);
2062 if (crypto_suite != 1) {
2063 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2064 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002065 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2066 " freq=%u type=%d ignore=unsupported-crypto-suite",
2067 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002068 return;
2069 }
2070 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002071 if (dpp_check_attrs(buf, len) < 0) {
2072 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2073 " freq=%u type=%d ignore=invalid-attributes",
2074 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002075 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002076 }
2077 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
2078 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002079
2080 switch (type) {
2081 case DPP_PA_AUTHENTICATION_REQ:
2082 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
2083 break;
2084 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002085 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002086 break;
2087 case DPP_PA_AUTHENTICATION_CONF:
2088 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
2089 break;
2090 case DPP_PA_PEER_DISCOVERY_RESP:
2091 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
2092 break;
2093 case DPP_PA_PKEX_EXCHANGE_REQ:
2094 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
2095 break;
2096 case DPP_PA_PKEX_EXCHANGE_RESP:
2097 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
2098 break;
2099 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2100 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
2101 freq);
2102 break;
2103 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2104 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
2105 freq);
2106 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002107#ifdef CONFIG_DPP2
2108 case DPP_PA_CONFIGURATION_RESULT:
2109 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
2110 break;
Hai Shalomc3565922019-10-28 11:58:20 -07002111 case DPP_PA_CONNECTION_STATUS_RESULT:
2112 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
2113 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002114#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002115 default:
2116 wpa_printf(MSG_DEBUG,
2117 "DPP: Ignored unsupported frame subtype %d", type);
2118 break;
2119 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002120
2121 if (wpa_s->dpp_pkex)
2122 pkex_t = wpa_s->dpp_pkex->t;
2123 else if (wpa_s->dpp_pkex_bi)
2124 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
2125 else
2126 pkex_t = 0;
2127 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2128 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2129 wpas_dpp_pkex_remove(wpa_s, "*");
2130 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002131}
2132
2133
2134static struct wpabuf *
2135wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query,
2136 size_t query_len)
2137{
2138 struct wpa_supplicant *wpa_s = ctx;
2139 struct dpp_authentication *auth = wpa_s->dpp_auth;
2140 struct wpabuf *resp;
2141
2142 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
2143 MAC2STR(sa));
2144 if (!auth || !auth->auth_success ||
2145 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
2146 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2147 return NULL;
2148 }
Hai Shalomc3565922019-10-28 11:58:20 -07002149
2150 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
2151 wpa_printf(MSG_DEBUG,
2152 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
2153 /* wpas_dpp_auth_success() would normally have been called from
2154 * TX status handler, but since there was no such handler call
2155 * yet, simply send out the event message and proceed with
2156 * exchange. */
2157 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
2158 wpa_s->dpp_auth_ok_on_ack = 0;
2159 }
2160
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002161 wpa_hexdump(MSG_DEBUG,
2162 "DPP: Received Configuration Request (GAS Query Request)",
2163 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002164 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2165 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002166 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom59532852018-12-07 10:32:58 -08002167 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002168 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002169 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002170 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002171 auth->conf_resp = resp;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002172 return resp;
2173}
2174
2175
2176static void
2177wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
2178{
2179 struct wpa_supplicant *wpa_s = ctx;
2180 struct dpp_authentication *auth = wpa_s->dpp_auth;
2181
2182 if (!auth) {
2183 wpabuf_free(resp);
2184 return;
2185 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002186 if (auth->conf_resp != resp) {
2187 wpa_printf(MSG_DEBUG,
2188 "DPP: Ignore GAS status report (ok=%d) for unknown response",
2189 ok);
2190 wpabuf_free(resp);
2191 return;
2192 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002193
2194 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2195 ok);
2196 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002197 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002198#ifdef CONFIG_DPP2
2199 if (ok && auth->peer_version >= 2 &&
2200 auth->conf_resp_status == DPP_STATUS_OK) {
2201 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
2202 auth->waiting_conf_result = 1;
2203 auth->conf_resp = NULL;
2204 wpabuf_free(resp);
2205 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2206 wpa_s, NULL);
2207 eloop_register_timeout(2, 0,
2208 wpas_dpp_config_result_wait_timeout,
2209 wpa_s, NULL);
2210 return;
2211 }
2212#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002213 offchannel_send_action_done(wpa_s);
2214 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002215 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002216 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08002217 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002218 }
2219 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002220 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002221 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002222 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002223 dpp_auth_deinit(wpa_s->dpp_auth);
2224 wpa_s->dpp_auth = NULL;
2225 wpabuf_free(resp);
2226}
2227
2228
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002229int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
2230{
2231 struct dpp_authentication *auth;
2232 int ret = -1;
2233 char *curve = NULL;
2234
2235 auth = os_zalloc(sizeof(*auth));
2236 if (!auth)
2237 return -1;
2238
2239 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08002240 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalom021b0b52019-04-10 11:17:58 -07002241 if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 &&
2242 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002243 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
2244 &auth->conf_obj[0]);
2245 if (!ret)
2246 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002247
2248 dpp_auth_deinit(auth);
2249 os_free(curve);
2250
2251 return ret;
2252}
2253
2254
2255static void
2256wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
2257 unsigned int freq, const u8 *dst,
2258 const u8 *src, const u8 *bssid,
2259 const u8 *data, size_t data_len,
2260 enum offchannel_send_action_result result)
2261{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002262 const char *res_txt;
2263
2264 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2265 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2266 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002267 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2268 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002269 freq, MAC2STR(dst), res_txt);
2270 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2271 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002272 /* TODO: Time out wait for response more quickly in error cases? */
2273}
2274
2275
2276int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2277 struct wpa_bss *bss)
2278{
2279 struct os_time now;
2280 struct wpabuf *msg;
2281 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07002282 const u8 *rsn;
2283 struct wpa_ie_data ied;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002284
2285 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
2286 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07002287 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2288 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
2289 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
2290 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002291 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
2292 return 0; /* PMKSA exists for DPP AKM - continue */
2293
2294 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2295 !ssid->dpp_csign) {
2296 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2297 "missing %s",
2298 !ssid->dpp_connector ? "Connector" :
2299 (!ssid->dpp_netaccesskey ? "netAccessKey" :
2300 "C-sign-key"));
2301 return -1;
2302 }
2303
2304 os_get_time(&now);
2305
2306 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002307 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002308 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2309 "netAccessKey expired");
2310 return -1;
2311 }
2312
2313 wpa_printf(MSG_DEBUG,
2314 "DPP: Starting network introduction protocol to derive PMKSA for "
2315 MACSTR, MAC2STR(bss->bssid));
2316
2317 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ,
2318 5 + 4 + os_strlen(ssid->dpp_connector));
2319 if (!msg)
2320 return -1;
2321
Roshan Pius3a1667e2018-07-03 15:17:14 -07002322#ifdef CONFIG_TESTING_OPTIONS
2323 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
2324 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
2325 goto skip_trans_id;
2326 }
2327 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
2328 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
2329 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2330 wpabuf_put_le16(msg, 0);
2331 goto skip_trans_id;
2332 }
2333#endif /* CONFIG_TESTING_OPTIONS */
2334
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002335 /* Transaction ID */
2336 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2337 wpabuf_put_le16(msg, 1);
2338 wpabuf_put_u8(msg, TRANSACTION_ID);
2339
Roshan Pius3a1667e2018-07-03 15:17:14 -07002340#ifdef CONFIG_TESTING_OPTIONS
2341skip_trans_id:
2342 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
2343 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
2344 goto skip_connector;
2345 }
2346 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
2347 char *connector;
2348
2349 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
2350 connector = dpp_corrupt_connector_signature(
2351 ssid->dpp_connector);
2352 if (!connector) {
2353 wpabuf_free(msg);
2354 return -1;
2355 }
2356 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2357 wpabuf_put_le16(msg, os_strlen(connector));
2358 wpabuf_put_str(msg, connector);
2359 os_free(connector);
2360 goto skip_connector;
2361 }
2362#endif /* CONFIG_TESTING_OPTIONS */
2363
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002364 /* DPP Connector */
2365 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2366 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
2367 wpabuf_put_str(msg, ssid->dpp_connector);
2368
Roshan Pius3a1667e2018-07-03 15:17:14 -07002369#ifdef CONFIG_TESTING_OPTIONS
2370skip_connector:
2371#endif /* CONFIG_TESTING_OPTIONS */
2372
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002373 /* TODO: Timeout on AP response */
2374 wait_time = wpa_s->max_remain_on_chan;
2375 if (wait_time > 2000)
2376 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002377 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2378 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002379 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
2380 broadcast,
2381 wpabuf_head(msg), wpabuf_len(msg),
2382 wait_time, wpas_dpp_tx_introduction_status, 0);
2383 wpabuf_free(msg);
2384
2385 /* Request this connection attempt to terminate - new one will be
2386 * started when network introduction protocol completes */
2387 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
2388 wpa_s->dpp_intro_network = ssid;
2389 return 1;
2390}
2391
2392
2393int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
2394{
2395 struct dpp_bootstrap_info *own_bi;
2396 const char *pos, *end;
2397 unsigned int wait_time;
2398
2399 pos = os_strstr(cmd, " own=");
2400 if (!pos)
2401 return -1;
2402 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07002403 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002404 if (!own_bi) {
2405 wpa_printf(MSG_DEBUG,
2406 "DPP: Identified bootstrap info not found");
2407 return -1;
2408 }
2409 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2410 wpa_printf(MSG_DEBUG,
2411 "DPP: Identified bootstrap info not for PKEX");
2412 return -1;
2413 }
2414 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002415 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002416
2417 os_free(wpa_s->dpp_pkex_identifier);
2418 wpa_s->dpp_pkex_identifier = NULL;
2419 pos = os_strstr(cmd, " identifier=");
2420 if (pos) {
2421 pos += 12;
2422 end = os_strchr(pos, ' ');
2423 if (!end)
2424 return -1;
2425 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
2426 if (!wpa_s->dpp_pkex_identifier)
2427 return -1;
2428 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
2429 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
2430 }
2431
2432 pos = os_strstr(cmd, " code=");
2433 if (!pos)
2434 return -1;
2435 os_free(wpa_s->dpp_pkex_code);
2436 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
2437 if (!wpa_s->dpp_pkex_code)
2438 return -1;
2439
2440 if (os_strstr(cmd, " init=1")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002441 struct dpp_pkex *pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002442 struct wpabuf *msg;
2443
2444 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
2445 dpp_pkex_free(wpa_s->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002446 wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002447 wpa_s->dpp_pkex_identifier,
2448 wpa_s->dpp_pkex_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002449 pkex = wpa_s->dpp_pkex;
2450 if (!pkex)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002451 return -1;
2452
Roshan Pius3a1667e2018-07-03 15:17:14 -07002453 msg = pkex->exchange_req;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002454 wait_time = wpa_s->max_remain_on_chan;
2455 if (wait_time > 2000)
2456 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002457 pkex->freq = 2437;
2458 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2459 " freq=%u type=%d",
2460 MAC2STR(broadcast), pkex->freq,
2461 DPP_PA_PKEX_EXCHANGE_REQ);
2462 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2463 wpa_s->own_addr, broadcast,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002464 wpabuf_head(msg), wpabuf_len(msg),
2465 wait_time, wpas_dpp_tx_pkex_status, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002466 if (wait_time == 0)
2467 wait_time = 2000;
2468 pkex->exch_req_wait_time = wait_time;
2469 pkex->exch_req_tries = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002470 }
2471
2472 /* TODO: Support multiple PKEX info entries */
2473
2474 os_free(wpa_s->dpp_pkex_auth_cmd);
2475 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
2476
2477 return 1;
2478}
2479
2480
2481int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
2482{
2483 unsigned int id_val;
2484
2485 if (os_strcmp(id, "*") == 0) {
2486 id_val = 0;
2487 } else {
2488 id_val = atoi(id);
2489 if (id_val == 0)
2490 return -1;
2491 }
2492
2493 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
2494 return -1;
2495
2496 /* TODO: Support multiple PKEX entries */
2497 os_free(wpa_s->dpp_pkex_code);
2498 wpa_s->dpp_pkex_code = NULL;
2499 os_free(wpa_s->dpp_pkex_identifier);
2500 wpa_s->dpp_pkex_identifier = NULL;
2501 os_free(wpa_s->dpp_pkex_auth_cmd);
2502 wpa_s->dpp_pkex_auth_cmd = NULL;
2503 wpa_s->dpp_pkex_bi = NULL;
2504 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2505 dpp_pkex_free(wpa_s->dpp_pkex);
2506 wpa_s->dpp_pkex = NULL;
2507 return 0;
2508}
2509
2510
Roshan Pius3a1667e2018-07-03 15:17:14 -07002511void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
2512{
2513 dpp_auth_deinit(wpa_s->dpp_auth);
2514 wpa_s->dpp_auth = NULL;
2515 dpp_pkex_free(wpa_s->dpp_pkex);
2516 wpa_s->dpp_pkex = NULL;
2517 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
2518 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
2519}
2520
2521
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002522int wpas_dpp_init(struct wpa_supplicant *wpa_s)
2523{
Hai Shalom81f62d82019-07-22 12:10:00 -07002524 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002525 u8 adv_proto_id[7];
2526
2527 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
2528 adv_proto_id[1] = 5;
2529 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
2530 adv_proto_id[5] = DPP_OUI_TYPE;
2531 adv_proto_id[6] = 0x01;
2532
2533 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
2534 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
2535 wpas_dpp_gas_status_handler, wpa_s) < 0)
2536 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002537
2538 os_memset(&config, 0, sizeof(config));
2539 config.msg_ctx = wpa_s;
2540 config.cb_ctx = wpa_s;
2541#ifdef CONFIG_DPP2
2542 config.process_conf_obj = wpas_dpp_process_conf_obj;
2543#endif /* CONFIG_DPP2 */
2544 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07002545 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002546}
2547
2548
2549void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
2550{
2551#ifdef CONFIG_TESTING_OPTIONS
2552 os_free(wpa_s->dpp_config_obj_override);
2553 wpa_s->dpp_config_obj_override = NULL;
2554 os_free(wpa_s->dpp_discovery_override);
2555 wpa_s->dpp_discovery_override = NULL;
2556 os_free(wpa_s->dpp_groups_override);
2557 wpa_s->dpp_groups_override = NULL;
2558 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
2559#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07002560 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002561 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07002562 dpp_global_clear(wpa_s->dpp);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002563 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002564 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002565 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
2566 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002567#ifdef CONFIG_DPP2
2568 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07002569 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2570 wpa_s, NULL);
2571 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002572 dpp_pfs_free(wpa_s->dpp_pfs);
2573 wpa_s->dpp_pfs = NULL;
2574#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002575 offchannel_send_action_done(wpa_s);
2576 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002577 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002578 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002579 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
2580 os_free(wpa_s->dpp_configurator_params);
2581 wpa_s->dpp_configurator_params = NULL;
2582}
Hai Shalom81f62d82019-07-22 12:10:00 -07002583
2584
2585#ifdef CONFIG_DPP2
2586int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
2587{
2588 struct dpp_controller_config config;
2589 const char *pos;
2590
2591 os_memset(&config, 0, sizeof(config));
2592 if (cmd) {
2593 pos = os_strstr(cmd, " tcp_port=");
2594 if (pos) {
2595 pos += 10;
2596 config.tcp_port = atoi(pos);
2597 }
2598 }
2599 config.configurator_params = wpa_s->dpp_configurator_params;
2600 return dpp_controller_start(wpa_s->dpp, &config);
2601}
2602#endif /* CONFIG_DPP2 */