blob: 22ba9023ee510be2faa261de51555e900bce33cd [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 Shalombf6e0ba2019-02-11 12:01:50 -0800532static void 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 Shalombf6e0ba2019-02-11 12:01:50 -0800548 return;
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 Shalombf6e0ba2019-02-11 12:01:50 -0800612 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700613 conf_sta->passphrase = os_strdup(pass);
614 if (!conf_sta->passphrase)
615 goto fail;
616 }
617 } else if (os_strstr(cmd, " conf=sta-dpp")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700618 conf_sta->akm = DPP_AKM_DPP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700619 } else {
620 goto fail;
621 }
Hai Shalomce48b4a2018-09-05 11:41:35 -0700622 if (os_strstr(cmd, " group_id=")) {
623 conf_sta->group_id = group_id;
624 group_id = NULL;
625 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700626 }
627
628 if (os_strstr(cmd, " conf=ap-")) {
629 conf_ap = os_zalloc(sizeof(struct dpp_configuration));
630 if (!conf_ap)
631 goto fail;
632 os_memcpy(conf_ap->ssid, ssid, ssid_len);
633 conf_ap->ssid_len = ssid_len;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700634 if (os_strstr(cmd, " conf=ap-psk") ||
635 os_strstr(cmd, " conf=ap-sae") ||
636 os_strstr(cmd, " conf=ap-psk-sae")) {
637 if (os_strstr(cmd, " conf=ap-psk-sae"))
638 conf_ap->akm = DPP_AKM_PSK_SAE;
639 else if (os_strstr(cmd, " conf=ap-sae"))
640 conf_ap->akm = DPP_AKM_SAE;
641 else
642 conf_ap->akm = DPP_AKM_PSK;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700643 if (psk_set) {
644 os_memcpy(conf_ap->psk, psk, PMK_LEN);
645 } else {
646 conf_ap->passphrase = os_strdup(pass);
647 if (!conf_ap->passphrase)
648 goto fail;
649 }
650 } else if (os_strstr(cmd, " conf=ap-dpp")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700651 conf_ap->akm = DPP_AKM_DPP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700652 } else {
653 goto fail;
654 }
Hai Shalomce48b4a2018-09-05 11:41:35 -0700655 if (os_strstr(cmd, " group_id=")) {
656 conf_ap->group_id = group_id;
657 group_id = NULL;
658 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700659 }
660
661 pos = os_strstr(cmd, " expiry=");
662 if (pos) {
663 long int val;
664
665 pos += 8;
666 val = strtol(pos, NULL, 0);
667 if (val <= 0)
668 goto fail;
669 if (conf_sta)
670 conf_sta->netaccesskey_expiry = val;
671 if (conf_ap)
672 conf_ap->netaccesskey_expiry = val;
673 }
674
675 pos = os_strstr(cmd, " configurator=");
676 if (pos) {
677 pos += 14;
678 conf = dpp_configurator_get_id(wpa_s, atoi(pos));
679 if (!conf) {
680 wpa_printf(MSG_INFO,
681 "DPP: Could not find the specified configurator");
682 goto fail;
683 }
684 }
685 auth->conf_sta = conf_sta;
686 auth->conf_ap = conf_ap;
687 auth->conf = conf;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700688 os_free(group_id);
Hai Shalombf6e0ba2019-02-11 12:01:50 -0800689 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700690
691fail:
Hai Shalombf6e0ba2019-02-11 12:01:50 -0800692 wpa_printf(MSG_DEBUG, "DPP: Failed to set configurator parameters");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700693 dpp_configuration_free(conf_sta);
694 dpp_configuration_free(conf_ap);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700695 os_free(group_id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700696}
697
698
Roshan Pius3a1667e2018-07-03 15:17:14 -0700699static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
700{
701 struct wpa_supplicant *wpa_s = eloop_ctx;
702
703 if (!wpa_s->dpp_auth)
704 return;
705 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
706 wpas_dpp_auth_init_next(wpa_s);
707}
708
709
710static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
711{
712 struct dpp_authentication *auth = wpa_s->dpp_auth;
713 const u8 *dst;
714 unsigned int wait_time, max_wait_time, freq, max_tries, used;
715 struct os_reltime now, diff;
716
717 wpa_s->dpp_in_response_listen = 0;
718 if (!auth)
719 return -1;
720
721 if (auth->freq_idx == 0)
722 os_get_reltime(&wpa_s->dpp_init_iter_start);
723
724 if (auth->freq_idx >= auth->num_freq) {
725 auth->num_freq_iters++;
726 if (wpa_s->dpp_init_max_tries)
727 max_tries = wpa_s->dpp_init_max_tries;
728 else
729 max_tries = 5;
730 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
731 wpa_printf(MSG_INFO,
732 "DPP: No response received from responder - stopping initiation attempt");
733 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -0800734 wpas_notify_dpp_timeout(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700735 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout,
736 wpa_s, NULL);
737 offchannel_send_action_done(wpa_s);
738 dpp_auth_deinit(wpa_s->dpp_auth);
739 wpa_s->dpp_auth = NULL;
740 return -1;
741 }
742 auth->freq_idx = 0;
743 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
744 if (wpa_s->dpp_init_retry_time)
745 wait_time = wpa_s->dpp_init_retry_time;
746 else
747 wait_time = 10000;
748 os_get_reltime(&now);
749 os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff);
750 used = diff.sec * 1000 + diff.usec / 1000;
751 if (used > wait_time)
752 wait_time = 0;
753 else
754 wait_time -= used;
755 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
756 wait_time);
757 eloop_register_timeout(wait_time / 1000,
758 (wait_time % 1000) * 1000,
759 wpas_dpp_init_timeout, wpa_s,
760 NULL);
761 return 0;
762 }
763 freq = auth->freq[auth->freq_idx++];
764 auth->curr_freq = freq;
765
766 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
767 dst = broadcast;
768 else
769 dst = auth->peer_bi->mac_addr;
770 wpa_s->dpp_auth_ok_on_ack = 0;
771 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
772 wait_time = wpa_s->max_remain_on_chan;
773 max_wait_time = wpa_s->dpp_resp_wait_time ?
774 wpa_s->dpp_resp_wait_time : 2000;
775 if (wait_time > max_wait_time)
776 wait_time = max_wait_time;
777 wait_time += 10; /* give the driver some extra time to complete */
778 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
779 wpas_dpp_reply_wait_timeout,
780 wpa_s, NULL);
781 wait_time -= 10;
782 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
783 wpa_printf(MSG_DEBUG,
784 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
785 freq, auth->neg_freq);
786 }
787 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
788 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
789 auth->auth_req_ack = 0;
790 os_get_reltime(&wpa_s->dpp_last_init);
791 return offchannel_send_action(wpa_s, freq, dst,
792 wpa_s->own_addr, broadcast,
793 wpabuf_head(auth->req_msg),
794 wpabuf_len(auth->req_msg),
795 wait_time, wpas_dpp_tx_status, 0);
796}
797
798
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700799int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
800{
801 const char *pos;
802 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700803 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
804 unsigned int neg_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700805
806 wpa_s->dpp_gas_client = 0;
807
808 pos = os_strstr(cmd, " peer=");
809 if (!pos)
810 return -1;
811 pos += 6;
812 peer_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
813 if (!peer_bi) {
814 wpa_printf(MSG_INFO,
815 "DPP: Could not find bootstrapping info for the identified peer");
816 return -1;
817 }
818
819 pos = os_strstr(cmd, " own=");
820 if (pos) {
821 pos += 5;
822 own_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
823 if (!own_bi) {
824 wpa_printf(MSG_INFO,
825 "DPP: Could not find bootstrapping info for the identified local entry");
826 return -1;
827 }
828
829 if (peer_bi->curve != own_bi->curve) {
830 wpa_printf(MSG_INFO,
831 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
832 peer_bi->curve->name, own_bi->curve->name);
833 return -1;
834 }
835 }
836
837 pos = os_strstr(cmd, " role=");
838 if (pos) {
839 pos += 6;
840 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700841 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700842 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700843 allowed_roles = DPP_CAPAB_ENROLLEE;
844 else if (os_strncmp(pos, "either", 6) == 0)
845 allowed_roles = DPP_CAPAB_CONFIGURATOR |
846 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700847 else
848 goto fail;
849 }
850
851 pos = os_strstr(cmd, " netrole=");
852 if (pos) {
853 pos += 9;
854 wpa_s->dpp_netrole_ap = os_strncmp(pos, "ap", 2) == 0;
855 }
856
Roshan Pius3a1667e2018-07-03 15:17:14 -0700857 pos = os_strstr(cmd, " neg_freq=");
858 if (pos)
859 neg_freq = atoi(pos + 10);
860
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700861 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700862 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700863 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700864 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
865 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700866 offchannel_send_action_done(wpa_s);
867 dpp_auth_deinit(wpa_s->dpp_auth);
868 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700869 wpa_s->dpp_auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles,
870 neg_freq,
871 wpa_s->hw.modes, wpa_s->hw.num_modes);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700872 if (!wpa_s->dpp_auth)
873 goto fail;
874 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalombf6e0ba2019-02-11 12:01:50 -0800875 wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700876
Roshan Pius3a1667e2018-07-03 15:17:14 -0700877 wpa_s->dpp_auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700878
Roshan Pius3a1667e2018-07-03 15:17:14 -0700879 if (!is_zero_ether_addr(peer_bi->mac_addr))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700880 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
881 ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700882
Roshan Pius3a1667e2018-07-03 15:17:14 -0700883 return wpas_dpp_auth_init_next(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700884fail:
885 return -1;
886}
887
888
889struct wpas_dpp_listen_work {
890 unsigned int freq;
891 unsigned int duration;
892 struct wpabuf *probe_resp_ie;
893};
894
895
896static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork)
897{
898 if (!lwork)
899 return;
900 os_free(lwork);
901}
902
903
904static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s)
905{
906 struct wpas_dpp_listen_work *lwork;
907
908 if (!wpa_s->dpp_listen_work)
909 return;
910
911 lwork = wpa_s->dpp_listen_work->ctx;
912 wpas_dpp_listen_work_free(lwork);
913 radio_work_done(wpa_s->dpp_listen_work);
914 wpa_s->dpp_listen_work = NULL;
915}
916
917
918static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit)
919{
920 struct wpa_supplicant *wpa_s = work->wpa_s;
921 struct wpas_dpp_listen_work *lwork = work->ctx;
922
923 if (deinit) {
924 if (work->started) {
925 wpa_s->dpp_listen_work = NULL;
926 wpas_dpp_listen_stop(wpa_s);
927 }
928 wpas_dpp_listen_work_free(lwork);
929 return;
930 }
931
932 wpa_s->dpp_listen_work = work;
933
934 wpa_s->dpp_pending_listen_freq = lwork->freq;
935
936 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq,
937 wpa_s->max_remain_on_chan) < 0) {
938 wpa_printf(MSG_DEBUG,
939 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
940 lwork->freq);
941 wpas_dpp_listen_work_done(wpa_s);
942 wpa_s->dpp_pending_listen_freq = 0;
943 return;
944 }
945 wpa_s->off_channel_freq = 0;
946 wpa_s->roc_waiting_drv_freq = lwork->freq;
947}
948
949
950static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
951 unsigned int freq)
952{
953 struct wpas_dpp_listen_work *lwork;
954
955 if (wpa_s->dpp_listen_work) {
956 wpa_printf(MSG_DEBUG,
957 "DPP: Reject start_listen since dpp_listen_work already exists");
958 return -1;
959 }
960
961 if (wpa_s->dpp_listen_freq)
962 wpas_dpp_listen_stop(wpa_s);
963 wpa_s->dpp_listen_freq = freq;
964
965 lwork = os_zalloc(sizeof(*lwork));
966 if (!lwork)
967 return -1;
968 lwork->freq = freq;
969
970 if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb,
971 lwork) < 0) {
972 wpas_dpp_listen_work_free(lwork);
973 return -1;
974 }
975
976 return 0;
977}
978
979
980int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd)
981{
982 int freq;
983
984 freq = atoi(cmd);
985 if (freq <= 0)
986 return -1;
987
988 if (os_strstr(cmd, " role=configurator"))
989 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
990 else if (os_strstr(cmd, " role=enrollee"))
991 wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
992 else
993 wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
994 DPP_CAPAB_ENROLLEE;
995 wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
996 wpa_s->dpp_netrole_ap = os_strstr(cmd, " netrole=ap") != NULL;
997 if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
998 wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
999 freq);
1000 return 0;
1001 }
1002
1003 return wpas_dpp_listen_start(wpa_s, freq);
1004}
1005
1006
1007void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
1008{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001009 wpa_s->dpp_in_response_listen = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001010 if (!wpa_s->dpp_listen_freq)
1011 return;
1012
1013 wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz",
1014 wpa_s->dpp_listen_freq);
1015 wpa_drv_cancel_remain_on_channel(wpa_s);
1016 wpa_s->dpp_listen_freq = 0;
1017 wpas_dpp_listen_work_done(wpa_s);
1018}
1019
1020
Hai Shalombf6e0ba2019-02-11 12:01:50 -08001021void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1022 unsigned int freq)
1023{
1024 if (!wpa_s->dpp_listen_freq && !wpa_s->dpp_pending_listen_freq)
1025 return;
1026
1027 wpa_printf(MSG_DEBUG,
1028 "DPP: remain-on-channel callback (off_channel_freq=%u dpp_pending_listen_freq=%d roc_waiting_drv_freq=%d freq=%u)",
1029 wpa_s->off_channel_freq, wpa_s->dpp_pending_listen_freq,
1030 wpa_s->roc_waiting_drv_freq, freq);
1031 if (wpa_s->off_channel_freq &&
1032 wpa_s->off_channel_freq == wpa_s->dpp_pending_listen_freq) {
1033 wpa_printf(MSG_DEBUG, "DPP: Listen on %u MHz started", freq);
1034 wpa_s->dpp_pending_listen_freq = 0;
1035 } else {
1036 wpa_printf(MSG_DEBUG,
1037 "DPP: Ignore remain-on-channel callback (off_channel_freq=%u dpp_pending_listen_freq=%d freq=%u)",
1038 wpa_s->off_channel_freq,
1039 wpa_s->dpp_pending_listen_freq, freq);
1040 }
1041}
1042
1043
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001044void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
1045 unsigned int freq)
1046{
1047 wpas_dpp_listen_work_done(wpa_s);
1048
Roshan Pius3a1667e2018-07-03 15:17:14 -07001049 if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) {
1050 unsigned int new_freq;
1051
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001052 /* Continue listen with a new remain-on-channel */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001053 if (wpa_s->dpp_auth->neg_freq > 0)
1054 new_freq = wpa_s->dpp_auth->neg_freq;
1055 else
1056 new_freq = wpa_s->dpp_auth->curr_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001057 wpa_printf(MSG_DEBUG,
1058 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001059 new_freq);
1060 wpas_dpp_listen_start(wpa_s, new_freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001061 return;
1062 }
1063
1064 if (wpa_s->dpp_listen_freq) {
1065 /* Continue listen with a new remain-on-channel */
1066 wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq);
1067 }
1068}
1069
1070
1071static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
1072 const u8 *hdr, const u8 *buf, size_t len,
1073 unsigned int freq)
1074{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001075 const u8 *r_bootstrap, *i_bootstrap;
1076 u16 r_bootstrap_len, i_bootstrap_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001077 struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL;
1078
1079 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
1080 MAC2STR(src));
1081
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001082 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
1083 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001084 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
1085 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1086 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001087 return;
1088 }
1089 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
1090 r_bootstrap, r_bootstrap_len);
1091
1092 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
1093 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001094 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
1095 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1096 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001097 return;
1098 }
1099 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
1100 i_bootstrap, i_bootstrap_len);
1101
1102 /* Try to find own and peer bootstrapping key matches based on the
1103 * received hash values */
1104 dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
1105 list) {
1106 if (!own_bi && bi->own &&
1107 os_memcmp(bi->pubkey_hash, r_bootstrap,
1108 SHA256_MAC_LEN) == 0) {
1109 wpa_printf(MSG_DEBUG,
1110 "DPP: Found matching own bootstrapping information");
1111 own_bi = bi;
1112 }
1113
1114 if (!peer_bi && !bi->own &&
1115 os_memcmp(bi->pubkey_hash, i_bootstrap,
1116 SHA256_MAC_LEN) == 0) {
1117 wpa_printf(MSG_DEBUG,
1118 "DPP: Found matching peer bootstrapping information");
1119 peer_bi = bi;
1120 }
1121
1122 if (own_bi && peer_bi)
1123 break;
1124 }
1125
1126 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001127 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1128 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001129 return;
1130 }
1131
1132 if (wpa_s->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001133 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1134 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001135 return;
1136 }
1137
1138 wpa_s->dpp_gas_client = 0;
1139 wpa_s->dpp_auth_ok_on_ack = 0;
1140 wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles,
1141 wpa_s->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001142 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001143 if (!wpa_s->dpp_auth) {
1144 wpa_printf(MSG_DEBUG, "DPP: No response generated");
1145 return;
1146 }
1147 wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
Hai Shalombf6e0ba2019-02-11 12:01:50 -08001148 wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth,
1149 wpa_s->dpp_configurator_params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001150 os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
1151
Roshan Pius3a1667e2018-07-03 15:17:14 -07001152 if (wpa_s->dpp_listen_freq &&
1153 wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) {
1154 wpa_printf(MSG_DEBUG,
1155 "DPP: Stop listen on %u MHz to allow response on the request %u MHz",
1156 wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq);
1157 wpas_dpp_listen_stop(wpa_s);
1158 }
1159
1160 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1161 MAC2STR(src), wpa_s->dpp_auth->curr_freq,
1162 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001163 offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq,
1164 src, wpa_s->own_addr, broadcast,
1165 wpabuf_head(wpa_s->dpp_auth->resp_msg),
1166 wpabuf_len(wpa_s->dpp_auth->resp_msg),
1167 500, wpas_dpp_tx_status, 0);
1168}
1169
1170
1171static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s)
1172{
1173 /* TODO: stop wait and start ROC */
1174}
1175
1176
1177static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
1178 struct dpp_authentication *auth)
1179{
1180 struct wpa_ssid *ssid;
1181
1182 ssid = wpa_config_add_network(wpa_s->conf);
1183 if (!ssid)
1184 return NULL;
1185 wpas_notify_network_added(wpa_s, ssid);
1186 wpa_config_set_network_defaults(ssid);
1187 ssid->disabled = 1;
1188
1189 ssid->ssid = os_malloc(auth->ssid_len);
1190 if (!ssid->ssid)
1191 goto fail;
1192 os_memcpy(ssid->ssid, auth->ssid, auth->ssid_len);
1193 ssid->ssid_len = auth->ssid_len;
1194
1195 if (auth->connector) {
1196 ssid->key_mgmt = WPA_KEY_MGMT_DPP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001197 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001198 ssid->dpp_connector = os_strdup(auth->connector);
1199 if (!ssid->dpp_connector)
1200 goto fail;
1201 }
1202
1203 if (auth->c_sign_key) {
1204 ssid->dpp_csign = os_malloc(wpabuf_len(auth->c_sign_key));
1205 if (!ssid->dpp_csign)
1206 goto fail;
1207 os_memcpy(ssid->dpp_csign, wpabuf_head(auth->c_sign_key),
1208 wpabuf_len(auth->c_sign_key));
1209 ssid->dpp_csign_len = wpabuf_len(auth->c_sign_key);
1210 }
1211
1212 if (auth->net_access_key) {
1213 ssid->dpp_netaccesskey =
1214 os_malloc(wpabuf_len(auth->net_access_key));
1215 if (!ssid->dpp_netaccesskey)
1216 goto fail;
1217 os_memcpy(ssid->dpp_netaccesskey,
1218 wpabuf_head(auth->net_access_key),
1219 wpabuf_len(auth->net_access_key));
1220 ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key);
1221 ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry;
1222 }
1223
1224 if (!auth->connector) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001225 ssid->key_mgmt = 0;
1226 if (auth->akm == DPP_AKM_PSK || auth->akm == DPP_AKM_PSK_SAE)
1227 ssid->key_mgmt |= WPA_KEY_MGMT_PSK |
1228 WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK;
1229 if (auth->akm == DPP_AKM_SAE || auth->akm == DPP_AKM_PSK_SAE)
1230 ssid->key_mgmt |= WPA_KEY_MGMT_SAE |
1231 WPA_KEY_MGMT_FT_SAE;
1232 ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001233 if (auth->passphrase[0]) {
1234 if (wpa_config_set_quoted(ssid, "psk",
1235 auth->passphrase) < 0)
1236 goto fail;
1237 wpa_config_update_psk(ssid);
1238 ssid->export_keys = 1;
1239 } else {
1240 ssid->psk_set = auth->psk_set;
1241 os_memcpy(ssid->psk, auth->psk, PMK_LEN);
1242 }
1243 }
1244
1245 return ssid;
1246fail:
1247 wpas_notify_network_removed(wpa_s, ssid);
1248 wpa_config_remove_network(wpa_s->conf, ssid->id);
1249 return NULL;
1250}
1251
1252
1253static void wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
1254 struct dpp_authentication *auth)
1255{
1256 struct wpa_ssid *ssid;
1257
1258 if (wpa_s->conf->dpp_config_processing < 1)
1259 return;
1260
1261 ssid = wpas_dpp_add_network(wpa_s, auth);
1262 if (!ssid)
1263 return;
1264
1265 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
Hai Shalom59532852018-12-07 10:32:58 -08001266
Hai Shalom706f99b2019-01-08 16:23:37 -08001267 wpas_notify_dpp_config_received(wpa_s, ssid);
Hai Shalom59532852018-12-07 10:32:58 -08001268
1269 if (wpa_s->conf->dpp_config_processing < 2) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001270 return;
Hai Shalom59532852018-12-07 10:32:58 -08001271 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001272
1273 wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
1274 ssid->disabled = 0;
1275 wpa_s->disconnected = 0;
1276 wpa_s->reassociate = 1;
1277 wpa_s->scan_runs = 0;
1278 wpa_s->normal_scans = 0;
1279 wpa_supplicant_cancel_sched_scan(wpa_s);
1280 wpa_supplicant_req_scan(wpa_s, 0, 0);
1281}
1282
1283
1284static void wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
1285 struct dpp_authentication *auth)
1286{
1287 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
1288 if (auth->ssid_len)
1289 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
1290 wpa_ssid_txt(auth->ssid, auth->ssid_len));
1291 if (auth->connector) {
1292 /* TODO: Save the Connector and consider using a command
1293 * to fetch the value instead of sending an event with
1294 * it. The Connector could end up being larger than what
1295 * most clients are ready to receive as an event
1296 * message. */
1297 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
1298 auth->connector);
1299 }
1300 if (auth->c_sign_key) {
1301 char *hex;
1302 size_t hexlen;
1303
1304 hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
1305 hex = os_malloc(hexlen);
1306 if (hex) {
1307 wpa_snprintf_hex(hex, hexlen,
1308 wpabuf_head(auth->c_sign_key),
1309 wpabuf_len(auth->c_sign_key));
1310 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s",
1311 hex);
1312 os_free(hex);
1313 }
1314 }
1315 if (auth->net_access_key) {
1316 char *hex;
1317 size_t hexlen;
1318
1319 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1320 hex = os_malloc(hexlen);
1321 if (hex) {
1322 wpa_snprintf_hex(hex, hexlen,
1323 wpabuf_head(auth->net_access_key),
1324 wpabuf_len(auth->net_access_key));
1325 if (auth->net_access_key_expiry)
1326 wpa_msg(wpa_s, MSG_INFO,
1327 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1328 (long unsigned)
1329 auth->net_access_key_expiry);
1330 else
1331 wpa_msg(wpa_s, MSG_INFO,
1332 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1333 os_free(hex);
1334 }
1335 }
1336
1337 wpas_dpp_process_config(wpa_s, auth);
1338}
1339
1340
1341static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1342 enum gas_query_result result,
1343 const struct wpabuf *adv_proto,
1344 const struct wpabuf *resp, u16 status_code)
1345{
1346 struct wpa_supplicant *wpa_s = ctx;
1347 const u8 *pos;
1348 struct dpp_authentication *auth = wpa_s->dpp_auth;
1349
Roshan Pius3a1667e2018-07-03 15:17:14 -07001350 wpa_s->dpp_gas_dialog_token = -1;
1351
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001352 if (!auth || !auth->auth_success) {
1353 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1354 return;
1355 }
Hai Shalombf6e0ba2019-02-11 12:01:50 -08001356 if (!resp || status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001357 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1358 goto fail;
1359 }
1360
1361 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1362 adv_proto);
1363 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1364 resp);
1365
1366 if (wpabuf_len(adv_proto) != 10 ||
1367 !(pos = wpabuf_head(adv_proto)) ||
1368 pos[0] != WLAN_EID_ADV_PROTO ||
1369 pos[1] != 8 ||
1370 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1371 pos[4] != 5 ||
1372 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1373 pos[8] != 0x1a ||
1374 pos[9] != 1) {
1375 wpa_printf(MSG_DEBUG,
1376 "DPP: Not a DPP Advertisement Protocol ID");
1377 goto fail;
1378 }
1379
1380 if (dpp_conf_resp_rx(auth, resp) < 0) {
1381 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1382 goto fail;
1383 }
1384
1385 wpas_dpp_handle_config_obj(wpa_s, auth);
1386 dpp_auth_deinit(wpa_s->dpp_auth);
1387 wpa_s->dpp_auth = NULL;
1388 return;
1389
1390fail:
1391 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08001392 wpas_notify_dpp_configuration_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001393 dpp_auth_deinit(wpa_s->dpp_auth);
1394 wpa_s->dpp_auth = NULL;
1395}
1396
1397
1398static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s)
1399{
1400 struct dpp_authentication *auth = wpa_s->dpp_auth;
1401 struct wpabuf *buf, *conf_req;
1402 char json[100];
1403 int res;
1404
1405 wpa_s->dpp_gas_client = 1;
1406 os_snprintf(json, sizeof(json),
1407 "{\"name\":\"Test\","
1408 "\"wi-fi_tech\":\"infra\","
1409 "\"netRole\":\"%s\"}",
1410 wpa_s->dpp_netrole_ap ? "ap" : "sta");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001411#ifdef CONFIG_TESTING_OPTIONS
1412 if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
1413 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Config Attr");
1414 json[29] = 'k'; /* replace "infra" with "knfra" */
1415 }
1416#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001417 wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
1418
1419 offchannel_send_action_done(wpa_s);
1420 wpas_dpp_listen_stop(wpa_s);
1421
1422 conf_req = dpp_build_conf_req(auth, json);
1423 if (!conf_req) {
1424 wpa_printf(MSG_DEBUG,
1425 "DPP: No configuration request data available");
1426 return;
1427 }
1428
1429 buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
1430 if (!buf) {
1431 wpabuf_free(conf_req);
1432 return;
1433 }
1434
1435 /* Advertisement Protocol IE */
1436 wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
1437 wpabuf_put_u8(buf, 8); /* Length */
1438 wpabuf_put_u8(buf, 0x7f);
1439 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
1440 wpabuf_put_u8(buf, 5);
1441 wpabuf_put_be24(buf, OUI_WFA);
1442 wpabuf_put_u8(buf, DPP_OUI_TYPE);
1443 wpabuf_put_u8(buf, 0x01);
1444
1445 /* GAS Query */
1446 wpabuf_put_le16(buf, wpabuf_len(conf_req));
1447 wpabuf_put_buf(buf, conf_req);
1448 wpabuf_free(conf_req);
1449
1450 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1451 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1452
1453 res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001454 1, buf, wpas_dpp_gas_resp_cb, wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001455 if (res < 0) {
1456 wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
1457 wpabuf_free(buf);
1458 } else {
1459 wpa_printf(MSG_DEBUG,
1460 "DPP: GAS query started with dialog token %u", res);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001461 wpa_s->dpp_gas_dialog_token = res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001462 }
1463}
1464
1465
1466static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator)
1467{
1468 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1469 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
Hai Shalom706f99b2019-01-08 16:23:37 -08001470 wpas_notify_dpp_auth_success(wpa_s);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001471#ifdef CONFIG_TESTING_OPTIONS
1472 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1473 wpa_printf(MSG_INFO,
1474 "DPP: TESTING - stop at Authentication Confirm");
1475 if (wpa_s->dpp_auth->configurator) {
1476 /* Prevent GAS response */
1477 wpa_s->dpp_auth->auth_success = 0;
1478 }
1479 return;
1480 }
1481#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001482
1483 if (wpa_s->dpp_auth->configurator)
1484 wpas_dpp_start_gas_server(wpa_s);
1485 else
1486 wpas_dpp_start_gas_client(wpa_s);
1487}
1488
1489
1490static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001491 const u8 *hdr, const u8 *buf, size_t len,
1492 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001493{
1494 struct dpp_authentication *auth = wpa_s->dpp_auth;
1495 struct wpabuf *msg;
1496
Roshan Pius3a1667e2018-07-03 15:17:14 -07001497 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR
1498 " (freq %u MHz)", MAC2STR(src), freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001499
1500 if (!auth) {
1501 wpa_printf(MSG_DEBUG,
1502 "DPP: No DPP Authentication in progress - drop");
1503 return;
1504 }
1505
1506 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1507 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1508 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1509 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1510 return;
1511 }
1512
1513 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
1514
Roshan Pius3a1667e2018-07-03 15:17:14 -07001515 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1516 wpa_printf(MSG_DEBUG,
1517 "DPP: Responder accepted request for different negotiation channel");
1518 auth->curr_freq = freq;
1519 }
1520
1521 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001522 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1523 if (!msg) {
1524 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1525 wpa_printf(MSG_DEBUG,
1526 "DPP: Start wait for full response");
Hai Shalom706f99b2019-01-08 16:23:37 -08001527 wpas_notify_dpp_resp_pending(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001528 offchannel_send_action_done(wpa_s);
1529 wpas_dpp_listen_start(wpa_s, auth->curr_freq);
1530 return;
1531 }
1532 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1533 return;
1534 }
1535 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1536
Roshan Pius3a1667e2018-07-03 15:17:14 -07001537 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1538 MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001539 offchannel_send_action(wpa_s, auth->curr_freq,
1540 src, wpa_s->own_addr, broadcast,
1541 wpabuf_head(msg), wpabuf_len(msg),
1542 500, wpas_dpp_tx_status, 0);
1543 wpabuf_free(msg);
1544 wpa_s->dpp_auth_ok_on_ack = 1;
1545}
1546
1547
1548static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
1549 const u8 *hdr, const u8 *buf, size_t len)
1550{
1551 struct dpp_authentication *auth = wpa_s->dpp_auth;
1552
1553 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1554 MAC2STR(src));
1555
1556 if (!auth) {
1557 wpa_printf(MSG_DEBUG,
1558 "DPP: No DPP Authentication in progress - drop");
1559 return;
1560 }
1561
1562 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1563 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1564 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1565 return;
1566 }
1567
1568 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1569 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
Hai Shalom706f99b2019-01-08 16:23:37 -08001570 wpas_notify_dpp_auth_failure(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001571 return;
1572 }
1573
1574 wpas_dpp_auth_success(wpa_s, 0);
1575}
1576
1577
1578static 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]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001645 goto fail;
1646 }
1647
1648 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1649 if (!connector) {
1650 wpa_printf(MSG_DEBUG,
1651 "DPP: Peer did not include its Connector");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001652 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1653 " fail=missing_connector", MAC2STR(src));
1654 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001655 }
1656
Roshan Pius3a1667e2018-07-03 15:17:14 -07001657 res = dpp_peer_intro(&intro, ssid->dpp_connector,
1658 ssid->dpp_netaccesskey,
1659 ssid->dpp_netaccesskey_len,
1660 ssid->dpp_csign,
1661 ssid->dpp_csign_len,
1662 connector, connector_len, &expiry);
1663 if (res != DPP_STATUS_OK) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001664 wpa_printf(MSG_INFO,
1665 "DPP: Network Introduction protocol resulted in failure");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001666 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1667 " fail=peer_connector_validation_failed", MAC2STR(src));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001668 goto fail;
1669 }
1670
1671 entry = os_zalloc(sizeof(*entry));
1672 if (!entry)
1673 goto fail;
1674 os_memcpy(entry->aa, src, ETH_ALEN);
1675 os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN);
1676 os_memcpy(entry->pmk, intro.pmk, intro.pmk_len);
1677 entry->pmk_len = intro.pmk_len;
1678 entry->akmp = WPA_KEY_MGMT_DPP;
1679 if (expiry) {
1680 os_get_time(&now);
1681 seconds = expiry - now.sec;
1682 } else {
1683 seconds = 86400 * 7;
1684 }
1685 os_get_reltime(&rnow);
1686 entry->expiration = rnow.sec + seconds;
1687 entry->reauth_time = rnow.sec + seconds;
1688 entry->network_ctx = ssid;
1689 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry);
1690
Roshan Pius3a1667e2018-07-03 15:17:14 -07001691 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR
1692 " status=%u", MAC2STR(src), status[0]);
1693
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001694 wpa_printf(MSG_DEBUG,
1695 "DPP: Try connection again after successful network introduction");
1696 if (wpa_supplicant_fast_associate(wpa_s) != 1) {
1697 wpa_supplicant_cancel_sched_scan(wpa_s);
1698 wpa_supplicant_req_scan(wpa_s, 0, 0);
1699 }
1700fail:
1701 os_memset(&intro, 0, sizeof(intro));
1702}
1703
1704
Roshan Pius3a1667e2018-07-03 15:17:14 -07001705static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq)
1706{
1707 int i, j;
1708
1709 if (!wpa_s->hw.modes)
1710 return -1;
1711
1712 for (i = 0; i < wpa_s->hw.num_modes; i++) {
1713 struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
1714
1715 for (j = 0; j < mode->num_channels; j++) {
1716 struct hostapd_channel_data *chan = &mode->channels[j];
1717
1718 if (chan->freq != (int) freq)
1719 continue;
1720
1721 if (chan->flag & (HOSTAPD_CHAN_DISABLED |
1722 HOSTAPD_CHAN_NO_IR |
1723 HOSTAPD_CHAN_RADAR))
1724 continue;
1725
1726 return 1;
1727 }
1728 }
1729
1730 wpa_printf(MSG_DEBUG,
1731 "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list",
1732 freq);
1733
1734 return 0;
1735}
1736
1737
1738static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s,
1739 struct dpp_pkex *pkex)
1740{
1741 if (pkex->freq == 2437)
1742 pkex->freq = 5745;
1743 else if (pkex->freq == 5745)
1744 pkex->freq = 5220;
1745 else if (pkex->freq == 5220)
1746 pkex->freq = 60480;
1747 else
1748 return -1; /* no more channels to try */
1749
1750 if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) {
1751 wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz",
1752 pkex->freq);
1753 return 0;
1754 }
1755
1756 /* Could not use this channel - try the next one */
1757 return wpas_dpp_pkex_next_channel(wpa_s, pkex);
1758}
1759
1760
1761static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx)
1762{
1763 struct wpa_supplicant *wpa_s = eloop_ctx;
1764 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1765
1766 if (!pkex || !pkex->exchange_req)
1767 return;
1768 if (pkex->exch_req_tries >= 5) {
1769 if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) {
1770 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL
1771 "No response from PKEX peer");
1772 dpp_pkex_free(pkex);
1773 wpa_s->dpp_pkex = NULL;
1774 return;
1775 }
1776 pkex->exch_req_tries = 0;
1777 }
1778
1779 pkex->exch_req_tries++;
1780 wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)",
1781 pkex->exch_req_tries);
1782 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1783 MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ);
1784 offchannel_send_action(wpa_s, pkex->freq, broadcast,
1785 wpa_s->own_addr, broadcast,
1786 wpabuf_head(pkex->exchange_req),
1787 wpabuf_len(pkex->exchange_req),
1788 pkex->exch_req_wait_time,
1789 wpas_dpp_tx_pkex_status, 0);
1790}
1791
1792
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001793static void
1794wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
1795 unsigned int freq, const u8 *dst,
1796 const u8 *src, const u8 *bssid,
1797 const u8 *data, size_t data_len,
1798 enum offchannel_send_action_result result)
1799{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001800 const char *res_txt;
1801 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1802
1803 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
1804 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
1805 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001806 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
1807 " result=%s (PKEX)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001808 freq, MAC2STR(dst), res_txt);
1809 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
1810 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
1811
1812 if (!pkex) {
1813 wpa_printf(MSG_DEBUG,
1814 "DPP: Ignore TX status since there is no ongoing PKEX exchange");
1815 return;
1816 }
1817
1818 if (pkex->failed) {
1819 wpa_printf(MSG_DEBUG,
1820 "DPP: Terminate PKEX exchange due to an earlier error");
1821 if (pkex->t > pkex->own_bi->pkex_t)
1822 pkex->own_bi->pkex_t = pkex->t;
1823 dpp_pkex_free(pkex);
1824 wpa_s->dpp_pkex = NULL;
1825 return;
1826 }
1827
1828 if (pkex->exch_req_wait_time && pkex->exchange_req) {
1829 /* Wait for PKEX Exchange Response frame and retry request if
1830 * no response is seen. */
1831 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1832 eloop_register_timeout(pkex->exch_req_wait_time / 1000,
1833 (pkex->exch_req_wait_time % 1000) * 1000,
1834 wpas_dpp_pkex_retry_timeout, wpa_s,
1835 NULL);
1836 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001837}
1838
1839
1840static void
1841wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src,
1842 const u8 *buf, size_t len, unsigned int freq)
1843{
1844 struct wpabuf *msg;
1845 unsigned int wait_time;
1846
1847 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1848 MAC2STR(src));
1849
1850 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1851 * values here */
1852
1853 if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) {
1854 wpa_printf(MSG_DEBUG,
1855 "DPP: No PKEX code configured - ignore request");
1856 return;
1857 }
1858
1859 if (wpa_s->dpp_pkex) {
1860 /* TODO: Support parallel operations */
1861 wpa_printf(MSG_DEBUG,
1862 "DPP: Already in PKEX session - ignore new request");
1863 return;
1864 }
1865
Roshan Pius3a1667e2018-07-03 15:17:14 -07001866 wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001867 wpa_s->own_addr, src,
1868 wpa_s->dpp_pkex_identifier,
1869 wpa_s->dpp_pkex_code,
1870 buf, len);
1871 if (!wpa_s->dpp_pkex) {
1872 wpa_printf(MSG_DEBUG,
1873 "DPP: Failed to process the request - ignore it");
1874 return;
1875 }
1876
1877 msg = wpa_s->dpp_pkex->exchange_resp;
1878 wait_time = wpa_s->max_remain_on_chan;
1879 if (wait_time > 2000)
1880 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001881 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1882 MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001883 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1884 broadcast,
1885 wpabuf_head(msg), wpabuf_len(msg),
1886 wait_time, wpas_dpp_tx_pkex_status, 0);
1887}
1888
1889
1890static void
1891wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src,
1892 const u8 *buf, size_t len, unsigned int freq)
1893{
1894 struct wpabuf *msg;
1895 unsigned int wait_time;
1896
1897 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1898 MAC2STR(src));
1899
1900 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1901 * values here */
1902
1903 if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator ||
1904 wpa_s->dpp_pkex->exchange_done) {
1905 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1906 return;
1907 }
1908
Roshan Pius3a1667e2018-07-03 15:17:14 -07001909 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
1910 wpa_s->dpp_pkex->exch_req_wait_time = 0;
1911
1912 msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001913 if (!msg) {
1914 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1915 return;
1916 }
1917
1918 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1919 MAC2STR(src));
1920
1921 wait_time = wpa_s->max_remain_on_chan;
1922 if (wait_time > 2000)
1923 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001924 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
1925 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001926 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
1927 broadcast,
1928 wpabuf_head(msg), wpabuf_len(msg),
1929 wait_time, wpas_dpp_tx_pkex_status, 0);
1930 wpabuf_free(msg);
1931}
1932
1933
Roshan Pius3a1667e2018-07-03 15:17:14 -07001934static struct dpp_bootstrap_info *
1935wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer,
1936 unsigned int freq)
1937{
1938 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
1939 struct dpp_bootstrap_info *bi;
1940
1941 bi = os_zalloc(sizeof(*bi));
1942 if (!bi)
1943 return NULL;
1944 bi->id = wpas_dpp_next_id(wpa_s);
1945 bi->type = DPP_BOOTSTRAP_PKEX;
1946 os_memcpy(bi->mac_addr, peer, ETH_ALEN);
1947 bi->num_freq = 1;
1948 bi->freq[0] = freq;
1949 bi->curve = pkex->own_bi->curve;
1950 bi->pubkey = pkex->peer_bootstrap_key;
1951 pkex->peer_bootstrap_key = NULL;
1952 dpp_pkex_free(pkex);
1953 wpa_s->dpp_pkex = NULL;
1954 if (dpp_bootstrap_key_hash(bi) < 0) {
1955 dpp_bootstrap_info_free(bi);
1956 return NULL;
1957 }
1958 dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
1959 return bi;
1960}
1961
1962
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001963static void
1964wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src,
1965 const u8 *hdr, const u8 *buf, size_t len,
1966 unsigned int freq)
1967{
1968 struct wpabuf *msg;
1969 unsigned int wait_time;
1970 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001971
1972 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1973 MAC2STR(src));
1974
1975 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1976 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1977 return;
1978 }
1979
1980 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1981 if (!msg) {
1982 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001983 if (pkex->failed) {
1984 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1985 if (pkex->t > pkex->own_bi->pkex_t)
1986 pkex->own_bi->pkex_t = pkex->t;
1987 dpp_pkex_free(wpa_s->dpp_pkex);
1988 wpa_s->dpp_pkex = NULL;
1989 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001990 return;
1991 }
1992
1993 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1994 MACSTR, MAC2STR(src));
1995
1996 wait_time = wpa_s->max_remain_on_chan;
1997 if (wait_time > 2000)
1998 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001999 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2000 MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002001 offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr,
2002 broadcast,
2003 wpabuf_head(msg), wpabuf_len(msg),
2004 wait_time, wpas_dpp_tx_pkex_status, 0);
2005 wpabuf_free(msg);
2006
Roshan Pius3a1667e2018-07-03 15:17:14 -07002007 wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002008}
2009
2010
2011static void
2012wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src,
2013 const u8 *hdr, const u8 *buf, size_t len,
2014 unsigned int freq)
2015{
2016 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002017 struct dpp_bootstrap_info *bi;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002018 struct dpp_pkex *pkex = wpa_s->dpp_pkex;
2019 char cmd[500];
2020
2021 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
2022 MAC2STR(src));
2023
2024 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
2025 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
2026 return;
2027 }
2028
2029 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
2030 if (res < 0) {
2031 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
2032 return;
2033 }
2034
Roshan Pius3a1667e2018-07-03 15:17:14 -07002035 bi = wpas_dpp_pkex_finish(wpa_s, src, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002036 if (!bi)
2037 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002038
2039 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
2040 bi->id,
2041 wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : "");
2042 wpa_printf(MSG_DEBUG,
2043 "DPP: Start authentication after PKEX with parameters: %s",
2044 cmd);
2045 if (wpas_dpp_auth_init(wpa_s, cmd) < 0) {
2046 wpa_printf(MSG_DEBUG,
2047 "DPP: Authentication initialization failed");
2048 return;
2049 }
2050}
2051
2052
2053void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
2054 const u8 *buf, size_t len, unsigned int freq)
2055{
2056 u8 crypto_suite;
2057 enum dpp_public_action_frame_type type;
2058 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002059 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002060
2061 if (len < DPP_HDR_LEN)
2062 return;
2063 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
2064 return;
2065 hdr = buf;
2066 buf += 4;
2067 len -= 4;
2068 crypto_suite = *buf++;
2069 type = *buf++;
2070 len -= 2;
2071
2072 wpa_printf(MSG_DEBUG,
2073 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
2074 MACSTR " freq=%u",
2075 crypto_suite, type, MAC2STR(src), freq);
2076 if (crypto_suite != 1) {
2077 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
2078 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002079 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2080 " freq=%u type=%d ignore=unsupported-crypto-suite",
2081 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002082 return;
2083 }
2084 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002085 if (dpp_check_attrs(buf, len) < 0) {
2086 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
2087 " freq=%u type=%d ignore=invalid-attributes",
2088 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002089 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002090 }
2091 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d",
2092 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002093
2094 switch (type) {
2095 case DPP_PA_AUTHENTICATION_REQ:
2096 wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq);
2097 break;
2098 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07002099 wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002100 break;
2101 case DPP_PA_AUTHENTICATION_CONF:
2102 wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len);
2103 break;
2104 case DPP_PA_PEER_DISCOVERY_RESP:
2105 wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len);
2106 break;
2107 case DPP_PA_PKEX_EXCHANGE_REQ:
2108 wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq);
2109 break;
2110 case DPP_PA_PKEX_EXCHANGE_RESP:
2111 wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq);
2112 break;
2113 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
2114 wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len,
2115 freq);
2116 break;
2117 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
2118 wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
2119 freq);
2120 break;
2121 default:
2122 wpa_printf(MSG_DEBUG,
2123 "DPP: Ignored unsupported frame subtype %d", type);
2124 break;
2125 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002126
2127 if (wpa_s->dpp_pkex)
2128 pkex_t = wpa_s->dpp_pkex->t;
2129 else if (wpa_s->dpp_pkex_bi)
2130 pkex_t = wpa_s->dpp_pkex_bi->pkex_t;
2131 else
2132 pkex_t = 0;
2133 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
2134 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
2135 wpas_dpp_pkex_remove(wpa_s, "*");
2136 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002137}
2138
2139
2140static struct wpabuf *
2141wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query,
2142 size_t query_len)
2143{
2144 struct wpa_supplicant *wpa_s = ctx;
2145 struct dpp_authentication *auth = wpa_s->dpp_auth;
2146 struct wpabuf *resp;
2147
2148 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR,
2149 MAC2STR(sa));
2150 if (!auth || !auth->auth_success ||
2151 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
2152 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
2153 return NULL;
2154 }
2155 wpa_hexdump(MSG_DEBUG,
2156 "DPP: Received Configuration Request (GAS Query Request)",
2157 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002158 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
2159 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002160 resp = dpp_conf_req_rx(auth, query, query_len);
Hai Shalom59532852018-12-07 10:32:58 -08002161 if (!resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002162 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002163 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002164 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002165 auth->conf_resp = resp;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002166 return resp;
2167}
2168
2169
2170static void
2171wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
2172{
2173 struct wpa_supplicant *wpa_s = ctx;
2174 struct dpp_authentication *auth = wpa_s->dpp_auth;
2175
2176 if (!auth) {
2177 wpabuf_free(resp);
2178 return;
2179 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002180 if (auth->conf_resp != resp) {
2181 wpa_printf(MSG_DEBUG,
2182 "DPP: Ignore GAS status report (ok=%d) for unknown response",
2183 ok);
2184 wpabuf_free(resp);
2185 return;
2186 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002187
2188 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
2189 ok);
2190 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002191 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002192 offchannel_send_action_done(wpa_s);
2193 wpas_dpp_listen_stop(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002194 if (ok) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002195 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom706f99b2019-01-08 16:23:37 -08002196 wpas_notify_dpp_config_sent(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002197 }
2198 else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002199 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
Hai Shalom706f99b2019-01-08 16:23:37 -08002200 wpas_notify_dpp_configuration_failure(wpa_s);
Hai Shalom59532852018-12-07 10:32:58 -08002201 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002202 dpp_auth_deinit(wpa_s->dpp_auth);
2203 wpa_s->dpp_auth = NULL;
2204 wpabuf_free(resp);
2205}
2206
2207
2208static unsigned int wpas_dpp_next_configurator_id(struct wpa_supplicant *wpa_s)
2209{
2210 struct dpp_configurator *conf;
2211 unsigned int max_id = 0;
2212
2213 dl_list_for_each(conf, &wpa_s->dpp_configurator,
2214 struct dpp_configurator, list) {
2215 if (conf->id > max_id)
2216 max_id = conf->id;
2217 }
2218 return max_id + 1;
2219}
2220
2221
2222int wpas_dpp_configurator_add(struct wpa_supplicant *wpa_s, const char *cmd)
2223{
2224 char *curve = NULL;
2225 char *key = NULL;
2226 u8 *privkey = NULL;
2227 size_t privkey_len = 0;
2228 int ret = -1;
2229 struct dpp_configurator *conf = NULL;
2230
2231 curve = get_param(cmd, " curve=");
2232 key = get_param(cmd, " key=");
2233
2234 if (key) {
2235 privkey_len = os_strlen(key) / 2;
2236 privkey = os_malloc(privkey_len);
2237 if (!privkey ||
2238 hexstr2bin(key, privkey, privkey_len) < 0)
2239 goto fail;
2240 }
2241
2242 conf = dpp_keygen_configurator(curve, privkey, privkey_len);
2243 if (!conf)
2244 goto fail;
2245
2246 conf->id = wpas_dpp_next_configurator_id(wpa_s);
2247 dl_list_add(&wpa_s->dpp_configurator, &conf->list);
2248 ret = conf->id;
2249 conf = NULL;
2250fail:
2251 os_free(curve);
2252 str_clear_free(key);
2253 bin_clear_free(privkey, privkey_len);
2254 dpp_configurator_free(conf);
2255 return ret;
2256}
2257
2258
2259static int dpp_configurator_del(struct wpa_supplicant *wpa_s, unsigned int id)
2260{
2261 struct dpp_configurator *conf, *tmp;
2262 int found = 0;
2263
2264 dl_list_for_each_safe(conf, tmp, &wpa_s->dpp_configurator,
2265 struct dpp_configurator, list) {
2266 if (id && conf->id != id)
2267 continue;
2268 found = 1;
2269 dl_list_del(&conf->list);
2270 dpp_configurator_free(conf);
2271 }
2272
2273 if (id == 0)
2274 return 0; /* flush succeeds regardless of entries found */
2275 return found ? 0 : -1;
2276}
2277
2278
2279int wpas_dpp_configurator_remove(struct wpa_supplicant *wpa_s, const char *id)
2280{
2281 unsigned int id_val;
2282
2283 if (os_strcmp(id, "*") == 0) {
2284 id_val = 0;
2285 } else {
2286 id_val = atoi(id);
2287 if (id_val == 0)
2288 return -1;
2289 }
2290
2291 return dpp_configurator_del(wpa_s, id_val);
2292}
2293
2294
2295int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
2296{
2297 struct dpp_authentication *auth;
2298 int ret = -1;
2299 char *curve = NULL;
2300
2301 auth = os_zalloc(sizeof(*auth));
2302 if (!auth)
2303 return -1;
2304
2305 curve = get_param(cmd, " curve=");
Hai Shalombf6e0ba2019-02-11 12:01:50 -08002306 wpas_dpp_set_configurator(wpa_s, auth, cmd);
2307
2308 if (dpp_configurator_own_config(auth, curve, 0) == 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002309 wpas_dpp_handle_config_obj(wpa_s, auth);
2310 ret = 0;
2311 }
2312
2313 dpp_auth_deinit(auth);
2314 os_free(curve);
2315
2316 return ret;
2317}
2318
2319
Roshan Pius3a1667e2018-07-03 15:17:14 -07002320int wpas_dpp_configurator_get_key(struct wpa_supplicant *wpa_s, unsigned int id,
2321 char *buf, size_t buflen)
2322{
2323 struct dpp_configurator *conf;
2324
2325 conf = dpp_configurator_get_id(wpa_s, id);
2326 if (!conf)
2327 return -1;
2328
2329 return dpp_configurator_get_key(conf, buf, buflen);
2330}
2331
2332
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002333static void
2334wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s,
2335 unsigned int freq, const u8 *dst,
2336 const u8 *src, const u8 *bssid,
2337 const u8 *data, size_t data_len,
2338 enum offchannel_send_action_result result)
2339{
Roshan Pius3a1667e2018-07-03 15:17:14 -07002340 const char *res_txt;
2341
2342 res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" :
2343 (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" :
2344 "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002345 wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR
2346 " result=%s (DPP Peer Discovery Request)",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002347 freq, MAC2STR(dst), res_txt);
2348 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
2349 " freq=%u result=%s", MAC2STR(dst), freq, res_txt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002350 /* TODO: Time out wait for response more quickly in error cases? */
2351}
2352
2353
2354int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2355 struct wpa_bss *bss)
2356{
2357 struct os_time now;
2358 struct wpabuf *msg;
2359 unsigned int wait_time;
2360
2361 if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss)
2362 return 0; /* Not using DPP AKM - continue */
2363 if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid))
2364 return 0; /* PMKSA exists for DPP AKM - continue */
2365
2366 if (!ssid->dpp_connector || !ssid->dpp_netaccesskey ||
2367 !ssid->dpp_csign) {
2368 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2369 "missing %s",
2370 !ssid->dpp_connector ? "Connector" :
2371 (!ssid->dpp_netaccesskey ? "netAccessKey" :
2372 "C-sign-key"));
2373 return -1;
2374 }
2375
2376 os_get_time(&now);
2377
2378 if (ssid->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07002379 (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002380 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR
2381 "netAccessKey expired");
2382 return -1;
2383 }
2384
2385 wpa_printf(MSG_DEBUG,
2386 "DPP: Starting network introduction protocol to derive PMKSA for "
2387 MACSTR, MAC2STR(bss->bssid));
2388
2389 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ,
2390 5 + 4 + os_strlen(ssid->dpp_connector));
2391 if (!msg)
2392 return -1;
2393
Roshan Pius3a1667e2018-07-03 15:17:14 -07002394#ifdef CONFIG_TESTING_OPTIONS
2395 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) {
2396 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
2397 goto skip_trans_id;
2398 }
2399 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) {
2400 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
2401 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2402 wpabuf_put_le16(msg, 0);
2403 goto skip_trans_id;
2404 }
2405#endif /* CONFIG_TESTING_OPTIONS */
2406
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002407 /* Transaction ID */
2408 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
2409 wpabuf_put_le16(msg, 1);
2410 wpabuf_put_u8(msg, TRANSACTION_ID);
2411
Roshan Pius3a1667e2018-07-03 15:17:14 -07002412#ifdef CONFIG_TESTING_OPTIONS
2413skip_trans_id:
2414 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) {
2415 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
2416 goto skip_connector;
2417 }
2418 if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) {
2419 char *connector;
2420
2421 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
2422 connector = dpp_corrupt_connector_signature(
2423 ssid->dpp_connector);
2424 if (!connector) {
2425 wpabuf_free(msg);
2426 return -1;
2427 }
2428 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2429 wpabuf_put_le16(msg, os_strlen(connector));
2430 wpabuf_put_str(msg, connector);
2431 os_free(connector);
2432 goto skip_connector;
2433 }
2434#endif /* CONFIG_TESTING_OPTIONS */
2435
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002436 /* DPP Connector */
2437 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
2438 wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector));
2439 wpabuf_put_str(msg, ssid->dpp_connector);
2440
Roshan Pius3a1667e2018-07-03 15:17:14 -07002441#ifdef CONFIG_TESTING_OPTIONS
2442skip_connector:
2443#endif /* CONFIG_TESTING_OPTIONS */
2444
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002445 /* TODO: Timeout on AP response */
2446 wait_time = wpa_s->max_remain_on_chan;
2447 if (wait_time > 2000)
2448 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002449 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
2450 MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002451 offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr,
2452 broadcast,
2453 wpabuf_head(msg), wpabuf_len(msg),
2454 wait_time, wpas_dpp_tx_introduction_status, 0);
2455 wpabuf_free(msg);
2456
2457 /* Request this connection attempt to terminate - new one will be
2458 * started when network introduction protocol completes */
2459 os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN);
2460 wpa_s->dpp_intro_network = ssid;
2461 return 1;
2462}
2463
2464
2465int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd)
2466{
2467 struct dpp_bootstrap_info *own_bi;
2468 const char *pos, *end;
2469 unsigned int wait_time;
2470
2471 pos = os_strstr(cmd, " own=");
2472 if (!pos)
2473 return -1;
2474 pos += 5;
2475 own_bi = dpp_bootstrap_get_id(wpa_s, atoi(pos));
2476 if (!own_bi) {
2477 wpa_printf(MSG_DEBUG,
2478 "DPP: Identified bootstrap info not found");
2479 return -1;
2480 }
2481 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
2482 wpa_printf(MSG_DEBUG,
2483 "DPP: Identified bootstrap info not for PKEX");
2484 return -1;
2485 }
2486 wpa_s->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002487 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002488
2489 os_free(wpa_s->dpp_pkex_identifier);
2490 wpa_s->dpp_pkex_identifier = NULL;
2491 pos = os_strstr(cmd, " identifier=");
2492 if (pos) {
2493 pos += 12;
2494 end = os_strchr(pos, ' ');
2495 if (!end)
2496 return -1;
2497 wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1);
2498 if (!wpa_s->dpp_pkex_identifier)
2499 return -1;
2500 os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos);
2501 wpa_s->dpp_pkex_identifier[end - pos] = '\0';
2502 }
2503
2504 pos = os_strstr(cmd, " code=");
2505 if (!pos)
2506 return -1;
2507 os_free(wpa_s->dpp_pkex_code);
2508 wpa_s->dpp_pkex_code = os_strdup(pos + 6);
2509 if (!wpa_s->dpp_pkex_code)
2510 return -1;
2511
2512 if (os_strstr(cmd, " init=1")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002513 struct dpp_pkex *pkex;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002514 struct wpabuf *msg;
2515
2516 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
2517 dpp_pkex_free(wpa_s->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002518 wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002519 wpa_s->dpp_pkex_identifier,
2520 wpa_s->dpp_pkex_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002521 pkex = wpa_s->dpp_pkex;
2522 if (!pkex)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002523 return -1;
2524
Roshan Pius3a1667e2018-07-03 15:17:14 -07002525 msg = pkex->exchange_req;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002526 wait_time = wpa_s->max_remain_on_chan;
2527 if (wait_time > 2000)
2528 wait_time = 2000;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002529 pkex->freq = 2437;
2530 wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
2531 " freq=%u type=%d",
2532 MAC2STR(broadcast), pkex->freq,
2533 DPP_PA_PKEX_EXCHANGE_REQ);
2534 offchannel_send_action(wpa_s, pkex->freq, broadcast,
2535 wpa_s->own_addr, broadcast,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002536 wpabuf_head(msg), wpabuf_len(msg),
2537 wait_time, wpas_dpp_tx_pkex_status, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002538 if (wait_time == 0)
2539 wait_time = 2000;
2540 pkex->exch_req_wait_time = wait_time;
2541 pkex->exch_req_tries = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002542 }
2543
2544 /* TODO: Support multiple PKEX info entries */
2545
2546 os_free(wpa_s->dpp_pkex_auth_cmd);
2547 wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd);
2548
2549 return 1;
2550}
2551
2552
2553int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id)
2554{
2555 unsigned int id_val;
2556
2557 if (os_strcmp(id, "*") == 0) {
2558 id_val = 0;
2559 } else {
2560 id_val = atoi(id);
2561 if (id_val == 0)
2562 return -1;
2563 }
2564
2565 if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code)
2566 return -1;
2567
2568 /* TODO: Support multiple PKEX entries */
2569 os_free(wpa_s->dpp_pkex_code);
2570 wpa_s->dpp_pkex_code = NULL;
2571 os_free(wpa_s->dpp_pkex_identifier);
2572 wpa_s->dpp_pkex_identifier = NULL;
2573 os_free(wpa_s->dpp_pkex_auth_cmd);
2574 wpa_s->dpp_pkex_auth_cmd = NULL;
2575 wpa_s->dpp_pkex_bi = NULL;
2576 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2577 dpp_pkex_free(wpa_s->dpp_pkex);
2578 wpa_s->dpp_pkex = NULL;
2579 return 0;
2580}
2581
2582
Roshan Pius3a1667e2018-07-03 15:17:14 -07002583void wpas_dpp_stop(struct wpa_supplicant *wpa_s)
2584{
2585 dpp_auth_deinit(wpa_s->dpp_auth);
2586 wpa_s->dpp_auth = NULL;
2587 dpp_pkex_free(wpa_s->dpp_pkex);
2588 wpa_s->dpp_pkex = NULL;
2589 if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0)
2590 gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token);
2591}
2592
2593
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002594int wpas_dpp_init(struct wpa_supplicant *wpa_s)
2595{
2596 u8 adv_proto_id[7];
2597
2598 adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC;
2599 adv_proto_id[1] = 5;
2600 WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA);
2601 adv_proto_id[5] = DPP_OUI_TYPE;
2602 adv_proto_id[6] = 0x01;
2603
2604 if (gas_server_register(wpa_s->gas_server, adv_proto_id,
2605 sizeof(adv_proto_id), wpas_dpp_gas_req_handler,
2606 wpas_dpp_gas_status_handler, wpa_s) < 0)
2607 return -1;
2608 dl_list_init(&wpa_s->dpp_bootstrap);
2609 dl_list_init(&wpa_s->dpp_configurator);
2610 wpa_s->dpp_init_done = 1;
2611 return 0;
2612}
2613
2614
2615void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
2616{
2617#ifdef CONFIG_TESTING_OPTIONS
2618 os_free(wpa_s->dpp_config_obj_override);
2619 wpa_s->dpp_config_obj_override = NULL;
2620 os_free(wpa_s->dpp_discovery_override);
2621 wpa_s->dpp_discovery_override = NULL;
2622 os_free(wpa_s->dpp_groups_override);
2623 wpa_s->dpp_groups_override = NULL;
2624 wpa_s->dpp_ignore_netaccesskey_mismatch = 0;
2625#endif /* CONFIG_TESTING_OPTIONS */
2626 if (!wpa_s->dpp_init_done)
2627 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002628 eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002629 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002630 eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
2631 eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002632 offchannel_send_action_done(wpa_s);
2633 wpas_dpp_listen_stop(wpa_s);
2634 dpp_bootstrap_del(wpa_s, 0);
2635 dpp_configurator_del(wpa_s, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002636 wpas_dpp_stop(wpa_s);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002637 wpas_dpp_pkex_remove(wpa_s, "*");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002638 os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN);
2639 os_free(wpa_s->dpp_configurator_params);
2640 wpa_s->dpp_configurator_params = NULL;
2641}