blob: 149f389f789f1f4adbb3b0e9da1da824e2741da8 [file] [log] [blame]
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001/*
2 * hostapd / DPP integration
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "utils/eloop.h"
13#include "common/dpp.h"
14#include "common/gas.h"
15#include "common/wpa_ctrl.h"
16#include "hostapd.h"
17#include "ap_drv_ops.h"
18#include "gas_query_ap.h"
19#include "wpa_auth.h"
20#include "dpp_hostapd.h"
21
22
Roshan Pius3a1667e2018-07-03 15:17:14 -070023static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070024static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -070025static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
26static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070027
28static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
29
30
31static struct dpp_configurator *
32hostapd_dpp_configurator_get_id(struct hostapd_data *hapd, unsigned int id)
33{
34 struct dpp_configurator *conf;
35
Roshan Pius3a1667e2018-07-03 15:17:14 -070036 dl_list_for_each(conf, &hapd->iface->interfaces->dpp_configurator,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070037 struct dpp_configurator, list) {
38 if (conf->id == id)
39 return conf;
40 }
41 return NULL;
42}
43
44
45static unsigned int hapd_dpp_next_id(struct hostapd_data *hapd)
46{
47 struct dpp_bootstrap_info *bi;
48 unsigned int max_id = 0;
49
Roshan Pius3a1667e2018-07-03 15:17:14 -070050 dl_list_for_each(bi, &hapd->iface->interfaces->dpp_bootstrap,
51 struct dpp_bootstrap_info, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070052 if (bi->id > max_id)
53 max_id = bi->id;
54 }
55 return max_id + 1;
56}
57
58
59/**
60 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
61 * @hapd: Pointer to hostapd_data
62 * @cmd: DPP URI read from a QR Code
63 * Returns: Identifier of the stored info or -1 on failure
64 */
65int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
66{
67 struct dpp_bootstrap_info *bi;
68 struct dpp_authentication *auth = hapd->dpp_auth;
69
70 bi = dpp_parse_qr_code(cmd);
71 if (!bi)
72 return -1;
73
74 bi->id = hapd_dpp_next_id(hapd);
Roshan Pius3a1667e2018-07-03 15:17:14 -070075 dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070076
77 if (auth && auth->response_pending &&
78 dpp_notify_new_qr_code(auth, bi) == 1) {
79 wpa_printf(MSG_DEBUG,
80 "DPP: Sending out pending authentication response");
Roshan Pius3a1667e2018-07-03 15:17:14 -070081 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
82 " freq=%u type=%d",
83 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
84 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070085 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
86 auth->peer_mac_addr,
87 wpabuf_head(hapd->dpp_auth->resp_msg),
88 wpabuf_len(hapd->dpp_auth->resp_msg));
89 }
90
91 return bi->id;
92}
93
94
95static char * get_param(const char *cmd, const char *param)
96{
97 const char *pos, *end;
98 char *val;
99 size_t len;
100
101 pos = os_strstr(cmd, param);
102 if (!pos)
103 return NULL;
104
105 pos += os_strlen(param);
106 end = os_strchr(pos, ' ');
107 if (end)
108 len = end - pos;
109 else
110 len = os_strlen(pos);
111 val = os_malloc(len + 1);
112 if (!val)
113 return NULL;
114 os_memcpy(val, pos, len);
115 val[len] = '\0';
116 return val;
117}
118
119
120int hostapd_dpp_bootstrap_gen(struct hostapd_data *hapd, const char *cmd)
121{
122 char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
123 char *key = NULL;
124 u8 *privkey = NULL;
125 size_t privkey_len = 0;
126 size_t len;
127 int ret = -1;
128 struct dpp_bootstrap_info *bi;
129
130 bi = os_zalloc(sizeof(*bi));
131 if (!bi)
132 goto fail;
133
134 if (os_strstr(cmd, "type=qrcode"))
135 bi->type = DPP_BOOTSTRAP_QR_CODE;
136 else if (os_strstr(cmd, "type=pkex"))
137 bi->type = DPP_BOOTSTRAP_PKEX;
138 else
139 goto fail;
140
141 chan = get_param(cmd, " chan=");
142 mac = get_param(cmd, " mac=");
143 info = get_param(cmd, " info=");
144 curve = get_param(cmd, " curve=");
145 key = get_param(cmd, " key=");
146
147 if (key) {
148 privkey_len = os_strlen(key) / 2;
149 privkey = os_malloc(privkey_len);
150 if (!privkey ||
151 hexstr2bin(key, privkey, privkey_len) < 0)
152 goto fail;
153 }
154
155 pk = dpp_keygen(bi, curve, privkey, privkey_len);
156 if (!pk)
157 goto fail;
158
159 len = 4; /* "DPP:" */
160 if (chan) {
161 if (dpp_parse_uri_chan_list(bi, chan) < 0)
162 goto fail;
163 len += 3 + os_strlen(chan); /* C:...; */
164 }
165 if (mac) {
166 if (dpp_parse_uri_mac(bi, mac) < 0)
167 goto fail;
168 len += 3 + os_strlen(mac); /* M:...; */
169 }
170 if (info) {
171 if (dpp_parse_uri_info(bi, info) < 0)
172 goto fail;
173 len += 3 + os_strlen(info); /* I:...; */
174 }
175 len += 4 + os_strlen(pk);
176 bi->uri = os_malloc(len + 1);
177 if (!bi->uri)
178 goto fail;
179 os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
180 chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
181 mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
182 info ? "I:" : "", info ? info : "", info ? ";" : "",
183 pk);
184 bi->id = hapd_dpp_next_id(hapd);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700185 dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700186 ret = bi->id;
187 bi = NULL;
188fail:
189 os_free(curve);
190 os_free(pk);
191 os_free(chan);
192 os_free(mac);
193 os_free(info);
194 str_clear_free(key);
195 bin_clear_free(privkey, privkey_len);
196 dpp_bootstrap_info_free(bi);
197 return ret;
198}
199
200
201static struct dpp_bootstrap_info *
202dpp_bootstrap_get_id(struct hostapd_data *hapd, unsigned int id)
203{
204 struct dpp_bootstrap_info *bi;
205
Roshan Pius3a1667e2018-07-03 15:17:14 -0700206 dl_list_for_each(bi, &hapd->iface->interfaces->dpp_bootstrap,
207 struct dpp_bootstrap_info, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700208 if (bi->id == id)
209 return bi;
210 }
211 return NULL;
212}
213
214
Roshan Pius3a1667e2018-07-03 15:17:14 -0700215static int dpp_bootstrap_del(struct hapd_interfaces *ifaces, unsigned int id)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700216{
217 struct dpp_bootstrap_info *bi, *tmp;
218 int found = 0;
219
Roshan Pius3a1667e2018-07-03 15:17:14 -0700220 dl_list_for_each_safe(bi, tmp, &ifaces->dpp_bootstrap,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700221 struct dpp_bootstrap_info, list) {
222 if (id && bi->id != id)
223 continue;
224 found = 1;
225 dl_list_del(&bi->list);
226 dpp_bootstrap_info_free(bi);
227 }
228
229 if (id == 0)
230 return 0; /* flush succeeds regardless of entries found */
231 return found ? 0 : -1;
232}
233
234
235int hostapd_dpp_bootstrap_remove(struct hostapd_data *hapd, const char *id)
236{
237 unsigned int id_val;
238
239 if (os_strcmp(id, "*") == 0) {
240 id_val = 0;
241 } else {
242 id_val = atoi(id);
243 if (id_val == 0)
244 return -1;
245 }
246
Roshan Pius3a1667e2018-07-03 15:17:14 -0700247 return dpp_bootstrap_del(hapd->iface->interfaces, id_val);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700248}
249
250
251const char * hostapd_dpp_bootstrap_get_uri(struct hostapd_data *hapd,
252 unsigned int id)
253{
254 struct dpp_bootstrap_info *bi;
255
256 bi = dpp_bootstrap_get_id(hapd, id);
257 if (!bi)
258 return NULL;
259 return bi->uri;
260}
261
262
263int hostapd_dpp_bootstrap_info(struct hostapd_data *hapd, int id,
264 char *reply, int reply_size)
265{
266 struct dpp_bootstrap_info *bi;
267
268 bi = dpp_bootstrap_get_id(hapd, id);
269 if (!bi)
270 return -1;
271 return os_snprintf(reply, reply_size, "type=%s\n"
272 "mac_addr=" MACSTR "\n"
273 "info=%s\n"
274 "num_freq=%u\n"
275 "curve=%s\n",
276 dpp_bootstrap_type_txt(bi->type),
277 MAC2STR(bi->mac_addr),
278 bi->info ? bi->info : "",
279 bi->num_freq,
280 bi->curve->name);
281}
282
283
Roshan Pius3a1667e2018-07-03 15:17:14 -0700284static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
285 void *timeout_ctx)
286{
287 struct hostapd_data *hapd = eloop_ctx;
288 struct dpp_authentication *auth = hapd->dpp_auth;
289
290 if (!auth || !auth->resp_msg)
291 return;
292
293 wpa_printf(MSG_DEBUG,
294 "DPP: Retry Authentication Response after timeout");
295 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
296 " freq=%u type=%d",
297 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
298 DPP_PA_AUTHENTICATION_RESP);
299 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
300 wpabuf_head(auth->resp_msg),
301 wpabuf_len(auth->resp_msg));
302}
303
304
305static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
306{
307 struct dpp_authentication *auth = hapd->dpp_auth;
308 unsigned int wait_time, max_tries;
309
310 if (!auth || !auth->resp_msg)
311 return;
312
313 if (hapd->dpp_resp_max_tries)
314 max_tries = hapd->dpp_resp_max_tries;
315 else
316 max_tries = 5;
317 auth->auth_resp_tries++;
318 if (auth->auth_resp_tries >= max_tries) {
319 wpa_printf(MSG_INFO,
320 "DPP: No confirm received from initiator - stopping exchange");
321 hostapd_drv_send_action_cancel_wait(hapd);
322 dpp_auth_deinit(hapd->dpp_auth);
323 hapd->dpp_auth = NULL;
324 return;
325 }
326
327 if (hapd->dpp_resp_retry_time)
328 wait_time = hapd->dpp_resp_retry_time;
329 else
330 wait_time = 1000;
331 wpa_printf(MSG_DEBUG,
332 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
333 wait_time);
334 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
335 eloop_register_timeout(wait_time / 1000,
336 (wait_time % 1000) * 1000,
337 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
338}
339
340
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700341void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
342 const u8 *data, size_t data_len, int ok)
343{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700344 struct dpp_authentication *auth = hapd->dpp_auth;
345
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700346 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
347 MAC2STR(dst), ok);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700348 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
349 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700350
351 if (!hapd->dpp_auth) {
352 wpa_printf(MSG_DEBUG,
353 "DPP: Ignore TX status since there is no ongoing authentication exchange");
354 return;
355 }
356
357 if (hapd->dpp_auth->remove_on_tx_status) {
358 wpa_printf(MSG_DEBUG,
359 "DPP: Terminate authentication exchange due to an earlier error");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700360 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
361 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
362 hapd, NULL);
363 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
364 NULL);
365 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700366 dpp_auth_deinit(hapd->dpp_auth);
367 hapd->dpp_auth = NULL;
368 return;
369 }
370
371 if (hapd->dpp_auth_ok_on_ack)
372 hostapd_dpp_auth_success(hapd, 1);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700373
374 if (!is_broadcast_ether_addr(dst) && !ok) {
375 wpa_printf(MSG_DEBUG,
376 "DPP: Unicast DPP Action frame was not ACKed");
377 if (auth->waiting_auth_resp) {
378 /* In case of DPP Authentication Request frame, move to
379 * the next channel immediately. */
380 hostapd_drv_send_action_cancel_wait(hapd);
381 hostapd_dpp_auth_init_next(hapd);
382 return;
383 }
384 if (auth->waiting_auth_conf) {
385 hostapd_dpp_auth_resp_retry(hapd);
386 return;
387 }
388 }
389
390 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
391 /* Allow timeout handling to stop iteration if no response is
392 * received from a peer that has ACKed a request. */
393 auth->auth_req_ack = 1;
394 }
395
396 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
397 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
398 wpa_printf(MSG_DEBUG,
399 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
400 hapd->dpp_auth->curr_freq,
401 hapd->dpp_auth->neg_freq);
402 hostapd_drv_send_action_cancel_wait(hapd);
403
404 if (hapd->dpp_auth->neg_freq !=
405 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
406 /* TODO: Listen operation on non-operating channel */
407 wpa_printf(MSG_INFO,
408 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
409 hapd->dpp_auth->neg_freq, hapd->iface->freq);
410 }
411 }
412
413 if (hapd->dpp_auth_ok_on_ack)
414 hapd->dpp_auth_ok_on_ack = 0;
415}
416
417
418static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
419{
420 struct hostapd_data *hapd = eloop_ctx;
421 struct dpp_authentication *auth = hapd->dpp_auth;
422 unsigned int freq;
423 struct os_reltime now, diff;
424 unsigned int wait_time, diff_ms;
425
426 if (!auth || !auth->waiting_auth_resp)
427 return;
428
429 wait_time = hapd->dpp_resp_wait_time ?
430 hapd->dpp_resp_wait_time : 2000;
431 os_get_reltime(&now);
432 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
433 diff_ms = diff.sec * 1000 + diff.usec / 1000;
434 wpa_printf(MSG_DEBUG,
435 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
436 wait_time, diff_ms);
437
438 if (auth->auth_req_ack && diff_ms >= wait_time) {
439 /* Peer ACK'ed Authentication Request frame, but did not reply
440 * with Authentication Response frame within two seconds. */
441 wpa_printf(MSG_INFO,
442 "DPP: No response received from responder - stopping initiation attempt");
443 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
444 hostapd_drv_send_action_cancel_wait(hapd);
445 hostapd_dpp_listen_stop(hapd);
446 dpp_auth_deinit(auth);
447 hapd->dpp_auth = NULL;
448 return;
449 }
450
451 if (diff_ms >= wait_time) {
452 /* Authentication Request frame was not ACK'ed and no reply
453 * was receiving within two seconds. */
454 wpa_printf(MSG_DEBUG,
455 "DPP: Continue Initiator channel iteration");
456 hostapd_drv_send_action_cancel_wait(hapd);
457 hostapd_dpp_listen_stop(hapd);
458 hostapd_dpp_auth_init_next(hapd);
459 return;
460 }
461
462 /* Driver did not support 2000 ms long wait_time with TX command, so
463 * schedule listen operation to continue waiting for the response.
464 *
465 * DPP listen operations continue until stopped, so simply schedule a
466 * new call to this function at the point when the two second reply
467 * wait has expired. */
468 wait_time -= diff_ms;
469
470 freq = auth->curr_freq;
471 if (auth->neg_freq > 0)
472 freq = auth->neg_freq;
473 wpa_printf(MSG_DEBUG,
474 "DPP: Continue reply wait on channel %u MHz for %u ms",
475 freq, wait_time);
476 hapd->dpp_in_response_listen = 1;
477
478 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
479 /* TODO: Listen operation on non-operating channel */
480 wpa_printf(MSG_INFO,
481 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
482 freq, hapd->iface->freq);
483 }
484
485 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
486 hostapd_dpp_reply_wait_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700487}
488
489
490static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
491 struct dpp_authentication *auth)
492{
493#ifdef CONFIG_TESTING_OPTIONS
494 if (hapd->dpp_config_obj_override)
495 auth->config_obj_override =
496 os_strdup(hapd->dpp_config_obj_override);
497 if (hapd->dpp_discovery_override)
498 auth->discovery_override =
499 os_strdup(hapd->dpp_discovery_override);
500 if (hapd->dpp_groups_override)
501 auth->groups_override = os_strdup(hapd->dpp_groups_override);
502 auth->ignore_netaccesskey_mismatch =
503 hapd->dpp_ignore_netaccesskey_mismatch;
504#endif /* CONFIG_TESTING_OPTIONS */
505}
506
507
Hai Shalom74f70d42019-02-11 14:42:39 -0800508static int hostapd_dpp_set_configurator(struct hostapd_data *hapd,
509 struct dpp_authentication *auth,
510 const char *cmd)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700511{
512 const char *pos, *end;
513 struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
514 struct dpp_configurator *conf = NULL;
515 u8 ssid[32] = { "test" };
516 size_t ssid_len = 4;
517 char pass[64] = { };
518 size_t pass_len = 0;
519 u8 psk[PMK_LEN];
520 int psk_set = 0;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700521 char *group_id = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700522
523 if (!cmd)
Hai Shalom74f70d42019-02-11 14:42:39 -0800524 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700525
526 wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
527 pos = os_strstr(cmd, " ssid=");
528 if (pos) {
529 pos += 6;
530 end = os_strchr(pos, ' ');
531 ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
532 ssid_len /= 2;
533 if (ssid_len > sizeof(ssid) ||
534 hexstr2bin(pos, ssid, ssid_len) < 0)
535 goto fail;
536 }
537
538 pos = os_strstr(cmd, " pass=");
539 if (pos) {
540 pos += 6;
541 end = os_strchr(pos, ' ');
542 pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
543 pass_len /= 2;
544 if (pass_len > sizeof(pass) - 1 || pass_len < 8 ||
545 hexstr2bin(pos, (u8 *) pass, pass_len) < 0)
546 goto fail;
547 }
548
549 pos = os_strstr(cmd, " psk=");
550 if (pos) {
551 pos += 5;
552 if (hexstr2bin(pos, psk, PMK_LEN) < 0)
553 goto fail;
554 psk_set = 1;
555 }
556
Hai Shalomce48b4a2018-09-05 11:41:35 -0700557 pos = os_strstr(cmd, " group_id=");
558 if (pos) {
559 size_t group_id_len;
560
561 pos += 10;
562 end = os_strchr(pos, ' ');
563 group_id_len = end ? (size_t) (end - pos) : os_strlen(pos);
564 group_id = os_malloc(group_id_len + 1);
565 if (!group_id)
566 goto fail;
567 os_memcpy(group_id, pos, group_id_len);
568 group_id[group_id_len] = '\0';
569 }
570
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700571 if (os_strstr(cmd, " conf=sta-")) {
572 conf_sta = os_zalloc(sizeof(struct dpp_configuration));
573 if (!conf_sta)
574 goto fail;
575 os_memcpy(conf_sta->ssid, ssid, ssid_len);
576 conf_sta->ssid_len = ssid_len;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700577 if (os_strstr(cmd, " conf=sta-psk") ||
578 os_strstr(cmd, " conf=sta-sae") ||
579 os_strstr(cmd, " conf=sta-psk-sae")) {
580 if (os_strstr(cmd, " conf=sta-psk-sae"))
581 conf_sta->akm = DPP_AKM_PSK_SAE;
582 else if (os_strstr(cmd, " conf=sta-sae"))
583 conf_sta->akm = DPP_AKM_SAE;
584 else
585 conf_sta->akm = DPP_AKM_PSK;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700586 if (psk_set) {
587 os_memcpy(conf_sta->psk, psk, PMK_LEN);
588 } else {
589 conf_sta->passphrase = os_strdup(pass);
590 if (!conf_sta->passphrase)
591 goto fail;
592 }
593 } else if (os_strstr(cmd, " conf=sta-dpp")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700594 conf_sta->akm = DPP_AKM_DPP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700595 } else {
596 goto fail;
597 }
Hai Shalomce48b4a2018-09-05 11:41:35 -0700598 if (os_strstr(cmd, " group_id=")) {
599 conf_sta->group_id = group_id;
600 group_id = NULL;
601 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700602 }
603
604 if (os_strstr(cmd, " conf=ap-")) {
605 conf_ap = os_zalloc(sizeof(struct dpp_configuration));
606 if (!conf_ap)
607 goto fail;
608 os_memcpy(conf_ap->ssid, ssid, ssid_len);
609 conf_ap->ssid_len = ssid_len;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700610 if (os_strstr(cmd, " conf=ap-psk") ||
611 os_strstr(cmd, " conf=ap-sae") ||
612 os_strstr(cmd, " conf=ap-psk-sae")) {
613 if (os_strstr(cmd, " conf=ap-psk-sae"))
614 conf_ap->akm = DPP_AKM_PSK_SAE;
615 else if (os_strstr(cmd, " conf=ap-sae"))
616 conf_ap->akm = DPP_AKM_SAE;
617 else
618 conf_ap->akm = DPP_AKM_PSK;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700619 if (psk_set) {
620 os_memcpy(conf_ap->psk, psk, PMK_LEN);
Hai Shalom74f70d42019-02-11 14:42:39 -0800621 } else if (pass_len > 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700622 conf_ap->passphrase = os_strdup(pass);
623 if (!conf_ap->passphrase)
624 goto fail;
Hai Shalom74f70d42019-02-11 14:42:39 -0800625 } else {
626 goto fail;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700627 }
628 } else if (os_strstr(cmd, " conf=ap-dpp")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700629 conf_ap->akm = DPP_AKM_DPP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700630 } else {
631 goto fail;
632 }
Hai Shalomce48b4a2018-09-05 11:41:35 -0700633 if (os_strstr(cmd, " group_id=")) {
634 conf_ap->group_id = group_id;
635 group_id = NULL;
636 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700637 }
638
639 pos = os_strstr(cmd, " expiry=");
640 if (pos) {
641 long int val;
642
643 pos += 8;
644 val = strtol(pos, NULL, 0);
645 if (val <= 0)
646 goto fail;
647 if (conf_sta)
648 conf_sta->netaccesskey_expiry = val;
649 if (conf_ap)
650 conf_ap->netaccesskey_expiry = val;
651 }
652
653 pos = os_strstr(cmd, " configurator=");
654 if (pos) {
655 auth->configurator = 1;
656 pos += 14;
657 conf = hostapd_dpp_configurator_get_id(hapd, atoi(pos));
658 if (!conf) {
659 wpa_printf(MSG_INFO,
660 "DPP: Could not find the specified configurator");
661 goto fail;
662 }
663 }
664 auth->conf_sta = conf_sta;
665 auth->conf_ap = conf_ap;
666 auth->conf = conf;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700667 os_free(group_id);
Hai Shalom74f70d42019-02-11 14:42:39 -0800668 return 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700669
670fail:
Hai Shalom74f70d42019-02-11 14:42:39 -0800671 wpa_msg(hapd->msg_ctx, MSG_INFO,
672 "DPP: Failed to set configurator parameters");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700673 dpp_configuration_free(conf_sta);
674 dpp_configuration_free(conf_ap);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700675 os_free(group_id);
Hai Shalom74f70d42019-02-11 14:42:39 -0800676 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700677}
678
679
Roshan Pius3a1667e2018-07-03 15:17:14 -0700680static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
681{
682 struct hostapd_data *hapd = eloop_ctx;
683
684 if (!hapd->dpp_auth)
685 return;
686 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
687 hostapd_dpp_auth_init_next(hapd);
688}
689
690
691static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
692{
693 struct dpp_authentication *auth = hapd->dpp_auth;
694 const u8 *dst;
695 unsigned int wait_time, max_wait_time, freq, max_tries, used;
696 struct os_reltime now, diff;
697
698 if (!auth)
699 return -1;
700
701 if (auth->freq_idx == 0)
702 os_get_reltime(&hapd->dpp_init_iter_start);
703
704 if (auth->freq_idx >= auth->num_freq) {
705 auth->num_freq_iters++;
706 if (hapd->dpp_init_max_tries)
707 max_tries = hapd->dpp_init_max_tries;
708 else
709 max_tries = 5;
710 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
711 wpa_printf(MSG_INFO,
712 "DPP: No response received from responder - stopping initiation attempt");
713 wpa_msg(hapd->msg_ctx, MSG_INFO,
714 DPP_EVENT_AUTH_INIT_FAILED);
715 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
716 hapd, NULL);
717 hostapd_drv_send_action_cancel_wait(hapd);
718 dpp_auth_deinit(hapd->dpp_auth);
719 hapd->dpp_auth = NULL;
720 return -1;
721 }
722 auth->freq_idx = 0;
723 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
724 if (hapd->dpp_init_retry_time)
725 wait_time = hapd->dpp_init_retry_time;
726 else
727 wait_time = 10000;
728 os_get_reltime(&now);
729 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
730 used = diff.sec * 1000 + diff.usec / 1000;
731 if (used > wait_time)
732 wait_time = 0;
733 else
734 wait_time -= used;
735 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
736 wait_time);
737 eloop_register_timeout(wait_time / 1000,
738 (wait_time % 1000) * 1000,
739 hostapd_dpp_init_timeout, hapd,
740 NULL);
741 return 0;
742 }
743 freq = auth->freq[auth->freq_idx++];
744 auth->curr_freq = freq;
745
746 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
747 dst = broadcast;
748 else
749 dst = auth->peer_bi->mac_addr;
750 hapd->dpp_auth_ok_on_ack = 0;
751 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
752 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
753 max_wait_time = hapd->dpp_resp_wait_time ?
754 hapd->dpp_resp_wait_time : 2000;
755 if (wait_time > max_wait_time)
756 wait_time = max_wait_time;
757 wait_time += 10; /* give the driver some extra time to complete */
758 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
759 hostapd_dpp_reply_wait_timeout, hapd, NULL);
760 wait_time -= 10;
761 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
762 wpa_printf(MSG_DEBUG,
763 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
764 freq, auth->neg_freq);
765 }
766 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
767 " freq=%u type=%d",
768 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
769 auth->auth_req_ack = 0;
770 os_get_reltime(&hapd->dpp_last_init);
771 return hostapd_drv_send_action(hapd, freq, wait_time,
772 dst,
773 wpabuf_head(hapd->dpp_auth->req_msg),
774 wpabuf_len(hapd->dpp_auth->req_msg));
775}
776
777
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700778int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
779{
780 const char *pos;
781 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700782 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
783 unsigned int neg_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700784
785 pos = os_strstr(cmd, " peer=");
786 if (!pos)
787 return -1;
788 pos += 6;
789 peer_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
790 if (!peer_bi) {
791 wpa_printf(MSG_INFO,
792 "DPP: Could not find bootstrapping info for the identified peer");
793 return -1;
794 }
795
796 pos = os_strstr(cmd, " own=");
797 if (pos) {
798 pos += 5;
799 own_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
800 if (!own_bi) {
801 wpa_printf(MSG_INFO,
802 "DPP: Could not find bootstrapping info for the identified local entry");
803 return -1;
804 }
805
806 if (peer_bi->curve != own_bi->curve) {
807 wpa_printf(MSG_INFO,
808 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
809 peer_bi->curve->name, own_bi->curve->name);
810 return -1;
811 }
812 }
813
814 pos = os_strstr(cmd, " role=");
815 if (pos) {
816 pos += 6;
817 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700818 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700819 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700820 allowed_roles = DPP_CAPAB_ENROLLEE;
821 else if (os_strncmp(pos, "either", 6) == 0)
822 allowed_roles = DPP_CAPAB_CONFIGURATOR |
823 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700824 else
825 goto fail;
826 }
827
Roshan Pius3a1667e2018-07-03 15:17:14 -0700828 pos = os_strstr(cmd, " neg_freq=");
829 if (pos)
830 neg_freq = atoi(pos + 10);
831
832 if (hapd->dpp_auth) {
833 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
834 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
835 hapd, NULL);
836 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
837 NULL);
838 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700839 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700840 }
841
842 hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
843 allowed_roles, neg_freq,
844 hapd->iface->hw_features,
845 hapd->iface->num_hw_features);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700846 if (!hapd->dpp_auth)
847 goto fail;
848 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800849 if (hostapd_dpp_set_configurator(hapd, hapd->dpp_auth, cmd) < 0) {
850 dpp_auth_deinit(hapd->dpp_auth);
851 hapd->dpp_auth = NULL;
852 goto fail;
853 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700854
Roshan Pius3a1667e2018-07-03 15:17:14 -0700855 hapd->dpp_auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700856
Roshan Pius3a1667e2018-07-03 15:17:14 -0700857 if (!is_zero_ether_addr(peer_bi->mac_addr))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700858 os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
859 ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700860
Roshan Pius3a1667e2018-07-03 15:17:14 -0700861 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700862fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700863 return -1;
864}
865
866
Roshan Pius3a1667e2018-07-03 15:17:14 -0700867int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
868{
869 int freq;
870
871 freq = atoi(cmd);
872 if (freq <= 0)
873 return -1;
874
875 if (os_strstr(cmd, " role=configurator"))
876 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
877 else if (os_strstr(cmd, " role=enrollee"))
878 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
879 else
880 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
881 DPP_CAPAB_ENROLLEE;
882 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
883
884 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
885 /* TODO: Listen operation on non-operating channel */
886 wpa_printf(MSG_INFO,
887 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
888 freq, hapd->iface->freq);
889 return -1;
890 }
891
892 return 0;
893}
894
895
896void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
897{
898 /* TODO: Stop listen operation on non-operating channel */
899}
900
901
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700902static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
903 const u8 *hdr, const u8 *buf, size_t len,
904 unsigned int freq)
905{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700906 const u8 *r_bootstrap, *i_bootstrap;
907 u16 r_bootstrap_len, i_bootstrap_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700908 struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL;
909
910 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
911 MAC2STR(src));
912
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700913 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
914 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700915 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
916 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
917 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700918 return;
919 }
920 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
921 r_bootstrap, r_bootstrap_len);
922
923 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
924 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700925 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
926 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
927 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700928 return;
929 }
930 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
931 i_bootstrap, i_bootstrap_len);
932
933 /* Try to find own and peer bootstrapping key matches based on the
934 * received hash values */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700935 dl_list_for_each(bi, &hapd->iface->interfaces->dpp_bootstrap,
936 struct dpp_bootstrap_info, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700937 if (!own_bi && bi->own &&
938 os_memcmp(bi->pubkey_hash, r_bootstrap,
939 SHA256_MAC_LEN) == 0) {
940 wpa_printf(MSG_DEBUG,
941 "DPP: Found matching own bootstrapping information");
942 own_bi = bi;
943 }
944
945 if (!peer_bi && !bi->own &&
946 os_memcmp(bi->pubkey_hash, i_bootstrap,
947 SHA256_MAC_LEN) == 0) {
948 wpa_printf(MSG_DEBUG,
949 "DPP: Found matching peer bootstrapping information");
950 peer_bi = bi;
951 }
952
953 if (own_bi && peer_bi)
954 break;
955 }
956
957 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700958 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
959 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700960 return;
961 }
962
963 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700964 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
965 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700966 return;
967 }
968
969 hapd->dpp_auth_ok_on_ack = 0;
970 hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
971 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700972 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700973 if (!hapd->dpp_auth) {
974 wpa_printf(MSG_DEBUG, "DPP: No response generated");
975 return;
976 }
977 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalom74f70d42019-02-11 14:42:39 -0800978 if (hostapd_dpp_set_configurator(hapd, hapd->dpp_auth,
979 hapd->dpp_configurator_params) < 0) {
980 dpp_auth_deinit(hapd->dpp_auth);
981 hapd->dpp_auth = NULL;
982 return;
983 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700984 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
985
Roshan Pius3a1667e2018-07-03 15:17:14 -0700986 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
987 " freq=%u type=%d",
988 MAC2STR(src), hapd->dpp_auth->curr_freq,
989 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700990 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
991 src, wpabuf_head(hapd->dpp_auth->resp_msg),
992 wpabuf_len(hapd->dpp_auth->resp_msg));
993}
994
995
Roshan Pius3a1667e2018-07-03 15:17:14 -0700996static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
997 struct dpp_authentication *auth)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700998{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700999 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001000 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
1001 dpp_akm_str(auth->akm));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001002 if (auth->ssid_len)
1003 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
1004 wpa_ssid_txt(auth->ssid, auth->ssid_len));
1005 if (auth->connector) {
1006 /* TODO: Save the Connector and consider using a command
1007 * to fetch the value instead of sending an event with
1008 * it. The Connector could end up being larger than what
1009 * most clients are ready to receive as an event
1010 * message. */
1011 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
1012 auth->connector);
1013 } else if (auth->passphrase[0]) {
1014 char hex[64 * 2 + 1];
1015
1016 wpa_snprintf_hex(hex, sizeof(hex),
1017 (const u8 *) auth->passphrase,
1018 os_strlen(auth->passphrase));
1019 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1020 hex);
1021 } else if (auth->psk_set) {
1022 char hex[PMK_LEN * 2 + 1];
1023
1024 wpa_snprintf_hex(hex, sizeof(hex), auth->psk, PMK_LEN);
1025 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1026 hex);
1027 }
1028 if (auth->c_sign_key) {
1029 char *hex;
1030 size_t hexlen;
1031
1032 hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
1033 hex = os_malloc(hexlen);
1034 if (hex) {
1035 wpa_snprintf_hex(hex, hexlen,
1036 wpabuf_head(auth->c_sign_key),
1037 wpabuf_len(auth->c_sign_key));
1038 wpa_msg(hapd->msg_ctx, MSG_INFO,
1039 DPP_EVENT_C_SIGN_KEY "%s", hex);
1040 os_free(hex);
1041 }
1042 }
1043 if (auth->net_access_key) {
1044 char *hex;
1045 size_t hexlen;
1046
1047 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1048 hex = os_malloc(hexlen);
1049 if (hex) {
1050 wpa_snprintf_hex(hex, hexlen,
1051 wpabuf_head(auth->net_access_key),
1052 wpabuf_len(auth->net_access_key));
1053 if (auth->net_access_key_expiry)
1054 wpa_msg(hapd->msg_ctx, MSG_INFO,
1055 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1056 (unsigned long)
1057 auth->net_access_key_expiry);
1058 else
1059 wpa_msg(hapd->msg_ctx, MSG_INFO,
1060 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1061 os_free(hex);
1062 }
1063 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001064}
1065
1066
1067static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1068 enum gas_query_ap_result result,
1069 const struct wpabuf *adv_proto,
1070 const struct wpabuf *resp, u16 status_code)
1071{
1072 struct hostapd_data *hapd = ctx;
1073 const u8 *pos;
1074 struct dpp_authentication *auth = hapd->dpp_auth;
1075
1076 if (!auth || !auth->auth_success) {
1077 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1078 return;
1079 }
1080 if (!resp || status_code != WLAN_STATUS_SUCCESS) {
1081 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1082 goto fail;
1083 }
1084
1085 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1086 adv_proto);
1087 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1088 resp);
1089
1090 if (wpabuf_len(adv_proto) != 10 ||
1091 !(pos = wpabuf_head(adv_proto)) ||
1092 pos[0] != WLAN_EID_ADV_PROTO ||
1093 pos[1] != 8 ||
1094 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1095 pos[4] != 5 ||
1096 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1097 pos[8] != 0x1a ||
1098 pos[9] != 1) {
1099 wpa_printf(MSG_DEBUG,
1100 "DPP: Not a DPP Advertisement Protocol ID");
1101 goto fail;
1102 }
1103
1104 if (dpp_conf_resp_rx(auth, resp) < 0) {
1105 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1106 goto fail;
1107 }
1108
1109 hostapd_dpp_handle_config_obj(hapd, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001110 dpp_auth_deinit(hapd->dpp_auth);
1111 hapd->dpp_auth = NULL;
1112 return;
1113
1114fail:
1115 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1116 dpp_auth_deinit(hapd->dpp_auth);
1117 hapd->dpp_auth = NULL;
1118}
1119
1120
1121static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
1122{
1123 struct dpp_authentication *auth = hapd->dpp_auth;
1124 struct wpabuf *buf, *conf_req;
1125 char json[100];
1126 int res;
1127 int netrole_ap = 1;
1128
1129 os_snprintf(json, sizeof(json),
1130 "{\"name\":\"Test\","
1131 "\"wi-fi_tech\":\"infra\","
1132 "\"netRole\":\"%s\"}",
1133 netrole_ap ? "ap" : "sta");
1134 wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
1135
1136 conf_req = dpp_build_conf_req(auth, json);
1137 if (!conf_req) {
1138 wpa_printf(MSG_DEBUG,
1139 "DPP: No configuration request data available");
1140 return;
1141 }
1142
1143 buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
1144 if (!buf) {
1145 wpabuf_free(conf_req);
1146 return;
1147 }
1148
1149 /* Advertisement Protocol IE */
1150 wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
1151 wpabuf_put_u8(buf, 8); /* Length */
1152 wpabuf_put_u8(buf, 0x7f);
1153 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
1154 wpabuf_put_u8(buf, 5);
1155 wpabuf_put_be24(buf, OUI_WFA);
1156 wpabuf_put_u8(buf, DPP_OUI_TYPE);
1157 wpabuf_put_u8(buf, 0x01);
1158
1159 /* GAS Query */
1160 wpabuf_put_le16(buf, wpabuf_len(conf_req));
1161 wpabuf_put_buf(buf, conf_req);
1162 wpabuf_free(conf_req);
1163
1164 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1165 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1166
1167 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
1168 buf, hostapd_dpp_gas_resp_cb, hapd);
1169 if (res < 0) {
1170 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1171 "GAS: Failed to send Query Request");
1172 wpabuf_free(buf);
1173 } else {
1174 wpa_printf(MSG_DEBUG,
1175 "DPP: GAS query started with dialog token %u", res);
1176 }
1177}
1178
1179
1180static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
1181{
1182 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1183 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
1184 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001185#ifdef CONFIG_TESTING_OPTIONS
1186 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1187 wpa_printf(MSG_INFO,
1188 "DPP: TESTING - stop at Authentication Confirm");
1189 if (hapd->dpp_auth->configurator) {
1190 /* Prevent GAS response */
1191 hapd->dpp_auth->auth_success = 0;
1192 }
1193 return;
1194 }
1195#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001196
1197 if (!hapd->dpp_auth->configurator)
1198 hostapd_dpp_start_gas_client(hapd);
1199}
1200
1201
1202static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001203 const u8 *hdr, const u8 *buf, size_t len,
1204 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001205{
1206 struct dpp_authentication *auth = hapd->dpp_auth;
1207 struct wpabuf *msg;
1208
1209 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
1210 MAC2STR(src));
1211
1212 if (!auth) {
1213 wpa_printf(MSG_DEBUG,
1214 "DPP: No DPP Authentication in progress - drop");
1215 return;
1216 }
1217
1218 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1219 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1220 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1221 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1222 return;
1223 }
1224
Roshan Pius3a1667e2018-07-03 15:17:14 -07001225 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1226
1227 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1228 wpa_printf(MSG_DEBUG,
1229 "DPP: Responder accepted request for different negotiation channel");
1230 auth->curr_freq = freq;
1231 }
1232
1233 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001234 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1235 if (!msg) {
1236 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1237 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
1238 return;
1239 }
1240 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1241 return;
1242 }
1243 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1244
Roshan Pius3a1667e2018-07-03 15:17:14 -07001245 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1246 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
1247 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001248 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
1249 wpabuf_head(msg), wpabuf_len(msg));
1250 wpabuf_free(msg);
1251 hapd->dpp_auth_ok_on_ack = 1;
1252}
1253
1254
1255static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1256 const u8 *hdr, const u8 *buf, size_t len)
1257{
1258 struct dpp_authentication *auth = hapd->dpp_auth;
1259
1260 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1261 MAC2STR(src));
1262
1263 if (!auth) {
1264 wpa_printf(MSG_DEBUG,
1265 "DPP: No DPP Authentication in progress - drop");
1266 return;
1267 }
1268
1269 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1270 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1271 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1272 return;
1273 }
1274
1275 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1276 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1277 return;
1278 }
1279
1280 hostapd_dpp_auth_success(hapd, 0);
1281}
1282
1283
Roshan Pius3a1667e2018-07-03 15:17:14 -07001284static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1285 const u8 *src, unsigned int freq,
1286 u8 trans_id,
1287 enum dpp_status_error status)
1288{
1289 struct wpabuf *msg;
1290
1291 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
1292 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
1293 if (!msg)
1294 return;
1295
1296#ifdef CONFIG_TESTING_OPTIONS
1297 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1298 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1299 goto skip_trans_id;
1300 }
1301 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1302 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1303 trans_id ^= 0x01;
1304 }
1305#endif /* CONFIG_TESTING_OPTIONS */
1306
1307 /* Transaction ID */
1308 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1309 wpabuf_put_le16(msg, 1);
1310 wpabuf_put_u8(msg, trans_id);
1311
1312#ifdef CONFIG_TESTING_OPTIONS
1313skip_trans_id:
1314 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1315 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1316 goto skip_status;
1317 }
1318 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1319 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1320 status = 254;
1321 }
1322#endif /* CONFIG_TESTING_OPTIONS */
1323
1324 /* DPP Status */
1325 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1326 wpabuf_put_le16(msg, 1);
1327 wpabuf_put_u8(msg, status);
1328
1329#ifdef CONFIG_TESTING_OPTIONS
1330skip_status:
1331 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1332 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1333 goto skip_connector;
1334 }
1335 if (status == DPP_STATUS_OK &&
1336 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1337 char *connector;
1338
1339 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1340 connector = dpp_corrupt_connector_signature(
1341 hapd->conf->dpp_connector);
1342 if (!connector) {
1343 wpabuf_free(msg);
1344 return;
1345 }
1346 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1347 wpabuf_put_le16(msg, os_strlen(connector));
1348 wpabuf_put_str(msg, connector);
1349 os_free(connector);
1350 goto skip_connector;
1351 }
1352#endif /* CONFIG_TESTING_OPTIONS */
1353
1354 /* DPP Connector */
1355 if (status == DPP_STATUS_OK) {
1356 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1357 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1358 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1359 }
1360
1361#ifdef CONFIG_TESTING_OPTIONS
1362skip_connector:
1363#endif /* CONFIG_TESTING_OPTIONS */
1364
1365 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1366 " status=%d", MAC2STR(src), status);
1367 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1368 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1369 DPP_PA_PEER_DISCOVERY_RESP, status);
1370 hostapd_drv_send_action(hapd, freq, 0, src,
1371 wpabuf_head(msg), wpabuf_len(msg));
1372 wpabuf_free(msg);
1373}
1374
1375
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001376static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1377 const u8 *src,
1378 const u8 *buf, size_t len,
1379 unsigned int freq)
1380{
1381 const u8 *connector, *trans_id;
1382 u16 connector_len, trans_id_len;
1383 struct os_time now;
1384 struct dpp_introduction intro;
1385 os_time_t expire;
1386 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001387 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001388
1389 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1390 MAC2STR(src));
1391 if (!hapd->wpa_auth ||
1392 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1393 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1394 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1395 return;
1396 }
1397
1398 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1399 !hapd->conf->dpp_csign) {
1400 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1401 return;
1402 }
1403
1404 os_get_time(&now);
1405
1406 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001407 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001408 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1409 return;
1410 }
1411
1412 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1413 &trans_id_len);
1414 if (!trans_id || trans_id_len != 1) {
1415 wpa_printf(MSG_DEBUG,
1416 "DPP: Peer did not include Transaction ID");
1417 return;
1418 }
1419
1420 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1421 if (!connector) {
1422 wpa_printf(MSG_DEBUG,
1423 "DPP: Peer did not include its Connector");
1424 return;
1425 }
1426
Roshan Pius3a1667e2018-07-03 15:17:14 -07001427 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1428 wpabuf_head(hapd->conf->dpp_netaccesskey),
1429 wpabuf_len(hapd->conf->dpp_netaccesskey),
1430 wpabuf_head(hapd->conf->dpp_csign),
1431 wpabuf_len(hapd->conf->dpp_csign),
1432 connector, connector_len, &expire);
1433 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001434 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001435 "DPP: Network Introduction protocol resulted in internal failure (peer "
1436 MACSTR ")", MAC2STR(src));
1437 return;
1438 }
1439 if (res != DPP_STATUS_OK) {
1440 wpa_printf(MSG_INFO,
1441 "DPP: Network Introduction protocol resulted in failure (peer "
1442 MACSTR " status %d)", MAC2STR(src), res);
1443 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1444 res);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001445 return;
1446 }
1447
Roshan Pius3a1667e2018-07-03 15:17:14 -07001448 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001449 expire = hapd->conf->dpp_netaccesskey_expiry;
1450 if (expire)
1451 expiration = expire - now.sec;
1452 else
1453 expiration = 0;
1454
1455 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1456 intro.pmkid, expiration,
1457 WPA_KEY_MGMT_DPP) < 0) {
1458 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
1459 return;
1460 }
1461
Roshan Pius3a1667e2018-07-03 15:17:14 -07001462 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1463 DPP_STATUS_OK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001464}
1465
1466
1467static void
1468hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
1469 const u8 *buf, size_t len,
1470 unsigned int freq)
1471{
1472 struct wpabuf *msg;
1473
1474 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1475 MAC2STR(src));
1476
1477 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1478 * values here */
1479
1480 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
1481 wpa_printf(MSG_DEBUG,
1482 "DPP: No PKEX code configured - ignore request");
1483 return;
1484 }
1485
1486 if (hapd->dpp_pkex) {
1487 /* TODO: Support parallel operations */
1488 wpa_printf(MSG_DEBUG,
1489 "DPP: Already in PKEX session - ignore new request");
1490 return;
1491 }
1492
Roshan Pius3a1667e2018-07-03 15:17:14 -07001493 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
1494 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001495 hapd->own_addr, src,
1496 hapd->dpp_pkex_identifier,
1497 hapd->dpp_pkex_code,
1498 buf, len);
1499 if (!hapd->dpp_pkex) {
1500 wpa_printf(MSG_DEBUG,
1501 "DPP: Failed to process the request - ignore it");
1502 return;
1503 }
1504
1505 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001506 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1507 " freq=%u type=%d", MAC2STR(src), freq,
1508 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001509 hostapd_drv_send_action(hapd, freq, 0, src,
1510 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001511 if (hapd->dpp_pkex->failed) {
1512 wpa_printf(MSG_DEBUG,
1513 "DPP: Terminate PKEX exchange due to an earlier error");
1514 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1515 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
1516 dpp_pkex_free(hapd->dpp_pkex);
1517 hapd->dpp_pkex = NULL;
1518 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001519}
1520
1521
1522static void
1523hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
1524 const u8 *buf, size_t len, unsigned int freq)
1525{
1526 struct wpabuf *msg;
1527
1528 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1529 MAC2STR(src));
1530
1531 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1532 * values here */
1533
1534 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
1535 hapd->dpp_pkex->exchange_done) {
1536 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1537 return;
1538 }
1539
Roshan Pius3a1667e2018-07-03 15:17:14 -07001540 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001541 if (!msg) {
1542 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1543 return;
1544 }
1545
1546 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1547 MAC2STR(src));
1548
Roshan Pius3a1667e2018-07-03 15:17:14 -07001549 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1550 " freq=%u type=%d", MAC2STR(src), freq,
1551 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001552 hostapd_drv_send_action(hapd, freq, 0, src,
1553 wpabuf_head(msg), wpabuf_len(msg));
1554 wpabuf_free(msg);
1555}
1556
1557
1558static void
1559hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
1560 const u8 *hdr, const u8 *buf, size_t len,
1561 unsigned int freq)
1562{
1563 struct wpabuf *msg;
1564 struct dpp_pkex *pkex = hapd->dpp_pkex;
1565 struct dpp_bootstrap_info *bi;
1566
1567 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1568 MAC2STR(src));
1569
1570 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1571 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1572 return;
1573 }
1574
1575 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1576 if (!msg) {
1577 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001578 if (hapd->dpp_pkex->failed) {
1579 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1580 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1581 hapd->dpp_pkex->own_bi->pkex_t =
1582 hapd->dpp_pkex->t;
1583 dpp_pkex_free(hapd->dpp_pkex);
1584 hapd->dpp_pkex = NULL;
1585 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001586 return;
1587 }
1588
1589 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1590 MACSTR, MAC2STR(src));
1591
Roshan Pius3a1667e2018-07-03 15:17:14 -07001592 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1593 " freq=%u type=%d", MAC2STR(src), freq,
1594 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001595 hostapd_drv_send_action(hapd, freq, 0, src,
1596 wpabuf_head(msg), wpabuf_len(msg));
1597 wpabuf_free(msg);
1598
1599 bi = os_zalloc(sizeof(*bi));
1600 if (!bi)
1601 return;
1602 bi->id = hapd_dpp_next_id(hapd);
1603 bi->type = DPP_BOOTSTRAP_PKEX;
1604 os_memcpy(bi->mac_addr, src, ETH_ALEN);
1605 bi->num_freq = 1;
1606 bi->freq[0] = freq;
1607 bi->curve = pkex->own_bi->curve;
1608 bi->pubkey = pkex->peer_bootstrap_key;
1609 pkex->peer_bootstrap_key = NULL;
1610 dpp_pkex_free(pkex);
1611 hapd->dpp_pkex = NULL;
1612 if (dpp_bootstrap_key_hash(bi) < 0) {
1613 dpp_bootstrap_info_free(bi);
1614 return;
1615 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001616 dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001617}
1618
1619
1620static void
1621hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
1622 const u8 *hdr, const u8 *buf, size_t len,
1623 unsigned int freq)
1624{
1625 int res;
1626 struct dpp_bootstrap_info *bi, *own_bi;
1627 struct dpp_pkex *pkex = hapd->dpp_pkex;
1628 char cmd[500];
1629
1630 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
1631 MAC2STR(src));
1632
1633 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1634 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1635 return;
1636 }
1637
1638 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1639 if (res < 0) {
1640 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1641 return;
1642 }
1643
1644 own_bi = pkex->own_bi;
1645
1646 bi = os_zalloc(sizeof(*bi));
1647 if (!bi)
1648 return;
1649 bi->id = hapd_dpp_next_id(hapd);
1650 bi->type = DPP_BOOTSTRAP_PKEX;
1651 os_memcpy(bi->mac_addr, src, ETH_ALEN);
1652 bi->num_freq = 1;
1653 bi->freq[0] = freq;
1654 bi->curve = own_bi->curve;
1655 bi->pubkey = pkex->peer_bootstrap_key;
1656 pkex->peer_bootstrap_key = NULL;
1657 dpp_pkex_free(pkex);
1658 hapd->dpp_pkex = NULL;
1659 if (dpp_bootstrap_key_hash(bi) < 0) {
1660 dpp_bootstrap_info_free(bi);
1661 return;
1662 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001663 dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001664
1665 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
1666 bi->id,
1667 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
1668 wpa_printf(MSG_DEBUG,
1669 "DPP: Start authentication after PKEX with parameters: %s",
1670 cmd);
1671 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
1672 wpa_printf(MSG_DEBUG,
1673 "DPP: Authentication initialization failed");
1674 return;
1675 }
1676}
1677
1678
1679void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
1680 const u8 *buf, size_t len, unsigned int freq)
1681{
1682 u8 crypto_suite;
1683 enum dpp_public_action_frame_type type;
1684 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001685 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001686
1687 if (len < DPP_HDR_LEN)
1688 return;
1689 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
1690 return;
1691 hdr = buf;
1692 buf += 4;
1693 len -= 4;
1694 crypto_suite = *buf++;
1695 type = *buf++;
1696 len -= 2;
1697
1698 wpa_printf(MSG_DEBUG,
1699 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
1700 MACSTR " freq=%u",
1701 crypto_suite, type, MAC2STR(src), freq);
1702 if (crypto_suite != 1) {
1703 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
1704 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001705 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1706 " freq=%u type=%d ignore=unsupported-crypto-suite",
1707 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001708 return;
1709 }
1710 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001711 if (dpp_check_attrs(buf, len) < 0) {
1712 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1713 " freq=%u type=%d ignore=invalid-attributes",
1714 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001715 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001716 }
1717 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1718 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001719
1720 switch (type) {
1721 case DPP_PA_AUTHENTICATION_REQ:
1722 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
1723 break;
1724 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07001725 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001726 break;
1727 case DPP_PA_AUTHENTICATION_CONF:
1728 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
1729 break;
1730 case DPP_PA_PEER_DISCOVERY_REQ:
1731 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
1732 break;
1733 case DPP_PA_PKEX_EXCHANGE_REQ:
1734 hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
1735 break;
1736 case DPP_PA_PKEX_EXCHANGE_RESP:
1737 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
1738 break;
1739 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1740 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
1741 freq);
1742 break;
1743 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1744 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
1745 freq);
1746 break;
1747 default:
1748 wpa_printf(MSG_DEBUG,
1749 "DPP: Ignored unsupported frame subtype %d", type);
1750 break;
1751 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001752
1753 if (hapd->dpp_pkex)
1754 pkex_t = hapd->dpp_pkex->t;
1755 else if (hapd->dpp_pkex_bi)
1756 pkex_t = hapd->dpp_pkex_bi->pkex_t;
1757 else
1758 pkex_t = 0;
1759 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
1760 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
1761 hostapd_dpp_pkex_remove(hapd, "*");
1762 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001763}
1764
1765
1766struct wpabuf *
1767hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
1768 const u8 *query, size_t query_len)
1769{
1770 struct dpp_authentication *auth = hapd->dpp_auth;
1771 struct wpabuf *resp;
1772
1773 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
1774 if (!auth || !auth->auth_success ||
1775 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
1776 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1777 return NULL;
1778 }
1779 wpa_hexdump(MSG_DEBUG,
1780 "DPP: Received Configuration Request (GAS Query Request)",
1781 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001782 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
1783 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001784 resp = dpp_conf_req_rx(auth, query, query_len);
1785 if (!resp)
1786 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1787 return resp;
1788}
1789
1790
Roshan Pius3a1667e2018-07-03 15:17:14 -07001791void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
1792{
1793 if (!hapd->dpp_auth)
1794 return;
1795
1796 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1797 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
1798 hostapd_drv_send_action_cancel_wait(hapd);
1799
1800 if (ok)
1801 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1802 else
1803 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1804 dpp_auth_deinit(hapd->dpp_auth);
1805 hapd->dpp_auth = NULL;
1806}
1807
1808
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001809static unsigned int hostapd_dpp_next_configurator_id(struct hostapd_data *hapd)
1810{
1811 struct dpp_configurator *conf;
1812 unsigned int max_id = 0;
1813
Roshan Pius3a1667e2018-07-03 15:17:14 -07001814 dl_list_for_each(conf, &hapd->iface->interfaces->dpp_configurator,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001815 struct dpp_configurator, list) {
1816 if (conf->id > max_id)
1817 max_id = conf->id;
1818 }
1819 return max_id + 1;
1820}
1821
1822
1823int hostapd_dpp_configurator_add(struct hostapd_data *hapd, const char *cmd)
1824{
1825 char *curve = NULL;
1826 char *key = NULL;
1827 u8 *privkey = NULL;
1828 size_t privkey_len = 0;
1829 int ret = -1;
1830 struct dpp_configurator *conf = NULL;
1831
1832 curve = get_param(cmd, " curve=");
1833 key = get_param(cmd, " key=");
1834
1835 if (key) {
1836 privkey_len = os_strlen(key) / 2;
1837 privkey = os_malloc(privkey_len);
1838 if (!privkey ||
1839 hexstr2bin(key, privkey, privkey_len) < 0)
1840 goto fail;
1841 }
1842
1843 conf = dpp_keygen_configurator(curve, privkey, privkey_len);
1844 if (!conf)
1845 goto fail;
1846
1847 conf->id = hostapd_dpp_next_configurator_id(hapd);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001848 dl_list_add(&hapd->iface->interfaces->dpp_configurator, &conf->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001849 ret = conf->id;
1850 conf = NULL;
1851fail:
1852 os_free(curve);
1853 str_clear_free(key);
1854 bin_clear_free(privkey, privkey_len);
1855 dpp_configurator_free(conf);
1856 return ret;
1857}
1858
1859
Roshan Pius3a1667e2018-07-03 15:17:14 -07001860static int dpp_configurator_del(struct hapd_interfaces *ifaces, unsigned int id)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001861{
1862 struct dpp_configurator *conf, *tmp;
1863 int found = 0;
1864
Roshan Pius3a1667e2018-07-03 15:17:14 -07001865 dl_list_for_each_safe(conf, tmp, &ifaces->dpp_configurator,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001866 struct dpp_configurator, list) {
1867 if (id && conf->id != id)
1868 continue;
1869 found = 1;
1870 dl_list_del(&conf->list);
1871 dpp_configurator_free(conf);
1872 }
1873
1874 if (id == 0)
1875 return 0; /* flush succeeds regardless of entries found */
1876 return found ? 0 : -1;
1877}
1878
1879
1880int hostapd_dpp_configurator_remove(struct hostapd_data *hapd, const char *id)
1881{
1882 unsigned int id_val;
1883
1884 if (os_strcmp(id, "*") == 0) {
1885 id_val = 0;
1886 } else {
1887 id_val = atoi(id);
1888 if (id_val == 0)
1889 return -1;
1890 }
1891
Roshan Pius3a1667e2018-07-03 15:17:14 -07001892 return dpp_configurator_del(hapd->iface->interfaces, id_val);
1893}
1894
1895
1896int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
1897{
1898 struct dpp_authentication *auth;
1899 int ret = -1;
1900 char *curve = NULL;
1901
1902 auth = os_zalloc(sizeof(*auth));
1903 if (!auth)
1904 return -1;
1905
1906 curve = get_param(cmd, " curve=");
Hai Shalom74f70d42019-02-11 14:42:39 -08001907 hostapd_dpp_set_testing_options(hapd, auth);
1908 if (hostapd_dpp_set_configurator(hapd, auth, cmd) == 0 &&
1909 dpp_configurator_own_config(auth, curve, 1) == 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001910 hostapd_dpp_handle_config_obj(hapd, auth);
1911 ret = 0;
1912 }
1913
1914 dpp_auth_deinit(auth);
1915 os_free(curve);
1916
1917 return ret;
1918}
1919
1920
1921int hostapd_dpp_configurator_get_key(struct hostapd_data *hapd, unsigned int id,
1922 char *buf, size_t buflen)
1923{
1924 struct dpp_configurator *conf;
1925
1926 conf = hostapd_dpp_configurator_get_id(hapd, id);
1927 if (!conf)
1928 return -1;
1929
1930 return dpp_configurator_get_key(conf, buf, buflen);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001931}
1932
1933
1934int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
1935{
1936 struct dpp_bootstrap_info *own_bi;
1937 const char *pos, *end;
1938
1939 pos = os_strstr(cmd, " own=");
1940 if (!pos)
1941 return -1;
1942 pos += 5;
1943 own_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
1944 if (!own_bi) {
1945 wpa_printf(MSG_DEBUG,
1946 "DPP: Identified bootstrap info not found");
1947 return -1;
1948 }
1949 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
1950 wpa_printf(MSG_DEBUG,
1951 "DPP: Identified bootstrap info not for PKEX");
1952 return -1;
1953 }
1954 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001955 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001956
1957 os_free(hapd->dpp_pkex_identifier);
1958 hapd->dpp_pkex_identifier = NULL;
1959 pos = os_strstr(cmd, " identifier=");
1960 if (pos) {
1961 pos += 12;
1962 end = os_strchr(pos, ' ');
1963 if (!end)
1964 return -1;
1965 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
1966 if (!hapd->dpp_pkex_identifier)
1967 return -1;
1968 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
1969 hapd->dpp_pkex_identifier[end - pos] = '\0';
1970 }
1971
1972 pos = os_strstr(cmd, " code=");
1973 if (!pos)
1974 return -1;
1975 os_free(hapd->dpp_pkex_code);
1976 hapd->dpp_pkex_code = os_strdup(pos + 6);
1977 if (!hapd->dpp_pkex_code)
1978 return -1;
1979
1980 if (os_strstr(cmd, " init=1")) {
1981 struct wpabuf *msg;
1982
1983 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
1984 dpp_pkex_free(hapd->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001985 hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
1986 hapd->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001987 hapd->dpp_pkex_identifier,
1988 hapd->dpp_pkex_code);
1989 if (!hapd->dpp_pkex)
1990 return -1;
1991
1992 msg = hapd->dpp_pkex->exchange_req;
1993 /* TODO: Which channel to use? */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001994 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1995 " freq=%u type=%d", MAC2STR(broadcast), 2437,
1996 DPP_PA_PKEX_EXCHANGE_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001997 hostapd_drv_send_action(hapd, 2437, 0, broadcast,
1998 wpabuf_head(msg), wpabuf_len(msg));
1999 }
2000
2001 /* TODO: Support multiple PKEX info entries */
2002
2003 os_free(hapd->dpp_pkex_auth_cmd);
2004 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
2005
2006 return 1;
2007}
2008
2009
2010int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
2011{
2012 unsigned int id_val;
2013
2014 if (os_strcmp(id, "*") == 0) {
2015 id_val = 0;
2016 } else {
2017 id_val = atoi(id);
2018 if (id_val == 0)
2019 return -1;
2020 }
2021
2022 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
2023 return -1;
2024
2025 /* TODO: Support multiple PKEX entries */
2026 os_free(hapd->dpp_pkex_code);
2027 hapd->dpp_pkex_code = NULL;
2028 os_free(hapd->dpp_pkex_identifier);
2029 hapd->dpp_pkex_identifier = NULL;
2030 os_free(hapd->dpp_pkex_auth_cmd);
2031 hapd->dpp_pkex_auth_cmd = NULL;
2032 hapd->dpp_pkex_bi = NULL;
2033 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2034 dpp_pkex_free(hapd->dpp_pkex);
2035 hapd->dpp_pkex = NULL;
2036 return 0;
2037}
2038
2039
Roshan Pius3a1667e2018-07-03 15:17:14 -07002040void hostapd_dpp_stop(struct hostapd_data *hapd)
2041{
2042 dpp_auth_deinit(hapd->dpp_auth);
2043 hapd->dpp_auth = NULL;
2044 dpp_pkex_free(hapd->dpp_pkex);
2045 hapd->dpp_pkex = NULL;
2046}
2047
2048
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002049int hostapd_dpp_init(struct hostapd_data *hapd)
2050{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002051 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
2052 hapd->dpp_init_done = 1;
2053 return 0;
2054}
2055
2056
2057void hostapd_dpp_deinit(struct hostapd_data *hapd)
2058{
2059#ifdef CONFIG_TESTING_OPTIONS
2060 os_free(hapd->dpp_config_obj_override);
2061 hapd->dpp_config_obj_override = NULL;
2062 os_free(hapd->dpp_discovery_override);
2063 hapd->dpp_discovery_override = NULL;
2064 os_free(hapd->dpp_groups_override);
2065 hapd->dpp_groups_override = NULL;
2066 hapd->dpp_ignore_netaccesskey_mismatch = 0;
2067#endif /* CONFIG_TESTING_OPTIONS */
2068 if (!hapd->dpp_init_done)
2069 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002070 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
2071 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
2072 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002073 dpp_auth_deinit(hapd->dpp_auth);
2074 hapd->dpp_auth = NULL;
2075 hostapd_dpp_pkex_remove(hapd, "*");
2076 hapd->dpp_pkex = NULL;
2077 os_free(hapd->dpp_configurator_params);
2078 hapd->dpp_configurator_params = NULL;
2079}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002080
2081
2082void hostapd_dpp_init_global(struct hapd_interfaces *ifaces)
2083{
2084 dl_list_init(&ifaces->dpp_bootstrap);
2085 dl_list_init(&ifaces->dpp_configurator);
2086 ifaces->dpp_init_done = 1;
2087}
2088
2089
2090void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces)
2091{
2092 if (!ifaces->dpp_init_done)
2093 return;
2094 dpp_bootstrap_del(ifaces, 0);
2095 dpp_configurator_del(ifaces, 0);
2096}