blob: 8877f7ae1e32e152859a78bf7197f127e472ec6b [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * wpa_supplicant - DPP
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
Roshan Pius3a1667e2018-07-03 15:17:14 -07004 * Copyright (c) 2018, 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"
14#include "common/dpp.h"
15#include "common/gas.h"
16#include "common/gas_server.h"
17#include "rsn_supp/wpa.h"
18#include "rsn_supp/pmksa_cache.h"
19#include "wpa_supplicant_i.h"
20#include "config.h"
21#include "driver_i.h"
22#include "offchannel.h"
23#include "gas_query.h"
24#include "bss.h"
25#include "scan.h"
26#include "notify.h"
27#include "dpp_supplicant.h"
Hai Shalom59532852018-12-07 10:32:58 -080028#include "hidl.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070029
30
31static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
32 unsigned int freq);
33static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
34static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
35static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
36 unsigned int freq, const u8 *dst,
37 const u8 *src, const u8 *bssid,
38 const u8 *data, size_t data_len,
39 enum offchannel_send_action_result result);
Roshan Pius3a1667e2018-07-03 15:17:14 -070040static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
41static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s);
42static void
43wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
44 unsigned int freq, const u8 *dst,
45 const u8 *src, const u8 *bssid,
46 const u8 *data, size_t data_len,
47 enum offchannel_send_action_result result);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070048
49static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
50
51/* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only
52 * a single transaction in progress at any point in time. */
53static const u8 TRANSACTION_ID = 1;
54
55
56static struct dpp_configurator *
57dpp_configurator_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
58{
59 struct dpp_configurator *conf;
60
61 dl_list_for_each(conf, &wpa_s->dpp_configurator,
62 struct dpp_configurator, list) {
63 if (conf->id == id)
64 return conf;
65 }
66 return NULL;
67}
68
69
70static unsigned int wpas_dpp_next_id(struct wpa_supplicant *wpa_s)
71{
72 struct dpp_bootstrap_info *bi;
73 unsigned int max_id = 0;
74
75 dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
76 list) {
77 if (bi->id > max_id)
78 max_id = bi->id;
79 }
80 return max_id + 1;
81}
82
83
84/**
85 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
86 * @wpa_s: Pointer to wpa_supplicant data
87 * @cmd: DPP URI read from a QR Code
88 * Returns: Identifier of the stored info or -1 on failure
89 */
90int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
91{
92 struct dpp_bootstrap_info *bi;
93 struct dpp_authentication *auth = wpa_s->dpp_auth;
94
95 bi = dpp_parse_qr_code(cmd);
96 if (!bi)
97 return -1;
98
99 bi->id = wpas_dpp_next_id(wpa_s);
100 dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
101
102 if (auth && auth->response_pending &&
103 dpp_notify_new_qr_code(auth, bi) == 1) {
104 wpa_printf(MSG_DEBUG,
105 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700106 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
107 " freq=%u type=%d",
108 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
109 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700110 offchannel_send_action(wpa_s, auth->curr_freq,
111 auth->peer_mac_addr, wpa_s->own_addr,
112 broadcast,
113 wpabuf_head(auth->resp_msg),
114 wpabuf_len(auth->resp_msg),
115 500, wpas_dpp_tx_status, 0);
116 }
117
118 return bi->id;
119}
120
121
122static char * get_param(const char *cmd, const char *param)
123{
124 const char *pos, *end;
125 char *val;
126 size_t len;
127
128 pos = os_strstr(cmd, param);
129 if (!pos)
130 return NULL;
131
132 pos += os_strlen(param);
133 end = os_strchr(pos, ' ');
134 if (end)
135 len = end - pos;
136 else
137 len = os_strlen(pos);
138 val = os_malloc(len + 1);
139 if (!val)
140 return NULL;
141 os_memcpy(val, pos, len);
142 val[len] = '\0';
143 return val;
144}
145
146
147int wpas_dpp_bootstrap_gen(struct wpa_supplicant *wpa_s, const char *cmd)
148{
149 char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
150 char *key = NULL;
151 u8 *privkey = NULL;
152 size_t privkey_len = 0;
153 size_t len;
154 int ret = -1;
155 struct dpp_bootstrap_info *bi;
156
157 bi = os_zalloc(sizeof(*bi));
158 if (!bi)
159 goto fail;
160
161 if (os_strstr(cmd, "type=qrcode"))
162 bi->type = DPP_BOOTSTRAP_QR_CODE;
163 else if (os_strstr(cmd, "type=pkex"))
164 bi->type = DPP_BOOTSTRAP_PKEX;
165 else
166 goto fail;
167
168 chan = get_param(cmd, " chan=");
169 mac = get_param(cmd, " mac=");
170 info = get_param(cmd, " info=");
171 curve = get_param(cmd, " curve=");
172 key = get_param(cmd, " key=");
173
174 if (key) {
175 privkey_len = os_strlen(key) / 2;
176 privkey = os_malloc(privkey_len);
177 if (!privkey ||
178 hexstr2bin(key, privkey, privkey_len) < 0)
179 goto fail;
180 }
181
182 pk = dpp_keygen(bi, curve, privkey, privkey_len);
183 if (!pk)
184 goto fail;
185
186 len = 4; /* "DPP:" */
187 if (chan) {
188 if (dpp_parse_uri_chan_list(bi, chan) < 0)
189 goto fail;
190 len += 3 + os_strlen(chan); /* C:...; */
191 }
192 if (mac) {
193 if (dpp_parse_uri_mac(bi, mac) < 0)
194 goto fail;
195 len += 3 + os_strlen(mac); /* M:...; */
196 }
197 if (info) {
198 if (dpp_parse_uri_info(bi, info) < 0)
199 goto fail;
200 len += 3 + os_strlen(info); /* I:...; */
201 }
202 len += 4 + os_strlen(pk);
203 bi->uri = os_malloc(len + 1);
204 if (!bi->uri)
205 goto fail;
206 os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
207 chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
208 mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
209 info ? "I:" : "", info ? info : "", info ? ";" : "",
210 pk);
211 bi->id = wpas_dpp_next_id(wpa_s);
212 dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
213 ret = bi->id;
214 bi = NULL;
215fail:
216 os_free(curve);
217 os_free(pk);
218 os_free(chan);
219 os_free(mac);
220 os_free(info);
221 str_clear_free(key);
222 bin_clear_free(privkey, privkey_len);
223 dpp_bootstrap_info_free(bi);
224 return ret;
225}
226
227
228static struct dpp_bootstrap_info *
229dpp_bootstrap_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
230{
231 struct dpp_bootstrap_info *bi;
232
233 dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
234 list) {
235 if (bi->id == id)
236 return bi;
237 }
238 return NULL;
239}
240
241
242static int dpp_bootstrap_del(struct wpa_supplicant *wpa_s, unsigned int id)
243{
244 struct dpp_bootstrap_info *bi, *tmp;
245 int found = 0;
246
247 dl_list_for_each_safe(bi, tmp, &wpa_s->dpp_bootstrap,
248 struct dpp_bootstrap_info, list) {
249 if (id && bi->id != id)
250 continue;
251 found = 1;
252 dl_list_del(&bi->list);
253 dpp_bootstrap_info_free(bi);
254 }
255
256 if (id == 0)
257 return 0; /* flush succeeds regardless of entries found */
258 return found ? 0 : -1;
259}
260
261
262int wpas_dpp_bootstrap_remove(struct wpa_supplicant *wpa_s, const char *id)
263{
264 unsigned int id_val;
265
266 if (os_strcmp(id, "*") == 0) {
267 id_val = 0;
268 } else {
269 id_val = atoi(id);
270 if (id_val == 0)
271 return -1;
272 }
273
274 return dpp_bootstrap_del(wpa_s, id_val);
275}
276
277
278const char * wpas_dpp_bootstrap_get_uri(struct wpa_supplicant *wpa_s,
279 unsigned int id)
280{
281 struct dpp_bootstrap_info *bi;
282
283 bi = dpp_bootstrap_get_id(wpa_s, id);
284 if (!bi)
285 return NULL;
286 return bi->uri;
287}
288
289
290int wpas_dpp_bootstrap_info(struct wpa_supplicant *wpa_s, int id,
291 char *reply, int reply_size)
292{
293 struct dpp_bootstrap_info *bi;
294
295 bi = dpp_bootstrap_get_id(wpa_s, id);
296 if (!bi)
297 return -1;
298 return os_snprintf(reply, reply_size, "type=%s\n"
299 "mac_addr=" MACSTR "\n"
300 "info=%s\n"
301 "num_freq=%u\n"
302 "curve=%s\n",
303 dpp_bootstrap_type_txt(bi->type),
304 MAC2STR(bi->mac_addr),
305 bi->info ? bi->info : "",
306 bi->num_freq,
307 bi->curve->name);
308}
309
310
Roshan Pius3a1667e2018-07-03 15:17:14 -0700311static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
312{
313 struct wpa_supplicant *wpa_s = eloop_ctx;
314 struct dpp_authentication *auth = wpa_s->dpp_auth;
315
316 if (!auth || !auth->resp_msg)
317 return;
318
319 wpa_printf(MSG_DEBUG,
320 "DPP: Retry Authentication Response after timeout");
321 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
322 " freq=%u type=%d",
323 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
324 DPP_PA_AUTHENTICATION_RESP);
325 offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr,
326 wpa_s->own_addr, broadcast,
327 wpabuf_head(auth->resp_msg),
328 wpabuf_len(auth->resp_msg),
329 500, wpas_dpp_tx_status, 0);
330}
331
332
333static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
334{
335 struct dpp_authentication *auth = wpa_s->dpp_auth;
336 unsigned int wait_time, max_tries;
337
338 if (!auth || !auth->resp_msg)
339 return;
340
341 if (wpa_s->dpp_resp_max_tries)
342 max_tries = wpa_s->dpp_resp_max_tries;
343 else
344 max_tries = 5;
345 auth->auth_resp_tries++;
346 if (auth->auth_resp_tries >= max_tries) {
347 wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange");
348 offchannel_send_action_done(wpa_s);
349 dpp_auth_deinit(wpa_s->dpp_auth);
350 wpa_s->dpp_auth = NULL;
351 return;
352 }
353
354 if (wpa_s->dpp_resp_retry_time)
355 wait_time = wpa_s->dpp_resp_retry_time;
356 else
357 wait_time = 1000;
358 wpa_printf(MSG_DEBUG,
359 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
360 wait_time);
361 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
362 eloop_register_timeout(wait_time / 1000,
363 (wait_time % 1000) * 1000,
364 wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
365}
366
367
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700368static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
369 unsigned int freq, const u8 *dst,
370 const u8 *src, const u8 *bssid,
371 const u8 *data, size_t data_len,
372 enum offchannel_send_action_result result)
373{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700374 const char *res_txt;
375 struct dpp_authentication *auth = wpa_s->dpp_auth;
376
377 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
378 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
379 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700380 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700381 " result=%s", freq, MAC2STR(dst), res_txt);
382 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
383 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700384
385 if (!wpa_s->dpp_auth) {
386 wpa_printf(MSG_DEBUG,
387 "DPP: Ignore TX status since there is no ongoing authentication exchange");
388 return;
389 }
390
391 if (wpa_s->dpp_auth->remove_on_tx_status) {
392 wpa_printf(MSG_DEBUG,
393 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700394 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700395 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700396 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
397 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700398 offchannel_send_action_done(wpa_s);
399 dpp_auth_deinit(wpa_s->dpp_auth);
400 wpa_s->dpp_auth = NULL;
401 return;
402 }
403
404 if (wpa_s->dpp_auth_ok_on_ack)
405 wpas_dpp_auth_success(wpa_s, 1);
406
407 if (!is_broadcast_ether_addr(dst) &&
408 result != OFFCHANNEL_SEND_ACTION_SUCCESS) {
409 wpa_printf(MSG_DEBUG,
410 "DPP: Unicast DPP Action frame was not ACKed");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700411 if (auth->waiting_auth_resp) {
412 /* In case of DPP Authentication Request frame, move to
413 * the next channel immediately. */
414 offchannel_send_action_done(wpa_s);
415 wpas_dpp_auth_init_next(wpa_s);
416 return;
417 }
418 if (auth->waiting_auth_conf) {
419 wpas_dpp_auth_resp_retry(wpa_s);
420 return;
421 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700422 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700423
424 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
425 result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
426 /* Allow timeout handling to stop iteration if no response is
427 * received from a peer that has ACKed a request. */
428 auth->auth_req_ack = 1;
429 }
430
431 if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 &&
432 wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) {
433 wpa_printf(MSG_DEBUG,
434 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
435 wpa_s->dpp_auth->curr_freq,
436 wpa_s->dpp_auth->neg_freq);
437 offchannel_send_action_done(wpa_s);
438 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq);
439 }
440
441 if (wpa_s->dpp_auth_ok_on_ack)
442 wpa_s->dpp_auth_ok_on_ack = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700443}
444
445
446static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
447{
448 struct wpa_supplicant *wpa_s = eloop_ctx;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700449 struct dpp_authentication *auth = wpa_s->dpp_auth;
450 unsigned int freq;
451 struct os_reltime now, diff;
452 unsigned int wait_time, diff_ms;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700453
Roshan Pius3a1667e2018-07-03 15:17:14 -0700454 if (!auth || !auth->waiting_auth_resp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700455 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700456
457 wait_time = wpa_s->dpp_resp_wait_time ?
458 wpa_s->dpp_resp_wait_time : 2000;
459 os_get_reltime(&now);
460 os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff);
461 diff_ms = diff.sec * 1000 + diff.usec / 1000;
462 wpa_printf(MSG_DEBUG,
463 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
464 wait_time, diff_ms);
465
466 if (auth->auth_req_ack && diff_ms >= wait_time) {
467 /* Peer ACK'ed Authentication Request frame, but did not reply
468 * with Authentication Response frame within two seconds. */
469 wpa_printf(MSG_INFO,
470 "DPP: No response received from responder - stopping initiation attempt");
471 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800472 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700473 offchannel_send_action_done(wpa_s);
474 wpas_dpp_listen_stop(wpa_s);
475 dpp_auth_deinit(auth);
476 wpa_s->dpp_auth = NULL;
477 return;
478 }
479
480 if (diff_ms >= wait_time) {
481 /* Authentication Request frame was not ACK'ed and no reply
482 * was receiving within two seconds. */
483 wpa_printf(MSG_DEBUG,
484 "DPP: Continue Initiator channel iteration");
485 offchannel_send_action_done(wpa_s);
486 wpas_dpp_listen_stop(wpa_s);
487 wpas_dpp_auth_init_next(wpa_s);
488 return;
489 }
490
491 /* Driver did not support 2000 ms long wait_time with TX command, so
492 * schedule listen operation to continue waiting for the response.
493 *
494 * DPP listen operations continue until stopped, so simply schedule a
495 * new call to this function at the point when the two second reply
496 * wait has expired. */
497 wait_time -= diff_ms;
498
499 freq = auth->curr_freq;
500 if (auth->neg_freq > 0)
501 freq = auth->neg_freq;
502 wpa_printf(MSG_DEBUG,
503 "DPP: Continue reply wait on channel %u MHz for %u ms",
504 freq, wait_time);
505 wpa_s->dpp_in_response_listen = 1;
506 wpas_dpp_listen_start(wpa_s, freq);
507
508 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
509 wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700510}
511
512
513static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
514 struct dpp_authentication *auth)
515{
516#ifdef CONFIG_TESTING_OPTIONS
517 if (wpa_s->dpp_config_obj_override)
518 auth->config_obj_override =
519 os_strdup(wpa_s->dpp_config_obj_override);
520 if (wpa_s->dpp_discovery_override)
521 auth->discovery_override =
522 os_strdup(wpa_s->dpp_discovery_override);
523 if (wpa_s->dpp_groups_override)
524 auth->groups_override =
525 os_strdup(wpa_s->dpp_groups_override);
526 auth->ignore_netaccesskey_mismatch =
527 wpa_s->dpp_ignore_netaccesskey_mismatch;
528#endif /* CONFIG_TESTING_OPTIONS */
529}
530
531
Hai Shalom74f70d42019-02-11 14:42:39 -0800532static int wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
533 struct dpp_authentication *auth,
534 const char *cmd)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700535{
536 const char *pos, *end;
537 struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
538 struct dpp_configurator *conf = NULL;
539 u8 ssid[32] = { "test" };
540 size_t ssid_len = 4;
541 char pass[64] = { };
542 size_t pass_len = 0;
543 u8 psk[PMK_LEN];
544 int psk_set = 0;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700545 char *group_id = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700546
547 if (!cmd)
Hai Shalom74f70d42019-02-11 14:42:39 -0800548 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700549
550 wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
551 pos = os_strstr(cmd, " ssid=");
552 if (pos) {
553 pos += 6;
554 end = os_strchr(pos, ' ');
555 ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
556 ssid_len /= 2;
557 if (ssid_len > sizeof(ssid) ||
558 hexstr2bin(pos, ssid, ssid_len) < 0)
559 goto fail;
560 }
561
562 pos = os_strstr(cmd, " pass=");
563 if (pos) {
564 pos += 6;
565 end = os_strchr(pos, ' ');
566 pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
567 pass_len /= 2;
568 if (pass_len > sizeof(pass) - 1 || pass_len < 8 ||
569 hexstr2bin(pos, (u8 *) pass, pass_len) < 0)
570 goto fail;
571 }
572
573 pos = os_strstr(cmd, " psk=");
574 if (pos) {
575 pos += 5;
576 if (hexstr2bin(pos, psk, PMK_LEN) < 0)
577 goto fail;
578 psk_set = 1;
579 }
580
Hai Shalomce48b4a2018-09-05 11:41:35 -0700581 pos = os_strstr(cmd, " group_id=");
582 if (pos) {
583 size_t group_id_len;
584
585 pos += 10;
586 end = os_strchr(pos, ' ');
587 group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
588 group_id = os_malloc(group_id_len + 1);
589 if (!group_id)
590 goto fail;
591 os_memcpy(group_id, pos, group_id_len);
592 group_id[group_id_len] = '\0';
593 }
594
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700595 if (os_strstr(cmd, " conf=sta-")) {
596 conf_sta = os_zalloc(sizeof(struct dpp_configuration));
597 if (!conf_sta)
598 goto fail;
599 os_memcpy(conf_sta->ssid, ssid, ssid_len);
600 conf_sta->ssid_len = ssid_len;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700601 if (os_strstr(cmd, " conf=sta-psk") ||
602 os_strstr(cmd, " conf=sta-sae") ||
603 os_strstr(cmd, " conf=sta-psk-sae")) {
604 if (os_strstr(cmd, " conf=sta-psk-sae"))
605 conf_sta->akm = DPP_AKM_PSK_SAE;
606 else if (os_strstr(cmd, " conf=sta-sae"))
607 conf_sta->akm = DPP_AKM_SAE;
608 else
609 conf_sta->akm = DPP_AKM_PSK;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700610 if (psk_set) {
611 os_memcpy(conf_sta->psk, psk, PMK_LEN);
Hai Shalom74f70d42019-02-11 14:42:39 -0800612 } else if (pass_len > 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700613 conf_sta->passphrase = os_strdup(pass);
614 if (!conf_sta->passphrase)
615 goto fail;
Hai Shalom74f70d42019-02-11 14:42:39 -0800616 } else {
617 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700618 }
619 } else if (os_strstr(cmd, " conf=sta-dpp")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700620 conf_sta->akm = DPP_AKM_DPP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700621 } else {
622 goto fail;
623 }
Hai Shalomce48b4a2018-09-05 11:41:35 -0700624 if (os_strstr(cmd, " group_id=")) {
625 conf_sta->group_id = group_id;
626 group_id = NULL;
627 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700628 }
629
630 if (os_strstr(cmd, " conf=ap-")) {
631 conf_ap = os_zalloc(sizeof(struct dpp_configuration));
632 if (!conf_ap)
633 goto fail;
634 os_memcpy(conf_ap->ssid, ssid, ssid_len);
635 conf_ap->ssid_len = ssid_len;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700636 if (os_strstr(cmd, " conf=ap-psk") ||
637 os_strstr(cmd, " conf=ap-sae") ||
638 os_strstr(cmd, " conf=ap-psk-sae")) {
639 if (os_strstr(cmd, " conf=ap-psk-sae"))
640 conf_ap->akm = DPP_AKM_PSK_SAE;
641 else if (os_strstr(cmd, " conf=ap-sae"))
642 conf_ap->akm = DPP_AKM_SAE;
643 else
644 conf_ap->akm = DPP_AKM_PSK;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700645 if (psk_set) {
646 os_memcpy(conf_ap->psk, psk, PMK_LEN);
647 } else {
648 conf_ap->passphrase = os_strdup(pass);
649 if (!conf_ap->passphrase)
650 goto fail;
651 }
652 } else if (os_strstr(cmd, " conf=ap-dpp")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700653 conf_ap->akm = DPP_AKM_DPP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700654 } else {
655 goto fail;
656 }
Hai Shalomce48b4a2018-09-05 11:41:35 -0700657 if (os_strstr(cmd, " group_id=")) {
658 conf_ap->group_id = group_id;
659 group_id = NULL;
660 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700661 }
662
663 pos = os_strstr(cmd, " expiry=");
664 if (pos) {
665 long int val;
666
667 pos += 8;
668 val = strtol(pos, NULL, 0);
669 if (val <= 0)
670 goto fail;
671 if (conf_sta)
672 conf_sta->netaccesskey_expiry = val;
673 if (conf_ap)
674 conf_ap->netaccesskey_expiry = val;
675 }
676
677 pos = os_strstr(cmd, " configurator=");
678 if (pos) {
679 pos += 14;
680 conf = dpp_configurator_get_id(wpa_s, atoi(pos));
681 if (!conf) {
682 wpa_printf(MSG_INFO,
683 "DPP: Could not find the specified configurator");
684 goto fail;
685 }
686 }
687 auth->conf_sta = conf_sta;
688 auth->conf_ap = conf_ap;
689 auth->conf = conf;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700690 os_free(group_id);
Hai Shalom74f70d42019-02-11 14:42:39 -0800691 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700692
693fail:
Hai Shalom74f70d42019-02-11 14:42:39 -0800694 wpa_msg(wpa_s, MSG_INFO, "DPP: Failed to set configurator parameters");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700695 dpp_configuration_free(conf_sta);
696 dpp_configuration_free(conf_ap);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700697 os_free(group_id);
Hai Shalom74f70d42019-02-11 14:42:39 -0800698 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700699}
700
701
Roshan Pius3a1667e2018-07-03 15:17:14 -0700702static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
703{
704 struct wpa_supplicant *wpa_s = eloop_ctx;
705
706 if (!wpa_s->dpp_auth)
707 return;
708 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
709 wpas_dpp_auth_init_next(wpa_s);
710}
711
712
713static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
714{
715 struct dpp_authentication *auth = wpa_s->dpp_auth;
716 const u8 *dst;
717 unsigned int wait_time, max_wait_time, freq, max_tries, used;
718 struct os_reltime now, diff;
719
720 wpa_s->dpp_in_response_listen = 0;
721 if (!auth)
722 return -1;
723
724 if (auth->freq_idx == 0)
725 os_get_reltime(&wpa_s->dpp_init_iter_start);
726
727 if (auth->freq_idx >= auth->num_freq) {
728 auth->num_freq_iters++;
729 if (wpa_s->dpp_init_max_tries)
730 max_tries = wpa_s->dpp_init_max_tries;
731 else
732 max_tries = 5;
733 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
734 wpa_printf(MSG_INFO,
735 "DPP: No response received from responder - stopping initiation attempt");
736 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800737 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700738 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
739 wpa_s, NULL);
740 offchannel_send_action_done(wpa_s);
741 dpp_auth_deinit(wpa_s->dpp_auth);
742 wpa_s->dpp_auth = NULL;
743 return -1;
744 }
745 auth->freq_idx = 0;
746 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
747 if (wpa_s->dpp_init_retry_time)
748 wait_time = wpa_s->dpp_init_retry_time;
749 else
750 wait_time = 10000;
751 os_get_reltime(&now);
752 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
753 used = diff.sec * 1000 + diff.usec / 1000;
754 if (used > wait_time)
755 wait_time = 0;
756 else
757 wait_time -= used;
758 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
759 wait_time);
760 eloop_register_timeout(wait_time / 1000,
761 (wait_time % 1000) * 1000,
762 wpas_dpp_init_timeout, wpa_s,
763 NULL);
764 return 0;
765 }
766 freq = auth->freq[auth->freq_idx++];
767 auth->curr_freq = freq;
768
769 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
770 dst = broadcast;
771 else
772 dst = auth->peer_bi->mac_addr;
773 wpa_s->dpp_auth_ok_on_ack = 0;
774 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
775 wait_time = wpa_s->max_remain_on_chan;
776 max_wait_time = wpa_s->dpp_resp_wait_time ?
777 wpa_s->dpp_resp_wait_time : 2000;
778 if (wait_time > max_wait_time)
779 wait_time = max_wait_time;
780 wait_time += 10; /* give the driver some extra time to complete */
781 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
782 wpas_dpp_reply_wait_timeout,
783 wpa_s, NULL);
784 wait_time -= 10;
785 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
786 wpa_printf(MSG_DEBUG,
787 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
788 freq, auth->neg_freq);
789 }
790 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
791 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
792 auth->auth_req_ack = 0;
793 os_get_reltime(&wpa_s->dpp_last_init);
794 return offchannel_send_action(wpa_s, freq, dst,
795 wpa_s->own_addr, broadcast,
796 wpabuf_head(auth->req_msg),
797 wpabuf_len(auth->req_msg),
798 wait_time, wpas_dpp_tx_status, 0);
799}
800
801
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700802int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
803{
804 const char *pos;
805 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700806 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
807 unsigned int neg_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700808
809 wpa_s->dpp_gas_client = 0;
810
811 pos = os_strstr(cmd, " peer=");
812 if (!pos)
813 return -1;
814 pos += 6;
815 peer_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
816 if (!peer_bi) {
817 wpa_printf(MSG_INFO,
818 "DPP: Could not find bootstrapping info for the identified peer");
819 return -1;
820 }
821
822 pos = os_strstr(cmd, " own=");
823 if (pos) {
824 pos += 5;
825 own_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
826 if (!own_bi) {
827 wpa_printf(MSG_INFO,
828 "DPP: Could not find bootstrapping info for the identified local entry");
829 return -1;
830 }
831
832 if (peer_bi->curve != own_bi->curve) {
833 wpa_printf(MSG_INFO,
834 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
835 peer_bi->curve->name, own_bi->curve->name);
836 return -1;
837 }
838 }
839
840 pos = os_strstr(cmd, " role=");
841 if (pos) {
842 pos += 6;
843 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700844 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700845 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700846 allowed_roles = DPP_CAPAB_ENROLLEE;
847 else if (os_strncmp(pos, "either", 6) == 0)
848 allowed_roles = DPP_CAPAB_CONFIGURATOR |
849 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700850 else
851 goto fail;
852 }
853
854 pos = os_strstr(cmd, " netrole=");
855 if (pos) {
856 pos += 9;
857 wpa_s->dpp_netrole_ap = os_strncmp(pos, "ap", 2) == 0;
858 }
859
Roshan Pius3a1667e2018-07-03 15:17:14 -0700860 pos = os_strstr(cmd, " neg_freq=");
861 if (pos)
862 neg_freq = atoi(pos + 10);
863
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700864 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700865 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700866 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700867 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
868 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700869 offchannel_send_action_done(wpa_s);
870 dpp_auth_deinit(wpa_s->dpp_auth);
871 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700872 wpa_s->dpp_auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles,
873 neg_freq,
874 wpa_s->hw.modes, wpa_s->hw.num_modes);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700875 if (!wpa_s->dpp_auth)
876 goto fail;
877 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800878 if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth, cmd) < 0) {
879 dpp_auth_deinit(wpa_s->dpp_auth);
880 wpa_s->dpp_auth = NULL;
881 goto fail;
882 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700883
Roshan Pius3a1667e2018-07-03 15:17:14 -0700884 wpa_s->dpp_auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700885
Roshan Pius3a1667e2018-07-03 15:17:14 -0700886 if (!is_zero_ether_addr(peer_bi->mac_addr))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700887 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
888 ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700889
Roshan Pius3a1667e2018-07-03 15:17:14 -0700890 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700891fail:
892 return -1;
893}
894
895
896struct wpas_dpp_listen_work {
897 unsigned int freq;
898 unsigned int duration;
899 struct wpabuf *probe_resp_ie;
900};
901
902
903static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
904{
905 if (!lwork)
906 return;
907 os_free(lwork);
908}
909
910
911static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
912{
913 struct wpas_dpp_listen_work *lwork;
914
915 if (!wpa_s->dpp_listen_work)
916 return;
917
918 lwork = wpa_s->dpp_listen_work->ctx;
919 wpas_dpp_listen_work_free(lwork);
920 radio_work_done(wpa_s->dpp_listen_work);
921 wpa_s->dpp_listen_work = NULL;
922}
923
924
925static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
926{
927 struct wpa_supplicant *wpa_s = work->wpa_s;
928 struct wpas_dpp_listen_work *lwork = work->ctx;
929
930 if (deinit) {
931 if (work->started) {
932 wpa_s->dpp_listen_work = NULL;
933 wpas_dpp_listen_stop(wpa_s);
934 }
935 wpas_dpp_listen_work_free(lwork);
936 return;
937 }
938
939 wpa_s->dpp_listen_work = work;
940
941 wpa_s->dpp_pending_listen_freq = lwork->freq;
942
943 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
944 wpa_s->max_remain_on_chan) < 0) {
945 wpa_printf(MSG_DEBUG,
946 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
947 lwork->freq);
Hai Shalom74f70d42019-02-11 14:42:39 -0800948 wpa_s->dpp_listen_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700949 wpas_dpp_listen_work_done(wpa_s);
950 wpa_s->dpp_pending_listen_freq = 0;
951 return;
952 }
953 wpa_s->off_channel_freq = 0;
954 wpa_s->roc_waiting_drv_freq = lwork->freq;
955}
956
957
958static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
959 unsigned int freq)
960{
961 struct wpas_dpp_listen_work *lwork;
962
963 if (wpa_s->dpp_listen_work) {
964 wpa_printf(MSG_DEBUG,
965 "DPP: Reject start_listen since dpp_listen_work already exists");
966 return -1;
967 }
968
969 if (wpa_s->dpp_listen_freq)
970 wpas_dpp_listen_stop(wpa_s);
971 wpa_s->dpp_listen_freq = freq;
972
973 lwork = os_zalloc(sizeof(*lwork));
974 if (!lwork)
975 return -1;
976 lwork->freq = freq;
977
978 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
979 lwork) < 0) {
980 wpas_dpp_listen_work_free(lwork);
981 return -1;
982 }
983
984 return 0;
985}
986
987
988int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
989{
990 int freq;
991
992 freq = atoi(cmd);
993 if (freq <= 0)
994 return -1;
995
996 if (os_strstr(cmd, " role=configurator"))
997 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
998 else if (os_strstr(cmd, " role=enrollee"))
999 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
1000 else
1001 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
1002 DPP_CAPAB_ENROLLEE;
1003 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
1004 wpa_s->dpp_netrole_ap = os_strstr(cmd, " netrole=ap") != NULL;
1005 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
1006 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
1007 freq);
1008 return 0;
1009 }
1010
1011 return wpas_dpp_listen_start(wpa_s, freq);
1012}
1013
1014
1015void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1016{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001017 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001018 if (!wpa_s->dpp_listen_freq)
1019 return;
1020
1021 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1022 wpa_s->dpp_listen_freq);
1023 wpa_drv_cancel_remain_on_channel(wpa_s);
1024 wpa_s->dpp_listen_freq = 0;
1025 wpas_dpp_listen_work_done(wpa_s);
1026}
1027
1028
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001029void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1030 unsigned int freq)
1031{
1032 wpas_dpp_listen_work_done(wpa_s);
1033
Roshan Pius3a1667e2018-07-03 15:17:14 -07001034 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1035 unsigned int new_freq;
1036
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001037 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001038 if (wpa_s->dpp_auth->neg_freq > 0)
1039 new_freq = wpa_s->dpp_auth->neg_freq;
1040 else
1041 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001042 wpa_printf(MSG_DEBUG,
1043 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001044 new_freq);
1045 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001046 return;
1047 }
1048
1049 if (wpa_s->dpp_listen_freq) {
1050 /* Continue listen with a new remain-on-channel */
1051 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1052 }
1053}
1054
1055
1056static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1057 const u8 *hdr, const u8 *buf, size_t len,
1058 unsigned int freq)
1059{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001060 const u8 *r_bootstrap, *i_bootstrap;
1061 u16 r_bootstrap_len, i_bootstrap_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001062 struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL;
1063
1064 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1065 MAC2STR(src));
1066
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001067 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1068 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001069 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1070 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1071 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001072 return;
1073 }
1074 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1075 r_bootstrap, r_bootstrap_len);
1076
1077 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1078 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001079 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1080 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1081 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001082 return;
1083 }
1084 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1085 i_bootstrap, i_bootstrap_len);
1086
1087 /* Try to find own and peer bootstrapping key matches based on the
1088 * received hash values */
1089 dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
1090 list) {
1091 if (!own_bi && bi->own &&
1092 os_memcmp(bi->pubkey_hash, r_bootstrap,
1093 SHA256_MAC_LEN) == 0) {
1094 wpa_printf(MSG_DEBUG,
1095 "DPP: Found matching own bootstrapping information");
1096 own_bi = bi;
1097 }
1098
1099 if (!peer_bi && !bi->own &&
1100 os_memcmp(bi->pubkey_hash, i_bootstrap,
1101 SHA256_MAC_LEN) == 0) {
1102 wpa_printf(MSG_DEBUG,
1103 "DPP: Found matching peer bootstrapping information");
1104 peer_bi = bi;
1105 }
1106
1107 if (own_bi && peer_bi)
1108 break;
1109 }
1110
1111 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001112 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1113 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001114 return;
1115 }
1116
1117 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001118 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1119 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001120 return;
1121 }
1122
1123 wpa_s->dpp_gas_client = 0;
1124 wpa_s->dpp_auth_ok_on_ack = 0;
1125 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles,
1126 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001127 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001128 if (!wpa_s->dpp_auth) {
1129 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1130 return;
1131 }
1132 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -08001133 if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth,
1134 wpa_s->dpp_configurator_params) < 0) {
1135 dpp_auth_deinit(wpa_s->dpp_auth);
1136 wpa_s->dpp_auth = NULL;
1137 return;
1138 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001139 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1140
Roshan Pius3a1667e2018-07-03 15:17:14 -07001141 if (wpa_s->dpp_listen_freq &&
1142 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1143 wpa_printf(MSG_DEBUG,
1144 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1145 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1146 wpas_dpp_listen_stop(wpa_s);
1147 }
1148
1149 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1150 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1151 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001152 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1153 src, wpa_s->own_addr, broadcast,
1154 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1155 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1156 500, wpas_dpp_tx_status, 0);
1157}
1158
1159
1160static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1161{
1162 /* TODO: stop wait and start ROC */
1163}
1164
1165
1166static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
1167 struct dpp_authentication *auth)
1168{
1169 struct wpa_ssid *ssid;
1170
1171 ssid = wpa_config_add_network(wpa_s->conf);
1172 if (!ssid)
1173 return NULL;
1174 wpas_notify_network_added(wpa_s, ssid);
1175 wpa_config_set_network_defaults(ssid);
1176 ssid->disabled = 1;
1177
1178 ssid->ssid = os_malloc(auth->ssid_len);
1179 if (!ssid->ssid)
1180 goto fail;
1181 os_memcpy(ssid->ssid, auth->ssid, auth->ssid_len);
1182 ssid->ssid_len = auth->ssid_len;
1183
1184 if (auth->connector) {
1185 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001186 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001187 ssid->dpp_connector = os_strdup(auth->connector);
1188 if (!ssid->dpp_connector)
1189 goto fail;
1190 }
1191
1192 if (auth->c_sign_key) {
1193 ssid->dpp_csign = os_malloc(wpabuf_len(auth->c_sign_key));
1194 if (!ssid->dpp_csign)
1195 goto fail;
1196 os_memcpy(ssid->dpp_csign, wpabuf_head(auth->c_sign_key),
1197 wpabuf_len(auth->c_sign_key));
1198 ssid->dpp_csign_len = wpabuf_len(auth->c_sign_key);
1199 }
1200
1201 if (auth->net_access_key) {
1202 ssid->dpp_netaccesskey =
1203 os_malloc(wpabuf_len(auth->net_access_key));
1204 if (!ssid->dpp_netaccesskey)
1205 goto fail;
1206 os_memcpy(ssid->dpp_netaccesskey,
1207 wpabuf_head(auth->net_access_key),
1208 wpabuf_len(auth->net_access_key));
1209 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1210 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1211 }
1212
1213 if (!auth->connector) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001214 ssid->key_mgmt = 0;
1215 if (auth->akm == DPP_AKM_PSK || auth->akm == DPP_AKM_PSK_SAE)
1216 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1217 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
1218 if (auth->akm == DPP_AKM_SAE || auth->akm == DPP_AKM_PSK_SAE)
1219 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1220 WPA_KEY_MGMT_FT_SAE;
1221 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001222 if (auth->passphrase[0]) {
1223 if (wpa_config_set_quoted(ssid, "psk",
1224 auth->passphrase) < 0)
1225 goto fail;
1226 wpa_config_update_psk(ssid);
1227 ssid->export_keys = 1;
1228 } else {
1229 ssid->psk_set = auth->psk_set;
1230 os_memcpy(ssid->psk, auth->psk, PMK_LEN);
1231 }
1232 }
1233
1234 return ssid;
1235fail:
1236 wpas_notify_network_removed(wpa_s, ssid);
1237 wpa_config_remove_network(wpa_s->conf, ssid->id);
1238 return NULL;
1239}
1240
1241
1242static void wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
1243 struct dpp_authentication *auth)
1244{
1245 struct wpa_ssid *ssid;
1246
1247 if (wpa_s->conf->dpp_config_processing < 1)
1248 return;
1249
1250 ssid = wpas_dpp_add_network(wpa_s, auth);
1251 if (!ssid)
1252 return;
1253
1254 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001255
Hai Shalom706f99b2019-01-08 16:23:37 -08001256 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001257
1258 if (wpa_s->conf->dpp_config_processing < 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001259 return;
Hai Shalom59532852018-12-07 10:32:58 -08001260 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001261
1262 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
1263 ssid->disabled = 0;
1264 wpa_s->disconnected = 0;
1265 wpa_s->reassociate = 1;
1266 wpa_s->scan_runs = 0;
1267 wpa_s->normal_scans = 0;
1268 wpa_supplicant_cancel_sched_scan(wpa_s);
1269 wpa_supplicant_req_scan(wpa_s, 0, 0);
1270}
1271
1272
1273static void wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
1274 struct dpp_authentication *auth)
1275{
1276 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
1277 if (auth->ssid_len)
1278 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
1279 wpa_ssid_txt(auth->ssid, auth->ssid_len));
1280 if (auth->connector) {
1281 /* TODO: Save the Connector and consider using a command
1282 * to fetch the value instead of sending an event with
1283 * it. The Connector could end up being larger than what
1284 * most clients are ready to receive as an event
1285 * message. */
1286 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
1287 auth->connector);
1288 }
1289 if (auth->c_sign_key) {
1290 char *hex;
1291 size_t hexlen;
1292
1293 hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
1294 hex = os_malloc(hexlen);
1295 if (hex) {
1296 wpa_snprintf_hex(hex, hexlen,
1297 wpabuf_head(auth->c_sign_key),
1298 wpabuf_len(auth->c_sign_key));
1299 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1300 hex);
1301 os_free(hex);
1302 }
1303 }
1304 if (auth->net_access_key) {
1305 char *hex;
1306 size_t hexlen;
1307
1308 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1309 hex = os_malloc(hexlen);
1310 if (hex) {
1311 wpa_snprintf_hex(hex, hexlen,
1312 wpabuf_head(auth->net_access_key),
1313 wpabuf_len(auth->net_access_key));
1314 if (auth->net_access_key_expiry)
1315 wpa_msg(wpa_s, MSG_INFO,
1316 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1317 (long unsigned)
1318 auth->net_access_key_expiry);
1319 else
1320 wpa_msg(wpa_s, MSG_INFO,
1321 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1322 os_free(hex);
1323 }
1324 }
1325
1326 wpas_dpp_process_config(wpa_s, auth);
1327}
1328
1329
1330static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1331 enum gas_query_result result,
1332 const struct wpabuf *adv_proto,
1333 const struct wpabuf *resp, u16 status_code)
1334{
1335 struct wpa_supplicant *wpa_s = ctx;
1336 const u8 *pos;
1337 struct dpp_authentication *auth = wpa_s->dpp_auth;
1338
Roshan Pius3a1667e2018-07-03 15:17:14 -07001339 wpa_s->dpp_gas_dialog_token = -1;
1340
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001341 if (!auth || !auth->auth_success) {
1342 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1343 return;
1344 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001345 if (result != GAS_QUERY_SUCCESS ||
1346 !resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001347 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1348 goto fail;
1349 }
1350
1351 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1352 adv_proto);
1353 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1354 resp);
1355
1356 if (wpabuf_len(adv_proto) != 10 ||
1357 !(pos = wpabuf_head(adv_proto)) ||
1358 pos[0] != WLAN_EID_ADV_PROTO ||
1359 pos[1] != 8 ||
1360 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1361 pos[4] != 5 ||
1362 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1363 pos[8] != 0x1a ||
1364 pos[9] != 1) {
1365 wpa_printf(MSG_DEBUG,
1366 "DPP: Not a DPP Advertisement Protocol ID");
1367 goto fail;
1368 }
1369
1370 if (dpp_conf_resp_rx(auth, resp) < 0) {
1371 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1372 goto fail;
1373 }
1374
1375 wpas_dpp_handle_config_obj(wpa_s, auth);
1376 dpp_auth_deinit(wpa_s->dpp_auth);
1377 wpa_s->dpp_auth = NULL;
1378 return;
1379
1380fail:
1381 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08001382 wpas_notify_dpp_configuration_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001383 dpp_auth_deinit(wpa_s->dpp_auth);
1384 wpa_s->dpp_auth = NULL;
1385}
1386
1387
1388static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1389{
1390 struct dpp_authentication *auth = wpa_s->dpp_auth;
1391 struct wpabuf *buf, *conf_req;
1392 char json[100];
1393 int res;
1394
1395 wpa_s->dpp_gas_client = 1;
1396 os_snprintf(json, sizeof(json),
1397 "{\"name\":\"Test\","
1398 "\"wi-fi_tech\":\"infra\","
1399 "\"netRole\":\"%s\"}",
1400 wpa_s->dpp_netrole_ap ? "ap" : "sta");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001401#ifdef CONFIG_TESTING_OPTIONS
1402 if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
1403 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr");
1404 json[29] = 'k'; /* replace "infra" with "knfra" */
1405 }
1406#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001407 wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
1408
1409 offchannel_send_action_done(wpa_s);
1410 wpas_dpp_listen_stop(wpa_s);
1411
1412 conf_req = dpp_build_conf_req(auth, json);
1413 if (!conf_req) {
1414 wpa_printf(MSG_DEBUG,
1415 "DPP: No configuration request data available");
1416 return;
1417 }
1418
1419 buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
1420 if (!buf) {
1421 wpabuf_free(conf_req);
1422 return;
1423 }
1424
1425 /* Advertisement Protocol IE */
1426 wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
1427 wpabuf_put_u8(buf, 8); /* Length */
1428 wpabuf_put_u8(buf, 0x7f);
1429 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
1430 wpabuf_put_u8(buf, 5);
1431 wpabuf_put_be24(buf, OUI_WFA);
1432 wpabuf_put_u8(buf, DPP_OUI_TYPE);
1433 wpabuf_put_u8(buf, 0x01);
1434
1435 /* GAS Query */
1436 wpabuf_put_le16(buf, wpabuf_len(conf_req));
1437 wpabuf_put_buf(buf, conf_req);
1438 wpabuf_free(conf_req);
1439
1440 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1441 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1442
1443 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001444 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001445 if (res < 0) {
1446 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1447 wpabuf_free(buf);
1448 } else {
1449 wpa_printf(MSG_DEBUG,
1450 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001451 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001452 }
1453}
1454
1455
1456static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1457{
1458 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1459 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001460 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001461#ifdef CONFIG_TESTING_OPTIONS
1462 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1463 wpa_printf(MSG_INFO,
1464 "DPP: TESTING - stop at Authentication Confirm");
1465 if (wpa_s->dpp_auth->configurator) {
1466 /* Prevent GAS response */
1467 wpa_s->dpp_auth->auth_success = 0;
1468 }
1469 return;
1470 }
1471#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001472
1473 if (wpa_s->dpp_auth->configurator)
1474 wpas_dpp_start_gas_server(wpa_s);
1475 else
1476 wpas_dpp_start_gas_client(wpa_s);
1477}
1478
1479
1480static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001481 const u8 *hdr, const u8 *buf, size_t len,
1482 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001483{
1484 struct dpp_authentication *auth = wpa_s->dpp_auth;
1485 struct wpabuf *msg;
1486
Roshan Pius3a1667e2018-07-03 15:17:14 -07001487 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1488 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001489
1490 if (!auth) {
1491 wpa_printf(MSG_DEBUG,
1492 "DPP: No DPP Authentication in progress - drop");
1493 return;
1494 }
1495
1496 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1497 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1498 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1499 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1500 return;
1501 }
1502
1503 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1504
Roshan Pius3a1667e2018-07-03 15:17:14 -07001505 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1506 wpa_printf(MSG_DEBUG,
1507 "DPP: Responder accepted request for different negotiation channel");
1508 auth->curr_freq = freq;
1509 }
1510
1511 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001512 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1513 if (!msg) {
1514 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1515 wpa_printf(MSG_DEBUG,
1516 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001517 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001518 offchannel_send_action_done(wpa_s);
1519 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1520 return;
1521 }
1522 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1523 return;
1524 }
1525 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1526
Roshan Pius3a1667e2018-07-03 15:17:14 -07001527 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1528 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001529 offchannel_send_action(wpa_s, auth->curr_freq,
1530 src, wpa_s->own_addr, broadcast,
1531 wpabuf_head(msg), wpabuf_len(msg),
1532 500, wpas_dpp_tx_status, 0);
1533 wpabuf_free(msg);
1534 wpa_s->dpp_auth_ok_on_ack = 1;
1535}
1536
1537
1538static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1539 const u8 *hdr, const u8 *buf, size_t len)
1540{
1541 struct dpp_authentication *auth = wpa_s->dpp_auth;
1542
1543 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1544 MAC2STR(src));
1545
1546 if (!auth) {
1547 wpa_printf(MSG_DEBUG,
1548 "DPP: No DPP Authentication in progress - drop");
1549 return;
1550 }
1551
1552 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1553 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1554 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1555 return;
1556 }
1557
1558 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1559 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001560 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001561 return;
1562 }
1563
1564 wpas_dpp_auth_success(wpa_s, 0);
1565}
1566
1567
1568static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
1569 const u8 *src,
1570 const u8 *buf, size_t len)
1571{
1572 struct wpa_ssid *ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001573 const u8 *connector, *trans_id, *status;
1574 u16 connector_len, trans_id_len, status_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001575 struct dpp_introduction intro;
1576 struct rsn_pmksa_cache_entry *entry;
1577 struct os_time now;
1578 struct os_reltime rnow;
1579 os_time_t expiry;
1580 unsigned int seconds;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001581 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001582
1583 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR,
1584 MAC2STR(src));
1585 if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) ||
1586 os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) {
1587 wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from "
1588 MACSTR " - drop", MAC2STR(src));
1589 return;
1590 }
1591 offchannel_send_action_done(wpa_s);
1592
1593 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1594 if (ssid == wpa_s->dpp_intro_network)
1595 break;
1596 }
1597 if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey ||
1598 !ssid->dpp_csign) {
1599 wpa_printf(MSG_DEBUG,
1600 "DPP: Profile not found for network introduction");
1601 return;
1602 }
1603
1604 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1605 &trans_id_len);
1606 if (!trans_id || trans_id_len != 1) {
1607 wpa_printf(MSG_DEBUG,
1608 "DPP: Peer did not include Transaction ID");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001609 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1610 " fail=missing_transaction_id", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001611 goto fail;
1612 }
1613 if (trans_id[0] != TRANSACTION_ID) {
1614 wpa_printf(MSG_DEBUG,
1615 "DPP: Ignore frame with unexpected Transaction ID %u",
1616 trans_id[0]);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001617 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1618 " fail=transaction_id_mismatch", MAC2STR(src));
1619 goto fail;
1620 }
1621
1622 status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len);
1623 if (!status || status_len != 1) {
1624 wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status");
1625 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1626 " fail=missing_status", MAC2STR(src));
1627 goto fail;
1628 }
1629 if (status[0] != DPP_STATUS_OK) {
1630 wpa_printf(MSG_DEBUG,
1631 "DPP: Peer rejected network introduction: Status %u",
1632 status[0]);
1633 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1634 " status=%u", MAC2STR(src), status[0]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001635 goto fail;
1636 }
1637
1638 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1639 if (!connector) {
1640 wpa_printf(MSG_DEBUG,
1641 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001642 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1643 " fail=missing_connector", MAC2STR(src));
1644 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001645 }
1646
Roshan Pius3a1667e2018-07-03 15:17:14 -07001647 res = dpp_peer_intro(&intro, ssid->dpp_connector,
1648 ssid->dpp_netaccesskey,
1649 ssid->dpp_netaccesskey_len,
1650 ssid->dpp_csign,
1651 ssid->dpp_csign_len,
1652 connector, connector_len, &expiry);
1653 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001654 wpa_printf(MSG_INFO,
1655 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001656 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1657 " fail=peer_connector_validation_failed", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001658 goto fail;
1659 }
1660
1661 entry = os_zalloc(sizeof(*entry));
1662 if (!entry)
1663 goto fail;
1664 os_memcpy(entry->aa, src, ETH_ALEN);
1665 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
1666 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
1667 entry->pmk_len = intro.pmk_len;
1668 entry->akmp = WPA_KEY_MGMT_DPP;
1669 if (expiry) {
1670 os_get_time(&now);
1671 seconds = expiry - now.sec;
1672 } else {
1673 seconds = 86400 * 7;
1674 }
1675 os_get_reltime(&rnow);
1676 entry->expiration = rnow.sec + seconds;
1677 entry->reauth_time = rnow.sec + seconds;
1678 entry->network_ctx = ssid;
1679 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
1680
Roshan Pius3a1667e2018-07-03 15:17:14 -07001681 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1682 " status=%u", MAC2STR(src), status[0]);
1683
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001684 wpa_printf(MSG_DEBUG,
1685 "DPP: Try connection again after successful network introduction");
1686 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
1687 wpa_supplicant_cancel_sched_scan(wpa_s);
1688 wpa_supplicant_req_scan(wpa_s, 0, 0);
1689 }
1690fail:
1691 os_memset(&intro, 0, sizeof(intro));
1692}
1693
1694
Roshan Pius3a1667e2018-07-03 15:17:14 -07001695static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
1696{
1697 int i, j;
1698
1699 if (!wpa_s->hw.modes)
1700 return -1;
1701
1702 for (i = 0; i < wpa_s->hw.num_modes; i++) {
1703 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
1704
1705 for (j = 0; j < mode->num_channels; j++) {
1706 struct hostapd_channel_data *chan = &mode->channels[j];
1707
1708 if (chan->freq != (int) freq)
1709 continue;
1710
1711 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
1712 HOSTAPD_CHAN_NO_IR |
1713 HOSTAPD_CHAN_RADAR))
1714 continue;
1715
1716 return 1;
1717 }
1718 }
1719
1720 wpa_printf(MSG_DEBUG,
1721 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
1722 freq);
1723
1724 return 0;
1725}
1726
1727
1728static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
1729 struct dpp_pkex *pkex)
1730{
1731 if (pkex->freq == 2437)
1732 pkex->freq = 5745;
1733 else if (pkex->freq == 5745)
1734 pkex->freq = 5220;
1735 else if (pkex->freq == 5220)
1736 pkex->freq = 60480;
1737 else
1738 return -1; /* no more channels to try */
1739
1740 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
1741 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
1742 pkex->freq);
1743 return 0;
1744 }
1745
1746 /* Could not use this channel - try the next one */
1747 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
1748}
1749
1750
1751static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
1752{
1753 struct wpa_supplicant *wpa_s = eloop_ctx;
1754 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1755
1756 if (!pkex || !pkex->exchange_req)
1757 return;
1758 if (pkex->exch_req_tries >= 5) {
1759 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
1760 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1761 "No response from PKEX peer");
1762 dpp_pkex_free(pkex);
1763 wpa_s->dpp_pkex = NULL;
1764 return;
1765 }
1766 pkex->exch_req_tries = 0;
1767 }
1768
1769 pkex->exch_req_tries++;
1770 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
1771 pkex->exch_req_tries);
1772 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1773 MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
1774 offchannel_send_action(wpa_s, pkex->freq, broadcast,
1775 wpa_s->own_addr, broadcast,
1776 wpabuf_head(pkex->exchange_req),
1777 wpabuf_len(pkex->exchange_req),
1778 pkex->exch_req_wait_time,
1779 wpas_dpp_tx_pkex_status, 0);
1780}
1781
1782
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001783static void
1784wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
1785 unsigned int freq, const u8 *dst,
1786 const u8 *src, const u8 *bssid,
1787 const u8 *data, size_t data_len,
1788 enum offchannel_send_action_result result)
1789{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001790 const char *res_txt;
1791 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1792
1793 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
1794 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
1795 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001796 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
1797 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001798 freq, MAC2STR(dst), res_txt);
1799 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
1800 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
1801
1802 if (!pkex) {
1803 wpa_printf(MSG_DEBUG,
1804 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
1805 return;
1806 }
1807
1808 if (pkex->failed) {
1809 wpa_printf(MSG_DEBUG,
1810 "DPP: Terminate PKEX exchange due to an earlier error");
1811 if (pkex->t > pkex->own_bi->pkex_t)
1812 pkex->own_bi->pkex_t = pkex->t;
1813 dpp_pkex_free(pkex);
1814 wpa_s->dpp_pkex = NULL;
1815 return;
1816 }
1817
1818 if (pkex->exch_req_wait_time && pkex->exchange_req) {
1819 /* Wait for PKEX Exchange Response frame and retry request if
1820 * no response is seen. */
1821 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1822 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
1823 (pkex->exch_req_wait_time % 1000) * 1000,
1824 wpas_dpp_pkex_retry_timeout, wpa_s,
1825 NULL);
1826 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001827}
1828
1829
1830static void
1831wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
1832 const u8 *buf, size_t len, unsigned int freq)
1833{
1834 struct wpabuf *msg;
1835 unsigned int wait_time;
1836
1837 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1838 MAC2STR(src));
1839
1840 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1841 * values here */
1842
1843 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
1844 wpa_printf(MSG_DEBUG,
1845 "DPP: No PKEX code configured - ignore request");
1846 return;
1847 }
1848
1849 if (wpa_s->dpp_pkex) {
1850 /* TODO: Support parallel operations */
1851 wpa_printf(MSG_DEBUG,
1852 "DPP: Already in PKEX session - ignore new request");
1853 return;
1854 }
1855
Roshan Pius3a1667e2018-07-03 15:17:14 -07001856 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001857 wpa_s->own_addr, src,
1858 wpa_s->dpp_pkex_identifier,
1859 wpa_s->dpp_pkex_code,
1860 buf, len);
1861 if (!wpa_s->dpp_pkex) {
1862 wpa_printf(MSG_DEBUG,
1863 "DPP: Failed to process the request - ignore it");
1864 return;
1865 }
1866
1867 msg = wpa_s->dpp_pkex->exchange_resp;
1868 wait_time = wpa_s->max_remain_on_chan;
1869 if (wait_time > 2000)
1870 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001871 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1872 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001873 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1874 broadcast,
1875 wpabuf_head(msg), wpabuf_len(msg),
1876 wait_time, wpas_dpp_tx_pkex_status, 0);
1877}
1878
1879
1880static void
1881wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
1882 const u8 *buf, size_t len, unsigned int freq)
1883{
1884 struct wpabuf *msg;
1885 unsigned int wait_time;
1886
1887 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1888 MAC2STR(src));
1889
1890 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1891 * values here */
1892
1893 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
1894 wpa_s->dpp_pkex->exchange_done) {
1895 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1896 return;
1897 }
1898
Roshan Pius3a1667e2018-07-03 15:17:14 -07001899 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1900 wpa_s->dpp_pkex->exch_req_wait_time = 0;
1901
1902 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001903 if (!msg) {
1904 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1905 return;
1906 }
1907
1908 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1909 MAC2STR(src));
1910
1911 wait_time = wpa_s->max_remain_on_chan;
1912 if (wait_time > 2000)
1913 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001914 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1915 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001916 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1917 broadcast,
1918 wpabuf_head(msg), wpabuf_len(msg),
1919 wait_time, wpas_dpp_tx_pkex_status, 0);
1920 wpabuf_free(msg);
1921}
1922
1923
Roshan Pius3a1667e2018-07-03 15:17:14 -07001924static struct dpp_bootstrap_info *
1925wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
1926 unsigned int freq)
1927{
1928 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1929 struct dpp_bootstrap_info *bi;
1930
1931 bi = os_zalloc(sizeof(*bi));
1932 if (!bi)
1933 return NULL;
1934 bi->id = wpas_dpp_next_id(wpa_s);
1935 bi->type = DPP_BOOTSTRAP_PKEX;
1936 os_memcpy(bi->mac_addr, peer, ETH_ALEN);
1937 bi->num_freq = 1;
1938 bi->freq[0] = freq;
1939 bi->curve = pkex->own_bi->curve;
1940 bi->pubkey = pkex->peer_bootstrap_key;
1941 pkex->peer_bootstrap_key = NULL;
1942 dpp_pkex_free(pkex);
1943 wpa_s->dpp_pkex = NULL;
1944 if (dpp_bootstrap_key_hash(bi) < 0) {
1945 dpp_bootstrap_info_free(bi);
1946 return NULL;
1947 }
1948 dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
1949 return bi;
1950}
1951
1952
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001953static void
1954wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
1955 const u8 *hdr, const u8 *buf, size_t len,
1956 unsigned int freq)
1957{
1958 struct wpabuf *msg;
1959 unsigned int wait_time;
1960 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001961
1962 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1963 MAC2STR(src));
1964
1965 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1966 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1967 return;
1968 }
1969
1970 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1971 if (!msg) {
1972 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001973 if (pkex->failed) {
1974 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1975 if (pkex->t > pkex->own_bi->pkex_t)
1976 pkex->own_bi->pkex_t = pkex->t;
1977 dpp_pkex_free(wpa_s->dpp_pkex);
1978 wpa_s->dpp_pkex = NULL;
1979 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001980 return;
1981 }
1982
1983 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1984 MACSTR, MAC2STR(src));
1985
1986 wait_time = wpa_s->max_remain_on_chan;
1987 if (wait_time > 2000)
1988 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001989 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1990 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001991 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1992 broadcast,
1993 wpabuf_head(msg), wpabuf_len(msg),
1994 wait_time, wpas_dpp_tx_pkex_status, 0);
1995 wpabuf_free(msg);
1996
Roshan Pius3a1667e2018-07-03 15:17:14 -07001997 wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001998}
1999
2000
2001static void
2002wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2003 const u8 *hdr, const u8 *buf, size_t len,
2004 unsigned int freq)
2005{
2006 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002007 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002008 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2009 char cmd[500];
2010
2011 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2012 MAC2STR(src));
2013
2014 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2015 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2016 return;
2017 }
2018
2019 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2020 if (res < 0) {
2021 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2022 return;
2023 }
2024
Roshan Pius3a1667e2018-07-03 15:17:14 -07002025 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002026 if (!bi)
2027 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002028
2029 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2030 bi->id,
2031 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
2032 wpa_printf(MSG_DEBUG,
2033 "DPP: Start authentication after PKEX with parameters: %s",
2034 cmd);
2035 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
2036 wpa_printf(MSG_DEBUG,
2037 "DPP: Authentication initialization failed");
2038 return;
2039 }
2040}
2041
2042
2043void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
2044 const u8 *buf, size_t len, unsigned int freq)
2045{
2046 u8 crypto_suite;
2047 enum dpp_public_action_frame_type type;
2048 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002049 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002050
2051 if (len < DPP_HDR_LEN)
2052 return;
2053 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2054 return;
2055 hdr = buf;
2056 buf += 4;
2057 len -= 4;
2058 crypto_suite = *buf++;
2059 type = *buf++;
2060 len -= 2;
2061
2062 wpa_printf(MSG_DEBUG,
2063 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2064 MACSTR " freq=%u",
2065 crypto_suite, type, MAC2STR(src), freq);
2066 if (crypto_suite != 1) {
2067 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2068 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002069 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2070 " freq=%u type=%d ignore=unsupported-crypto-suite",
2071 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002072 return;
2073 }
2074 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002075 if (dpp_check_attrs(buf, len) < 0) {
2076 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2077 " freq=%u type=%d ignore=invalid-attributes",
2078 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002079 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002080 }
2081 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
2082 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002083
2084 switch (type) {
2085 case DPP_PA_AUTHENTICATION_REQ:
2086 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
2087 break;
2088 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002089 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002090 break;
2091 case DPP_PA_AUTHENTICATION_CONF:
2092 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
2093 break;
2094 case DPP_PA_PEER_DISCOVERY_RESP:
2095 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
2096 break;
2097 case DPP_PA_PKEX_EXCHANGE_REQ:
2098 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
2099 break;
2100 case DPP_PA_PKEX_EXCHANGE_RESP:
2101 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
2102 break;
2103 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2104 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
2105 freq);
2106 break;
2107 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2108 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
2109 freq);
2110 break;
2111 default:
2112 wpa_printf(MSG_DEBUG,
2113 "DPP: Ignored unsupported frame subtype %d", type);
2114 break;
2115 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002116
2117 if (wpa_s->dpp_pkex)
2118 pkex_t = wpa_s->dpp_pkex->t;
2119 else if (wpa_s->dpp_pkex_bi)
2120 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
2121 else
2122 pkex_t = 0;
2123 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2124 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2125 wpas_dpp_pkex_remove(wpa_s, "*");
2126 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002127}
2128
2129
2130static struct wpabuf *
2131wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query,
2132 size_t query_len)
2133{
2134 struct wpa_supplicant *wpa_s = ctx;
2135 struct dpp_authentication *auth = wpa_s->dpp_auth;
2136 struct wpabuf *resp;
2137
2138 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
2139 MAC2STR(sa));
2140 if (!auth || !auth->auth_success ||
2141 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
2142 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2143 return NULL;
2144 }
2145 wpa_hexdump(MSG_DEBUG,
2146 "DPP: Received Configuration Request (GAS Query Request)",
2147 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002148 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2149 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002150 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom59532852018-12-07 10:32:58 -08002151 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002152 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002153 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002154 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002155 auth->conf_resp = resp;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002156 return resp;
2157}
2158
2159
2160static void
2161wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
2162{
2163 struct wpa_supplicant *wpa_s = ctx;
2164 struct dpp_authentication *auth = wpa_s->dpp_auth;
2165
2166 if (!auth) {
2167 wpabuf_free(resp);
2168 return;
2169 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002170 if (auth->conf_resp != resp) {
2171 wpa_printf(MSG_DEBUG,
2172 "DPP: Ignore GAS status report (ok=%d) for unknown response",
2173 ok);
2174 wpabuf_free(resp);
2175 return;
2176 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002177
2178 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2179 ok);
2180 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002181 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002182 offchannel_send_action_done(wpa_s);
2183 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002184 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002185 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08002186 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002187 }
2188 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002189 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002190 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002191 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002192 dpp_auth_deinit(wpa_s->dpp_auth);
2193 wpa_s->dpp_auth = NULL;
2194 wpabuf_free(resp);
2195}
2196
2197
2198static unsigned int wpas_dpp_next_configurator_id(struct wpa_supplicant *wpa_s)
2199{
2200 struct dpp_configurator *conf;
2201 unsigned int max_id = 0;
2202
2203 dl_list_for_each(conf, &wpa_s->dpp_configurator,
2204 struct dpp_configurator, list) {
2205 if (conf->id > max_id)
2206 max_id = conf->id;
2207 }
2208 return max_id + 1;
2209}
2210
2211
2212int wpas_dpp_configurator_add(struct wpa_supplicant *wpa_s, const char *cmd)
2213{
2214 char *curve = NULL;
2215 char *key = NULL;
2216 u8 *privkey = NULL;
2217 size_t privkey_len = 0;
2218 int ret = -1;
2219 struct dpp_configurator *conf = NULL;
2220
2221 curve = get_param(cmd, " curve=");
2222 key = get_param(cmd, " key=");
2223
2224 if (key) {
2225 privkey_len = os_strlen(key) / 2;
2226 privkey = os_malloc(privkey_len);
2227 if (!privkey ||
2228 hexstr2bin(key, privkey, privkey_len) < 0)
2229 goto fail;
2230 }
2231
2232 conf = dpp_keygen_configurator(curve, privkey, privkey_len);
2233 if (!conf)
2234 goto fail;
2235
2236 conf->id = wpas_dpp_next_configurator_id(wpa_s);
2237 dl_list_add(&wpa_s->dpp_configurator, &conf->list);
2238 ret = conf->id;
2239 conf = NULL;
2240fail:
2241 os_free(curve);
2242 str_clear_free(key);
2243 bin_clear_free(privkey, privkey_len);
2244 dpp_configurator_free(conf);
2245 return ret;
2246}
2247
2248
2249static int dpp_configurator_del(struct wpa_supplicant *wpa_s, unsigned int id)
2250{
2251 struct dpp_configurator *conf, *tmp;
2252 int found = 0;
2253
2254 dl_list_for_each_safe(conf, tmp, &wpa_s->dpp_configurator,
2255 struct dpp_configurator, list) {
2256 if (id && conf->id != id)
2257 continue;
2258 found = 1;
2259 dl_list_del(&conf->list);
2260 dpp_configurator_free(conf);
2261 }
2262
2263 if (id == 0)
2264 return 0; /* flush succeeds regardless of entries found */
2265 return found ? 0 : -1;
2266}
2267
2268
2269int wpas_dpp_configurator_remove(struct wpa_supplicant *wpa_s, const char *id)
2270{
2271 unsigned int id_val;
2272
2273 if (os_strcmp(id, "*") == 0) {
2274 id_val = 0;
2275 } else {
2276 id_val = atoi(id);
2277 if (id_val == 0)
2278 return -1;
2279 }
2280
2281 return dpp_configurator_del(wpa_s, id_val);
2282}
2283
2284
2285int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
2286{
2287 struct dpp_authentication *auth;
2288 int ret = -1;
2289 char *curve = NULL;
2290
2291 auth = os_zalloc(sizeof(*auth));
2292 if (!auth)
2293 return -1;
2294
2295 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08002296 wpas_dpp_set_testing_options(wpa_s, auth);
2297 if (wpas_dpp_set_configurator(wpa_s, auth, cmd) == 0 &&
2298 dpp_configurator_own_config(auth, curve, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002299 wpas_dpp_handle_config_obj(wpa_s, auth);
2300 ret = 0;
2301 }
2302
2303 dpp_auth_deinit(auth);
2304 os_free(curve);
2305
2306 return ret;
2307}
2308
2309
Roshan Pius3a1667e2018-07-03 15:17:14 -07002310int wpas_dpp_configurator_get_key(struct wpa_supplicant *wpa_s, unsigned int id,
2311 char *buf, size_t buflen)
2312{
2313 struct dpp_configurator *conf;
2314
2315 conf = dpp_configurator_get_id(wpa_s, id);
2316 if (!conf)
2317 return -1;
2318
2319 return dpp_configurator_get_key(conf, buf, buflen);
2320}
2321
2322
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002323static void
2324wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
2325 unsigned int freq, const u8 *dst,
2326 const u8 *src, const u8 *bssid,
2327 const u8 *data, size_t data_len,
2328 enum offchannel_send_action_result result)
2329{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002330 const char *res_txt;
2331
2332 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2333 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2334 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002335 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2336 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002337 freq, MAC2STR(dst), res_txt);
2338 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2339 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002340 /* TODO: Time out wait for response more quickly in error cases? */
2341}
2342
2343
2344int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2345 struct wpa_bss *bss)
2346{
2347 struct os_time now;
2348 struct wpabuf *msg;
2349 unsigned int wait_time;
2350
2351 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
2352 return 0; /* Not using DPP AKM - continue */
2353 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
2354 return 0; /* PMKSA exists for DPP AKM - continue */
2355
2356 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2357 !ssid->dpp_csign) {
2358 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2359 "missing %s",
2360 !ssid->dpp_connector ? "Connector" :
2361 (!ssid->dpp_netaccesskey ? "netAccessKey" :
2362 "C-sign-key"));
2363 return -1;
2364 }
2365
2366 os_get_time(&now);
2367
2368 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002369 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002370 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2371 "netAccessKey expired");
2372 return -1;
2373 }
2374
2375 wpa_printf(MSG_DEBUG,
2376 "DPP: Starting network introduction protocol to derive PMKSA for "
2377 MACSTR, MAC2STR(bss->bssid));
2378
2379 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ,
2380 5 + 4 + os_strlen(ssid->dpp_connector));
2381 if (!msg)
2382 return -1;
2383
Roshan Pius3a1667e2018-07-03 15:17:14 -07002384#ifdef CONFIG_TESTING_OPTIONS
2385 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
2386 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
2387 goto skip_trans_id;
2388 }
2389 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
2390 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
2391 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2392 wpabuf_put_le16(msg, 0);
2393 goto skip_trans_id;
2394 }
2395#endif /* CONFIG_TESTING_OPTIONS */
2396
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002397 /* Transaction ID */
2398 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2399 wpabuf_put_le16(msg, 1);
2400 wpabuf_put_u8(msg, TRANSACTION_ID);
2401
Roshan Pius3a1667e2018-07-03 15:17:14 -07002402#ifdef CONFIG_TESTING_OPTIONS
2403skip_trans_id:
2404 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
2405 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
2406 goto skip_connector;
2407 }
2408 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
2409 char *connector;
2410
2411 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
2412 connector = dpp_corrupt_connector_signature(
2413 ssid->dpp_connector);
2414 if (!connector) {
2415 wpabuf_free(msg);
2416 return -1;
2417 }
2418 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2419 wpabuf_put_le16(msg, os_strlen(connector));
2420 wpabuf_put_str(msg, connector);
2421 os_free(connector);
2422 goto skip_connector;
2423 }
2424#endif /* CONFIG_TESTING_OPTIONS */
2425
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002426 /* DPP Connector */
2427 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2428 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
2429 wpabuf_put_str(msg, ssid->dpp_connector);
2430
Roshan Pius3a1667e2018-07-03 15:17:14 -07002431#ifdef CONFIG_TESTING_OPTIONS
2432skip_connector:
2433#endif /* CONFIG_TESTING_OPTIONS */
2434
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002435 /* TODO: Timeout on AP response */
2436 wait_time = wpa_s->max_remain_on_chan;
2437 if (wait_time > 2000)
2438 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002439 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2440 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002441 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
2442 broadcast,
2443 wpabuf_head(msg), wpabuf_len(msg),
2444 wait_time, wpas_dpp_tx_introduction_status, 0);
2445 wpabuf_free(msg);
2446
2447 /* Request this connection attempt to terminate - new one will be
2448 * started when network introduction protocol completes */
2449 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
2450 wpa_s->dpp_intro_network = ssid;
2451 return 1;
2452}
2453
2454
2455int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
2456{
2457 struct dpp_bootstrap_info *own_bi;
2458 const char *pos, *end;
2459 unsigned int wait_time;
2460
2461 pos = os_strstr(cmd, " own=");
2462 if (!pos)
2463 return -1;
2464 pos += 5;
2465 own_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
2466 if (!own_bi) {
2467 wpa_printf(MSG_DEBUG,
2468 "DPP: Identified bootstrap info not found");
2469 return -1;
2470 }
2471 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2472 wpa_printf(MSG_DEBUG,
2473 "DPP: Identified bootstrap info not for PKEX");
2474 return -1;
2475 }
2476 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002477 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002478
2479 os_free(wpa_s->dpp_pkex_identifier);
2480 wpa_s->dpp_pkex_identifier = NULL;
2481 pos = os_strstr(cmd, " identifier=");
2482 if (pos) {
2483 pos += 12;
2484 end = os_strchr(pos, ' ');
2485 if (!end)
2486 return -1;
2487 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
2488 if (!wpa_s->dpp_pkex_identifier)
2489 return -1;
2490 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
2491 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
2492 }
2493
2494 pos = os_strstr(cmd, " code=");
2495 if (!pos)
2496 return -1;
2497 os_free(wpa_s->dpp_pkex_code);
2498 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
2499 if (!wpa_s->dpp_pkex_code)
2500 return -1;
2501
2502 if (os_strstr(cmd, " init=1")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002503 struct dpp_pkex *pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002504 struct wpabuf *msg;
2505
2506 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
2507 dpp_pkex_free(wpa_s->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002508 wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002509 wpa_s->dpp_pkex_identifier,
2510 wpa_s->dpp_pkex_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002511 pkex = wpa_s->dpp_pkex;
2512 if (!pkex)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002513 return -1;
2514
Roshan Pius3a1667e2018-07-03 15:17:14 -07002515 msg = pkex->exchange_req;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002516 wait_time = wpa_s->max_remain_on_chan;
2517 if (wait_time > 2000)
2518 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002519 pkex->freq = 2437;
2520 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2521 " freq=%u type=%d",
2522 MAC2STR(broadcast), pkex->freq,
2523 DPP_PA_PKEX_EXCHANGE_REQ);
2524 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2525 wpa_s->own_addr, broadcast,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002526 wpabuf_head(msg), wpabuf_len(msg),
2527 wait_time, wpas_dpp_tx_pkex_status, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002528 if (wait_time == 0)
2529 wait_time = 2000;
2530 pkex->exch_req_wait_time = wait_time;
2531 pkex->exch_req_tries = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002532 }
2533
2534 /* TODO: Support multiple PKEX info entries */
2535
2536 os_free(wpa_s->dpp_pkex_auth_cmd);
2537 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
2538
2539 return 1;
2540}
2541
2542
2543int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
2544{
2545 unsigned int id_val;
2546
2547 if (os_strcmp(id, "*") == 0) {
2548 id_val = 0;
2549 } else {
2550 id_val = atoi(id);
2551 if (id_val == 0)
2552 return -1;
2553 }
2554
2555 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
2556 return -1;
2557
2558 /* TODO: Support multiple PKEX entries */
2559 os_free(wpa_s->dpp_pkex_code);
2560 wpa_s->dpp_pkex_code = NULL;
2561 os_free(wpa_s->dpp_pkex_identifier);
2562 wpa_s->dpp_pkex_identifier = NULL;
2563 os_free(wpa_s->dpp_pkex_auth_cmd);
2564 wpa_s->dpp_pkex_auth_cmd = NULL;
2565 wpa_s->dpp_pkex_bi = NULL;
2566 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2567 dpp_pkex_free(wpa_s->dpp_pkex);
2568 wpa_s->dpp_pkex = NULL;
2569 return 0;
2570}
2571
2572
Roshan Pius3a1667e2018-07-03 15:17:14 -07002573void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
2574{
2575 dpp_auth_deinit(wpa_s->dpp_auth);
2576 wpa_s->dpp_auth = NULL;
2577 dpp_pkex_free(wpa_s->dpp_pkex);
2578 wpa_s->dpp_pkex = NULL;
2579 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
2580 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
2581}
2582
2583
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002584int wpas_dpp_init(struct wpa_supplicant *wpa_s)
2585{
2586 u8 adv_proto_id[7];
2587
2588 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
2589 adv_proto_id[1] = 5;
2590 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
2591 adv_proto_id[5] = DPP_OUI_TYPE;
2592 adv_proto_id[6] = 0x01;
2593
2594 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
2595 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
2596 wpas_dpp_gas_status_handler, wpa_s) < 0)
2597 return -1;
2598 dl_list_init(&wpa_s->dpp_bootstrap);
2599 dl_list_init(&wpa_s->dpp_configurator);
2600 wpa_s->dpp_init_done = 1;
2601 return 0;
2602}
2603
2604
2605void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
2606{
2607#ifdef CONFIG_TESTING_OPTIONS
2608 os_free(wpa_s->dpp_config_obj_override);
2609 wpa_s->dpp_config_obj_override = NULL;
2610 os_free(wpa_s->dpp_discovery_override);
2611 wpa_s->dpp_discovery_override = NULL;
2612 os_free(wpa_s->dpp_groups_override);
2613 wpa_s->dpp_groups_override = NULL;
2614 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
2615#endif /* CONFIG_TESTING_OPTIONS */
2616 if (!wpa_s->dpp_init_done)
2617 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002618 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002619 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002620 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
2621 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002622 offchannel_send_action_done(wpa_s);
2623 wpas_dpp_listen_stop(wpa_s);
2624 dpp_bootstrap_del(wpa_s, 0);
2625 dpp_configurator_del(wpa_s, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002626 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002627 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002628 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
2629 os_free(wpa_s->dpp_configurator_params);
2630 wpa_s->dpp_configurator_params = NULL;
2631}