185732ac8SCy Schubert /* 285732ac8SCy Schubert * wpa_supplicant - DPP 385732ac8SCy Schubert * Copyright (c) 2017, Qualcomm Atheros, Inc. 4c1d255d3SCy Schubert * Copyright (c) 2018-2020, The Linux Foundation 585732ac8SCy Schubert * 685732ac8SCy Schubert * This software may be distributed under the terms of the BSD license. 785732ac8SCy Schubert * See README for more details. 885732ac8SCy Schubert */ 985732ac8SCy Schubert 1085732ac8SCy Schubert #include "utils/includes.h" 1185732ac8SCy Schubert 1285732ac8SCy Schubert #include "utils/common.h" 1385732ac8SCy Schubert #include "utils/eloop.h" 14206b73d0SCy Schubert #include "utils/ip_addr.h" 15c1d255d3SCy Schubert #include "utils/base64.h" 1685732ac8SCy Schubert #include "common/dpp.h" 1785732ac8SCy Schubert #include "common/gas.h" 1885732ac8SCy Schubert #include "common/gas_server.h" 1985732ac8SCy Schubert #include "rsn_supp/wpa.h" 2085732ac8SCy Schubert #include "rsn_supp/pmksa_cache.h" 2185732ac8SCy Schubert #include "wpa_supplicant_i.h" 2285732ac8SCy Schubert #include "config.h" 2385732ac8SCy Schubert #include "driver_i.h" 2485732ac8SCy Schubert #include "offchannel.h" 2585732ac8SCy Schubert #include "gas_query.h" 2685732ac8SCy Schubert #include "bss.h" 2785732ac8SCy Schubert #include "scan.h" 2885732ac8SCy Schubert #include "notify.h" 2985732ac8SCy Schubert #include "dpp_supplicant.h" 3085732ac8SCy Schubert 3185732ac8SCy Schubert 3285732ac8SCy Schubert static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s, 3385732ac8SCy Schubert unsigned int freq); 3485732ac8SCy Schubert static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx); 35c1d255d3SCy Schubert static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx); 3685732ac8SCy Schubert static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator); 3785732ac8SCy Schubert static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s, 3885732ac8SCy Schubert unsigned int freq, const u8 *dst, 3985732ac8SCy Schubert const u8 *src, const u8 *bssid, 4085732ac8SCy Schubert const u8 *data, size_t data_len, 4185732ac8SCy Schubert enum offchannel_send_action_result result); 4285732ac8SCy Schubert static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx); 4385732ac8SCy Schubert static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s); 4485732ac8SCy Schubert static void 4585732ac8SCy Schubert wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s, 4685732ac8SCy Schubert unsigned int freq, const u8 *dst, 4785732ac8SCy Schubert const u8 *src, const u8 *bssid, 4885732ac8SCy Schubert const u8 *data, size_t data_len, 4985732ac8SCy Schubert enum offchannel_send_action_result result); 50c1d255d3SCy Schubert #ifdef CONFIG_DPP2 51c1d255d3SCy Schubert static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, 52c1d255d3SCy Schubert void *timeout_ctx); 53c1d255d3SCy Schubert static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s); 54c1d255d3SCy Schubert static int wpas_dpp_process_conf_obj(void *ctx, 55c1d255d3SCy Schubert struct dpp_authentication *auth); 56c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 5785732ac8SCy Schubert 5885732ac8SCy Schubert static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 5985732ac8SCy Schubert 6085732ac8SCy Schubert /* Use a hardcoded Transaction ID 1 in Peer Discovery frames since there is only 6185732ac8SCy Schubert * a single transaction in progress at any point in time. */ 6285732ac8SCy Schubert static const u8 TRANSACTION_ID = 1; 6385732ac8SCy Schubert 6485732ac8SCy Schubert 6585732ac8SCy Schubert /** 6685732ac8SCy Schubert * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code 6785732ac8SCy Schubert * @wpa_s: Pointer to wpa_supplicant data 6885732ac8SCy Schubert * @cmd: DPP URI read from a QR Code 6985732ac8SCy Schubert * Returns: Identifier of the stored info or -1 on failure 7085732ac8SCy Schubert */ 7185732ac8SCy Schubert int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd) 7285732ac8SCy Schubert { 7385732ac8SCy Schubert struct dpp_bootstrap_info *bi; 7485732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 7585732ac8SCy Schubert 764bc52338SCy Schubert bi = dpp_add_qr_code(wpa_s->dpp, cmd); 7785732ac8SCy Schubert if (!bi) 7885732ac8SCy Schubert return -1; 7985732ac8SCy Schubert 8085732ac8SCy Schubert if (auth && auth->response_pending && 8185732ac8SCy Schubert dpp_notify_new_qr_code(auth, bi) == 1) { 8285732ac8SCy Schubert wpa_printf(MSG_DEBUG, 8385732ac8SCy Schubert "DPP: Sending out pending authentication response"); 8485732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 8585732ac8SCy Schubert " freq=%u type=%d", 8685732ac8SCy Schubert MAC2STR(auth->peer_mac_addr), auth->curr_freq, 8785732ac8SCy Schubert DPP_PA_AUTHENTICATION_RESP); 8885732ac8SCy Schubert offchannel_send_action(wpa_s, auth->curr_freq, 8985732ac8SCy Schubert auth->peer_mac_addr, wpa_s->own_addr, 9085732ac8SCy Schubert broadcast, 9185732ac8SCy Schubert wpabuf_head(auth->resp_msg), 9285732ac8SCy Schubert wpabuf_len(auth->resp_msg), 9385732ac8SCy Schubert 500, wpas_dpp_tx_status, 0); 9485732ac8SCy Schubert } 9585732ac8SCy Schubert 96c1d255d3SCy Schubert #ifdef CONFIG_DPP2 97c1d255d3SCy Schubert dpp_controller_new_qr_code(wpa_s->dpp, bi); 98c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 99c1d255d3SCy Schubert 10085732ac8SCy Schubert return bi->id; 10185732ac8SCy Schubert } 10285732ac8SCy Schubert 10385732ac8SCy Schubert 104c1d255d3SCy Schubert /** 105c1d255d3SCy Schubert * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI) 106c1d255d3SCy Schubert * @wpa_s: Pointer to wpa_supplicant data 107c1d255d3SCy Schubert * @cmd: DPP URI read from a NFC Tag (URI NDEF message) 108c1d255d3SCy Schubert * Returns: Identifier of the stored info or -1 on failure 109c1d255d3SCy Schubert */ 110c1d255d3SCy Schubert int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd) 111c1d255d3SCy Schubert { 112c1d255d3SCy Schubert struct dpp_bootstrap_info *bi; 113c1d255d3SCy Schubert 114c1d255d3SCy Schubert bi = dpp_add_nfc_uri(wpa_s->dpp, cmd); 115c1d255d3SCy Schubert if (!bi) 116c1d255d3SCy Schubert return -1; 117c1d255d3SCy Schubert 118c1d255d3SCy Schubert return bi->id; 119c1d255d3SCy Schubert } 120c1d255d3SCy Schubert 121c1d255d3SCy Schubert 122c1d255d3SCy Schubert int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd) 123c1d255d3SCy Schubert { 124c1d255d3SCy Schubert const char *pos; 125c1d255d3SCy Schubert struct dpp_bootstrap_info *peer_bi, *own_bi; 126c1d255d3SCy Schubert 127c1d255d3SCy Schubert pos = os_strstr(cmd, " own="); 128c1d255d3SCy Schubert if (!pos) 129c1d255d3SCy Schubert return -1; 130c1d255d3SCy Schubert pos += 5; 131c1d255d3SCy Schubert own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); 132c1d255d3SCy Schubert if (!own_bi) 133c1d255d3SCy Schubert return -1; 134c1d255d3SCy Schubert own_bi->nfc_negotiated = 1; 135c1d255d3SCy Schubert 136c1d255d3SCy Schubert pos = os_strstr(cmd, " uri="); 137c1d255d3SCy Schubert if (!pos) 138c1d255d3SCy Schubert return -1; 139c1d255d3SCy Schubert pos += 5; 140c1d255d3SCy Schubert peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos); 141c1d255d3SCy Schubert if (!peer_bi) { 142c1d255d3SCy Schubert wpa_printf(MSG_INFO, 143c1d255d3SCy Schubert "DPP: Failed to parse URI from NFC Handover Request"); 144c1d255d3SCy Schubert return -1; 145c1d255d3SCy Schubert } 146c1d255d3SCy Schubert 147c1d255d3SCy Schubert if (dpp_nfc_update_bi(own_bi, peer_bi) < 0) 148c1d255d3SCy Schubert return -1; 149c1d255d3SCy Schubert 150c1d255d3SCy Schubert return peer_bi->id; 151c1d255d3SCy Schubert } 152c1d255d3SCy Schubert 153c1d255d3SCy Schubert 154c1d255d3SCy Schubert int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd) 155c1d255d3SCy Schubert { 156c1d255d3SCy Schubert const char *pos; 157c1d255d3SCy Schubert struct dpp_bootstrap_info *peer_bi, *own_bi; 158c1d255d3SCy Schubert 159c1d255d3SCy Schubert pos = os_strstr(cmd, " own="); 160c1d255d3SCy Schubert if (!pos) 161c1d255d3SCy Schubert return -1; 162c1d255d3SCy Schubert pos += 5; 163c1d255d3SCy Schubert own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); 164c1d255d3SCy Schubert if (!own_bi) 165c1d255d3SCy Schubert return -1; 166c1d255d3SCy Schubert own_bi->nfc_negotiated = 1; 167c1d255d3SCy Schubert 168c1d255d3SCy Schubert pos = os_strstr(cmd, " uri="); 169c1d255d3SCy Schubert if (!pos) 170c1d255d3SCy Schubert return -1; 171c1d255d3SCy Schubert pos += 5; 172c1d255d3SCy Schubert peer_bi = dpp_add_nfc_uri(wpa_s->dpp, pos); 173c1d255d3SCy Schubert if (!peer_bi) { 174c1d255d3SCy Schubert wpa_printf(MSG_INFO, 175c1d255d3SCy Schubert "DPP: Failed to parse URI from NFC Handover Select"); 176c1d255d3SCy Schubert return -1; 177c1d255d3SCy Schubert } 178c1d255d3SCy Schubert 179c1d255d3SCy Schubert if (peer_bi->curve != own_bi->curve) { 180c1d255d3SCy Schubert wpa_printf(MSG_INFO, 181c1d255d3SCy Schubert "DPP: Peer (NFC Handover Selector) used different curve"); 182c1d255d3SCy Schubert return -1; 183c1d255d3SCy Schubert } 184c1d255d3SCy Schubert 185c1d255d3SCy Schubert return peer_bi->id; 186c1d255d3SCy Schubert } 187c1d255d3SCy Schubert 188c1d255d3SCy Schubert 18985732ac8SCy Schubert static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx) 19085732ac8SCy Schubert { 19185732ac8SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 19285732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 19385732ac8SCy Schubert 19485732ac8SCy Schubert if (!auth || !auth->resp_msg) 19585732ac8SCy Schubert return; 19685732ac8SCy Schubert 19785732ac8SCy Schubert wpa_printf(MSG_DEBUG, 19885732ac8SCy Schubert "DPP: Retry Authentication Response after timeout"); 19985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 20085732ac8SCy Schubert " freq=%u type=%d", 20185732ac8SCy Schubert MAC2STR(auth->peer_mac_addr), auth->curr_freq, 20285732ac8SCy Schubert DPP_PA_AUTHENTICATION_RESP); 20385732ac8SCy Schubert offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr, 20485732ac8SCy Schubert wpa_s->own_addr, broadcast, 20585732ac8SCy Schubert wpabuf_head(auth->resp_msg), 20685732ac8SCy Schubert wpabuf_len(auth->resp_msg), 20785732ac8SCy Schubert 500, wpas_dpp_tx_status, 0); 20885732ac8SCy Schubert } 20985732ac8SCy Schubert 21085732ac8SCy Schubert 21185732ac8SCy Schubert static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s) 21285732ac8SCy Schubert { 21385732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 21485732ac8SCy Schubert unsigned int wait_time, max_tries; 21585732ac8SCy Schubert 21685732ac8SCy Schubert if (!auth || !auth->resp_msg) 21785732ac8SCy Schubert return; 21885732ac8SCy Schubert 21985732ac8SCy Schubert if (wpa_s->dpp_resp_max_tries) 22085732ac8SCy Schubert max_tries = wpa_s->dpp_resp_max_tries; 22185732ac8SCy Schubert else 22285732ac8SCy Schubert max_tries = 5; 22385732ac8SCy Schubert auth->auth_resp_tries++; 22485732ac8SCy Schubert if (auth->auth_resp_tries >= max_tries) { 22585732ac8SCy Schubert wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange"); 22685732ac8SCy Schubert offchannel_send_action_done(wpa_s); 22785732ac8SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 22885732ac8SCy Schubert wpa_s->dpp_auth = NULL; 22985732ac8SCy Schubert return; 23085732ac8SCy Schubert } 23185732ac8SCy Schubert 23285732ac8SCy Schubert if (wpa_s->dpp_resp_retry_time) 23385732ac8SCy Schubert wait_time = wpa_s->dpp_resp_retry_time; 23485732ac8SCy Schubert else 23585732ac8SCy Schubert wait_time = 1000; 23685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 23785732ac8SCy Schubert "DPP: Schedule retransmission of Authentication Response frame in %u ms", 23885732ac8SCy Schubert wait_time); 23985732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); 24085732ac8SCy Schubert eloop_register_timeout(wait_time / 1000, 24185732ac8SCy Schubert (wait_time % 1000) * 1000, 24285732ac8SCy Schubert wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); 24385732ac8SCy Schubert } 24485732ac8SCy Schubert 24585732ac8SCy Schubert 2464bc52338SCy Schubert static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s) 2474bc52338SCy Schubert { 2484bc52338SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network"); 249c1d255d3SCy Schubert wpa_s->suitable_network = 0; 250c1d255d3SCy Schubert wpa_s->no_suitable_network = 0; 2514bc52338SCy Schubert wpa_s->disconnected = 0; 2524bc52338SCy Schubert wpa_s->reassociate = 1; 2534bc52338SCy Schubert wpa_s->scan_runs = 0; 2544bc52338SCy Schubert wpa_s->normal_scans = 0; 2554bc52338SCy Schubert wpa_supplicant_cancel_sched_scan(wpa_s); 2564bc52338SCy Schubert wpa_supplicant_req_scan(wpa_s, 0, 0); 2574bc52338SCy Schubert } 2584bc52338SCy Schubert 2594bc52338SCy Schubert 260c1d255d3SCy Schubert #ifdef CONFIG_DPP2 261c1d255d3SCy Schubert 262c1d255d3SCy Schubert static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s, 263c1d255d3SCy Schubert unsigned int freq, 264c1d255d3SCy Schubert unsigned int wait_time) 265c1d255d3SCy Schubert { 266c1d255d3SCy Schubert struct os_reltime now, res; 267c1d255d3SCy Schubert unsigned int remaining; 268c1d255d3SCy Schubert 269c1d255d3SCy Schubert if (!wpa_s->dpp_listen_freq) 270c1d255d3SCy Schubert return; 271c1d255d3SCy Schubert 272c1d255d3SCy Schubert os_get_reltime(&now); 273c1d255d3SCy Schubert if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) { 274c1d255d3SCy Schubert os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res); 275c1d255d3SCy Schubert remaining = res.sec * 1000 + res.usec / 1000; 276c1d255d3SCy Schubert } else { 277c1d255d3SCy Schubert remaining = 0; 278c1d255d3SCy Schubert } 279c1d255d3SCy Schubert if (wpa_s->dpp_listen_freq == freq && remaining > wait_time) 280c1d255d3SCy Schubert return; 281c1d255d3SCy Schubert 282c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 283c1d255d3SCy Schubert "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms", 284c1d255d3SCy Schubert wpa_s->dpp_listen_freq, remaining, freq, wait_time); 285c1d255d3SCy Schubert wpas_dpp_listen_stop(wpa_s); 286c1d255d3SCy Schubert 287c1d255d3SCy Schubert /* TODO: Restart listen in some cases after TX? */ 288c1d255d3SCy Schubert } 289c1d255d3SCy Schubert 290c1d255d3SCy Schubert 291c1d255d3SCy Schubert static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx, 292c1d255d3SCy Schubert void *timeout_ctx) 293c1d255d3SCy Schubert { 294c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 295c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 296c1d255d3SCy Schubert enum dpp_status_error result; 297c1d255d3SCy Schubert 298c1d255d3SCy Schubert if (!auth || !auth->conn_status_requested) 299c1d255d3SCy Schubert return; 300c1d255d3SCy Schubert 301c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 302c1d255d3SCy Schubert "DPP: Connection timeout - report Connection Status Result"); 303c1d255d3SCy Schubert if (wpa_s->suitable_network) 304c1d255d3SCy Schubert result = DPP_STATUS_AUTH_FAILURE; 305c1d255d3SCy Schubert else if (wpa_s->no_suitable_network) 306c1d255d3SCy Schubert result = DPP_STATUS_NO_AP; 307c1d255d3SCy Schubert else 308c1d255d3SCy Schubert result = 255; /* What to report here for unexpected state? */ 309c1d255d3SCy Schubert if (wpa_s->wpa_state == WPA_SCANNING) 310c1d255d3SCy Schubert wpas_abort_ongoing_scan(wpa_s); 311c1d255d3SCy Schubert wpas_dpp_send_conn_status_result(wpa_s, result); 312c1d255d3SCy Schubert } 313c1d255d3SCy Schubert 314c1d255d3SCy Schubert 315c1d255d3SCy Schubert static char * wpas_dpp_scan_channel_list(struct wpa_supplicant *wpa_s) 316c1d255d3SCy Schubert { 317c1d255d3SCy Schubert char *str, *end, *pos; 318c1d255d3SCy Schubert size_t len; 319c1d255d3SCy Schubert unsigned int i; 320c1d255d3SCy Schubert u8 last_op_class = 0; 321c1d255d3SCy Schubert int res; 322c1d255d3SCy Schubert 323c1d255d3SCy Schubert if (!wpa_s->last_scan_freqs || !wpa_s->num_last_scan_freqs) 324c1d255d3SCy Schubert return NULL; 325c1d255d3SCy Schubert 326c1d255d3SCy Schubert len = wpa_s->num_last_scan_freqs * 8; 327c1d255d3SCy Schubert str = os_zalloc(len); 328c1d255d3SCy Schubert if (!str) 329c1d255d3SCy Schubert return NULL; 330c1d255d3SCy Schubert end = str + len; 331c1d255d3SCy Schubert pos = str; 332c1d255d3SCy Schubert 333c1d255d3SCy Schubert for (i = 0; i < wpa_s->num_last_scan_freqs; i++) { 334c1d255d3SCy Schubert enum hostapd_hw_mode mode; 335c1d255d3SCy Schubert u8 op_class, channel; 336c1d255d3SCy Schubert 337c1d255d3SCy Schubert mode = ieee80211_freq_to_channel_ext(wpa_s->last_scan_freqs[i], 338c1d255d3SCy Schubert 0, 0, &op_class, &channel); 339c1d255d3SCy Schubert if (mode == NUM_HOSTAPD_MODES) 340c1d255d3SCy Schubert continue; 341c1d255d3SCy Schubert if (op_class == last_op_class) 342c1d255d3SCy Schubert res = os_snprintf(pos, end - pos, ",%d", channel); 343c1d255d3SCy Schubert else 344c1d255d3SCy Schubert res = os_snprintf(pos, end - pos, "%s%d/%d", 345c1d255d3SCy Schubert pos == str ? "" : ",", 346c1d255d3SCy Schubert op_class, channel); 347c1d255d3SCy Schubert if (os_snprintf_error(end - pos, res)) { 348c1d255d3SCy Schubert *pos = '\0'; 349c1d255d3SCy Schubert break; 350c1d255d3SCy Schubert } 351c1d255d3SCy Schubert pos += res; 352c1d255d3SCy Schubert last_op_class = op_class; 353c1d255d3SCy Schubert } 354c1d255d3SCy Schubert 355c1d255d3SCy Schubert if (pos == str) { 356c1d255d3SCy Schubert os_free(str); 357c1d255d3SCy Schubert str = NULL; 358c1d255d3SCy Schubert } 359c1d255d3SCy Schubert return str; 360c1d255d3SCy Schubert } 361c1d255d3SCy Schubert 362c1d255d3SCy Schubert 363c1d255d3SCy Schubert void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s, 364c1d255d3SCy Schubert enum dpp_status_error result) 365c1d255d3SCy Schubert { 366c1d255d3SCy Schubert struct wpabuf *msg; 367c1d255d3SCy Schubert const char *channel_list = NULL; 368c1d255d3SCy Schubert char *channel_list_buf = NULL; 369c1d255d3SCy Schubert struct wpa_ssid *ssid = wpa_s->current_ssid; 370c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 371c1d255d3SCy Schubert 372c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL); 373c1d255d3SCy Schubert 374c1d255d3SCy Schubert if (!auth || !auth->conn_status_requested) 375c1d255d3SCy Schubert return; 376c1d255d3SCy Schubert auth->conn_status_requested = 0; 377c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d", 378c1d255d3SCy Schubert result); 379c1d255d3SCy Schubert 380c1d255d3SCy Schubert if (result == DPP_STATUS_NO_AP) { 381c1d255d3SCy Schubert channel_list_buf = wpas_dpp_scan_channel_list(wpa_s); 382c1d255d3SCy Schubert channel_list = channel_list_buf; 383c1d255d3SCy Schubert } 384c1d255d3SCy Schubert 385c1d255d3SCy Schubert msg = dpp_build_conn_status_result(auth, result, 386c1d255d3SCy Schubert ssid ? ssid->ssid : 387c1d255d3SCy Schubert wpa_s->dpp_last_ssid, 388c1d255d3SCy Schubert ssid ? ssid->ssid_len : 389c1d255d3SCy Schubert wpa_s->dpp_last_ssid_len, 390c1d255d3SCy Schubert channel_list); 391c1d255d3SCy Schubert os_free(channel_list_buf); 392c1d255d3SCy Schubert if (!msg) { 393c1d255d3SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 394c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 395c1d255d3SCy Schubert return; 396c1d255d3SCy Schubert } 397c1d255d3SCy Schubert 398c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, 399c1d255d3SCy Schubert DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 400c1d255d3SCy Schubert MAC2STR(auth->peer_mac_addr), auth->curr_freq, 401c1d255d3SCy Schubert DPP_PA_CONNECTION_STATUS_RESULT); 402c1d255d3SCy Schubert offchannel_send_action(wpa_s, auth->curr_freq, 403c1d255d3SCy Schubert auth->peer_mac_addr, wpa_s->own_addr, broadcast, 404c1d255d3SCy Schubert wpabuf_head(msg), wpabuf_len(msg), 405c1d255d3SCy Schubert 500, wpas_dpp_tx_status, 0); 406c1d255d3SCy Schubert wpabuf_free(msg); 407c1d255d3SCy Schubert 408c1d255d3SCy Schubert /* This exchange will be terminated in the TX status handler */ 409c1d255d3SCy Schubert auth->remove_on_tx_status = 1; 410c1d255d3SCy Schubert 411c1d255d3SCy Schubert return; 412c1d255d3SCy Schubert } 413c1d255d3SCy Schubert 414c1d255d3SCy Schubert 415c1d255d3SCy Schubert void wpas_dpp_connected(struct wpa_supplicant *wpa_s) 416c1d255d3SCy Schubert { 417c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 418c1d255d3SCy Schubert 419c1d255d3SCy Schubert if (auth && auth->conn_status_requested) 420c1d255d3SCy Schubert wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK); 421c1d255d3SCy Schubert } 422c1d255d3SCy Schubert 423c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 424c1d255d3SCy Schubert 425c1d255d3SCy Schubert 42685732ac8SCy Schubert static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s, 42785732ac8SCy Schubert unsigned int freq, const u8 *dst, 42885732ac8SCy Schubert const u8 *src, const u8 *bssid, 42985732ac8SCy Schubert const u8 *data, size_t data_len, 43085732ac8SCy Schubert enum offchannel_send_action_result result) 43185732ac8SCy Schubert { 43285732ac8SCy Schubert const char *res_txt; 43385732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 43485732ac8SCy Schubert 43585732ac8SCy Schubert res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" : 43685732ac8SCy Schubert (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" : 43785732ac8SCy Schubert "FAILED"); 43885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR 43985732ac8SCy Schubert " result=%s", freq, MAC2STR(dst), res_txt); 44085732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR 44185732ac8SCy Schubert " freq=%u result=%s", MAC2STR(dst), freq, res_txt); 44285732ac8SCy Schubert 44385732ac8SCy Schubert if (!wpa_s->dpp_auth) { 44485732ac8SCy Schubert wpa_printf(MSG_DEBUG, 44585732ac8SCy Schubert "DPP: Ignore TX status since there is no ongoing authentication exchange"); 44685732ac8SCy Schubert return; 44785732ac8SCy Schubert } 44885732ac8SCy Schubert 4494bc52338SCy Schubert #ifdef CONFIG_DPP2 4504bc52338SCy Schubert if (auth->connect_on_tx_status) { 451c1d255d3SCy Schubert auth->connect_on_tx_status = 0; 4524bc52338SCy Schubert wpa_printf(MSG_DEBUG, 4534bc52338SCy Schubert "DPP: Try to connect after completed configuration result"); 4544bc52338SCy Schubert wpas_dpp_try_to_connect(wpa_s); 455c1d255d3SCy Schubert if (auth->conn_status_requested) { 456c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 457c1d255d3SCy Schubert "DPP: Start 15 second timeout for reporting connection status result"); 458c1d255d3SCy Schubert eloop_cancel_timeout( 459c1d255d3SCy Schubert wpas_dpp_conn_status_result_timeout, 460c1d255d3SCy Schubert wpa_s, NULL); 461c1d255d3SCy Schubert eloop_register_timeout( 462c1d255d3SCy Schubert 15, 0, wpas_dpp_conn_status_result_timeout, 463c1d255d3SCy Schubert wpa_s, NULL); 464c1d255d3SCy Schubert } else { 4654bc52338SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 4664bc52338SCy Schubert wpa_s->dpp_auth = NULL; 467c1d255d3SCy Schubert } 4684bc52338SCy Schubert return; 4694bc52338SCy Schubert } 4704bc52338SCy Schubert #endif /* CONFIG_DPP2 */ 4714bc52338SCy Schubert 47285732ac8SCy Schubert if (wpa_s->dpp_auth->remove_on_tx_status) { 47385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 474c1d255d3SCy Schubert "DPP: Terminate authentication exchange due to a request to do so on TX status"); 47585732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); 47685732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); 477c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, 478c1d255d3SCy Schubert NULL); 47985732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, 48085732ac8SCy Schubert NULL); 481c1d255d3SCy Schubert #ifdef CONFIG_DPP2 482c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, 483c1d255d3SCy Schubert wpa_s, NULL); 484c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 48585732ac8SCy Schubert offchannel_send_action_done(wpa_s); 48685732ac8SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 48785732ac8SCy Schubert wpa_s->dpp_auth = NULL; 48885732ac8SCy Schubert return; 48985732ac8SCy Schubert } 49085732ac8SCy Schubert 49185732ac8SCy Schubert if (wpa_s->dpp_auth_ok_on_ack) 49285732ac8SCy Schubert wpas_dpp_auth_success(wpa_s, 1); 49385732ac8SCy Schubert 49485732ac8SCy Schubert if (!is_broadcast_ether_addr(dst) && 49585732ac8SCy Schubert result != OFFCHANNEL_SEND_ACTION_SUCCESS) { 49685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 49785732ac8SCy Schubert "DPP: Unicast DPP Action frame was not ACKed"); 49885732ac8SCy Schubert if (auth->waiting_auth_resp) { 49985732ac8SCy Schubert /* In case of DPP Authentication Request frame, move to 50085732ac8SCy Schubert * the next channel immediately. */ 50185732ac8SCy Schubert offchannel_send_action_done(wpa_s); 50285732ac8SCy Schubert wpas_dpp_auth_init_next(wpa_s); 50385732ac8SCy Schubert return; 50485732ac8SCy Schubert } 50585732ac8SCy Schubert if (auth->waiting_auth_conf) { 50685732ac8SCy Schubert wpas_dpp_auth_resp_retry(wpa_s); 50785732ac8SCy Schubert return; 50885732ac8SCy Schubert } 50985732ac8SCy Schubert } 51085732ac8SCy Schubert 511c1d255d3SCy Schubert if (auth->waiting_auth_conf && 512c1d255d3SCy Schubert auth->auth_resp_status == DPP_STATUS_OK) { 513c1d255d3SCy Schubert /* Make sure we do not get stuck waiting for Auth Confirm 514c1d255d3SCy Schubert * indefinitely after successfully transmitted Auth Response to 515c1d255d3SCy Schubert * allow new authentication exchanges to be started. */ 516c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, 517c1d255d3SCy Schubert NULL); 518c1d255d3SCy Schubert eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout, 519c1d255d3SCy Schubert wpa_s, NULL); 520c1d255d3SCy Schubert } 521c1d255d3SCy Schubert 52285732ac8SCy Schubert if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && 52385732ac8SCy Schubert result == OFFCHANNEL_SEND_ACTION_SUCCESS) { 52485732ac8SCy Schubert /* Allow timeout handling to stop iteration if no response is 52585732ac8SCy Schubert * received from a peer that has ACKed a request. */ 52685732ac8SCy Schubert auth->auth_req_ack = 1; 52785732ac8SCy Schubert } 52885732ac8SCy Schubert 52985732ac8SCy Schubert if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 && 53085732ac8SCy Schubert wpa_s->dpp_auth->curr_freq != wpa_s->dpp_auth->neg_freq) { 53185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 53285732ac8SCy Schubert "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response", 53385732ac8SCy Schubert wpa_s->dpp_auth->curr_freq, 53485732ac8SCy Schubert wpa_s->dpp_auth->neg_freq); 53585732ac8SCy Schubert offchannel_send_action_done(wpa_s); 53685732ac8SCy Schubert wpas_dpp_listen_start(wpa_s, wpa_s->dpp_auth->neg_freq); 53785732ac8SCy Schubert } 53885732ac8SCy Schubert 53985732ac8SCy Schubert if (wpa_s->dpp_auth_ok_on_ack) 54085732ac8SCy Schubert wpa_s->dpp_auth_ok_on_ack = 0; 54185732ac8SCy Schubert } 54285732ac8SCy Schubert 54385732ac8SCy Schubert 54485732ac8SCy Schubert static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx) 54585732ac8SCy Schubert { 54685732ac8SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 54785732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 54885732ac8SCy Schubert unsigned int freq; 54985732ac8SCy Schubert struct os_reltime now, diff; 55085732ac8SCy Schubert unsigned int wait_time, diff_ms; 55185732ac8SCy Schubert 55285732ac8SCy Schubert if (!auth || !auth->waiting_auth_resp) 55385732ac8SCy Schubert return; 55485732ac8SCy Schubert 55585732ac8SCy Schubert wait_time = wpa_s->dpp_resp_wait_time ? 55685732ac8SCy Schubert wpa_s->dpp_resp_wait_time : 2000; 55785732ac8SCy Schubert os_get_reltime(&now); 55885732ac8SCy Schubert os_reltime_sub(&now, &wpa_s->dpp_last_init, &diff); 55985732ac8SCy Schubert diff_ms = diff.sec * 1000 + diff.usec / 1000; 56085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 56185732ac8SCy Schubert "DPP: Reply wait timeout - wait_time=%u diff_ms=%u", 56285732ac8SCy Schubert wait_time, diff_ms); 56385732ac8SCy Schubert 56485732ac8SCy Schubert if (auth->auth_req_ack && diff_ms >= wait_time) { 56585732ac8SCy Schubert /* Peer ACK'ed Authentication Request frame, but did not reply 56685732ac8SCy Schubert * with Authentication Response frame within two seconds. */ 56785732ac8SCy Schubert wpa_printf(MSG_INFO, 56885732ac8SCy Schubert "DPP: No response received from responder - stopping initiation attempt"); 56985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED); 57085732ac8SCy Schubert offchannel_send_action_done(wpa_s); 57185732ac8SCy Schubert wpas_dpp_listen_stop(wpa_s); 57285732ac8SCy Schubert dpp_auth_deinit(auth); 57385732ac8SCy Schubert wpa_s->dpp_auth = NULL; 57485732ac8SCy Schubert return; 57585732ac8SCy Schubert } 57685732ac8SCy Schubert 57785732ac8SCy Schubert if (diff_ms >= wait_time) { 57885732ac8SCy Schubert /* Authentication Request frame was not ACK'ed and no reply 57985732ac8SCy Schubert * was receiving within two seconds. */ 58085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 58185732ac8SCy Schubert "DPP: Continue Initiator channel iteration"); 58285732ac8SCy Schubert offchannel_send_action_done(wpa_s); 58385732ac8SCy Schubert wpas_dpp_listen_stop(wpa_s); 58485732ac8SCy Schubert wpas_dpp_auth_init_next(wpa_s); 58585732ac8SCy Schubert return; 58685732ac8SCy Schubert } 58785732ac8SCy Schubert 58885732ac8SCy Schubert /* Driver did not support 2000 ms long wait_time with TX command, so 58985732ac8SCy Schubert * schedule listen operation to continue waiting for the response. 59085732ac8SCy Schubert * 59185732ac8SCy Schubert * DPP listen operations continue until stopped, so simply schedule a 59285732ac8SCy Schubert * new call to this function at the point when the two second reply 59385732ac8SCy Schubert * wait has expired. */ 59485732ac8SCy Schubert wait_time -= diff_ms; 59585732ac8SCy Schubert 59685732ac8SCy Schubert freq = auth->curr_freq; 59785732ac8SCy Schubert if (auth->neg_freq > 0) 59885732ac8SCy Schubert freq = auth->neg_freq; 59985732ac8SCy Schubert wpa_printf(MSG_DEBUG, 60085732ac8SCy Schubert "DPP: Continue reply wait on channel %u MHz for %u ms", 60185732ac8SCy Schubert freq, wait_time); 60285732ac8SCy Schubert wpa_s->dpp_in_response_listen = 1; 60385732ac8SCy Schubert wpas_dpp_listen_start(wpa_s, freq); 60485732ac8SCy Schubert 60585732ac8SCy Schubert eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, 60685732ac8SCy Schubert wpas_dpp_reply_wait_timeout, wpa_s, NULL); 60785732ac8SCy Schubert } 60885732ac8SCy Schubert 60985732ac8SCy Schubert 610c1d255d3SCy Schubert static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx) 611c1d255d3SCy Schubert { 612c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 613c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 614c1d255d3SCy Schubert 615c1d255d3SCy Schubert if (!auth || !auth->waiting_auth_conf) 616c1d255d3SCy Schubert return; 617c1d255d3SCy Schubert 618c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 619c1d255d3SCy Schubert "DPP: Terminate authentication exchange due to Auth Confirm timeout"); 620c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received"); 621c1d255d3SCy Schubert offchannel_send_action_done(wpa_s); 622c1d255d3SCy Schubert dpp_auth_deinit(auth); 623c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 624c1d255d3SCy Schubert } 625c1d255d3SCy Schubert 626c1d255d3SCy Schubert 62785732ac8SCy Schubert static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s, 62885732ac8SCy Schubert struct dpp_authentication *auth) 62985732ac8SCy Schubert { 63085732ac8SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 63185732ac8SCy Schubert if (wpa_s->dpp_config_obj_override) 63285732ac8SCy Schubert auth->config_obj_override = 63385732ac8SCy Schubert os_strdup(wpa_s->dpp_config_obj_override); 63485732ac8SCy Schubert if (wpa_s->dpp_discovery_override) 63585732ac8SCy Schubert auth->discovery_override = 63685732ac8SCy Schubert os_strdup(wpa_s->dpp_discovery_override); 63785732ac8SCy Schubert if (wpa_s->dpp_groups_override) 63885732ac8SCy Schubert auth->groups_override = 63985732ac8SCy Schubert os_strdup(wpa_s->dpp_groups_override); 64085732ac8SCy Schubert auth->ignore_netaccesskey_mismatch = 64185732ac8SCy Schubert wpa_s->dpp_ignore_netaccesskey_mismatch; 64285732ac8SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 64385732ac8SCy Schubert } 64485732ac8SCy Schubert 64585732ac8SCy Schubert 64685732ac8SCy Schubert static void wpas_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx) 64785732ac8SCy Schubert { 64885732ac8SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 64985732ac8SCy Schubert 65085732ac8SCy Schubert if (!wpa_s->dpp_auth) 65185732ac8SCy Schubert return; 65285732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout"); 65385732ac8SCy Schubert wpas_dpp_auth_init_next(wpa_s); 65485732ac8SCy Schubert } 65585732ac8SCy Schubert 65685732ac8SCy Schubert 65785732ac8SCy Schubert static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s) 65885732ac8SCy Schubert { 65985732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 66085732ac8SCy Schubert const u8 *dst; 66185732ac8SCy Schubert unsigned int wait_time, max_wait_time, freq, max_tries, used; 66285732ac8SCy Schubert struct os_reltime now, diff; 66385732ac8SCy Schubert 66485732ac8SCy Schubert wpa_s->dpp_in_response_listen = 0; 66585732ac8SCy Schubert if (!auth) 66685732ac8SCy Schubert return -1; 66785732ac8SCy Schubert 66885732ac8SCy Schubert if (auth->freq_idx == 0) 66985732ac8SCy Schubert os_get_reltime(&wpa_s->dpp_init_iter_start); 67085732ac8SCy Schubert 67185732ac8SCy Schubert if (auth->freq_idx >= auth->num_freq) { 67285732ac8SCy Schubert auth->num_freq_iters++; 67385732ac8SCy Schubert if (wpa_s->dpp_init_max_tries) 67485732ac8SCy Schubert max_tries = wpa_s->dpp_init_max_tries; 67585732ac8SCy Schubert else 67685732ac8SCy Schubert max_tries = 5; 67785732ac8SCy Schubert if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) { 67885732ac8SCy Schubert wpa_printf(MSG_INFO, 67985732ac8SCy Schubert "DPP: No response received from responder - stopping initiation attempt"); 68085732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED); 68185732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, 68285732ac8SCy Schubert wpa_s, NULL); 68385732ac8SCy Schubert offchannel_send_action_done(wpa_s); 68485732ac8SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 68585732ac8SCy Schubert wpa_s->dpp_auth = NULL; 68685732ac8SCy Schubert return -1; 68785732ac8SCy Schubert } 68885732ac8SCy Schubert auth->freq_idx = 0; 68985732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); 69085732ac8SCy Schubert if (wpa_s->dpp_init_retry_time) 69185732ac8SCy Schubert wait_time = wpa_s->dpp_init_retry_time; 69285732ac8SCy Schubert else 69385732ac8SCy Schubert wait_time = 10000; 69485732ac8SCy Schubert os_get_reltime(&now); 69585732ac8SCy Schubert os_reltime_sub(&now, &wpa_s->dpp_init_iter_start, &diff); 69685732ac8SCy Schubert used = diff.sec * 1000 + diff.usec / 1000; 69785732ac8SCy Schubert if (used > wait_time) 69885732ac8SCy Schubert wait_time = 0; 69985732ac8SCy Schubert else 70085732ac8SCy Schubert wait_time -= used; 70185732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms", 70285732ac8SCy Schubert wait_time); 70385732ac8SCy Schubert eloop_register_timeout(wait_time / 1000, 70485732ac8SCy Schubert (wait_time % 1000) * 1000, 70585732ac8SCy Schubert wpas_dpp_init_timeout, wpa_s, 70685732ac8SCy Schubert NULL); 70785732ac8SCy Schubert return 0; 70885732ac8SCy Schubert } 70985732ac8SCy Schubert freq = auth->freq[auth->freq_idx++]; 71085732ac8SCy Schubert auth->curr_freq = freq; 71185732ac8SCy Schubert 712c1d255d3SCy Schubert if (!is_zero_ether_addr(auth->peer_mac_addr)) 713c1d255d3SCy Schubert dst = auth->peer_mac_addr; 714c1d255d3SCy Schubert else if (is_zero_ether_addr(auth->peer_bi->mac_addr)) 71585732ac8SCy Schubert dst = broadcast; 71685732ac8SCy Schubert else 71785732ac8SCy Schubert dst = auth->peer_bi->mac_addr; 71885732ac8SCy Schubert wpa_s->dpp_auth_ok_on_ack = 0; 71985732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); 72085732ac8SCy Schubert wait_time = wpa_s->max_remain_on_chan; 72185732ac8SCy Schubert max_wait_time = wpa_s->dpp_resp_wait_time ? 72285732ac8SCy Schubert wpa_s->dpp_resp_wait_time : 2000; 72385732ac8SCy Schubert if (wait_time > max_wait_time) 72485732ac8SCy Schubert wait_time = max_wait_time; 72585732ac8SCy Schubert wait_time += 10; /* give the driver some extra time to complete */ 72685732ac8SCy Schubert eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, 72785732ac8SCy Schubert wpas_dpp_reply_wait_timeout, 72885732ac8SCy Schubert wpa_s, NULL); 72985732ac8SCy Schubert wait_time -= 10; 73085732ac8SCy Schubert if (auth->neg_freq > 0 && freq != auth->neg_freq) { 73185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 73285732ac8SCy Schubert "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response", 73385732ac8SCy Schubert freq, auth->neg_freq); 73485732ac8SCy Schubert } 73585732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 73685732ac8SCy Schubert MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ); 73785732ac8SCy Schubert auth->auth_req_ack = 0; 73885732ac8SCy Schubert os_get_reltime(&wpa_s->dpp_last_init); 73985732ac8SCy Schubert return offchannel_send_action(wpa_s, freq, dst, 74085732ac8SCy Schubert wpa_s->own_addr, broadcast, 74185732ac8SCy Schubert wpabuf_head(auth->req_msg), 74285732ac8SCy Schubert wpabuf_len(auth->req_msg), 74385732ac8SCy Schubert wait_time, wpas_dpp_tx_status, 0); 74485732ac8SCy Schubert } 74585732ac8SCy Schubert 74685732ac8SCy Schubert 74785732ac8SCy Schubert int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) 74885732ac8SCy Schubert { 74985732ac8SCy Schubert const char *pos; 75085732ac8SCy Schubert struct dpp_bootstrap_info *peer_bi, *own_bi = NULL; 751206b73d0SCy Schubert struct dpp_authentication *auth; 75285732ac8SCy Schubert u8 allowed_roles = DPP_CAPAB_CONFIGURATOR; 75385732ac8SCy Schubert unsigned int neg_freq = 0; 754206b73d0SCy Schubert int tcp = 0; 755206b73d0SCy Schubert #ifdef CONFIG_DPP2 756206b73d0SCy Schubert int tcp_port = DPP_TCP_PORT; 757206b73d0SCy Schubert struct hostapd_ip_addr ipaddr; 758206b73d0SCy Schubert char *addr; 759206b73d0SCy Schubert #endif /* CONFIG_DPP2 */ 76085732ac8SCy Schubert 76185732ac8SCy Schubert wpa_s->dpp_gas_client = 0; 76285732ac8SCy Schubert 76385732ac8SCy Schubert pos = os_strstr(cmd, " peer="); 76485732ac8SCy Schubert if (!pos) 76585732ac8SCy Schubert return -1; 76685732ac8SCy Schubert pos += 6; 7674bc52338SCy Schubert peer_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); 76885732ac8SCy Schubert if (!peer_bi) { 76985732ac8SCy Schubert wpa_printf(MSG_INFO, 77085732ac8SCy Schubert "DPP: Could not find bootstrapping info for the identified peer"); 77185732ac8SCy Schubert return -1; 77285732ac8SCy Schubert } 77385732ac8SCy Schubert 774206b73d0SCy Schubert #ifdef CONFIG_DPP2 775206b73d0SCy Schubert pos = os_strstr(cmd, " tcp_port="); 776206b73d0SCy Schubert if (pos) { 777206b73d0SCy Schubert pos += 10; 778206b73d0SCy Schubert tcp_port = atoi(pos); 779206b73d0SCy Schubert } 780206b73d0SCy Schubert 781206b73d0SCy Schubert addr = get_param(cmd, " tcp_addr="); 782206b73d0SCy Schubert if (addr) { 783206b73d0SCy Schubert int res; 784206b73d0SCy Schubert 785206b73d0SCy Schubert res = hostapd_parse_ip_addr(addr, &ipaddr); 786206b73d0SCy Schubert os_free(addr); 787206b73d0SCy Schubert if (res) 788206b73d0SCy Schubert return -1; 789206b73d0SCy Schubert tcp = 1; 790206b73d0SCy Schubert } 791206b73d0SCy Schubert #endif /* CONFIG_DPP2 */ 792206b73d0SCy Schubert 79385732ac8SCy Schubert pos = os_strstr(cmd, " own="); 79485732ac8SCy Schubert if (pos) { 79585732ac8SCy Schubert pos += 5; 7964bc52338SCy Schubert own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); 79785732ac8SCy Schubert if (!own_bi) { 79885732ac8SCy Schubert wpa_printf(MSG_INFO, 79985732ac8SCy Schubert "DPP: Could not find bootstrapping info for the identified local entry"); 80085732ac8SCy Schubert return -1; 80185732ac8SCy Schubert } 80285732ac8SCy Schubert 80385732ac8SCy Schubert if (peer_bi->curve != own_bi->curve) { 80485732ac8SCy Schubert wpa_printf(MSG_INFO, 80585732ac8SCy Schubert "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)", 80685732ac8SCy Schubert peer_bi->curve->name, own_bi->curve->name); 80785732ac8SCy Schubert return -1; 80885732ac8SCy Schubert } 80985732ac8SCy Schubert } 81085732ac8SCy Schubert 81185732ac8SCy Schubert pos = os_strstr(cmd, " role="); 81285732ac8SCy Schubert if (pos) { 81385732ac8SCy Schubert pos += 6; 81485732ac8SCy Schubert if (os_strncmp(pos, "configurator", 12) == 0) 81585732ac8SCy Schubert allowed_roles = DPP_CAPAB_CONFIGURATOR; 81685732ac8SCy Schubert else if (os_strncmp(pos, "enrollee", 8) == 0) 81785732ac8SCy Schubert allowed_roles = DPP_CAPAB_ENROLLEE; 81885732ac8SCy Schubert else if (os_strncmp(pos, "either", 6) == 0) 81985732ac8SCy Schubert allowed_roles = DPP_CAPAB_CONFIGURATOR | 82085732ac8SCy Schubert DPP_CAPAB_ENROLLEE; 82185732ac8SCy Schubert else 82285732ac8SCy Schubert goto fail; 82385732ac8SCy Schubert } 82485732ac8SCy Schubert 82585732ac8SCy Schubert pos = os_strstr(cmd, " netrole="); 82685732ac8SCy Schubert if (pos) { 82785732ac8SCy Schubert pos += 9; 828c1d255d3SCy Schubert if (os_strncmp(pos, "ap", 2) == 0) 829c1d255d3SCy Schubert wpa_s->dpp_netrole = DPP_NETROLE_AP; 830c1d255d3SCy Schubert else if (os_strncmp(pos, "configurator", 12) == 0) 831c1d255d3SCy Schubert wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR; 832c1d255d3SCy Schubert else 833c1d255d3SCy Schubert wpa_s->dpp_netrole = DPP_NETROLE_STA; 834c1d255d3SCy Schubert } else { 835c1d255d3SCy Schubert wpa_s->dpp_netrole = DPP_NETROLE_STA; 83685732ac8SCy Schubert } 83785732ac8SCy Schubert 83885732ac8SCy Schubert pos = os_strstr(cmd, " neg_freq="); 83985732ac8SCy Schubert if (pos) 84085732ac8SCy Schubert neg_freq = atoi(pos + 10); 84185732ac8SCy Schubert 842206b73d0SCy Schubert if (!tcp && wpa_s->dpp_auth) { 84385732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); 84485732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); 845c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, 846c1d255d3SCy Schubert NULL); 84785732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, 84885732ac8SCy Schubert NULL); 849c1d255d3SCy Schubert #ifdef CONFIG_DPP2 850c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, 851c1d255d3SCy Schubert wpa_s, NULL); 852c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 85385732ac8SCy Schubert offchannel_send_action_done(wpa_s); 85485732ac8SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 85585732ac8SCy Schubert wpa_s->dpp_auth = NULL; 856206b73d0SCy Schubert } 857206b73d0SCy Schubert 858c1d255d3SCy Schubert auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles, 859c1d255d3SCy Schubert neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes); 860206b73d0SCy Schubert if (!auth) 861206b73d0SCy Schubert goto fail; 862206b73d0SCy Schubert wpas_dpp_set_testing_options(wpa_s, auth); 863c1d255d3SCy Schubert if (dpp_set_configurator(auth, cmd) < 0) { 864206b73d0SCy Schubert dpp_auth_deinit(auth); 86585732ac8SCy Schubert goto fail; 86685732ac8SCy Schubert } 86785732ac8SCy Schubert 868206b73d0SCy Schubert auth->neg_freq = neg_freq; 86985732ac8SCy Schubert 87085732ac8SCy Schubert if (!is_zero_ether_addr(peer_bi->mac_addr)) 871206b73d0SCy Schubert os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN); 87285732ac8SCy Schubert 873206b73d0SCy Schubert #ifdef CONFIG_DPP2 874206b73d0SCy Schubert if (tcp) 875c1d255d3SCy Schubert return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port, 876c1d255d3SCy Schubert wpa_s->conf->dpp_name, DPP_NETROLE_STA, 877c1d255d3SCy Schubert wpa_s, wpa_s, wpas_dpp_process_conf_obj); 878206b73d0SCy Schubert #endif /* CONFIG_DPP2 */ 879206b73d0SCy Schubert 880206b73d0SCy Schubert wpa_s->dpp_auth = auth; 88185732ac8SCy Schubert return wpas_dpp_auth_init_next(wpa_s); 88285732ac8SCy Schubert fail: 88385732ac8SCy Schubert return -1; 88485732ac8SCy Schubert } 88585732ac8SCy Schubert 88685732ac8SCy Schubert 88785732ac8SCy Schubert struct wpas_dpp_listen_work { 88885732ac8SCy Schubert unsigned int freq; 88985732ac8SCy Schubert unsigned int duration; 89085732ac8SCy Schubert struct wpabuf *probe_resp_ie; 89185732ac8SCy Schubert }; 89285732ac8SCy Schubert 89385732ac8SCy Schubert 89485732ac8SCy Schubert static void wpas_dpp_listen_work_free(struct wpas_dpp_listen_work *lwork) 89585732ac8SCy Schubert { 89685732ac8SCy Schubert if (!lwork) 89785732ac8SCy Schubert return; 89885732ac8SCy Schubert os_free(lwork); 89985732ac8SCy Schubert } 90085732ac8SCy Schubert 90185732ac8SCy Schubert 90285732ac8SCy Schubert static void wpas_dpp_listen_work_done(struct wpa_supplicant *wpa_s) 90385732ac8SCy Schubert { 90485732ac8SCy Schubert struct wpas_dpp_listen_work *lwork; 90585732ac8SCy Schubert 90685732ac8SCy Schubert if (!wpa_s->dpp_listen_work) 90785732ac8SCy Schubert return; 90885732ac8SCy Schubert 90985732ac8SCy Schubert lwork = wpa_s->dpp_listen_work->ctx; 91085732ac8SCy Schubert wpas_dpp_listen_work_free(lwork); 91185732ac8SCy Schubert radio_work_done(wpa_s->dpp_listen_work); 91285732ac8SCy Schubert wpa_s->dpp_listen_work = NULL; 91385732ac8SCy Schubert } 91485732ac8SCy Schubert 91585732ac8SCy Schubert 91685732ac8SCy Schubert static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit) 91785732ac8SCy Schubert { 91885732ac8SCy Schubert struct wpa_supplicant *wpa_s = work->wpa_s; 91985732ac8SCy Schubert struct wpas_dpp_listen_work *lwork = work->ctx; 92085732ac8SCy Schubert 92185732ac8SCy Schubert if (deinit) { 92285732ac8SCy Schubert if (work->started) { 92385732ac8SCy Schubert wpa_s->dpp_listen_work = NULL; 92485732ac8SCy Schubert wpas_dpp_listen_stop(wpa_s); 92585732ac8SCy Schubert } 92685732ac8SCy Schubert wpas_dpp_listen_work_free(lwork); 92785732ac8SCy Schubert return; 92885732ac8SCy Schubert } 92985732ac8SCy Schubert 93085732ac8SCy Schubert wpa_s->dpp_listen_work = work; 93185732ac8SCy Schubert 93285732ac8SCy Schubert wpa_s->dpp_pending_listen_freq = lwork->freq; 93385732ac8SCy Schubert 93485732ac8SCy Schubert if (wpa_drv_remain_on_channel(wpa_s, lwork->freq, 93585732ac8SCy Schubert wpa_s->max_remain_on_chan) < 0) { 93685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 93785732ac8SCy Schubert "DPP: Failed to request the driver to remain on channel (%u MHz) for listen", 93885732ac8SCy Schubert lwork->freq); 9394bc52338SCy Schubert wpa_s->dpp_listen_freq = 0; 94085732ac8SCy Schubert wpas_dpp_listen_work_done(wpa_s); 94185732ac8SCy Schubert wpa_s->dpp_pending_listen_freq = 0; 94285732ac8SCy Schubert return; 94385732ac8SCy Schubert } 94485732ac8SCy Schubert wpa_s->off_channel_freq = 0; 94585732ac8SCy Schubert wpa_s->roc_waiting_drv_freq = lwork->freq; 946c1d255d3SCy Schubert wpa_drv_dpp_listen(wpa_s, true); 94785732ac8SCy Schubert } 94885732ac8SCy Schubert 94985732ac8SCy Schubert 95085732ac8SCy Schubert static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s, 95185732ac8SCy Schubert unsigned int freq) 95285732ac8SCy Schubert { 95385732ac8SCy Schubert struct wpas_dpp_listen_work *lwork; 95485732ac8SCy Schubert 95585732ac8SCy Schubert if (wpa_s->dpp_listen_work) { 95685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 95785732ac8SCy Schubert "DPP: Reject start_listen since dpp_listen_work already exists"); 95885732ac8SCy Schubert return -1; 95985732ac8SCy Schubert } 96085732ac8SCy Schubert 96185732ac8SCy Schubert if (wpa_s->dpp_listen_freq) 96285732ac8SCy Schubert wpas_dpp_listen_stop(wpa_s); 96385732ac8SCy Schubert wpa_s->dpp_listen_freq = freq; 96485732ac8SCy Schubert 96585732ac8SCy Schubert lwork = os_zalloc(sizeof(*lwork)); 96685732ac8SCy Schubert if (!lwork) 96785732ac8SCy Schubert return -1; 96885732ac8SCy Schubert lwork->freq = freq; 96985732ac8SCy Schubert 97085732ac8SCy Schubert if (radio_add_work(wpa_s, freq, "dpp-listen", 0, dpp_start_listen_cb, 97185732ac8SCy Schubert lwork) < 0) { 97285732ac8SCy Schubert wpas_dpp_listen_work_free(lwork); 97385732ac8SCy Schubert return -1; 97485732ac8SCy Schubert } 97585732ac8SCy Schubert 97685732ac8SCy Schubert return 0; 97785732ac8SCy Schubert } 97885732ac8SCy Schubert 97985732ac8SCy Schubert 98085732ac8SCy Schubert int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd) 98185732ac8SCy Schubert { 98285732ac8SCy Schubert int freq; 98385732ac8SCy Schubert 98485732ac8SCy Schubert freq = atoi(cmd); 98585732ac8SCy Schubert if (freq <= 0) 98685732ac8SCy Schubert return -1; 98785732ac8SCy Schubert 98885732ac8SCy Schubert if (os_strstr(cmd, " role=configurator")) 98985732ac8SCy Schubert wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR; 99085732ac8SCy Schubert else if (os_strstr(cmd, " role=enrollee")) 99185732ac8SCy Schubert wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; 99285732ac8SCy Schubert else 99385732ac8SCy Schubert wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | 99485732ac8SCy Schubert DPP_CAPAB_ENROLLEE; 99585732ac8SCy Schubert wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL; 996c1d255d3SCy Schubert if (os_strstr(cmd, " netrole=ap")) 997c1d255d3SCy Schubert wpa_s->dpp_netrole = DPP_NETROLE_AP; 998c1d255d3SCy Schubert else if (os_strstr(cmd, " netrole=configurator")) 999c1d255d3SCy Schubert wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR; 1000c1d255d3SCy Schubert else 1001c1d255d3SCy Schubert wpa_s->dpp_netrole = DPP_NETROLE_STA; 100285732ac8SCy Schubert if (wpa_s->dpp_listen_freq == (unsigned int) freq) { 100385732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz", 100485732ac8SCy Schubert freq); 100585732ac8SCy Schubert return 0; 100685732ac8SCy Schubert } 100785732ac8SCy Schubert 100885732ac8SCy Schubert return wpas_dpp_listen_start(wpa_s, freq); 100985732ac8SCy Schubert } 101085732ac8SCy Schubert 101185732ac8SCy Schubert 101285732ac8SCy Schubert void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s) 101385732ac8SCy Schubert { 101485732ac8SCy Schubert wpa_s->dpp_in_response_listen = 0; 101585732ac8SCy Schubert if (!wpa_s->dpp_listen_freq) 101685732ac8SCy Schubert return; 101785732ac8SCy Schubert 101885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz", 101985732ac8SCy Schubert wpa_s->dpp_listen_freq); 102085732ac8SCy Schubert wpa_drv_cancel_remain_on_channel(wpa_s); 1021c1d255d3SCy Schubert wpa_drv_dpp_listen(wpa_s, false); 102285732ac8SCy Schubert wpa_s->dpp_listen_freq = 0; 102385732ac8SCy Schubert wpas_dpp_listen_work_done(wpa_s); 1024*32a95656SCy Schubert radio_remove_works(wpa_s, "dpp-listen", 0); 102585732ac8SCy Schubert } 102685732ac8SCy Schubert 102785732ac8SCy Schubert 1028c1d255d3SCy Schubert void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s, 1029c1d255d3SCy Schubert unsigned int freq, unsigned int duration) 1030c1d255d3SCy Schubert { 1031c1d255d3SCy Schubert if (wpa_s->dpp_listen_freq != freq) 1032c1d255d3SCy Schubert return; 1033c1d255d3SCy Schubert 1034c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1035c1d255d3SCy Schubert "DPP: Remain-on-channel started for listen on %u MHz for %u ms", 1036c1d255d3SCy Schubert freq, duration); 1037c1d255d3SCy Schubert os_get_reltime(&wpa_s->dpp_listen_end); 1038c1d255d3SCy Schubert wpa_s->dpp_listen_end.usec += duration * 1000; 1039c1d255d3SCy Schubert while (wpa_s->dpp_listen_end.usec >= 1000000) { 1040c1d255d3SCy Schubert wpa_s->dpp_listen_end.sec++; 1041c1d255d3SCy Schubert wpa_s->dpp_listen_end.usec -= 1000000; 1042c1d255d3SCy Schubert } 1043c1d255d3SCy Schubert } 1044c1d255d3SCy Schubert 1045c1d255d3SCy Schubert 104685732ac8SCy Schubert void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, 104785732ac8SCy Schubert unsigned int freq) 104885732ac8SCy Schubert { 104985732ac8SCy Schubert wpas_dpp_listen_work_done(wpa_s); 105085732ac8SCy Schubert 105185732ac8SCy Schubert if (wpa_s->dpp_auth && wpa_s->dpp_in_response_listen) { 105285732ac8SCy Schubert unsigned int new_freq; 105385732ac8SCy Schubert 105485732ac8SCy Schubert /* Continue listen with a new remain-on-channel */ 105585732ac8SCy Schubert if (wpa_s->dpp_auth->neg_freq > 0) 105685732ac8SCy Schubert new_freq = wpa_s->dpp_auth->neg_freq; 105785732ac8SCy Schubert else 105885732ac8SCy Schubert new_freq = wpa_s->dpp_auth->curr_freq; 105985732ac8SCy Schubert wpa_printf(MSG_DEBUG, 106085732ac8SCy Schubert "DPP: Continue wait on %u MHz for the ongoing DPP provisioning session", 106185732ac8SCy Schubert new_freq); 106285732ac8SCy Schubert wpas_dpp_listen_start(wpa_s, new_freq); 106385732ac8SCy Schubert return; 106485732ac8SCy Schubert } 106585732ac8SCy Schubert 106685732ac8SCy Schubert if (wpa_s->dpp_listen_freq) { 106785732ac8SCy Schubert /* Continue listen with a new remain-on-channel */ 106885732ac8SCy Schubert wpas_dpp_listen_start(wpa_s, wpa_s->dpp_listen_freq); 106985732ac8SCy Schubert } 107085732ac8SCy Schubert } 107185732ac8SCy Schubert 107285732ac8SCy Schubert 107385732ac8SCy Schubert static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, 107485732ac8SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 107585732ac8SCy Schubert unsigned int freq) 107685732ac8SCy Schubert { 107785732ac8SCy Schubert const u8 *r_bootstrap, *i_bootstrap; 107885732ac8SCy Schubert u16 r_bootstrap_len, i_bootstrap_len; 10794bc52338SCy Schubert struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL; 10804bc52338SCy Schubert 10814bc52338SCy Schubert if (!wpa_s->dpp) 10824bc52338SCy Schubert return; 108385732ac8SCy Schubert 108485732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR, 108585732ac8SCy Schubert MAC2STR(src)); 108685732ac8SCy Schubert 1087c1d255d3SCy Schubert #ifdef CONFIG_DPP2 1088c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 1089c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 1090c1d255d3SCy Schubert 109185732ac8SCy Schubert r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, 109285732ac8SCy Schubert &r_bootstrap_len); 109385732ac8SCy Schubert if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { 109485732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL 109585732ac8SCy Schubert "Missing or invalid required Responder Bootstrapping Key Hash attribute"); 109685732ac8SCy Schubert return; 109785732ac8SCy Schubert } 109885732ac8SCy Schubert wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", 109985732ac8SCy Schubert r_bootstrap, r_bootstrap_len); 110085732ac8SCy Schubert 110185732ac8SCy Schubert i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH, 110285732ac8SCy Schubert &i_bootstrap_len); 110385732ac8SCy Schubert if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) { 110485732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL 110585732ac8SCy Schubert "Missing or invalid required Initiator Bootstrapping Key Hash attribute"); 110685732ac8SCy Schubert return; 110785732ac8SCy Schubert } 110885732ac8SCy Schubert wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", 110985732ac8SCy Schubert i_bootstrap, i_bootstrap_len); 111085732ac8SCy Schubert 111185732ac8SCy Schubert /* Try to find own and peer bootstrapping key matches based on the 111285732ac8SCy Schubert * received hash values */ 11134bc52338SCy Schubert dpp_bootstrap_find_pair(wpa_s->dpp, i_bootstrap, r_bootstrap, 11144bc52338SCy Schubert &own_bi, &peer_bi); 111585732ac8SCy Schubert if (!own_bi) { 111685732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL 111785732ac8SCy Schubert "No matching own bootstrapping key found - ignore message"); 111885732ac8SCy Schubert return; 111985732ac8SCy Schubert } 112085732ac8SCy Schubert 112185732ac8SCy Schubert if (wpa_s->dpp_auth) { 112285732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL 112385732ac8SCy Schubert "Already in DPP authentication exchange - ignore new one"); 112485732ac8SCy Schubert return; 112585732ac8SCy Schubert } 112685732ac8SCy Schubert 112785732ac8SCy Schubert wpa_s->dpp_gas_client = 0; 112885732ac8SCy Schubert wpa_s->dpp_auth_ok_on_ack = 0; 1129c1d255d3SCy Schubert wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s, 1130c1d255d3SCy Schubert wpa_s->dpp_allowed_roles, 113185732ac8SCy Schubert wpa_s->dpp_qr_mutual, 113285732ac8SCy Schubert peer_bi, own_bi, freq, hdr, buf, len); 113385732ac8SCy Schubert if (!wpa_s->dpp_auth) { 113485732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No response generated"); 113585732ac8SCy Schubert return; 113685732ac8SCy Schubert } 113785732ac8SCy Schubert wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth); 1138c1d255d3SCy Schubert if (dpp_set_configurator(wpa_s->dpp_auth, 113985732ac8SCy Schubert wpa_s->dpp_configurator_params) < 0) { 114085732ac8SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 114185732ac8SCy Schubert wpa_s->dpp_auth = NULL; 114285732ac8SCy Schubert return; 114385732ac8SCy Schubert } 114485732ac8SCy Schubert os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN); 114585732ac8SCy Schubert 114685732ac8SCy Schubert if (wpa_s->dpp_listen_freq && 114785732ac8SCy Schubert wpa_s->dpp_listen_freq != wpa_s->dpp_auth->curr_freq) { 114885732ac8SCy Schubert wpa_printf(MSG_DEBUG, 114985732ac8SCy Schubert "DPP: Stop listen on %u MHz to allow response on the request %u MHz", 115085732ac8SCy Schubert wpa_s->dpp_listen_freq, wpa_s->dpp_auth->curr_freq); 115185732ac8SCy Schubert wpas_dpp_listen_stop(wpa_s); 115285732ac8SCy Schubert } 115385732ac8SCy Schubert 115485732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 115585732ac8SCy Schubert MAC2STR(src), wpa_s->dpp_auth->curr_freq, 115685732ac8SCy Schubert DPP_PA_AUTHENTICATION_RESP); 115785732ac8SCy Schubert offchannel_send_action(wpa_s, wpa_s->dpp_auth->curr_freq, 115885732ac8SCy Schubert src, wpa_s->own_addr, broadcast, 115985732ac8SCy Schubert wpabuf_head(wpa_s->dpp_auth->resp_msg), 116085732ac8SCy Schubert wpabuf_len(wpa_s->dpp_auth->resp_msg), 116185732ac8SCy Schubert 500, wpas_dpp_tx_status, 0); 116285732ac8SCy Schubert } 116385732ac8SCy Schubert 116485732ac8SCy Schubert 116585732ac8SCy Schubert static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s) 116685732ac8SCy Schubert { 116785732ac8SCy Schubert /* TODO: stop wait and start ROC */ 116885732ac8SCy Schubert } 116985732ac8SCy Schubert 117085732ac8SCy Schubert 117185732ac8SCy Schubert static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, 1172c1d255d3SCy Schubert struct dpp_authentication *auth, 1173c1d255d3SCy Schubert struct dpp_config_obj *conf) 117485732ac8SCy Schubert { 117585732ac8SCy Schubert struct wpa_ssid *ssid; 117685732ac8SCy Schubert 11774bc52338SCy Schubert #ifdef CONFIG_DPP2 1178c1d255d3SCy Schubert if (conf->akm == DPP_AKM_SAE) { 11794bc52338SCy Schubert #ifdef CONFIG_SAE 11804bc52338SCy Schubert struct wpa_driver_capa capa; 11814bc52338SCy Schubert int res; 11824bc52338SCy Schubert 11834bc52338SCy Schubert res = wpa_drv_get_capa(wpa_s, &capa); 11844bc52338SCy Schubert if (res == 0 && 1185c1d255d3SCy Schubert !(capa.key_mgmt_iftype[WPA_IF_STATION] & 1186c1d255d3SCy Schubert WPA_DRIVER_CAPA_KEY_MGMT_SAE) && 11874bc52338SCy Schubert !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) { 11884bc52338SCy Schubert wpa_printf(MSG_DEBUG, 11894bc52338SCy Schubert "DPP: SAE not supported by the driver"); 11904bc52338SCy Schubert return NULL; 11914bc52338SCy Schubert } 11924bc52338SCy Schubert #else /* CONFIG_SAE */ 11934bc52338SCy Schubert wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build"); 11944bc52338SCy Schubert return NULL; 11954bc52338SCy Schubert #endif /* CONFIG_SAE */ 11964bc52338SCy Schubert } 11974bc52338SCy Schubert #endif /* CONFIG_DPP2 */ 11984bc52338SCy Schubert 119985732ac8SCy Schubert ssid = wpa_config_add_network(wpa_s->conf); 120085732ac8SCy Schubert if (!ssid) 120185732ac8SCy Schubert return NULL; 120285732ac8SCy Schubert wpas_notify_network_added(wpa_s, ssid); 120385732ac8SCy Schubert wpa_config_set_network_defaults(ssid); 120485732ac8SCy Schubert ssid->disabled = 1; 120585732ac8SCy Schubert 1206c1d255d3SCy Schubert ssid->ssid = os_malloc(conf->ssid_len); 120785732ac8SCy Schubert if (!ssid->ssid) 120885732ac8SCy Schubert goto fail; 1209c1d255d3SCy Schubert os_memcpy(ssid->ssid, conf->ssid, conf->ssid_len); 1210c1d255d3SCy Schubert ssid->ssid_len = conf->ssid_len; 121185732ac8SCy Schubert 1212c1d255d3SCy Schubert if (conf->connector) { 1213c1d255d3SCy Schubert if (dpp_akm_dpp(conf->akm)) { 121485732ac8SCy Schubert ssid->key_mgmt = WPA_KEY_MGMT_DPP; 121585732ac8SCy Schubert ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; 1216c1d255d3SCy Schubert } 1217c1d255d3SCy Schubert ssid->dpp_connector = os_strdup(conf->connector); 121885732ac8SCy Schubert if (!ssid->dpp_connector) 121985732ac8SCy Schubert goto fail; 122085732ac8SCy Schubert } 122185732ac8SCy Schubert 1222c1d255d3SCy Schubert if (conf->c_sign_key) { 1223c1d255d3SCy Schubert ssid->dpp_csign = os_malloc(wpabuf_len(conf->c_sign_key)); 122485732ac8SCy Schubert if (!ssid->dpp_csign) 122585732ac8SCy Schubert goto fail; 1226c1d255d3SCy Schubert os_memcpy(ssid->dpp_csign, wpabuf_head(conf->c_sign_key), 1227c1d255d3SCy Schubert wpabuf_len(conf->c_sign_key)); 1228c1d255d3SCy Schubert ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key); 1229c1d255d3SCy Schubert } 1230c1d255d3SCy Schubert 1231c1d255d3SCy Schubert if (conf->pp_key) { 1232c1d255d3SCy Schubert ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key)); 1233c1d255d3SCy Schubert if (!ssid->dpp_pp_key) 1234c1d255d3SCy Schubert goto fail; 1235c1d255d3SCy Schubert os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key), 1236c1d255d3SCy Schubert wpabuf_len(conf->pp_key)); 1237c1d255d3SCy Schubert ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key); 123885732ac8SCy Schubert } 123985732ac8SCy Schubert 124085732ac8SCy Schubert if (auth->net_access_key) { 124185732ac8SCy Schubert ssid->dpp_netaccesskey = 124285732ac8SCy Schubert os_malloc(wpabuf_len(auth->net_access_key)); 124385732ac8SCy Schubert if (!ssid->dpp_netaccesskey) 124485732ac8SCy Schubert goto fail; 124585732ac8SCy Schubert os_memcpy(ssid->dpp_netaccesskey, 124685732ac8SCy Schubert wpabuf_head(auth->net_access_key), 124785732ac8SCy Schubert wpabuf_len(auth->net_access_key)); 124885732ac8SCy Schubert ssid->dpp_netaccesskey_len = wpabuf_len(auth->net_access_key); 124985732ac8SCy Schubert ssid->dpp_netaccesskey_expiry = auth->net_access_key_expiry; 125085732ac8SCy Schubert } 125185732ac8SCy Schubert 1252c1d255d3SCy Schubert if (!conf->connector || dpp_akm_psk(conf->akm) || 1253c1d255d3SCy Schubert dpp_akm_sae(conf->akm)) { 1254c1d255d3SCy Schubert if (!conf->connector || !dpp_akm_dpp(conf->akm)) 125585732ac8SCy Schubert ssid->key_mgmt = 0; 1256c1d255d3SCy Schubert if (dpp_akm_psk(conf->akm)) 125785732ac8SCy Schubert ssid->key_mgmt |= WPA_KEY_MGMT_PSK | 125885732ac8SCy Schubert WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_FT_PSK; 1259c1d255d3SCy Schubert if (dpp_akm_sae(conf->akm)) 126085732ac8SCy Schubert ssid->key_mgmt |= WPA_KEY_MGMT_SAE | 126185732ac8SCy Schubert WPA_KEY_MGMT_FT_SAE; 126285732ac8SCy Schubert ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; 1263c1d255d3SCy Schubert if (conf->passphrase[0]) { 126485732ac8SCy Schubert if (wpa_config_set_quoted(ssid, "psk", 1265c1d255d3SCy Schubert conf->passphrase) < 0) 126685732ac8SCy Schubert goto fail; 126785732ac8SCy Schubert wpa_config_update_psk(ssid); 126885732ac8SCy Schubert ssid->export_keys = 1; 126985732ac8SCy Schubert } else { 1270c1d255d3SCy Schubert ssid->psk_set = conf->psk_set; 1271c1d255d3SCy Schubert os_memcpy(ssid->psk, conf->psk, PMK_LEN); 127285732ac8SCy Schubert } 127385732ac8SCy Schubert } 127485732ac8SCy Schubert 1275c1d255d3SCy Schubert #if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL) 1276c1d255d3SCy Schubert if (conf->akm == DPP_AKM_DOT1X) { 1277c1d255d3SCy Schubert int i; 1278c1d255d3SCy Schubert char name[100], blobname[128]; 1279c1d255d3SCy Schubert struct wpa_config_blob *blob; 1280c1d255d3SCy Schubert 1281c1d255d3SCy Schubert ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X | 1282c1d255d3SCy Schubert WPA_KEY_MGMT_IEEE8021X_SHA256 | 1283c1d255d3SCy Schubert WPA_KEY_MGMT_IEEE8021X_SHA256; 1284c1d255d3SCy Schubert ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; 1285c1d255d3SCy Schubert 1286c1d255d3SCy Schubert if (conf->cacert) { 1287c1d255d3SCy Schubert /* caCert is DER-encoded X.509v3 certificate for the 1288c1d255d3SCy Schubert * server certificate if that is different from the 1289c1d255d3SCy Schubert * trust root included in certBag. */ 1290c1d255d3SCy Schubert /* TODO: ssid->eap.cert.ca_cert */ 1291c1d255d3SCy Schubert } 1292c1d255d3SCy Schubert 1293c1d255d3SCy Schubert if (conf->certs) { 1294c1d255d3SCy Schubert for (i = 0; ; i++) { 1295c1d255d3SCy Schubert os_snprintf(name, sizeof(name), "dpp-certs-%d", 1296c1d255d3SCy Schubert i); 1297c1d255d3SCy Schubert if (!wpa_config_get_blob(wpa_s->conf, name)) 1298c1d255d3SCy Schubert break; 1299c1d255d3SCy Schubert } 1300c1d255d3SCy Schubert 1301c1d255d3SCy Schubert blob = os_zalloc(sizeof(*blob)); 1302c1d255d3SCy Schubert if (!blob) 1303c1d255d3SCy Schubert goto fail; 1304c1d255d3SCy Schubert blob->len = wpabuf_len(conf->certs); 1305c1d255d3SCy Schubert blob->name = os_strdup(name); 1306c1d255d3SCy Schubert blob->data = os_malloc(blob->len); 1307c1d255d3SCy Schubert if (!blob->name || !blob->data) { 1308c1d255d3SCy Schubert wpa_config_free_blob(blob); 1309c1d255d3SCy Schubert goto fail; 1310c1d255d3SCy Schubert } 1311c1d255d3SCy Schubert os_memcpy(blob->data, wpabuf_head(conf->certs), 1312c1d255d3SCy Schubert blob->len); 1313c1d255d3SCy Schubert os_snprintf(blobname, sizeof(blobname), "blob://%s", 1314c1d255d3SCy Schubert name); 1315c1d255d3SCy Schubert wpa_config_set_blob(wpa_s->conf, blob); 1316c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s", 1317c1d255d3SCy Schubert name); 1318c1d255d3SCy Schubert ssid->eap.cert.client_cert = os_strdup(blobname); 1319c1d255d3SCy Schubert if (!ssid->eap.cert.client_cert) 1320c1d255d3SCy Schubert goto fail; 1321c1d255d3SCy Schubert 1322c1d255d3SCy Schubert /* TODO: ssid->eap.identity from own certificate */ 1323c1d255d3SCy Schubert if (wpa_config_set(ssid, "identity", "\"dpp-ent\"", 1324c1d255d3SCy Schubert 0) < 0) 1325c1d255d3SCy Schubert goto fail; 1326c1d255d3SCy Schubert } 1327c1d255d3SCy Schubert 1328c1d255d3SCy Schubert if (auth->priv_key) { 1329c1d255d3SCy Schubert for (i = 0; ; i++) { 1330c1d255d3SCy Schubert os_snprintf(name, sizeof(name), "dpp-key-%d", 1331c1d255d3SCy Schubert i); 1332c1d255d3SCy Schubert if (!wpa_config_get_blob(wpa_s->conf, name)) 1333c1d255d3SCy Schubert break; 1334c1d255d3SCy Schubert } 1335c1d255d3SCy Schubert 1336c1d255d3SCy Schubert blob = os_zalloc(sizeof(*blob)); 1337c1d255d3SCy Schubert if (!blob) 1338c1d255d3SCy Schubert goto fail; 1339c1d255d3SCy Schubert blob->len = wpabuf_len(auth->priv_key); 1340c1d255d3SCy Schubert blob->name = os_strdup(name); 1341c1d255d3SCy Schubert blob->data = os_malloc(blob->len); 1342c1d255d3SCy Schubert if (!blob->name || !blob->data) { 1343c1d255d3SCy Schubert wpa_config_free_blob(blob); 1344c1d255d3SCy Schubert goto fail; 1345c1d255d3SCy Schubert } 1346c1d255d3SCy Schubert os_memcpy(blob->data, wpabuf_head(auth->priv_key), 1347c1d255d3SCy Schubert blob->len); 1348c1d255d3SCy Schubert os_snprintf(blobname, sizeof(blobname), "blob://%s", 1349c1d255d3SCy Schubert name); 1350c1d255d3SCy Schubert wpa_config_set_blob(wpa_s->conf, blob); 1351c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s", 1352c1d255d3SCy Schubert name); 1353c1d255d3SCy Schubert ssid->eap.cert.private_key = os_strdup(blobname); 1354c1d255d3SCy Schubert if (!ssid->eap.cert.private_key) 1355c1d255d3SCy Schubert goto fail; 1356c1d255d3SCy Schubert } 1357c1d255d3SCy Schubert 1358c1d255d3SCy Schubert if (conf->server_name) { 1359c1d255d3SCy Schubert ssid->eap.cert.domain_suffix_match = 1360c1d255d3SCy Schubert os_strdup(conf->server_name); 1361c1d255d3SCy Schubert if (!ssid->eap.cert.domain_suffix_match) 1362c1d255d3SCy Schubert goto fail; 1363c1d255d3SCy Schubert } 1364c1d255d3SCy Schubert 1365c1d255d3SCy Schubert /* TODO: Use entCreds::eapMethods */ 1366c1d255d3SCy Schubert if (wpa_config_set(ssid, "eap", "TLS", 0) < 0) 1367c1d255d3SCy Schubert goto fail; 1368c1d255d3SCy Schubert } 1369c1d255d3SCy Schubert #endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */ 1370c1d255d3SCy Schubert 1371c1d255d3SCy Schubert os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len); 1372c1d255d3SCy Schubert wpa_s->dpp_last_ssid_len = conf->ssid_len; 1373c1d255d3SCy Schubert 137485732ac8SCy Schubert return ssid; 137585732ac8SCy Schubert fail: 137685732ac8SCy Schubert wpas_notify_network_removed(wpa_s, ssid); 137785732ac8SCy Schubert wpa_config_remove_network(wpa_s->conf, ssid->id); 137885732ac8SCy Schubert return NULL; 137985732ac8SCy Schubert } 138085732ac8SCy Schubert 138185732ac8SCy Schubert 13824bc52338SCy Schubert static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s, 1383c1d255d3SCy Schubert struct dpp_authentication *auth, 1384c1d255d3SCy Schubert struct dpp_config_obj *conf) 138585732ac8SCy Schubert { 138685732ac8SCy Schubert struct wpa_ssid *ssid; 138785732ac8SCy Schubert 138885732ac8SCy Schubert if (wpa_s->conf->dpp_config_processing < 1) 13894bc52338SCy Schubert return 0; 139085732ac8SCy Schubert 1391c1d255d3SCy Schubert ssid = wpas_dpp_add_network(wpa_s, auth, conf); 139285732ac8SCy Schubert if (!ssid) 13934bc52338SCy Schubert return -1; 139485732ac8SCy Schubert 139585732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id); 13964bc52338SCy Schubert if (wpa_s->conf->dpp_config_processing == 2) 139785732ac8SCy Schubert ssid->disabled = 0; 13984bc52338SCy Schubert 13994bc52338SCy Schubert #ifndef CONFIG_NO_CONFIG_WRITE 14004bc52338SCy Schubert if (wpa_s->conf->update_config && 14014bc52338SCy Schubert wpa_config_write(wpa_s->confname, wpa_s->conf)) 14024bc52338SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to update configuration"); 14034bc52338SCy Schubert #endif /* CONFIG_NO_CONFIG_WRITE */ 14044bc52338SCy Schubert 14054bc52338SCy Schubert return 0; 1406c1d255d3SCy Schubert } 1407c1d255d3SCy Schubert 1408c1d255d3SCy Schubert 1409c1d255d3SCy Schubert static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s, 1410c1d255d3SCy Schubert struct dpp_authentication *auth) 1411c1d255d3SCy Schubert { 1412c1d255d3SCy Schubert #ifdef CONFIG_DPP2 1413c1d255d3SCy Schubert if (auth->reconfig && wpa_s->dpp_reconfig_ssid && 1414c1d255d3SCy Schubert wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) == 1415c1d255d3SCy Schubert wpa_s->dpp_reconfig_ssid) { 1416c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1417c1d255d3SCy Schubert "DPP: Remove reconfigured network profile"); 1418c1d255d3SCy Schubert wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid); 1419c1d255d3SCy Schubert wpa_config_remove_network(wpa_s->conf, 1420c1d255d3SCy Schubert wpa_s->dpp_reconfig_ssid_id); 1421c1d255d3SCy Schubert wpa_s->dpp_reconfig_ssid = NULL; 1422c1d255d3SCy Schubert wpa_s->dpp_reconfig_ssid_id = -1; 1423c1d255d3SCy Schubert } 1424c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 1425c1d255d3SCy Schubert 1426c1d255d3SCy Schubert if (wpa_s->conf->dpp_config_processing < 2) 1427c1d255d3SCy Schubert return; 14284bc52338SCy Schubert 14294bc52338SCy Schubert #ifdef CONFIG_DPP2 14304bc52338SCy Schubert if (auth->peer_version >= 2) { 14314bc52338SCy Schubert wpa_printf(MSG_DEBUG, 14324bc52338SCy Schubert "DPP: Postpone connection attempt to wait for completion of DPP Configuration Result"); 14334bc52338SCy Schubert auth->connect_on_tx_status = 1; 1434c1d255d3SCy Schubert return; 14354bc52338SCy Schubert } 14364bc52338SCy Schubert #endif /* CONFIG_DPP2 */ 14374bc52338SCy Schubert 14384bc52338SCy Schubert wpas_dpp_try_to_connect(wpa_s); 143985732ac8SCy Schubert } 144085732ac8SCy Schubert 144185732ac8SCy Schubert 14424bc52338SCy Schubert static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s, 1443c1d255d3SCy Schubert struct dpp_authentication *auth, 1444c1d255d3SCy Schubert struct dpp_config_obj *conf) 144585732ac8SCy Schubert { 144685732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED); 1447c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s", 1448c1d255d3SCy Schubert dpp_akm_str(conf->akm)); 1449c1d255d3SCy Schubert if (conf->ssid_len) 145085732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s", 1451c1d255d3SCy Schubert wpa_ssid_txt(conf->ssid, conf->ssid_len)); 1452c1d255d3SCy Schubert if (conf->ssid_charset) 1453c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d", 1454c1d255d3SCy Schubert conf->ssid_charset); 1455c1d255d3SCy Schubert if (conf->connector) { 145685732ac8SCy Schubert /* TODO: Save the Connector and consider using a command 145785732ac8SCy Schubert * to fetch the value instead of sending an event with 145885732ac8SCy Schubert * it. The Connector could end up being larger than what 145985732ac8SCy Schubert * most clients are ready to receive as an event 146085732ac8SCy Schubert * message. */ 146185732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s", 1462c1d255d3SCy Schubert conf->connector); 146385732ac8SCy Schubert } 1464c1d255d3SCy Schubert if (conf->passphrase[0]) { 1465c1d255d3SCy Schubert char hex[64 * 2 + 1]; 1466c1d255d3SCy Schubert 1467c1d255d3SCy Schubert wpa_snprintf_hex(hex, sizeof(hex), 1468c1d255d3SCy Schubert (const u8 *) conf->passphrase, 1469c1d255d3SCy Schubert os_strlen(conf->passphrase)); 1470c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s", 1471c1d255d3SCy Schubert hex); 1472c1d255d3SCy Schubert } else if (conf->psk_set) { 1473c1d255d3SCy Schubert char hex[PMK_LEN * 2 + 1]; 1474c1d255d3SCy Schubert 1475c1d255d3SCy Schubert wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN); 1476c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s", 1477c1d255d3SCy Schubert hex); 1478c1d255d3SCy Schubert } 1479c1d255d3SCy Schubert if (conf->c_sign_key) { 148085732ac8SCy Schubert char *hex; 148185732ac8SCy Schubert size_t hexlen; 148285732ac8SCy Schubert 1483c1d255d3SCy Schubert hexlen = 2 * wpabuf_len(conf->c_sign_key) + 1; 148485732ac8SCy Schubert hex = os_malloc(hexlen); 148585732ac8SCy Schubert if (hex) { 148685732ac8SCy Schubert wpa_snprintf_hex(hex, hexlen, 1487c1d255d3SCy Schubert wpabuf_head(conf->c_sign_key), 1488c1d255d3SCy Schubert wpabuf_len(conf->c_sign_key)); 148985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_C_SIGN_KEY "%s", 149085732ac8SCy Schubert hex); 149185732ac8SCy Schubert os_free(hex); 149285732ac8SCy Schubert } 149385732ac8SCy Schubert } 1494c1d255d3SCy Schubert if (conf->pp_key) { 1495c1d255d3SCy Schubert char *hex; 1496c1d255d3SCy Schubert size_t hexlen; 1497c1d255d3SCy Schubert 1498c1d255d3SCy Schubert hexlen = 2 * wpabuf_len(conf->pp_key) + 1; 1499c1d255d3SCy Schubert hex = os_malloc(hexlen); 1500c1d255d3SCy Schubert if (hex) { 1501c1d255d3SCy Schubert wpa_snprintf_hex(hex, hexlen, 1502c1d255d3SCy Schubert wpabuf_head(conf->pp_key), 1503c1d255d3SCy Schubert wpabuf_len(conf->pp_key)); 1504c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex); 1505c1d255d3SCy Schubert os_free(hex); 1506c1d255d3SCy Schubert } 1507c1d255d3SCy Schubert } 150885732ac8SCy Schubert if (auth->net_access_key) { 150985732ac8SCy Schubert char *hex; 151085732ac8SCy Schubert size_t hexlen; 151185732ac8SCy Schubert 151285732ac8SCy Schubert hexlen = 2 * wpabuf_len(auth->net_access_key) + 1; 151385732ac8SCy Schubert hex = os_malloc(hexlen); 151485732ac8SCy Schubert if (hex) { 151585732ac8SCy Schubert wpa_snprintf_hex(hex, hexlen, 151685732ac8SCy Schubert wpabuf_head(auth->net_access_key), 151785732ac8SCy Schubert wpabuf_len(auth->net_access_key)); 151885732ac8SCy Schubert if (auth->net_access_key_expiry) 151985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, 152085732ac8SCy Schubert DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex, 152185732ac8SCy Schubert (long unsigned) 152285732ac8SCy Schubert auth->net_access_key_expiry); 152385732ac8SCy Schubert else 152485732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, 152585732ac8SCy Schubert DPP_EVENT_NET_ACCESS_KEY "%s", hex); 152685732ac8SCy Schubert os_free(hex); 152785732ac8SCy Schubert } 152885732ac8SCy Schubert } 152985732ac8SCy Schubert 1530c1d255d3SCy Schubert #ifdef CONFIG_DPP2 1531c1d255d3SCy Schubert if (conf->certbag) { 1532c1d255d3SCy Schubert char *b64; 1533c1d255d3SCy Schubert 1534c1d255d3SCy Schubert b64 = base64_encode_no_lf(wpabuf_head(conf->certbag), 1535c1d255d3SCy Schubert wpabuf_len(conf->certbag), NULL); 1536c1d255d3SCy Schubert if (b64) 1537c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64); 1538c1d255d3SCy Schubert os_free(b64); 153985732ac8SCy Schubert } 154085732ac8SCy Schubert 1541c1d255d3SCy Schubert if (conf->cacert) { 1542c1d255d3SCy Schubert char *b64; 1543c1d255d3SCy Schubert 1544c1d255d3SCy Schubert b64 = base64_encode_no_lf(wpabuf_head(conf->cacert), 1545c1d255d3SCy Schubert wpabuf_len(conf->cacert), NULL); 1546c1d255d3SCy Schubert if (b64) 1547c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64); 1548c1d255d3SCy Schubert os_free(b64); 1549c1d255d3SCy Schubert } 1550c1d255d3SCy Schubert 1551c1d255d3SCy Schubert if (conf->server_name) 1552c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s", 1553c1d255d3SCy Schubert conf->server_name); 1554c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 1555c1d255d3SCy Schubert 1556c1d255d3SCy Schubert return wpas_dpp_process_config(wpa_s, auth, conf); 1557c1d255d3SCy Schubert } 1558c1d255d3SCy Schubert 1559c1d255d3SCy Schubert 1560c1d255d3SCy Schubert static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s, 1561c1d255d3SCy Schubert struct dpp_asymmetric_key *key) 1562c1d255d3SCy Schubert { 1563c1d255d3SCy Schubert #ifdef CONFIG_DPP2 1564c1d255d3SCy Schubert int res; 1565c1d255d3SCy Schubert 1566c1d255d3SCy Schubert if (!key) 1567c1d255d3SCy Schubert return 0; 1568c1d255d3SCy Schubert 1569c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup"); 1570c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED); 1571c1d255d3SCy Schubert wpa_s->dpp_conf_backup_received = true; 1572c1d255d3SCy Schubert 1573c1d255d3SCy Schubert while (key) { 1574c1d255d3SCy Schubert res = dpp_configurator_from_backup(wpa_s->dpp, key); 1575c1d255d3SCy Schubert if (res < 0) 1576c1d255d3SCy Schubert return -1; 1577c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFIGURATOR_ID "%d", 1578c1d255d3SCy Schubert res); 1579c1d255d3SCy Schubert key = key->next; 1580c1d255d3SCy Schubert } 1581c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 1582c1d255d3SCy Schubert 1583c1d255d3SCy Schubert return 0; 1584c1d255d3SCy Schubert } 1585c1d255d3SCy Schubert 1586c1d255d3SCy Schubert 1587c1d255d3SCy Schubert #ifdef CONFIG_DPP2 1588c1d255d3SCy Schubert static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx) 1589c1d255d3SCy Schubert { 1590c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 1591c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 1592c1d255d3SCy Schubert 1593c1d255d3SCy Schubert if (!auth || !auth->csrattrs) 1594c1d255d3SCy Schubert return; 1595c1d255d3SCy Schubert 1596c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Build CSR"); 1597c1d255d3SCy Schubert wpabuf_free(auth->csr); 1598c1d255d3SCy Schubert /* TODO: Additional information needed for CSR based on csrAttrs */ 1599c1d255d3SCy Schubert auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ? 1600c1d255d3SCy Schubert wpa_s->conf->dpp_name : "Test"); 1601c1d255d3SCy Schubert if (!auth->csr) { 1602c1d255d3SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 1603c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 1604c1d255d3SCy Schubert return; 1605c1d255d3SCy Schubert } 1606c1d255d3SCy Schubert 1607c1d255d3SCy Schubert wpas_dpp_start_gas_client(wpa_s); 1608c1d255d3SCy Schubert } 1609c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 1610c1d255d3SCy Schubert 161185732ac8SCy Schubert 161285732ac8SCy Schubert static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, 161385732ac8SCy Schubert enum gas_query_result result, 161485732ac8SCy Schubert const struct wpabuf *adv_proto, 161585732ac8SCy Schubert const struct wpabuf *resp, u16 status_code) 161685732ac8SCy Schubert { 161785732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 161885732ac8SCy Schubert const u8 *pos; 161985732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 16204bc52338SCy Schubert int res; 16214bc52338SCy Schubert enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED; 1622c1d255d3SCy Schubert unsigned int i; 162385732ac8SCy Schubert 162485732ac8SCy Schubert wpa_s->dpp_gas_dialog_token = -1; 162585732ac8SCy Schubert 1626c1d255d3SCy Schubert if (!auth || (!auth->auth_success && !auth->reconfig_success) || 1627c1d255d3SCy Schubert os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) { 162885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); 162985732ac8SCy Schubert return; 163085732ac8SCy Schubert } 163185732ac8SCy Schubert if (result != GAS_QUERY_SUCCESS || 163285732ac8SCy Schubert !resp || status_code != WLAN_STATUS_SUCCESS) { 163385732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed"); 163485732ac8SCy Schubert goto fail; 163585732ac8SCy Schubert } 163685732ac8SCy Schubert 163785732ac8SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto", 163885732ac8SCy Schubert adv_proto); 163985732ac8SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)", 164085732ac8SCy Schubert resp); 164185732ac8SCy Schubert 164285732ac8SCy Schubert if (wpabuf_len(adv_proto) != 10 || 164385732ac8SCy Schubert !(pos = wpabuf_head(adv_proto)) || 164485732ac8SCy Schubert pos[0] != WLAN_EID_ADV_PROTO || 164585732ac8SCy Schubert pos[1] != 8 || 164685732ac8SCy Schubert pos[3] != WLAN_EID_VENDOR_SPECIFIC || 164785732ac8SCy Schubert pos[4] != 5 || 164885732ac8SCy Schubert WPA_GET_BE24(&pos[5]) != OUI_WFA || 164985732ac8SCy Schubert pos[8] != 0x1a || 165085732ac8SCy Schubert pos[9] != 1) { 165185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 165285732ac8SCy Schubert "DPP: Not a DPP Advertisement Protocol ID"); 165385732ac8SCy Schubert goto fail; 165485732ac8SCy Schubert } 165585732ac8SCy Schubert 1656c1d255d3SCy Schubert res = dpp_conf_resp_rx(auth, resp); 1657c1d255d3SCy Schubert #ifdef CONFIG_DPP2 1658c1d255d3SCy Schubert if (res == -2) { 1659c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: CSR needed"); 1660c1d255d3SCy Schubert eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL); 1661c1d255d3SCy Schubert return; 1662c1d255d3SCy Schubert } 1663c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 1664c1d255d3SCy Schubert if (res < 0) { 166585732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); 166685732ac8SCy Schubert goto fail; 166785732ac8SCy Schubert } 166885732ac8SCy Schubert 1669c1d255d3SCy Schubert wpa_s->dpp_conf_backup_received = false; 1670c1d255d3SCy Schubert for (i = 0; i < auth->num_conf_obj; i++) { 1671c1d255d3SCy Schubert res = wpas_dpp_handle_config_obj(wpa_s, auth, 1672c1d255d3SCy Schubert &auth->conf_obj[i]); 16734bc52338SCy Schubert if (res < 0) 16744bc52338SCy Schubert goto fail; 1675c1d255d3SCy Schubert } 1676c1d255d3SCy Schubert if (auth->num_conf_obj) 1677c1d255d3SCy Schubert wpas_dpp_post_process_config(wpa_s, auth); 1678c1d255d3SCy Schubert if (wpas_dpp_handle_key_pkg(wpa_s, auth->conf_key_pkg) < 0) 1679c1d255d3SCy Schubert goto fail; 168085732ac8SCy Schubert 16814bc52338SCy Schubert status = DPP_STATUS_OK; 16824bc52338SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 16834bc52338SCy Schubert if (dpp_test == DPP_TEST_REJECT_CONFIG) { 16844bc52338SCy Schubert wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object"); 16854bc52338SCy Schubert status = DPP_STATUS_CONFIG_REJECTED; 16864bc52338SCy Schubert } 16874bc52338SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 168885732ac8SCy Schubert fail: 16894bc52338SCy Schubert if (status != DPP_STATUS_OK) 169085732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); 16914bc52338SCy Schubert #ifdef CONFIG_DPP2 16924bc52338SCy Schubert if (auth->peer_version >= 2 && 16934bc52338SCy Schubert auth->conf_resp_status == DPP_STATUS_OK) { 16944bc52338SCy Schubert struct wpabuf *msg; 16954bc52338SCy Schubert 16964bc52338SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result"); 16974bc52338SCy Schubert msg = dpp_build_conf_result(auth, status); 16984bc52338SCy Schubert if (!msg) 16994bc52338SCy Schubert goto fail2; 17004bc52338SCy Schubert 17014bc52338SCy Schubert wpa_msg(wpa_s, MSG_INFO, 17024bc52338SCy Schubert DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 17034bc52338SCy Schubert MAC2STR(addr), auth->curr_freq, 17044bc52338SCy Schubert DPP_PA_CONFIGURATION_RESULT); 17054bc52338SCy Schubert offchannel_send_action(wpa_s, auth->curr_freq, 17064bc52338SCy Schubert addr, wpa_s->own_addr, broadcast, 17074bc52338SCy Schubert wpabuf_head(msg), 17084bc52338SCy Schubert wpabuf_len(msg), 17094bc52338SCy Schubert 500, wpas_dpp_tx_status, 0); 17104bc52338SCy Schubert wpabuf_free(msg); 17114bc52338SCy Schubert 17124bc52338SCy Schubert /* This exchange will be terminated in the TX status handler */ 1713c1d255d3SCy Schubert if (wpa_s->conf->dpp_config_processing < 2 || 1714c1d255d3SCy Schubert wpa_s->dpp_conf_backup_received) 1715c1d255d3SCy Schubert auth->remove_on_tx_status = 1; 17164bc52338SCy Schubert return; 17174bc52338SCy Schubert } 17184bc52338SCy Schubert fail2: 17194bc52338SCy Schubert #endif /* CONFIG_DPP2 */ 172085732ac8SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 172185732ac8SCy Schubert wpa_s->dpp_auth = NULL; 172285732ac8SCy Schubert } 172385732ac8SCy Schubert 172485732ac8SCy Schubert 172585732ac8SCy Schubert static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s) 172685732ac8SCy Schubert { 172785732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 17284bc52338SCy Schubert struct wpabuf *buf; 172985732ac8SCy Schubert int res; 1730c1d255d3SCy Schubert int *supp_op_classes; 173185732ac8SCy Schubert 173285732ac8SCy Schubert wpa_s->dpp_gas_client = 1; 173385732ac8SCy Schubert offchannel_send_action_done(wpa_s); 173485732ac8SCy Schubert wpas_dpp_listen_stop(wpa_s); 173585732ac8SCy Schubert 1736c1d255d3SCy Schubert supp_op_classes = wpas_supp_op_classes(wpa_s); 1737c1d255d3SCy Schubert buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name, 1738c1d255d3SCy Schubert wpa_s->dpp_netrole, 1739c1d255d3SCy Schubert wpa_s->conf->dpp_mud_url, 1740c1d255d3SCy Schubert supp_op_classes); 1741c1d255d3SCy Schubert os_free(supp_op_classes); 17424bc52338SCy Schubert if (!buf) { 174385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 174485732ac8SCy Schubert "DPP: No configuration request data available"); 174585732ac8SCy Schubert return; 174685732ac8SCy Schubert } 174785732ac8SCy Schubert 174885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)", 174985732ac8SCy Schubert MAC2STR(auth->peer_mac_addr), auth->curr_freq); 175085732ac8SCy Schubert 175185732ac8SCy Schubert res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq, 1752c1d255d3SCy Schubert 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s); 175385732ac8SCy Schubert if (res < 0) { 175485732ac8SCy Schubert wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); 175585732ac8SCy Schubert wpabuf_free(buf); 175685732ac8SCy Schubert } else { 175785732ac8SCy Schubert wpa_printf(MSG_DEBUG, 175885732ac8SCy Schubert "DPP: GAS query started with dialog token %u", res); 175985732ac8SCy Schubert wpa_s->dpp_gas_dialog_token = res; 176085732ac8SCy Schubert } 176185732ac8SCy Schubert } 176285732ac8SCy Schubert 176385732ac8SCy Schubert 176485732ac8SCy Schubert static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator) 176585732ac8SCy Schubert { 176685732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded"); 176785732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator); 176885732ac8SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 176985732ac8SCy Schubert if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { 177085732ac8SCy Schubert wpa_printf(MSG_INFO, 177185732ac8SCy Schubert "DPP: TESTING - stop at Authentication Confirm"); 177285732ac8SCy Schubert if (wpa_s->dpp_auth->configurator) { 177385732ac8SCy Schubert /* Prevent GAS response */ 177485732ac8SCy Schubert wpa_s->dpp_auth->auth_success = 0; 177585732ac8SCy Schubert } 177685732ac8SCy Schubert return; 177785732ac8SCy Schubert } 177885732ac8SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 177985732ac8SCy Schubert 178085732ac8SCy Schubert if (wpa_s->dpp_auth->configurator) 178185732ac8SCy Schubert wpas_dpp_start_gas_server(wpa_s); 178285732ac8SCy Schubert else 178385732ac8SCy Schubert wpas_dpp_start_gas_client(wpa_s); 178485732ac8SCy Schubert } 178585732ac8SCy Schubert 178685732ac8SCy Schubert 178785732ac8SCy Schubert static void wpas_dpp_rx_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, 178885732ac8SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 178985732ac8SCy Schubert unsigned int freq) 179085732ac8SCy Schubert { 179185732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 179285732ac8SCy Schubert struct wpabuf *msg; 179385732ac8SCy Schubert 179485732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR 179585732ac8SCy Schubert " (freq %u MHz)", MAC2STR(src), freq); 179685732ac8SCy Schubert 179785732ac8SCy Schubert if (!auth) { 179885732ac8SCy Schubert wpa_printf(MSG_DEBUG, 179985732ac8SCy Schubert "DPP: No DPP Authentication in progress - drop"); 180085732ac8SCy Schubert return; 180185732ac8SCy Schubert } 180285732ac8SCy Schubert 180385732ac8SCy Schubert if (!is_zero_ether_addr(auth->peer_mac_addr) && 180485732ac8SCy Schubert os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { 180585732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " 180685732ac8SCy Schubert MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); 180785732ac8SCy Schubert return; 180885732ac8SCy Schubert } 180985732ac8SCy Schubert 181085732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); 181185732ac8SCy Schubert 181285732ac8SCy Schubert if (auth->curr_freq != freq && auth->neg_freq == freq) { 181385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 181485732ac8SCy Schubert "DPP: Responder accepted request for different negotiation channel"); 181585732ac8SCy Schubert auth->curr_freq = freq; 181685732ac8SCy Schubert } 181785732ac8SCy Schubert 181885732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); 181985732ac8SCy Schubert msg = dpp_auth_resp_rx(auth, hdr, buf, len); 182085732ac8SCy Schubert if (!msg) { 182185732ac8SCy Schubert if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { 182285732ac8SCy Schubert wpa_printf(MSG_DEBUG, 182385732ac8SCy Schubert "DPP: Start wait for full response"); 182485732ac8SCy Schubert offchannel_send_action_done(wpa_s); 182585732ac8SCy Schubert wpas_dpp_listen_start(wpa_s, auth->curr_freq); 182685732ac8SCy Schubert return; 182785732ac8SCy Schubert } 182885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No confirm generated"); 182985732ac8SCy Schubert return; 183085732ac8SCy Schubert } 183185732ac8SCy Schubert os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); 183285732ac8SCy Schubert 183385732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 183485732ac8SCy Schubert MAC2STR(src), auth->curr_freq, DPP_PA_AUTHENTICATION_CONF); 183585732ac8SCy Schubert offchannel_send_action(wpa_s, auth->curr_freq, 183685732ac8SCy Schubert src, wpa_s->own_addr, broadcast, 183785732ac8SCy Schubert wpabuf_head(msg), wpabuf_len(msg), 183885732ac8SCy Schubert 500, wpas_dpp_tx_status, 0); 183985732ac8SCy Schubert wpabuf_free(msg); 184085732ac8SCy Schubert wpa_s->dpp_auth_ok_on_ack = 1; 184185732ac8SCy Schubert } 184285732ac8SCy Schubert 184385732ac8SCy Schubert 184485732ac8SCy Schubert static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src, 184585732ac8SCy Schubert const u8 *hdr, const u8 *buf, size_t len) 184685732ac8SCy Schubert { 184785732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 184885732ac8SCy Schubert 184985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR, 185085732ac8SCy Schubert MAC2STR(src)); 185185732ac8SCy Schubert 185285732ac8SCy Schubert if (!auth) { 185385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 185485732ac8SCy Schubert "DPP: No DPP Authentication in progress - drop"); 185585732ac8SCy Schubert return; 185685732ac8SCy Schubert } 185785732ac8SCy Schubert 185885732ac8SCy Schubert if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { 185985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " 186085732ac8SCy Schubert MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); 186185732ac8SCy Schubert return; 186285732ac8SCy Schubert } 186385732ac8SCy Schubert 1864c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL); 1865c1d255d3SCy Schubert 186685732ac8SCy Schubert if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) { 186785732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); 186885732ac8SCy Schubert return; 186985732ac8SCy Schubert } 187085732ac8SCy Schubert 187185732ac8SCy Schubert wpas_dpp_auth_success(wpa_s, 0); 187285732ac8SCy Schubert } 187385732ac8SCy Schubert 187485732ac8SCy Schubert 18754bc52338SCy Schubert #ifdef CONFIG_DPP2 18764bc52338SCy Schubert 18774bc52338SCy Schubert static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx, 18784bc52338SCy Schubert void *timeout_ctx) 18794bc52338SCy Schubert { 18804bc52338SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 18814bc52338SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 18824bc52338SCy Schubert 18834bc52338SCy Schubert if (!auth || !auth->waiting_conf_result) 18844bc52338SCy Schubert return; 18854bc52338SCy Schubert 18864bc52338SCy Schubert wpa_printf(MSG_DEBUG, 18874bc52338SCy Schubert "DPP: Timeout while waiting for Configuration Result"); 18884bc52338SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); 18894bc52338SCy Schubert dpp_auth_deinit(auth); 18904bc52338SCy Schubert wpa_s->dpp_auth = NULL; 18914bc52338SCy Schubert } 18924bc52338SCy Schubert 18934bc52338SCy Schubert 1894c1d255d3SCy Schubert static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx, 1895c1d255d3SCy Schubert void *timeout_ctx) 1896c1d255d3SCy Schubert { 1897c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 1898c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 1899c1d255d3SCy Schubert 1900c1d255d3SCy Schubert if (!auth || !auth->waiting_conn_status_result) 1901c1d255d3SCy Schubert return; 1902c1d255d3SCy Schubert 1903c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1904c1d255d3SCy Schubert "DPP: Timeout while waiting for Connection Status Result"); 1905c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout"); 1906c1d255d3SCy Schubert wpas_dpp_listen_stop(wpa_s); 1907c1d255d3SCy Schubert dpp_auth_deinit(auth); 1908c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 1909c1d255d3SCy Schubert } 1910c1d255d3SCy Schubert 1911c1d255d3SCy Schubert 19124bc52338SCy Schubert static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src, 19134bc52338SCy Schubert const u8 *hdr, const u8 *buf, size_t len) 19144bc52338SCy Schubert { 19154bc52338SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 19164bc52338SCy Schubert enum dpp_status_error status; 19174bc52338SCy Schubert 19184bc52338SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR, 19194bc52338SCy Schubert MAC2STR(src)); 19204bc52338SCy Schubert 19214bc52338SCy Schubert if (!auth || !auth->waiting_conf_result) { 1922c1d255d3SCy Schubert if (auth && 1923c1d255d3SCy Schubert os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 && 1924c1d255d3SCy Schubert gas_server_response_sent(wpa_s->gas_server, 1925c1d255d3SCy Schubert auth->gas_server_ctx)) { 1926c1d255d3SCy Schubert /* This could happen if the TX status event gets delayed 1927c1d255d3SCy Schubert * long enough for the Enrollee to have time to send 1928c1d255d3SCy Schubert * the next frame before the TX status gets processed 1929c1d255d3SCy Schubert * locally. */ 1930c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1931c1d255d3SCy Schubert "DPP: GAS response was sent but TX status not yet received - assume it was ACKed since the Enrollee sent the next frame in the sequence"); 1932c1d255d3SCy Schubert auth->waiting_conf_result = 1; 1933c1d255d3SCy Schubert } else { 19344bc52338SCy Schubert wpa_printf(MSG_DEBUG, 19354bc52338SCy Schubert "DPP: No DPP Configuration waiting for result - drop"); 19364bc52338SCy Schubert return; 19374bc52338SCy Schubert } 1938c1d255d3SCy Schubert } 19394bc52338SCy Schubert 19404bc52338SCy Schubert if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { 19414bc52338SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " 19424bc52338SCy Schubert MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); 19434bc52338SCy Schubert return; 19444bc52338SCy Schubert } 19454bc52338SCy Schubert 19464bc52338SCy Schubert status = dpp_conf_result_rx(auth, hdr, buf, len); 19474bc52338SCy Schubert 1948c1d255d3SCy Schubert if (status == DPP_STATUS_OK && auth->send_conn_status) { 1949c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, 1950c1d255d3SCy Schubert DPP_EVENT_CONF_SENT "wait_conn_status=1"); 1951c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); 1952c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, 1953c1d255d3SCy Schubert wpa_s, NULL); 1954c1d255d3SCy Schubert auth->waiting_conn_status_result = 1; 1955c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout, 1956c1d255d3SCy Schubert wpa_s, NULL); 1957c1d255d3SCy Schubert eloop_register_timeout(16, 0, 1958c1d255d3SCy Schubert wpas_dpp_conn_status_result_wait_timeout, 1959c1d255d3SCy Schubert wpa_s, NULL); 1960c1d255d3SCy Schubert offchannel_send_action_done(wpa_s); 1961c1d255d3SCy Schubert wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq : 1962c1d255d3SCy Schubert auth->curr_freq); 1963c1d255d3SCy Schubert return; 1964c1d255d3SCy Schubert } 19654bc52338SCy Schubert offchannel_send_action_done(wpa_s); 19664bc52338SCy Schubert wpas_dpp_listen_stop(wpa_s); 19674bc52338SCy Schubert if (status == DPP_STATUS_OK) 19684bc52338SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT); 19694bc52338SCy Schubert else 19704bc52338SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); 19714bc52338SCy Schubert dpp_auth_deinit(auth); 19724bc52338SCy Schubert wpa_s->dpp_auth = NULL; 19734bc52338SCy Schubert eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL); 19744bc52338SCy Schubert } 19754bc52338SCy Schubert 1976206b73d0SCy Schubert 1977c1d255d3SCy Schubert static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s, 1978c1d255d3SCy Schubert const u8 *src, const u8 *hdr, 1979c1d255d3SCy Schubert const u8 *buf, size_t len) 1980c1d255d3SCy Schubert { 1981c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 1982c1d255d3SCy Schubert enum dpp_status_error status; 1983c1d255d3SCy Schubert u8 ssid[SSID_MAX_LEN]; 1984c1d255d3SCy Schubert size_t ssid_len = 0; 1985c1d255d3SCy Schubert char *channel_list = NULL; 1986c1d255d3SCy Schubert 1987c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Connection Status Result"); 1988c1d255d3SCy Schubert 1989c1d255d3SCy Schubert if (!auth || !auth->waiting_conn_status_result) { 1990c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1991c1d255d3SCy Schubert "DPP: No DPP Configuration waiting for connection status result - drop"); 1992c1d255d3SCy Schubert return; 1993c1d255d3SCy Schubert } 1994c1d255d3SCy Schubert 1995c1d255d3SCy Schubert status = dpp_conn_status_result_rx(auth, hdr, buf, len, 1996c1d255d3SCy Schubert ssid, &ssid_len, &channel_list); 1997c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT 1998c1d255d3SCy Schubert "result=%d ssid=%s channel_list=%s", 1999c1d255d3SCy Schubert status, wpa_ssid_txt(ssid, ssid_len), 2000c1d255d3SCy Schubert channel_list ? channel_list : "N/A"); 2001c1d255d3SCy Schubert os_free(channel_list); 2002c1d255d3SCy Schubert offchannel_send_action_done(wpa_s); 2003c1d255d3SCy Schubert wpas_dpp_listen_stop(wpa_s); 2004c1d255d3SCy Schubert dpp_auth_deinit(auth); 2005c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 2006c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout, 2007c1d255d3SCy Schubert wpa_s, NULL); 2008c1d255d3SCy Schubert } 2009c1d255d3SCy Schubert 2010c1d255d3SCy Schubert 2011206b73d0SCy Schubert static int wpas_dpp_process_conf_obj(void *ctx, 2012206b73d0SCy Schubert struct dpp_authentication *auth) 2013206b73d0SCy Schubert { 2014206b73d0SCy Schubert struct wpa_supplicant *wpa_s = ctx; 2015c1d255d3SCy Schubert unsigned int i; 2016c1d255d3SCy Schubert int res = -1; 2017206b73d0SCy Schubert 2018c1d255d3SCy Schubert for (i = 0; i < auth->num_conf_obj; i++) { 2019c1d255d3SCy Schubert res = wpas_dpp_handle_config_obj(wpa_s, auth, 2020c1d255d3SCy Schubert &auth->conf_obj[i]); 2021c1d255d3SCy Schubert if (res) 2022c1d255d3SCy Schubert break; 2023c1d255d3SCy Schubert } 2024c1d255d3SCy Schubert if (!res) 2025c1d255d3SCy Schubert wpas_dpp_post_process_config(wpa_s, auth); 2026c1d255d3SCy Schubert 2027c1d255d3SCy Schubert return res; 2028c1d255d3SCy Schubert } 2029c1d255d3SCy Schubert 2030c1d255d3SCy Schubert 2031c1d255d3SCy Schubert static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi) 2032c1d255d3SCy Schubert { 2033c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = ctx; 2034c1d255d3SCy Schubert 2035c1d255d3SCy Schubert if (bi == wpa_s->dpp_chirp_bi) 2036c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 2037c1d255d3SCy Schubert } 2038c1d255d3SCy Schubert 2039c1d255d3SCy Schubert 2040c1d255d3SCy Schubert static void 2041c1d255d3SCy Schubert wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src, 2042c1d255d3SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 2043c1d255d3SCy Schubert unsigned int freq) 2044c1d255d3SCy Schubert { 2045c1d255d3SCy Schubert const u8 *r_bootstrap; 2046c1d255d3SCy Schubert u16 r_bootstrap_len; 2047c1d255d3SCy Schubert struct dpp_bootstrap_info *peer_bi; 2048c1d255d3SCy Schubert struct dpp_authentication *auth; 2049c1d255d3SCy Schubert 2050c1d255d3SCy Schubert if (!wpa_s->dpp) 2051c1d255d3SCy Schubert return; 2052c1d255d3SCy Schubert 2053c1d255d3SCy Schubert if (wpa_s->dpp_auth) { 2054c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2055c1d255d3SCy Schubert "DPP: Ignore Presence Announcement during ongoing Authentication"); 2056c1d255d3SCy Schubert return; 2057c1d255d3SCy Schubert } 2058c1d255d3SCy Schubert 2059c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR, 2060c1d255d3SCy Schubert MAC2STR(src)); 2061c1d255d3SCy Schubert 2062c1d255d3SCy Schubert r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, 2063c1d255d3SCy Schubert &r_bootstrap_len); 2064c1d255d3SCy Schubert if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { 2065c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL 2066c1d255d3SCy Schubert "Missing or invalid required Responder Bootstrapping Key Hash attribute"); 2067c1d255d3SCy Schubert return; 2068c1d255d3SCy Schubert } 2069c1d255d3SCy Schubert wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", 2070c1d255d3SCy Schubert r_bootstrap, r_bootstrap_len); 2071c1d255d3SCy Schubert peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap); 2072c1d255d3SCy Schubert dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src, 2073c1d255d3SCy Schubert freq, r_bootstrap); 2074c1d255d3SCy Schubert if (!peer_bi) { 2075c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2076c1d255d3SCy Schubert "DPP: No matching bootstrapping information found"); 2077c1d255d3SCy Schubert return; 2078c1d255d3SCy Schubert } 2079c1d255d3SCy Schubert 2080c1d255d3SCy Schubert auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL, 2081c1d255d3SCy Schubert DPP_CAPAB_CONFIGURATOR, freq, NULL, 0); 2082c1d255d3SCy Schubert if (!auth) 2083c1d255d3SCy Schubert return; 2084c1d255d3SCy Schubert wpas_dpp_set_testing_options(wpa_s, auth); 2085c1d255d3SCy Schubert if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) { 2086c1d255d3SCy Schubert dpp_auth_deinit(auth); 2087c1d255d3SCy Schubert return; 2088c1d255d3SCy Schubert } 2089c1d255d3SCy Schubert 2090c1d255d3SCy Schubert auth->neg_freq = freq; 2091c1d255d3SCy Schubert 2092c1d255d3SCy Schubert /* The source address of the Presence Announcement frame overrides any 2093c1d255d3SCy Schubert * MAC address information from the bootstrapping information. */ 2094c1d255d3SCy Schubert os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); 2095c1d255d3SCy Schubert 2096c1d255d3SCy Schubert wpa_s->dpp_auth = auth; 2097c1d255d3SCy Schubert if (wpas_dpp_auth_init_next(wpa_s) < 0) { 2098c1d255d3SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 2099c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 2100c1d255d3SCy Schubert } 2101c1d255d3SCy Schubert } 2102c1d255d3SCy Schubert 2103c1d255d3SCy Schubert 2104c1d255d3SCy Schubert static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, 2105c1d255d3SCy Schubert void *timeout_ctx) 2106c1d255d3SCy Schubert { 2107c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 2108c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 2109c1d255d3SCy Schubert 2110c1d255d3SCy Schubert if (!auth) 2111c1d255d3SCy Schubert return; 2112c1d255d3SCy Schubert 2113c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout"); 2114c1d255d3SCy Schubert offchannel_send_action_done(wpa_s); 2115c1d255d3SCy Schubert wpas_dpp_listen_stop(wpa_s); 2116c1d255d3SCy Schubert dpp_auth_deinit(auth); 2117c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 2118c1d255d3SCy Schubert } 2119c1d255d3SCy Schubert 2120c1d255d3SCy Schubert 2121c1d255d3SCy Schubert static void 2122c1d255d3SCy Schubert wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, 2123c1d255d3SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 2124c1d255d3SCy Schubert unsigned int freq) 2125c1d255d3SCy Schubert { 2126c1d255d3SCy Schubert const u8 *csign_hash, *fcgroup, *a_nonce, *e_id; 2127c1d255d3SCy Schubert u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len; 2128c1d255d3SCy Schubert struct dpp_configurator *conf; 2129c1d255d3SCy Schubert struct dpp_authentication *auth; 2130c1d255d3SCy Schubert unsigned int wait_time, max_wait_time; 2131c1d255d3SCy Schubert u16 group; 2132c1d255d3SCy Schubert 2133c1d255d3SCy Schubert if (!wpa_s->dpp) 2134c1d255d3SCy Schubert return; 2135c1d255d3SCy Schubert 2136c1d255d3SCy Schubert if (wpa_s->dpp_auth) { 2137c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2138c1d255d3SCy Schubert "DPP: Ignore Reconfig Announcement during ongoing Authentication"); 2139c1d255d3SCy Schubert return; 2140c1d255d3SCy Schubert } 2141c1d255d3SCy Schubert 2142c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR, 2143c1d255d3SCy Schubert MAC2STR(src)); 2144c1d255d3SCy Schubert 2145c1d255d3SCy Schubert csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, 2146c1d255d3SCy Schubert &csign_hash_len); 2147c1d255d3SCy Schubert if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { 2148c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL 2149c1d255d3SCy Schubert "Missing or invalid required Configurator C-sign key Hash attribute"); 2150c1d255d3SCy Schubert return; 2151c1d255d3SCy Schubert } 2152c1d255d3SCy Schubert wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", 2153c1d255d3SCy Schubert csign_hash, csign_hash_len); 2154c1d255d3SCy Schubert conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash); 2155c1d255d3SCy Schubert if (!conf) { 2156c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2157c1d255d3SCy Schubert "DPP: No matching Configurator information found"); 2158c1d255d3SCy Schubert return; 2159c1d255d3SCy Schubert } 2160c1d255d3SCy Schubert 2161c1d255d3SCy Schubert fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, 2162c1d255d3SCy Schubert &fcgroup_len); 2163c1d255d3SCy Schubert if (!fcgroup || fcgroup_len != 2) { 2164c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL 2165c1d255d3SCy Schubert "Missing or invalid required Finite Cyclic Group attribute"); 2166c1d255d3SCy Schubert return; 2167c1d255d3SCy Schubert } 2168c1d255d3SCy Schubert group = WPA_GET_LE16(fcgroup); 2169c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); 2170c1d255d3SCy Schubert 2171c1d255d3SCy Schubert a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len); 2172c1d255d3SCy Schubert e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len); 2173c1d255d3SCy Schubert 2174c1d255d3SCy Schubert auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group, 2175c1d255d3SCy Schubert a_nonce, a_nonce_len, e_id, e_id_len); 2176c1d255d3SCy Schubert if (!auth) 2177c1d255d3SCy Schubert return; 2178c1d255d3SCy Schubert wpas_dpp_set_testing_options(wpa_s, auth); 2179c1d255d3SCy Schubert if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) { 2180c1d255d3SCy Schubert dpp_auth_deinit(auth); 2181c1d255d3SCy Schubert return; 2182c1d255d3SCy Schubert } 2183c1d255d3SCy Schubert 2184c1d255d3SCy Schubert os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); 2185c1d255d3SCy Schubert wpa_s->dpp_auth = auth; 2186c1d255d3SCy Schubert 2187c1d255d3SCy Schubert wpa_s->dpp_in_response_listen = 0; 2188c1d255d3SCy Schubert wpa_s->dpp_auth_ok_on_ack = 0; 2189c1d255d3SCy Schubert wait_time = wpa_s->max_remain_on_chan; 2190c1d255d3SCy Schubert max_wait_time = wpa_s->dpp_resp_wait_time ? 2191c1d255d3SCy Schubert wpa_s->dpp_resp_wait_time : 2000; 2192c1d255d3SCy Schubert if (wait_time > max_wait_time) 2193c1d255d3SCy Schubert wait_time = max_wait_time; 2194c1d255d3SCy Schubert wait_time += 10; /* give the driver some extra time to complete */ 2195c1d255d3SCy Schubert eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, 2196c1d255d3SCy Schubert wpas_dpp_reconfig_reply_wait_timeout, 2197c1d255d3SCy Schubert wpa_s, NULL); 2198c1d255d3SCy Schubert wait_time -= 10; 2199c1d255d3SCy Schubert 2200c1d255d3SCy Schubert wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time); 2201c1d255d3SCy Schubert 2202c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 2203c1d255d3SCy Schubert MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ); 2204c1d255d3SCy Schubert if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, 2205c1d255d3SCy Schubert wpabuf_head(auth->reconfig_req_msg), 2206c1d255d3SCy Schubert wpabuf_len(auth->reconfig_req_msg), 2207c1d255d3SCy Schubert wait_time, wpas_dpp_tx_status, 0) < 0) { 2208c1d255d3SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 2209c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 2210c1d255d3SCy Schubert } 2211c1d255d3SCy Schubert } 2212c1d255d3SCy Schubert 2213c1d255d3SCy Schubert 2214c1d255d3SCy Schubert static void 2215c1d255d3SCy Schubert wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, 2216c1d255d3SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 2217c1d255d3SCy Schubert unsigned int freq) 2218c1d255d3SCy Schubert { 2219c1d255d3SCy Schubert struct wpa_ssid *ssid; 2220c1d255d3SCy Schubert struct dpp_authentication *auth; 2221c1d255d3SCy Schubert 2222c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from " 2223c1d255d3SCy Schubert MACSTR, MAC2STR(src)); 2224c1d255d3SCy Schubert 2225c1d255d3SCy Schubert if (!wpa_s->dpp) 2226c1d255d3SCy Schubert return; 2227c1d255d3SCy Schubert if (wpa_s->dpp_auth) { 2228c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2229c1d255d3SCy Schubert "DPP: Not ready for reconfiguration - pending authentication exchange in progress"); 2230c1d255d3SCy Schubert return; 2231c1d255d3SCy Schubert } 2232c1d255d3SCy Schubert if (!wpa_s->dpp_reconfig_ssid) { 2233c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2234c1d255d3SCy Schubert "DPP: Not ready for reconfiguration - not requested"); 2235c1d255d3SCy Schubert return; 2236c1d255d3SCy Schubert } 2237c1d255d3SCy Schubert for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 2238c1d255d3SCy Schubert if (ssid == wpa_s->dpp_reconfig_ssid && 2239c1d255d3SCy Schubert ssid->id == wpa_s->dpp_reconfig_ssid_id) 2240c1d255d3SCy Schubert break; 2241c1d255d3SCy Schubert } 2242c1d255d3SCy Schubert if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey || 2243c1d255d3SCy Schubert !ssid->dpp_csign) { 2244c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2245c1d255d3SCy Schubert "DPP: Not ready for reconfiguration - no matching network profile with Connector found"); 2246c1d255d3SCy Schubert return; 2247c1d255d3SCy Schubert } 2248c1d255d3SCy Schubert 2249c1d255d3SCy Schubert auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector, 2250c1d255d3SCy Schubert ssid->dpp_netaccesskey, 2251c1d255d3SCy Schubert ssid->dpp_netaccesskey_len, 2252c1d255d3SCy Schubert ssid->dpp_csign, ssid->dpp_csign_len, 2253c1d255d3SCy Schubert freq, hdr, buf, len); 2254c1d255d3SCy Schubert if (!auth) 2255c1d255d3SCy Schubert return; 2256c1d255d3SCy Schubert os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); 2257c1d255d3SCy Schubert wpa_s->dpp_auth = auth; 2258c1d255d3SCy Schubert 2259c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 2260c1d255d3SCy Schubert 2261c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 2262c1d255d3SCy Schubert MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP); 2263c1d255d3SCy Schubert if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, 2264c1d255d3SCy Schubert wpabuf_head(auth->reconfig_resp_msg), 2265c1d255d3SCy Schubert wpabuf_len(auth->reconfig_resp_msg), 2266c1d255d3SCy Schubert 500, wpas_dpp_tx_status, 0) < 0) { 2267c1d255d3SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 2268c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 2269c1d255d3SCy Schubert } 2270c1d255d3SCy Schubert } 2271c1d255d3SCy Schubert 2272c1d255d3SCy Schubert 2273c1d255d3SCy Schubert static void 2274c1d255d3SCy Schubert wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, 2275c1d255d3SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 2276c1d255d3SCy Schubert unsigned int freq) 2277c1d255d3SCy Schubert { 2278c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 2279c1d255d3SCy Schubert struct wpabuf *conf; 2280c1d255d3SCy Schubert 2281c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from " 2282c1d255d3SCy Schubert MACSTR, MAC2STR(src)); 2283c1d255d3SCy Schubert 2284c1d255d3SCy Schubert if (!auth || !auth->reconfig || !auth->configurator) { 2285c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2286c1d255d3SCy Schubert "DPP: No DPP Reconfig Authentication in progress - drop"); 2287c1d255d3SCy Schubert return; 2288c1d255d3SCy Schubert } 2289c1d255d3SCy Schubert 2290c1d255d3SCy Schubert if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { 2291c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " 2292c1d255d3SCy Schubert MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); 2293c1d255d3SCy Schubert return; 2294c1d255d3SCy Schubert } 2295c1d255d3SCy Schubert 2296c1d255d3SCy Schubert conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); 2297c1d255d3SCy Schubert if (!conf) 2298c1d255d3SCy Schubert return; 2299c1d255d3SCy Schubert 2300c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL); 2301c1d255d3SCy Schubert 2302c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 2303c1d255d3SCy Schubert MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF); 2304c1d255d3SCy Schubert if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, 2305c1d255d3SCy Schubert wpabuf_head(conf), wpabuf_len(conf), 2306c1d255d3SCy Schubert 500, wpas_dpp_tx_status, 0) < 0) { 2307c1d255d3SCy Schubert wpabuf_free(conf); 2308c1d255d3SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 2309c1d255d3SCy Schubert wpa_s->dpp_auth = NULL; 2310c1d255d3SCy Schubert return; 2311c1d255d3SCy Schubert } 2312c1d255d3SCy Schubert wpabuf_free(conf); 2313c1d255d3SCy Schubert 2314c1d255d3SCy Schubert wpas_dpp_start_gas_server(wpa_s); 2315c1d255d3SCy Schubert } 2316c1d255d3SCy Schubert 2317c1d255d3SCy Schubert 2318c1d255d3SCy Schubert static void 2319c1d255d3SCy Schubert wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src, 2320c1d255d3SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 2321c1d255d3SCy Schubert unsigned int freq) 2322c1d255d3SCy Schubert { 2323c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 2324c1d255d3SCy Schubert 2325c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from " 2326c1d255d3SCy Schubert MACSTR, MAC2STR(src)); 2327c1d255d3SCy Schubert 2328c1d255d3SCy Schubert if (!auth || !auth->reconfig || auth->configurator) { 2329c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2330c1d255d3SCy Schubert "DPP: No DPP Reconfig Authentication in progress - drop"); 2331c1d255d3SCy Schubert return; 2332c1d255d3SCy Schubert } 2333c1d255d3SCy Schubert 2334c1d255d3SCy Schubert if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { 2335c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " 2336c1d255d3SCy Schubert MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); 2337c1d255d3SCy Schubert return; 2338c1d255d3SCy Schubert } 2339c1d255d3SCy Schubert 2340c1d255d3SCy Schubert if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0) 2341c1d255d3SCy Schubert return; 2342c1d255d3SCy Schubert 2343c1d255d3SCy Schubert wpas_dpp_start_gas_client(wpa_s); 2344206b73d0SCy Schubert } 2345206b73d0SCy Schubert 23464bc52338SCy Schubert #endif /* CONFIG_DPP2 */ 23474bc52338SCy Schubert 23484bc52338SCy Schubert 234985732ac8SCy Schubert static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s, 235085732ac8SCy Schubert const u8 *src, 235185732ac8SCy Schubert const u8 *buf, size_t len) 235285732ac8SCy Schubert { 235385732ac8SCy Schubert struct wpa_ssid *ssid; 235485732ac8SCy Schubert const u8 *connector, *trans_id, *status; 235585732ac8SCy Schubert u16 connector_len, trans_id_len, status_len; 2356c1d255d3SCy Schubert #ifdef CONFIG_DPP2 2357c1d255d3SCy Schubert const u8 *version; 2358c1d255d3SCy Schubert u16 version_len; 2359c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 2360c1d255d3SCy Schubert u8 peer_version = 1; 236185732ac8SCy Schubert struct dpp_introduction intro; 236285732ac8SCy Schubert struct rsn_pmksa_cache_entry *entry; 236385732ac8SCy Schubert struct os_time now; 236485732ac8SCy Schubert struct os_reltime rnow; 236585732ac8SCy Schubert os_time_t expiry; 236685732ac8SCy Schubert unsigned int seconds; 236785732ac8SCy Schubert enum dpp_status_error res; 236885732ac8SCy Schubert 236985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Response from " MACSTR, 237085732ac8SCy Schubert MAC2STR(src)); 237185732ac8SCy Schubert if (is_zero_ether_addr(wpa_s->dpp_intro_bssid) || 237285732ac8SCy Schubert os_memcmp(src, wpa_s->dpp_intro_bssid, ETH_ALEN) != 0) { 237385732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Not waiting for response from " 237485732ac8SCy Schubert MACSTR " - drop", MAC2STR(src)); 237585732ac8SCy Schubert return; 237685732ac8SCy Schubert } 237785732ac8SCy Schubert offchannel_send_action_done(wpa_s); 237885732ac8SCy Schubert 237985732ac8SCy Schubert for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 238085732ac8SCy Schubert if (ssid == wpa_s->dpp_intro_network) 238185732ac8SCy Schubert break; 238285732ac8SCy Schubert } 238385732ac8SCy Schubert if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey || 238485732ac8SCy Schubert !ssid->dpp_csign) { 238585732ac8SCy Schubert wpa_printf(MSG_DEBUG, 238685732ac8SCy Schubert "DPP: Profile not found for network introduction"); 238785732ac8SCy Schubert return; 238885732ac8SCy Schubert } 238985732ac8SCy Schubert 239085732ac8SCy Schubert trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID, 239185732ac8SCy Schubert &trans_id_len); 239285732ac8SCy Schubert if (!trans_id || trans_id_len != 1) { 239385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 239485732ac8SCy Schubert "DPP: Peer did not include Transaction ID"); 239585732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR 239685732ac8SCy Schubert " fail=missing_transaction_id", MAC2STR(src)); 239785732ac8SCy Schubert goto fail; 239885732ac8SCy Schubert } 239985732ac8SCy Schubert if (trans_id[0] != TRANSACTION_ID) { 240085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 240185732ac8SCy Schubert "DPP: Ignore frame with unexpected Transaction ID %u", 240285732ac8SCy Schubert trans_id[0]); 240385732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR 240485732ac8SCy Schubert " fail=transaction_id_mismatch", MAC2STR(src)); 240585732ac8SCy Schubert goto fail; 240685732ac8SCy Schubert } 240785732ac8SCy Schubert 240885732ac8SCy Schubert status = dpp_get_attr(buf, len, DPP_ATTR_STATUS, &status_len); 240985732ac8SCy Schubert if (!status || status_len != 1) { 241085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Peer did not include Status"); 241185732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR 241285732ac8SCy Schubert " fail=missing_status", MAC2STR(src)); 241385732ac8SCy Schubert goto fail; 241485732ac8SCy Schubert } 241585732ac8SCy Schubert if (status[0] != DPP_STATUS_OK) { 241685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 241785732ac8SCy Schubert "DPP: Peer rejected network introduction: Status %u", 241885732ac8SCy Schubert status[0]); 241985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR 242085732ac8SCy Schubert " status=%u", MAC2STR(src), status[0]); 2421c1d255d3SCy Schubert #ifdef CONFIG_DPP2 2422c1d255d3SCy Schubert wpas_dpp_send_conn_status_result(wpa_s, status[0]); 2423c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 242485732ac8SCy Schubert goto fail; 242585732ac8SCy Schubert } 242685732ac8SCy Schubert 242785732ac8SCy Schubert connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len); 242885732ac8SCy Schubert if (!connector) { 242985732ac8SCy Schubert wpa_printf(MSG_DEBUG, 243085732ac8SCy Schubert "DPP: Peer did not include its Connector"); 243185732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR 243285732ac8SCy Schubert " fail=missing_connector", MAC2STR(src)); 243385732ac8SCy Schubert goto fail; 243485732ac8SCy Schubert } 243585732ac8SCy Schubert 243685732ac8SCy Schubert res = dpp_peer_intro(&intro, ssid->dpp_connector, 243785732ac8SCy Schubert ssid->dpp_netaccesskey, 243885732ac8SCy Schubert ssid->dpp_netaccesskey_len, 243985732ac8SCy Schubert ssid->dpp_csign, 244085732ac8SCy Schubert ssid->dpp_csign_len, 244185732ac8SCy Schubert connector, connector_len, &expiry); 244285732ac8SCy Schubert if (res != DPP_STATUS_OK) { 244385732ac8SCy Schubert wpa_printf(MSG_INFO, 244485732ac8SCy Schubert "DPP: Network Introduction protocol resulted in failure"); 244585732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR 244685732ac8SCy Schubert " fail=peer_connector_validation_failed", MAC2STR(src)); 2447c1d255d3SCy Schubert #ifdef CONFIG_DPP2 2448c1d255d3SCy Schubert wpas_dpp_send_conn_status_result(wpa_s, res); 2449c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 245085732ac8SCy Schubert goto fail; 245185732ac8SCy Schubert } 245285732ac8SCy Schubert 245385732ac8SCy Schubert entry = os_zalloc(sizeof(*entry)); 245485732ac8SCy Schubert if (!entry) 245585732ac8SCy Schubert goto fail; 245685732ac8SCy Schubert os_memcpy(entry->aa, src, ETH_ALEN); 245785732ac8SCy Schubert os_memcpy(entry->pmkid, intro.pmkid, PMKID_LEN); 245885732ac8SCy Schubert os_memcpy(entry->pmk, intro.pmk, intro.pmk_len); 245985732ac8SCy Schubert entry->pmk_len = intro.pmk_len; 246085732ac8SCy Schubert entry->akmp = WPA_KEY_MGMT_DPP; 2461c1d255d3SCy Schubert #ifdef CONFIG_DPP2 2462c1d255d3SCy Schubert version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION, 2463c1d255d3SCy Schubert &version_len); 2464c1d255d3SCy Schubert if (version && version_len >= 1) 2465c1d255d3SCy Schubert peer_version = version[0]; 2466*32a95656SCy Schubert #ifdef CONFIG_DPP3 2467*32a95656SCy Schubert if (intro.peer_version && intro.peer_version >= 2 && 2468*32a95656SCy Schubert peer_version != intro.peer_version) { 2469*32a95656SCy Schubert wpa_printf(MSG_INFO, 2470*32a95656SCy Schubert "DPP: Protocol version mismatch (Connector: %d Attribute: %d", 2471*32a95656SCy Schubert intro.peer_version, peer_version); 2472*32a95656SCy Schubert wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH); 2473*32a95656SCy Schubert goto fail; 2474*32a95656SCy Schubert } 2475*32a95656SCy Schubert #endif /* CONFIG_DPP3 */ 2476c1d255d3SCy Schubert entry->dpp_pfs = peer_version >= 2; 2477c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 247885732ac8SCy Schubert if (expiry) { 247985732ac8SCy Schubert os_get_time(&now); 248085732ac8SCy Schubert seconds = expiry - now.sec; 248185732ac8SCy Schubert } else { 248285732ac8SCy Schubert seconds = 86400 * 7; 248385732ac8SCy Schubert } 248485732ac8SCy Schubert os_get_reltime(&rnow); 248585732ac8SCy Schubert entry->expiration = rnow.sec + seconds; 248685732ac8SCy Schubert entry->reauth_time = rnow.sec + seconds; 248785732ac8SCy Schubert entry->network_ctx = ssid; 248885732ac8SCy Schubert wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry); 248985732ac8SCy Schubert 249085732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR 2491c1d255d3SCy Schubert " status=%u version=%u", MAC2STR(src), status[0], peer_version); 249285732ac8SCy Schubert 249385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 249485732ac8SCy Schubert "DPP: Try connection again after successful network introduction"); 249585732ac8SCy Schubert if (wpa_supplicant_fast_associate(wpa_s) != 1) { 249685732ac8SCy Schubert wpa_supplicant_cancel_sched_scan(wpa_s); 249785732ac8SCy Schubert wpa_supplicant_req_scan(wpa_s, 0, 0); 249885732ac8SCy Schubert } 249985732ac8SCy Schubert fail: 250085732ac8SCy Schubert os_memset(&intro, 0, sizeof(intro)); 250185732ac8SCy Schubert } 250285732ac8SCy Schubert 250385732ac8SCy Schubert 250485732ac8SCy Schubert static int wpas_dpp_allow_ir(struct wpa_supplicant *wpa_s, unsigned int freq) 250585732ac8SCy Schubert { 250685732ac8SCy Schubert int i, j; 250785732ac8SCy Schubert 250885732ac8SCy Schubert if (!wpa_s->hw.modes) 250985732ac8SCy Schubert return -1; 251085732ac8SCy Schubert 251185732ac8SCy Schubert for (i = 0; i < wpa_s->hw.num_modes; i++) { 251285732ac8SCy Schubert struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i]; 251385732ac8SCy Schubert 251485732ac8SCy Schubert for (j = 0; j < mode->num_channels; j++) { 251585732ac8SCy Schubert struct hostapd_channel_data *chan = &mode->channels[j]; 251685732ac8SCy Schubert 251785732ac8SCy Schubert if (chan->freq != (int) freq) 251885732ac8SCy Schubert continue; 251985732ac8SCy Schubert 252085732ac8SCy Schubert if (chan->flag & (HOSTAPD_CHAN_DISABLED | 252185732ac8SCy Schubert HOSTAPD_CHAN_NO_IR | 252285732ac8SCy Schubert HOSTAPD_CHAN_RADAR)) 252385732ac8SCy Schubert continue; 252485732ac8SCy Schubert 252585732ac8SCy Schubert return 1; 252685732ac8SCy Schubert } 252785732ac8SCy Schubert } 252885732ac8SCy Schubert 252985732ac8SCy Schubert wpa_printf(MSG_DEBUG, 253085732ac8SCy Schubert "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list", 253185732ac8SCy Schubert freq); 253285732ac8SCy Schubert 253385732ac8SCy Schubert return 0; 253485732ac8SCy Schubert } 253585732ac8SCy Schubert 253685732ac8SCy Schubert 253785732ac8SCy Schubert static int wpas_dpp_pkex_next_channel(struct wpa_supplicant *wpa_s, 253885732ac8SCy Schubert struct dpp_pkex *pkex) 253985732ac8SCy Schubert { 254085732ac8SCy Schubert if (pkex->freq == 2437) 254185732ac8SCy Schubert pkex->freq = 5745; 254285732ac8SCy Schubert else if (pkex->freq == 5745) 254385732ac8SCy Schubert pkex->freq = 5220; 254485732ac8SCy Schubert else if (pkex->freq == 5220) 254585732ac8SCy Schubert pkex->freq = 60480; 254685732ac8SCy Schubert else 254785732ac8SCy Schubert return -1; /* no more channels to try */ 254885732ac8SCy Schubert 254985732ac8SCy Schubert if (wpas_dpp_allow_ir(wpa_s, pkex->freq) == 1) { 255085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz", 255185732ac8SCy Schubert pkex->freq); 255285732ac8SCy Schubert return 0; 255385732ac8SCy Schubert } 255485732ac8SCy Schubert 255585732ac8SCy Schubert /* Could not use this channel - try the next one */ 255685732ac8SCy Schubert return wpas_dpp_pkex_next_channel(wpa_s, pkex); 255785732ac8SCy Schubert } 255885732ac8SCy Schubert 255985732ac8SCy Schubert 256085732ac8SCy Schubert static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx) 256185732ac8SCy Schubert { 256285732ac8SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 256385732ac8SCy Schubert struct dpp_pkex *pkex = wpa_s->dpp_pkex; 256485732ac8SCy Schubert 256585732ac8SCy Schubert if (!pkex || !pkex->exchange_req) 256685732ac8SCy Schubert return; 256785732ac8SCy Schubert if (pkex->exch_req_tries >= 5) { 256885732ac8SCy Schubert if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) { 256985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL 257085732ac8SCy Schubert "No response from PKEX peer"); 257185732ac8SCy Schubert dpp_pkex_free(pkex); 257285732ac8SCy Schubert wpa_s->dpp_pkex = NULL; 257385732ac8SCy Schubert return; 257485732ac8SCy Schubert } 257585732ac8SCy Schubert pkex->exch_req_tries = 0; 257685732ac8SCy Schubert } 257785732ac8SCy Schubert 257885732ac8SCy Schubert pkex->exch_req_tries++; 257985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)", 258085732ac8SCy Schubert pkex->exch_req_tries); 258185732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 2582*32a95656SCy Schubert MAC2STR(broadcast), pkex->freq, 2583*32a95656SCy Schubert pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ : 2584*32a95656SCy Schubert DPP_PA_PKEX_V1_EXCHANGE_REQ); 258585732ac8SCy Schubert offchannel_send_action(wpa_s, pkex->freq, broadcast, 258685732ac8SCy Schubert wpa_s->own_addr, broadcast, 258785732ac8SCy Schubert wpabuf_head(pkex->exchange_req), 258885732ac8SCy Schubert wpabuf_len(pkex->exchange_req), 258985732ac8SCy Schubert pkex->exch_req_wait_time, 259085732ac8SCy Schubert wpas_dpp_tx_pkex_status, 0); 259185732ac8SCy Schubert } 259285732ac8SCy Schubert 259385732ac8SCy Schubert 259485732ac8SCy Schubert static void 259585732ac8SCy Schubert wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s, 259685732ac8SCy Schubert unsigned int freq, const u8 *dst, 259785732ac8SCy Schubert const u8 *src, const u8 *bssid, 259885732ac8SCy Schubert const u8 *data, size_t data_len, 259985732ac8SCy Schubert enum offchannel_send_action_result result) 260085732ac8SCy Schubert { 260185732ac8SCy Schubert const char *res_txt; 260285732ac8SCy Schubert struct dpp_pkex *pkex = wpa_s->dpp_pkex; 260385732ac8SCy Schubert 260485732ac8SCy Schubert res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" : 260585732ac8SCy Schubert (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" : 260685732ac8SCy Schubert "FAILED"); 260785732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR 260885732ac8SCy Schubert " result=%s (PKEX)", 260985732ac8SCy Schubert freq, MAC2STR(dst), res_txt); 261085732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR 261185732ac8SCy Schubert " freq=%u result=%s", MAC2STR(dst), freq, res_txt); 261285732ac8SCy Schubert 261385732ac8SCy Schubert if (!pkex) { 261485732ac8SCy Schubert wpa_printf(MSG_DEBUG, 261585732ac8SCy Schubert "DPP: Ignore TX status since there is no ongoing PKEX exchange"); 261685732ac8SCy Schubert return; 261785732ac8SCy Schubert } 261885732ac8SCy Schubert 261985732ac8SCy Schubert if (pkex->failed) { 262085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 262185732ac8SCy Schubert "DPP: Terminate PKEX exchange due to an earlier error"); 262285732ac8SCy Schubert if (pkex->t > pkex->own_bi->pkex_t) 262385732ac8SCy Schubert pkex->own_bi->pkex_t = pkex->t; 262485732ac8SCy Schubert dpp_pkex_free(pkex); 262585732ac8SCy Schubert wpa_s->dpp_pkex = NULL; 262685732ac8SCy Schubert return; 262785732ac8SCy Schubert } 262885732ac8SCy Schubert 262985732ac8SCy Schubert if (pkex->exch_req_wait_time && pkex->exchange_req) { 263085732ac8SCy Schubert /* Wait for PKEX Exchange Response frame and retry request if 263185732ac8SCy Schubert * no response is seen. */ 263285732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL); 263385732ac8SCy Schubert eloop_register_timeout(pkex->exch_req_wait_time / 1000, 263485732ac8SCy Schubert (pkex->exch_req_wait_time % 1000) * 1000, 263585732ac8SCy Schubert wpas_dpp_pkex_retry_timeout, wpa_s, 263685732ac8SCy Schubert NULL); 263785732ac8SCy Schubert } 263885732ac8SCy Schubert } 263985732ac8SCy Schubert 264085732ac8SCy Schubert 264185732ac8SCy Schubert static void 264285732ac8SCy Schubert wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src, 2643*32a95656SCy Schubert const u8 *buf, size_t len, unsigned int freq, 2644*32a95656SCy Schubert bool v2) 264585732ac8SCy Schubert { 264685732ac8SCy Schubert struct wpabuf *msg; 264785732ac8SCy Schubert unsigned int wait_time; 264885732ac8SCy Schubert 264985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR, 265085732ac8SCy Schubert MAC2STR(src)); 265185732ac8SCy Schubert 265285732ac8SCy Schubert /* TODO: Support multiple PKEX codes by iterating over all the enabled 265385732ac8SCy Schubert * values here */ 265485732ac8SCy Schubert 265585732ac8SCy Schubert if (!wpa_s->dpp_pkex_code || !wpa_s->dpp_pkex_bi) { 265685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 265785732ac8SCy Schubert "DPP: No PKEX code configured - ignore request"); 265885732ac8SCy Schubert return; 265985732ac8SCy Schubert } 266085732ac8SCy Schubert 266185732ac8SCy Schubert if (wpa_s->dpp_pkex) { 266285732ac8SCy Schubert /* TODO: Support parallel operations */ 266385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 266485732ac8SCy Schubert "DPP: Already in PKEX session - ignore new request"); 266585732ac8SCy Schubert return; 266685732ac8SCy Schubert } 266785732ac8SCy Schubert 266885732ac8SCy Schubert wpa_s->dpp_pkex = dpp_pkex_rx_exchange_req(wpa_s, wpa_s->dpp_pkex_bi, 266985732ac8SCy Schubert wpa_s->own_addr, src, 267085732ac8SCy Schubert wpa_s->dpp_pkex_identifier, 267185732ac8SCy Schubert wpa_s->dpp_pkex_code, 2672*32a95656SCy Schubert buf, len, v2); 267385732ac8SCy Schubert if (!wpa_s->dpp_pkex) { 267485732ac8SCy Schubert wpa_printf(MSG_DEBUG, 267585732ac8SCy Schubert "DPP: Failed to process the request - ignore it"); 267685732ac8SCy Schubert return; 267785732ac8SCy Schubert } 267885732ac8SCy Schubert 267985732ac8SCy Schubert msg = wpa_s->dpp_pkex->exchange_resp; 268085732ac8SCy Schubert wait_time = wpa_s->max_remain_on_chan; 268185732ac8SCy Schubert if (wait_time > 2000) 268285732ac8SCy Schubert wait_time = 2000; 268385732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 268485732ac8SCy Schubert MAC2STR(src), freq, DPP_PA_PKEX_EXCHANGE_RESP); 268585732ac8SCy Schubert offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, 268685732ac8SCy Schubert broadcast, 268785732ac8SCy Schubert wpabuf_head(msg), wpabuf_len(msg), 268885732ac8SCy Schubert wait_time, wpas_dpp_tx_pkex_status, 0); 268985732ac8SCy Schubert } 269085732ac8SCy Schubert 269185732ac8SCy Schubert 269285732ac8SCy Schubert static void 269385732ac8SCy Schubert wpas_dpp_rx_pkex_exchange_resp(struct wpa_supplicant *wpa_s, const u8 *src, 269485732ac8SCy Schubert const u8 *buf, size_t len, unsigned int freq) 269585732ac8SCy Schubert { 269685732ac8SCy Schubert struct wpabuf *msg; 269785732ac8SCy Schubert unsigned int wait_time; 269885732ac8SCy Schubert 269985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR, 270085732ac8SCy Schubert MAC2STR(src)); 270185732ac8SCy Schubert 270285732ac8SCy Schubert /* TODO: Support multiple PKEX codes by iterating over all the enabled 270385732ac8SCy Schubert * values here */ 270485732ac8SCy Schubert 270585732ac8SCy Schubert if (!wpa_s->dpp_pkex || !wpa_s->dpp_pkex->initiator || 270685732ac8SCy Schubert wpa_s->dpp_pkex->exchange_done) { 270785732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); 270885732ac8SCy Schubert return; 270985732ac8SCy Schubert } 271085732ac8SCy Schubert 271185732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL); 271285732ac8SCy Schubert wpa_s->dpp_pkex->exch_req_wait_time = 0; 271385732ac8SCy Schubert 271485732ac8SCy Schubert msg = dpp_pkex_rx_exchange_resp(wpa_s->dpp_pkex, src, buf, len); 271585732ac8SCy Schubert if (!msg) { 271685732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to process the response"); 271785732ac8SCy Schubert return; 271885732ac8SCy Schubert } 271985732ac8SCy Schubert 272085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR, 272185732ac8SCy Schubert MAC2STR(src)); 272285732ac8SCy Schubert 272385732ac8SCy Schubert wait_time = wpa_s->max_remain_on_chan; 272485732ac8SCy Schubert if (wait_time > 2000) 272585732ac8SCy Schubert wait_time = 2000; 272685732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 272785732ac8SCy Schubert MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_REQ); 272885732ac8SCy Schubert offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, 272985732ac8SCy Schubert broadcast, 273085732ac8SCy Schubert wpabuf_head(msg), wpabuf_len(msg), 273185732ac8SCy Schubert wait_time, wpas_dpp_tx_pkex_status, 0); 273285732ac8SCy Schubert wpabuf_free(msg); 273385732ac8SCy Schubert } 273485732ac8SCy Schubert 273585732ac8SCy Schubert 273685732ac8SCy Schubert static struct dpp_bootstrap_info * 273785732ac8SCy Schubert wpas_dpp_pkex_finish(struct wpa_supplicant *wpa_s, const u8 *peer, 273885732ac8SCy Schubert unsigned int freq) 273985732ac8SCy Schubert { 274085732ac8SCy Schubert struct dpp_bootstrap_info *bi; 274185732ac8SCy Schubert 27424bc52338SCy Schubert bi = dpp_pkex_finish(wpa_s->dpp, wpa_s->dpp_pkex, peer, freq); 274385732ac8SCy Schubert if (!bi) 274485732ac8SCy Schubert return NULL; 274585732ac8SCy Schubert wpa_s->dpp_pkex = NULL; 274685732ac8SCy Schubert return bi; 274785732ac8SCy Schubert } 274885732ac8SCy Schubert 274985732ac8SCy Schubert 275085732ac8SCy Schubert static void 275185732ac8SCy Schubert wpas_dpp_rx_pkex_commit_reveal_req(struct wpa_supplicant *wpa_s, const u8 *src, 275285732ac8SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 275385732ac8SCy Schubert unsigned int freq) 275485732ac8SCy Schubert { 275585732ac8SCy Schubert struct wpabuf *msg; 275685732ac8SCy Schubert unsigned int wait_time; 275785732ac8SCy Schubert struct dpp_pkex *pkex = wpa_s->dpp_pkex; 275885732ac8SCy Schubert 275985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR, 276085732ac8SCy Schubert MAC2STR(src)); 276185732ac8SCy Schubert 276285732ac8SCy Schubert if (!pkex || pkex->initiator || !pkex->exchange_done) { 276385732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); 276485732ac8SCy Schubert return; 276585732ac8SCy Schubert } 276685732ac8SCy Schubert 276785732ac8SCy Schubert msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len); 276885732ac8SCy Schubert if (!msg) { 276985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to process the request"); 277085732ac8SCy Schubert if (pkex->failed) { 277185732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange"); 277285732ac8SCy Schubert if (pkex->t > pkex->own_bi->pkex_t) 277385732ac8SCy Schubert pkex->own_bi->pkex_t = pkex->t; 277485732ac8SCy Schubert dpp_pkex_free(wpa_s->dpp_pkex); 277585732ac8SCy Schubert wpa_s->dpp_pkex = NULL; 277685732ac8SCy Schubert } 277785732ac8SCy Schubert return; 277885732ac8SCy Schubert } 277985732ac8SCy Schubert 278085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to " 278185732ac8SCy Schubert MACSTR, MAC2STR(src)); 278285732ac8SCy Schubert 278385732ac8SCy Schubert wait_time = wpa_s->max_remain_on_chan; 278485732ac8SCy Schubert if (wait_time > 2000) 278585732ac8SCy Schubert wait_time = 2000; 278685732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 278785732ac8SCy Schubert MAC2STR(src), freq, DPP_PA_PKEX_COMMIT_REVEAL_RESP); 278885732ac8SCy Schubert offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, 278985732ac8SCy Schubert broadcast, 279085732ac8SCy Schubert wpabuf_head(msg), wpabuf_len(msg), 279185732ac8SCy Schubert wait_time, wpas_dpp_tx_pkex_status, 0); 279285732ac8SCy Schubert wpabuf_free(msg); 279385732ac8SCy Schubert 279485732ac8SCy Schubert wpas_dpp_pkex_finish(wpa_s, src, freq); 279585732ac8SCy Schubert } 279685732ac8SCy Schubert 279785732ac8SCy Schubert 279885732ac8SCy Schubert static void 279985732ac8SCy Schubert wpas_dpp_rx_pkex_commit_reveal_resp(struct wpa_supplicant *wpa_s, const u8 *src, 280085732ac8SCy Schubert const u8 *hdr, const u8 *buf, size_t len, 280185732ac8SCy Schubert unsigned int freq) 280285732ac8SCy Schubert { 280385732ac8SCy Schubert int res; 280485732ac8SCy Schubert struct dpp_bootstrap_info *bi; 280585732ac8SCy Schubert struct dpp_pkex *pkex = wpa_s->dpp_pkex; 280685732ac8SCy Schubert char cmd[500]; 280785732ac8SCy Schubert 280885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR, 280985732ac8SCy Schubert MAC2STR(src)); 281085732ac8SCy Schubert 281185732ac8SCy Schubert if (!pkex || !pkex->initiator || !pkex->exchange_done) { 281285732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); 281385732ac8SCy Schubert return; 281485732ac8SCy Schubert } 281585732ac8SCy Schubert 281685732ac8SCy Schubert res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len); 281785732ac8SCy Schubert if (res < 0) { 281885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to process the response"); 281985732ac8SCy Schubert return; 282085732ac8SCy Schubert } 282185732ac8SCy Schubert 282285732ac8SCy Schubert bi = wpas_dpp_pkex_finish(wpa_s, src, freq); 282385732ac8SCy Schubert if (!bi) 282485732ac8SCy Schubert return; 282585732ac8SCy Schubert 282685732ac8SCy Schubert os_snprintf(cmd, sizeof(cmd), " peer=%u %s", 282785732ac8SCy Schubert bi->id, 282885732ac8SCy Schubert wpa_s->dpp_pkex_auth_cmd ? wpa_s->dpp_pkex_auth_cmd : ""); 282985732ac8SCy Schubert wpa_printf(MSG_DEBUG, 283085732ac8SCy Schubert "DPP: Start authentication after PKEX with parameters: %s", 283185732ac8SCy Schubert cmd); 283285732ac8SCy Schubert if (wpas_dpp_auth_init(wpa_s, cmd) < 0) { 283385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 283485732ac8SCy Schubert "DPP: Authentication initialization failed"); 2835c1d255d3SCy Schubert offchannel_send_action_done(wpa_s); 283685732ac8SCy Schubert return; 283785732ac8SCy Schubert } 283885732ac8SCy Schubert } 283985732ac8SCy Schubert 284085732ac8SCy Schubert 284185732ac8SCy Schubert void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, 284285732ac8SCy Schubert const u8 *buf, size_t len, unsigned int freq) 284385732ac8SCy Schubert { 284485732ac8SCy Schubert u8 crypto_suite; 284585732ac8SCy Schubert enum dpp_public_action_frame_type type; 284685732ac8SCy Schubert const u8 *hdr; 284785732ac8SCy Schubert unsigned int pkex_t; 284885732ac8SCy Schubert 284985732ac8SCy Schubert if (len < DPP_HDR_LEN) 285085732ac8SCy Schubert return; 285185732ac8SCy Schubert if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE) 285285732ac8SCy Schubert return; 285385732ac8SCy Schubert hdr = buf; 285485732ac8SCy Schubert buf += 4; 285585732ac8SCy Schubert len -= 4; 285685732ac8SCy Schubert crypto_suite = *buf++; 285785732ac8SCy Schubert type = *buf++; 285885732ac8SCy Schubert len -= 2; 285985732ac8SCy Schubert 286085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 286185732ac8SCy Schubert "DPP: Received DPP Public Action frame crypto suite %u type %d from " 286285732ac8SCy Schubert MACSTR " freq=%u", 286385732ac8SCy Schubert crypto_suite, type, MAC2STR(src), freq); 286485732ac8SCy Schubert if (crypto_suite != 1) { 286585732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u", 286685732ac8SCy Schubert crypto_suite); 286785732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR 286885732ac8SCy Schubert " freq=%u type=%d ignore=unsupported-crypto-suite", 286985732ac8SCy Schubert MAC2STR(src), freq, type); 287085732ac8SCy Schubert return; 287185732ac8SCy Schubert } 287285732ac8SCy Schubert wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len); 287385732ac8SCy Schubert if (dpp_check_attrs(buf, len) < 0) { 287485732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR 287585732ac8SCy Schubert " freq=%u type=%d ignore=invalid-attributes", 287685732ac8SCy Schubert MAC2STR(src), freq, type); 287785732ac8SCy Schubert return; 287885732ac8SCy Schubert } 287985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d", 288085732ac8SCy Schubert MAC2STR(src), freq, type); 288185732ac8SCy Schubert 288285732ac8SCy Schubert switch (type) { 288385732ac8SCy Schubert case DPP_PA_AUTHENTICATION_REQ: 288485732ac8SCy Schubert wpas_dpp_rx_auth_req(wpa_s, src, hdr, buf, len, freq); 288585732ac8SCy Schubert break; 288685732ac8SCy Schubert case DPP_PA_AUTHENTICATION_RESP: 288785732ac8SCy Schubert wpas_dpp_rx_auth_resp(wpa_s, src, hdr, buf, len, freq); 288885732ac8SCy Schubert break; 288985732ac8SCy Schubert case DPP_PA_AUTHENTICATION_CONF: 289085732ac8SCy Schubert wpas_dpp_rx_auth_conf(wpa_s, src, hdr, buf, len); 289185732ac8SCy Schubert break; 289285732ac8SCy Schubert case DPP_PA_PEER_DISCOVERY_RESP: 289385732ac8SCy Schubert wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len); 289485732ac8SCy Schubert break; 2895*32a95656SCy Schubert #ifdef CONFIG_DPP3 289685732ac8SCy Schubert case DPP_PA_PKEX_EXCHANGE_REQ: 2897*32a95656SCy Schubert /* This is for PKEXv2, but for now, process only with 2898*32a95656SCy Schubert * CONFIG_DPP3 to avoid issues with a capability that has not 2899*32a95656SCy Schubert * been tested with other implementations. */ 2900*32a95656SCy Schubert wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true); 2901*32a95656SCy Schubert break; 2902*32a95656SCy Schubert #endif /* CONFIG_DPP3 */ 2903*32a95656SCy Schubert case DPP_PA_PKEX_V1_EXCHANGE_REQ: 2904*32a95656SCy Schubert wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, 2905*32a95656SCy Schubert false); 290685732ac8SCy Schubert break; 290785732ac8SCy Schubert case DPP_PA_PKEX_EXCHANGE_RESP: 290885732ac8SCy Schubert wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq); 290985732ac8SCy Schubert break; 291085732ac8SCy Schubert case DPP_PA_PKEX_COMMIT_REVEAL_REQ: 291185732ac8SCy Schubert wpas_dpp_rx_pkex_commit_reveal_req(wpa_s, src, hdr, buf, len, 291285732ac8SCy Schubert freq); 291385732ac8SCy Schubert break; 291485732ac8SCy Schubert case DPP_PA_PKEX_COMMIT_REVEAL_RESP: 291585732ac8SCy Schubert wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len, 291685732ac8SCy Schubert freq); 291785732ac8SCy Schubert break; 29184bc52338SCy Schubert #ifdef CONFIG_DPP2 29194bc52338SCy Schubert case DPP_PA_CONFIGURATION_RESULT: 29204bc52338SCy Schubert wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len); 29214bc52338SCy Schubert break; 2922c1d255d3SCy Schubert case DPP_PA_CONNECTION_STATUS_RESULT: 2923c1d255d3SCy Schubert wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len); 2924c1d255d3SCy Schubert break; 2925c1d255d3SCy Schubert case DPP_PA_PRESENCE_ANNOUNCEMENT: 2926c1d255d3SCy Schubert wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len, 2927c1d255d3SCy Schubert freq); 2928c1d255d3SCy Schubert break; 2929c1d255d3SCy Schubert case DPP_PA_RECONFIG_ANNOUNCEMENT: 2930c1d255d3SCy Schubert wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len, 2931c1d255d3SCy Schubert freq); 2932c1d255d3SCy Schubert break; 2933c1d255d3SCy Schubert case DPP_PA_RECONFIG_AUTH_REQ: 2934c1d255d3SCy Schubert wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq); 2935c1d255d3SCy Schubert break; 2936c1d255d3SCy Schubert case DPP_PA_RECONFIG_AUTH_RESP: 2937c1d255d3SCy Schubert wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq); 2938c1d255d3SCy Schubert break; 2939c1d255d3SCy Schubert case DPP_PA_RECONFIG_AUTH_CONF: 2940c1d255d3SCy Schubert wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq); 2941c1d255d3SCy Schubert break; 29424bc52338SCy Schubert #endif /* CONFIG_DPP2 */ 294385732ac8SCy Schubert default: 294485732ac8SCy Schubert wpa_printf(MSG_DEBUG, 294585732ac8SCy Schubert "DPP: Ignored unsupported frame subtype %d", type); 294685732ac8SCy Schubert break; 294785732ac8SCy Schubert } 294885732ac8SCy Schubert 294985732ac8SCy Schubert if (wpa_s->dpp_pkex) 295085732ac8SCy Schubert pkex_t = wpa_s->dpp_pkex->t; 295185732ac8SCy Schubert else if (wpa_s->dpp_pkex_bi) 295285732ac8SCy Schubert pkex_t = wpa_s->dpp_pkex_bi->pkex_t; 295385732ac8SCy Schubert else 295485732ac8SCy Schubert pkex_t = 0; 295585732ac8SCy Schubert if (pkex_t >= PKEX_COUNTER_T_LIMIT) { 295685732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0"); 295785732ac8SCy Schubert wpas_dpp_pkex_remove(wpa_s, "*"); 295885732ac8SCy Schubert } 295985732ac8SCy Schubert } 296085732ac8SCy Schubert 296185732ac8SCy Schubert 296285732ac8SCy Schubert static struct wpabuf * 2963c1d255d3SCy Schubert wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa, 2964c1d255d3SCy Schubert const u8 *query, size_t query_len, u16 *comeback_delay) 296585732ac8SCy Schubert { 296685732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 296785732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 296885732ac8SCy Schubert struct wpabuf *resp; 296985732ac8SCy Schubert 297085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, 297185732ac8SCy Schubert MAC2STR(sa)); 2972c1d255d3SCy Schubert if (!auth || (!auth->auth_success && !auth->reconfig_success) || 297385732ac8SCy Schubert os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { 297485732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); 297585732ac8SCy Schubert return NULL; 297685732ac8SCy Schubert } 2977206b73d0SCy Schubert 2978206b73d0SCy Schubert if (wpa_s->dpp_auth_ok_on_ack && auth->configurator) { 2979206b73d0SCy Schubert wpa_printf(MSG_DEBUG, 2980206b73d0SCy Schubert "DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request"); 2981206b73d0SCy Schubert /* wpas_dpp_auth_success() would normally have been called from 2982206b73d0SCy Schubert * TX status handler, but since there was no such handler call 2983206b73d0SCy Schubert * yet, simply send out the event message and proceed with 2984206b73d0SCy Schubert * exchange. */ 2985206b73d0SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=1"); 2986206b73d0SCy Schubert wpa_s->dpp_auth_ok_on_ack = 0; 2987206b73d0SCy Schubert } 2988206b73d0SCy Schubert 298985732ac8SCy Schubert wpa_hexdump(MSG_DEBUG, 299085732ac8SCy Schubert "DPP: Received Configuration Request (GAS Query Request)", 299185732ac8SCy Schubert query, query_len); 299285732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR, 299385732ac8SCy Schubert MAC2STR(sa)); 299485732ac8SCy Schubert resp = dpp_conf_req_rx(auth, query, query_len); 2995c1d255d3SCy Schubert 2996c1d255d3SCy Schubert #ifdef CONFIG_DPP2 2997c1d255d3SCy Schubert if (!resp && auth->waiting_cert) { 2998c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); 2999c1d255d3SCy Schubert auth->cert_resp_ctx = resp_ctx; 3000c1d255d3SCy Schubert *comeback_delay = 500; 3001c1d255d3SCy Schubert return NULL; 3002c1d255d3SCy Schubert } 3003c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 3004c1d255d3SCy Schubert 300585732ac8SCy Schubert if (!resp) 300685732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); 300785732ac8SCy Schubert auth->conf_resp = resp; 3008c1d255d3SCy Schubert auth->gas_server_ctx = resp_ctx; 300985732ac8SCy Schubert return resp; 301085732ac8SCy Schubert } 301185732ac8SCy Schubert 301285732ac8SCy Schubert 301385732ac8SCy Schubert static void 301485732ac8SCy Schubert wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok) 301585732ac8SCy Schubert { 301685732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 301785732ac8SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 301885732ac8SCy Schubert 301985732ac8SCy Schubert if (!auth) { 302085732ac8SCy Schubert wpabuf_free(resp); 302185732ac8SCy Schubert return; 302285732ac8SCy Schubert } 302385732ac8SCy Schubert if (auth->conf_resp != resp) { 302485732ac8SCy Schubert wpa_printf(MSG_DEBUG, 302585732ac8SCy Schubert "DPP: Ignore GAS status report (ok=%d) for unknown response", 302685732ac8SCy Schubert ok); 302785732ac8SCy Schubert wpabuf_free(resp); 302885732ac8SCy Schubert return; 302985732ac8SCy Schubert } 303085732ac8SCy Schubert 3031c1d255d3SCy Schubert #ifdef CONFIG_DPP2 3032c1d255d3SCy Schubert if (auth->waiting_csr && ok) { 3033c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR"); 3034c1d255d3SCy Schubert wpabuf_free(resp); 3035c1d255d3SCy Schubert return; 3036c1d255d3SCy Schubert } 3037c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 3038c1d255d3SCy Schubert 303985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)", 304085732ac8SCy Schubert ok); 304185732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); 3042c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL); 304385732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); 30444bc52338SCy Schubert #ifdef CONFIG_DPP2 30454bc52338SCy Schubert if (ok && auth->peer_version >= 2 && 3046c1d255d3SCy Schubert auth->conf_resp_status == DPP_STATUS_OK && 3047c1d255d3SCy Schubert !auth->waiting_conf_result) { 30484bc52338SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); 30494bc52338SCy Schubert auth->waiting_conf_result = 1; 30504bc52338SCy Schubert auth->conf_resp = NULL; 30514bc52338SCy Schubert wpabuf_free(resp); 30524bc52338SCy Schubert eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, 30534bc52338SCy Schubert wpa_s, NULL); 30544bc52338SCy Schubert eloop_register_timeout(2, 0, 30554bc52338SCy Schubert wpas_dpp_config_result_wait_timeout, 30564bc52338SCy Schubert wpa_s, NULL); 30574bc52338SCy Schubert return; 30584bc52338SCy Schubert } 30594bc52338SCy Schubert #endif /* CONFIG_DPP2 */ 306085732ac8SCy Schubert offchannel_send_action_done(wpa_s); 306185732ac8SCy Schubert wpas_dpp_listen_stop(wpa_s); 306285732ac8SCy Schubert if (ok) 306385732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT); 306485732ac8SCy Schubert else 306585732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); 306685732ac8SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 306785732ac8SCy Schubert wpa_s->dpp_auth = NULL; 306885732ac8SCy Schubert wpabuf_free(resp); 306985732ac8SCy Schubert } 307085732ac8SCy Schubert 307185732ac8SCy Schubert 307285732ac8SCy Schubert int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd) 307385732ac8SCy Schubert { 307485732ac8SCy Schubert struct dpp_authentication *auth; 307585732ac8SCy Schubert int ret = -1; 307685732ac8SCy Schubert char *curve = NULL; 307785732ac8SCy Schubert 3078c1d255d3SCy Schubert auth = dpp_alloc_auth(wpa_s->dpp, wpa_s); 307985732ac8SCy Schubert if (!auth) 308085732ac8SCy Schubert return -1; 308185732ac8SCy Schubert 308285732ac8SCy Schubert curve = get_param(cmd, " curve="); 308385732ac8SCy Schubert wpas_dpp_set_testing_options(wpa_s, auth); 3084c1d255d3SCy Schubert if (dpp_set_configurator(auth, cmd) == 0 && 30854bc52338SCy Schubert dpp_configurator_own_config(auth, curve, 0) == 0) 3086c1d255d3SCy Schubert ret = wpas_dpp_handle_config_obj(wpa_s, auth, 3087c1d255d3SCy Schubert &auth->conf_obj[0]); 3088c1d255d3SCy Schubert if (!ret) 3089c1d255d3SCy Schubert wpas_dpp_post_process_config(wpa_s, auth); 309085732ac8SCy Schubert 309185732ac8SCy Schubert dpp_auth_deinit(auth); 309285732ac8SCy Schubert os_free(curve); 309385732ac8SCy Schubert 309485732ac8SCy Schubert return ret; 309585732ac8SCy Schubert } 309685732ac8SCy Schubert 309785732ac8SCy Schubert 309885732ac8SCy Schubert static void 309985732ac8SCy Schubert wpas_dpp_tx_introduction_status(struct wpa_supplicant *wpa_s, 310085732ac8SCy Schubert unsigned int freq, const u8 *dst, 310185732ac8SCy Schubert const u8 *src, const u8 *bssid, 310285732ac8SCy Schubert const u8 *data, size_t data_len, 310385732ac8SCy Schubert enum offchannel_send_action_result result) 310485732ac8SCy Schubert { 310585732ac8SCy Schubert const char *res_txt; 310685732ac8SCy Schubert 310785732ac8SCy Schubert res_txt = result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" : 310885732ac8SCy Schubert (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" : 310985732ac8SCy Schubert "FAILED"); 311085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: TX status: freq=%u dst=" MACSTR 311185732ac8SCy Schubert " result=%s (DPP Peer Discovery Request)", 311285732ac8SCy Schubert freq, MAC2STR(dst), res_txt); 311385732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR 311485732ac8SCy Schubert " freq=%u result=%s", MAC2STR(dst), freq, res_txt); 311585732ac8SCy Schubert /* TODO: Time out wait for response more quickly in error cases? */ 311685732ac8SCy Schubert } 311785732ac8SCy Schubert 311885732ac8SCy Schubert 311985732ac8SCy Schubert int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 312085732ac8SCy Schubert struct wpa_bss *bss) 312185732ac8SCy Schubert { 312285732ac8SCy Schubert struct os_time now; 312385732ac8SCy Schubert struct wpabuf *msg; 312485732ac8SCy Schubert unsigned int wait_time; 31254bc52338SCy Schubert const u8 *rsn; 31264bc52338SCy Schubert struct wpa_ie_data ied; 3127c1d255d3SCy Schubert size_t len; 312885732ac8SCy Schubert 312985732ac8SCy Schubert if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss) 313085732ac8SCy Schubert return 0; /* Not using DPP AKM - continue */ 31314bc52338SCy Schubert rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 31324bc52338SCy Schubert if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 && 31334bc52338SCy Schubert !(ied.key_mgmt & WPA_KEY_MGMT_DPP)) 31344bc52338SCy Schubert return 0; /* AP does not support DPP AKM - continue */ 313585732ac8SCy Schubert if (wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid)) 313685732ac8SCy Schubert return 0; /* PMKSA exists for DPP AKM - continue */ 313785732ac8SCy Schubert 313885732ac8SCy Schubert if (!ssid->dpp_connector || !ssid->dpp_netaccesskey || 313985732ac8SCy Schubert !ssid->dpp_csign) { 314085732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR 314185732ac8SCy Schubert "missing %s", 314285732ac8SCy Schubert !ssid->dpp_connector ? "Connector" : 314385732ac8SCy Schubert (!ssid->dpp_netaccesskey ? "netAccessKey" : 314485732ac8SCy Schubert "C-sign-key")); 314585732ac8SCy Schubert return -1; 314685732ac8SCy Schubert } 314785732ac8SCy Schubert 314885732ac8SCy Schubert os_get_time(&now); 314985732ac8SCy Schubert 315085732ac8SCy Schubert if (ssid->dpp_netaccesskey_expiry && 315185732ac8SCy Schubert (os_time_t) ssid->dpp_netaccesskey_expiry < now.sec) { 315285732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_MISSING_CONNECTOR 315385732ac8SCy Schubert "netAccessKey expired"); 315485732ac8SCy Schubert return -1; 315585732ac8SCy Schubert } 315685732ac8SCy Schubert 315785732ac8SCy Schubert wpa_printf(MSG_DEBUG, 315885732ac8SCy Schubert "DPP: Starting network introduction protocol to derive PMKSA for " 315985732ac8SCy Schubert MACSTR, MAC2STR(bss->bssid)); 316085732ac8SCy Schubert 3161c1d255d3SCy Schubert len = 5 + 4 + os_strlen(ssid->dpp_connector); 3162c1d255d3SCy Schubert #ifdef CONFIG_DPP2 3163c1d255d3SCy Schubert len += 5; 3164c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 3165c1d255d3SCy Schubert msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len); 316685732ac8SCy Schubert if (!msg) 316785732ac8SCy Schubert return -1; 316885732ac8SCy Schubert 316985732ac8SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 317085732ac8SCy Schubert if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ) { 317185732ac8SCy Schubert wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID"); 317285732ac8SCy Schubert goto skip_trans_id; 317385732ac8SCy Schubert } 317485732ac8SCy Schubert if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ) { 317585732ac8SCy Schubert wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID"); 317685732ac8SCy Schubert wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); 317785732ac8SCy Schubert wpabuf_put_le16(msg, 0); 317885732ac8SCy Schubert goto skip_trans_id; 317985732ac8SCy Schubert } 318085732ac8SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 318185732ac8SCy Schubert 318285732ac8SCy Schubert /* Transaction ID */ 318385732ac8SCy Schubert wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); 318485732ac8SCy Schubert wpabuf_put_le16(msg, 1); 318585732ac8SCy Schubert wpabuf_put_u8(msg, TRANSACTION_ID); 318685732ac8SCy Schubert 318785732ac8SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 318885732ac8SCy Schubert skip_trans_id: 318985732ac8SCy Schubert if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ) { 319085732ac8SCy Schubert wpa_printf(MSG_INFO, "DPP: TESTING - no Connector"); 319185732ac8SCy Schubert goto skip_connector; 319285732ac8SCy Schubert } 319385732ac8SCy Schubert if (dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ) { 319485732ac8SCy Schubert char *connector; 319585732ac8SCy Schubert 319685732ac8SCy Schubert wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector"); 319785732ac8SCy Schubert connector = dpp_corrupt_connector_signature( 319885732ac8SCy Schubert ssid->dpp_connector); 319985732ac8SCy Schubert if (!connector) { 320085732ac8SCy Schubert wpabuf_free(msg); 320185732ac8SCy Schubert return -1; 320285732ac8SCy Schubert } 320385732ac8SCy Schubert wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); 320485732ac8SCy Schubert wpabuf_put_le16(msg, os_strlen(connector)); 320585732ac8SCy Schubert wpabuf_put_str(msg, connector); 320685732ac8SCy Schubert os_free(connector); 320785732ac8SCy Schubert goto skip_connector; 320885732ac8SCy Schubert } 320985732ac8SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 321085732ac8SCy Schubert 321185732ac8SCy Schubert /* DPP Connector */ 321285732ac8SCy Schubert wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); 321385732ac8SCy Schubert wpabuf_put_le16(msg, os_strlen(ssid->dpp_connector)); 321485732ac8SCy Schubert wpabuf_put_str(msg, ssid->dpp_connector); 321585732ac8SCy Schubert 321685732ac8SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 321785732ac8SCy Schubert skip_connector: 3218*32a95656SCy Schubert if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) { 3219*32a95656SCy Schubert wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version"); 3220*32a95656SCy Schubert goto skip_proto_ver; 3221*32a95656SCy Schubert } 322285732ac8SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 322385732ac8SCy Schubert 3224c1d255d3SCy Schubert #ifdef CONFIG_DPP2 3225c1d255d3SCy Schubert if (DPP_VERSION > 1) { 3226*32a95656SCy Schubert u8 ver = DPP_VERSION; 3227*32a95656SCy Schubert #ifdef CONFIG_DPP3 3228*32a95656SCy Schubert int conn_ver; 3229*32a95656SCy Schubert 3230*32a95656SCy Schubert conn_ver = dpp_get_connector_version(ssid->dpp_connector); 3231*32a95656SCy Schubert if (conn_ver > 0 && ver != conn_ver) { 3232*32a95656SCy Schubert wpa_printf(MSG_DEBUG, 3233*32a95656SCy Schubert "DPP: Use Connector version %d instead of current protocol version %d", 3234*32a95656SCy Schubert conn_ver, ver); 3235*32a95656SCy Schubert ver = conn_ver; 3236*32a95656SCy Schubert } 3237*32a95656SCy Schubert #endif /* CONFIG_DPP3 */ 3238*32a95656SCy Schubert 3239c1d255d3SCy Schubert /* Protocol Version */ 3240c1d255d3SCy Schubert wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); 3241c1d255d3SCy Schubert wpabuf_put_le16(msg, 1); 3242*32a95656SCy Schubert wpabuf_put_u8(msg, ver); 3243c1d255d3SCy Schubert } 3244c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 3245c1d255d3SCy Schubert 3246*32a95656SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 3247*32a95656SCy Schubert skip_proto_ver: 3248*32a95656SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 3249*32a95656SCy Schubert 325085732ac8SCy Schubert /* TODO: Timeout on AP response */ 325185732ac8SCy Schubert wait_time = wpa_s->max_remain_on_chan; 325285732ac8SCy Schubert if (wait_time > 2000) 325385732ac8SCy Schubert wait_time = 2000; 325485732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 325585732ac8SCy Schubert MAC2STR(bss->bssid), bss->freq, DPP_PA_PEER_DISCOVERY_REQ); 325685732ac8SCy Schubert offchannel_send_action(wpa_s, bss->freq, bss->bssid, wpa_s->own_addr, 325785732ac8SCy Schubert broadcast, 325885732ac8SCy Schubert wpabuf_head(msg), wpabuf_len(msg), 325985732ac8SCy Schubert wait_time, wpas_dpp_tx_introduction_status, 0); 326085732ac8SCy Schubert wpabuf_free(msg); 326185732ac8SCy Schubert 326285732ac8SCy Schubert /* Request this connection attempt to terminate - new one will be 326385732ac8SCy Schubert * started when network introduction protocol completes */ 326485732ac8SCy Schubert os_memcpy(wpa_s->dpp_intro_bssid, bss->bssid, ETH_ALEN); 326585732ac8SCy Schubert wpa_s->dpp_intro_network = ssid; 326685732ac8SCy Schubert return 1; 326785732ac8SCy Schubert } 326885732ac8SCy Schubert 326985732ac8SCy Schubert 327085732ac8SCy Schubert int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd) 327185732ac8SCy Schubert { 327285732ac8SCy Schubert struct dpp_bootstrap_info *own_bi; 327385732ac8SCy Schubert const char *pos, *end; 327485732ac8SCy Schubert unsigned int wait_time; 327585732ac8SCy Schubert 327685732ac8SCy Schubert pos = os_strstr(cmd, " own="); 327785732ac8SCy Schubert if (!pos) 327885732ac8SCy Schubert return -1; 327985732ac8SCy Schubert pos += 5; 32804bc52338SCy Schubert own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); 328185732ac8SCy Schubert if (!own_bi) { 328285732ac8SCy Schubert wpa_printf(MSG_DEBUG, 328385732ac8SCy Schubert "DPP: Identified bootstrap info not found"); 328485732ac8SCy Schubert return -1; 328585732ac8SCy Schubert } 328685732ac8SCy Schubert if (own_bi->type != DPP_BOOTSTRAP_PKEX) { 328785732ac8SCy Schubert wpa_printf(MSG_DEBUG, 328885732ac8SCy Schubert "DPP: Identified bootstrap info not for PKEX"); 328985732ac8SCy Schubert return -1; 329085732ac8SCy Schubert } 329185732ac8SCy Schubert wpa_s->dpp_pkex_bi = own_bi; 329285732ac8SCy Schubert own_bi->pkex_t = 0; /* clear pending errors on new code */ 329385732ac8SCy Schubert 329485732ac8SCy Schubert os_free(wpa_s->dpp_pkex_identifier); 329585732ac8SCy Schubert wpa_s->dpp_pkex_identifier = NULL; 329685732ac8SCy Schubert pos = os_strstr(cmd, " identifier="); 329785732ac8SCy Schubert if (pos) { 329885732ac8SCy Schubert pos += 12; 329985732ac8SCy Schubert end = os_strchr(pos, ' '); 330085732ac8SCy Schubert if (!end) 330185732ac8SCy Schubert return -1; 330285732ac8SCy Schubert wpa_s->dpp_pkex_identifier = os_malloc(end - pos + 1); 330385732ac8SCy Schubert if (!wpa_s->dpp_pkex_identifier) 330485732ac8SCy Schubert return -1; 330585732ac8SCy Schubert os_memcpy(wpa_s->dpp_pkex_identifier, pos, end - pos); 330685732ac8SCy Schubert wpa_s->dpp_pkex_identifier[end - pos] = '\0'; 330785732ac8SCy Schubert } 330885732ac8SCy Schubert 330985732ac8SCy Schubert pos = os_strstr(cmd, " code="); 331085732ac8SCy Schubert if (!pos) 331185732ac8SCy Schubert return -1; 331285732ac8SCy Schubert os_free(wpa_s->dpp_pkex_code); 331385732ac8SCy Schubert wpa_s->dpp_pkex_code = os_strdup(pos + 6); 331485732ac8SCy Schubert if (!wpa_s->dpp_pkex_code) 331585732ac8SCy Schubert return -1; 331685732ac8SCy Schubert 3317*32a95656SCy Schubert if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) { 331885732ac8SCy Schubert struct dpp_pkex *pkex; 331985732ac8SCy Schubert struct wpabuf *msg; 3320*32a95656SCy Schubert bool v2 = os_strstr(cmd, " init=2") != NULL; 332185732ac8SCy Schubert 332285732ac8SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX"); 332385732ac8SCy Schubert dpp_pkex_free(wpa_s->dpp_pkex); 332485732ac8SCy Schubert wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr, 332585732ac8SCy Schubert wpa_s->dpp_pkex_identifier, 3326*32a95656SCy Schubert wpa_s->dpp_pkex_code, v2); 332785732ac8SCy Schubert pkex = wpa_s->dpp_pkex; 332885732ac8SCy Schubert if (!pkex) 332985732ac8SCy Schubert return -1; 333085732ac8SCy Schubert 333185732ac8SCy Schubert msg = pkex->exchange_req; 333285732ac8SCy Schubert wait_time = wpa_s->max_remain_on_chan; 333385732ac8SCy Schubert if (wait_time > 2000) 333485732ac8SCy Schubert wait_time = 2000; 333585732ac8SCy Schubert pkex->freq = 2437; 333685732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 333785732ac8SCy Schubert " freq=%u type=%d", 333885732ac8SCy Schubert MAC2STR(broadcast), pkex->freq, 3339*32a95656SCy Schubert v2 ? DPP_PA_PKEX_EXCHANGE_REQ : 3340*32a95656SCy Schubert DPP_PA_PKEX_V1_EXCHANGE_REQ); 334185732ac8SCy Schubert offchannel_send_action(wpa_s, pkex->freq, broadcast, 334285732ac8SCy Schubert wpa_s->own_addr, broadcast, 334385732ac8SCy Schubert wpabuf_head(msg), wpabuf_len(msg), 334485732ac8SCy Schubert wait_time, wpas_dpp_tx_pkex_status, 0); 334585732ac8SCy Schubert if (wait_time == 0) 334685732ac8SCy Schubert wait_time = 2000; 334785732ac8SCy Schubert pkex->exch_req_wait_time = wait_time; 334885732ac8SCy Schubert pkex->exch_req_tries = 1; 334985732ac8SCy Schubert } 335085732ac8SCy Schubert 335185732ac8SCy Schubert /* TODO: Support multiple PKEX info entries */ 335285732ac8SCy Schubert 335385732ac8SCy Schubert os_free(wpa_s->dpp_pkex_auth_cmd); 335485732ac8SCy Schubert wpa_s->dpp_pkex_auth_cmd = os_strdup(cmd); 335585732ac8SCy Schubert 335685732ac8SCy Schubert return 1; 335785732ac8SCy Schubert } 335885732ac8SCy Schubert 335985732ac8SCy Schubert 336085732ac8SCy Schubert int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id) 336185732ac8SCy Schubert { 336285732ac8SCy Schubert unsigned int id_val; 336385732ac8SCy Schubert 336485732ac8SCy Schubert if (os_strcmp(id, "*") == 0) { 336585732ac8SCy Schubert id_val = 0; 336685732ac8SCy Schubert } else { 336785732ac8SCy Schubert id_val = atoi(id); 336885732ac8SCy Schubert if (id_val == 0) 336985732ac8SCy Schubert return -1; 337085732ac8SCy Schubert } 337185732ac8SCy Schubert 337285732ac8SCy Schubert if ((id_val != 0 && id_val != 1) || !wpa_s->dpp_pkex_code) 337385732ac8SCy Schubert return -1; 337485732ac8SCy Schubert 337585732ac8SCy Schubert /* TODO: Support multiple PKEX entries */ 337685732ac8SCy Schubert os_free(wpa_s->dpp_pkex_code); 337785732ac8SCy Schubert wpa_s->dpp_pkex_code = NULL; 337885732ac8SCy Schubert os_free(wpa_s->dpp_pkex_identifier); 337985732ac8SCy Schubert wpa_s->dpp_pkex_identifier = NULL; 338085732ac8SCy Schubert os_free(wpa_s->dpp_pkex_auth_cmd); 338185732ac8SCy Schubert wpa_s->dpp_pkex_auth_cmd = NULL; 338285732ac8SCy Schubert wpa_s->dpp_pkex_bi = NULL; 338385732ac8SCy Schubert /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */ 338485732ac8SCy Schubert dpp_pkex_free(wpa_s->dpp_pkex); 338585732ac8SCy Schubert wpa_s->dpp_pkex = NULL; 338685732ac8SCy Schubert return 0; 338785732ac8SCy Schubert } 338885732ac8SCy Schubert 338985732ac8SCy Schubert 339085732ac8SCy Schubert void wpas_dpp_stop(struct wpa_supplicant *wpa_s) 339185732ac8SCy Schubert { 3392c1d255d3SCy Schubert if (wpa_s->dpp_auth || wpa_s->dpp_pkex) 3393c1d255d3SCy Schubert offchannel_send_action_done(wpa_s); 339485732ac8SCy Schubert dpp_auth_deinit(wpa_s->dpp_auth); 339585732ac8SCy Schubert wpa_s->dpp_auth = NULL; 339685732ac8SCy Schubert dpp_pkex_free(wpa_s->dpp_pkex); 339785732ac8SCy Schubert wpa_s->dpp_pkex = NULL; 339885732ac8SCy Schubert if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0) 339985732ac8SCy Schubert gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token); 340085732ac8SCy Schubert } 340185732ac8SCy Schubert 340285732ac8SCy Schubert 340385732ac8SCy Schubert int wpas_dpp_init(struct wpa_supplicant *wpa_s) 340485732ac8SCy Schubert { 3405206b73d0SCy Schubert struct dpp_global_config config; 340685732ac8SCy Schubert u8 adv_proto_id[7]; 340785732ac8SCy Schubert 340885732ac8SCy Schubert adv_proto_id[0] = WLAN_EID_VENDOR_SPECIFIC; 340985732ac8SCy Schubert adv_proto_id[1] = 5; 341085732ac8SCy Schubert WPA_PUT_BE24(&adv_proto_id[2], OUI_WFA); 341185732ac8SCy Schubert adv_proto_id[5] = DPP_OUI_TYPE; 341285732ac8SCy Schubert adv_proto_id[6] = 0x01; 341385732ac8SCy Schubert 341485732ac8SCy Schubert if (gas_server_register(wpa_s->gas_server, adv_proto_id, 341585732ac8SCy Schubert sizeof(adv_proto_id), wpas_dpp_gas_req_handler, 341685732ac8SCy Schubert wpas_dpp_gas_status_handler, wpa_s) < 0) 341785732ac8SCy Schubert return -1; 3418206b73d0SCy Schubert 3419206b73d0SCy Schubert os_memset(&config, 0, sizeof(config)); 3420206b73d0SCy Schubert config.cb_ctx = wpa_s; 3421206b73d0SCy Schubert #ifdef CONFIG_DPP2 3422c1d255d3SCy Schubert config.remove_bi = wpas_dpp_remove_bi; 3423206b73d0SCy Schubert #endif /* CONFIG_DPP2 */ 3424206b73d0SCy Schubert wpa_s->dpp = dpp_global_init(&config); 34254bc52338SCy Schubert return wpa_s->dpp ? 0 : -1; 342685732ac8SCy Schubert } 342785732ac8SCy Schubert 342885732ac8SCy Schubert 342985732ac8SCy Schubert void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) 343085732ac8SCy Schubert { 343185732ac8SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 343285732ac8SCy Schubert os_free(wpa_s->dpp_config_obj_override); 343385732ac8SCy Schubert wpa_s->dpp_config_obj_override = NULL; 343485732ac8SCy Schubert os_free(wpa_s->dpp_discovery_override); 343585732ac8SCy Schubert wpa_s->dpp_discovery_override = NULL; 343685732ac8SCy Schubert os_free(wpa_s->dpp_groups_override); 343785732ac8SCy Schubert wpa_s->dpp_groups_override = NULL; 343885732ac8SCy Schubert wpa_s->dpp_ignore_netaccesskey_mismatch = 0; 343985732ac8SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 34404bc52338SCy Schubert if (!wpa_s->dpp) 344185732ac8SCy Schubert return; 344285732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL); 344385732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); 3444c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL); 344585732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); 344685732ac8SCy Schubert eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); 34474bc52338SCy Schubert #ifdef CONFIG_DPP2 34484bc52338SCy Schubert eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL); 3449c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout, 3450c1d255d3SCy Schubert wpa_s, NULL); 3451c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL); 3452c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, 3453c1d255d3SCy Schubert wpa_s, NULL); 3454c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL); 34554bc52338SCy Schubert dpp_pfs_free(wpa_s->dpp_pfs); 34564bc52338SCy Schubert wpa_s->dpp_pfs = NULL; 3457c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3458c1d255d3SCy Schubert dpp_free_reconfig_id(wpa_s->dpp_reconfig_id); 3459c1d255d3SCy Schubert wpa_s->dpp_reconfig_id = NULL; 34604bc52338SCy Schubert #endif /* CONFIG_DPP2 */ 346185732ac8SCy Schubert offchannel_send_action_done(wpa_s); 346285732ac8SCy Schubert wpas_dpp_listen_stop(wpa_s); 346385732ac8SCy Schubert wpas_dpp_stop(wpa_s); 346485732ac8SCy Schubert wpas_dpp_pkex_remove(wpa_s, "*"); 346585732ac8SCy Schubert os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN); 346685732ac8SCy Schubert os_free(wpa_s->dpp_configurator_params); 346785732ac8SCy Schubert wpa_s->dpp_configurator_params = NULL; 3468c1d255d3SCy Schubert dpp_global_clear(wpa_s->dpp); 346985732ac8SCy Schubert } 3470206b73d0SCy Schubert 3471206b73d0SCy Schubert 3472206b73d0SCy Schubert #ifdef CONFIG_DPP2 3473c1d255d3SCy Schubert 3474206b73d0SCy Schubert int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) 3475206b73d0SCy Schubert { 3476206b73d0SCy Schubert struct dpp_controller_config config; 3477206b73d0SCy Schubert const char *pos; 3478206b73d0SCy Schubert 3479206b73d0SCy Schubert os_memset(&config, 0, sizeof(config)); 3480c1d255d3SCy Schubert config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; 3481c1d255d3SCy Schubert config.netrole = DPP_NETROLE_STA; 3482c1d255d3SCy Schubert config.msg_ctx = wpa_s; 3483c1d255d3SCy Schubert config.cb_ctx = wpa_s; 3484c1d255d3SCy Schubert config.process_conf_obj = wpas_dpp_process_conf_obj; 3485206b73d0SCy Schubert if (cmd) { 3486206b73d0SCy Schubert pos = os_strstr(cmd, " tcp_port="); 3487206b73d0SCy Schubert if (pos) { 3488206b73d0SCy Schubert pos += 10; 3489206b73d0SCy Schubert config.tcp_port = atoi(pos); 3490206b73d0SCy Schubert } 3491c1d255d3SCy Schubert 3492c1d255d3SCy Schubert pos = os_strstr(cmd, " role="); 3493c1d255d3SCy Schubert if (pos) { 3494c1d255d3SCy Schubert pos += 6; 3495c1d255d3SCy Schubert if (os_strncmp(pos, "configurator", 12) == 0) 3496c1d255d3SCy Schubert config.allowed_roles = DPP_CAPAB_CONFIGURATOR; 3497c1d255d3SCy Schubert else if (os_strncmp(pos, "enrollee", 8) == 0) 3498c1d255d3SCy Schubert config.allowed_roles = DPP_CAPAB_ENROLLEE; 3499c1d255d3SCy Schubert else if (os_strncmp(pos, "either", 6) == 0) 3500c1d255d3SCy Schubert config.allowed_roles = DPP_CAPAB_CONFIGURATOR | 3501c1d255d3SCy Schubert DPP_CAPAB_ENROLLEE; 3502c1d255d3SCy Schubert else 3503c1d255d3SCy Schubert return -1; 3504c1d255d3SCy Schubert } 3505c1d255d3SCy Schubert 3506c1d255d3SCy Schubert config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL; 3507206b73d0SCy Schubert } 3508206b73d0SCy Schubert config.configurator_params = wpa_s->dpp_configurator_params; 3509206b73d0SCy Schubert return dpp_controller_start(wpa_s->dpp, &config); 3510206b73d0SCy Schubert } 3511c1d255d3SCy Schubert 3512c1d255d3SCy Schubert 3513c1d255d3SCy Schubert static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx); 3514c1d255d3SCy Schubert 3515c1d255d3SCy Schubert static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx) 3516c1d255d3SCy Schubert { 3517c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 3518c1d255d3SCy Schubert 3519c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No chirp response received"); 3520c1d255d3SCy Schubert offchannel_send_action_done(wpa_s); 3521c1d255d3SCy Schubert wpas_dpp_chirp_next(wpa_s, NULL); 3522c1d255d3SCy Schubert } 3523c1d255d3SCy Schubert 3524c1d255d3SCy Schubert 3525c1d255d3SCy Schubert static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s, 3526c1d255d3SCy Schubert unsigned int freq, const u8 *dst, 3527c1d255d3SCy Schubert const u8 *src, const u8 *bssid, 3528c1d255d3SCy Schubert const u8 *data, size_t data_len, 3529c1d255d3SCy Schubert enum offchannel_send_action_result result) 3530c1d255d3SCy Schubert { 3531c1d255d3SCy Schubert if (result == OFFCHANNEL_SEND_ACTION_FAILED) { 3532c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz", 3533c1d255d3SCy Schubert wpa_s->dpp_chirp_freq); 3534c1d255d3SCy Schubert if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next, 3535c1d255d3SCy Schubert wpa_s, NULL) < 0) 3536c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3537c1d255d3SCy Schubert return; 3538c1d255d3SCy Schubert } 3539c1d255d3SCy Schubert 3540c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response"); 3541c1d255d3SCy Schubert if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout, 3542c1d255d3SCy Schubert wpa_s, NULL) < 0) 3543c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3544c1d255d3SCy Schubert } 3545c1d255d3SCy Schubert 3546c1d255d3SCy Schubert 3547c1d255d3SCy Schubert static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s) 3548c1d255d3SCy Schubert { 3549c1d255d3SCy Schubert struct wpabuf *msg, *announce = NULL; 3550c1d255d3SCy Schubert int type; 3551c1d255d3SCy Schubert 3552c1d255d3SCy Schubert msg = wpa_s->dpp_presence_announcement; 3553c1d255d3SCy Schubert type = DPP_PA_PRESENCE_ANNOUNCEMENT; 3554c1d255d3SCy Schubert if (!msg) { 3555c1d255d3SCy Schubert struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid; 3556c1d255d3SCy Schubert 3557c1d255d3SCy Schubert if (ssid && wpa_s->dpp_reconfig_id && 3558c1d255d3SCy Schubert wpa_config_get_network(wpa_s->conf, 3559c1d255d3SCy Schubert wpa_s->dpp_reconfig_ssid_id) == 3560c1d255d3SCy Schubert ssid) { 3561c1d255d3SCy Schubert announce = dpp_build_reconfig_announcement( 3562c1d255d3SCy Schubert ssid->dpp_csign, 3563c1d255d3SCy Schubert ssid->dpp_csign_len, 3564c1d255d3SCy Schubert ssid->dpp_netaccesskey, 3565c1d255d3SCy Schubert ssid->dpp_netaccesskey_len, 3566c1d255d3SCy Schubert wpa_s->dpp_reconfig_id); 3567c1d255d3SCy Schubert msg = announce; 3568c1d255d3SCy Schubert } 3569c1d255d3SCy Schubert if (!msg) 3570c1d255d3SCy Schubert return; 3571c1d255d3SCy Schubert type = DPP_PA_RECONFIG_ANNOUNCEMENT; 3572c1d255d3SCy Schubert } 3573c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq); 3574c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 3575c1d255d3SCy Schubert MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type); 3576c1d255d3SCy Schubert if (offchannel_send_action( 3577c1d255d3SCy Schubert wpa_s, wpa_s->dpp_chirp_freq, broadcast, 3578c1d255d3SCy Schubert wpa_s->own_addr, broadcast, 3579c1d255d3SCy Schubert wpabuf_head(msg), wpabuf_len(msg), 3580c1d255d3SCy Schubert 2000, wpas_dpp_chirp_tx_status, 0) < 0) 3581c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3582c1d255d3SCy Schubert 3583c1d255d3SCy Schubert wpabuf_free(announce); 3584c1d255d3SCy Schubert } 3585c1d255d3SCy Schubert 3586c1d255d3SCy Schubert 3587c1d255d3SCy Schubert static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, 3588c1d255d3SCy Schubert struct wpa_scan_results *scan_res) 3589c1d255d3SCy Schubert { 3590c1d255d3SCy Schubert struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi; 3591c1d255d3SCy Schubert unsigned int i; 3592c1d255d3SCy Schubert struct hostapd_hw_modes *mode; 3593c1d255d3SCy Schubert int c; 3594c1d255d3SCy Schubert struct wpa_bss *bss; 3595c1d255d3SCy Schubert bool chan6 = wpa_s->hw.modes == NULL; 3596c1d255d3SCy Schubert 3597c1d255d3SCy Schubert if (!bi && !wpa_s->dpp_reconfig_ssid) 3598c1d255d3SCy Schubert return; 3599c1d255d3SCy Schubert 3600c1d255d3SCy Schubert wpa_s->dpp_chirp_scan_done = 1; 3601c1d255d3SCy Schubert 3602c1d255d3SCy Schubert os_free(wpa_s->dpp_chirp_freqs); 3603c1d255d3SCy Schubert wpa_s->dpp_chirp_freqs = NULL; 3604c1d255d3SCy Schubert 3605c1d255d3SCy Schubert /* Channels from own bootstrapping info */ 3606c1d255d3SCy Schubert if (bi) { 3607c1d255d3SCy Schubert for (i = 0; i < bi->num_freq; i++) 3608c1d255d3SCy Schubert int_array_add_unique(&wpa_s->dpp_chirp_freqs, 3609c1d255d3SCy Schubert bi->freq[i]); 3610c1d255d3SCy Schubert } 3611c1d255d3SCy Schubert 3612c1d255d3SCy Schubert /* Preferred chirping channels */ 3613c1d255d3SCy Schubert mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, 3614c1d255d3SCy Schubert HOSTAPD_MODE_IEEE80211G, false); 3615c1d255d3SCy Schubert if (mode) { 3616c1d255d3SCy Schubert for (c = 0; c < mode->num_channels; c++) { 3617c1d255d3SCy Schubert struct hostapd_channel_data *chan = &mode->channels[c]; 3618c1d255d3SCy Schubert 3619c1d255d3SCy Schubert if ((chan->flag & HOSTAPD_CHAN_DISABLED) || 3620c1d255d3SCy Schubert chan->freq != 2437) 3621c1d255d3SCy Schubert continue; 3622c1d255d3SCy Schubert chan6 = true; 3623c1d255d3SCy Schubert break; 3624c1d255d3SCy Schubert } 3625c1d255d3SCy Schubert } 3626c1d255d3SCy Schubert if (chan6) 3627c1d255d3SCy Schubert int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437); 3628c1d255d3SCy Schubert 3629c1d255d3SCy Schubert mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, 3630c1d255d3SCy Schubert HOSTAPD_MODE_IEEE80211A, false); 3631c1d255d3SCy Schubert if (mode) { 3632c1d255d3SCy Schubert int chan44 = 0, chan149 = 0; 3633c1d255d3SCy Schubert 3634c1d255d3SCy Schubert for (c = 0; c < mode->num_channels; c++) { 3635c1d255d3SCy Schubert struct hostapd_channel_data *chan = &mode->channels[c]; 3636c1d255d3SCy Schubert 3637c1d255d3SCy Schubert if (chan->flag & (HOSTAPD_CHAN_DISABLED | 3638c1d255d3SCy Schubert HOSTAPD_CHAN_RADAR)) 3639c1d255d3SCy Schubert continue; 3640c1d255d3SCy Schubert if (chan->freq == 5220) 3641c1d255d3SCy Schubert chan44 = 1; 3642c1d255d3SCy Schubert if (chan->freq == 5745) 3643c1d255d3SCy Schubert chan149 = 1; 3644c1d255d3SCy Schubert } 3645c1d255d3SCy Schubert if (chan149) 3646c1d255d3SCy Schubert int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745); 3647c1d255d3SCy Schubert else if (chan44) 3648c1d255d3SCy Schubert int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220); 3649c1d255d3SCy Schubert } 3650c1d255d3SCy Schubert 3651c1d255d3SCy Schubert mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, 3652c1d255d3SCy Schubert HOSTAPD_MODE_IEEE80211AD, false); 3653c1d255d3SCy Schubert if (mode) { 3654c1d255d3SCy Schubert for (c = 0; c < mode->num_channels; c++) { 3655c1d255d3SCy Schubert struct hostapd_channel_data *chan = &mode->channels[c]; 3656c1d255d3SCy Schubert 3657c1d255d3SCy Schubert if ((chan->flag & (HOSTAPD_CHAN_DISABLED | 3658c1d255d3SCy Schubert HOSTAPD_CHAN_RADAR)) || 3659c1d255d3SCy Schubert chan->freq != 60480) 3660c1d255d3SCy Schubert continue; 3661c1d255d3SCy Schubert int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480); 3662c1d255d3SCy Schubert break; 3663c1d255d3SCy Schubert } 3664c1d255d3SCy Schubert } 3665c1d255d3SCy Schubert 3666c1d255d3SCy Schubert /* Add channels from scan results for APs that advertise Configurator 3667c1d255d3SCy Schubert * Connectivity element */ 3668c1d255d3SCy Schubert dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 3669c1d255d3SCy Schubert if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE)) 3670c1d255d3SCy Schubert int_array_add_unique(&wpa_s->dpp_chirp_freqs, 3671c1d255d3SCy Schubert bss->freq); 3672c1d255d3SCy Schubert } 3673c1d255d3SCy Schubert 3674c1d255d3SCy Schubert if (!wpa_s->dpp_chirp_freqs || 3675c1d255d3SCy Schubert eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0) 3676c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3677c1d255d3SCy Schubert } 3678c1d255d3SCy Schubert 3679c1d255d3SCy Schubert 3680c1d255d3SCy Schubert static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx) 3681c1d255d3SCy Schubert { 3682c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = eloop_ctx; 3683c1d255d3SCy Schubert int i; 3684c1d255d3SCy Schubert 3685c1d255d3SCy Schubert if (wpa_s->dpp_chirp_listen) 3686c1d255d3SCy Schubert wpas_dpp_listen_stop(wpa_s); 3687c1d255d3SCy Schubert 3688c1d255d3SCy Schubert if (wpa_s->dpp_chirp_freq == 0) { 3689c1d255d3SCy Schubert if (wpa_s->dpp_chirp_round % 4 == 0 && 3690c1d255d3SCy Schubert !wpa_s->dpp_chirp_scan_done) { 3691c1d255d3SCy Schubert if (wpas_scan_scheduled(wpa_s)) { 3692c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3693c1d255d3SCy Schubert "DPP: Deferring chirp scan because another scan is planned already"); 3694c1d255d3SCy Schubert if (eloop_register_timeout(1, 0, 3695c1d255d3SCy Schubert wpas_dpp_chirp_next, 3696c1d255d3SCy Schubert wpa_s, NULL) < 0) { 3697c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3698c1d255d3SCy Schubert return; 3699c1d255d3SCy Schubert } 3700c1d255d3SCy Schubert return; 3701c1d255d3SCy Schubert } 3702c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3703c1d255d3SCy Schubert "DPP: Update channel list for chirping"); 3704c1d255d3SCy Schubert wpa_s->scan_req = MANUAL_SCAN_REQ; 3705c1d255d3SCy Schubert wpa_s->scan_res_handler = 3706c1d255d3SCy Schubert wpas_dpp_chirp_scan_res_handler; 3707c1d255d3SCy Schubert wpa_supplicant_req_scan(wpa_s, 0, 0); 3708c1d255d3SCy Schubert return; 3709c1d255d3SCy Schubert } 3710c1d255d3SCy Schubert wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0]; 3711c1d255d3SCy Schubert wpa_s->dpp_chirp_round++; 3712c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d", 3713c1d255d3SCy Schubert wpa_s->dpp_chirp_round); 3714c1d255d3SCy Schubert } else { 3715c1d255d3SCy Schubert for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++) 3716c1d255d3SCy Schubert if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq) 3717c1d255d3SCy Schubert break; 3718c1d255d3SCy Schubert if (!wpa_s->dpp_chirp_freqs[i]) { 3719c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3720c1d255d3SCy Schubert "DPP: Previous chirp freq %d not found", 3721c1d255d3SCy Schubert wpa_s->dpp_chirp_freq); 3722c1d255d3SCy Schubert return; 3723c1d255d3SCy Schubert } 3724c1d255d3SCy Schubert i++; 3725c1d255d3SCy Schubert if (wpa_s->dpp_chirp_freqs[i]) { 3726c1d255d3SCy Schubert wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i]; 3727c1d255d3SCy Schubert } else { 3728c1d255d3SCy Schubert wpa_s->dpp_chirp_iter--; 3729c1d255d3SCy Schubert if (wpa_s->dpp_chirp_iter <= 0) { 3730c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3731c1d255d3SCy Schubert "DPP: Chirping iterations completed"); 3732c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3733c1d255d3SCy Schubert return; 3734c1d255d3SCy Schubert } 3735c1d255d3SCy Schubert wpa_s->dpp_chirp_freq = 0; 3736c1d255d3SCy Schubert wpa_s->dpp_chirp_scan_done = 0; 3737c1d255d3SCy Schubert if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next, 3738c1d255d3SCy Schubert wpa_s, NULL) < 0) { 3739c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3740c1d255d3SCy Schubert return; 3741c1d255d3SCy Schubert } 3742c1d255d3SCy Schubert if (wpa_s->dpp_chirp_listen) { 3743c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3744c1d255d3SCy Schubert "DPP: Listen on %d MHz during chirp 30 second wait", 3745c1d255d3SCy Schubert wpa_s->dpp_chirp_listen); 3746c1d255d3SCy Schubert wpas_dpp_listen_start(wpa_s, 3747c1d255d3SCy Schubert wpa_s->dpp_chirp_listen); 3748c1d255d3SCy Schubert } else { 3749c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3750c1d255d3SCy Schubert "DPP: Wait 30 seconds before starting the next chirping round"); 3751c1d255d3SCy Schubert } 3752c1d255d3SCy Schubert return; 3753c1d255d3SCy Schubert } 3754c1d255d3SCy Schubert } 3755c1d255d3SCy Schubert 3756c1d255d3SCy Schubert wpas_dpp_chirp_start(wpa_s); 3757c1d255d3SCy Schubert } 3758c1d255d3SCy Schubert 3759c1d255d3SCy Schubert 3760c1d255d3SCy Schubert int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd) 3761c1d255d3SCy Schubert { 3762c1d255d3SCy Schubert const char *pos; 3763c1d255d3SCy Schubert int iter = 1, listen_freq = 0; 3764c1d255d3SCy Schubert struct dpp_bootstrap_info *bi; 3765c1d255d3SCy Schubert 3766c1d255d3SCy Schubert pos = os_strstr(cmd, " own="); 3767c1d255d3SCy Schubert if (!pos) 3768c1d255d3SCy Schubert return -1; 3769c1d255d3SCy Schubert pos += 5; 3770c1d255d3SCy Schubert bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); 3771c1d255d3SCy Schubert if (!bi) { 3772c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3773c1d255d3SCy Schubert "DPP: Identified bootstrap info not found"); 3774c1d255d3SCy Schubert return -1; 3775c1d255d3SCy Schubert } 3776c1d255d3SCy Schubert 3777c1d255d3SCy Schubert pos = os_strstr(cmd, " iter="); 3778c1d255d3SCy Schubert if (pos) { 3779c1d255d3SCy Schubert iter = atoi(pos + 6); 3780c1d255d3SCy Schubert if (iter <= 0) 3781c1d255d3SCy Schubert return -1; 3782c1d255d3SCy Schubert } 3783c1d255d3SCy Schubert 3784c1d255d3SCy Schubert pos = os_strstr(cmd, " listen="); 3785c1d255d3SCy Schubert if (pos) { 3786c1d255d3SCy Schubert listen_freq = atoi(pos + 8); 3787c1d255d3SCy Schubert if (listen_freq <= 0) 3788c1d255d3SCy Schubert return -1; 3789c1d255d3SCy Schubert } 3790c1d255d3SCy Schubert 3791c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3792c1d255d3SCy Schubert wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; 3793c1d255d3SCy Schubert wpa_s->dpp_qr_mutual = 0; 3794c1d255d3SCy Schubert wpa_s->dpp_chirp_bi = bi; 3795c1d255d3SCy Schubert wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi); 3796c1d255d3SCy Schubert if (!wpa_s->dpp_presence_announcement) 3797c1d255d3SCy Schubert return -1; 3798c1d255d3SCy Schubert wpa_s->dpp_chirp_iter = iter; 3799c1d255d3SCy Schubert wpa_s->dpp_chirp_round = 0; 3800c1d255d3SCy Schubert wpa_s->dpp_chirp_scan_done = 0; 3801c1d255d3SCy Schubert wpa_s->dpp_chirp_listen = listen_freq; 3802c1d255d3SCy Schubert 3803c1d255d3SCy Schubert return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL); 3804c1d255d3SCy Schubert } 3805c1d255d3SCy Schubert 3806c1d255d3SCy Schubert 3807c1d255d3SCy Schubert void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s) 3808c1d255d3SCy Schubert { 3809c1d255d3SCy Schubert if (wpa_s->dpp_presence_announcement || 3810c1d255d3SCy Schubert wpa_s->dpp_reconfig_ssid) { 3811c1d255d3SCy Schubert offchannel_send_action_done(wpa_s); 3812c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED); 3813c1d255d3SCy Schubert } 3814c1d255d3SCy Schubert wpa_s->dpp_chirp_bi = NULL; 3815c1d255d3SCy Schubert wpabuf_free(wpa_s->dpp_presence_announcement); 3816c1d255d3SCy Schubert wpa_s->dpp_presence_announcement = NULL; 3817c1d255d3SCy Schubert if (wpa_s->dpp_chirp_listen) 3818c1d255d3SCy Schubert wpas_dpp_listen_stop(wpa_s); 3819c1d255d3SCy Schubert wpa_s->dpp_chirp_listen = 0; 3820c1d255d3SCy Schubert wpa_s->dpp_chirp_freq = 0; 3821c1d255d3SCy Schubert os_free(wpa_s->dpp_chirp_freqs); 3822c1d255d3SCy Schubert wpa_s->dpp_chirp_freqs = NULL; 3823c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL); 3824c1d255d3SCy Schubert eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL); 3825c1d255d3SCy Schubert if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) { 3826c1d255d3SCy Schubert wpas_abort_ongoing_scan(wpa_s); 3827c1d255d3SCy Schubert wpa_s->scan_res_handler = NULL; 3828c1d255d3SCy Schubert } 3829c1d255d3SCy Schubert } 3830c1d255d3SCy Schubert 3831c1d255d3SCy Schubert 3832c1d255d3SCy Schubert int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd) 3833c1d255d3SCy Schubert { 3834c1d255d3SCy Schubert struct wpa_ssid *ssid; 3835c1d255d3SCy Schubert int iter = 1; 3836c1d255d3SCy Schubert const char *pos; 3837c1d255d3SCy Schubert 3838c1d255d3SCy Schubert ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 3839c1d255d3SCy Schubert if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey || 3840c1d255d3SCy Schubert !ssid->dpp_csign) { 3841c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3842c1d255d3SCy Schubert "DPP: Not a valid network profile for reconfiguration"); 3843c1d255d3SCy Schubert return -1; 3844c1d255d3SCy Schubert } 3845c1d255d3SCy Schubert 3846c1d255d3SCy Schubert pos = os_strstr(cmd, " iter="); 3847c1d255d3SCy Schubert if (pos) { 3848c1d255d3SCy Schubert iter = atoi(pos + 6); 3849c1d255d3SCy Schubert if (iter <= 0) 3850c1d255d3SCy Schubert return -1; 3851c1d255d3SCy Schubert } 3852c1d255d3SCy Schubert 3853c1d255d3SCy Schubert if (wpa_s->dpp_auth) { 3854c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3855c1d255d3SCy Schubert "DPP: Not ready to start reconfiguration - pending authentication exchange in progress"); 3856c1d255d3SCy Schubert return -1; 3857c1d255d3SCy Schubert } 3858c1d255d3SCy Schubert 3859c1d255d3SCy Schubert dpp_free_reconfig_id(wpa_s->dpp_reconfig_id); 3860c1d255d3SCy Schubert wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign, 3861c1d255d3SCy Schubert ssid->dpp_csign_len, 3862c1d255d3SCy Schubert ssid->dpp_pp_key, 3863c1d255d3SCy Schubert ssid->dpp_pp_key_len); 3864c1d255d3SCy Schubert if (!wpa_s->dpp_reconfig_id) { 3865c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3866c1d255d3SCy Schubert "DPP: Failed to generate E-id for reconfiguration"); 3867c1d255d3SCy Schubert return -1; 3868c1d255d3SCy Schubert } 3869c1d255d3SCy Schubert if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 3870c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration"); 3871c1d255d3SCy Schubert wpa_s->own_disconnect_req = 1; 3872c1d255d3SCy Schubert wpa_supplicant_deauthenticate( 3873c1d255d3SCy Schubert wpa_s, WLAN_REASON_DEAUTH_LEAVING); 3874c1d255d3SCy Schubert } 3875c1d255d3SCy Schubert wpas_dpp_chirp_stop(wpa_s); 3876c1d255d3SCy Schubert wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; 3877c1d255d3SCy Schubert wpa_s->dpp_qr_mutual = 0; 3878c1d255d3SCy Schubert wpa_s->dpp_reconfig_ssid = ssid; 3879c1d255d3SCy Schubert wpa_s->dpp_reconfig_ssid_id = ssid->id; 3880c1d255d3SCy Schubert wpa_s->dpp_chirp_iter = iter; 3881c1d255d3SCy Schubert wpa_s->dpp_chirp_round = 0; 3882c1d255d3SCy Schubert wpa_s->dpp_chirp_scan_done = 0; 3883c1d255d3SCy Schubert wpa_s->dpp_chirp_listen = 0; 3884c1d255d3SCy Schubert 3885c1d255d3SCy Schubert return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL); 3886c1d255d3SCy Schubert } 3887c1d255d3SCy Schubert 3888c1d255d3SCy Schubert 3889c1d255d3SCy Schubert static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s, 3890c1d255d3SCy Schubert struct dpp_authentication *auth, bool tcp) 3891c1d255d3SCy Schubert { 3892c1d255d3SCy Schubert struct wpabuf *resp; 3893c1d255d3SCy Schubert 3894c1d255d3SCy Schubert resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len, 3895c1d255d3SCy Schubert auth->e_netrole, true); 3896c1d255d3SCy Schubert if (!resp) 3897c1d255d3SCy Schubert return -1; 3898c1d255d3SCy Schubert 3899c1d255d3SCy Schubert if (tcp) { 3900c1d255d3SCy Schubert auth->conf_resp_tcp = resp; 3901c1d255d3SCy Schubert return 0; 3902c1d255d3SCy Schubert } 3903c1d255d3SCy Schubert 3904c1d255d3SCy Schubert if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx, 3905c1d255d3SCy Schubert resp) < 0) { 3906c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3907c1d255d3SCy Schubert "DPP: Could not find pending GAS response"); 3908c1d255d3SCy Schubert wpabuf_free(resp); 3909c1d255d3SCy Schubert return -1; 3910c1d255d3SCy Schubert } 3911c1d255d3SCy Schubert auth->conf_resp = resp; 3912c1d255d3SCy Schubert return 0; 3913c1d255d3SCy Schubert } 3914c1d255d3SCy Schubert 3915c1d255d3SCy Schubert 3916c1d255d3SCy Schubert int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) 3917c1d255d3SCy Schubert { 3918c1d255d3SCy Schubert int peer = -1; 3919c1d255d3SCy Schubert const char *pos, *value; 3920c1d255d3SCy Schubert struct dpp_authentication *auth = wpa_s->dpp_auth; 3921c1d255d3SCy Schubert u8 *bin; 3922c1d255d3SCy Schubert size_t bin_len; 3923c1d255d3SCy Schubert struct wpabuf *buf; 3924c1d255d3SCy Schubert bool tcp = false; 3925c1d255d3SCy Schubert 3926c1d255d3SCy Schubert pos = os_strstr(cmd, " peer="); 3927c1d255d3SCy Schubert if (pos) { 3928c1d255d3SCy Schubert peer = atoi(pos + 6); 3929c1d255d3SCy Schubert if (!auth || !auth->waiting_cert || 3930c1d255d3SCy Schubert (auth->peer_bi && 3931c1d255d3SCy Schubert (unsigned int) peer != auth->peer_bi->id)) { 3932c1d255d3SCy Schubert auth = dpp_controller_get_auth(wpa_s->dpp, peer); 3933c1d255d3SCy Schubert tcp = true; 3934c1d255d3SCy Schubert } 3935c1d255d3SCy Schubert } 3936c1d255d3SCy Schubert 3937c1d255d3SCy Schubert if (!auth || !auth->waiting_cert) { 3938c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 3939c1d255d3SCy Schubert "DPP: No authentication exchange waiting for certificate information"); 3940c1d255d3SCy Schubert return -1; 3941c1d255d3SCy Schubert } 3942c1d255d3SCy Schubert 3943c1d255d3SCy Schubert if (peer >= 0 && 3944c1d255d3SCy Schubert (!auth->peer_bi || 3945c1d255d3SCy Schubert (unsigned int) peer != auth->peer_bi->id) && 3946c1d255d3SCy Schubert (!auth->tmp_peer_bi || 3947c1d255d3SCy Schubert (unsigned int) peer != auth->tmp_peer_bi->id)) { 3948c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Peer mismatch"); 3949c1d255d3SCy Schubert return -1; 3950c1d255d3SCy Schubert } 3951c1d255d3SCy Schubert 3952c1d255d3SCy Schubert pos = os_strstr(cmd, " value="); 3953c1d255d3SCy Schubert if (!pos) 3954c1d255d3SCy Schubert return -1; 3955c1d255d3SCy Schubert value = pos + 7; 3956c1d255d3SCy Schubert 3957c1d255d3SCy Schubert pos = os_strstr(cmd, " name="); 3958c1d255d3SCy Schubert if (!pos) 3959c1d255d3SCy Schubert return -1; 3960c1d255d3SCy Schubert pos += 6; 3961c1d255d3SCy Schubert 3962c1d255d3SCy Schubert if (os_strncmp(pos, "status ", 7) == 0) { 3963c1d255d3SCy Schubert auth->force_conf_resp_status = atoi(value); 3964c1d255d3SCy Schubert return wpas_dpp_build_conf_resp(wpa_s, auth, tcp); 3965c1d255d3SCy Schubert } 3966c1d255d3SCy Schubert 3967c1d255d3SCy Schubert if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) { 3968c1d255d3SCy Schubert os_free(auth->trusted_eap_server_name); 3969c1d255d3SCy Schubert auth->trusted_eap_server_name = os_strdup(value); 3970c1d255d3SCy Schubert return auth->trusted_eap_server_name ? 0 : -1; 3971c1d255d3SCy Schubert } 3972c1d255d3SCy Schubert 3973c1d255d3SCy Schubert bin = base64_decode(value, os_strlen(value), &bin_len); 3974c1d255d3SCy Schubert if (!bin) 3975c1d255d3SCy Schubert return -1; 3976c1d255d3SCy Schubert buf = wpabuf_alloc_copy(bin, bin_len); 3977c1d255d3SCy Schubert os_free(bin); 3978c1d255d3SCy Schubert 3979c1d255d3SCy Schubert if (os_strncmp(pos, "caCert ", 7) == 0) { 3980c1d255d3SCy Schubert wpabuf_free(auth->cacert); 3981c1d255d3SCy Schubert auth->cacert = buf; 3982c1d255d3SCy Schubert return 0; 3983c1d255d3SCy Schubert } 3984c1d255d3SCy Schubert 3985c1d255d3SCy Schubert if (os_strncmp(pos, "certBag ", 8) == 0) { 3986c1d255d3SCy Schubert wpabuf_free(auth->certbag); 3987c1d255d3SCy Schubert auth->certbag = buf; 3988c1d255d3SCy Schubert return wpas_dpp_build_conf_resp(wpa_s, auth, tcp); 3989c1d255d3SCy Schubert } 3990c1d255d3SCy Schubert 3991c1d255d3SCy Schubert wpabuf_free(buf); 3992c1d255d3SCy Schubert return -1; 3993c1d255d3SCy Schubert } 3994c1d255d3SCy Schubert 3995206b73d0SCy Schubert #endif /* CONFIG_DPP2 */ 3996