blob: a436930b1c22706c136670420a364f0f18a79057 [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);
Hai Shalom06768112019-12-04 15:49:43 -08001438 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07001439 dpp_auth_deinit(auth);
1440 wpa_s->dpp_auth = NULL;
1441}
1442
1443
Hai Shalomc3565922019-10-28 11:58:20 -07001444static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
1445 void *timeout_ctx)
1446{
1447 struct wpa_supplicant *wpa_s = eloop_ctx;
1448 struct dpp_authentication *auth = wpa_s->dpp_auth;
1449
1450 if (!auth || !auth->waiting_conn_status_result)
1451 return;
1452
1453 wpa_printf(MSG_DEBUG,
1454 "DPP: Timeout while waiting for Connection Status Result");
1455 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
Hai Shalom06768112019-12-04 15:49:43 -08001456 wpas_notify_dpp_timeout(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001457 wpas_dpp_listen_stop(wpa_s);
1458 dpp_auth_deinit(auth);
1459 wpa_s->dpp_auth = NULL;
1460}
1461
1462
Hai Shalom021b0b52019-04-10 11:17:58 -07001463static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
1464 const u8 *hdr, const u8 *buf, size_t len)
1465{
1466 struct dpp_authentication *auth = wpa_s->dpp_auth;
1467 enum dpp_status_error status;
1468
1469 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
1470 MAC2STR(src));
1471
1472 if (!auth || !auth->waiting_conf_result) {
1473 wpa_printf(MSG_DEBUG,
1474 "DPP: No DPP Configuration waiting for result - drop");
1475 return;
1476 }
1477
1478 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1479 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1480 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1481 return;
1482 }
1483
1484 status = dpp_conf_result_rx(auth, hdr, buf, len);
1485
Hai Shalomc3565922019-10-28 11:58:20 -07001486 if (status == DPP_STATUS_OK && auth->send_conn_status) {
1487 wpa_msg(wpa_s, MSG_INFO,
1488 DPP_EVENT_CONF_SENT "wait_conn_status=1");
1489 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shalom06768112019-12-04 15:49:43 -08001490 wpas_notify_dpp_config_accepted(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07001491 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
1492 wpa_s, NULL);
1493 auth->waiting_conn_status_result = 1;
1494 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1495 wpa_s, NULL);
1496 eloop_register_timeout(16, 0,
1497 wpas_dpp_conn_status_result_wait_timeout,
1498 wpa_s, NULL);
1499 offchannel_send_action_done(wpa_s);
1500 wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq :
1501 auth->curr_freq);
1502 return;
1503 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001504 offchannel_send_action_done(wpa_s);
1505 wpas_dpp_listen_stop(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001506 if (status == DPP_STATUS_OK) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001507 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalome4073332019-11-05 16:20:12 -08001508 wpas_notify_dpp_config_sent(wpa_s);
1509 }
1510 else {
Hai Shalom021b0b52019-04-10 11:17:58 -07001511 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom06768112019-12-04 15:49:43 -08001512 wpas_notify_dpp_config_rejected(wpa_s);
Hai Shalome4073332019-11-05 16:20:12 -08001513 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001514 dpp_auth_deinit(auth);
1515 wpa_s->dpp_auth = NULL;
1516 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
1517}
1518
Hai Shalom81f62d82019-07-22 12:10:00 -07001519
Hai Shalomc3565922019-10-28 11:58:20 -07001520static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
1521 const u8 *src, const u8 *hdr,
1522 const u8 *buf, size_t len)
1523{
1524 struct dpp_authentication *auth = wpa_s->dpp_auth;
1525 enum dpp_status_error status;
1526 u8 ssid[SSID_MAX_LEN];
1527 size_t ssid_len = 0;
1528 char *channel_list = NULL;
1529
1530 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
1531
1532 if (!auth || !auth->waiting_conn_status_result) {
1533 wpa_printf(MSG_DEBUG,
1534 "DPP: No DPP Configuration waiting for connection status result - drop");
1535 return;
1536 }
1537
1538 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
1539 ssid, &ssid_len, &channel_list);
1540 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
1541 "result=%d ssid=%s channel_list=%s",
1542 status, wpa_ssid_txt(ssid, ssid_len),
1543 channel_list ? channel_list : "N/A");
Hai Shalom06768112019-12-04 15:49:43 -08001544 wpas_notify_dpp_conn_status(wpa_s, status, wpa_ssid_txt(ssid, ssid_len),
1545 channel_list, auth->band_list, auth->band_list_size);
Hai Shalomc3565922019-10-28 11:58:20 -07001546 os_free(channel_list);
1547 offchannel_send_action_done(wpa_s);
1548 wpas_dpp_listen_stop(wpa_s);
1549 dpp_auth_deinit(auth);
1550 wpa_s->dpp_auth = NULL;
1551 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
1552 wpa_s, NULL);
1553}
1554
1555
Hai Shalom81f62d82019-07-22 12:10:00 -07001556static int wpas_dpp_process_conf_obj(void *ctx,
1557 struct dpp_authentication *auth)
1558{
1559 struct wpa_supplicant *wpa_s = ctx;
Hai Shalomc3565922019-10-28 11:58:20 -07001560 unsigned int i;
1561 int res = -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001562
Hai Shalomc3565922019-10-28 11:58:20 -07001563 for (i = 0; i < auth->num_conf_obj; i++) {
1564 res = wpas_dpp_handle_config_obj(wpa_s, auth,
1565 &auth->conf_obj[i]);
1566 if (res)
1567 break;
1568 }
1569 if (!res)
1570 wpas_dpp_post_process_config(wpa_s, auth);
1571
1572 return res;
Hai Shalom81f62d82019-07-22 12:10:00 -07001573}
1574
Hai Shalom021b0b52019-04-10 11:17:58 -07001575#endif /* CONFIG_DPP2 */
1576
1577
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001578static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
1579 const u8 *src,
1580 const u8 *buf, size_t len)
1581{
1582 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001583 const u8 *connector, *trans_id, *status;
1584 u16 connector_len, trans_id_len, status_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001585 struct dpp_introduction intro;
1586 struct rsn_pmksa_cache_entry *entry;
1587 struct os_time now;
1588 struct os_reltime rnow;
1589 os_time_t expiry;
1590 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001591 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001592
1593 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
1594 MAC2STR(src));
1595 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
1596 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
1597 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
1598 MACSTR " - drop", MAC2STR(src));
1599 return;
1600 }
1601 offchannel_send_action_done(wpa_s);
1602
1603 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1604 if (ssid == wpa_s->dpp_intro_network)
1605 break;
1606 }
1607 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
1608 !ssid->dpp_csign) {
1609 wpa_printf(MSG_DEBUG,
1610 "DPP: Profile not found for network introduction");
1611 return;
1612 }
1613
1614 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1615 &trans_id_len);
1616 if (!trans_id || trans_id_len != 1) {
1617 wpa_printf(MSG_DEBUG,
1618 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001619 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1620 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001621 goto fail;
1622 }
1623 if (trans_id[0] != TRANSACTION_ID) {
1624 wpa_printf(MSG_DEBUG,
1625 "DPP: Ignore frame with unexpected Transaction ID %u",
1626 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001627 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1628 " fail=transaction_id_mismatch", MAC2STR(src));
1629 goto fail;
1630 }
1631
1632 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
1633 if (!status || status_len != 1) {
1634 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
1635 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1636 " fail=missing_status", MAC2STR(src));
1637 goto fail;
1638 }
1639 if (status[0] != DPP_STATUS_OK) {
1640 wpa_printf(MSG_DEBUG,
1641 "DPP: Peer rejected network introduction: Status %u",
1642 status[0]);
1643 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1644 " status=%u", MAC2STR(src), status[0]);
Hai Shalomc3565922019-10-28 11:58:20 -07001645#ifdef CONFIG_DPP2
1646 wpas_dpp_send_conn_status_result(wpa_s, status[0]);
1647#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001648 goto fail;
1649 }
1650
1651 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1652 if (!connector) {
1653 wpa_printf(MSG_DEBUG,
1654 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001655 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1656 " fail=missing_connector", MAC2STR(src));
1657 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001658 }
1659
Roshan Pius3a1667e2018-07-03 15:17:14 -07001660 res = dpp_peer_intro(&intro, ssid->dpp_connector,
1661 ssid->dpp_netaccesskey,
1662 ssid->dpp_netaccesskey_len,
1663 ssid->dpp_csign,
1664 ssid->dpp_csign_len,
1665 connector, connector_len, &expiry);
1666 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001667 wpa_printf(MSG_INFO,
1668 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001669 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1670 " fail=peer_connector_validation_failed", MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07001671#ifdef CONFIG_DPP2
1672 wpas_dpp_send_conn_status_result(wpa_s, res);
1673#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001674 goto fail;
1675 }
1676
1677 entry = os_zalloc(sizeof(*entry));
1678 if (!entry)
1679 goto fail;
1680 os_memcpy(entry->aa, src, ETH_ALEN);
1681 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
1682 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
1683 entry->pmk_len = intro.pmk_len;
1684 entry->akmp = WPA_KEY_MGMT_DPP;
1685 if (expiry) {
1686 os_get_time(&now);
1687 seconds = expiry - now.sec;
1688 } else {
1689 seconds = 86400 * 7;
1690 }
1691 os_get_reltime(&rnow);
1692 entry->expiration = rnow.sec + seconds;
1693 entry->reauth_time = rnow.sec + seconds;
1694 entry->network_ctx = ssid;
1695 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
1696
Roshan Pius3a1667e2018-07-03 15:17:14 -07001697 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1698 " status=%u", MAC2STR(src), status[0]);
1699
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001700 wpa_printf(MSG_DEBUG,
1701 "DPP: Try connection again after successful network introduction");
1702 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
1703 wpa_supplicant_cancel_sched_scan(wpa_s);
1704 wpa_supplicant_req_scan(wpa_s, 0, 0);
1705 }
1706fail:
1707 os_memset(&intro, 0, sizeof(intro));
1708}
1709
1710
Roshan Pius3a1667e2018-07-03 15:17:14 -07001711static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
1712{
1713 int i, j;
1714
1715 if (!wpa_s->hw.modes)
1716 return -1;
1717
1718 for (i = 0; i < wpa_s->hw.num_modes; i++) {
1719 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
1720
1721 for (j = 0; j < mode->num_channels; j++) {
1722 struct hostapd_channel_data *chan = &mode->channels[j];
1723
1724 if (chan->freq != (int) freq)
1725 continue;
1726
1727 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
1728 HOSTAPD_CHAN_NO_IR |
1729 HOSTAPD_CHAN_RADAR))
1730 continue;
1731
1732 return 1;
1733 }
1734 }
1735
1736 wpa_printf(MSG_DEBUG,
1737 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
1738 freq);
1739
1740 return 0;
1741}
1742
1743
1744static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
1745 struct dpp_pkex *pkex)
1746{
1747 if (pkex->freq == 2437)
1748 pkex->freq = 5745;
1749 else if (pkex->freq == 5745)
1750 pkex->freq = 5220;
1751 else if (pkex->freq == 5220)
1752 pkex->freq = 60480;
1753 else
1754 return -1; /* no more channels to try */
1755
1756 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
1757 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
1758 pkex->freq);
1759 return 0;
1760 }
1761
1762 /* Could not use this channel - try the next one */
1763 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
1764}
1765
1766
1767static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
1768{
1769 struct wpa_supplicant *wpa_s = eloop_ctx;
1770 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1771
1772 if (!pkex || !pkex->exchange_req)
1773 return;
1774 if (pkex->exch_req_tries >= 5) {
1775 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
1776 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1777 "No response from PKEX peer");
1778 dpp_pkex_free(pkex);
1779 wpa_s->dpp_pkex = NULL;
1780 return;
1781 }
1782 pkex->exch_req_tries = 0;
1783 }
1784
1785 pkex->exch_req_tries++;
1786 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
1787 pkex->exch_req_tries);
1788 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1789 MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
1790 offchannel_send_action(wpa_s, pkex->freq, broadcast,
1791 wpa_s->own_addr, broadcast,
1792 wpabuf_head(pkex->exchange_req),
1793 wpabuf_len(pkex->exchange_req),
1794 pkex->exch_req_wait_time,
1795 wpas_dpp_tx_pkex_status, 0);
1796}
1797
1798
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001799static void
1800wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
1801 unsigned int freq, const u8 *dst,
1802 const u8 *src, const u8 *bssid,
1803 const u8 *data, size_t data_len,
1804 enum offchannel_send_action_result result)
1805{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001806 const char *res_txt;
1807 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1808
1809 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
1810 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
1811 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001812 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
1813 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001814 freq, MAC2STR(dst), res_txt);
1815 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
1816 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
1817
1818 if (!pkex) {
1819 wpa_printf(MSG_DEBUG,
1820 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
1821 return;
1822 }
1823
1824 if (pkex->failed) {
1825 wpa_printf(MSG_DEBUG,
1826 "DPP: Terminate PKEX exchange due to an earlier error");
1827 if (pkex->t > pkex->own_bi->pkex_t)
1828 pkex->own_bi->pkex_t = pkex->t;
1829 dpp_pkex_free(pkex);
1830 wpa_s->dpp_pkex = NULL;
1831 return;
1832 }
1833
1834 if (pkex->exch_req_wait_time && pkex->exchange_req) {
1835 /* Wait for PKEX Exchange Response frame and retry request if
1836 * no response is seen. */
1837 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1838 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
1839 (pkex->exch_req_wait_time % 1000) * 1000,
1840 wpas_dpp_pkex_retry_timeout, wpa_s,
1841 NULL);
1842 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001843}
1844
1845
1846static void
1847wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
1848 const u8 *buf, size_t len, unsigned int freq)
1849{
1850 struct wpabuf *msg;
1851 unsigned int wait_time;
1852
1853 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1854 MAC2STR(src));
1855
1856 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1857 * values here */
1858
1859 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
1860 wpa_printf(MSG_DEBUG,
1861 "DPP: No PKEX code configured - ignore request");
1862 return;
1863 }
1864
1865 if (wpa_s->dpp_pkex) {
1866 /* TODO: Support parallel operations */
1867 wpa_printf(MSG_DEBUG,
1868 "DPP: Already in PKEX session - ignore new request");
1869 return;
1870 }
1871
Roshan Pius3a1667e2018-07-03 15:17:14 -07001872 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001873 wpa_s->own_addr, src,
1874 wpa_s->dpp_pkex_identifier,
1875 wpa_s->dpp_pkex_code,
1876 buf, len);
1877 if (!wpa_s->dpp_pkex) {
1878 wpa_printf(MSG_DEBUG,
1879 "DPP: Failed to process the request - ignore it");
1880 return;
1881 }
1882
1883 msg = wpa_s->dpp_pkex->exchange_resp;
1884 wait_time = wpa_s->max_remain_on_chan;
1885 if (wait_time > 2000)
1886 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001887 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1888 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001889 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1890 broadcast,
1891 wpabuf_head(msg), wpabuf_len(msg),
1892 wait_time, wpas_dpp_tx_pkex_status, 0);
1893}
1894
1895
1896static void
1897wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
1898 const u8 *buf, size_t len, unsigned int freq)
1899{
1900 struct wpabuf *msg;
1901 unsigned int wait_time;
1902
1903 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1904 MAC2STR(src));
1905
1906 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1907 * values here */
1908
1909 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
1910 wpa_s->dpp_pkex->exchange_done) {
1911 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1912 return;
1913 }
1914
Roshan Pius3a1667e2018-07-03 15:17:14 -07001915 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1916 wpa_s->dpp_pkex->exch_req_wait_time = 0;
1917
1918 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001919 if (!msg) {
1920 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1921 return;
1922 }
1923
1924 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1925 MAC2STR(src));
1926
1927 wait_time = wpa_s->max_remain_on_chan;
1928 if (wait_time > 2000)
1929 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001930 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1931 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001932 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1933 broadcast,
1934 wpabuf_head(msg), wpabuf_len(msg),
1935 wait_time, wpas_dpp_tx_pkex_status, 0);
1936 wpabuf_free(msg);
1937}
1938
1939
Roshan Pius3a1667e2018-07-03 15:17:14 -07001940static struct dpp_bootstrap_info *
1941wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
1942 unsigned int freq)
1943{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001944 struct dpp_bootstrap_info *bi;
1945
Hai Shalom021b0b52019-04-10 11:17:58 -07001946 bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001947 if (!bi)
1948 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001949 wpa_s->dpp_pkex = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001950 return bi;
1951}
1952
1953
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001954static void
1955wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
1956 const u8 *hdr, const u8 *buf, size_t len,
1957 unsigned int freq)
1958{
1959 struct wpabuf *msg;
1960 unsigned int wait_time;
1961 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001962
1963 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1964 MAC2STR(src));
1965
1966 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1967 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1968 return;
1969 }
1970
1971 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1972 if (!msg) {
1973 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001974 if (pkex->failed) {
1975 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1976 if (pkex->t > pkex->own_bi->pkex_t)
1977 pkex->own_bi->pkex_t = pkex->t;
1978 dpp_pkex_free(wpa_s->dpp_pkex);
1979 wpa_s->dpp_pkex = NULL;
1980 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001981 return;
1982 }
1983
1984 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1985 MACSTR, MAC2STR(src));
1986
1987 wait_time = wpa_s->max_remain_on_chan;
1988 if (wait_time > 2000)
1989 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001990 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1991 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001992 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1993 broadcast,
1994 wpabuf_head(msg), wpabuf_len(msg),
1995 wait_time, wpas_dpp_tx_pkex_status, 0);
1996 wpabuf_free(msg);
1997
Roshan Pius3a1667e2018-07-03 15:17:14 -07001998 wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001999}
2000
2001
2002static void
2003wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2004 const u8 *hdr, const u8 *buf, size_t len,
2005 unsigned int freq)
2006{
2007 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002008 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002009 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2010 char cmd[500];
2011
2012 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2013 MAC2STR(src));
2014
2015 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2016 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2017 return;
2018 }
2019
2020 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2021 if (res < 0) {
2022 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2023 return;
2024 }
2025
Roshan Pius3a1667e2018-07-03 15:17:14 -07002026 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002027 if (!bi)
2028 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002029
2030 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2031 bi->id,
2032 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
2033 wpa_printf(MSG_DEBUG,
2034 "DPP: Start authentication after PKEX with parameters: %s",
2035 cmd);
2036 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
2037 wpa_printf(MSG_DEBUG,
2038 "DPP: Authentication initialization failed");
2039 return;
2040 }
2041}
2042
2043
2044void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
2045 const u8 *buf, size_t len, unsigned int freq)
2046{
2047 u8 crypto_suite;
2048 enum dpp_public_action_frame_type type;
2049 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002050 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002051
2052 if (len < DPP_HDR_LEN)
2053 return;
2054 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2055 return;
2056 hdr = buf;
2057 buf += 4;
2058 len -= 4;
2059 crypto_suite = *buf++;
2060 type = *buf++;
2061 len -= 2;
2062
2063 wpa_printf(MSG_DEBUG,
2064 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2065 MACSTR " freq=%u",
2066 crypto_suite, type, MAC2STR(src), freq);
2067 if (crypto_suite != 1) {
2068 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2069 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002070 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2071 " freq=%u type=%d ignore=unsupported-crypto-suite",
2072 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002073 return;
2074 }
2075 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002076 if (dpp_check_attrs(buf, len) < 0) {
2077 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2078 " freq=%u type=%d ignore=invalid-attributes",
2079 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002080 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002081 }
2082 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
2083 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002084
2085 switch (type) {
2086 case DPP_PA_AUTHENTICATION_REQ:
2087 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
2088 break;
2089 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002090 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002091 break;
2092 case DPP_PA_AUTHENTICATION_CONF:
2093 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
2094 break;
2095 case DPP_PA_PEER_DISCOVERY_RESP:
2096 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
2097 break;
2098 case DPP_PA_PKEX_EXCHANGE_REQ:
2099 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
2100 break;
2101 case DPP_PA_PKEX_EXCHANGE_RESP:
2102 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
2103 break;
2104 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2105 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
2106 freq);
2107 break;
2108 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2109 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
2110 freq);
2111 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002112#ifdef CONFIG_DPP2
2113 case DPP_PA_CONFIGURATION_RESULT:
2114 wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
2115 break;
Hai Shalomc3565922019-10-28 11:58:20 -07002116 case DPP_PA_CONNECTION_STATUS_RESULT:
2117 wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
2118 break;
Hai Shalom021b0b52019-04-10 11:17:58 -07002119#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002120 default:
2121 wpa_printf(MSG_DEBUG,
2122 "DPP: Ignored unsupported frame subtype %d", type);
2123 break;
2124 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002125
2126 if (wpa_s->dpp_pkex)
2127 pkex_t = wpa_s->dpp_pkex->t;
2128 else if (wpa_s->dpp_pkex_bi)
2129 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
2130 else
2131 pkex_t = 0;
2132 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2133 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2134 wpas_dpp_pkex_remove(wpa_s, "*");
2135 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002136}
2137
2138
2139static struct wpabuf *
2140wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query,
2141 size_t query_len)
2142{
2143 struct wpa_supplicant *wpa_s = ctx;
2144 struct dpp_authentication *auth = wpa_s->dpp_auth;
2145 struct wpabuf *resp;
2146
2147 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
2148 MAC2STR(sa));
2149 if (!auth || !auth->auth_success ||
2150 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
2151 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2152 return NULL;
2153 }
Hai Shalomc3565922019-10-28 11:58:20 -07002154
2155 if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) {
2156 wpa_printf(MSG_DEBUG,
2157 "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
2158 /* wpas_dpp_auth_success() would normally have been called from
2159 * TX status handler, but since there was no such handler call
2160 * yet, simply send out the event message and proceed with
2161 * exchange. */
2162 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1");
2163 wpa_s->dpp_auth_ok_on_ack = 0;
2164 }
2165
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002166 wpa_hexdump(MSG_DEBUG,
2167 "DPP: Received Configuration Request (GAS Query Request)",
2168 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002169 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2170 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002171 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom59532852018-12-07 10:32:58 -08002172 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002173 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002174 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002175 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002176 auth->conf_resp = resp;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002177 return resp;
2178}
2179
2180
2181static void
2182wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
2183{
2184 struct wpa_supplicant *wpa_s = ctx;
2185 struct dpp_authentication *auth = wpa_s->dpp_auth;
2186
2187 if (!auth) {
2188 wpabuf_free(resp);
2189 return;
2190 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002191 if (auth->conf_resp != resp) {
2192 wpa_printf(MSG_DEBUG,
2193 "DPP: Ignore GAS status report (ok=%d) for unknown response",
2194 ok);
2195 wpabuf_free(resp);
2196 return;
2197 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002198
2199 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2200 ok);
2201 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002202 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002203#ifdef CONFIG_DPP2
2204 if (ok && auth->peer_version >= 2 &&
2205 auth->conf_resp_status == DPP_STATUS_OK) {
2206 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
Hai Shalom06768112019-12-04 15:49:43 -08002207 wpas_notify_dpp_config_sent_wait_response(wpa_s);
Hai Shalom021b0b52019-04-10 11:17:58 -07002208 auth->waiting_conf_result = 1;
2209 auth->conf_resp = NULL;
2210 wpabuf_free(resp);
2211 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
2212 wpa_s, NULL);
2213 eloop_register_timeout(2, 0,
2214 wpas_dpp_config_result_wait_timeout,
2215 wpa_s, NULL);
2216 return;
2217 }
2218#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002219 offchannel_send_action_done(wpa_s);
2220 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002221 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002222 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08002223 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002224 }
2225 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002226 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002227 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002228 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002229 dpp_auth_deinit(wpa_s->dpp_auth);
2230 wpa_s->dpp_auth = NULL;
2231 wpabuf_free(resp);
2232}
2233
2234
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002235int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
2236{
2237 struct dpp_authentication *auth;
2238 int ret = -1;
2239 char *curve = NULL;
2240
2241 auth = os_zalloc(sizeof(*auth));
2242 if (!auth)
2243 return -1;
2244
2245 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08002246 wpas_dpp_set_testing_options(wpa_s, auth);
Hai Shalom021b0b52019-04-10 11:17:58 -07002247 if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 &&
2248 dpp_configurator_own_config(auth, curve, 0) == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002249 ret = wpas_dpp_handle_config_obj(wpa_s, auth,
2250 &auth->conf_obj[0]);
2251 if (!ret)
2252 wpas_dpp_post_process_config(wpa_s, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002253
2254 dpp_auth_deinit(auth);
2255 os_free(curve);
2256
2257 return ret;
2258}
2259
2260
2261static void
2262wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
2263 unsigned int freq, const u8 *dst,
2264 const u8 *src, const u8 *bssid,
2265 const u8 *data, size_t data_len,
2266 enum offchannel_send_action_result result)
2267{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002268 const char *res_txt;
2269
2270 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2271 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2272 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002273 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2274 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002275 freq, MAC2STR(dst), res_txt);
2276 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2277 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002278 /* TODO: Time out wait for response more quickly in error cases? */
2279}
2280
2281
2282int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2283 struct wpa_bss *bss)
2284{
2285 struct os_time now;
2286 struct wpabuf *msg;
2287 unsigned int wait_time;
Hai Shalom021b0b52019-04-10 11:17:58 -07002288 const u8 *rsn;
2289 struct wpa_ie_data ied;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002290
2291 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
2292 return 0; /* Not using DPP AKM - continue */
Hai Shalom021b0b52019-04-10 11:17:58 -07002293 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
2294 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
2295 !(ied.key_mgmt & WPA_KEY_MGMT_DPP))
2296 return 0; /* AP does not support DPP AKM - continue */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002297 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
2298 return 0; /* PMKSA exists for DPP AKM - continue */
2299
2300 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2301 !ssid->dpp_csign) {
2302 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2303 "missing %s",
2304 !ssid->dpp_connector ? "Connector" :
2305 (!ssid->dpp_netaccesskey ? "netAccessKey" :
2306 "C-sign-key"));
2307 return -1;
2308 }
2309
2310 os_get_time(&now);
2311
2312 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002313 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002314 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2315 "netAccessKey expired");
2316 return -1;
2317 }
2318
2319 wpa_printf(MSG_DEBUG,
2320 "DPP: Starting network introduction protocol to derive PMKSA for "
2321 MACSTR, MAC2STR(bss->bssid));
2322
2323 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ,
2324 5 + 4 + os_strlen(ssid->dpp_connector));
2325 if (!msg)
2326 return -1;
2327
Roshan Pius3a1667e2018-07-03 15:17:14 -07002328#ifdef CONFIG_TESTING_OPTIONS
2329 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
2330 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
2331 goto skip_trans_id;
2332 }
2333 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
2334 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
2335 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2336 wpabuf_put_le16(msg, 0);
2337 goto skip_trans_id;
2338 }
2339#endif /* CONFIG_TESTING_OPTIONS */
2340
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002341 /* Transaction ID */
2342 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2343 wpabuf_put_le16(msg, 1);
2344 wpabuf_put_u8(msg, TRANSACTION_ID);
2345
Roshan Pius3a1667e2018-07-03 15:17:14 -07002346#ifdef CONFIG_TESTING_OPTIONS
2347skip_trans_id:
2348 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
2349 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
2350 goto skip_connector;
2351 }
2352 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
2353 char *connector;
2354
2355 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
2356 connector = dpp_corrupt_connector_signature(
2357 ssid->dpp_connector);
2358 if (!connector) {
2359 wpabuf_free(msg);
2360 return -1;
2361 }
2362 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2363 wpabuf_put_le16(msg, os_strlen(connector));
2364 wpabuf_put_str(msg, connector);
2365 os_free(connector);
2366 goto skip_connector;
2367 }
2368#endif /* CONFIG_TESTING_OPTIONS */
2369
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002370 /* DPP Connector */
2371 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2372 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
2373 wpabuf_put_str(msg, ssid->dpp_connector);
2374
Roshan Pius3a1667e2018-07-03 15:17:14 -07002375#ifdef CONFIG_TESTING_OPTIONS
2376skip_connector:
2377#endif /* CONFIG_TESTING_OPTIONS */
2378
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002379 /* TODO: Timeout on AP response */
2380 wait_time = wpa_s->max_remain_on_chan;
2381 if (wait_time > 2000)
2382 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002383 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2384 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002385 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
2386 broadcast,
2387 wpabuf_head(msg), wpabuf_len(msg),
2388 wait_time, wpas_dpp_tx_introduction_status, 0);
2389 wpabuf_free(msg);
2390
2391 /* Request this connection attempt to terminate - new one will be
2392 * started when network introduction protocol completes */
2393 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
2394 wpa_s->dpp_intro_network = ssid;
2395 return 1;
2396}
2397
2398
2399int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
2400{
2401 struct dpp_bootstrap_info *own_bi;
2402 const char *pos, *end;
2403 unsigned int wait_time;
2404
2405 pos = os_strstr(cmd, " own=");
2406 if (!pos)
2407 return -1;
2408 pos += 5;
Hai Shalom021b0b52019-04-10 11:17:58 -07002409 own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002410 if (!own_bi) {
2411 wpa_printf(MSG_DEBUG,
2412 "DPP: Identified bootstrap info not found");
2413 return -1;
2414 }
2415 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2416 wpa_printf(MSG_DEBUG,
2417 "DPP: Identified bootstrap info not for PKEX");
2418 return -1;
2419 }
2420 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002421 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002422
2423 os_free(wpa_s->dpp_pkex_identifier);
2424 wpa_s->dpp_pkex_identifier = NULL;
2425 pos = os_strstr(cmd, " identifier=");
2426 if (pos) {
2427 pos += 12;
2428 end = os_strchr(pos, ' ');
2429 if (!end)
2430 return -1;
2431 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
2432 if (!wpa_s->dpp_pkex_identifier)
2433 return -1;
2434 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
2435 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
2436 }
2437
2438 pos = os_strstr(cmd, " code=");
2439 if (!pos)
2440 return -1;
2441 os_free(wpa_s->dpp_pkex_code);
2442 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
2443 if (!wpa_s->dpp_pkex_code)
2444 return -1;
2445
2446 if (os_strstr(cmd, " init=1")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002447 struct dpp_pkex *pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002448 struct wpabuf *msg;
2449
2450 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
2451 dpp_pkex_free(wpa_s->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002452 wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002453 wpa_s->dpp_pkex_identifier,
2454 wpa_s->dpp_pkex_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002455 pkex = wpa_s->dpp_pkex;
2456 if (!pkex)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002457 return -1;
2458
Roshan Pius3a1667e2018-07-03 15:17:14 -07002459 msg = pkex->exchange_req;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002460 wait_time = wpa_s->max_remain_on_chan;
2461 if (wait_time > 2000)
2462 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002463 pkex->freq = 2437;
2464 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2465 " freq=%u type=%d",
2466 MAC2STR(broadcast), pkex->freq,
2467 DPP_PA_PKEX_EXCHANGE_REQ);
2468 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2469 wpa_s->own_addr, broadcast,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002470 wpabuf_head(msg), wpabuf_len(msg),
2471 wait_time, wpas_dpp_tx_pkex_status, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002472 if (wait_time == 0)
2473 wait_time = 2000;
2474 pkex->exch_req_wait_time = wait_time;
2475 pkex->exch_req_tries = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002476 }
2477
2478 /* TODO: Support multiple PKEX info entries */
2479
2480 os_free(wpa_s->dpp_pkex_auth_cmd);
2481 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
2482
2483 return 1;
2484}
2485
2486
2487int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
2488{
2489 unsigned int id_val;
2490
2491 if (os_strcmp(id, "*") == 0) {
2492 id_val = 0;
2493 } else {
2494 id_val = atoi(id);
2495 if (id_val == 0)
2496 return -1;
2497 }
2498
2499 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
2500 return -1;
2501
2502 /* TODO: Support multiple PKEX entries */
2503 os_free(wpa_s->dpp_pkex_code);
2504 wpa_s->dpp_pkex_code = NULL;
2505 os_free(wpa_s->dpp_pkex_identifier);
2506 wpa_s->dpp_pkex_identifier = NULL;
2507 os_free(wpa_s->dpp_pkex_auth_cmd);
2508 wpa_s->dpp_pkex_auth_cmd = NULL;
2509 wpa_s->dpp_pkex_bi = NULL;
2510 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2511 dpp_pkex_free(wpa_s->dpp_pkex);
2512 wpa_s->dpp_pkex = NULL;
2513 return 0;
2514}
2515
2516
Roshan Pius3a1667e2018-07-03 15:17:14 -07002517void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
2518{
2519 dpp_auth_deinit(wpa_s->dpp_auth);
2520 wpa_s->dpp_auth = NULL;
2521 dpp_pkex_free(wpa_s->dpp_pkex);
2522 wpa_s->dpp_pkex = NULL;
2523 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
2524 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
2525}
2526
2527
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002528int wpas_dpp_init(struct wpa_supplicant *wpa_s)
2529{
Hai Shalom81f62d82019-07-22 12:10:00 -07002530 struct dpp_global_config config;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002531 u8 adv_proto_id[7];
2532
2533 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
2534 adv_proto_id[1] = 5;
2535 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
2536 adv_proto_id[5] = DPP_OUI_TYPE;
2537 adv_proto_id[6] = 0x01;
2538
2539 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
2540 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
2541 wpas_dpp_gas_status_handler, wpa_s) < 0)
2542 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002543
2544 os_memset(&config, 0, sizeof(config));
2545 config.msg_ctx = wpa_s;
2546 config.cb_ctx = wpa_s;
2547#ifdef CONFIG_DPP2
2548 config.process_conf_obj = wpas_dpp_process_conf_obj;
2549#endif /* CONFIG_DPP2 */
2550 wpa_s->dpp = dpp_global_init(&config);
Hai Shalom021b0b52019-04-10 11:17:58 -07002551 return wpa_s->dpp ? 0 : -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002552}
2553
2554
2555void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
2556{
2557#ifdef CONFIG_TESTING_OPTIONS
2558 os_free(wpa_s->dpp_config_obj_override);
2559 wpa_s->dpp_config_obj_override = NULL;
2560 os_free(wpa_s->dpp_discovery_override);
2561 wpa_s->dpp_discovery_override = NULL;
2562 os_free(wpa_s->dpp_groups_override);
2563 wpa_s->dpp_groups_override = NULL;
2564 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
2565#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom021b0b52019-04-10 11:17:58 -07002566 if (!wpa_s->dpp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002567 return;
Hai Shalom021b0b52019-04-10 11:17:58 -07002568 dpp_global_clear(wpa_s->dpp);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002569 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002570 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002571 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
2572 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002573#ifdef CONFIG_DPP2
2574 eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
Hai Shalomc3565922019-10-28 11:58:20 -07002575 eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
2576 wpa_s, NULL);
2577 eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
Hai Shalom021b0b52019-04-10 11:17:58 -07002578 dpp_pfs_free(wpa_s->dpp_pfs);
2579 wpa_s->dpp_pfs = NULL;
2580#endif /* CONFIG_DPP2 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002581 offchannel_send_action_done(wpa_s);
2582 wpas_dpp_listen_stop(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002583 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002584 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002585 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
2586 os_free(wpa_s->dpp_configurator_params);
2587 wpa_s->dpp_configurator_params = NULL;
2588}
Hai Shalom81f62d82019-07-22 12:10:00 -07002589
2590
2591#ifdef CONFIG_DPP2
2592int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
2593{
2594 struct dpp_controller_config config;
2595 const char *pos;
2596
2597 os_memset(&config, 0, sizeof(config));
2598 if (cmd) {
2599 pos = os_strstr(cmd, " tcp_port=");
2600 if (pos) {
2601 pos += 10;
2602 config.tcp_port = atoi(pos);
2603 }
2604 }
2605 config.configurator_params = wpa_s->dpp_configurator_params;
2606 return dpp_controller_start(wpa_s->dpp, &config);
2607}
2608#endif /* CONFIG_DPP2 */