DPP2: Configuration Result message generation and processing
Use this new message from Enrollee to Configurator to indicate result of the config object provisioning if both devices support protocol version 2 or newer. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
8b6c834ff9
commit
22f90b32f1
4 changed files with 456 additions and 30 deletions
|
@ -354,6 +354,16 @@ void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
if (auth->connect_on_tx_status) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Complete exchange on configuration result");
|
||||
dpp_auth_deinit(hapd->dpp_auth);
|
||||
hapd->dpp_auth = NULL;
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
if (hapd->dpp_auth->remove_on_tx_status) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Terminate authentication exchange due to an earlier error");
|
||||
|
@ -1072,6 +1082,7 @@ static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||
struct hostapd_data *hapd = ctx;
|
||||
const u8 *pos;
|
||||
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||
enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
|
||||
|
||||
if (!auth || !auth->auth_success) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
|
||||
|
@ -1107,12 +1118,35 @@ static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||
}
|
||||
|
||||
hostapd_dpp_handle_config_obj(hapd, auth);
|
||||
dpp_auth_deinit(hapd->dpp_auth);
|
||||
hapd->dpp_auth = NULL;
|
||||
return;
|
||||
|
||||
status = DPP_STATUS_OK;
|
||||
fail:
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
if (status != DPP_STATUS_OK)
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
#ifdef CONFIG_DPP2
|
||||
if (auth->peer_version >= 2 &&
|
||||
auth->conf_resp_status == DPP_STATUS_OK) {
|
||||
struct wpabuf *msg;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
|
||||
msg = dpp_build_conf_result(auth, status);
|
||||
if (!msg)
|
||||
goto fail2;
|
||||
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||
DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
|
||||
MAC2STR(addr), auth->curr_freq,
|
||||
DPP_PA_CONFIGURATION_RESULT);
|
||||
hostapd_drv_send_action(hapd, auth->curr_freq, 0,
|
||||
addr, wpabuf_head(msg),
|
||||
wpabuf_len(msg));
|
||||
wpabuf_free(msg);
|
||||
|
||||
/* This exchange will be terminated in the TX status handler */
|
||||
auth->connect_on_tx_status = 1;
|
||||
return;
|
||||
}
|
||||
fail2:
|
||||
#endif /* CONFIG_DPP2 */
|
||||
dpp_auth_deinit(hapd->dpp_auth);
|
||||
hapd->dpp_auth = NULL;
|
||||
}
|
||||
|
@ -1281,6 +1315,63 @@ static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
|
||||
static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
|
||||
void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||
|
||||
if (!auth || !auth->waiting_conf_result)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Timeout while waiting for Configuration Result");
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
dpp_auth_deinit(auth);
|
||||
hapd->dpp_auth = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
|
||||
const u8 *hdr, const u8 *buf, size_t len)
|
||||
{
|
||||
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||
enum dpp_status_error status;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
|
||||
MAC2STR(src));
|
||||
|
||||
if (!auth || !auth->waiting_conf_result) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: No DPP Configuration waiting for result - drop");
|
||||
return;
|
||||
}
|
||||
|
||||
if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
|
||||
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
|
||||
return;
|
||||
}
|
||||
|
||||
status = dpp_conf_result_rx(auth, hdr, buf, len);
|
||||
|
||||
hostapd_drv_send_action_cancel_wait(hapd);
|
||||
hostapd_dpp_listen_stop(hapd);
|
||||
if (status == DPP_STATUS_OK)
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
|
||||
else
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
dpp_auth_deinit(auth);
|
||||
hapd->dpp_auth = NULL;
|
||||
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
|
||||
static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
|
||||
const u8 *src, unsigned int freq,
|
||||
u8 trans_id,
|
||||
|
@ -1744,6 +1835,11 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
|
|||
hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
|
||||
freq);
|
||||
break;
|
||||
#ifdef CONFIG_DPP2
|
||||
case DPP_PA_CONFIGURATION_RESULT:
|
||||
hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
|
||||
break;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Ignored unsupported frame subtype %d", type);
|
||||
|
@ -1790,11 +1886,28 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
|
|||
|
||||
void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
|
||||
{
|
||||
if (!hapd->dpp_auth)
|
||||
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||
|
||||
if (!auth)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
|
||||
ok);
|
||||
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
|
||||
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
|
||||
#ifdef CONFIG_DPP2
|
||||
if (ok && auth->peer_version >= 2 &&
|
||||
auth->conf_resp_status == DPP_STATUS_OK) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
|
||||
auth->waiting_conf_result = 1;
|
||||
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
|
||||
hapd, NULL);
|
||||
eloop_register_timeout(2, 0,
|
||||
hostapd_dpp_config_result_wait_timeout,
|
||||
hapd, NULL);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
hostapd_drv_send_action_cancel_wait(hapd);
|
||||
|
||||
if (ok)
|
||||
|
@ -2070,6 +2183,10 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
|
|||
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
|
||||
eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL);
|
||||
eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL);
|
||||
#ifdef CONFIG_DPP2
|
||||
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
|
||||
NULL);
|
||||
#endif /* CONFIG_DPP2 */
|
||||
dpp_auth_deinit(hapd->dpp_auth);
|
||||
hapd->dpp_auth = NULL;
|
||||
hostapd_dpp_pkex_remove(hapd, "*");
|
||||
|
|
145
src/common/dpp.c
145
src/common/dpp.c
|
@ -4441,6 +4441,7 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
|
|||
wpabuf_head(conf), wpabuf_len(conf));
|
||||
}
|
||||
status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE;
|
||||
auth->conf_resp_status = status;
|
||||
|
||||
/* { E-nonce, configurationObject}ke */
|
||||
clear_len = 4 + e_nonce_len;
|
||||
|
@ -4613,6 +4614,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
|||
goto fail;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
|
||||
os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
|
||||
|
||||
config_attr = dpp_get_attr(unwrapped, unwrapped_len,
|
||||
DPP_ATTR_CONFIG_ATTR_OBJ,
|
||||
|
@ -5486,6 +5488,8 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
|||
size_t unwrapped_len = 0;
|
||||
int ret = -1;
|
||||
|
||||
auth->conf_resp_status = 255;
|
||||
|
||||
if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) {
|
||||
dpp_auth_fail(auth, "Invalid attribute in config response");
|
||||
return -1;
|
||||
|
@ -5546,6 +5550,7 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
|||
"Missing or invalid required DPP Status attribute");
|
||||
goto fail;
|
||||
}
|
||||
auth->conf_resp_status = status[0];
|
||||
wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
|
||||
if (status[0] != DPP_STATUS_OK) {
|
||||
dpp_auth_fail(auth, "Configurator rejected configuration");
|
||||
|
@ -5572,6 +5577,146 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
|
||||
const u8 *hdr,
|
||||
const u8 *attr_start, size_t attr_len)
|
||||
{
|
||||
const u8 *wrapped_data, *status, *e_nonce;
|
||||
u16 wrapped_data_len, status_len, e_nonce_len;
|
||||
const u8 *addr[2];
|
||||
size_t len[2];
|
||||
u8 *unwrapped = NULL;
|
||||
size_t unwrapped_len = 0;
|
||||
enum dpp_status_error ret = 256;
|
||||
|
||||
wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
|
||||
&wrapped_data_len);
|
||||
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
|
||||
dpp_auth_fail(auth,
|
||||
"Missing or invalid required Wrapped Data attribute");
|
||||
goto fail;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
|
||||
wrapped_data, wrapped_data_len);
|
||||
|
||||
attr_len = wrapped_data - 4 - attr_start;
|
||||
|
||||
addr[0] = hdr;
|
||||
len[0] = DPP_HDR_LEN;
|
||||
addr[1] = attr_start;
|
||||
len[1] = attr_len;
|
||||
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
|
||||
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
|
||||
wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
|
||||
wrapped_data, wrapped_data_len);
|
||||
unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
|
||||
unwrapped = os_malloc(unwrapped_len);
|
||||
if (!unwrapped)
|
||||
goto fail;
|
||||
if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
|
||||
wrapped_data, wrapped_data_len,
|
||||
2, addr, len, unwrapped) < 0) {
|
||||
dpp_auth_fail(auth, "AES-SIV decryption failed");
|
||||
goto fail;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
|
||||
unwrapped, unwrapped_len);
|
||||
|
||||
if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
|
||||
dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
|
||||
DPP_ATTR_ENROLLEE_NONCE,
|
||||
&e_nonce_len);
|
||||
if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
|
||||
dpp_auth_fail(auth,
|
||||
"Missing or invalid Enrollee Nonce attribute");
|
||||
goto fail;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
|
||||
if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
|
||||
dpp_auth_fail(auth, "Enrollee Nonce mismatch");
|
||||
wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce",
|
||||
auth->e_nonce, e_nonce_len);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_STATUS,
|
||||
&status_len);
|
||||
if (!status || status_len < 1) {
|
||||
dpp_auth_fail(auth,
|
||||
"Missing or invalid required DPP Status attribute");
|
||||
goto fail;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
|
||||
ret = status[0];
|
||||
|
||||
fail:
|
||||
bin_clear_free(unwrapped, unwrapped_len);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
|
||||
struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
|
||||
enum dpp_status_error status)
|
||||
{
|
||||
struct wpabuf *msg, *clear;
|
||||
size_t nonce_len, clear_len, attr_len;
|
||||
const u8 *addr[2];
|
||||
size_t len[2];
|
||||
u8 *wrapped;
|
||||
|
||||
nonce_len = auth->curve->nonce_len;
|
||||
clear_len = 5 + 4 + nonce_len;
|
||||
attr_len = 4 + clear_len + AES_BLOCK_SIZE;
|
||||
clear = wpabuf_alloc(clear_len);
|
||||
msg = dpp_alloc_msg(DPP_PA_CONFIGURATION_RESULT, attr_len);
|
||||
if (!clear || !msg)
|
||||
return NULL;
|
||||
|
||||
/* DPP Status */
|
||||
dpp_build_attr_status(clear, status);
|
||||
|
||||
/* E-nonce */
|
||||
wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
|
||||
wpabuf_put_le16(clear, nonce_len);
|
||||
wpabuf_put_data(clear, auth->e_nonce, nonce_len);
|
||||
|
||||
/* OUI, OUI type, Crypto Suite, DPP frame type */
|
||||
addr[0] = wpabuf_head_u8(msg) + 2;
|
||||
len[0] = 3 + 1 + 1 + 1;
|
||||
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
|
||||
|
||||
/* Attributes before Wrapped Data (none) */
|
||||
addr[1] = wpabuf_put(msg, 0);
|
||||
len[1] = 0;
|
||||
wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
|
||||
|
||||
/* Wrapped Data */
|
||||
wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
|
||||
wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
|
||||
wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
|
||||
|
||||
wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
|
||||
if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
|
||||
wpabuf_head(clear), wpabuf_len(clear),
|
||||
2, addr, len, wrapped) < 0)
|
||||
goto fail;
|
||||
|
||||
wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Result attributes", msg);
|
||||
wpabuf_free(clear);
|
||||
return msg;
|
||||
fail:
|
||||
wpabuf_free(clear);
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void dpp_configurator_free(struct dpp_configurator *conf)
|
||||
{
|
||||
if (!conf)
|
||||
|
|
|
@ -28,6 +28,7 @@ enum dpp_public_action_frame_type {
|
|||
DPP_PA_PKEX_EXCHANGE_RESP = 8,
|
||||
DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9,
|
||||
DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
|
||||
DPP_PA_CONFIGURATION_RESULT = 11,
|
||||
};
|
||||
|
||||
enum dpp_attribute_id {
|
||||
|
@ -69,6 +70,7 @@ enum dpp_status_error {
|
|||
DPP_STATUS_RESPONSE_PENDING = 6,
|
||||
DPP_STATUS_INVALID_CONNECTOR = 7,
|
||||
DPP_STATUS_NO_MATCH = 8,
|
||||
DPP_STATUS_CONFIG_REJECTED = 9,
|
||||
};
|
||||
|
||||
#define DPP_CAPAB_ENROLLEE BIT(0)
|
||||
|
@ -173,6 +175,7 @@ struct dpp_authentication {
|
|||
u8 waiting_pubkey_hash[SHA256_MAC_LEN];
|
||||
int response_pending;
|
||||
enum dpp_status_error auth_resp_status;
|
||||
enum dpp_status_error conf_resp_status;
|
||||
u8 peer_mac_addr[ETH_ALEN];
|
||||
u8 i_nonce[DPP_MAX_NONCE_LEN];
|
||||
u8 r_nonce[DPP_MAX_NONCE_LEN];
|
||||
|
@ -208,6 +211,8 @@ struct dpp_authentication {
|
|||
u8 allowed_roles;
|
||||
int configurator;
|
||||
int remove_on_tx_status;
|
||||
int connect_on_tx_status;
|
||||
int waiting_conf_result;
|
||||
int auth_success;
|
||||
struct wpabuf *conf_req;
|
||||
const struct wpabuf *conf_resp; /* owned by GAS server */
|
||||
|
@ -393,6 +398,11 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
|||
size_t attr_len);
|
||||
int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
||||
const struct wpabuf *resp);
|
||||
enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
|
||||
const u8 *hdr,
|
||||
const u8 *attr_start, size_t attr_len);
|
||||
struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
|
||||
enum dpp_status_error status);
|
||||
struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
|
||||
size_t len);
|
||||
const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len);
|
||||
|
|
|
@ -364,6 +364,18 @@ static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s)
|
|||
}
|
||||
|
||||
|
||||
static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
|
||||
wpa_s->disconnected = 0;
|
||||
wpa_s->reassociate = 1;
|
||||
wpa_s->scan_runs = 0;
|
||||
wpa_s->normal_scans = 0;
|
||||
wpa_supplicant_cancel_sched_scan(wpa_s);
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
|
||||
unsigned int freq, const u8 *dst,
|
||||
const u8 *src, const u8 *bssid,
|
||||
|
@ -387,6 +399,17 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
if (auth->connect_on_tx_status) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Try to connect after completed configuration result");
|
||||
wpas_dpp_try_to_connect(wpa_s);
|
||||
dpp_auth_deinit(wpa_s->dpp_auth);
|
||||
wpa_s->dpp_auth = NULL;
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
if (wpa_s->dpp_auth->remove_on_tx_status) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Terminate authentication exchange due to an earlier error");
|
||||
|
@ -1165,6 +1188,27 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
|
|||
{
|
||||
struct wpa_ssid *ssid;
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
if (auth->akm == DPP_AKM_SAE) {
|
||||
#ifdef CONFIG_SAE
|
||||
struct wpa_driver_capa capa;
|
||||
int res;
|
||||
|
||||
res = wpa_drv_get_capa(wpa_s, &capa);
|
||||
if (res == 0 &&
|
||||
!(capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) &&
|
||||
!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: SAE not supported by the driver");
|
||||
return NULL;
|
||||
}
|
||||
#else /* CONFIG_SAE */
|
||||
wpa_printf(MSG_DEBUG, "DPP: SAE not supported in the build");
|
||||
return NULL;
|
||||
#endif /* CONFIG_SAE */
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
ssid = wpa_config_add_network(wpa_s->conf);
|
||||
if (!ssid)
|
||||
return NULL;
|
||||
|
@ -1236,17 +1280,17 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
static void wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
|
||||
struct dpp_authentication *auth)
|
||||
static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
|
||||
struct dpp_authentication *auth)
|
||||
{
|
||||
struct wpa_ssid *ssid;
|
||||
|
||||
if (wpa_s->conf->dpp_config_processing < 1)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
ssid = wpas_dpp_add_network(wpa_s, auth);
|
||||
if (!ssid)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_NETWORK_ID "%d", ssid->id);
|
||||
if (wpa_s->conf->dpp_config_processing == 2)
|
||||
|
@ -1259,20 +1303,24 @@ static void wpas_dpp_process_config(struct wpa_supplicant *wpa_s,
|
|||
#endif /* CONFIG_NO_CONFIG_WRITE */
|
||||
|
||||
if (wpa_s->conf->dpp_config_processing < 2)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Trying to connect to the new network");
|
||||
wpa_s->disconnected = 0;
|
||||
wpa_s->reassociate = 1;
|
||||
wpa_s->scan_runs = 0;
|
||||
wpa_s->normal_scans = 0;
|
||||
wpa_supplicant_cancel_sched_scan(wpa_s);
|
||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||
#ifdef CONFIG_DPP2
|
||||
if (auth->peer_version >= 2) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Postpone connection attempt to wait for completion of DPP Configuration Result");
|
||||
auth->connect_on_tx_status = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
wpas_dpp_try_to_connect(wpa_s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
|
||||
struct dpp_authentication *auth)
|
||||
static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
|
||||
struct dpp_authentication *auth)
|
||||
{
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
|
||||
if (auth->ssid_len)
|
||||
|
@ -1324,7 +1372,7 @@ static void wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
}
|
||||
|
||||
wpas_dpp_process_config(wpa_s, auth);
|
||||
return wpas_dpp_process_config(wpa_s, auth);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1336,6 +1384,8 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||
struct wpa_supplicant *wpa_s = ctx;
|
||||
const u8 *pos;
|
||||
struct dpp_authentication *auth = wpa_s->dpp_auth;
|
||||
int res;
|
||||
enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
|
||||
|
||||
wpa_s->dpp_gas_dialog_token = -1;
|
||||
|
||||
|
@ -1373,13 +1423,40 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
wpas_dpp_handle_config_obj(wpa_s, auth);
|
||||
dpp_auth_deinit(wpa_s->dpp_auth);
|
||||
wpa_s->dpp_auth = NULL;
|
||||
return;
|
||||
res = wpas_dpp_handle_config_obj(wpa_s, auth);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
|
||||
status = DPP_STATUS_OK;
|
||||
fail:
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
if (status != DPP_STATUS_OK)
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
#ifdef CONFIG_DPP2
|
||||
if (auth->peer_version >= 2 &&
|
||||
auth->conf_resp_status == DPP_STATUS_OK) {
|
||||
struct wpabuf *msg;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
|
||||
msg = dpp_build_conf_result(auth, status);
|
||||
if (!msg)
|
||||
goto fail2;
|
||||
|
||||
wpa_msg(wpa_s, MSG_INFO,
|
||||
DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d",
|
||||
MAC2STR(addr), auth->curr_freq,
|
||||
DPP_PA_CONFIGURATION_RESULT);
|
||||
offchannel_send_action(wpa_s, auth->curr_freq,
|
||||
addr, wpa_s->own_addr, broadcast,
|
||||
wpabuf_head(msg),
|
||||
wpabuf_len(msg),
|
||||
500, wpas_dpp_tx_status, 0);
|
||||
wpabuf_free(msg);
|
||||
|
||||
/* This exchange will be terminated in the TX status handler */
|
||||
return;
|
||||
}
|
||||
fail2:
|
||||
#endif /* CONFIG_DPP2 */
|
||||
dpp_auth_deinit(wpa_s->dpp_auth);
|
||||
wpa_s->dpp_auth = NULL;
|
||||
}
|
||||
|
@ -1562,6 +1639,62 @@ static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP2
|
||||
|
||||
static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
|
||||
void *timeout_ctx)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
struct dpp_authentication *auth = wpa_s->dpp_auth;
|
||||
|
||||
if (!auth || !auth->waiting_conf_result)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Timeout while waiting for Configuration Result");
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
dpp_auth_deinit(auth);
|
||||
wpa_s->dpp_auth = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||
const u8 *hdr, const u8 *buf, size_t len)
|
||||
{
|
||||
struct dpp_authentication *auth = wpa_s->dpp_auth;
|
||||
enum dpp_status_error status;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Configuration Result from " MACSTR,
|
||||
MAC2STR(src));
|
||||
|
||||
if (!auth || !auth->waiting_conf_result) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: No DPP Configuration waiting for result - drop");
|
||||
return;
|
||||
}
|
||||
|
||||
if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
|
||||
MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
|
||||
return;
|
||||
}
|
||||
|
||||
status = dpp_conf_result_rx(auth, hdr, buf, len);
|
||||
|
||||
offchannel_send_action_done(wpa_s);
|
||||
wpas_dpp_listen_stop(wpa_s);
|
||||
if (status == DPP_STATUS_OK)
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_SENT);
|
||||
else
|
||||
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
|
||||
dpp_auth_deinit(auth);
|
||||
wpa_s->dpp_auth = NULL;
|
||||
eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
|
||||
static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
|
||||
const u8 *src,
|
||||
const u8 *buf, size_t len)
|
||||
|
@ -2105,6 +2238,11 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
|
|||
wpas_dpp_rx_pkex_commit_reveal_resp(wpa_s, src, hdr, buf, len,
|
||||
freq);
|
||||
break;
|
||||
#ifdef CONFIG_DPP2
|
||||
case DPP_PA_CONFIGURATION_RESULT:
|
||||
wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
|
||||
break;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Ignored unsupported frame subtype %d", type);
|
||||
|
@ -2174,6 +2312,21 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
|
|||
ok);
|
||||
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
|
||||
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
|
||||
#ifdef CONFIG_DPP2
|
||||
if (ok && auth->peer_version >= 2 &&
|
||||
auth->conf_resp_status == DPP_STATUS_OK) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
|
||||
auth->waiting_conf_result = 1;
|
||||
auth->conf_resp = NULL;
|
||||
wpabuf_free(resp);
|
||||
eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
|
||||
wpa_s, NULL);
|
||||
eloop_register_timeout(2, 0,
|
||||
wpas_dpp_config_result_wait_timeout,
|
||||
wpa_s, NULL);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
offchannel_send_action_done(wpa_s);
|
||||
wpas_dpp_listen_stop(wpa_s);
|
||||
if (ok)
|
||||
|
@ -2286,10 +2439,8 @@ int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
|
|||
curve = get_param(cmd, " curve=");
|
||||
wpas_dpp_set_testing_options(wpa_s, auth);
|
||||
if (wpas_dpp_set_configurator(wpa_s, auth, cmd) == 0 &&
|
||||
dpp_configurator_own_config(auth, curve, 0) == 0) {
|
||||
wpas_dpp_handle_config_obj(wpa_s, auth);
|
||||
ret = 0;
|
||||
}
|
||||
dpp_configurator_own_config(auth, curve, 0) == 0)
|
||||
ret = wpas_dpp_handle_config_obj(wpa_s, auth);
|
||||
|
||||
dpp_auth_deinit(auth);
|
||||
os_free(curve);
|
||||
|
@ -2610,6 +2761,9 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
|||
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
|
||||
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
|
||||
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
|
||||
#ifdef CONFIG_DPP2
|
||||
eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
|
||||
#endif /* CONFIG_DPP2 */
|
||||
offchannel_send_action_done(wpa_s);
|
||||
wpas_dpp_listen_stop(wpa_s);
|
||||
dpp_bootstrap_del(wpa_s, 0);
|
||||
|
|
Loading…
Reference in a new issue