2 * hostapd / DPP integration
3 * Copyright (c) 2017, Qualcomm Atheros, Inc.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
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"
17 #include "ap_drv_ops.h"
18 #include "gas_query_ap.h"
20 #include "dpp_hostapd.h"
23 static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
24 static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
25 static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
26 static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
28 static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
32 * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
33 * @hapd: Pointer to hostapd_data
34 * @cmd: DPP URI read from a QR Code
35 * Returns: Identifier of the stored info or -1 on failure
37 int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
39 struct dpp_bootstrap_info *bi;
40 struct dpp_authentication *auth = hapd->dpp_auth;
42 bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd);
46 if (auth && auth->response_pending &&
47 dpp_notify_new_qr_code(auth, bi) == 1) {
49 "DPP: Sending out pending authentication response");
50 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
52 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
53 DPP_PA_AUTHENTICATION_RESP);
54 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
56 wpabuf_head(hapd->dpp_auth->resp_msg),
57 wpabuf_len(hapd->dpp_auth->resp_msg));
64 static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
67 struct hostapd_data *hapd = eloop_ctx;
68 struct dpp_authentication *auth = hapd->dpp_auth;
70 if (!auth || !auth->resp_msg)
74 "DPP: Retry Authentication Response after timeout");
75 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
77 MAC2STR(auth->peer_mac_addr), auth->curr_freq,
78 DPP_PA_AUTHENTICATION_RESP);
79 hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr,
80 wpabuf_head(auth->resp_msg),
81 wpabuf_len(auth->resp_msg));
85 static void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd)
87 struct dpp_authentication *auth = hapd->dpp_auth;
88 unsigned int wait_time, max_tries;
90 if (!auth || !auth->resp_msg)
93 if (hapd->dpp_resp_max_tries)
94 max_tries = hapd->dpp_resp_max_tries;
97 auth->auth_resp_tries++;
98 if (auth->auth_resp_tries >= max_tries) {
100 "DPP: No confirm received from initiator - stopping exchange");
101 hostapd_drv_send_action_cancel_wait(hapd);
102 dpp_auth_deinit(hapd->dpp_auth);
103 hapd->dpp_auth = NULL;
107 if (hapd->dpp_resp_retry_time)
108 wait_time = hapd->dpp_resp_retry_time;
111 wpa_printf(MSG_DEBUG,
112 "DPP: Schedule retransmission of Authentication Response frame in %u ms",
114 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
115 eloop_register_timeout(wait_time / 1000,
116 (wait_time % 1000) * 1000,
117 hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
121 void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
122 const u8 *data, size_t data_len, int ok)
124 struct dpp_authentication *auth = hapd->dpp_auth;
126 wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
128 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
129 " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
131 if (!hapd->dpp_auth) {
132 wpa_printf(MSG_DEBUG,
133 "DPP: Ignore TX status since there is no ongoing authentication exchange");
138 if (auth->connect_on_tx_status) {
139 wpa_printf(MSG_DEBUG,
140 "DPP: Complete exchange on configuration result");
141 dpp_auth_deinit(hapd->dpp_auth);
142 hapd->dpp_auth = NULL;
145 #endif /* CONFIG_DPP2 */
147 if (hapd->dpp_auth->remove_on_tx_status) {
148 wpa_printf(MSG_DEBUG,
149 "DPP: Terminate authentication exchange due to an earlier error");
150 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
151 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
153 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
155 hostapd_drv_send_action_cancel_wait(hapd);
156 dpp_auth_deinit(hapd->dpp_auth);
157 hapd->dpp_auth = NULL;
161 if (hapd->dpp_auth_ok_on_ack)
162 hostapd_dpp_auth_success(hapd, 1);
164 if (!is_broadcast_ether_addr(dst) && !ok) {
165 wpa_printf(MSG_DEBUG,
166 "DPP: Unicast DPP Action frame was not ACKed");
167 if (auth->waiting_auth_resp) {
168 /* In case of DPP Authentication Request frame, move to
169 * the next channel immediately. */
170 hostapd_drv_send_action_cancel_wait(hapd);
171 hostapd_dpp_auth_init_next(hapd);
174 if (auth->waiting_auth_conf) {
175 hostapd_dpp_auth_resp_retry(hapd);
180 if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) {
181 /* Allow timeout handling to stop iteration if no response is
182 * received from a peer that has ACKed a request. */
183 auth->auth_req_ack = 1;
186 if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 &&
187 hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) {
188 wpa_printf(MSG_DEBUG,
189 "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response",
190 hapd->dpp_auth->curr_freq,
191 hapd->dpp_auth->neg_freq);
192 hostapd_drv_send_action_cancel_wait(hapd);
194 if (hapd->dpp_auth->neg_freq !=
195 (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
196 /* TODO: Listen operation on non-operating channel */
198 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
199 hapd->dpp_auth->neg_freq, hapd->iface->freq);
203 if (hapd->dpp_auth_ok_on_ack)
204 hapd->dpp_auth_ok_on_ack = 0;
208 static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
210 struct hostapd_data *hapd = eloop_ctx;
211 struct dpp_authentication *auth = hapd->dpp_auth;
213 struct os_reltime now, diff;
214 unsigned int wait_time, diff_ms;
216 if (!auth || !auth->waiting_auth_resp)
219 wait_time = hapd->dpp_resp_wait_time ?
220 hapd->dpp_resp_wait_time : 2000;
221 os_get_reltime(&now);
222 os_reltime_sub(&now, &hapd->dpp_last_init, &diff);
223 diff_ms = diff.sec * 1000 + diff.usec / 1000;
224 wpa_printf(MSG_DEBUG,
225 "DPP: Reply wait timeout - wait_time=%u diff_ms=%u",
228 if (auth->auth_req_ack && diff_ms >= wait_time) {
229 /* Peer ACK'ed Authentication Request frame, but did not reply
230 * with Authentication Response frame within two seconds. */
232 "DPP: No response received from responder - stopping initiation attempt");
233 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED);
234 hostapd_drv_send_action_cancel_wait(hapd);
235 hostapd_dpp_listen_stop(hapd);
236 dpp_auth_deinit(auth);
237 hapd->dpp_auth = NULL;
241 if (diff_ms >= wait_time) {
242 /* Authentication Request frame was not ACK'ed and no reply
243 * was receiving within two seconds. */
244 wpa_printf(MSG_DEBUG,
245 "DPP: Continue Initiator channel iteration");
246 hostapd_drv_send_action_cancel_wait(hapd);
247 hostapd_dpp_listen_stop(hapd);
248 hostapd_dpp_auth_init_next(hapd);
252 /* Driver did not support 2000 ms long wait_time with TX command, so
253 * schedule listen operation to continue waiting for the response.
255 * DPP listen operations continue until stopped, so simply schedule a
256 * new call to this function at the point when the two second reply
257 * wait has expired. */
258 wait_time -= diff_ms;
260 freq = auth->curr_freq;
261 if (auth->neg_freq > 0)
262 freq = auth->neg_freq;
263 wpa_printf(MSG_DEBUG,
264 "DPP: Continue reply wait on channel %u MHz for %u ms",
266 hapd->dpp_in_response_listen = 1;
268 if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) {
269 /* TODO: Listen operation on non-operating channel */
271 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
272 freq, hapd->iface->freq);
275 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
276 hostapd_dpp_reply_wait_timeout, hapd, NULL);
280 static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
281 struct dpp_authentication *auth)
283 #ifdef CONFIG_TESTING_OPTIONS
284 if (hapd->dpp_config_obj_override)
285 auth->config_obj_override =
286 os_strdup(hapd->dpp_config_obj_override);
287 if (hapd->dpp_discovery_override)
288 auth->discovery_override =
289 os_strdup(hapd->dpp_discovery_override);
290 if (hapd->dpp_groups_override)
291 auth->groups_override = os_strdup(hapd->dpp_groups_override);
292 auth->ignore_netaccesskey_mismatch =
293 hapd->dpp_ignore_netaccesskey_mismatch;
294 #endif /* CONFIG_TESTING_OPTIONS */
298 static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx)
300 struct hostapd_data *hapd = eloop_ctx;
304 wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout");
305 hostapd_dpp_auth_init_next(hapd);
309 static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd)
311 struct dpp_authentication *auth = hapd->dpp_auth;
313 unsigned int wait_time, max_wait_time, freq, max_tries, used;
314 struct os_reltime now, diff;
319 if (auth->freq_idx == 0)
320 os_get_reltime(&hapd->dpp_init_iter_start);
322 if (auth->freq_idx >= auth->num_freq) {
323 auth->num_freq_iters++;
324 if (hapd->dpp_init_max_tries)
325 max_tries = hapd->dpp_init_max_tries;
328 if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) {
330 "DPP: No response received from responder - stopping initiation attempt");
331 wpa_msg(hapd->msg_ctx, MSG_INFO,
332 DPP_EVENT_AUTH_INIT_FAILED);
333 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
335 hostapd_drv_send_action_cancel_wait(hapd);
336 dpp_auth_deinit(hapd->dpp_auth);
337 hapd->dpp_auth = NULL;
341 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
342 if (hapd->dpp_init_retry_time)
343 wait_time = hapd->dpp_init_retry_time;
346 os_get_reltime(&now);
347 os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff);
348 used = diff.sec * 1000 + diff.usec / 1000;
349 if (used > wait_time)
353 wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms",
355 eloop_register_timeout(wait_time / 1000,
356 (wait_time % 1000) * 1000,
357 hostapd_dpp_init_timeout, hapd,
361 freq = auth->freq[auth->freq_idx++];
362 auth->curr_freq = freq;
364 if (is_zero_ether_addr(auth->peer_bi->mac_addr))
367 dst = auth->peer_bi->mac_addr;
368 hapd->dpp_auth_ok_on_ack = 0;
369 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
370 wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */
371 max_wait_time = hapd->dpp_resp_wait_time ?
372 hapd->dpp_resp_wait_time : 2000;
373 if (wait_time > max_wait_time)
374 wait_time = max_wait_time;
375 wait_time += 10; /* give the driver some extra time to complete */
376 eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000,
377 hostapd_dpp_reply_wait_timeout, hapd, NULL);
379 if (auth->neg_freq > 0 && freq != auth->neg_freq) {
380 wpa_printf(MSG_DEBUG,
381 "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response",
382 freq, auth->neg_freq);
384 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
386 MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ);
387 auth->auth_req_ack = 0;
388 os_get_reltime(&hapd->dpp_last_init);
389 return hostapd_drv_send_action(hapd, freq, wait_time,
391 wpabuf_head(hapd->dpp_auth->req_msg),
392 wpabuf_len(hapd->dpp_auth->req_msg));
396 int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
399 struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
400 u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
401 unsigned int neg_freq = 0;
403 pos = os_strstr(cmd, " peer=");
407 peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
410 "DPP: Could not find bootstrapping info for the identified peer");
414 pos = os_strstr(cmd, " own=");
417 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp,
421 "DPP: Could not find bootstrapping info for the identified local entry");
425 if (peer_bi->curve != own_bi->curve) {
427 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
428 peer_bi->curve->name, own_bi->curve->name);
433 pos = os_strstr(cmd, " role=");
436 if (os_strncmp(pos, "configurator", 12) == 0)
437 allowed_roles = DPP_CAPAB_CONFIGURATOR;
438 else if (os_strncmp(pos, "enrollee", 8) == 0)
439 allowed_roles = DPP_CAPAB_ENROLLEE;
440 else if (os_strncmp(pos, "either", 6) == 0)
441 allowed_roles = DPP_CAPAB_CONFIGURATOR |
447 pos = os_strstr(cmd, " neg_freq=");
449 neg_freq = atoi(pos + 10);
451 if (hapd->dpp_auth) {
452 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
453 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout,
455 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd,
457 hostapd_drv_send_action_cancel_wait(hapd);
458 dpp_auth_deinit(hapd->dpp_auth);
461 hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
462 allowed_roles, neg_freq,
463 hapd->iface->hw_features,
464 hapd->iface->num_hw_features);
467 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
468 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
469 hapd->dpp_auth, cmd) < 0) {
470 dpp_auth_deinit(hapd->dpp_auth);
471 hapd->dpp_auth = NULL;
475 hapd->dpp_auth->neg_freq = neg_freq;
477 if (!is_zero_ether_addr(peer_bi->mac_addr))
478 os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
481 return hostapd_dpp_auth_init_next(hapd);
487 int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
495 if (os_strstr(cmd, " role=configurator"))
496 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
497 else if (os_strstr(cmd, " role=enrollee"))
498 hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
500 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
502 hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
504 if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
505 /* TODO: Listen operation on non-operating channel */
507 "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
508 freq, hapd->iface->freq);
516 void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
518 /* TODO: Stop listen operation on non-operating channel */
522 static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
523 const u8 *hdr, const u8 *buf, size_t len,
526 const u8 *r_bootstrap, *i_bootstrap;
527 u16 r_bootstrap_len, i_bootstrap_len;
528 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
530 if (!hapd->iface->interfaces->dpp)
533 wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
536 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
538 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
539 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
540 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
543 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
544 r_bootstrap, r_bootstrap_len);
546 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
548 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
549 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
550 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
553 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
554 i_bootstrap, i_bootstrap_len);
556 /* Try to find own and peer bootstrapping key matches based on the
557 * received hash values */
558 dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
559 r_bootstrap, &own_bi, &peer_bi);
561 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
562 "No matching own bootstrapping key found - ignore message");
566 if (hapd->dpp_auth) {
567 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
568 "Already in DPP authentication exchange - ignore new one");
572 hapd->dpp_auth_ok_on_ack = 0;
573 hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
575 peer_bi, own_bi, freq, hdr, buf, len);
576 if (!hapd->dpp_auth) {
577 wpa_printf(MSG_DEBUG, "DPP: No response generated");
580 hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
581 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
583 hapd->dpp_configurator_params) < 0) {
584 dpp_auth_deinit(hapd->dpp_auth);
585 hapd->dpp_auth = NULL;
588 os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
590 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
592 MAC2STR(src), hapd->dpp_auth->curr_freq,
593 DPP_PA_AUTHENTICATION_RESP);
594 hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
595 src, wpabuf_head(hapd->dpp_auth->resp_msg),
596 wpabuf_len(hapd->dpp_auth->resp_msg));
600 static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd,
601 struct dpp_authentication *auth)
603 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
604 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
605 dpp_akm_str(auth->akm));
607 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
608 wpa_ssid_txt(auth->ssid, auth->ssid_len));
609 if (auth->connector) {
610 /* TODO: Save the Connector and consider using a command
611 * to fetch the value instead of sending an event with
612 * it. The Connector could end up being larger than what
613 * most clients are ready to receive as an event
615 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
617 } else if (auth->passphrase[0]) {
618 char hex[64 * 2 + 1];
620 wpa_snprintf_hex(hex, sizeof(hex),
621 (const u8 *) auth->passphrase,
622 os_strlen(auth->passphrase));
623 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
625 } else if (auth->psk_set) {
626 char hex[PMK_LEN * 2 + 1];
628 wpa_snprintf_hex(hex, sizeof(hex), auth->psk, PMK_LEN);
629 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
632 if (auth->c_sign_key) {
636 hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
637 hex = os_malloc(hexlen);
639 wpa_snprintf_hex(hex, hexlen,
640 wpabuf_head(auth->c_sign_key),
641 wpabuf_len(auth->c_sign_key));
642 wpa_msg(hapd->msg_ctx, MSG_INFO,
643 DPP_EVENT_C_SIGN_KEY "%s", hex);
647 if (auth->net_access_key) {
651 hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
652 hex = os_malloc(hexlen);
654 wpa_snprintf_hex(hex, hexlen,
655 wpabuf_head(auth->net_access_key),
656 wpabuf_len(auth->net_access_key));
657 if (auth->net_access_key_expiry)
658 wpa_msg(hapd->msg_ctx, MSG_INFO,
659 DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
661 auth->net_access_key_expiry);
663 wpa_msg(hapd->msg_ctx, MSG_INFO,
664 DPP_EVENT_NET_ACCESS_KEY "%s", hex);
671 static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
672 enum gas_query_ap_result result,
673 const struct wpabuf *adv_proto,
674 const struct wpabuf *resp, u16 status_code)
676 struct hostapd_data *hapd = ctx;
678 struct dpp_authentication *auth = hapd->dpp_auth;
679 enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
681 if (!auth || !auth->auth_success) {
682 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
685 if (!resp || status_code != WLAN_STATUS_SUCCESS) {
686 wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
690 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
692 wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
695 if (wpabuf_len(adv_proto) != 10 ||
696 !(pos = wpabuf_head(adv_proto)) ||
697 pos[0] != WLAN_EID_ADV_PROTO ||
699 pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
701 WPA_GET_BE24(&pos[5]) != OUI_WFA ||
704 wpa_printf(MSG_DEBUG,
705 "DPP: Not a DPP Advertisement Protocol ID");
709 if (dpp_conf_resp_rx(auth, resp) < 0) {
710 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
714 hostapd_dpp_handle_config_obj(hapd, auth);
715 status = DPP_STATUS_OK;
716 #ifdef CONFIG_TESTING_OPTIONS
717 if (dpp_test == DPP_TEST_REJECT_CONFIG) {
718 wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object");
719 status = DPP_STATUS_CONFIG_REJECTED;
721 #endif /* CONFIG_TESTING_OPTIONS */
723 if (status != DPP_STATUS_OK)
724 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
726 if (auth->peer_version >= 2 &&
727 auth->conf_resp_status == DPP_STATUS_OK) {
730 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
731 msg = dpp_build_conf_result(auth, status);
735 wpa_msg(hapd->msg_ctx, MSG_INFO,
736 DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
737 MAC2STR(addr), auth->curr_freq,
738 DPP_PA_CONFIGURATION_RESULT);
739 hostapd_drv_send_action(hapd, auth->curr_freq, 0,
740 addr, wpabuf_head(msg),
744 /* This exchange will be terminated in the TX status handler */
745 auth->connect_on_tx_status = 1;
749 #endif /* CONFIG_DPP2 */
750 dpp_auth_deinit(hapd->dpp_auth);
751 hapd->dpp_auth = NULL;
755 static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
757 struct dpp_authentication *auth = hapd->dpp_auth;
763 os_snprintf(json, sizeof(json),
764 "{\"name\":\"Test\","
765 "\"wi-fi_tech\":\"infra\","
766 "\"netRole\":\"%s\"}",
767 netrole_ap ? "ap" : "sta");
768 wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
770 buf = dpp_build_conf_req(auth, json);
772 wpa_printf(MSG_DEBUG,
773 "DPP: No configuration request data available");
777 wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
778 MAC2STR(auth->peer_mac_addr), auth->curr_freq);
780 res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
781 buf, hostapd_dpp_gas_resp_cb, hapd);
783 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
784 "GAS: Failed to send Query Request");
787 wpa_printf(MSG_DEBUG,
788 "DPP: GAS query started with dialog token %u", res);
793 static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
795 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
796 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
798 #ifdef CONFIG_TESTING_OPTIONS
799 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
801 "DPP: TESTING - stop at Authentication Confirm");
802 if (hapd->dpp_auth->configurator) {
803 /* Prevent GAS response */
804 hapd->dpp_auth->auth_success = 0;
808 #endif /* CONFIG_TESTING_OPTIONS */
810 if (!hapd->dpp_auth->configurator)
811 hostapd_dpp_start_gas_client(hapd);
815 static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
816 const u8 *hdr, const u8 *buf, size_t len,
819 struct dpp_authentication *auth = hapd->dpp_auth;
822 wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
826 wpa_printf(MSG_DEBUG,
827 "DPP: No DPP Authentication in progress - drop");
831 if (!is_zero_ether_addr(auth->peer_mac_addr) &&
832 os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
833 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
834 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
838 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
840 if (auth->curr_freq != freq && auth->neg_freq == freq) {
841 wpa_printf(MSG_DEBUG,
842 "DPP: Responder accepted request for different negotiation channel");
843 auth->curr_freq = freq;
846 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
847 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
849 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
850 wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
853 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
856 os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
858 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
859 " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
860 DPP_PA_AUTHENTICATION_CONF);
861 hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
862 wpabuf_head(msg), wpabuf_len(msg));
864 hapd->dpp_auth_ok_on_ack = 1;
868 static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
869 const u8 *hdr, const u8 *buf, size_t len)
871 struct dpp_authentication *auth = hapd->dpp_auth;
873 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
877 wpa_printf(MSG_DEBUG,
878 "DPP: No DPP Authentication in progress - drop");
882 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
883 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
884 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
888 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
889 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
893 hostapd_dpp_auth_success(hapd, 0);
899 static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
902 struct hostapd_data *hapd = eloop_ctx;
903 struct dpp_authentication *auth = hapd->dpp_auth;
905 if (!auth || !auth->waiting_conf_result)
908 wpa_printf(MSG_DEBUG,
909 "DPP: Timeout while waiting for Configuration Result");
910 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
911 dpp_auth_deinit(auth);
912 hapd->dpp_auth = NULL;
916 static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
917 const u8 *hdr, const u8 *buf, size_t len)
919 struct dpp_authentication *auth = hapd->dpp_auth;
920 enum dpp_status_error status;
922 wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
925 if (!auth || !auth->waiting_conf_result) {
926 wpa_printf(MSG_DEBUG,
927 "DPP: No DPP Configuration waiting for result - drop");
931 if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
932 wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
933 MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
937 status = dpp_conf_result_rx(auth, hdr, buf, len);
939 hostapd_drv_send_action_cancel_wait(hapd);
940 hostapd_dpp_listen_stop(hapd);
941 if (status == DPP_STATUS_OK)
942 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
944 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
945 dpp_auth_deinit(auth);
946 hapd->dpp_auth = NULL;
947 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
951 #endif /* CONFIG_DPP2 */
954 static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
955 const u8 *src, unsigned int freq,
957 enum dpp_status_error status)
961 msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
962 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
966 #ifdef CONFIG_TESTING_OPTIONS
967 if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
968 wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
971 if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) {
972 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID");
975 #endif /* CONFIG_TESTING_OPTIONS */
978 wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
979 wpabuf_put_le16(msg, 1);
980 wpabuf_put_u8(msg, trans_id);
982 #ifdef CONFIG_TESTING_OPTIONS
984 if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
985 wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
988 if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) {
989 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
992 #endif /* CONFIG_TESTING_OPTIONS */
995 wpabuf_put_le16(msg, DPP_ATTR_STATUS);
996 wpabuf_put_le16(msg, 1);
997 wpabuf_put_u8(msg, status);
999 #ifdef CONFIG_TESTING_OPTIONS
1001 if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
1002 wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
1003 goto skip_connector;
1005 if (status == DPP_STATUS_OK &&
1006 dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) {
1009 wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector");
1010 connector = dpp_corrupt_connector_signature(
1011 hapd->conf->dpp_connector);
1016 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1017 wpabuf_put_le16(msg, os_strlen(connector));
1018 wpabuf_put_str(msg, connector);
1020 goto skip_connector;
1022 #endif /* CONFIG_TESTING_OPTIONS */
1025 if (status == DPP_STATUS_OK) {
1026 wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
1027 wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
1028 wpabuf_put_str(msg, hapd->conf->dpp_connector);
1031 #ifdef CONFIG_TESTING_OPTIONS
1033 #endif /* CONFIG_TESTING_OPTIONS */
1035 wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
1036 " status=%d", MAC2STR(src), status);
1037 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1038 " freq=%u type=%d status=%d", MAC2STR(src), freq,
1039 DPP_PA_PEER_DISCOVERY_RESP, status);
1040 hostapd_drv_send_action(hapd, freq, 0, src,
1041 wpabuf_head(msg), wpabuf_len(msg));
1046 static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
1048 const u8 *buf, size_t len,
1051 const u8 *connector, *trans_id;
1052 u16 connector_len, trans_id_len;
1054 struct dpp_introduction intro;
1057 enum dpp_status_error res;
1059 wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
1061 if (!hapd->wpa_auth ||
1062 !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
1063 !(hapd->conf->wpa & WPA_PROTO_RSN)) {
1064 wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
1068 if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
1069 !hapd->conf->dpp_csign) {
1070 wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
1076 if (hapd->conf->dpp_netaccesskey_expiry &&
1077 (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) {
1078 wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
1082 trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
1084 if (!trans_id || trans_id_len != 1) {
1085 wpa_printf(MSG_DEBUG,
1086 "DPP: Peer did not include Transaction ID");
1090 connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
1092 wpa_printf(MSG_DEBUG,
1093 "DPP: Peer did not include its Connector");
1097 res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
1098 wpabuf_head(hapd->conf->dpp_netaccesskey),
1099 wpabuf_len(hapd->conf->dpp_netaccesskey),
1100 wpabuf_head(hapd->conf->dpp_csign),
1101 wpabuf_len(hapd->conf->dpp_csign),
1102 connector, connector_len, &expire);
1104 wpa_printf(MSG_INFO,
1105 "DPP: Network Introduction protocol resulted in internal failure (peer "
1106 MACSTR ")", MAC2STR(src));
1109 if (res != DPP_STATUS_OK) {
1110 wpa_printf(MSG_INFO,
1111 "DPP: Network Introduction protocol resulted in failure (peer "
1112 MACSTR " status %d)", MAC2STR(src), res);
1113 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1118 if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire)
1119 expire = hapd->conf->dpp_netaccesskey_expiry;
1121 expiration = expire - now.sec;
1125 if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
1126 intro.pmkid, expiration,
1127 WPA_KEY_MGMT_DPP) < 0) {
1128 wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
1132 hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
1138 hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
1139 const u8 *buf, size_t len,
1144 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
1147 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1150 if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
1151 wpa_printf(MSG_DEBUG,
1152 "DPP: No PKEX code configured - ignore request");
1156 if (hapd->dpp_pkex) {
1157 /* TODO: Support parallel operations */
1158 wpa_printf(MSG_DEBUG,
1159 "DPP: Already in PKEX session - ignore new request");
1163 hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
1165 hapd->own_addr, src,
1166 hapd->dpp_pkex_identifier,
1167 hapd->dpp_pkex_code,
1169 if (!hapd->dpp_pkex) {
1170 wpa_printf(MSG_DEBUG,
1171 "DPP: Failed to process the request - ignore it");
1175 msg = hapd->dpp_pkex->exchange_resp;
1176 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1177 " freq=%u type=%d", MAC2STR(src), freq,
1178 DPP_PA_PKEX_EXCHANGE_RESP);
1179 hostapd_drv_send_action(hapd, freq, 0, src,
1180 wpabuf_head(msg), wpabuf_len(msg));
1181 if (hapd->dpp_pkex->failed) {
1182 wpa_printf(MSG_DEBUG,
1183 "DPP: Terminate PKEX exchange due to an earlier error");
1184 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1185 hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
1186 dpp_pkex_free(hapd->dpp_pkex);
1187 hapd->dpp_pkex = NULL;
1193 hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
1194 const u8 *buf, size_t len, unsigned int freq)
1198 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
1201 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1204 if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
1205 hapd->dpp_pkex->exchange_done) {
1206 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1210 msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len);
1212 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1216 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
1219 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1220 " freq=%u type=%d", MAC2STR(src), freq,
1221 DPP_PA_PKEX_COMMIT_REVEAL_REQ);
1222 hostapd_drv_send_action(hapd, freq, 0, src,
1223 wpabuf_head(msg), wpabuf_len(msg));
1229 hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
1230 const u8 *hdr, const u8 *buf, size_t len,
1234 struct dpp_pkex *pkex = hapd->dpp_pkex;
1235 struct dpp_bootstrap_info *bi;
1237 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
1240 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1241 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1245 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1247 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
1248 if (hapd->dpp_pkex->failed) {
1249 wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
1250 if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
1251 hapd->dpp_pkex->own_bi->pkex_t =
1253 dpp_pkex_free(hapd->dpp_pkex);
1254 hapd->dpp_pkex = NULL;
1259 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
1260 MACSTR, MAC2STR(src));
1262 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1263 " freq=%u type=%d", MAC2STR(src), freq,
1264 DPP_PA_PKEX_COMMIT_REVEAL_RESP);
1265 hostapd_drv_send_action(hapd, freq, 0, src,
1266 wpabuf_head(msg), wpabuf_len(msg));
1269 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
1272 hapd->dpp_pkex = NULL;
1277 hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
1278 const u8 *hdr, const u8 *buf, size_t len,
1282 struct dpp_bootstrap_info *bi;
1283 struct dpp_pkex *pkex = hapd->dpp_pkex;
1286 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
1289 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1290 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1294 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1296 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1300 bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq);
1303 hapd->dpp_pkex = NULL;
1305 os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
1307 hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
1308 wpa_printf(MSG_DEBUG,
1309 "DPP: Start authentication after PKEX with parameters: %s",
1311 if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
1312 wpa_printf(MSG_DEBUG,
1313 "DPP: Authentication initialization failed");
1319 void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
1320 const u8 *buf, size_t len, unsigned int freq)
1323 enum dpp_public_action_frame_type type;
1325 unsigned int pkex_t;
1327 if (len < DPP_HDR_LEN)
1329 if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
1334 crypto_suite = *buf++;
1338 wpa_printf(MSG_DEBUG,
1339 "DPP: Received DPP Public Action frame crypto suite %u type %d from "
1341 crypto_suite, type, MAC2STR(src), freq);
1342 if (crypto_suite != 1) {
1343 wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
1345 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1346 " freq=%u type=%d ignore=unsupported-crypto-suite",
1347 MAC2STR(src), freq, type);
1350 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
1351 if (dpp_check_attrs(buf, len) < 0) {
1352 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1353 " freq=%u type=%d ignore=invalid-attributes",
1354 MAC2STR(src), freq, type);
1357 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
1358 " freq=%u type=%d", MAC2STR(src), freq, type);
1361 case DPP_PA_AUTHENTICATION_REQ:
1362 hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
1364 case DPP_PA_AUTHENTICATION_RESP:
1365 hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq);
1367 case DPP_PA_AUTHENTICATION_CONF:
1368 hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
1370 case DPP_PA_PEER_DISCOVERY_REQ:
1371 hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
1373 case DPP_PA_PKEX_EXCHANGE_REQ:
1374 hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
1376 case DPP_PA_PKEX_EXCHANGE_RESP:
1377 hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
1379 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1380 hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
1383 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1384 hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
1388 case DPP_PA_CONFIGURATION_RESULT:
1389 hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
1391 #endif /* CONFIG_DPP2 */
1393 wpa_printf(MSG_DEBUG,
1394 "DPP: Ignored unsupported frame subtype %d", type);
1399 pkex_t = hapd->dpp_pkex->t;
1400 else if (hapd->dpp_pkex_bi)
1401 pkex_t = hapd->dpp_pkex_bi->pkex_t;
1404 if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
1405 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
1406 hostapd_dpp_pkex_remove(hapd, "*");
1412 hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
1413 const u8 *query, size_t query_len)
1415 struct dpp_authentication *auth = hapd->dpp_auth;
1416 struct wpabuf *resp;
1418 wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
1419 if (!auth || !auth->auth_success ||
1420 os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
1421 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1424 wpa_hexdump(MSG_DEBUG,
1425 "DPP: Received Configuration Request (GAS Query Request)",
1427 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR,
1429 resp = dpp_conf_req_rx(auth, query, query_len);
1431 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1436 void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
1438 struct dpp_authentication *auth = hapd->dpp_auth;
1443 wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
1445 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1446 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
1448 if (ok && auth->peer_version >= 2 &&
1449 auth->conf_resp_status == DPP_STATUS_OK) {
1450 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
1451 auth->waiting_conf_result = 1;
1452 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
1454 eloop_register_timeout(2, 0,
1455 hostapd_dpp_config_result_wait_timeout,
1459 #endif /* CONFIG_DPP2 */
1460 hostapd_drv_send_action_cancel_wait(hapd);
1463 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
1465 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
1466 dpp_auth_deinit(hapd->dpp_auth);
1467 hapd->dpp_auth = NULL;
1471 int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
1473 struct dpp_authentication *auth;
1477 auth = os_zalloc(sizeof(*auth));
1481 curve = get_param(cmd, " curve=");
1482 hostapd_dpp_set_testing_options(hapd, auth);
1483 if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx,
1485 dpp_configurator_own_config(auth, curve, 1) == 0) {
1486 hostapd_dpp_handle_config_obj(hapd, auth);
1490 dpp_auth_deinit(auth);
1497 int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
1499 struct dpp_bootstrap_info *own_bi;
1500 const char *pos, *end;
1502 pos = os_strstr(cmd, " own=");
1506 own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos));
1508 wpa_printf(MSG_DEBUG,
1509 "DPP: Identified bootstrap info not found");
1512 if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
1513 wpa_printf(MSG_DEBUG,
1514 "DPP: Identified bootstrap info not for PKEX");
1517 hapd->dpp_pkex_bi = own_bi;
1518 own_bi->pkex_t = 0; /* clear pending errors on new code */
1520 os_free(hapd->dpp_pkex_identifier);
1521 hapd->dpp_pkex_identifier = NULL;
1522 pos = os_strstr(cmd, " identifier=");
1525 end = os_strchr(pos, ' ');
1528 hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
1529 if (!hapd->dpp_pkex_identifier)
1531 os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
1532 hapd->dpp_pkex_identifier[end - pos] = '\0';
1535 pos = os_strstr(cmd, " code=");
1538 os_free(hapd->dpp_pkex_code);
1539 hapd->dpp_pkex_code = os_strdup(pos + 6);
1540 if (!hapd->dpp_pkex_code)
1543 if (os_strstr(cmd, " init=1")) {
1546 wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
1547 dpp_pkex_free(hapd->dpp_pkex);
1548 hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
1550 hapd->dpp_pkex_identifier,
1551 hapd->dpp_pkex_code);
1552 if (!hapd->dpp_pkex)
1555 msg = hapd->dpp_pkex->exchange_req;
1556 /* TODO: Which channel to use? */
1557 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
1558 " freq=%u type=%d", MAC2STR(broadcast), 2437,
1559 DPP_PA_PKEX_EXCHANGE_REQ);
1560 hostapd_drv_send_action(hapd, 2437, 0, broadcast,
1561 wpabuf_head(msg), wpabuf_len(msg));
1564 /* TODO: Support multiple PKEX info entries */
1566 os_free(hapd->dpp_pkex_auth_cmd);
1567 hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
1573 int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
1575 unsigned int id_val;
1577 if (os_strcmp(id, "*") == 0) {
1585 if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
1588 /* TODO: Support multiple PKEX entries */
1589 os_free(hapd->dpp_pkex_code);
1590 hapd->dpp_pkex_code = NULL;
1591 os_free(hapd->dpp_pkex_identifier);
1592 hapd->dpp_pkex_identifier = NULL;
1593 os_free(hapd->dpp_pkex_auth_cmd);
1594 hapd->dpp_pkex_auth_cmd = NULL;
1595 hapd->dpp_pkex_bi = NULL;
1596 /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
1597 dpp_pkex_free(hapd->dpp_pkex);
1598 hapd->dpp_pkex = NULL;
1603 void hostapd_dpp_stop(struct hostapd_data *hapd)
1605 dpp_auth_deinit(hapd->dpp_auth);
1606 hapd->dpp_auth = NULL;
1607 dpp_pkex_free(hapd->dpp_pkex);
1608 hapd->dpp_pkex = NULL;
1612 int hostapd_dpp_init(struct hostapd_data *hapd)
1614 hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
1615 hapd->dpp_init_done = 1;
1620 void hostapd_dpp_deinit(struct hostapd_data *hapd)
1622 #ifdef CONFIG_TESTING_OPTIONS
1623 os_free(hapd->dpp_config_obj_override);
1624 hapd->dpp_config_obj_override = NULL;
1625 os_free(hapd->dpp_discovery_override);
1626 hapd->dpp_discovery_override = NULL;
1627 os_free(hapd->dpp_groups_override);
1628 hapd->dpp_groups_override = NULL;
1629 hapd->dpp_ignore_netaccesskey_mismatch = 0;
1630 #endif /* CONFIG_TESTING_OPTIONS */
1631 if (!hapd->dpp_init_done)
1633 eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
1634 eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
1635 eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
1637 eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
1639 #endif /* CONFIG_DPP2 */
1640 dpp_auth_deinit(hapd->dpp_auth);
1641 hapd->dpp_auth = NULL;
1642 hostapd_dpp_pkex_remove(hapd, "*");
1643 hapd->dpp_pkex = NULL;
1644 os_free(hapd->dpp_configurator_params);
1645 hapd->dpp_configurator_params = NULL;