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/gas_server.h"
16 #include "rsn_supp/wpa.h"
17 #include "rsn_supp/pmksa_cache.h"
18 #include "wpa_supplicant_i.h"
21 #include "offchannel.h"
22 #include "gas_query.h"
25 #include "dpp_supplicant.h"
28 static int wpas_dpp_listen_start(struct wpa_supplicant
*wpa_s
,
30 static void wpas_dpp_reply_wait_timeout(void *eloop_ctx
, void *timeout_ctx
);
31 static void wpas_dpp_auth_success(struct wpa_supplicant
*wpa_s
, int initiator
);
32 static void wpas_dpp_tx_status(struct wpa_supplicant
*wpa_s
,
33 unsigned int freq
, const u8
*dst
,
34 const u8
*src
, const u8
*bssid
,
35 const u8
*data
, size_t data_len
,
36 enum offchannel_send_action_result result
);
38 static const u8 broadcast
[ETH_ALEN
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
41 static struct dpp_configurator
*
42 dpp_configurator_get_id(struct wpa_supplicant
*wpa_s
, unsigned int id
)
44 struct dpp_configurator
*conf
;
46 dl_list_for_each(conf
, &wpa_s
->dpp_configurator
,
47 struct dpp_configurator
, list
) {
55 static unsigned int wpas_dpp_next_id(struct wpa_supplicant
*wpa_s
)
57 struct dpp_bootstrap_info
*bi
;
58 unsigned int max_id
= 0;
60 dl_list_for_each(bi
, &wpa_s
->dpp_bootstrap
, struct dpp_bootstrap_info
,
70 * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
71 * @wpa_s: Pointer to wpa_supplicant data
72 * @cmd: DPP URI read from a QR Code
73 * Returns: Identifier of the stored info or -1 on failure
75 int wpas_dpp_qr_code(struct wpa_supplicant
*wpa_s
, const char *cmd
)
77 struct dpp_bootstrap_info
*bi
;
78 struct dpp_authentication
*auth
= wpa_s
->dpp_auth
;
80 bi
= dpp_parse_qr_code(cmd
);
84 bi
->id
= wpas_dpp_next_id(wpa_s
);
85 dl_list_add(&wpa_s
->dpp_bootstrap
, &bi
->list
);
87 if (auth
&& auth
->response_pending
&&
88 dpp_notify_new_qr_code(auth
, bi
) == 1) {
92 "DPP: Sending out pending authentication response");
93 msg
= dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP
,
94 wpabuf_len(auth
->resp_attr
));
97 wpabuf_put_buf(msg
, wpa_s
->dpp_auth
->resp_attr
);
99 offchannel_send_action(wpa_s
, auth
->curr_freq
,
100 auth
->peer_mac_addr
, wpa_s
->own_addr
,
102 wpabuf_head(msg
), wpabuf_len(msg
),
103 500, wpas_dpp_tx_status
, 0);
112 static char * get_param(const char *cmd
, const char *param
)
114 const char *pos
, *end
;
118 pos
= os_strstr(cmd
, param
);
122 pos
+= os_strlen(param
);
123 end
= os_strchr(pos
, ' ');
127 len
= os_strlen(pos
);
128 val
= os_malloc(len
+ 1);
131 os_memcpy(val
, pos
, len
);
137 int wpas_dpp_bootstrap_gen(struct wpa_supplicant
*wpa_s
, const char *cmd
)
139 char *chan
= NULL
, *mac
= NULL
, *info
= NULL
, *pk
= NULL
, *curve
= NULL
;
142 size_t privkey_len
= 0;
145 struct dpp_bootstrap_info
*bi
;
147 bi
= os_zalloc(sizeof(*bi
));
151 if (os_strstr(cmd
, "type=qrcode"))
152 bi
->type
= DPP_BOOTSTRAP_QR_CODE
;
156 chan
= get_param(cmd
, " chan=");
157 mac
= get_param(cmd
, " mac=");
158 info
= get_param(cmd
, " info=");
159 curve
= get_param(cmd
, " curve=");
160 key
= get_param(cmd
, " key=");
163 privkey_len
= os_strlen(key
) / 2;
164 privkey
= os_malloc(privkey_len
);
166 hexstr2bin(key
, privkey
, privkey_len
) < 0)
170 pk
= dpp_keygen(bi
, curve
, privkey
, privkey_len
);
174 len
= 4; /* "DPP:" */
176 if (dpp_parse_uri_chan_list(bi
, chan
) < 0)
178 len
+= 3 + os_strlen(chan
); /* C:...; */
181 if (dpp_parse_uri_mac(bi
, mac
) < 0)
183 len
+= 3 + os_strlen(mac
); /* M:...; */
186 if (dpp_parse_uri_info(bi
, info
) < 0)
188 len
+= 3 + os_strlen(info
); /* I:...; */
190 len
+= 4 + os_strlen(pk
);
191 bi
->uri
= os_malloc(len
+ 1);
194 os_snprintf(bi
->uri
, len
+ 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
195 chan
? "C:" : "", chan
? chan
: "", chan
? ";" : "",
196 mac
? "M:" : "", mac
? mac
: "", mac
? ";" : "",
197 info
? "I:" : "", info
? info
: "", info
? ";" : "",
199 bi
->id
= wpas_dpp_next_id(wpa_s
);
200 dl_list_add(&wpa_s
->dpp_bootstrap
, &bi
->list
);
210 bin_clear_free(privkey
, privkey_len
);
211 dpp_bootstrap_info_free(bi
);
216 static struct dpp_bootstrap_info
*
217 dpp_bootstrap_get_id(struct wpa_supplicant
*wpa_s
, unsigned int id
)
219 struct dpp_bootstrap_info
*bi
;
221 dl_list_for_each(bi
, &wpa_s
->dpp_bootstrap
, struct dpp_bootstrap_info
,
230 static int dpp_bootstrap_del(struct wpa_supplicant
*wpa_s
, unsigned int id
)
232 struct dpp_bootstrap_info
*bi
, *tmp
;
235 dl_list_for_each_safe(bi
, tmp
, &wpa_s
->dpp_bootstrap
,
236 struct dpp_bootstrap_info
, list
) {
237 if (id
&& bi
->id
!= id
)
240 dl_list_del(&bi
->list
);
241 dpp_bootstrap_info_free(bi
);
245 return 0; /* flush succeeds regardless of entries found */
246 return found
? 0 : -1;
250 int wpas_dpp_bootstrap_remove(struct wpa_supplicant
*wpa_s
, const char *id
)
254 if (os_strcmp(id
, "*") == 0) {
262 return dpp_bootstrap_del(wpa_s
, id_val
);
266 const char * wpas_dpp_bootstrap_get_uri(struct wpa_supplicant
*wpa_s
,
269 struct dpp_bootstrap_info
*bi
;
271 bi
= dpp_bootstrap_get_id(wpa_s
, id
);
278 static void wpas_dpp_tx_status(struct wpa_supplicant
*wpa_s
,
279 unsigned int freq
, const u8
*dst
,
280 const u8
*src
, const u8
*bssid
,
281 const u8
*data
, size_t data_len
,
282 enum offchannel_send_action_result result
)
284 wpa_printf(MSG_DEBUG
, "DPP: TX status: freq=%u dst=" MACSTR
287 result
== OFFCHANNEL_SEND_ACTION_SUCCESS
? "SUCCESS" :
288 (result
== OFFCHANNEL_SEND_ACTION_NO_ACK
? "no-ACK" :
291 if (!wpa_s
->dpp_auth
) {
292 wpa_printf(MSG_DEBUG
,
293 "DPP: Ignore TX status since there is no ongoing authentication exchange");
297 if (wpa_s
->dpp_auth
->remove_on_tx_status
) {
298 wpa_printf(MSG_DEBUG
,
299 "DPP: Terminate authentication exchange due to an earlier error");
300 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout
, wpa_s
, NULL
);
301 offchannel_send_action_done(wpa_s
);
302 dpp_auth_deinit(wpa_s
->dpp_auth
);
303 wpa_s
->dpp_auth
= NULL
;
307 if (wpa_s
->dpp_auth_ok_on_ack
)
308 wpas_dpp_auth_success(wpa_s
, 1);
310 if (!is_broadcast_ether_addr(dst
) &&
311 result
!= OFFCHANNEL_SEND_ACTION_SUCCESS
) {
312 wpa_printf(MSG_DEBUG
,
313 "DPP: Unicast DPP Action frame was not ACKed");
314 /* TODO: In case of DPP Authentication Request frame, move to
315 * the next channel immediately */
320 static void wpas_dpp_reply_wait_timeout(void *eloop_ctx
, void *timeout_ctx
)
322 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
324 if (!wpa_s
->dpp_auth
)
326 wpa_printf(MSG_DEBUG
, "DPP: Continue reply wait on channel %u MHz",
327 wpa_s
->dpp_auth
->curr_freq
);
328 wpas_dpp_listen_start(wpa_s
, wpa_s
->dpp_auth
->curr_freq
);
332 static void wpas_dpp_set_testing_options(struct wpa_supplicant
*wpa_s
,
333 struct dpp_authentication
*auth
)
335 #ifdef CONFIG_TESTING_OPTIONS
336 if (wpa_s
->dpp_config_obj_override
)
337 auth
->config_obj_override
=
338 os_strdup(wpa_s
->dpp_config_obj_override
);
339 if (wpa_s
->dpp_discovery_override
)
340 auth
->discovery_override
=
341 os_strdup(wpa_s
->dpp_discovery_override
);
342 if (wpa_s
->dpp_groups_override
)
343 auth
->groups_override
=
344 os_strdup(wpa_s
->dpp_groups_override
);
345 if (wpa_s
->dpp_devices_override
)
346 auth
->devices_override
=
347 os_strdup(wpa_s
->dpp_devices_override
);
348 auth
->ignore_netaccesskey_mismatch
=
349 wpa_s
->dpp_ignore_netaccesskey_mismatch
;
350 #endif /* CONFIG_TESTING_OPTIONS */
354 int wpas_dpp_auth_init(struct wpa_supplicant
*wpa_s
, const char *cmd
)
357 struct dpp_bootstrap_info
*peer_bi
, *own_bi
= NULL
;
361 int configurator
= 1;
362 unsigned int wait_time
;
363 struct dpp_configuration
*conf_sta
= NULL
, *conf_ap
= NULL
;
364 struct dpp_configurator
*conf
= NULL
;
366 wpa_s
->dpp_gas_client
= 0;
368 pos
= os_strstr(cmd
, " peer=");
372 peer_bi
= dpp_bootstrap_get_id(wpa_s
, atoi(pos
));
375 "DPP: Could not find bootstrapping info for the identified peer");
379 pos
= os_strstr(cmd
, " own=");
382 own_bi
= dpp_bootstrap_get_id(wpa_s
, atoi(pos
));
385 "DPP: Could not find bootstrapping info for the identified local entry");
389 if (peer_bi
->curve
!= own_bi
->curve
) {
391 "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
392 peer_bi
->curve
->name
, own_bi
->curve
->name
);
397 pos
= os_strstr(cmd
, " role=");
400 if (os_strncmp(pos
, "configurator", 12) == 0)
402 else if (os_strncmp(pos
, "enrollee", 8) == 0)
408 pos
= os_strstr(cmd
, " netrole=");
411 wpa_s
->dpp_netrole_ap
= os_strncmp(pos
, "ap", 2) == 0;
414 if (os_strstr(cmd
, " conf=sta-")) {
415 conf_sta
= os_zalloc(sizeof(struct dpp_configuration
));
418 /* TODO: Configuration of network parameters from upper layers
420 os_memcpy(conf_sta
->ssid
, "test", 4);
421 conf_sta
->ssid_len
= 4;
422 if (os_strstr(cmd
, " conf=sta-psk")) {
424 conf_sta
->passphrase
= os_strdup("secret passphrase");
425 if (!conf_sta
->passphrase
)
427 } else if (os_strstr(cmd
, " conf=sta-dpp")) {
434 if (os_strstr(cmd
, " conf=ap-")) {
435 conf_ap
= os_zalloc(sizeof(struct dpp_configuration
));
438 /* TODO: Configuration of network parameters from upper layers
440 os_memcpy(conf_ap
->ssid
, "test", 4);
441 conf_ap
->ssid_len
= 4;
442 if (os_strstr(cmd
, " conf=ap-psk")) {
444 conf_ap
->passphrase
= os_strdup("secret passphrase");
445 if (!conf_ap
->passphrase
)
447 } else if (os_strstr(cmd
, " conf=ap-dpp")) {
454 pos
= os_strstr(cmd
, " expiry=");
459 val
= strtol(pos
, NULL
, 0);
463 conf_sta
->netaccesskey_expiry
= val
;
465 conf_ap
->netaccesskey_expiry
= val
;
468 pos
= os_strstr(cmd
, " configurator=");
471 conf
= dpp_configurator_get_id(wpa_s
, atoi(pos
));
474 "DPP: Could not find the specified configurator");
479 if (wpa_s
->dpp_auth
) {
480 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout
, wpa_s
, NULL
);
481 offchannel_send_action_done(wpa_s
);
482 dpp_auth_deinit(wpa_s
->dpp_auth
);
484 wpa_s
->dpp_auth
= dpp_auth_init(wpa_s
, peer_bi
, own_bi
, configurator
);
485 if (!wpa_s
->dpp_auth
)
487 wpas_dpp_set_testing_options(wpa_s
, wpa_s
->dpp_auth
);
488 wpa_s
->dpp_auth
->conf_sta
= conf_sta
;
489 wpa_s
->dpp_auth
->conf_ap
= conf_ap
;
490 wpa_s
->dpp_auth
->conf
= conf
;
492 /* TODO: Support iteration over all frequencies and filtering of
493 * frequencies based on locally enabled channels that allow initiation
494 * of transmission. */
495 if (peer_bi
->num_freq
> 0)
496 wpa_s
->dpp_auth
->curr_freq
= peer_bi
->freq
[0];
498 wpa_s
->dpp_auth
->curr_freq
= 2412;
500 msg
= dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ
,
501 wpabuf_len(wpa_s
->dpp_auth
->req_attr
));
504 wpabuf_put_buf(msg
, wpa_s
->dpp_auth
->req_attr
);
506 if (is_zero_ether_addr(peer_bi
->mac_addr
)) {
509 dst
= peer_bi
->mac_addr
;
510 os_memcpy(wpa_s
->dpp_auth
->peer_mac_addr
, peer_bi
->mac_addr
,
513 wpa_s
->dpp_auth_ok_on_ack
= 0;
514 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout
, wpa_s
, NULL
);
515 wait_time
= wpa_s
->max_remain_on_chan
;
516 if (wait_time
> 2000)
518 eloop_register_timeout(wait_time
/ 1000, (wait_time
% 1000) * 1000,
519 wpas_dpp_reply_wait_timeout
,
521 res
= offchannel_send_action(wpa_s
, wpa_s
->dpp_auth
->curr_freq
,
522 dst
, wpa_s
->own_addr
, broadcast
,
523 wpabuf_head(msg
), wpabuf_len(msg
),
524 wait_time
, wpas_dpp_tx_status
, 0);
529 dpp_configuration_free(conf_sta
);
530 dpp_configuration_free(conf_ap
);
535 struct wpas_dpp_listen_work
{
537 unsigned int duration
;
538 struct wpabuf
*probe_resp_ie
;
542 static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work
*lwork
)
550 static void wpas_dpp_listen_work_done(struct wpa_supplicant
*wpa_s
)
552 struct wpas_dpp_listen_work
*lwork
;
554 if (!wpa_s
->dpp_listen_work
)
557 lwork
= wpa_s
->dpp_listen_work
->ctx
;
558 wpas_dpp_listen_work_free(lwork
);
559 radio_work_done(wpa_s
->dpp_listen_work
);
560 wpa_s
->dpp_listen_work
= NULL
;
564 static void dpp_start_listen_cb(struct wpa_radio_work
*work
, int deinit
)
566 struct wpa_supplicant
*wpa_s
= work
->wpa_s
;
567 struct wpas_dpp_listen_work
*lwork
= work
->ctx
;
571 wpa_s
->dpp_listen_work
= NULL
;
572 wpas_dpp_listen_stop(wpa_s
);
574 wpas_dpp_listen_work_free(lwork
);
578 wpa_s
->dpp_listen_work
= work
;
580 wpa_s
->dpp_pending_listen_freq
= lwork
->freq
;
582 if (wpa_drv_remain_on_channel(wpa_s
, lwork
->freq
,
583 wpa_s
->max_remain_on_chan
) < 0) {
584 wpa_printf(MSG_DEBUG
,
585 "DPP: Failed to request the driver to remain on channel (%u MHz) for listen",
587 wpas_dpp_listen_work_done(wpa_s
);
588 wpa_s
->dpp_pending_listen_freq
= 0;
591 wpa_s
->off_channel_freq
= 0;
592 wpa_s
->roc_waiting_drv_freq
= lwork
->freq
;
596 static int wpas_dpp_listen_start(struct wpa_supplicant
*wpa_s
,
599 struct wpas_dpp_listen_work
*lwork
;
601 if (wpa_s
->dpp_listen_work
) {
602 wpa_printf(MSG_DEBUG
,
603 "DPP: Reject start_listen since dpp_listen_work already exists");
607 if (wpa_s
->dpp_listen_freq
)
608 wpas_dpp_listen_stop(wpa_s
);
609 wpa_s
->dpp_listen_freq
= freq
;
611 lwork
= os_zalloc(sizeof(*lwork
));
616 if (radio_add_work(wpa_s
, freq
, "dpp-listen", 0, dpp_start_listen_cb
,
618 wpas_dpp_listen_work_free(lwork
);
626 int wpas_dpp_listen(struct wpa_supplicant
*wpa_s
, const char *cmd
)
634 if (os_strstr(cmd
, " role=configurator"))
635 wpa_s
->dpp_allowed_roles
= DPP_CAPAB_CONFIGURATOR
;
636 else if (os_strstr(cmd
, " role=enrollee"))
637 wpa_s
->dpp_allowed_roles
= DPP_CAPAB_ENROLLEE
;
639 wpa_s
->dpp_allowed_roles
= DPP_CAPAB_CONFIGURATOR
|
641 wpa_s
->dpp_qr_mutual
= os_strstr(cmd
, " qr=mutual") != NULL
;
642 wpa_s
->dpp_netrole_ap
= os_strstr(cmd
, " netrole=ap") != NULL
;
643 if (wpa_s
->dpp_listen_freq
== (unsigned int) freq
) {
644 wpa_printf(MSG_DEBUG
, "DPP: Already listening on %u MHz",
649 return wpas_dpp_listen_start(wpa_s
, freq
);
653 void wpas_dpp_listen_stop(struct wpa_supplicant
*wpa_s
)
655 if (!wpa_s
->dpp_listen_freq
)
658 wpa_printf(MSG_DEBUG
, "DPP: Stop listen on %u MHz",
659 wpa_s
->dpp_listen_freq
);
660 wpa_drv_cancel_remain_on_channel(wpa_s
);
661 wpa_s
->dpp_listen_freq
= 0;
662 wpas_dpp_listen_work_done(wpa_s
);
666 void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant
*wpa_s
,
669 if (!wpa_s
->dpp_listen_freq
&& !wpa_s
->dpp_pending_listen_freq
)
672 wpa_printf(MSG_DEBUG
,
673 "DPP: remain-on-channel callback (off_channel_freq=%u dpp_pending_listen_freq=%d roc_waiting_drv_freq=%d freq=%u)",
674 wpa_s
->off_channel_freq
, wpa_s
->dpp_pending_listen_freq
,
675 wpa_s
->roc_waiting_drv_freq
, freq
);
676 if (wpa_s
->off_channel_freq
&&
677 wpa_s
->off_channel_freq
== wpa_s
->dpp_pending_listen_freq
) {
678 wpa_printf(MSG_DEBUG
, "DPP: Listen on %u MHz started", freq
);
679 wpa_s
->dpp_pending_listen_freq
= 0;
681 wpa_printf(MSG_DEBUG
,
682 "DPP: Ignore remain-on-channel callback (off_channel_freq=%u dpp_pending_listen_freq=%d freq=%u)",
683 wpa_s
->off_channel_freq
,
684 wpa_s
->dpp_pending_listen_freq
, freq
);
689 void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant
*wpa_s
,
692 wpas_dpp_listen_work_done(wpa_s
);
694 if (wpa_s
->dpp_auth
&& !wpa_s
->dpp_gas_client
) {
695 /* Continue listen with a new remain-on-channel */
696 wpa_printf(MSG_DEBUG
,
697 "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session",
698 wpa_s
->dpp_auth
->curr_freq
);
699 wpas_dpp_listen_start(wpa_s
, wpa_s
->dpp_auth
->curr_freq
);
703 if (wpa_s
->dpp_listen_freq
) {
704 /* Continue listen with a new remain-on-channel */
705 wpas_dpp_listen_start(wpa_s
, wpa_s
->dpp_listen_freq
);
710 static void wpas_dpp_rx_auth_req(struct wpa_supplicant
*wpa_s
, const u8
*src
,
711 const u8
*buf
, size_t len
, unsigned int freq
)
713 const u8
*r_bootstrap
, *i_bootstrap
, *wrapped_data
;
714 u16 r_bootstrap_len
, i_bootstrap_len
, wrapped_data_len
;
715 struct dpp_bootstrap_info
*bi
, *own_bi
= NULL
, *peer_bi
= NULL
;
718 wpa_printf(MSG_DEBUG
, "DPP: Authentication Request from " MACSTR
,
721 wrapped_data
= dpp_get_attr(buf
, len
, DPP_ATTR_WRAPPED_DATA
,
724 wpa_printf(MSG_DEBUG
,
725 "DPP: Missing required Wrapped data attribute");
728 wpa_hexdump(MSG_MSGDUMP
, "DPP: Wrapped data",
729 wrapped_data
, wrapped_data_len
);
731 r_bootstrap
= dpp_get_attr(buf
, len
, DPP_ATTR_R_BOOTSTRAP_KEY_HASH
,
733 if (!r_bootstrap
|| r_bootstrap
> wrapped_data
||
734 r_bootstrap_len
!= SHA256_MAC_LEN
) {
735 wpa_printf(MSG_DEBUG
,
736 "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
739 wpa_hexdump(MSG_MSGDUMP
, "DPP: Responder Bootstrapping Key Hash",
740 r_bootstrap
, r_bootstrap_len
);
742 i_bootstrap
= dpp_get_attr(buf
, len
, DPP_ATTR_I_BOOTSTRAP_KEY_HASH
,
744 if (!i_bootstrap
|| i_bootstrap
> wrapped_data
||
745 i_bootstrap_len
!= SHA256_MAC_LEN
) {
746 wpa_printf(MSG_DEBUG
,
747 "DPP: Missing or invalid required Initiator Bootstrapping Key Hash attribute");
750 wpa_hexdump(MSG_MSGDUMP
, "DPP: Initiator Bootstrapping Key Hash",
751 i_bootstrap
, i_bootstrap_len
);
753 /* Try to find own and peer bootstrapping key matches based on the
754 * received hash values */
755 dl_list_for_each(bi
, &wpa_s
->dpp_bootstrap
, struct dpp_bootstrap_info
,
757 if (!own_bi
&& bi
->own
&&
758 os_memcmp(bi
->pubkey_hash
, r_bootstrap
,
759 SHA256_MAC_LEN
) == 0) {
760 wpa_printf(MSG_DEBUG
,
761 "DPP: Found matching own bootstrapping information");
765 if (!peer_bi
&& !bi
->own
&&
766 os_memcmp(bi
->pubkey_hash
, i_bootstrap
,
767 SHA256_MAC_LEN
) == 0) {
768 wpa_printf(MSG_DEBUG
,
769 "DPP: Found matching peer bootstrapping information");
773 if (own_bi
&& peer_bi
)
778 wpa_printf(MSG_DEBUG
,
779 "DPP: No matching own bootstrapping key found - ignore message");
783 if (wpa_s
->dpp_auth
) {
784 wpa_printf(MSG_DEBUG
,
785 "DPP: Already in DPP authentication exchange - ignore new one");
789 wpa_s
->dpp_gas_client
= 0;
790 wpa_s
->dpp_auth_ok_on_ack
= 0;
791 wpa_s
->dpp_auth
= dpp_auth_req_rx(wpa_s
, wpa_s
->dpp_allowed_roles
,
792 wpa_s
->dpp_qr_mutual
,
793 peer_bi
, own_bi
, freq
, buf
,
794 wrapped_data
, wrapped_data_len
);
795 if (!wpa_s
->dpp_auth
) {
796 wpa_printf(MSG_DEBUG
, "DPP: No response generated");
799 wpas_dpp_set_testing_options(wpa_s
, wpa_s
->dpp_auth
);
800 os_memcpy(wpa_s
->dpp_auth
->peer_mac_addr
, src
, ETH_ALEN
);
802 msg
= dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP
,
803 wpabuf_len(wpa_s
->dpp_auth
->resp_attr
));
806 wpabuf_put_buf(msg
, wpa_s
->dpp_auth
->resp_attr
);
808 offchannel_send_action(wpa_s
, wpa_s
->dpp_auth
->curr_freq
,
809 src
, wpa_s
->own_addr
, broadcast
,
810 wpabuf_head(msg
), wpabuf_len(msg
),
811 500, wpas_dpp_tx_status
, 0);
816 static void wpas_dpp_start_gas_server(struct wpa_supplicant
*wpa_s
)
818 /* TODO: stop wait and start ROC */
822 static void wpas_dpp_gas_resp_cb(void *ctx
, const u8
*addr
, u8 dialog_token
,
823 enum gas_query_result result
,
824 const struct wpabuf
*adv_proto
,
825 const struct wpabuf
*resp
, u16 status_code
)
827 struct wpa_supplicant
*wpa_s
= ctx
;
829 struct dpp_authentication
*auth
= wpa_s
->dpp_auth
;
831 if (!auth
|| !auth
->auth_success
) {
832 wpa_printf(MSG_DEBUG
, "DPP: No matching exchange in progress");
835 if (!resp
|| status_code
!= WLAN_STATUS_SUCCESS
) {
836 wpa_printf(MSG_DEBUG
, "DPP: GAS query did not succeed");
840 wpa_hexdump_buf(MSG_DEBUG
, "DPP: Configuration Response adv_proto",
842 wpa_hexdump_buf(MSG_DEBUG
, "DPP: Configuration Response (GAS response)",
845 if (wpabuf_len(adv_proto
) != 10 ||
846 !(pos
= wpabuf_head(adv_proto
)) ||
847 pos
[0] != WLAN_EID_ADV_PROTO
||
849 pos
[3] != WLAN_EID_VENDOR_SPECIFIC
||
851 WPA_GET_BE24(&pos
[5]) != OUI_WFA
||
854 wpa_printf(MSG_DEBUG
,
855 "DPP: Not a DPP Advertisement Protocol ID");
859 if (dpp_conf_resp_rx(auth
, resp
) < 0) {
860 wpa_printf(MSG_DEBUG
, "DPP: Configuration attempt failed");
864 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_CONF_RECEIVED
);
866 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_CONFOBJ_SSID
"%s",
867 wpa_ssid_txt(auth
->ssid
, auth
->ssid_len
));
868 if (auth
->connector
) {
869 /* TODO: Save the Connector and consider using a command
870 * to fetch the value instead of sending an event with
871 * it. The Connector could end up being larger than what
872 * most clients are ready to receive as an event
874 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_CONNECTOR
"%s",
877 if (auth
->c_sign_key
) {
881 hexlen
= 2 * wpabuf_len(auth
->c_sign_key
) + 1;
882 hex
= os_malloc(hexlen
);
884 wpa_snprintf_hex(hex
, hexlen
,
885 wpabuf_head(auth
->c_sign_key
),
886 wpabuf_len(auth
->c_sign_key
));
887 if (auth
->c_sign_key_expiry
)
888 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_C_SIGN_KEY
891 auth
->c_sign_key_expiry
);
893 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_C_SIGN_KEY
898 if (auth
->net_access_key
) {
902 hexlen
= 2 * wpabuf_len(auth
->net_access_key
) + 1;
903 hex
= os_malloc(hexlen
);
905 wpa_snprintf_hex(hex
, hexlen
,
906 wpabuf_head(auth
->net_access_key
),
907 wpabuf_len(auth
->net_access_key
));
908 if (auth
->net_access_key_expiry
)
909 wpa_msg(wpa_s
, MSG_INFO
,
910 DPP_EVENT_NET_ACCESS_KEY
"%s %lu", hex
,
912 auth
->net_access_key_expiry
);
914 wpa_msg(wpa_s
, MSG_INFO
,
915 DPP_EVENT_NET_ACCESS_KEY
"%s", hex
);
919 dpp_auth_deinit(wpa_s
->dpp_auth
);
920 wpa_s
->dpp_auth
= NULL
;
924 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_CONF_FAILED
);
925 dpp_auth_deinit(wpa_s
->dpp_auth
);
926 wpa_s
->dpp_auth
= NULL
;
930 static void wpas_dpp_start_gas_client(struct wpa_supplicant
*wpa_s
)
932 struct dpp_authentication
*auth
= wpa_s
->dpp_auth
;
933 struct wpabuf
*buf
, *conf_req
;
937 wpa_s
->dpp_gas_client
= 1;
938 os_snprintf(json
, sizeof(json
),
939 "{\"name\":\"Test\","
940 "\"wi-fi_tech\":\"infra\","
941 "\"netRole\":\"%s\"}",
942 wpa_s
->dpp_netrole_ap
? "ap" : "sta");
943 wpa_printf(MSG_DEBUG
, "DPP: GAS Config Attributes: %s", json
);
945 offchannel_send_action_done(wpa_s
);
946 wpas_dpp_listen_stop(wpa_s
);
948 conf_req
= dpp_build_conf_req(auth
, json
);
950 wpa_printf(MSG_DEBUG
,
951 "DPP: No configuration request data available");
955 buf
= gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req
));
957 wpabuf_free(conf_req
);
961 /* Advertisement Protocol IE */
962 wpabuf_put_u8(buf
, WLAN_EID_ADV_PROTO
);
963 wpabuf_put_u8(buf
, 8); /* Length */
964 wpabuf_put_u8(buf
, 0x7f);
965 wpabuf_put_u8(buf
, WLAN_EID_VENDOR_SPECIFIC
);
966 wpabuf_put_u8(buf
, 5);
967 wpabuf_put_be24(buf
, OUI_WFA
);
968 wpabuf_put_u8(buf
, DPP_OUI_TYPE
);
969 wpabuf_put_u8(buf
, 0x01);
972 wpabuf_put_le16(buf
, wpabuf_len(conf_req
));
973 wpabuf_put_buf(buf
, conf_req
);
974 wpabuf_free(conf_req
);
976 wpa_printf(MSG_DEBUG
, "DPP: GAS request to " MACSTR
" (freq %u MHz)",
977 MAC2STR(auth
->peer_mac_addr
), auth
->curr_freq
);
979 res
= gas_query_req(wpa_s
->gas
, auth
->peer_mac_addr
, auth
->curr_freq
,
980 buf
, wpas_dpp_gas_resp_cb
, wpa_s
);
982 wpa_msg(wpa_s
, MSG_DEBUG
, "GAS: Failed to send Query Request");
985 wpa_printf(MSG_DEBUG
,
986 "DPP: GAS query started with dialog token %u", res
);
991 static void wpas_dpp_auth_success(struct wpa_supplicant
*wpa_s
, int initiator
)
993 wpa_printf(MSG_DEBUG
, "DPP: Authentication succeeded");
994 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_AUTH_SUCCESS
"init=%d", initiator
);
996 if (wpa_s
->dpp_auth
->configurator
)
997 wpas_dpp_start_gas_server(wpa_s
);
999 wpas_dpp_start_gas_client(wpa_s
);
1003 static void wpas_dpp_rx_auth_resp(struct wpa_supplicant
*wpa_s
, const u8
*src
,
1004 const u8
*buf
, size_t len
)
1006 struct dpp_authentication
*auth
= wpa_s
->dpp_auth
;
1007 struct wpabuf
*msg
, *attr
;
1009 wpa_printf(MSG_DEBUG
, "DPP: Authentication Response from " MACSTR
,
1013 wpa_printf(MSG_DEBUG
,
1014 "DPP: No DPP Authentication in progress - drop");
1018 if (!is_zero_ether_addr(auth
->peer_mac_addr
) &&
1019 os_memcmp(src
, auth
->peer_mac_addr
, ETH_ALEN
) != 0) {
1020 wpa_printf(MSG_DEBUG
, "DPP: MAC address mismatch (expected "
1021 MACSTR
") - drop", MAC2STR(auth
->peer_mac_addr
));
1025 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout
, wpa_s
, NULL
);
1027 attr
= dpp_auth_resp_rx(auth
, buf
, len
);
1029 if (auth
->auth_resp_status
== DPP_STATUS_RESPONSE_PENDING
) {
1030 wpa_printf(MSG_DEBUG
,
1031 "DPP: Start wait for full response");
1032 offchannel_send_action_done(wpa_s
);
1033 wpas_dpp_listen_start(wpa_s
, auth
->curr_freq
);
1036 wpa_printf(MSG_DEBUG
, "DPP: No confirm generated");
1039 os_memcpy(auth
->peer_mac_addr
, src
, ETH_ALEN
);
1041 msg
= dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF
, wpabuf_len(attr
));
1046 wpabuf_put_buf(msg
, attr
);
1049 offchannel_send_action(wpa_s
, auth
->curr_freq
,
1050 src
, wpa_s
->own_addr
, broadcast
,
1051 wpabuf_head(msg
), wpabuf_len(msg
),
1052 500, wpas_dpp_tx_status
, 0);
1054 wpa_s
->dpp_auth_ok_on_ack
= 1;
1058 static void wpas_dpp_rx_auth_conf(struct wpa_supplicant
*wpa_s
, const u8
*src
,
1059 const u8
*buf
, size_t len
)
1061 struct dpp_authentication
*auth
= wpa_s
->dpp_auth
;
1063 wpa_printf(MSG_DEBUG
, "DPP: Authentication Confirmation from " MACSTR
,
1067 wpa_printf(MSG_DEBUG
,
1068 "DPP: No DPP Authentication in progress - drop");
1072 if (os_memcmp(src
, auth
->peer_mac_addr
, ETH_ALEN
) != 0) {
1073 wpa_printf(MSG_DEBUG
, "DPP: MAC address mismatch (expected "
1074 MACSTR
") - drop", MAC2STR(auth
->peer_mac_addr
));
1078 if (dpp_auth_conf_rx(auth
, buf
, len
) < 0) {
1079 wpa_printf(MSG_DEBUG
, "DPP: Authentication failed");
1083 wpas_dpp_auth_success(wpa_s
, 0);
1087 static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant
*wpa_s
,
1089 const u8
*buf
, size_t len
)
1091 struct wpa_ssid
*ssid
;
1092 const u8
*connector
, *pk_hash
, *nk_hash
;
1093 u16 connector_len
, pk_hash_len
, nk_hash_len
;
1094 struct dpp_introduction intro
;
1095 struct rsn_pmksa_cache_entry
*entry
;
1097 wpa_printf(MSG_DEBUG
, "DPP: Peer Discovery Response from " MACSTR
,
1099 if (is_zero_ether_addr(wpa_s
->dpp_intro_bssid
) ||
1100 os_memcmp(src
, wpa_s
->dpp_intro_bssid
, ETH_ALEN
) != 0) {
1101 wpa_printf(MSG_DEBUG
, "DPP: Not waiting for response from "
1102 MACSTR
" - drop", MAC2STR(src
));
1105 offchannel_send_action_done(wpa_s
);
1107 for (ssid
= wpa_s
->conf
->ssid
; ssid
; ssid
= ssid
->next
) {
1108 if (ssid
== wpa_s
->dpp_intro_network
)
1111 if (!ssid
|| !ssid
->dpp_connector
|| !ssid
->dpp_netaccesskey
||
1113 wpa_printf(MSG_DEBUG
,
1114 "DPP: Profile not found for network introduction");
1118 connector
= dpp_get_attr(buf
, len
, DPP_ATTR_CONNECTOR
, &connector_len
);
1120 wpa_printf(MSG_DEBUG
,
1121 "DPP: Peer did not include its Connector");
1125 if (dpp_peer_intro(&intro
, ssid
->dpp_connector
,
1126 ssid
->dpp_netaccesskey
,
1127 ssid
->dpp_netaccesskey_len
,
1129 ssid
->dpp_csign_len
,
1130 connector
, connector_len
) < 0) {
1131 wpa_printf(MSG_INFO
,
1132 "DPP: Network Introduction protocol resulted in failure");
1136 pk_hash
= dpp_get_attr(buf
, len
, DPP_ATTR_PEER_NET_PK_HASH
,
1138 if (!pk_hash
|| pk_hash_len
!= SHA256_MAC_LEN
) {
1139 wpa_printf(MSG_DEBUG
, "DPP: Peer did not include SHA256(PK)");
1142 if (os_memcmp(pk_hash
, intro
.nk_hash
, SHA256_MAC_LEN
) != 0) {
1143 wpa_printf(MSG_DEBUG
, "DPP: SHA256(PK) mismatch");
1144 wpa_hexdump(MSG_DEBUG
, "DPP: Received SHA256(PK)",
1145 pk_hash
, pk_hash_len
);
1146 wpa_hexdump(MSG_DEBUG
, "DPP: Calculated SHA256(PK)",
1147 intro
.nk_hash
, SHA256_MAC_LEN
);
1151 nk_hash
= dpp_get_attr(buf
, len
, DPP_ATTR_OWN_NET_NK_HASH
,
1153 if (!nk_hash
|| nk_hash_len
!= SHA256_MAC_LEN
) {
1154 wpa_printf(MSG_DEBUG
, "DPP: Peer did not include SHA256(NK)");
1157 if (os_memcmp(nk_hash
, intro
.pk_hash
, SHA256_MAC_LEN
) != 0) {
1158 wpa_printf(MSG_DEBUG
, "DPP: SHA256(NK) mismatch");
1159 wpa_hexdump(MSG_DEBUG
, "DPP: Received SHA256(NK)",
1160 nk_hash
, nk_hash_len
);
1161 wpa_hexdump(MSG_DEBUG
, "DPP: Calculated SHA256(NK)",
1162 intro
.pk_hash
, SHA256_MAC_LEN
);
1166 entry
= os_zalloc(sizeof(*entry
));
1169 os_memcpy(entry
->aa
, src
, ETH_ALEN
);
1170 os_memcpy(entry
->pmkid
, intro
.pmkid
, PMKID_LEN
);
1171 os_memcpy(entry
->pmk
, intro
.pmk
, intro
.pmk_len
);
1172 entry
->pmk_len
= intro
.pmk_len
;
1173 entry
->akmp
= WPA_KEY_MGMT_DPP
;
1174 /* TODO: expiration */
1175 entry
->network_ctx
= ssid
;
1176 wpa_sm_pmksa_cache_add_entry(wpa_s
->wpa
, entry
);
1178 wpa_printf(MSG_DEBUG
,
1179 "DPP: Try connection again after successful network introduction");
1180 if (wpa_supplicant_fast_associate(wpa_s
) != 1) {
1181 wpa_supplicant_cancel_sched_scan(wpa_s
);
1182 wpa_supplicant_req_scan(wpa_s
, 0, 0);
1185 os_memset(&intro
, 0, sizeof(intro
));
1189 void wpas_dpp_rx_action(struct wpa_supplicant
*wpa_s
, const u8
*src
,
1190 const u8
*buf
, size_t len
, unsigned int freq
)
1192 enum dpp_public_action_frame_type type
;
1200 wpa_printf(MSG_DEBUG
,
1201 "DPP: Received DPP Public Action frame type %d from "
1203 type
, MAC2STR(src
), freq
);
1204 wpa_hexdump(MSG_MSGDUMP
, "DPP: Received message attributes", buf
, len
);
1205 if (dpp_check_attrs(buf
, len
) < 0)
1209 case DPP_PA_AUTHENTICATION_REQ
:
1210 wpas_dpp_rx_auth_req(wpa_s
, src
, buf
, len
, freq
);
1212 case DPP_PA_AUTHENTICATION_RESP
:
1213 wpas_dpp_rx_auth_resp(wpa_s
, src
, buf
, len
);
1215 case DPP_PA_AUTHENTICATION_CONF
:
1216 wpas_dpp_rx_auth_conf(wpa_s
, src
, buf
, len
);
1218 case DPP_PA_PEER_DISCOVERY_RESP
:
1219 wpas_dpp_rx_peer_disc_resp(wpa_s
, src
, buf
, len
);
1222 wpa_printf(MSG_DEBUG
,
1223 "DPP: Ignored unsupported frame subtype %d", type
);
1229 static struct wpabuf
*
1230 wpas_dpp_gas_req_handler(void *ctx
, const u8
*sa
, const u8
*query
,
1233 struct wpa_supplicant
*wpa_s
= ctx
;
1234 struct dpp_authentication
*auth
= wpa_s
->dpp_auth
;
1235 struct wpabuf
*resp
;
1237 wpa_printf(MSG_DEBUG
, "DPP: GAS request from " MACSTR
,
1239 if (!auth
|| !auth
->auth_success
||
1240 os_memcmp(sa
, auth
->peer_mac_addr
, ETH_ALEN
) != 0) {
1241 wpa_printf(MSG_DEBUG
, "DPP: No matching exchange in progress");
1244 wpa_hexdump(MSG_DEBUG
,
1245 "DPP: Received Configuration Request (GAS Query Request)",
1247 resp
= dpp_conf_req_rx(auth
, query
, query_len
);
1249 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_CONF_FAILED
);
1255 wpas_dpp_gas_status_handler(void *ctx
, struct wpabuf
*resp
, int ok
)
1257 struct wpa_supplicant
*wpa_s
= ctx
;
1258 struct dpp_authentication
*auth
= wpa_s
->dpp_auth
;
1265 wpa_printf(MSG_DEBUG
, "DPP: Configuration exchange completed (ok=%d)",
1267 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout
, wpa_s
, NULL
);
1268 offchannel_send_action_done(wpa_s
);
1269 wpas_dpp_listen_stop(wpa_s
);
1271 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_CONF_SENT
);
1273 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_CONF_FAILED
);
1274 dpp_auth_deinit(wpa_s
->dpp_auth
);
1275 wpa_s
->dpp_auth
= NULL
;
1280 static unsigned int wpas_dpp_next_configurator_id(struct wpa_supplicant
*wpa_s
)
1282 struct dpp_configurator
*conf
;
1283 unsigned int max_id
= 0;
1285 dl_list_for_each(conf
, &wpa_s
->dpp_configurator
,
1286 struct dpp_configurator
, list
) {
1287 if (conf
->id
> max_id
)
1294 int wpas_dpp_configurator_add(struct wpa_supplicant
*wpa_s
, const char *cmd
)
1296 char *expiry
= NULL
, *curve
= NULL
;
1299 size_t privkey_len
= 0;
1301 struct dpp_configurator
*conf
= NULL
;
1303 expiry
= get_param(cmd
, " expiry=");
1304 curve
= get_param(cmd
, " curve=");
1305 key
= get_param(cmd
, " key=");
1308 privkey_len
= os_strlen(key
) / 2;
1309 privkey
= os_malloc(privkey_len
);
1311 hexstr2bin(key
, privkey
, privkey_len
) < 0)
1315 conf
= dpp_keygen_configurator(curve
, privkey
, privkey_len
);
1322 val
= strtol(expiry
, NULL
, 0);
1325 conf
->csign_expiry
= val
;
1328 conf
->id
= wpas_dpp_next_configurator_id(wpa_s
);
1329 dl_list_add(&wpa_s
->dpp_configurator
, &conf
->list
);
1335 str_clear_free(key
);
1336 bin_clear_free(privkey
, privkey_len
);
1337 dpp_configurator_free(conf
);
1342 static int dpp_configurator_del(struct wpa_supplicant
*wpa_s
, unsigned int id
)
1344 struct dpp_configurator
*conf
, *tmp
;
1347 dl_list_for_each_safe(conf
, tmp
, &wpa_s
->dpp_configurator
,
1348 struct dpp_configurator
, list
) {
1349 if (id
&& conf
->id
!= id
)
1352 dl_list_del(&conf
->list
);
1353 dpp_configurator_free(conf
);
1357 return 0; /* flush succeeds regardless of entries found */
1358 return found
? 0 : -1;
1362 int wpas_dpp_configurator_remove(struct wpa_supplicant
*wpa_s
, const char *id
)
1364 unsigned int id_val
;
1366 if (os_strcmp(id
, "*") == 0) {
1374 return dpp_configurator_del(wpa_s
, id_val
);
1379 wpas_dpp_tx_introduction_status(struct wpa_supplicant
*wpa_s
,
1380 unsigned int freq
, const u8
*dst
,
1381 const u8
*src
, const u8
*bssid
,
1382 const u8
*data
, size_t data_len
,
1383 enum offchannel_send_action_result result
)
1385 wpa_printf(MSG_DEBUG
, "DPP: TX status: freq=%u dst=" MACSTR
1386 " result=%s (DPP Peer Discovery Request)",
1388 result
== OFFCHANNEL_SEND_ACTION_SUCCESS
? "SUCCESS" :
1389 (result
== OFFCHANNEL_SEND_ACTION_NO_ACK
? "no-ACK" :
1391 /* TODO: Time out wait for response more quickly in error cases? */
1395 int wpas_dpp_check_connect(struct wpa_supplicant
*wpa_s
, struct wpa_ssid
*ssid
,
1396 struct wpa_bss
*bss
)
1400 unsigned int wait_time
;
1402 if (!(ssid
->key_mgmt
& WPA_KEY_MGMT_DPP
) || !bss
)
1403 return 0; /* Not using DPP AKM - continue */
1404 if (wpa_sm_pmksa_exists(wpa_s
->wpa
, bss
->bssid
, ssid
))
1405 return 0; /* PMKSA exists for DPP AKM - continue */
1407 if (!ssid
->dpp_connector
|| !ssid
->dpp_netaccesskey
||
1409 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_MISSING_CONNECTOR
1411 !ssid
->dpp_connector
? "Connector" :
1412 (!ssid
->dpp_netaccesskey
? "netAccessKey" :
1419 if (ssid
->dpp_csign_expiry
&& ssid
->dpp_csign_expiry
< now
.sec
) {
1420 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_MISSING_CONNECTOR
1421 "C-sign-key expired");
1425 if (ssid
->dpp_netaccesskey_expiry
&&
1426 ssid
->dpp_netaccesskey_expiry
< now
.sec
) {
1427 wpa_msg(wpa_s
, MSG_INFO
, DPP_EVENT_MISSING_CONNECTOR
1428 "netAccessKey expired");
1432 wpa_printf(MSG_DEBUG
,
1433 "DPP: Starting network introduction protocol to derive PMKSA for "
1434 MACSTR
, MAC2STR(bss
->bssid
));
1436 msg
= dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ
,
1437 4 + os_strlen(ssid
->dpp_connector
));
1442 wpabuf_put_le16(msg
, DPP_ATTR_CONNECTOR
);
1443 wpabuf_put_le16(msg
, os_strlen(ssid
->dpp_connector
));
1444 wpabuf_put_str(msg
, ssid
->dpp_connector
);
1446 /* TODO: Timeout on AP response */
1447 wait_time
= wpa_s
->max_remain_on_chan
;
1448 if (wait_time
> 2000)
1450 offchannel_send_action(wpa_s
, bss
->freq
, bss
->bssid
, wpa_s
->own_addr
,
1452 wpabuf_head(msg
), wpabuf_len(msg
),
1453 wait_time
, wpas_dpp_tx_introduction_status
, 0);
1456 /* Request this connection attempt to terminate - new one will be
1457 * started when network introduction protocol completes */
1458 os_memcpy(wpa_s
->dpp_intro_bssid
, bss
->bssid
, ETH_ALEN
);
1459 wpa_s
->dpp_intro_network
= ssid
;
1464 int wpas_dpp_init(struct wpa_supplicant
*wpa_s
)
1468 adv_proto_id
[0] = WLAN_EID_VENDOR_SPECIFIC
;
1469 adv_proto_id
[1] = 5;
1470 WPA_PUT_BE24(&adv_proto_id
[2], OUI_WFA
);
1471 adv_proto_id
[5] = DPP_OUI_TYPE
;
1472 adv_proto_id
[6] = 0x01;
1474 if (gas_server_register(wpa_s
->gas_server
, adv_proto_id
,
1475 sizeof(adv_proto_id
), wpas_dpp_gas_req_handler
,
1476 wpas_dpp_gas_status_handler
, wpa_s
) < 0)
1478 dl_list_init(&wpa_s
->dpp_bootstrap
);
1479 dl_list_init(&wpa_s
->dpp_configurator
);
1480 wpa_s
->dpp_init_done
= 1;
1485 void wpas_dpp_deinit(struct wpa_supplicant
*wpa_s
)
1487 #ifdef CONFIG_TESTING_OPTIONS
1488 os_free(wpa_s
->dpp_config_obj_override
);
1489 wpa_s
->dpp_config_obj_override
= NULL
;
1490 os_free(wpa_s
->dpp_discovery_override
);
1491 wpa_s
->dpp_discovery_override
= NULL
;
1492 os_free(wpa_s
->dpp_groups_override
);
1493 wpa_s
->dpp_groups_override
= NULL
;
1494 os_free(wpa_s
->dpp_devices_override
);
1495 wpa_s
->dpp_devices_override
= NULL
;
1496 wpa_s
->dpp_ignore_netaccesskey_mismatch
= 0;
1497 #endif /* CONFIG_TESTING_OPTIONS */
1498 if (!wpa_s
->dpp_init_done
)
1500 eloop_cancel_timeout(wpas_dpp_reply_wait_timeout
, wpa_s
, NULL
);
1501 offchannel_send_action_done(wpa_s
);
1502 wpas_dpp_listen_stop(wpa_s
);
1503 dpp_bootstrap_del(wpa_s
, 0);
1504 dpp_configurator_del(wpa_s
, 0);
1505 dpp_auth_deinit(wpa_s
->dpp_auth
);
1506 wpa_s
->dpp_auth
= NULL
;
1507 os_memset(wpa_s
->dpp_intro_bssid
, 0, ETH_ALEN
);