blob: 4ec044e175cae4cb6a57a25e613d13715df12cf1 [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 Shalombf6e0ba2019-02-11 12:01:50 -0800508static void 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 Shalombf6e0ba2019-02-11 12:01:50 -0800524 return;
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 Shalombf6e0ba2019-02-11 12:01:50 -0800621 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700622 conf_ap->passphrase = os_strdup(pass);
623 if (!conf_ap->passphrase)
624 goto fail;
625 }
626 } else if (os_strstr(cmd, " conf=ap-dpp")) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700627 conf_ap->akm = DPP_AKM_DPP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700628 } else {
629 goto fail;
630 }
Hai Shalomce48b4a2018-09-05 11:41:35 -0700631 if (os_strstr(cmd, " group_id=")) {
632 conf_ap->group_id = group_id;
633 group_id = NULL;
634 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700635 }
636
637 pos = os_strstr(cmd, " expiry=");
638 if (pos) {
639 long int val;
640
641 pos += 8;
642 val = strtol(pos, NULL, 0);
643 if (val <= 0)
644 goto fail;
645 if (conf_sta)
646 conf_sta->netaccesskey_expiry = val;
647 if (conf_ap)
648 conf_ap->netaccesskey_expiry = val;
649 }
650
651 pos = os_strstr(cmd, " configurator=");
652 if (pos) {
653 auth->configurator = 1;
654 pos += 14;
655 conf = hostapd_dpp_configurator_get_id(hapd, atoi(pos));
656 if (!conf) {
657 wpa_printf(MSG_INFO,
658 "DPP: Could not find the specified configurator");
659 goto fail;
660 }
661 }
662 auth->conf_sta = conf_sta;
663 auth->conf_ap = conf_ap;
664 auth->conf = conf;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700665 os_free(group_id);
Hai Shalombf6e0ba2019-02-11 12:01:50 -0800666 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700667
668fail:
Hai Shalombf6e0ba2019-02-11 12:01:50 -0800669 wpa_printf(MSG_DEBUG, "DPP: Failed to set configurator parameters");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700670 dpp_configuration_free(conf_sta);
671 dpp_configuration_free(conf_ap);
Hai Shalomce48b4a2018-09-05 11:41:35 -0700672 os_free(group_id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700673}
674
675
Roshan Pius3a1667e2018-07-03 15:17:14 -0700676static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
677{
678 struct hostapd_data *hapd = eloop_ctx;
679
680 if (!hapd->dpp_auth)
681 return;
682 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
683 hostapd_dpp_auth_init_next(hapd);
684}
685
686
687static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
688{
689 struct dpp_authentication *auth = hapd->dpp_auth;
690 const u8 *dst;
691 unsigned int wait_time, max_wait_time, freq, max_tries, used;
692 struct os_reltime now, diff;
693
694 if (!auth)
695 return -1;
696
697 if (auth->freq_idx == 0)
698 os_get_reltime(&hapd->dpp_init_iter_start);
699
700 if (auth->freq_idx >= auth->num_freq) {
701 auth->num_freq_iters++;
702 if (hapd->dpp_init_max_tries)
703 max_tries = hapd->dpp_init_max_tries;
704 else
705 max_tries = 5;
706 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
707 wpa_printf(MSG_INFO,
708 "DPP: No response received from responder - stopping initiation attempt");
709 wpa_msg(hapd->msg_ctx, MSG_INFO,
710 DPP_EVENT_AUTH_INIT_FAILED);
711 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
712 hapd, NULL);
713 hostapd_drv_send_action_cancel_wait(hapd);
714 dpp_auth_deinit(hapd->dpp_auth);
715 hapd->dpp_auth = NULL;
716 return -1;
717 }
718 auth->freq_idx = 0;
719 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
720 if (hapd->dpp_init_retry_time)
721 wait_time = hapd->dpp_init_retry_time;
722 else
723 wait_time = 10000;
724 os_get_reltime(&now);
725 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
726 used = diff.sec * 1000 + diff.usec / 1000;
727 if (used > wait_time)
728 wait_time = 0;
729 else
730 wait_time -= used;
731 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
732 wait_time);
733 eloop_register_timeout(wait_time / 1000,
734 (wait_time % 1000) * 1000,
735 hostapd_dpp_init_timeout, hapd,
736 NULL);
737 return 0;
738 }
739 freq = auth->freq[auth->freq_idx++];
740 auth->curr_freq = freq;
741
742 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
743 dst = broadcast;
744 else
745 dst = auth->peer_bi->mac_addr;
746 hapd->dpp_auth_ok_on_ack = 0;
747 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
748 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
749 max_wait_time = hapd->dpp_resp_wait_time ?
750 hapd->dpp_resp_wait_time : 2000;
751 if (wait_time > max_wait_time)
752 wait_time = max_wait_time;
753 wait_time += 10; /* give the driver some extra time to complete */
754 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
755 hostapd_dpp_reply_wait_timeout, hapd, NULL);
756 wait_time -= 10;
757 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
758 wpa_printf(MSG_DEBUG,
759 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
760 freq, auth->neg_freq);
761 }
762 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
763 " freq=%u type=%d",
764 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
765 auth->auth_req_ack = 0;
766 os_get_reltime(&hapd->dpp_last_init);
767 return hostapd_drv_send_action(hapd, freq, wait_time,
768 dst,
769 wpabuf_head(hapd->dpp_auth->req_msg),
770 wpabuf_len(hapd->dpp_auth->req_msg));
771}
772
773
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700774int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
775{
776 const char *pos;
777 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700778 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
779 unsigned int neg_freq = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700780
781 pos = os_strstr(cmd, " peer=");
782 if (!pos)
783 return -1;
784 pos += 6;
785 peer_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
786 if (!peer_bi) {
787 wpa_printf(MSG_INFO,
788 "DPP: Could not find bootstrapping info for the identified peer");
789 return -1;
790 }
791
792 pos = os_strstr(cmd, " own=");
793 if (pos) {
794 pos += 5;
795 own_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
796 if (!own_bi) {
797 wpa_printf(MSG_INFO,
798 "DPP: Could not find bootstrapping info for the identified local entry");
799 return -1;
800 }
801
802 if (peer_bi->curve != own_bi->curve) {
803 wpa_printf(MSG_INFO,
804 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
805 peer_bi->curve->name, own_bi->curve->name);
806 return -1;
807 }
808 }
809
810 pos = os_strstr(cmd, " role=");
811 if (pos) {
812 pos += 6;
813 if (os_strncmp(pos, "configurator", 12) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700814 allowed_roles = DPP_CAPAB_CONFIGURATOR;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700815 else if (os_strncmp(pos, "enrollee", 8) == 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700816 allowed_roles = DPP_CAPAB_ENROLLEE;
817 else if (os_strncmp(pos, "either", 6) == 0)
818 allowed_roles = DPP_CAPAB_CONFIGURATOR |
819 DPP_CAPAB_ENROLLEE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700820 else
821 goto fail;
822 }
823
Roshan Pius3a1667e2018-07-03 15:17:14 -0700824 pos = os_strstr(cmd, " neg_freq=");
825 if (pos)
826 neg_freq = atoi(pos + 10);
827
828 if (hapd->dpp_auth) {
829 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
830 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
831 hapd, NULL);
832 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
833 NULL);
834 hostapd_drv_send_action_cancel_wait(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700835 dpp_auth_deinit(hapd->dpp_auth);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700836 }
837
838 hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
839 allowed_roles, neg_freq,
840 hapd->iface->hw_features,
841 hapd->iface->num_hw_features);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700842 if (!hapd->dpp_auth)
843 goto fail;
844 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalombf6e0ba2019-02-11 12:01:50 -0800845 hostapd_dpp_set_configurator(hapd, hapd->dpp_auth, cmd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700846
Roshan Pius3a1667e2018-07-03 15:17:14 -0700847 hapd->dpp_auth->neg_freq = neg_freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700848
Roshan Pius3a1667e2018-07-03 15:17:14 -0700849 if (!is_zero_ether_addr(peer_bi->mac_addr))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700850 os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
851 ETH_ALEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700852
Roshan Pius3a1667e2018-07-03 15:17:14 -0700853 return hostapd_dpp_auth_init_next(hapd);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700854fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700855 return -1;
856}
857
858
Roshan Pius3a1667e2018-07-03 15:17:14 -0700859int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
860{
861 int freq;
862
863 freq = atoi(cmd);
864 if (freq <= 0)
865 return -1;
866
867 if (os_strstr(cmd, " role=configurator"))
868 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
869 else if (os_strstr(cmd, " role=enrollee"))
870 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
871 else
872 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
873 DPP_CAPAB_ENROLLEE;
874 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
875
876 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
877 /* TODO: Listen operation on non-operating channel */
878 wpa_printf(MSG_INFO,
879 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
880 freq, hapd->iface->freq);
881 return -1;
882 }
883
884 return 0;
885}
886
887
888void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
889{
890 /* TODO: Stop listen operation on non-operating channel */
891}
892
893
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700894static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
895 const u8 *hdr, const u8 *buf, size_t len,
896 unsigned int freq)
897{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700898 const u8 *r_bootstrap, *i_bootstrap;
899 u16 r_bootstrap_len, i_bootstrap_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700900 struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL;
901
902 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
903 MAC2STR(src));
904
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700905 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
906 &r_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700907 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
908 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
909 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700910 return;
911 }
912 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
913 r_bootstrap, r_bootstrap_len);
914
915 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
916 &i_bootstrap_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700917 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
918 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
919 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700920 return;
921 }
922 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
923 i_bootstrap, i_bootstrap_len);
924
925 /* Try to find own and peer bootstrapping key matches based on the
926 * received hash values */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700927 dl_list_for_each(bi, &hapd->iface->interfaces->dpp_bootstrap,
928 struct dpp_bootstrap_info, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700929 if (!own_bi && bi->own &&
930 os_memcmp(bi->pubkey_hash, r_bootstrap,
931 SHA256_MAC_LEN) == 0) {
932 wpa_printf(MSG_DEBUG,
933 "DPP: Found matching own bootstrapping information");
934 own_bi = bi;
935 }
936
937 if (!peer_bi && !bi->own &&
938 os_memcmp(bi->pubkey_hash, i_bootstrap,
939 SHA256_MAC_LEN) == 0) {
940 wpa_printf(MSG_DEBUG,
941 "DPP: Found matching peer bootstrapping information");
942 peer_bi = bi;
943 }
944
945 if (own_bi && peer_bi)
946 break;
947 }
948
949 if (!own_bi) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700950 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
951 "No matching own bootstrapping key found - ignore message");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700952 return;
953 }
954
955 if (hapd->dpp_auth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700956 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
957 "Already in DPP authentication exchange - ignore new one");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700958 return;
959 }
960
961 hapd->dpp_auth_ok_on_ack = 0;
962 hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
963 hapd->dpp_qr_mutual,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700964 peer_bi, own_bi, freq, hdr, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700965 if (!hapd->dpp_auth) {
966 wpa_printf(MSG_DEBUG, "DPP: No response generated");
967 return;
968 }
969 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
Hai Shalombf6e0ba2019-02-11 12:01:50 -0800970 hostapd_dpp_set_configurator(hapd, hapd->dpp_auth,
971 hapd->dpp_configurator_params);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700972 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
973
Roshan Pius3a1667e2018-07-03 15:17:14 -0700974 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
975 " freq=%u type=%d",
976 MAC2STR(src), hapd->dpp_auth->curr_freq,
977 DPP_PA_AUTHENTICATION_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700978 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
979 src, wpabuf_head(hapd->dpp_auth->resp_msg),
980 wpabuf_len(hapd->dpp_auth->resp_msg));
981}
982
983
Roshan Pius3a1667e2018-07-03 15:17:14 -0700984static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
985 struct dpp_authentication *auth)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700986{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700987 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700988 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
989 dpp_akm_str(auth->akm));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700990 if (auth->ssid_len)
991 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
992 wpa_ssid_txt(auth->ssid, auth->ssid_len));
993 if (auth->connector) {
994 /* TODO: Save the Connector and consider using a command
995 * to fetch the value instead of sending an event with
996 * it. The Connector could end up being larger than what
997 * most clients are ready to receive as an event
998 * message. */
999 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
1000 auth->connector);
1001 } else if (auth->passphrase[0]) {
1002 char hex[64 * 2 + 1];
1003
1004 wpa_snprintf_hex(hex, sizeof(hex),
1005 (const u8 *) auth->passphrase,
1006 os_strlen(auth->passphrase));
1007 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
1008 hex);
1009 } else if (auth->psk_set) {
1010 char hex[PMK_LEN * 2 + 1];
1011
1012 wpa_snprintf_hex(hex, sizeof(hex), auth->psk, PMK_LEN);
1013 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
1014 hex);
1015 }
1016 if (auth->c_sign_key) {
1017 char *hex;
1018 size_t hexlen;
1019
1020 hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
1021 hex = os_malloc(hexlen);
1022 if (hex) {
1023 wpa_snprintf_hex(hex, hexlen,
1024 wpabuf_head(auth->c_sign_key),
1025 wpabuf_len(auth->c_sign_key));
1026 wpa_msg(hapd->msg_ctx, MSG_INFO,
1027 DPP_EVENT_C_SIGN_KEY "%s", hex);
1028 os_free(hex);
1029 }
1030 }
1031 if (auth->net_access_key) {
1032 char *hex;
1033 size_t hexlen;
1034
1035 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
1036 hex = os_malloc(hexlen);
1037 if (hex) {
1038 wpa_snprintf_hex(hex, hexlen,
1039 wpabuf_head(auth->net_access_key),
1040 wpabuf_len(auth->net_access_key));
1041 if (auth->net_access_key_expiry)
1042 wpa_msg(hapd->msg_ctx, MSG_INFO,
1043 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
1044 (unsigned long)
1045 auth->net_access_key_expiry);
1046 else
1047 wpa_msg(hapd->msg_ctx, MSG_INFO,
1048 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
1049 os_free(hex);
1050 }
1051 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001052}
1053
1054
1055static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
1056 enum gas_query_ap_result result,
1057 const struct wpabuf *adv_proto,
1058 const struct wpabuf *resp, u16 status_code)
1059{
1060 struct hostapd_data *hapd = ctx;
1061 const u8 *pos;
1062 struct dpp_authentication *auth = hapd->dpp_auth;
1063
1064 if (!auth || !auth->auth_success) {
1065 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1066 return;
1067 }
1068 if (!resp || status_code != WLAN_STATUS_SUCCESS) {
1069 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
1070 goto fail;
1071 }
1072
1073 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
1074 adv_proto);
1075 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
1076 resp);
1077
1078 if (wpabuf_len(adv_proto) != 10 ||
1079 !(pos = wpabuf_head(adv_proto)) ||
1080 pos[0] != WLAN_EID_ADV_PROTO ||
1081 pos[1] != 8 ||
1082 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
1083 pos[4] != 5 ||
1084 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
1085 pos[8] != 0x1a ||
1086 pos[9] != 1) {
1087 wpa_printf(MSG_DEBUG,
1088 "DPP: Not a DPP Advertisement Protocol ID");
1089 goto fail;
1090 }
1091
1092 if (dpp_conf_resp_rx(auth, resp) < 0) {
1093 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1094 goto fail;
1095 }
1096
1097 hostapd_dpp_handle_config_obj(hapd, auth);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001098 dpp_auth_deinit(hapd->dpp_auth);
1099 hapd->dpp_auth = NULL;
1100 return;
1101
1102fail:
1103 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1104 dpp_auth_deinit(hapd->dpp_auth);
1105 hapd->dpp_auth = NULL;
1106}
1107
1108
1109static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
1110{
1111 struct dpp_authentication *auth = hapd->dpp_auth;
1112 struct wpabuf *buf, *conf_req;
1113 char json[100];
1114 int res;
1115 int netrole_ap = 1;
1116
1117 os_snprintf(json, sizeof(json),
1118 "{\"name\":\"Test\","
1119 "\"wi-fi_tech\":\"infra\","
1120 "\"netRole\":\"%s\"}",
1121 netrole_ap ? "ap" : "sta");
1122 wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
1123
1124 conf_req = dpp_build_conf_req(auth, json);
1125 if (!conf_req) {
1126 wpa_printf(MSG_DEBUG,
1127 "DPP: No configuration request data available");
1128 return;
1129 }
1130
1131 buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
1132 if (!buf) {
1133 wpabuf_free(conf_req);
1134 return;
1135 }
1136
1137 /* Advertisement Protocol IE */
1138 wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
1139 wpabuf_put_u8(buf, 8); /* Length */
1140 wpabuf_put_u8(buf, 0x7f);
1141 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
1142 wpabuf_put_u8(buf, 5);
1143 wpabuf_put_be24(buf, OUI_WFA);
1144 wpabuf_put_u8(buf, DPP_OUI_TYPE);
1145 wpabuf_put_u8(buf, 0x01);
1146
1147 /* GAS Query */
1148 wpabuf_put_le16(buf, wpabuf_len(conf_req));
1149 wpabuf_put_buf(buf, conf_req);
1150 wpabuf_free(conf_req);
1151
1152 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
1153 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
1154
1155 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
1156 buf, hostapd_dpp_gas_resp_cb, hapd);
1157 if (res < 0) {
1158 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1159 "GAS: Failed to send Query Request");
1160 wpabuf_free(buf);
1161 } else {
1162 wpa_printf(MSG_DEBUG,
1163 "DPP: GAS query started with dialog token %u", res);
1164 }
1165}
1166
1167
1168static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
1169{
1170 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
1171 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
1172 initiator);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001173#ifdef CONFIG_TESTING_OPTIONS
1174 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
1175 wpa_printf(MSG_INFO,
1176 "DPP: TESTING - stop at Authentication Confirm");
1177 if (hapd->dpp_auth->configurator) {
1178 /* Prevent GAS response */
1179 hapd->dpp_auth->auth_success = 0;
1180 }
1181 return;
1182 }
1183#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001184
1185 if (!hapd->dpp_auth->configurator)
1186 hostapd_dpp_start_gas_client(hapd);
1187}
1188
1189
1190static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001191 const u8 *hdr, const u8 *buf, size_t len,
1192 unsigned int freq)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001193{
1194 struct dpp_authentication *auth = hapd->dpp_auth;
1195 struct wpabuf *msg;
1196
1197 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
1198 MAC2STR(src));
1199
1200 if (!auth) {
1201 wpa_printf(MSG_DEBUG,
1202 "DPP: No DPP Authentication in progress - drop");
1203 return;
1204 }
1205
1206 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
1207 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1208 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1209 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1210 return;
1211 }
1212
Roshan Pius3a1667e2018-07-03 15:17:14 -07001213 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1214
1215 if (auth->curr_freq != freq && auth->neg_freq == freq) {
1216 wpa_printf(MSG_DEBUG,
1217 "DPP: Responder accepted request for different negotiation channel");
1218 auth->curr_freq = freq;
1219 }
1220
1221 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001222 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
1223 if (!msg) {
1224 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
1225 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
1226 return;
1227 }
1228 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
1229 return;
1230 }
1231 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
1232
Roshan Pius3a1667e2018-07-03 15:17:14 -07001233 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1234 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
1235 DPP_PA_AUTHENTICATION_CONF);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001236 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
1237 wpabuf_head(msg), wpabuf_len(msg));
1238 wpabuf_free(msg);
1239 hapd->dpp_auth_ok_on_ack = 1;
1240}
1241
1242
1243static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
1244 const u8 *hdr, const u8 *buf, size_t len)
1245{
1246 struct dpp_authentication *auth = hapd->dpp_auth;
1247
1248 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
1249 MAC2STR(src));
1250
1251 if (!auth) {
1252 wpa_printf(MSG_DEBUG,
1253 "DPP: No DPP Authentication in progress - drop");
1254 return;
1255 }
1256
1257 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
1258 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
1259 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
1260 return;
1261 }
1262
1263 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
1264 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
1265 return;
1266 }
1267
1268 hostapd_dpp_auth_success(hapd, 0);
1269}
1270
1271
Roshan Pius3a1667e2018-07-03 15:17:14 -07001272static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
1273 const u8 *src, unsigned int freq,
1274 u8 trans_id,
1275 enum dpp_status_error status)
1276{
1277 struct wpabuf *msg;
1278
1279 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
1280 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
1281 if (!msg)
1282 return;
1283
1284#ifdef CONFIG_TESTING_OPTIONS
1285 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
1286 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
1287 goto skip_trans_id;
1288 }
1289 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
1290 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
1291 trans_id ^= 0x01;
1292 }
1293#endif /* CONFIG_TESTING_OPTIONS */
1294
1295 /* Transaction ID */
1296 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
1297 wpabuf_put_le16(msg, 1);
1298 wpabuf_put_u8(msg, trans_id);
1299
1300#ifdef CONFIG_TESTING_OPTIONS
1301skip_trans_id:
1302 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
1303 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
1304 goto skip_status;
1305 }
1306 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
1307 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
1308 status = 254;
1309 }
1310#endif /* CONFIG_TESTING_OPTIONS */
1311
1312 /* DPP Status */
1313 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
1314 wpabuf_put_le16(msg, 1);
1315 wpabuf_put_u8(msg, status);
1316
1317#ifdef CONFIG_TESTING_OPTIONS
1318skip_status:
1319 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1320 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1321 goto skip_connector;
1322 }
1323 if (status == DPP_STATUS_OK &&
1324 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1325 char *connector;
1326
1327 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1328 connector = dpp_corrupt_connector_signature(
1329 hapd->conf->dpp_connector);
1330 if (!connector) {
1331 wpabuf_free(msg);
1332 return;
1333 }
1334 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1335 wpabuf_put_le16(msg, os_strlen(connector));
1336 wpabuf_put_str(msg, connector);
1337 os_free(connector);
1338 goto skip_connector;
1339 }
1340#endif /* CONFIG_TESTING_OPTIONS */
1341
1342 /* DPP Connector */
1343 if (status == DPP_STATUS_OK) {
1344 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1345 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1346 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1347 }
1348
1349#ifdef CONFIG_TESTING_OPTIONS
1350skip_connector:
1351#endif /* CONFIG_TESTING_OPTIONS */
1352
1353 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1354 " status=%d", MAC2STR(src), status);
1355 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1356 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1357 DPP_PA_PEER_DISCOVERY_RESP, status);
1358 hostapd_drv_send_action(hapd, freq, 0, src,
1359 wpabuf_head(msg), wpabuf_len(msg));
1360 wpabuf_free(msg);
1361}
1362
1363
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001364static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1365 const u8 *src,
1366 const u8 *buf, size_t len,
1367 unsigned int freq)
1368{
1369 const u8 *connector, *trans_id;
1370 u16 connector_len, trans_id_len;
1371 struct os_time now;
1372 struct dpp_introduction intro;
1373 os_time_t expire;
1374 int expiration;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001375 enum dpp_status_error res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001376
1377 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1378 MAC2STR(src));
1379 if (!hapd->wpa_auth ||
1380 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1381 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1382 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1383 return;
1384 }
1385
1386 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1387 !hapd->conf->dpp_csign) {
1388 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1389 return;
1390 }
1391
1392 os_get_time(&now);
1393
1394 if (hapd->conf->dpp_netaccesskey_expiry &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001395 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001396 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1397 return;
1398 }
1399
1400 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1401 &trans_id_len);
1402 if (!trans_id || trans_id_len != 1) {
1403 wpa_printf(MSG_DEBUG,
1404 "DPP: Peer did not include Transaction ID");
1405 return;
1406 }
1407
1408 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1409 if (!connector) {
1410 wpa_printf(MSG_DEBUG,
1411 "DPP: Peer did not include its Connector");
1412 return;
1413 }
1414
Roshan Pius3a1667e2018-07-03 15:17:14 -07001415 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1416 wpabuf_head(hapd->conf->dpp_netaccesskey),
1417 wpabuf_len(hapd->conf->dpp_netaccesskey),
1418 wpabuf_head(hapd->conf->dpp_csign),
1419 wpabuf_len(hapd->conf->dpp_csign),
1420 connector, connector_len, &expire);
1421 if (res == 255) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001422 wpa_printf(MSG_INFO,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001423 "DPP: Network Introduction protocol resulted in internal failure (peer "
1424 MACSTR ")", MAC2STR(src));
1425 return;
1426 }
1427 if (res != DPP_STATUS_OK) {
1428 wpa_printf(MSG_INFO,
1429 "DPP: Network Introduction protocol resulted in failure (peer "
1430 MACSTR " status %d)", MAC2STR(src), res);
1431 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1432 res);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001433 return;
1434 }
1435
Roshan Pius3a1667e2018-07-03 15:17:14 -07001436 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001437 expire = hapd->conf->dpp_netaccesskey_expiry;
1438 if (expire)
1439 expiration = expire - now.sec;
1440 else
1441 expiration = 0;
1442
1443 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1444 intro.pmkid, expiration,
1445 WPA_KEY_MGMT_DPP) < 0) {
1446 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
1447 return;
1448 }
1449
Roshan Pius3a1667e2018-07-03 15:17:14 -07001450 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1451 DPP_STATUS_OK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001452}
1453
1454
1455static void
1456hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
1457 const u8 *buf, size_t len,
1458 unsigned int freq)
1459{
1460 struct wpabuf *msg;
1461
1462 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1463 MAC2STR(src));
1464
1465 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1466 * values here */
1467
1468 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
1469 wpa_printf(MSG_DEBUG,
1470 "DPP: No PKEX code configured - ignore request");
1471 return;
1472 }
1473
1474 if (hapd->dpp_pkex) {
1475 /* TODO: Support parallel operations */
1476 wpa_printf(MSG_DEBUG,
1477 "DPP: Already in PKEX session - ignore new request");
1478 return;
1479 }
1480
Roshan Pius3a1667e2018-07-03 15:17:14 -07001481 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
1482 hapd->dpp_pkex_bi,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001483 hapd->own_addr, src,
1484 hapd->dpp_pkex_identifier,
1485 hapd->dpp_pkex_code,
1486 buf, len);
1487 if (!hapd->dpp_pkex) {
1488 wpa_printf(MSG_DEBUG,
1489 "DPP: Failed to process the request - ignore it");
1490 return;
1491 }
1492
1493 msg = hapd->dpp_pkex->exchange_resp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001494 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1495 " freq=%u type=%d", MAC2STR(src), freq,
1496 DPP_PA_PKEX_EXCHANGE_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001497 hostapd_drv_send_action(hapd, freq, 0, src,
1498 wpabuf_head(msg), wpabuf_len(msg));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001499 if (hapd->dpp_pkex->failed) {
1500 wpa_printf(MSG_DEBUG,
1501 "DPP: Terminate PKEX exchange due to an earlier error");
1502 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1503 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
1504 dpp_pkex_free(hapd->dpp_pkex);
1505 hapd->dpp_pkex = NULL;
1506 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001507}
1508
1509
1510static void
1511hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
1512 const u8 *buf, size_t len, unsigned int freq)
1513{
1514 struct wpabuf *msg;
1515
1516 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1517 MAC2STR(src));
1518
1519 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1520 * values here */
1521
1522 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
1523 hapd->dpp_pkex->exchange_done) {
1524 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1525 return;
1526 }
1527
Roshan Pius3a1667e2018-07-03 15:17:14 -07001528 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001529 if (!msg) {
1530 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1531 return;
1532 }
1533
1534 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1535 MAC2STR(src));
1536
Roshan Pius3a1667e2018-07-03 15:17:14 -07001537 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1538 " freq=%u type=%d", MAC2STR(src), freq,
1539 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001540 hostapd_drv_send_action(hapd, freq, 0, src,
1541 wpabuf_head(msg), wpabuf_len(msg));
1542 wpabuf_free(msg);
1543}
1544
1545
1546static void
1547hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
1548 const u8 *hdr, const u8 *buf, size_t len,
1549 unsigned int freq)
1550{
1551 struct wpabuf *msg;
1552 struct dpp_pkex *pkex = hapd->dpp_pkex;
1553 struct dpp_bootstrap_info *bi;
1554
1555 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1556 MAC2STR(src));
1557
1558 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1559 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1560 return;
1561 }
1562
1563 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1564 if (!msg) {
1565 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001566 if (hapd->dpp_pkex->failed) {
1567 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1568 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1569 hapd->dpp_pkex->own_bi->pkex_t =
1570 hapd->dpp_pkex->t;
1571 dpp_pkex_free(hapd->dpp_pkex);
1572 hapd->dpp_pkex = NULL;
1573 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001574 return;
1575 }
1576
1577 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1578 MACSTR, MAC2STR(src));
1579
Roshan Pius3a1667e2018-07-03 15:17:14 -07001580 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1581 " freq=%u type=%d", MAC2STR(src), freq,
1582 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001583 hostapd_drv_send_action(hapd, freq, 0, src,
1584 wpabuf_head(msg), wpabuf_len(msg));
1585 wpabuf_free(msg);
1586
1587 bi = os_zalloc(sizeof(*bi));
1588 if (!bi)
1589 return;
1590 bi->id = hapd_dpp_next_id(hapd);
1591 bi->type = DPP_BOOTSTRAP_PKEX;
1592 os_memcpy(bi->mac_addr, src, ETH_ALEN);
1593 bi->num_freq = 1;
1594 bi->freq[0] = freq;
1595 bi->curve = pkex->own_bi->curve;
1596 bi->pubkey = pkex->peer_bootstrap_key;
1597 pkex->peer_bootstrap_key = NULL;
1598 dpp_pkex_free(pkex);
1599 hapd->dpp_pkex = NULL;
1600 if (dpp_bootstrap_key_hash(bi) < 0) {
1601 dpp_bootstrap_info_free(bi);
1602 return;
1603 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001604 dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001605}
1606
1607
1608static void
1609hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
1610 const u8 *hdr, const u8 *buf, size_t len,
1611 unsigned int freq)
1612{
1613 int res;
1614 struct dpp_bootstrap_info *bi, *own_bi;
1615 struct dpp_pkex *pkex = hapd->dpp_pkex;
1616 char cmd[500];
1617
1618 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
1619 MAC2STR(src));
1620
1621 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1622 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1623 return;
1624 }
1625
1626 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1627 if (res < 0) {
1628 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1629 return;
1630 }
1631
1632 own_bi = pkex->own_bi;
1633
1634 bi = os_zalloc(sizeof(*bi));
1635 if (!bi)
1636 return;
1637 bi->id = hapd_dpp_next_id(hapd);
1638 bi->type = DPP_BOOTSTRAP_PKEX;
1639 os_memcpy(bi->mac_addr, src, ETH_ALEN);
1640 bi->num_freq = 1;
1641 bi->freq[0] = freq;
1642 bi->curve = own_bi->curve;
1643 bi->pubkey = pkex->peer_bootstrap_key;
1644 pkex->peer_bootstrap_key = NULL;
1645 dpp_pkex_free(pkex);
1646 hapd->dpp_pkex = NULL;
1647 if (dpp_bootstrap_key_hash(bi) < 0) {
1648 dpp_bootstrap_info_free(bi);
1649 return;
1650 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001651 dl_list_add(&hapd->iface->interfaces->dpp_bootstrap, &bi->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001652
1653 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
1654 bi->id,
1655 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
1656 wpa_printf(MSG_DEBUG,
1657 "DPP: Start authentication after PKEX with parameters: %s",
1658 cmd);
1659 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
1660 wpa_printf(MSG_DEBUG,
1661 "DPP: Authentication initialization failed");
1662 return;
1663 }
1664}
1665
1666
1667void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
1668 const u8 *buf, size_t len, unsigned int freq)
1669{
1670 u8 crypto_suite;
1671 enum dpp_public_action_frame_type type;
1672 const u8 *hdr;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001673 unsigned int pkex_t;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001674
1675 if (len < DPP_HDR_LEN)
1676 return;
1677 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
1678 return;
1679 hdr = buf;
1680 buf += 4;
1681 len -= 4;
1682 crypto_suite = *buf++;
1683 type = *buf++;
1684 len -= 2;
1685
1686 wpa_printf(MSG_DEBUG,
1687 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
1688 MACSTR " freq=%u",
1689 crypto_suite, type, MAC2STR(src), freq);
1690 if (crypto_suite != 1) {
1691 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
1692 crypto_suite);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001693 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1694 " freq=%u type=%d ignore=unsupported-crypto-suite",
1695 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001696 return;
1697 }
1698 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001699 if (dpp_check_attrs(buf, len) < 0) {
1700 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1701 " freq=%u type=%d ignore=invalid-attributes",
1702 MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001703 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001704 }
1705 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1706 " freq=%u type=%d", MAC2STR(src), freq, type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001707
1708 switch (type) {
1709 case DPP_PA_AUTHENTICATION_REQ:
1710 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
1711 break;
1712 case DPP_PA_AUTHENTICATION_RESP:
Roshan Pius3a1667e2018-07-03 15:17:14 -07001713 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001714 break;
1715 case DPP_PA_AUTHENTICATION_CONF:
1716 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
1717 break;
1718 case DPP_PA_PEER_DISCOVERY_REQ:
1719 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
1720 break;
1721 case DPP_PA_PKEX_EXCHANGE_REQ:
1722 hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
1723 break;
1724 case DPP_PA_PKEX_EXCHANGE_RESP:
1725 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
1726 break;
1727 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1728 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
1729 freq);
1730 break;
1731 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1732 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
1733 freq);
1734 break;
1735 default:
1736 wpa_printf(MSG_DEBUG,
1737 "DPP: Ignored unsupported frame subtype %d", type);
1738 break;
1739 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001740
1741 if (hapd->dpp_pkex)
1742 pkex_t = hapd->dpp_pkex->t;
1743 else if (hapd->dpp_pkex_bi)
1744 pkex_t = hapd->dpp_pkex_bi->pkex_t;
1745 else
1746 pkex_t = 0;
1747 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
1748 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
1749 hostapd_dpp_pkex_remove(hapd, "*");
1750 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001751}
1752
1753
1754struct wpabuf *
1755hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
1756 const u8 *query, size_t query_len)
1757{
1758 struct dpp_authentication *auth = hapd->dpp_auth;
1759 struct wpabuf *resp;
1760
1761 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
1762 if (!auth || !auth->auth_success ||
1763 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
1764 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1765 return NULL;
1766 }
1767 wpa_hexdump(MSG_DEBUG,
1768 "DPP: Received Configuration Request (GAS Query Request)",
1769 query, query_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001770 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
1771 MAC2STR(sa));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001772 resp = dpp_conf_req_rx(auth, query, query_len);
1773 if (!resp)
1774 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1775 return resp;
1776}
1777
1778
Roshan Pius3a1667e2018-07-03 15:17:14 -07001779void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
1780{
1781 if (!hapd->dpp_auth)
1782 return;
1783
1784 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1785 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
1786 hostapd_drv_send_action_cancel_wait(hapd);
1787
1788 if (ok)
1789 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1790 else
1791 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1792 dpp_auth_deinit(hapd->dpp_auth);
1793 hapd->dpp_auth = NULL;
1794}
1795
1796
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001797static unsigned int hostapd_dpp_next_configurator_id(struct hostapd_data *hapd)
1798{
1799 struct dpp_configurator *conf;
1800 unsigned int max_id = 0;
1801
Roshan Pius3a1667e2018-07-03 15:17:14 -07001802 dl_list_for_each(conf, &hapd->iface->interfaces->dpp_configurator,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001803 struct dpp_configurator, list) {
1804 if (conf->id > max_id)
1805 max_id = conf->id;
1806 }
1807 return max_id + 1;
1808}
1809
1810
1811int hostapd_dpp_configurator_add(struct hostapd_data *hapd, const char *cmd)
1812{
1813 char *curve = NULL;
1814 char *key = NULL;
1815 u8 *privkey = NULL;
1816 size_t privkey_len = 0;
1817 int ret = -1;
1818 struct dpp_configurator *conf = NULL;
1819
1820 curve = get_param(cmd, " curve=");
1821 key = get_param(cmd, " key=");
1822
1823 if (key) {
1824 privkey_len = os_strlen(key) / 2;
1825 privkey = os_malloc(privkey_len);
1826 if (!privkey ||
1827 hexstr2bin(key, privkey, privkey_len) < 0)
1828 goto fail;
1829 }
1830
1831 conf = dpp_keygen_configurator(curve, privkey, privkey_len);
1832 if (!conf)
1833 goto fail;
1834
1835 conf->id = hostapd_dpp_next_configurator_id(hapd);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001836 dl_list_add(&hapd->iface->interfaces->dpp_configurator, &conf->list);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001837 ret = conf->id;
1838 conf = NULL;
1839fail:
1840 os_free(curve);
1841 str_clear_free(key);
1842 bin_clear_free(privkey, privkey_len);
1843 dpp_configurator_free(conf);
1844 return ret;
1845}
1846
1847
Roshan Pius3a1667e2018-07-03 15:17:14 -07001848static int dpp_configurator_del(struct hapd_interfaces *ifaces, unsigned int id)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001849{
1850 struct dpp_configurator *conf, *tmp;
1851 int found = 0;
1852
Roshan Pius3a1667e2018-07-03 15:17:14 -07001853 dl_list_for_each_safe(conf, tmp, &ifaces->dpp_configurator,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001854 struct dpp_configurator, list) {
1855 if (id && conf->id != id)
1856 continue;
1857 found = 1;
1858 dl_list_del(&conf->list);
1859 dpp_configurator_free(conf);
1860 }
1861
1862 if (id == 0)
1863 return 0; /* flush succeeds regardless of entries found */
1864 return found ? 0 : -1;
1865}
1866
1867
1868int hostapd_dpp_configurator_remove(struct hostapd_data *hapd, const char *id)
1869{
1870 unsigned int id_val;
1871
1872 if (os_strcmp(id, "*") == 0) {
1873 id_val = 0;
1874 } else {
1875 id_val = atoi(id);
1876 if (id_val == 0)
1877 return -1;
1878 }
1879
Roshan Pius3a1667e2018-07-03 15:17:14 -07001880 return dpp_configurator_del(hapd->iface->interfaces, id_val);
1881}
1882
1883
1884int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
1885{
1886 struct dpp_authentication *auth;
1887 int ret = -1;
1888 char *curve = NULL;
1889
1890 auth = os_zalloc(sizeof(*auth));
1891 if (!auth)
1892 return -1;
1893
1894 curve = get_param(cmd, " curve=");
Hai Shalombf6e0ba2019-02-11 12:01:50 -08001895 hostapd_dpp_set_configurator(hapd, auth, cmd);
1896
1897 if (dpp_configurator_own_config(auth, curve, 1) == 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001898 hostapd_dpp_handle_config_obj(hapd, auth);
1899 ret = 0;
1900 }
1901
1902 dpp_auth_deinit(auth);
1903 os_free(curve);
1904
1905 return ret;
1906}
1907
1908
1909int hostapd_dpp_configurator_get_key(struct hostapd_data *hapd, unsigned int id,
1910 char *buf, size_t buflen)
1911{
1912 struct dpp_configurator *conf;
1913
1914 conf = hostapd_dpp_configurator_get_id(hapd, id);
1915 if (!conf)
1916 return -1;
1917
1918 return dpp_configurator_get_key(conf, buf, buflen);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001919}
1920
1921
1922int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
1923{
1924 struct dpp_bootstrap_info *own_bi;
1925 const char *pos, *end;
1926
1927 pos = os_strstr(cmd, " own=");
1928 if (!pos)
1929 return -1;
1930 pos += 5;
1931 own_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
1932 if (!own_bi) {
1933 wpa_printf(MSG_DEBUG,
1934 "DPP: Identified bootstrap info not found");
1935 return -1;
1936 }
1937 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
1938 wpa_printf(MSG_DEBUG,
1939 "DPP: Identified bootstrap info not for PKEX");
1940 return -1;
1941 }
1942 hapd->dpp_pkex_bi = own_bi;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001943 own_bi->pkex_t = 0; /* clear pending errors on new code */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001944
1945 os_free(hapd->dpp_pkex_identifier);
1946 hapd->dpp_pkex_identifier = NULL;
1947 pos = os_strstr(cmd, " identifier=");
1948 if (pos) {
1949 pos += 12;
1950 end = os_strchr(pos, ' ');
1951 if (!end)
1952 return -1;
1953 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
1954 if (!hapd->dpp_pkex_identifier)
1955 return -1;
1956 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
1957 hapd->dpp_pkex_identifier[end - pos] = '\0';
1958 }
1959
1960 pos = os_strstr(cmd, " code=");
1961 if (!pos)
1962 return -1;
1963 os_free(hapd->dpp_pkex_code);
1964 hapd->dpp_pkex_code = os_strdup(pos + 6);
1965 if (!hapd->dpp_pkex_code)
1966 return -1;
1967
1968 if (os_strstr(cmd, " init=1")) {
1969 struct wpabuf *msg;
1970
1971 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
1972 dpp_pkex_free(hapd->dpp_pkex);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001973 hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
1974 hapd->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001975 hapd->dpp_pkex_identifier,
1976 hapd->dpp_pkex_code);
1977 if (!hapd->dpp_pkex)
1978 return -1;
1979
1980 msg = hapd->dpp_pkex->exchange_req;
1981 /* TODO: Which channel to use? */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001982 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1983 " freq=%u type=%d", MAC2STR(broadcast), 2437,
1984 DPP_PA_PKEX_EXCHANGE_REQ);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001985 hostapd_drv_send_action(hapd, 2437, 0, broadcast,
1986 wpabuf_head(msg), wpabuf_len(msg));
1987 }
1988
1989 /* TODO: Support multiple PKEX info entries */
1990
1991 os_free(hapd->dpp_pkex_auth_cmd);
1992 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
1993
1994 return 1;
1995}
1996
1997
1998int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
1999{
2000 unsigned int id_val;
2001
2002 if (os_strcmp(id, "*") == 0) {
2003 id_val = 0;
2004 } else {
2005 id_val = atoi(id);
2006 if (id_val == 0)
2007 return -1;
2008 }
2009
2010 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
2011 return -1;
2012
2013 /* TODO: Support multiple PKEX entries */
2014 os_free(hapd->dpp_pkex_code);
2015 hapd->dpp_pkex_code = NULL;
2016 os_free(hapd->dpp_pkex_identifier);
2017 hapd->dpp_pkex_identifier = NULL;
2018 os_free(hapd->dpp_pkex_auth_cmd);
2019 hapd->dpp_pkex_auth_cmd = NULL;
2020 hapd->dpp_pkex_bi = NULL;
2021 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
2022 dpp_pkex_free(hapd->dpp_pkex);
2023 hapd->dpp_pkex = NULL;
2024 return 0;
2025}
2026
2027
Roshan Pius3a1667e2018-07-03 15:17:14 -07002028void hostapd_dpp_stop(struct hostapd_data *hapd)
2029{
2030 dpp_auth_deinit(hapd->dpp_auth);
2031 hapd->dpp_auth = NULL;
2032 dpp_pkex_free(hapd->dpp_pkex);
2033 hapd->dpp_pkex = NULL;
2034}
2035
2036
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002037int hostapd_dpp_init(struct hostapd_data *hapd)
2038{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002039 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
2040 hapd->dpp_init_done = 1;
2041 return 0;
2042}
2043
2044
2045void hostapd_dpp_deinit(struct hostapd_data *hapd)
2046{
2047#ifdef CONFIG_TESTING_OPTIONS
2048 os_free(hapd->dpp_config_obj_override);
2049 hapd->dpp_config_obj_override = NULL;
2050 os_free(hapd->dpp_discovery_override);
2051 hapd->dpp_discovery_override = NULL;
2052 os_free(hapd->dpp_groups_override);
2053 hapd->dpp_groups_override = NULL;
2054 hapd->dpp_ignore_netaccesskey_mismatch = 0;
2055#endif /* CONFIG_TESTING_OPTIONS */
2056 if (!hapd->dpp_init_done)
2057 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002058 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
2059 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
2060 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002061 dpp_auth_deinit(hapd->dpp_auth);
2062 hapd->dpp_auth = NULL;
2063 hostapd_dpp_pkex_remove(hapd, "*");
2064 hapd->dpp_pkex = NULL;
2065 os_free(hapd->dpp_configurator_params);
2066 hapd->dpp_configurator_params = NULL;
2067}
Roshan Pius3a1667e2018-07-03 15:17:14 -07002068
2069
2070void hostapd_dpp_init_global(struct hapd_interfaces *ifaces)
2071{
2072 dl_list_init(&ifaces->dpp_bootstrap);
2073 dl_list_init(&ifaces->dpp_configurator);
2074 ifaces->dpp_init_done = 1;
2075}
2076
2077
2078void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces)
2079{
2080 if (!ifaces->dpp_init_done)
2081 return;
2082 dpp_bootstrap_del(ifaces, 0);
2083 dpp_configurator_del(ifaces, 0);
2084}