1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * hostapd / DPP integration 3e5b75505Sopenharmony_ci * Copyright (c) 2017, Qualcomm Atheros, Inc. 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "utils/includes.h" 10e5b75505Sopenharmony_ci 11e5b75505Sopenharmony_ci#include "utils/common.h" 12e5b75505Sopenharmony_ci#include "utils/eloop.h" 13e5b75505Sopenharmony_ci#include "common/dpp.h" 14e5b75505Sopenharmony_ci#include "common/gas.h" 15e5b75505Sopenharmony_ci#include "common/wpa_ctrl.h" 16e5b75505Sopenharmony_ci#include "hostapd.h" 17e5b75505Sopenharmony_ci#include "ap_drv_ops.h" 18e5b75505Sopenharmony_ci#include "gas_query_ap.h" 19e5b75505Sopenharmony_ci#include "gas_serv.h" 20e5b75505Sopenharmony_ci#include "wpa_auth.h" 21e5b75505Sopenharmony_ci#include "dpp_hostapd.h" 22e5b75505Sopenharmony_ci 23e5b75505Sopenharmony_ci 24e5b75505Sopenharmony_cistatic void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx); 25e5b75505Sopenharmony_cistatic void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator); 26e5b75505Sopenharmony_cistatic void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx); 27e5b75505Sopenharmony_cistatic int hostapd_dpp_auth_init_next(struct hostapd_data *hapd); 28e5b75505Sopenharmony_ci 29e5b75505Sopenharmony_cistatic const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 30e5b75505Sopenharmony_ci 31e5b75505Sopenharmony_ci 32e5b75505Sopenharmony_ci/** 33e5b75505Sopenharmony_ci * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code 34e5b75505Sopenharmony_ci * @hapd: Pointer to hostapd_data 35e5b75505Sopenharmony_ci * @cmd: DPP URI read from a QR Code 36e5b75505Sopenharmony_ci * Returns: Identifier of the stored info or -1 on failure 37e5b75505Sopenharmony_ci */ 38e5b75505Sopenharmony_ciint hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd) 39e5b75505Sopenharmony_ci{ 40e5b75505Sopenharmony_ci struct dpp_bootstrap_info *bi; 41e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 42e5b75505Sopenharmony_ci 43e5b75505Sopenharmony_ci bi = dpp_add_qr_code(hapd->iface->interfaces->dpp, cmd); 44e5b75505Sopenharmony_ci if (!bi) 45e5b75505Sopenharmony_ci return -1; 46e5b75505Sopenharmony_ci 47e5b75505Sopenharmony_ci if (auth && auth->response_pending && 48e5b75505Sopenharmony_ci dpp_notify_new_qr_code(auth, bi) == 1) { 49e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 50e5b75505Sopenharmony_ci "DPP: Sending out pending authentication response"); 51e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 52e5b75505Sopenharmony_ci " freq=%u type=%d", 53e5b75505Sopenharmony_ci MAC2STR(auth->peer_mac_addr), auth->curr_freq, 54e5b75505Sopenharmony_ci DPP_PA_AUTHENTICATION_RESP); 55e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, auth->curr_freq, 0, 56e5b75505Sopenharmony_ci auth->peer_mac_addr, 57e5b75505Sopenharmony_ci wpabuf_head(hapd->dpp_auth->resp_msg), 58e5b75505Sopenharmony_ci wpabuf_len(hapd->dpp_auth->resp_msg)); 59e5b75505Sopenharmony_ci } 60e5b75505Sopenharmony_ci 61e5b75505Sopenharmony_ci return bi->id; 62e5b75505Sopenharmony_ci} 63e5b75505Sopenharmony_ci 64e5b75505Sopenharmony_ci 65e5b75505Sopenharmony_cistatic void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx, 66e5b75505Sopenharmony_ci void *timeout_ctx) 67e5b75505Sopenharmony_ci{ 68e5b75505Sopenharmony_ci struct hostapd_data *hapd = eloop_ctx; 69e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 70e5b75505Sopenharmony_ci 71e5b75505Sopenharmony_ci if (!auth || !auth->resp_msg) 72e5b75505Sopenharmony_ci return; 73e5b75505Sopenharmony_ci 74e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 75e5b75505Sopenharmony_ci "DPP: Retry Authentication Response after timeout"); 76e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 77e5b75505Sopenharmony_ci " freq=%u type=%d", 78e5b75505Sopenharmony_ci MAC2STR(auth->peer_mac_addr), auth->curr_freq, 79e5b75505Sopenharmony_ci DPP_PA_AUTHENTICATION_RESP); 80e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, auth->curr_freq, 500, auth->peer_mac_addr, 81e5b75505Sopenharmony_ci wpabuf_head(auth->resp_msg), 82e5b75505Sopenharmony_ci wpabuf_len(auth->resp_msg)); 83e5b75505Sopenharmony_ci} 84e5b75505Sopenharmony_ci 85e5b75505Sopenharmony_ci 86e5b75505Sopenharmony_cistatic void hostapd_dpp_auth_resp_retry(struct hostapd_data *hapd) 87e5b75505Sopenharmony_ci{ 88e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 89e5b75505Sopenharmony_ci unsigned int wait_time, max_tries; 90e5b75505Sopenharmony_ci 91e5b75505Sopenharmony_ci if (!auth || !auth->resp_msg) 92e5b75505Sopenharmony_ci return; 93e5b75505Sopenharmony_ci 94e5b75505Sopenharmony_ci if (hapd->dpp_resp_max_tries) 95e5b75505Sopenharmony_ci max_tries = hapd->dpp_resp_max_tries; 96e5b75505Sopenharmony_ci else 97e5b75505Sopenharmony_ci max_tries = 5; 98e5b75505Sopenharmony_ci auth->auth_resp_tries++; 99e5b75505Sopenharmony_ci if (auth->auth_resp_tries >= max_tries) { 100e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 101e5b75505Sopenharmony_ci "DPP: No confirm received from initiator - stopping exchange"); 102e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 103e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 104e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 105e5b75505Sopenharmony_ci return; 106e5b75505Sopenharmony_ci } 107e5b75505Sopenharmony_ci 108e5b75505Sopenharmony_ci if (hapd->dpp_resp_retry_time) 109e5b75505Sopenharmony_ci wait_time = hapd->dpp_resp_retry_time; 110e5b75505Sopenharmony_ci else 111e5b75505Sopenharmony_ci wait_time = 1000; 112e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 113e5b75505Sopenharmony_ci "DPP: Schedule retransmission of Authentication Response frame in %u ms", 114e5b75505Sopenharmony_ci wait_time); 115e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); 116e5b75505Sopenharmony_ci eloop_register_timeout(wait_time / 1000, 117e5b75505Sopenharmony_ci (wait_time % 1000) * 1000, 118e5b75505Sopenharmony_ci hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); 119e5b75505Sopenharmony_ci} 120e5b75505Sopenharmony_ci 121e5b75505Sopenharmony_ci 122e5b75505Sopenharmony_civoid hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst, 123e5b75505Sopenharmony_ci const u8 *data, size_t data_len, int ok) 124e5b75505Sopenharmony_ci{ 125e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 126e5b75505Sopenharmony_ci 127e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d", 128e5b75505Sopenharmony_ci MAC2STR(dst), ok); 129e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR 130e5b75505Sopenharmony_ci " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED"); 131e5b75505Sopenharmony_ci 132e5b75505Sopenharmony_ci if (!hapd->dpp_auth) { 133e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 134e5b75505Sopenharmony_ci "DPP: Ignore TX status since there is no ongoing authentication exchange"); 135e5b75505Sopenharmony_ci return; 136e5b75505Sopenharmony_ci } 137e5b75505Sopenharmony_ci 138e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 139e5b75505Sopenharmony_ci if (auth->connect_on_tx_status) { 140e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 141e5b75505Sopenharmony_ci "DPP: Complete exchange on configuration result"); 142e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 143e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 144e5b75505Sopenharmony_ci return; 145e5b75505Sopenharmony_ci } 146e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 147e5b75505Sopenharmony_ci 148e5b75505Sopenharmony_ci if (hapd->dpp_auth->remove_on_tx_status) { 149e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 150e5b75505Sopenharmony_ci "DPP: Terminate authentication exchange due to an earlier error"); 151e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); 152e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, 153e5b75505Sopenharmony_ci hapd, NULL); 154e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, 155e5b75505Sopenharmony_ci NULL); 156e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 157e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 158e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 159e5b75505Sopenharmony_ci return; 160e5b75505Sopenharmony_ci } 161e5b75505Sopenharmony_ci 162e5b75505Sopenharmony_ci if (hapd->dpp_auth_ok_on_ack) 163e5b75505Sopenharmony_ci hostapd_dpp_auth_success(hapd, 1); 164e5b75505Sopenharmony_ci 165e5b75505Sopenharmony_ci if (!is_broadcast_ether_addr(dst) && !ok) { 166e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 167e5b75505Sopenharmony_ci "DPP: Unicast DPP Action frame was not ACKed"); 168e5b75505Sopenharmony_ci if (auth->waiting_auth_resp) { 169e5b75505Sopenharmony_ci /* In case of DPP Authentication Request frame, move to 170e5b75505Sopenharmony_ci * the next channel immediately. */ 171e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 172e5b75505Sopenharmony_ci hostapd_dpp_auth_init_next(hapd); 173e5b75505Sopenharmony_ci return; 174e5b75505Sopenharmony_ci } 175e5b75505Sopenharmony_ci if (auth->waiting_auth_conf) { 176e5b75505Sopenharmony_ci hostapd_dpp_auth_resp_retry(hapd); 177e5b75505Sopenharmony_ci return; 178e5b75505Sopenharmony_ci } 179e5b75505Sopenharmony_ci } 180e5b75505Sopenharmony_ci 181e5b75505Sopenharmony_ci if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp && ok) { 182e5b75505Sopenharmony_ci /* Allow timeout handling to stop iteration if no response is 183e5b75505Sopenharmony_ci * received from a peer that has ACKed a request. */ 184e5b75505Sopenharmony_ci auth->auth_req_ack = 1; 185e5b75505Sopenharmony_ci } 186e5b75505Sopenharmony_ci 187e5b75505Sopenharmony_ci if (!hapd->dpp_auth_ok_on_ack && hapd->dpp_auth->neg_freq > 0 && 188e5b75505Sopenharmony_ci hapd->dpp_auth->curr_freq != hapd->dpp_auth->neg_freq) { 189e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 190e5b75505Sopenharmony_ci "DPP: Move from curr_freq %u MHz to neg_freq %u MHz for response", 191e5b75505Sopenharmony_ci hapd->dpp_auth->curr_freq, 192e5b75505Sopenharmony_ci hapd->dpp_auth->neg_freq); 193e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 194e5b75505Sopenharmony_ci 195e5b75505Sopenharmony_ci if (hapd->dpp_auth->neg_freq != 196e5b75505Sopenharmony_ci (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) { 197e5b75505Sopenharmony_ci /* TODO: Listen operation on non-operating channel */ 198e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 199e5b75505Sopenharmony_ci "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)", 200e5b75505Sopenharmony_ci hapd->dpp_auth->neg_freq, hapd->iface->freq); 201e5b75505Sopenharmony_ci } 202e5b75505Sopenharmony_ci } 203e5b75505Sopenharmony_ci 204e5b75505Sopenharmony_ci if (hapd->dpp_auth_ok_on_ack) 205e5b75505Sopenharmony_ci hapd->dpp_auth_ok_on_ack = 0; 206e5b75505Sopenharmony_ci} 207e5b75505Sopenharmony_ci 208e5b75505Sopenharmony_ci 209e5b75505Sopenharmony_cistatic void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx) 210e5b75505Sopenharmony_ci{ 211e5b75505Sopenharmony_ci struct hostapd_data *hapd = eloop_ctx; 212e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 213e5b75505Sopenharmony_ci unsigned int freq; 214e5b75505Sopenharmony_ci struct os_reltime now, diff; 215e5b75505Sopenharmony_ci unsigned int wait_time, diff_ms; 216e5b75505Sopenharmony_ci 217e5b75505Sopenharmony_ci if (!auth || !auth->waiting_auth_resp) 218e5b75505Sopenharmony_ci return; 219e5b75505Sopenharmony_ci 220e5b75505Sopenharmony_ci wait_time = hapd->dpp_resp_wait_time ? 221e5b75505Sopenharmony_ci hapd->dpp_resp_wait_time : 2000; 222e5b75505Sopenharmony_ci os_get_reltime(&now); 223e5b75505Sopenharmony_ci os_reltime_sub(&now, &hapd->dpp_last_init, &diff); 224e5b75505Sopenharmony_ci diff_ms = diff.sec * 1000 + diff.usec / 1000; 225e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 226e5b75505Sopenharmony_ci "DPP: Reply wait timeout - wait_time=%u diff_ms=%u", 227e5b75505Sopenharmony_ci wait_time, diff_ms); 228e5b75505Sopenharmony_ci 229e5b75505Sopenharmony_ci if (auth->auth_req_ack && diff_ms >= wait_time) { 230e5b75505Sopenharmony_ci /* Peer ACK'ed Authentication Request frame, but did not reply 231e5b75505Sopenharmony_ci * with Authentication Response frame within two seconds. */ 232e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 233e5b75505Sopenharmony_ci "DPP: No response received from responder - stopping initiation attempt"); 234e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_INIT_FAILED); 235e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 236e5b75505Sopenharmony_ci hostapd_dpp_listen_stop(hapd); 237e5b75505Sopenharmony_ci dpp_auth_deinit(auth); 238e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 239e5b75505Sopenharmony_ci return; 240e5b75505Sopenharmony_ci } 241e5b75505Sopenharmony_ci 242e5b75505Sopenharmony_ci if (diff_ms >= wait_time) { 243e5b75505Sopenharmony_ci /* Authentication Request frame was not ACK'ed and no reply 244e5b75505Sopenharmony_ci * was receiving within two seconds. */ 245e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 246e5b75505Sopenharmony_ci "DPP: Continue Initiator channel iteration"); 247e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 248e5b75505Sopenharmony_ci hostapd_dpp_listen_stop(hapd); 249e5b75505Sopenharmony_ci hostapd_dpp_auth_init_next(hapd); 250e5b75505Sopenharmony_ci return; 251e5b75505Sopenharmony_ci } 252e5b75505Sopenharmony_ci 253e5b75505Sopenharmony_ci /* Driver did not support 2000 ms long wait_time with TX command, so 254e5b75505Sopenharmony_ci * schedule listen operation to continue waiting for the response. 255e5b75505Sopenharmony_ci * 256e5b75505Sopenharmony_ci * DPP listen operations continue until stopped, so simply schedule a 257e5b75505Sopenharmony_ci * new call to this function at the point when the two second reply 258e5b75505Sopenharmony_ci * wait has expired. */ 259e5b75505Sopenharmony_ci wait_time -= diff_ms; 260e5b75505Sopenharmony_ci 261e5b75505Sopenharmony_ci freq = auth->curr_freq; 262e5b75505Sopenharmony_ci if (auth->neg_freq > 0) 263e5b75505Sopenharmony_ci freq = auth->neg_freq; 264e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 265e5b75505Sopenharmony_ci "DPP: Continue reply wait on channel %u MHz for %u ms", 266e5b75505Sopenharmony_ci freq, wait_time); 267e5b75505Sopenharmony_ci hapd->dpp_in_response_listen = 1; 268e5b75505Sopenharmony_ci 269e5b75505Sopenharmony_ci if (freq != (unsigned int) hapd->iface->freq && hapd->iface->freq > 0) { 270e5b75505Sopenharmony_ci /* TODO: Listen operation on non-operating channel */ 271e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 272e5b75505Sopenharmony_ci "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)", 273e5b75505Sopenharmony_ci freq, hapd->iface->freq); 274e5b75505Sopenharmony_ci } 275e5b75505Sopenharmony_ci 276e5b75505Sopenharmony_ci eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, 277e5b75505Sopenharmony_ci hostapd_dpp_reply_wait_timeout, hapd, NULL); 278e5b75505Sopenharmony_ci} 279e5b75505Sopenharmony_ci 280e5b75505Sopenharmony_ci 281e5b75505Sopenharmony_cistatic void hostapd_dpp_set_testing_options(struct hostapd_data *hapd, 282e5b75505Sopenharmony_ci struct dpp_authentication *auth) 283e5b75505Sopenharmony_ci{ 284e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 285e5b75505Sopenharmony_ci if (hapd->dpp_config_obj_override) 286e5b75505Sopenharmony_ci auth->config_obj_override = 287e5b75505Sopenharmony_ci os_strdup(hapd->dpp_config_obj_override); 288e5b75505Sopenharmony_ci if (hapd->dpp_discovery_override) 289e5b75505Sopenharmony_ci auth->discovery_override = 290e5b75505Sopenharmony_ci os_strdup(hapd->dpp_discovery_override); 291e5b75505Sopenharmony_ci if (hapd->dpp_groups_override) 292e5b75505Sopenharmony_ci auth->groups_override = os_strdup(hapd->dpp_groups_override); 293e5b75505Sopenharmony_ci auth->ignore_netaccesskey_mismatch = 294e5b75505Sopenharmony_ci hapd->dpp_ignore_netaccesskey_mismatch; 295e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 296e5b75505Sopenharmony_ci} 297e5b75505Sopenharmony_ci 298e5b75505Sopenharmony_ci 299e5b75505Sopenharmony_cistatic void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx) 300e5b75505Sopenharmony_ci{ 301e5b75505Sopenharmony_ci struct hostapd_data *hapd = eloop_ctx; 302e5b75505Sopenharmony_ci 303e5b75505Sopenharmony_ci if (!hapd->dpp_auth) 304e5b75505Sopenharmony_ci return; 305e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Retry initiation after timeout"); 306e5b75505Sopenharmony_ci hostapd_dpp_auth_init_next(hapd); 307e5b75505Sopenharmony_ci} 308e5b75505Sopenharmony_ci 309e5b75505Sopenharmony_ci 310e5b75505Sopenharmony_cistatic int hostapd_dpp_auth_init_next(struct hostapd_data *hapd) 311e5b75505Sopenharmony_ci{ 312e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 313e5b75505Sopenharmony_ci const u8 *dst; 314e5b75505Sopenharmony_ci unsigned int wait_time, max_wait_time, freq, max_tries, used; 315e5b75505Sopenharmony_ci struct os_reltime now, diff; 316e5b75505Sopenharmony_ci 317e5b75505Sopenharmony_ci if (!auth) 318e5b75505Sopenharmony_ci return -1; 319e5b75505Sopenharmony_ci 320e5b75505Sopenharmony_ci if (auth->freq_idx == 0) 321e5b75505Sopenharmony_ci os_get_reltime(&hapd->dpp_init_iter_start); 322e5b75505Sopenharmony_ci 323e5b75505Sopenharmony_ci if (auth->freq_idx >= auth->num_freq) { 324e5b75505Sopenharmony_ci auth->num_freq_iters++; 325e5b75505Sopenharmony_ci if (hapd->dpp_init_max_tries) 326e5b75505Sopenharmony_ci max_tries = hapd->dpp_init_max_tries; 327e5b75505Sopenharmony_ci else 328e5b75505Sopenharmony_ci max_tries = 5; 329e5b75505Sopenharmony_ci if (auth->num_freq_iters >= max_tries || auth->auth_req_ack) { 330e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 331e5b75505Sopenharmony_ci "DPP: No response received from responder - stopping initiation attempt"); 332e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, 333e5b75505Sopenharmony_ci DPP_EVENT_AUTH_INIT_FAILED); 334e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, 335e5b75505Sopenharmony_ci hapd, NULL); 336e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 337e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 338e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 339e5b75505Sopenharmony_ci return -1; 340e5b75505Sopenharmony_ci } 341e5b75505Sopenharmony_ci auth->freq_idx = 0; 342e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); 343e5b75505Sopenharmony_ci if (hapd->dpp_init_retry_time) 344e5b75505Sopenharmony_ci wait_time = hapd->dpp_init_retry_time; 345e5b75505Sopenharmony_ci else 346e5b75505Sopenharmony_ci wait_time = 10000; 347e5b75505Sopenharmony_ci os_get_reltime(&now); 348e5b75505Sopenharmony_ci os_reltime_sub(&now, &hapd->dpp_init_iter_start, &diff); 349e5b75505Sopenharmony_ci used = diff.sec * 1000 + diff.usec / 1000; 350e5b75505Sopenharmony_ci if (used > wait_time) 351e5b75505Sopenharmony_ci wait_time = 0; 352e5b75505Sopenharmony_ci else 353e5b75505Sopenharmony_ci wait_time -= used; 354e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Next init attempt in %u ms", 355e5b75505Sopenharmony_ci wait_time); 356e5b75505Sopenharmony_ci eloop_register_timeout(wait_time / 1000, 357e5b75505Sopenharmony_ci (wait_time % 1000) * 1000, 358e5b75505Sopenharmony_ci hostapd_dpp_init_timeout, hapd, 359e5b75505Sopenharmony_ci NULL); 360e5b75505Sopenharmony_ci return 0; 361e5b75505Sopenharmony_ci } 362e5b75505Sopenharmony_ci freq = auth->freq[auth->freq_idx++]; 363e5b75505Sopenharmony_ci auth->curr_freq = freq; 364e5b75505Sopenharmony_ci 365e5b75505Sopenharmony_ci if (is_zero_ether_addr(auth->peer_bi->mac_addr)) 366e5b75505Sopenharmony_ci dst = broadcast; 367e5b75505Sopenharmony_ci else 368e5b75505Sopenharmony_ci dst = auth->peer_bi->mac_addr; 369e5b75505Sopenharmony_ci hapd->dpp_auth_ok_on_ack = 0; 370e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); 371e5b75505Sopenharmony_ci wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */ 372e5b75505Sopenharmony_ci max_wait_time = hapd->dpp_resp_wait_time ? 373e5b75505Sopenharmony_ci hapd->dpp_resp_wait_time : 2000; 374e5b75505Sopenharmony_ci if (wait_time > max_wait_time) 375e5b75505Sopenharmony_ci wait_time = max_wait_time; 376e5b75505Sopenharmony_ci wait_time += 10; /* give the driver some extra time to complete */ 377e5b75505Sopenharmony_ci eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, 378e5b75505Sopenharmony_ci hostapd_dpp_reply_wait_timeout, hapd, NULL); 379e5b75505Sopenharmony_ci wait_time -= 10; 380e5b75505Sopenharmony_ci if (auth->neg_freq > 0 && freq != auth->neg_freq) { 381e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 382e5b75505Sopenharmony_ci "DPP: Initiate on %u MHz and move to neg_freq %u MHz for response", 383e5b75505Sopenharmony_ci freq, auth->neg_freq); 384e5b75505Sopenharmony_ci } 385e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 386e5b75505Sopenharmony_ci " freq=%u type=%d", 387e5b75505Sopenharmony_ci MAC2STR(dst), freq, DPP_PA_AUTHENTICATION_REQ); 388e5b75505Sopenharmony_ci auth->auth_req_ack = 0; 389e5b75505Sopenharmony_ci os_get_reltime(&hapd->dpp_last_init); 390e5b75505Sopenharmony_ci return hostapd_drv_send_action(hapd, freq, wait_time, 391e5b75505Sopenharmony_ci dst, 392e5b75505Sopenharmony_ci wpabuf_head(hapd->dpp_auth->req_msg), 393e5b75505Sopenharmony_ci wpabuf_len(hapd->dpp_auth->req_msg)); 394e5b75505Sopenharmony_ci} 395e5b75505Sopenharmony_ci 396e5b75505Sopenharmony_ci 397e5b75505Sopenharmony_ciint hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) 398e5b75505Sopenharmony_ci{ 399e5b75505Sopenharmony_ci const char *pos; 400e5b75505Sopenharmony_ci struct dpp_bootstrap_info *peer_bi, *own_bi = NULL; 401e5b75505Sopenharmony_ci u8 allowed_roles = DPP_CAPAB_CONFIGURATOR; 402e5b75505Sopenharmony_ci unsigned int neg_freq = 0; 403e5b75505Sopenharmony_ci 404e5b75505Sopenharmony_ci pos = os_strstr(cmd, " peer="); 405e5b75505Sopenharmony_ci if (!pos) 406e5b75505Sopenharmony_ci return -1; 407e5b75505Sopenharmony_ci pos += 6; 408e5b75505Sopenharmony_ci peer_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos)); 409e5b75505Sopenharmony_ci if (!peer_bi) { 410e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 411e5b75505Sopenharmony_ci "DPP: Could not find bootstrapping info for the identified peer"); 412e5b75505Sopenharmony_ci return -1; 413e5b75505Sopenharmony_ci } 414e5b75505Sopenharmony_ci 415e5b75505Sopenharmony_ci pos = os_strstr(cmd, " own="); 416e5b75505Sopenharmony_ci if (pos) { 417e5b75505Sopenharmony_ci pos += 5; 418e5b75505Sopenharmony_ci own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, 419e5b75505Sopenharmony_ci atoi(pos)); 420e5b75505Sopenharmony_ci if (!own_bi) { 421e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 422e5b75505Sopenharmony_ci "DPP: Could not find bootstrapping info for the identified local entry"); 423e5b75505Sopenharmony_ci return -1; 424e5b75505Sopenharmony_ci } 425e5b75505Sopenharmony_ci 426e5b75505Sopenharmony_ci if (peer_bi->curve != own_bi->curve) { 427e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 428e5b75505Sopenharmony_ci "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)", 429e5b75505Sopenharmony_ci peer_bi->curve->name, own_bi->curve->name); 430e5b75505Sopenharmony_ci return -1; 431e5b75505Sopenharmony_ci } 432e5b75505Sopenharmony_ci } 433e5b75505Sopenharmony_ci 434e5b75505Sopenharmony_ci pos = os_strstr(cmd, " role="); 435e5b75505Sopenharmony_ci if (pos) { 436e5b75505Sopenharmony_ci pos += 6; 437e5b75505Sopenharmony_ci if (os_strncmp(pos, "configurator", 12) == 0) 438e5b75505Sopenharmony_ci allowed_roles = DPP_CAPAB_CONFIGURATOR; 439e5b75505Sopenharmony_ci else if (os_strncmp(pos, "enrollee", 8) == 0) 440e5b75505Sopenharmony_ci allowed_roles = DPP_CAPAB_ENROLLEE; 441e5b75505Sopenharmony_ci else if (os_strncmp(pos, "either", 6) == 0) 442e5b75505Sopenharmony_ci allowed_roles = DPP_CAPAB_CONFIGURATOR | 443e5b75505Sopenharmony_ci DPP_CAPAB_ENROLLEE; 444e5b75505Sopenharmony_ci else 445e5b75505Sopenharmony_ci goto fail; 446e5b75505Sopenharmony_ci } 447e5b75505Sopenharmony_ci 448e5b75505Sopenharmony_ci pos = os_strstr(cmd, " neg_freq="); 449e5b75505Sopenharmony_ci if (pos) 450e5b75505Sopenharmony_ci neg_freq = atoi(pos + 10); 451e5b75505Sopenharmony_ci 452e5b75505Sopenharmony_ci if (hapd->dpp_auth) { 453e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); 454e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, 455e5b75505Sopenharmony_ci hapd, NULL); 456e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, 457e5b75505Sopenharmony_ci NULL); 458e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 459e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 460e5b75505Sopenharmony_ci } 461e5b75505Sopenharmony_ci 462e5b75505Sopenharmony_ci hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi, 463e5b75505Sopenharmony_ci allowed_roles, neg_freq, 464e5b75505Sopenharmony_ci hapd->iface->hw_features, 465e5b75505Sopenharmony_ci hapd->iface->num_hw_features); 466e5b75505Sopenharmony_ci if (!hapd->dpp_auth) 467e5b75505Sopenharmony_ci goto fail; 468e5b75505Sopenharmony_ci hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); 469e5b75505Sopenharmony_ci if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, 470e5b75505Sopenharmony_ci hapd->dpp_auth, cmd) < 0) { 471e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 472e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 473e5b75505Sopenharmony_ci goto fail; 474e5b75505Sopenharmony_ci } 475e5b75505Sopenharmony_ci 476e5b75505Sopenharmony_ci hapd->dpp_auth->neg_freq = neg_freq; 477e5b75505Sopenharmony_ci 478e5b75505Sopenharmony_ci if (!is_zero_ether_addr(peer_bi->mac_addr)) 479e5b75505Sopenharmony_ci os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr, 480e5b75505Sopenharmony_ci ETH_ALEN); 481e5b75505Sopenharmony_ci 482e5b75505Sopenharmony_ci return hostapd_dpp_auth_init_next(hapd); 483e5b75505Sopenharmony_cifail: 484e5b75505Sopenharmony_ci return -1; 485e5b75505Sopenharmony_ci} 486e5b75505Sopenharmony_ci 487e5b75505Sopenharmony_ci 488e5b75505Sopenharmony_ciint hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd) 489e5b75505Sopenharmony_ci{ 490e5b75505Sopenharmony_ci int freq; 491e5b75505Sopenharmony_ci 492e5b75505Sopenharmony_ci freq = atoi(cmd); 493e5b75505Sopenharmony_ci if (freq <= 0) 494e5b75505Sopenharmony_ci return -1; 495e5b75505Sopenharmony_ci 496e5b75505Sopenharmony_ci if (os_strstr(cmd, " role=configurator")) 497e5b75505Sopenharmony_ci hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR; 498e5b75505Sopenharmony_ci else if (os_strstr(cmd, " role=enrollee")) 499e5b75505Sopenharmony_ci hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; 500e5b75505Sopenharmony_ci else 501e5b75505Sopenharmony_ci hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | 502e5b75505Sopenharmony_ci DPP_CAPAB_ENROLLEE; 503e5b75505Sopenharmony_ci hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL; 504e5b75505Sopenharmony_ci 505e5b75505Sopenharmony_ci if (freq != hapd->iface->freq && hapd->iface->freq > 0) { 506e5b75505Sopenharmony_ci /* TODO: Listen operation on non-operating channel */ 507e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 508e5b75505Sopenharmony_ci "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)", 509e5b75505Sopenharmony_ci freq, hapd->iface->freq); 510e5b75505Sopenharmony_ci return -1; 511e5b75505Sopenharmony_ci } 512e5b75505Sopenharmony_ci 513e5b75505Sopenharmony_ci return 0; 514e5b75505Sopenharmony_ci} 515e5b75505Sopenharmony_ci 516e5b75505Sopenharmony_ci 517e5b75505Sopenharmony_civoid hostapd_dpp_listen_stop(struct hostapd_data *hapd) 518e5b75505Sopenharmony_ci{ 519e5b75505Sopenharmony_ci /* TODO: Stop listen operation on non-operating channel */ 520e5b75505Sopenharmony_ci} 521e5b75505Sopenharmony_ci 522e5b75505Sopenharmony_ci 523e5b75505Sopenharmony_cistatic void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, 524e5b75505Sopenharmony_ci const u8 *hdr, const u8 *buf, size_t len, 525e5b75505Sopenharmony_ci unsigned int freq) 526e5b75505Sopenharmony_ci{ 527e5b75505Sopenharmony_ci const u8 *r_bootstrap, *i_bootstrap; 528e5b75505Sopenharmony_ci u16 r_bootstrap_len, i_bootstrap_len; 529e5b75505Sopenharmony_ci struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL; 530e5b75505Sopenharmony_ci 531e5b75505Sopenharmony_ci if (!hapd->iface->interfaces->dpp) 532e5b75505Sopenharmony_ci return; 533e5b75505Sopenharmony_ci 534e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR, 535e5b75505Sopenharmony_ci MAC2STR(src)); 536e5b75505Sopenharmony_ci 537e5b75505Sopenharmony_ci r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, 538e5b75505Sopenharmony_ci &r_bootstrap_len); 539e5b75505Sopenharmony_ci if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { 540e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL 541e5b75505Sopenharmony_ci "Missing or invalid required Responder Bootstrapping Key Hash attribute"); 542e5b75505Sopenharmony_ci return; 543e5b75505Sopenharmony_ci } 544e5b75505Sopenharmony_ci wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", 545e5b75505Sopenharmony_ci r_bootstrap, r_bootstrap_len); 546e5b75505Sopenharmony_ci 547e5b75505Sopenharmony_ci i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH, 548e5b75505Sopenharmony_ci &i_bootstrap_len); 549e5b75505Sopenharmony_ci if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) { 550e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL 551e5b75505Sopenharmony_ci "Missing or invalid required Initiator Bootstrapping Key Hash attribute"); 552e5b75505Sopenharmony_ci return; 553e5b75505Sopenharmony_ci } 554e5b75505Sopenharmony_ci wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", 555e5b75505Sopenharmony_ci i_bootstrap, i_bootstrap_len); 556e5b75505Sopenharmony_ci 557e5b75505Sopenharmony_ci /* Try to find own and peer bootstrapping key matches based on the 558e5b75505Sopenharmony_ci * received hash values */ 559e5b75505Sopenharmony_ci dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap, 560e5b75505Sopenharmony_ci r_bootstrap, &own_bi, &peer_bi); 561e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 562e5b75505Sopenharmony_ci if (!own_bi) { 563e5b75505Sopenharmony_ci if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, 564e5b75505Sopenharmony_ci src, hdr, buf, len, freq, i_bootstrap, 565e5b75505Sopenharmony_ci r_bootstrap) == 0) 566e5b75505Sopenharmony_ci return; 567e5b75505Sopenharmony_ci } 568e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 569e5b75505Sopenharmony_ci if (!own_bi) { 570e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL 571e5b75505Sopenharmony_ci "No matching own bootstrapping key found - ignore message"); 572e5b75505Sopenharmony_ci return; 573e5b75505Sopenharmony_ci } 574e5b75505Sopenharmony_ci 575e5b75505Sopenharmony_ci if (hapd->dpp_auth) { 576e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL 577e5b75505Sopenharmony_ci "Already in DPP authentication exchange - ignore new one"); 578e5b75505Sopenharmony_ci return; 579e5b75505Sopenharmony_ci } 580e5b75505Sopenharmony_ci 581e5b75505Sopenharmony_ci hapd->dpp_auth_ok_on_ack = 0; 582e5b75505Sopenharmony_ci hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles, 583e5b75505Sopenharmony_ci hapd->dpp_qr_mutual, 584e5b75505Sopenharmony_ci peer_bi, own_bi, freq, hdr, buf, len); 585e5b75505Sopenharmony_ci if (!hapd->dpp_auth) { 586e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: No response generated"); 587e5b75505Sopenharmony_ci return; 588e5b75505Sopenharmony_ci } 589e5b75505Sopenharmony_ci hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); 590e5b75505Sopenharmony_ci if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, 591e5b75505Sopenharmony_ci hapd->dpp_auth, 592e5b75505Sopenharmony_ci hapd->dpp_configurator_params) < 0) { 593e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 594e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 595e5b75505Sopenharmony_ci return; 596e5b75505Sopenharmony_ci } 597e5b75505Sopenharmony_ci os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN); 598e5b75505Sopenharmony_ci 599e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 600e5b75505Sopenharmony_ci " freq=%u type=%d", 601e5b75505Sopenharmony_ci MAC2STR(src), hapd->dpp_auth->curr_freq, 602e5b75505Sopenharmony_ci DPP_PA_AUTHENTICATION_RESP); 603e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0, 604e5b75505Sopenharmony_ci src, wpabuf_head(hapd->dpp_auth->resp_msg), 605e5b75505Sopenharmony_ci wpabuf_len(hapd->dpp_auth->resp_msg)); 606e5b75505Sopenharmony_ci} 607e5b75505Sopenharmony_ci 608e5b75505Sopenharmony_ci 609e5b75505Sopenharmony_cistatic void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd, 610e5b75505Sopenharmony_ci struct dpp_authentication *auth) 611e5b75505Sopenharmony_ci{ 612e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED); 613e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s", 614e5b75505Sopenharmony_ci dpp_akm_str(auth->akm)); 615e5b75505Sopenharmony_ci if (auth->ssid_len) 616e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s", 617e5b75505Sopenharmony_ci wpa_ssid_txt(auth->ssid, auth->ssid_len)); 618e5b75505Sopenharmony_ci if (auth->connector) { 619e5b75505Sopenharmony_ci /* TODO: Save the Connector and consider using a command 620e5b75505Sopenharmony_ci * to fetch the value instead of sending an event with 621e5b75505Sopenharmony_ci * it. The Connector could end up being larger than what 622e5b75505Sopenharmony_ci * most clients are ready to receive as an event 623e5b75505Sopenharmony_ci * message. */ 624e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s", 625e5b75505Sopenharmony_ci auth->connector); 626e5b75505Sopenharmony_ci } else if (auth->passphrase[0]) { 627e5b75505Sopenharmony_ci char hex[64 * 2 + 1]; 628e5b75505Sopenharmony_ci 629e5b75505Sopenharmony_ci wpa_snprintf_hex(hex, sizeof(hex), 630e5b75505Sopenharmony_ci (const u8 *) auth->passphrase, 631e5b75505Sopenharmony_ci os_strlen(auth->passphrase)); 632e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s", 633e5b75505Sopenharmony_ci hex); 634e5b75505Sopenharmony_ci } else if (auth->psk_set) { 635e5b75505Sopenharmony_ci char hex[PMK_LEN * 2 + 1]; 636e5b75505Sopenharmony_ci 637e5b75505Sopenharmony_ci wpa_snprintf_hex(hex, sizeof(hex), auth->psk, PMK_LEN); 638e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s", 639e5b75505Sopenharmony_ci hex); 640e5b75505Sopenharmony_ci } 641e5b75505Sopenharmony_ci if (auth->c_sign_key) { 642e5b75505Sopenharmony_ci char *hex; 643e5b75505Sopenharmony_ci size_t hexlen; 644e5b75505Sopenharmony_ci 645e5b75505Sopenharmony_ci hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1; 646e5b75505Sopenharmony_ci hex = os_malloc(hexlen); 647e5b75505Sopenharmony_ci if (hex) { 648e5b75505Sopenharmony_ci wpa_snprintf_hex(hex, hexlen, 649e5b75505Sopenharmony_ci wpabuf_head(auth->c_sign_key), 650e5b75505Sopenharmony_ci wpabuf_len(auth->c_sign_key)); 651e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, 652e5b75505Sopenharmony_ci DPP_EVENT_C_SIGN_KEY "%s", hex); 653e5b75505Sopenharmony_ci os_free(hex); 654e5b75505Sopenharmony_ci } 655e5b75505Sopenharmony_ci } 656e5b75505Sopenharmony_ci if (auth->net_access_key) { 657e5b75505Sopenharmony_ci char *hex; 658e5b75505Sopenharmony_ci size_t hexlen; 659e5b75505Sopenharmony_ci 660e5b75505Sopenharmony_ci hexlen = 2 * wpabuf_len(auth->net_access_key) + 1; 661e5b75505Sopenharmony_ci hex = os_malloc(hexlen); 662e5b75505Sopenharmony_ci if (hex) { 663e5b75505Sopenharmony_ci wpa_snprintf_hex(hex, hexlen, 664e5b75505Sopenharmony_ci wpabuf_head(auth->net_access_key), 665e5b75505Sopenharmony_ci wpabuf_len(auth->net_access_key)); 666e5b75505Sopenharmony_ci if (auth->net_access_key_expiry) 667e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, 668e5b75505Sopenharmony_ci DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex, 669e5b75505Sopenharmony_ci (unsigned long) 670e5b75505Sopenharmony_ci auth->net_access_key_expiry); 671e5b75505Sopenharmony_ci else 672e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, 673e5b75505Sopenharmony_ci DPP_EVENT_NET_ACCESS_KEY "%s", hex); 674e5b75505Sopenharmony_ci os_free(hex); 675e5b75505Sopenharmony_ci } 676e5b75505Sopenharmony_ci } 677e5b75505Sopenharmony_ci} 678e5b75505Sopenharmony_ci 679e5b75505Sopenharmony_ci 680e5b75505Sopenharmony_cistatic void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, 681e5b75505Sopenharmony_ci enum gas_query_ap_result result, 682e5b75505Sopenharmony_ci const struct wpabuf *adv_proto, 683e5b75505Sopenharmony_ci const struct wpabuf *resp, u16 status_code) 684e5b75505Sopenharmony_ci{ 685e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 686e5b75505Sopenharmony_ci const u8 *pos; 687e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 688e5b75505Sopenharmony_ci enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED; 689e5b75505Sopenharmony_ci 690e5b75505Sopenharmony_ci if (!auth || !auth->auth_success) { 691e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); 692e5b75505Sopenharmony_ci return; 693e5b75505Sopenharmony_ci } 694e5b75505Sopenharmony_ci if (!resp || status_code != WLAN_STATUS_SUCCESS) { 695e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed"); 696e5b75505Sopenharmony_ci goto fail; 697e5b75505Sopenharmony_ci } 698e5b75505Sopenharmony_ci 699e5b75505Sopenharmony_ci wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto", 700e5b75505Sopenharmony_ci adv_proto); 701e5b75505Sopenharmony_ci wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)", 702e5b75505Sopenharmony_ci resp); 703e5b75505Sopenharmony_ci 704e5b75505Sopenharmony_ci if (wpabuf_len(adv_proto) != 10 || 705e5b75505Sopenharmony_ci !(pos = wpabuf_head(adv_proto)) || 706e5b75505Sopenharmony_ci pos[0] != WLAN_EID_ADV_PROTO || 707e5b75505Sopenharmony_ci pos[1] != 8 || 708e5b75505Sopenharmony_ci pos[3] != WLAN_EID_VENDOR_SPECIFIC || 709e5b75505Sopenharmony_ci pos[4] != 5 || 710e5b75505Sopenharmony_ci WPA_GET_BE24(&pos[5]) != OUI_WFA || 711e5b75505Sopenharmony_ci pos[8] != 0x1a || 712e5b75505Sopenharmony_ci pos[9] != 1) { 713e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 714e5b75505Sopenharmony_ci "DPP: Not a DPP Advertisement Protocol ID"); 715e5b75505Sopenharmony_ci goto fail; 716e5b75505Sopenharmony_ci } 717e5b75505Sopenharmony_ci 718e5b75505Sopenharmony_ci if (dpp_conf_resp_rx(auth, resp) < 0) { 719e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); 720e5b75505Sopenharmony_ci goto fail; 721e5b75505Sopenharmony_ci } 722e5b75505Sopenharmony_ci 723e5b75505Sopenharmony_ci hostapd_dpp_handle_config_obj(hapd, auth); 724e5b75505Sopenharmony_ci status = DPP_STATUS_OK; 725e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 726e5b75505Sopenharmony_ci if (dpp_test == DPP_TEST_REJECT_CONFIG) { 727e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "DPP: TESTING - Reject Config Object"); 728e5b75505Sopenharmony_ci status = DPP_STATUS_CONFIG_REJECTED; 729e5b75505Sopenharmony_ci } 730e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 731e5b75505Sopenharmony_cifail: 732e5b75505Sopenharmony_ci if (status != DPP_STATUS_OK) 733e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED); 734e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 735e5b75505Sopenharmony_ci if (auth->peer_version >= 2 && 736e5b75505Sopenharmony_ci auth->conf_resp_status == DPP_STATUS_OK) { 737e5b75505Sopenharmony_ci struct wpabuf *msg; 738e5b75505Sopenharmony_ci 739e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result"); 740e5b75505Sopenharmony_ci msg = dpp_build_conf_result(auth, status); 741e5b75505Sopenharmony_ci if (!msg) 742e5b75505Sopenharmony_ci goto fail2; 743e5b75505Sopenharmony_ci 744e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, 745e5b75505Sopenharmony_ci DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", 746e5b75505Sopenharmony_ci MAC2STR(addr), auth->curr_freq, 747e5b75505Sopenharmony_ci DPP_PA_CONFIGURATION_RESULT); 748e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, auth->curr_freq, 0, 749e5b75505Sopenharmony_ci addr, wpabuf_head(msg), 750e5b75505Sopenharmony_ci wpabuf_len(msg)); 751e5b75505Sopenharmony_ci wpabuf_free(msg); 752e5b75505Sopenharmony_ci 753e5b75505Sopenharmony_ci /* This exchange will be terminated in the TX status handler */ 754e5b75505Sopenharmony_ci auth->connect_on_tx_status = 1; 755e5b75505Sopenharmony_ci return; 756e5b75505Sopenharmony_ci } 757e5b75505Sopenharmony_cifail2: 758e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 759e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 760e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 761e5b75505Sopenharmony_ci} 762e5b75505Sopenharmony_ci 763e5b75505Sopenharmony_ci 764e5b75505Sopenharmony_cistatic void hostapd_dpp_start_gas_client(struct hostapd_data *hapd) 765e5b75505Sopenharmony_ci{ 766e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 767e5b75505Sopenharmony_ci struct wpabuf *buf; 768e5b75505Sopenharmony_ci char json[100]; 769e5b75505Sopenharmony_ci int res; 770e5b75505Sopenharmony_ci int netrole_ap = 1; 771e5b75505Sopenharmony_ci 772e5b75505Sopenharmony_ci os_snprintf(json, sizeof(json), 773e5b75505Sopenharmony_ci "{\"name\":\"Test\"," 774e5b75505Sopenharmony_ci "\"wi-fi_tech\":\"infra\"," 775e5b75505Sopenharmony_ci "\"netRole\":\"%s\"}", 776e5b75505Sopenharmony_ci netrole_ap ? "ap" : "sta"); 777e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json); 778e5b75505Sopenharmony_ci 779e5b75505Sopenharmony_ci buf = dpp_build_conf_req(auth, json); 780e5b75505Sopenharmony_ci if (!buf) { 781e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 782e5b75505Sopenharmony_ci "DPP: No configuration request data available"); 783e5b75505Sopenharmony_ci return; 784e5b75505Sopenharmony_ci } 785e5b75505Sopenharmony_ci 786e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)", 787e5b75505Sopenharmony_ci MAC2STR(auth->peer_mac_addr), auth->curr_freq); 788e5b75505Sopenharmony_ci 789e5b75505Sopenharmony_ci res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq, 790e5b75505Sopenharmony_ci buf, hostapd_dpp_gas_resp_cb, hapd); 791e5b75505Sopenharmony_ci if (res < 0) { 792e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_DEBUG, 793e5b75505Sopenharmony_ci "GAS: Failed to send Query Request"); 794e5b75505Sopenharmony_ci wpabuf_free(buf); 795e5b75505Sopenharmony_ci } else { 796e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 797e5b75505Sopenharmony_ci "DPP: GAS query started with dialog token %u", res); 798e5b75505Sopenharmony_ci } 799e5b75505Sopenharmony_ci} 800e5b75505Sopenharmony_ci 801e5b75505Sopenharmony_ci 802e5b75505Sopenharmony_cistatic void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator) 803e5b75505Sopenharmony_ci{ 804e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded"); 805e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", 806e5b75505Sopenharmony_ci initiator); 807e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 808e5b75505Sopenharmony_ci if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { 809e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 810e5b75505Sopenharmony_ci "DPP: TESTING - stop at Authentication Confirm"); 811e5b75505Sopenharmony_ci if (hapd->dpp_auth->configurator) { 812e5b75505Sopenharmony_ci /* Prevent GAS response */ 813e5b75505Sopenharmony_ci hapd->dpp_auth->auth_success = 0; 814e5b75505Sopenharmony_ci } 815e5b75505Sopenharmony_ci return; 816e5b75505Sopenharmony_ci } 817e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 818e5b75505Sopenharmony_ci 819e5b75505Sopenharmony_ci if (!hapd->dpp_auth->configurator) 820e5b75505Sopenharmony_ci hostapd_dpp_start_gas_client(hapd); 821e5b75505Sopenharmony_ci} 822e5b75505Sopenharmony_ci 823e5b75505Sopenharmony_ci 824e5b75505Sopenharmony_cistatic void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src, 825e5b75505Sopenharmony_ci const u8 *hdr, const u8 *buf, size_t len, 826e5b75505Sopenharmony_ci unsigned int freq) 827e5b75505Sopenharmony_ci{ 828e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 829e5b75505Sopenharmony_ci struct wpabuf *msg; 830e5b75505Sopenharmony_ci 831e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR, 832e5b75505Sopenharmony_ci MAC2STR(src)); 833e5b75505Sopenharmony_ci 834e5b75505Sopenharmony_ci if (!auth) { 835e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 836e5b75505Sopenharmony_ci "DPP: No DPP Authentication in progress - drop"); 837e5b75505Sopenharmony_ci return; 838e5b75505Sopenharmony_ci } 839e5b75505Sopenharmony_ci 840e5b75505Sopenharmony_ci if (!is_zero_ether_addr(auth->peer_mac_addr) && 841e5b75505Sopenharmony_ci os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { 842e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " 843e5b75505Sopenharmony_ci MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); 844e5b75505Sopenharmony_ci return; 845e5b75505Sopenharmony_ci } 846e5b75505Sopenharmony_ci 847e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); 848e5b75505Sopenharmony_ci 849e5b75505Sopenharmony_ci if (auth->curr_freq != freq && auth->neg_freq == freq) { 850e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 851e5b75505Sopenharmony_ci "DPP: Responder accepted request for different negotiation channel"); 852e5b75505Sopenharmony_ci auth->curr_freq = freq; 853e5b75505Sopenharmony_ci } 854e5b75505Sopenharmony_ci 855e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); 856e5b75505Sopenharmony_ci msg = dpp_auth_resp_rx(auth, hdr, buf, len); 857e5b75505Sopenharmony_ci if (!msg) { 858e5b75505Sopenharmony_ci if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { 859e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Wait for full response"); 860e5b75505Sopenharmony_ci return; 861e5b75505Sopenharmony_ci } 862e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: No confirm generated"); 863e5b75505Sopenharmony_ci return; 864e5b75505Sopenharmony_ci } 865e5b75505Sopenharmony_ci os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); 866e5b75505Sopenharmony_ci 867e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 868e5b75505Sopenharmony_ci " freq=%u type=%d", MAC2STR(src), auth->curr_freq, 869e5b75505Sopenharmony_ci DPP_PA_AUTHENTICATION_CONF); 870e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, auth->curr_freq, 0, src, 871e5b75505Sopenharmony_ci wpabuf_head(msg), wpabuf_len(msg)); 872e5b75505Sopenharmony_ci wpabuf_free(msg); 873e5b75505Sopenharmony_ci hapd->dpp_auth_ok_on_ack = 1; 874e5b75505Sopenharmony_ci} 875e5b75505Sopenharmony_ci 876e5b75505Sopenharmony_ci 877e5b75505Sopenharmony_cistatic void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src, 878e5b75505Sopenharmony_ci const u8 *hdr, const u8 *buf, size_t len) 879e5b75505Sopenharmony_ci{ 880e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 881e5b75505Sopenharmony_ci 882e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR, 883e5b75505Sopenharmony_ci MAC2STR(src)); 884e5b75505Sopenharmony_ci 885e5b75505Sopenharmony_ci if (!auth) { 886e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 887e5b75505Sopenharmony_ci "DPP: No DPP Authentication in progress - drop"); 888e5b75505Sopenharmony_ci return; 889e5b75505Sopenharmony_ci } 890e5b75505Sopenharmony_ci 891e5b75505Sopenharmony_ci if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { 892e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " 893e5b75505Sopenharmony_ci MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); 894e5b75505Sopenharmony_ci return; 895e5b75505Sopenharmony_ci } 896e5b75505Sopenharmony_ci 897e5b75505Sopenharmony_ci if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) { 898e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); 899e5b75505Sopenharmony_ci return; 900e5b75505Sopenharmony_ci } 901e5b75505Sopenharmony_ci 902e5b75505Sopenharmony_ci hostapd_dpp_auth_success(hapd, 0); 903e5b75505Sopenharmony_ci} 904e5b75505Sopenharmony_ci 905e5b75505Sopenharmony_ci 906e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 907e5b75505Sopenharmony_ci 908e5b75505Sopenharmony_cistatic void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx, 909e5b75505Sopenharmony_ci void *timeout_ctx) 910e5b75505Sopenharmony_ci{ 911e5b75505Sopenharmony_ci struct hostapd_data *hapd = eloop_ctx; 912e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 913e5b75505Sopenharmony_ci 914e5b75505Sopenharmony_ci if (!auth || !auth->waiting_conf_result) 915e5b75505Sopenharmony_ci return; 916e5b75505Sopenharmony_ci 917e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 918e5b75505Sopenharmony_ci "DPP: Timeout while waiting for Configuration Result"); 919e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED); 920e5b75505Sopenharmony_ci dpp_auth_deinit(auth); 921e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 922e5b75505Sopenharmony_ci} 923e5b75505Sopenharmony_ci 924e5b75505Sopenharmony_ci 925e5b75505Sopenharmony_cistatic void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src, 926e5b75505Sopenharmony_ci const u8 *hdr, const u8 *buf, size_t len) 927e5b75505Sopenharmony_ci{ 928e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 929e5b75505Sopenharmony_ci enum dpp_status_error status; 930e5b75505Sopenharmony_ci 931e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR, 932e5b75505Sopenharmony_ci MAC2STR(src)); 933e5b75505Sopenharmony_ci 934e5b75505Sopenharmony_ci if (!auth || !auth->waiting_conf_result) { 935e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 936e5b75505Sopenharmony_ci "DPP: No DPP Configuration waiting for result - drop"); 937e5b75505Sopenharmony_ci return; 938e5b75505Sopenharmony_ci } 939e5b75505Sopenharmony_ci 940e5b75505Sopenharmony_ci if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { 941e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " 942e5b75505Sopenharmony_ci MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); 943e5b75505Sopenharmony_ci return; 944e5b75505Sopenharmony_ci } 945e5b75505Sopenharmony_ci 946e5b75505Sopenharmony_ci status = dpp_conf_result_rx(auth, hdr, buf, len); 947e5b75505Sopenharmony_ci 948e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 949e5b75505Sopenharmony_ci hostapd_dpp_listen_stop(hapd); 950e5b75505Sopenharmony_ci if (status == DPP_STATUS_OK) 951e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); 952e5b75505Sopenharmony_ci else 953e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED); 954e5b75505Sopenharmony_ci dpp_auth_deinit(auth); 955e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 956e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd, 957e5b75505Sopenharmony_ci NULL); 958e5b75505Sopenharmony_ci} 959e5b75505Sopenharmony_ci 960e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 961e5b75505Sopenharmony_ci 962e5b75505Sopenharmony_ci 963e5b75505Sopenharmony_cistatic void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd, 964e5b75505Sopenharmony_ci const u8 *src, unsigned int freq, 965e5b75505Sopenharmony_ci u8 trans_id, 966e5b75505Sopenharmony_ci enum dpp_status_error status) 967e5b75505Sopenharmony_ci{ 968e5b75505Sopenharmony_ci struct wpabuf *msg; 969e5b75505Sopenharmony_ci 970e5b75505Sopenharmony_ci msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, 971e5b75505Sopenharmony_ci 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector)); 972e5b75505Sopenharmony_ci if (!msg) 973e5b75505Sopenharmony_ci return; 974e5b75505Sopenharmony_ci 975e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 976e5b75505Sopenharmony_ci if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) { 977e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID"); 978e5b75505Sopenharmony_ci goto skip_trans_id; 979e5b75505Sopenharmony_ci } 980e5b75505Sopenharmony_ci if (dpp_test == DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP) { 981e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "DPP: TESTING - invalid Transaction ID"); 982e5b75505Sopenharmony_ci trans_id ^= 0x01; 983e5b75505Sopenharmony_ci } 984e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 985e5b75505Sopenharmony_ci 986e5b75505Sopenharmony_ci /* Transaction ID */ 987e5b75505Sopenharmony_ci wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); 988e5b75505Sopenharmony_ci wpabuf_put_le16(msg, 1); 989e5b75505Sopenharmony_ci wpabuf_put_u8(msg, trans_id); 990e5b75505Sopenharmony_ci 991e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 992e5b75505Sopenharmony_ciskip_trans_id: 993e5b75505Sopenharmony_ci if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) { 994e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); 995e5b75505Sopenharmony_ci goto skip_status; 996e5b75505Sopenharmony_ci } 997e5b75505Sopenharmony_ci if (dpp_test == DPP_TEST_INVALID_STATUS_PEER_DISC_RESP) { 998e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); 999e5b75505Sopenharmony_ci status = 254; 1000e5b75505Sopenharmony_ci } 1001e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 1002e5b75505Sopenharmony_ci 1003e5b75505Sopenharmony_ci /* DPP Status */ 1004e5b75505Sopenharmony_ci wpabuf_put_le16(msg, DPP_ATTR_STATUS); 1005e5b75505Sopenharmony_ci wpabuf_put_le16(msg, 1); 1006e5b75505Sopenharmony_ci wpabuf_put_u8(msg, status); 1007e5b75505Sopenharmony_ci 1008e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 1009e5b75505Sopenharmony_ciskip_status: 1010e5b75505Sopenharmony_ci if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) { 1011e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "DPP: TESTING - no Connector"); 1012e5b75505Sopenharmony_ci goto skip_connector; 1013e5b75505Sopenharmony_ci } 1014e5b75505Sopenharmony_ci if (status == DPP_STATUS_OK && 1015e5b75505Sopenharmony_ci dpp_test == DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP) { 1016e5b75505Sopenharmony_ci char *connector; 1017e5b75505Sopenharmony_ci 1018e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "DPP: TESTING - invalid Connector"); 1019e5b75505Sopenharmony_ci connector = dpp_corrupt_connector_signature( 1020e5b75505Sopenharmony_ci hapd->conf->dpp_connector); 1021e5b75505Sopenharmony_ci if (!connector) { 1022e5b75505Sopenharmony_ci wpabuf_free(msg); 1023e5b75505Sopenharmony_ci return; 1024e5b75505Sopenharmony_ci } 1025e5b75505Sopenharmony_ci wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); 1026e5b75505Sopenharmony_ci wpabuf_put_le16(msg, os_strlen(connector)); 1027e5b75505Sopenharmony_ci wpabuf_put_str(msg, connector); 1028e5b75505Sopenharmony_ci os_free(connector); 1029e5b75505Sopenharmony_ci goto skip_connector; 1030e5b75505Sopenharmony_ci } 1031e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 1032e5b75505Sopenharmony_ci 1033e5b75505Sopenharmony_ci /* DPP Connector */ 1034e5b75505Sopenharmony_ci if (status == DPP_STATUS_OK) { 1035e5b75505Sopenharmony_ci wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); 1036e5b75505Sopenharmony_ci wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector)); 1037e5b75505Sopenharmony_ci wpabuf_put_str(msg, hapd->conf->dpp_connector); 1038e5b75505Sopenharmony_ci } 1039e5b75505Sopenharmony_ci 1040e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 1041e5b75505Sopenharmony_ciskip_connector: 1042e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 1043e5b75505Sopenharmony_ci 1044e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR 1045e5b75505Sopenharmony_ci " status=%d", MAC2STR(src), status); 1046e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 1047e5b75505Sopenharmony_ci " freq=%u type=%d status=%d", MAC2STR(src), freq, 1048e5b75505Sopenharmony_ci DPP_PA_PEER_DISCOVERY_RESP, status); 1049e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, freq, 0, src, 1050e5b75505Sopenharmony_ci wpabuf_head(msg), wpabuf_len(msg)); 1051e5b75505Sopenharmony_ci wpabuf_free(msg); 1052e5b75505Sopenharmony_ci} 1053e5b75505Sopenharmony_ci 1054e5b75505Sopenharmony_ci 1055e5b75505Sopenharmony_cistatic void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd, 1056e5b75505Sopenharmony_ci const u8 *src, 1057e5b75505Sopenharmony_ci const u8 *buf, size_t len, 1058e5b75505Sopenharmony_ci unsigned int freq) 1059e5b75505Sopenharmony_ci{ 1060e5b75505Sopenharmony_ci const u8 *connector, *trans_id; 1061e5b75505Sopenharmony_ci u16 connector_len, trans_id_len; 1062e5b75505Sopenharmony_ci struct os_time now; 1063e5b75505Sopenharmony_ci struct dpp_introduction intro; 1064e5b75505Sopenharmony_ci os_time_t expire; 1065e5b75505Sopenharmony_ci int expiration; 1066e5b75505Sopenharmony_ci enum dpp_status_error res; 1067e5b75505Sopenharmony_ci 1068e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR, 1069e5b75505Sopenharmony_ci MAC2STR(src)); 1070e5b75505Sopenharmony_ci if (!hapd->wpa_auth || 1071e5b75505Sopenharmony_ci !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) || 1072e5b75505Sopenharmony_ci !(hapd->conf->wpa & WPA_PROTO_RSN)) { 1073e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use"); 1074e5b75505Sopenharmony_ci return; 1075e5b75505Sopenharmony_ci } 1076e5b75505Sopenharmony_ci 1077e5b75505Sopenharmony_ci if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey || 1078e5b75505Sopenharmony_ci !hapd->conf->dpp_csign) { 1079e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set"); 1080e5b75505Sopenharmony_ci return; 1081e5b75505Sopenharmony_ci } 1082e5b75505Sopenharmony_ci 1083e5b75505Sopenharmony_ci os_get_time(&now); 1084e5b75505Sopenharmony_ci 1085e5b75505Sopenharmony_ci if (hapd->conf->dpp_netaccesskey_expiry && 1086e5b75505Sopenharmony_ci (os_time_t) hapd->conf->dpp_netaccesskey_expiry < now.sec) { 1087e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired"); 1088e5b75505Sopenharmony_ci return; 1089e5b75505Sopenharmony_ci } 1090e5b75505Sopenharmony_ci 1091e5b75505Sopenharmony_ci trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID, 1092e5b75505Sopenharmony_ci &trans_id_len); 1093e5b75505Sopenharmony_ci if (!trans_id || trans_id_len != 1) { 1094e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1095e5b75505Sopenharmony_ci "DPP: Peer did not include Transaction ID"); 1096e5b75505Sopenharmony_ci return; 1097e5b75505Sopenharmony_ci } 1098e5b75505Sopenharmony_ci 1099e5b75505Sopenharmony_ci connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len); 1100e5b75505Sopenharmony_ci if (!connector) { 1101e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1102e5b75505Sopenharmony_ci "DPP: Peer did not include its Connector"); 1103e5b75505Sopenharmony_ci return; 1104e5b75505Sopenharmony_ci } 1105e5b75505Sopenharmony_ci 1106e5b75505Sopenharmony_ci res = dpp_peer_intro(&intro, hapd->conf->dpp_connector, 1107e5b75505Sopenharmony_ci wpabuf_head(hapd->conf->dpp_netaccesskey), 1108e5b75505Sopenharmony_ci wpabuf_len(hapd->conf->dpp_netaccesskey), 1109e5b75505Sopenharmony_ci wpabuf_head(hapd->conf->dpp_csign), 1110e5b75505Sopenharmony_ci wpabuf_len(hapd->conf->dpp_csign), 1111e5b75505Sopenharmony_ci connector, connector_len, &expire); 1112e5b75505Sopenharmony_ci if (res == 255) { 1113e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1114e5b75505Sopenharmony_ci "DPP: Network Introduction protocol resulted in internal failure (peer " 1115e5b75505Sopenharmony_ci MACSTR ")", MAC2STR(src)); 1116e5b75505Sopenharmony_ci return; 1117e5b75505Sopenharmony_ci } 1118e5b75505Sopenharmony_ci if (res != DPP_STATUS_OK) { 1119e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 1120e5b75505Sopenharmony_ci "DPP: Network Introduction protocol resulted in failure (peer " 1121e5b75505Sopenharmony_ci MACSTR " status %d)", MAC2STR(src), res); 1122e5b75505Sopenharmony_ci hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0], 1123e5b75505Sopenharmony_ci res); 1124e5b75505Sopenharmony_ci return; 1125e5b75505Sopenharmony_ci } 1126e5b75505Sopenharmony_ci 1127e5b75505Sopenharmony_ci if (!expire || (os_time_t) hapd->conf->dpp_netaccesskey_expiry < expire) 1128e5b75505Sopenharmony_ci expire = hapd->conf->dpp_netaccesskey_expiry; 1129e5b75505Sopenharmony_ci if (expire) 1130e5b75505Sopenharmony_ci expiration = expire - now.sec; 1131e5b75505Sopenharmony_ci else 1132e5b75505Sopenharmony_ci expiration = 0; 1133e5b75505Sopenharmony_ci 1134e5b75505Sopenharmony_ci if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len, 1135e5b75505Sopenharmony_ci intro.pmkid, expiration, 1136e5b75505Sopenharmony_ci WPA_KEY_MGMT_DPP) < 0) { 1137e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry"); 1138e5b75505Sopenharmony_ci return; 1139e5b75505Sopenharmony_ci } 1140e5b75505Sopenharmony_ci 1141e5b75505Sopenharmony_ci hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0], 1142e5b75505Sopenharmony_ci DPP_STATUS_OK); 1143e5b75505Sopenharmony_ci} 1144e5b75505Sopenharmony_ci 1145e5b75505Sopenharmony_ci 1146e5b75505Sopenharmony_cistatic void 1147e5b75505Sopenharmony_cihostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src, 1148e5b75505Sopenharmony_ci const u8 *buf, size_t len, 1149e5b75505Sopenharmony_ci unsigned int freq) 1150e5b75505Sopenharmony_ci{ 1151e5b75505Sopenharmony_ci struct wpabuf *msg; 1152e5b75505Sopenharmony_ci 1153e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR, 1154e5b75505Sopenharmony_ci MAC2STR(src)); 1155e5b75505Sopenharmony_ci 1156e5b75505Sopenharmony_ci /* TODO: Support multiple PKEX codes by iterating over all the enabled 1157e5b75505Sopenharmony_ci * values here */ 1158e5b75505Sopenharmony_ci 1159e5b75505Sopenharmony_ci if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) { 1160e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1161e5b75505Sopenharmony_ci "DPP: No PKEX code configured - ignore request"); 1162e5b75505Sopenharmony_ci return; 1163e5b75505Sopenharmony_ci } 1164e5b75505Sopenharmony_ci 1165e5b75505Sopenharmony_ci if (hapd->dpp_pkex) { 1166e5b75505Sopenharmony_ci /* TODO: Support parallel operations */ 1167e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1168e5b75505Sopenharmony_ci "DPP: Already in PKEX session - ignore new request"); 1169e5b75505Sopenharmony_ci return; 1170e5b75505Sopenharmony_ci } 1171e5b75505Sopenharmony_ci 1172e5b75505Sopenharmony_ci hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx, 1173e5b75505Sopenharmony_ci hapd->dpp_pkex_bi, 1174e5b75505Sopenharmony_ci hapd->own_addr, src, 1175e5b75505Sopenharmony_ci hapd->dpp_pkex_identifier, 1176e5b75505Sopenharmony_ci hapd->dpp_pkex_code, 1177e5b75505Sopenharmony_ci buf, len); 1178e5b75505Sopenharmony_ci if (!hapd->dpp_pkex) { 1179e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1180e5b75505Sopenharmony_ci "DPP: Failed to process the request - ignore it"); 1181e5b75505Sopenharmony_ci return; 1182e5b75505Sopenharmony_ci } 1183e5b75505Sopenharmony_ci 1184e5b75505Sopenharmony_ci msg = hapd->dpp_pkex->exchange_resp; 1185e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 1186e5b75505Sopenharmony_ci " freq=%u type=%d", MAC2STR(src), freq, 1187e5b75505Sopenharmony_ci DPP_PA_PKEX_EXCHANGE_RESP); 1188e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, freq, 0, src, 1189e5b75505Sopenharmony_ci wpabuf_head(msg), wpabuf_len(msg)); 1190e5b75505Sopenharmony_ci if (hapd->dpp_pkex->failed) { 1191e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1192e5b75505Sopenharmony_ci "DPP: Terminate PKEX exchange due to an earlier error"); 1193e5b75505Sopenharmony_ci if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t) 1194e5b75505Sopenharmony_ci hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t; 1195e5b75505Sopenharmony_ci dpp_pkex_free(hapd->dpp_pkex); 1196e5b75505Sopenharmony_ci hapd->dpp_pkex = NULL; 1197e5b75505Sopenharmony_ci } 1198e5b75505Sopenharmony_ci} 1199e5b75505Sopenharmony_ci 1200e5b75505Sopenharmony_ci 1201e5b75505Sopenharmony_cistatic void 1202e5b75505Sopenharmony_cihostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src, 1203e5b75505Sopenharmony_ci const u8 *buf, size_t len, unsigned int freq) 1204e5b75505Sopenharmony_ci{ 1205e5b75505Sopenharmony_ci struct wpabuf *msg; 1206e5b75505Sopenharmony_ci 1207e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR, 1208e5b75505Sopenharmony_ci MAC2STR(src)); 1209e5b75505Sopenharmony_ci 1210e5b75505Sopenharmony_ci /* TODO: Support multiple PKEX codes by iterating over all the enabled 1211e5b75505Sopenharmony_ci * values here */ 1212e5b75505Sopenharmony_ci 1213e5b75505Sopenharmony_ci if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator || 1214e5b75505Sopenharmony_ci hapd->dpp_pkex->exchange_done) { 1215e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); 1216e5b75505Sopenharmony_ci return; 1217e5b75505Sopenharmony_ci } 1218e5b75505Sopenharmony_ci 1219e5b75505Sopenharmony_ci msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len); 1220e5b75505Sopenharmony_ci if (!msg) { 1221e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Failed to process the response"); 1222e5b75505Sopenharmony_ci return; 1223e5b75505Sopenharmony_ci } 1224e5b75505Sopenharmony_ci 1225e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR, 1226e5b75505Sopenharmony_ci MAC2STR(src)); 1227e5b75505Sopenharmony_ci 1228e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 1229e5b75505Sopenharmony_ci " freq=%u type=%d", MAC2STR(src), freq, 1230e5b75505Sopenharmony_ci DPP_PA_PKEX_COMMIT_REVEAL_REQ); 1231e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, freq, 0, src, 1232e5b75505Sopenharmony_ci wpabuf_head(msg), wpabuf_len(msg)); 1233e5b75505Sopenharmony_ci wpabuf_free(msg); 1234e5b75505Sopenharmony_ci} 1235e5b75505Sopenharmony_ci 1236e5b75505Sopenharmony_ci 1237e5b75505Sopenharmony_cistatic void 1238e5b75505Sopenharmony_cihostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src, 1239e5b75505Sopenharmony_ci const u8 *hdr, const u8 *buf, size_t len, 1240e5b75505Sopenharmony_ci unsigned int freq) 1241e5b75505Sopenharmony_ci{ 1242e5b75505Sopenharmony_ci struct wpabuf *msg; 1243e5b75505Sopenharmony_ci struct dpp_pkex *pkex = hapd->dpp_pkex; 1244e5b75505Sopenharmony_ci struct dpp_bootstrap_info *bi; 1245e5b75505Sopenharmony_ci 1246e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR, 1247e5b75505Sopenharmony_ci MAC2STR(src)); 1248e5b75505Sopenharmony_ci 1249e5b75505Sopenharmony_ci if (!pkex || pkex->initiator || !pkex->exchange_done) { 1250e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); 1251e5b75505Sopenharmony_ci return; 1252e5b75505Sopenharmony_ci } 1253e5b75505Sopenharmony_ci 1254e5b75505Sopenharmony_ci msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len); 1255e5b75505Sopenharmony_ci if (!msg) { 1256e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Failed to process the request"); 1257e5b75505Sopenharmony_ci if (hapd->dpp_pkex->failed) { 1258e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange"); 1259e5b75505Sopenharmony_ci if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t) 1260e5b75505Sopenharmony_ci hapd->dpp_pkex->own_bi->pkex_t = 1261e5b75505Sopenharmony_ci hapd->dpp_pkex->t; 1262e5b75505Sopenharmony_ci dpp_pkex_free(hapd->dpp_pkex); 1263e5b75505Sopenharmony_ci hapd->dpp_pkex = NULL; 1264e5b75505Sopenharmony_ci } 1265e5b75505Sopenharmony_ci return; 1266e5b75505Sopenharmony_ci } 1267e5b75505Sopenharmony_ci 1268e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to " 1269e5b75505Sopenharmony_ci MACSTR, MAC2STR(src)); 1270e5b75505Sopenharmony_ci 1271e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 1272e5b75505Sopenharmony_ci " freq=%u type=%d", MAC2STR(src), freq, 1273e5b75505Sopenharmony_ci DPP_PA_PKEX_COMMIT_REVEAL_RESP); 1274e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, freq, 0, src, 1275e5b75505Sopenharmony_ci wpabuf_head(msg), wpabuf_len(msg)); 1276e5b75505Sopenharmony_ci wpabuf_free(msg); 1277e5b75505Sopenharmony_ci 1278e5b75505Sopenharmony_ci bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq); 1279e5b75505Sopenharmony_ci if (!bi) 1280e5b75505Sopenharmony_ci return; 1281e5b75505Sopenharmony_ci hapd->dpp_pkex = NULL; 1282e5b75505Sopenharmony_ci} 1283e5b75505Sopenharmony_ci 1284e5b75505Sopenharmony_ci 1285e5b75505Sopenharmony_cistatic void 1286e5b75505Sopenharmony_cihostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src, 1287e5b75505Sopenharmony_ci const u8 *hdr, const u8 *buf, size_t len, 1288e5b75505Sopenharmony_ci unsigned int freq) 1289e5b75505Sopenharmony_ci{ 1290e5b75505Sopenharmony_ci int res; 1291e5b75505Sopenharmony_ci struct dpp_bootstrap_info *bi; 1292e5b75505Sopenharmony_ci struct dpp_pkex *pkex = hapd->dpp_pkex; 1293e5b75505Sopenharmony_ci char cmd[500]; 1294e5b75505Sopenharmony_ci 1295e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR, 1296e5b75505Sopenharmony_ci MAC2STR(src)); 1297e5b75505Sopenharmony_ci 1298e5b75505Sopenharmony_ci if (!pkex || !pkex->initiator || !pkex->exchange_done) { 1299e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); 1300e5b75505Sopenharmony_ci return; 1301e5b75505Sopenharmony_ci } 1302e5b75505Sopenharmony_ci 1303e5b75505Sopenharmony_ci res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len); 1304e5b75505Sopenharmony_ci if (res < 0) { 1305e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Failed to process the response"); 1306e5b75505Sopenharmony_ci return; 1307e5b75505Sopenharmony_ci } 1308e5b75505Sopenharmony_ci 1309e5b75505Sopenharmony_ci bi = dpp_pkex_finish(hapd->iface->interfaces->dpp, pkex, src, freq); 1310e5b75505Sopenharmony_ci if (!bi) 1311e5b75505Sopenharmony_ci return; 1312e5b75505Sopenharmony_ci hapd->dpp_pkex = NULL; 1313e5b75505Sopenharmony_ci 1314e5b75505Sopenharmony_ci os_snprintf(cmd, sizeof(cmd), " peer=%u %s", 1315e5b75505Sopenharmony_ci bi->id, 1316e5b75505Sopenharmony_ci hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : ""); 1317e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1318e5b75505Sopenharmony_ci "DPP: Start authentication after PKEX with parameters: %s", 1319e5b75505Sopenharmony_ci cmd); 1320e5b75505Sopenharmony_ci if (hostapd_dpp_auth_init(hapd, cmd) < 0) { 1321e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1322e5b75505Sopenharmony_ci "DPP: Authentication initialization failed"); 1323e5b75505Sopenharmony_ci return; 1324e5b75505Sopenharmony_ci } 1325e5b75505Sopenharmony_ci} 1326e5b75505Sopenharmony_ci 1327e5b75505Sopenharmony_ci 1328e5b75505Sopenharmony_civoid hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, 1329e5b75505Sopenharmony_ci const u8 *buf, size_t len, unsigned int freq) 1330e5b75505Sopenharmony_ci{ 1331e5b75505Sopenharmony_ci u8 crypto_suite; 1332e5b75505Sopenharmony_ci enum dpp_public_action_frame_type type; 1333e5b75505Sopenharmony_ci const u8 *hdr; 1334e5b75505Sopenharmony_ci unsigned int pkex_t; 1335e5b75505Sopenharmony_ci 1336e5b75505Sopenharmony_ci if (len < DPP_HDR_LEN) 1337e5b75505Sopenharmony_ci return; 1338e5b75505Sopenharmony_ci if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE) 1339e5b75505Sopenharmony_ci return; 1340e5b75505Sopenharmony_ci hdr = buf; 1341e5b75505Sopenharmony_ci buf += 4; 1342e5b75505Sopenharmony_ci len -= 4; 1343e5b75505Sopenharmony_ci crypto_suite = *buf++; 1344e5b75505Sopenharmony_ci type = *buf++; 1345e5b75505Sopenharmony_ci len -= 2; 1346e5b75505Sopenharmony_ci 1347e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1348e5b75505Sopenharmony_ci "DPP: Received DPP Public Action frame crypto suite %u type %d from " 1349e5b75505Sopenharmony_ci MACSTR " freq=%u", 1350e5b75505Sopenharmony_ci crypto_suite, type, MAC2STR(src), freq); 1351e5b75505Sopenharmony_ci if (crypto_suite != 1) { 1352e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u", 1353e5b75505Sopenharmony_ci crypto_suite); 1354e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR 1355e5b75505Sopenharmony_ci " freq=%u type=%d ignore=unsupported-crypto-suite", 1356e5b75505Sopenharmony_ci MAC2STR(src), freq, type); 1357e5b75505Sopenharmony_ci return; 1358e5b75505Sopenharmony_ci } 1359e5b75505Sopenharmony_ci wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len); 1360e5b75505Sopenharmony_ci if (dpp_check_attrs(buf, len) < 0) { 1361e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR 1362e5b75505Sopenharmony_ci " freq=%u type=%d ignore=invalid-attributes", 1363e5b75505Sopenharmony_ci MAC2STR(src), freq, type); 1364e5b75505Sopenharmony_ci return; 1365e5b75505Sopenharmony_ci } 1366e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR 1367e5b75505Sopenharmony_ci " freq=%u type=%d", MAC2STR(src), freq, type); 1368e5b75505Sopenharmony_ci 1369e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 1370e5b75505Sopenharmony_ci if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, 1371e5b75505Sopenharmony_ci src, hdr, buf, len, freq, NULL, NULL) == 0) 1372e5b75505Sopenharmony_ci return; 1373e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 1374e5b75505Sopenharmony_ci 1375e5b75505Sopenharmony_ci switch (type) { 1376e5b75505Sopenharmony_ci case DPP_PA_AUTHENTICATION_REQ: 1377e5b75505Sopenharmony_ci hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq); 1378e5b75505Sopenharmony_ci break; 1379e5b75505Sopenharmony_ci case DPP_PA_AUTHENTICATION_RESP: 1380e5b75505Sopenharmony_ci hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len, freq); 1381e5b75505Sopenharmony_ci break; 1382e5b75505Sopenharmony_ci case DPP_PA_AUTHENTICATION_CONF: 1383e5b75505Sopenharmony_ci hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len); 1384e5b75505Sopenharmony_ci break; 1385e5b75505Sopenharmony_ci case DPP_PA_PEER_DISCOVERY_REQ: 1386e5b75505Sopenharmony_ci hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq); 1387e5b75505Sopenharmony_ci break; 1388e5b75505Sopenharmony_ci case DPP_PA_PKEX_EXCHANGE_REQ: 1389e5b75505Sopenharmony_ci hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq); 1390e5b75505Sopenharmony_ci break; 1391e5b75505Sopenharmony_ci case DPP_PA_PKEX_EXCHANGE_RESP: 1392e5b75505Sopenharmony_ci hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq); 1393e5b75505Sopenharmony_ci break; 1394e5b75505Sopenharmony_ci case DPP_PA_PKEX_COMMIT_REVEAL_REQ: 1395e5b75505Sopenharmony_ci hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len, 1396e5b75505Sopenharmony_ci freq); 1397e5b75505Sopenharmony_ci break; 1398e5b75505Sopenharmony_ci case DPP_PA_PKEX_COMMIT_REVEAL_RESP: 1399e5b75505Sopenharmony_ci hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len, 1400e5b75505Sopenharmony_ci freq); 1401e5b75505Sopenharmony_ci break; 1402e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 1403e5b75505Sopenharmony_ci case DPP_PA_CONFIGURATION_RESULT: 1404e5b75505Sopenharmony_ci hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len); 1405e5b75505Sopenharmony_ci break; 1406e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 1407e5b75505Sopenharmony_ci default: 1408e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1409e5b75505Sopenharmony_ci "DPP: Ignored unsupported frame subtype %d", type); 1410e5b75505Sopenharmony_ci break; 1411e5b75505Sopenharmony_ci } 1412e5b75505Sopenharmony_ci 1413e5b75505Sopenharmony_ci if (hapd->dpp_pkex) 1414e5b75505Sopenharmony_ci pkex_t = hapd->dpp_pkex->t; 1415e5b75505Sopenharmony_ci else if (hapd->dpp_pkex_bi) 1416e5b75505Sopenharmony_ci pkex_t = hapd->dpp_pkex_bi->pkex_t; 1417e5b75505Sopenharmony_ci else 1418e5b75505Sopenharmony_ci pkex_t = 0; 1419e5b75505Sopenharmony_ci if (pkex_t >= PKEX_COUNTER_T_LIMIT) { 1420e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0"); 1421e5b75505Sopenharmony_ci hostapd_dpp_pkex_remove(hapd, "*"); 1422e5b75505Sopenharmony_ci } 1423e5b75505Sopenharmony_ci} 1424e5b75505Sopenharmony_ci 1425e5b75505Sopenharmony_ci 1426e5b75505Sopenharmony_cistruct wpabuf * 1427e5b75505Sopenharmony_cihostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, 1428e5b75505Sopenharmony_ci const u8 *query, size_t query_len, 1429e5b75505Sopenharmony_ci const u8 *data, size_t data_len) 1430e5b75505Sopenharmony_ci{ 1431e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 1432e5b75505Sopenharmony_ci struct wpabuf *resp; 1433e5b75505Sopenharmony_ci 1434e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa)); 1435e5b75505Sopenharmony_ci if (!auth || !auth->auth_success || 1436e5b75505Sopenharmony_ci os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { 1437e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 1438e5b75505Sopenharmony_ci if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data, 1439e5b75505Sopenharmony_ci data_len) == 0) { 1440e5b75505Sopenharmony_ci /* Response will be forwarded once received over TCP */ 1441e5b75505Sopenharmony_ci return NULL; 1442e5b75505Sopenharmony_ci } 1443e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 1444e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); 1445e5b75505Sopenharmony_ci return NULL; 1446e5b75505Sopenharmony_ci } 1447e5b75505Sopenharmony_ci wpa_hexdump(MSG_DEBUG, 1448e5b75505Sopenharmony_ci "DPP: Received Configuration Request (GAS Query Request)", 1449e5b75505Sopenharmony_ci query, query_len); 1450e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR, 1451e5b75505Sopenharmony_ci MAC2STR(sa)); 1452e5b75505Sopenharmony_ci resp = dpp_conf_req_rx(auth, query, query_len); 1453e5b75505Sopenharmony_ci if (!resp) 1454e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED); 1455e5b75505Sopenharmony_ci return resp; 1456e5b75505Sopenharmony_ci} 1457e5b75505Sopenharmony_ci 1458e5b75505Sopenharmony_ci 1459e5b75505Sopenharmony_civoid hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok) 1460e5b75505Sopenharmony_ci{ 1461e5b75505Sopenharmony_ci struct dpp_authentication *auth = hapd->dpp_auth; 1462e5b75505Sopenharmony_ci 1463e5b75505Sopenharmony_ci if (!auth) 1464e5b75505Sopenharmony_ci return; 1465e5b75505Sopenharmony_ci 1466e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)", 1467e5b75505Sopenharmony_ci ok); 1468e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); 1469e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); 1470e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 1471e5b75505Sopenharmony_ci if (ok && auth->peer_version >= 2 && 1472e5b75505Sopenharmony_ci auth->conf_resp_status == DPP_STATUS_OK) { 1473e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); 1474e5b75505Sopenharmony_ci auth->waiting_conf_result = 1; 1475e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, 1476e5b75505Sopenharmony_ci hapd, NULL); 1477e5b75505Sopenharmony_ci eloop_register_timeout(2, 0, 1478e5b75505Sopenharmony_ci hostapd_dpp_config_result_wait_timeout, 1479e5b75505Sopenharmony_ci hapd, NULL); 1480e5b75505Sopenharmony_ci return; 1481e5b75505Sopenharmony_ci } 1482e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 1483e5b75505Sopenharmony_ci hostapd_drv_send_action_cancel_wait(hapd); 1484e5b75505Sopenharmony_ci 1485e5b75505Sopenharmony_ci if (ok) 1486e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); 1487e5b75505Sopenharmony_ci else 1488e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED); 1489e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 1490e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 1491e5b75505Sopenharmony_ci} 1492e5b75505Sopenharmony_ci 1493e5b75505Sopenharmony_ci 1494e5b75505Sopenharmony_ciint hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd) 1495e5b75505Sopenharmony_ci{ 1496e5b75505Sopenharmony_ci struct dpp_authentication *auth; 1497e5b75505Sopenharmony_ci int ret = -1; 1498e5b75505Sopenharmony_ci char *curve = NULL; 1499e5b75505Sopenharmony_ci 1500e5b75505Sopenharmony_ci auth = os_zalloc(sizeof(*auth)); 1501e5b75505Sopenharmony_ci if (!auth) 1502e5b75505Sopenharmony_ci return -1; 1503e5b75505Sopenharmony_ci 1504e5b75505Sopenharmony_ci curve = get_param(cmd, " curve="); 1505e5b75505Sopenharmony_ci hostapd_dpp_set_testing_options(hapd, auth); 1506e5b75505Sopenharmony_ci if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, 1507e5b75505Sopenharmony_ci auth, cmd) == 0 && 1508e5b75505Sopenharmony_ci dpp_configurator_own_config(auth, curve, 1) == 0) { 1509e5b75505Sopenharmony_ci hostapd_dpp_handle_config_obj(hapd, auth); 1510e5b75505Sopenharmony_ci ret = 0; 1511e5b75505Sopenharmony_ci } 1512e5b75505Sopenharmony_ci 1513e5b75505Sopenharmony_ci dpp_auth_deinit(auth); 1514e5b75505Sopenharmony_ci os_free(curve); 1515e5b75505Sopenharmony_ci 1516e5b75505Sopenharmony_ci return ret; 1517e5b75505Sopenharmony_ci} 1518e5b75505Sopenharmony_ci 1519e5b75505Sopenharmony_ci 1520e5b75505Sopenharmony_ciint hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd) 1521e5b75505Sopenharmony_ci{ 1522e5b75505Sopenharmony_ci struct dpp_bootstrap_info *own_bi; 1523e5b75505Sopenharmony_ci const char *pos, *end; 1524e5b75505Sopenharmony_ci 1525e5b75505Sopenharmony_ci pos = os_strstr(cmd, " own="); 1526e5b75505Sopenharmony_ci if (!pos) 1527e5b75505Sopenharmony_ci return -1; 1528e5b75505Sopenharmony_ci pos += 5; 1529e5b75505Sopenharmony_ci own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos)); 1530e5b75505Sopenharmony_ci if (!own_bi) { 1531e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1532e5b75505Sopenharmony_ci "DPP: Identified bootstrap info not found"); 1533e5b75505Sopenharmony_ci return -1; 1534e5b75505Sopenharmony_ci } 1535e5b75505Sopenharmony_ci if (own_bi->type != DPP_BOOTSTRAP_PKEX) { 1536e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, 1537e5b75505Sopenharmony_ci "DPP: Identified bootstrap info not for PKEX"); 1538e5b75505Sopenharmony_ci return -1; 1539e5b75505Sopenharmony_ci } 1540e5b75505Sopenharmony_ci hapd->dpp_pkex_bi = own_bi; 1541e5b75505Sopenharmony_ci own_bi->pkex_t = 0; /* clear pending errors on new code */ 1542e5b75505Sopenharmony_ci 1543e5b75505Sopenharmony_ci os_free(hapd->dpp_pkex_identifier); 1544e5b75505Sopenharmony_ci hapd->dpp_pkex_identifier = NULL; 1545e5b75505Sopenharmony_ci pos = os_strstr(cmd, " identifier="); 1546e5b75505Sopenharmony_ci if (pos) { 1547e5b75505Sopenharmony_ci pos += 12; 1548e5b75505Sopenharmony_ci end = os_strchr(pos, ' '); 1549e5b75505Sopenharmony_ci if (!end) 1550e5b75505Sopenharmony_ci return -1; 1551e5b75505Sopenharmony_ci hapd->dpp_pkex_identifier = os_malloc(end - pos + 1); 1552e5b75505Sopenharmony_ci if (!hapd->dpp_pkex_identifier) 1553e5b75505Sopenharmony_ci return -1; 1554e5b75505Sopenharmony_ci os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos); 1555e5b75505Sopenharmony_ci hapd->dpp_pkex_identifier[end - pos] = '\0'; 1556e5b75505Sopenharmony_ci } 1557e5b75505Sopenharmony_ci 1558e5b75505Sopenharmony_ci pos = os_strstr(cmd, " code="); 1559e5b75505Sopenharmony_ci if (!pos) 1560e5b75505Sopenharmony_ci return -1; 1561e5b75505Sopenharmony_ci os_free(hapd->dpp_pkex_code); 1562e5b75505Sopenharmony_ci hapd->dpp_pkex_code = os_strdup(pos + 6); 1563e5b75505Sopenharmony_ci if (!hapd->dpp_pkex_code) 1564e5b75505Sopenharmony_ci return -1; 1565e5b75505Sopenharmony_ci 1566e5b75505Sopenharmony_ci if (os_strstr(cmd, " init=1")) { 1567e5b75505Sopenharmony_ci struct wpabuf *msg; 1568e5b75505Sopenharmony_ci 1569e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX"); 1570e5b75505Sopenharmony_ci dpp_pkex_free(hapd->dpp_pkex); 1571e5b75505Sopenharmony_ci hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi, 1572e5b75505Sopenharmony_ci hapd->own_addr, 1573e5b75505Sopenharmony_ci hapd->dpp_pkex_identifier, 1574e5b75505Sopenharmony_ci hapd->dpp_pkex_code); 1575e5b75505Sopenharmony_ci if (!hapd->dpp_pkex) 1576e5b75505Sopenharmony_ci return -1; 1577e5b75505Sopenharmony_ci 1578e5b75505Sopenharmony_ci msg = hapd->dpp_pkex->exchange_req; 1579e5b75505Sopenharmony_ci /* TODO: Which channel to use? */ 1580e5b75505Sopenharmony_ci wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR 1581e5b75505Sopenharmony_ci " freq=%u type=%d", MAC2STR(broadcast), 2437, 1582e5b75505Sopenharmony_ci DPP_PA_PKEX_EXCHANGE_REQ); 1583e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, 2437, 0, broadcast, 1584e5b75505Sopenharmony_ci wpabuf_head(msg), wpabuf_len(msg)); 1585e5b75505Sopenharmony_ci } 1586e5b75505Sopenharmony_ci 1587e5b75505Sopenharmony_ci /* TODO: Support multiple PKEX info entries */ 1588e5b75505Sopenharmony_ci 1589e5b75505Sopenharmony_ci os_free(hapd->dpp_pkex_auth_cmd); 1590e5b75505Sopenharmony_ci hapd->dpp_pkex_auth_cmd = os_strdup(cmd); 1591e5b75505Sopenharmony_ci 1592e5b75505Sopenharmony_ci return 1; 1593e5b75505Sopenharmony_ci} 1594e5b75505Sopenharmony_ci 1595e5b75505Sopenharmony_ci 1596e5b75505Sopenharmony_ciint hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id) 1597e5b75505Sopenharmony_ci{ 1598e5b75505Sopenharmony_ci unsigned int id_val; 1599e5b75505Sopenharmony_ci 1600e5b75505Sopenharmony_ci if (os_strcmp(id, "*") == 0) { 1601e5b75505Sopenharmony_ci id_val = 0; 1602e5b75505Sopenharmony_ci } else { 1603e5b75505Sopenharmony_ci id_val = atoi(id); 1604e5b75505Sopenharmony_ci if (id_val == 0) 1605e5b75505Sopenharmony_ci return -1; 1606e5b75505Sopenharmony_ci } 1607e5b75505Sopenharmony_ci 1608e5b75505Sopenharmony_ci if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code) 1609e5b75505Sopenharmony_ci return -1; 1610e5b75505Sopenharmony_ci 1611e5b75505Sopenharmony_ci /* TODO: Support multiple PKEX entries */ 1612e5b75505Sopenharmony_ci os_free(hapd->dpp_pkex_code); 1613e5b75505Sopenharmony_ci hapd->dpp_pkex_code = NULL; 1614e5b75505Sopenharmony_ci os_free(hapd->dpp_pkex_identifier); 1615e5b75505Sopenharmony_ci hapd->dpp_pkex_identifier = NULL; 1616e5b75505Sopenharmony_ci os_free(hapd->dpp_pkex_auth_cmd); 1617e5b75505Sopenharmony_ci hapd->dpp_pkex_auth_cmd = NULL; 1618e5b75505Sopenharmony_ci hapd->dpp_pkex_bi = NULL; 1619e5b75505Sopenharmony_ci /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */ 1620e5b75505Sopenharmony_ci dpp_pkex_free(hapd->dpp_pkex); 1621e5b75505Sopenharmony_ci hapd->dpp_pkex = NULL; 1622e5b75505Sopenharmony_ci return 0; 1623e5b75505Sopenharmony_ci} 1624e5b75505Sopenharmony_ci 1625e5b75505Sopenharmony_ci 1626e5b75505Sopenharmony_civoid hostapd_dpp_stop(struct hostapd_data *hapd) 1627e5b75505Sopenharmony_ci{ 1628e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 1629e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 1630e5b75505Sopenharmony_ci dpp_pkex_free(hapd->dpp_pkex); 1631e5b75505Sopenharmony_ci hapd->dpp_pkex = NULL; 1632e5b75505Sopenharmony_ci} 1633e5b75505Sopenharmony_ci 1634e5b75505Sopenharmony_ci 1635e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 1636e5b75505Sopenharmony_ci 1637e5b75505Sopenharmony_cistatic void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq, 1638e5b75505Sopenharmony_ci const u8 *msg, size_t len) 1639e5b75505Sopenharmony_ci{ 1640e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 1641e5b75505Sopenharmony_ci u8 *buf; 1642e5b75505Sopenharmony_ci 1643e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u", 1644e5b75505Sopenharmony_ci MAC2STR(addr), freq); 1645e5b75505Sopenharmony_ci buf = os_malloc(2 + len); 1646e5b75505Sopenharmony_ci if (!buf) 1647e5b75505Sopenharmony_ci return; 1648e5b75505Sopenharmony_ci buf[0] = WLAN_ACTION_PUBLIC; 1649e5b75505Sopenharmony_ci buf[1] = WLAN_PA_VENDOR_SPECIFIC; 1650e5b75505Sopenharmony_ci os_memcpy(buf + 2, msg, len); 1651e5b75505Sopenharmony_ci hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len); 1652e5b75505Sopenharmony_ci os_free(buf); 1653e5b75505Sopenharmony_ci} 1654e5b75505Sopenharmony_ci 1655e5b75505Sopenharmony_ci 1656e5b75505Sopenharmony_cistatic void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr, 1657e5b75505Sopenharmony_ci u8 dialog_token, int prot, 1658e5b75505Sopenharmony_ci struct wpabuf *buf) 1659e5b75505Sopenharmony_ci{ 1660e5b75505Sopenharmony_ci struct hostapd_data *hapd = ctx; 1661e5b75505Sopenharmony_ci 1662e5b75505Sopenharmony_ci gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf); 1663e5b75505Sopenharmony_ci} 1664e5b75505Sopenharmony_ci 1665e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 1666e5b75505Sopenharmony_ci 1667e5b75505Sopenharmony_ci 1668e5b75505Sopenharmony_cistatic int hostapd_dpp_add_controllers(struct hostapd_data *hapd) 1669e5b75505Sopenharmony_ci{ 1670e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 1671e5b75505Sopenharmony_ci struct dpp_controller_conf *ctrl; 1672e5b75505Sopenharmony_ci struct dpp_relay_config config; 1673e5b75505Sopenharmony_ci 1674e5b75505Sopenharmony_ci os_memset(&config, 0, sizeof(config)); 1675e5b75505Sopenharmony_ci config.cb_ctx = hapd; 1676e5b75505Sopenharmony_ci config.tx = hostapd_dpp_relay_tx; 1677e5b75505Sopenharmony_ci config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx; 1678e5b75505Sopenharmony_ci for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) { 1679e5b75505Sopenharmony_ci config.ipaddr = &ctrl->ipaddr; 1680e5b75505Sopenharmony_ci config.pkhash = ctrl->pkhash; 1681e5b75505Sopenharmony_ci if (dpp_relay_add_controller(hapd->iface->interfaces->dpp, 1682e5b75505Sopenharmony_ci &config) < 0) 1683e5b75505Sopenharmony_ci return -1; 1684e5b75505Sopenharmony_ci } 1685e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 1686e5b75505Sopenharmony_ci 1687e5b75505Sopenharmony_ci return 0; 1688e5b75505Sopenharmony_ci} 1689e5b75505Sopenharmony_ci 1690e5b75505Sopenharmony_ci 1691e5b75505Sopenharmony_ciint hostapd_dpp_init(struct hostapd_data *hapd) 1692e5b75505Sopenharmony_ci{ 1693e5b75505Sopenharmony_ci hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE; 1694e5b75505Sopenharmony_ci hapd->dpp_init_done = 1; 1695e5b75505Sopenharmony_ci return hostapd_dpp_add_controllers(hapd); 1696e5b75505Sopenharmony_ci} 1697e5b75505Sopenharmony_ci 1698e5b75505Sopenharmony_ci 1699e5b75505Sopenharmony_civoid hostapd_dpp_deinit(struct hostapd_data *hapd) 1700e5b75505Sopenharmony_ci{ 1701e5b75505Sopenharmony_ci#ifdef CONFIG_TESTING_OPTIONS 1702e5b75505Sopenharmony_ci os_free(hapd->dpp_config_obj_override); 1703e5b75505Sopenharmony_ci hapd->dpp_config_obj_override = NULL; 1704e5b75505Sopenharmony_ci os_free(hapd->dpp_discovery_override); 1705e5b75505Sopenharmony_ci hapd->dpp_discovery_override = NULL; 1706e5b75505Sopenharmony_ci os_free(hapd->dpp_groups_override); 1707e5b75505Sopenharmony_ci hapd->dpp_groups_override = NULL; 1708e5b75505Sopenharmony_ci hapd->dpp_ignore_netaccesskey_mismatch = 0; 1709e5b75505Sopenharmony_ci#endif /* CONFIG_TESTING_OPTIONS */ 1710e5b75505Sopenharmony_ci if (!hapd->dpp_init_done) 1711e5b75505Sopenharmony_ci return; 1712e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); 1713e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); 1714e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); 1715e5b75505Sopenharmony_ci#ifdef CONFIG_DPP2 1716e5b75505Sopenharmony_ci eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd, 1717e5b75505Sopenharmony_ci NULL); 1718e5b75505Sopenharmony_ci#endif /* CONFIG_DPP2 */ 1719e5b75505Sopenharmony_ci dpp_auth_deinit(hapd->dpp_auth); 1720e5b75505Sopenharmony_ci hapd->dpp_auth = NULL; 1721e5b75505Sopenharmony_ci hostapd_dpp_pkex_remove(hapd, "*"); 1722e5b75505Sopenharmony_ci hapd->dpp_pkex = NULL; 1723e5b75505Sopenharmony_ci os_free(hapd->dpp_configurator_params); 1724e5b75505Sopenharmony_ci hapd->dpp_configurator_params = NULL; 1725e5b75505Sopenharmony_ci} 1726