diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 42f992e50..f7d286747 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1300,6 +1300,50 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, } } + +static void +hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct dpp_authentication *auth = hapd->dpp_auth; + struct wpabuf *conf; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from " + MACSTR, MAC2STR(src)); + + if (!auth || !auth->reconfig || !auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - 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; + } + + conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); + if (!conf) + return; + + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); + + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF); + if (hostapd_drv_send_action(hapd, freq, 500, src, + wpabuf_head(conf), wpabuf_len(conf)) < 0) { + wpabuf_free(conf); + dpp_auth_deinit(hapd->dpp_auth); + hapd->dpp_auth = NULL; + return; + } + wpabuf_free(conf); +} + #endif /* CONFIG_DPP2 */ @@ -1770,6 +1814,10 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len, freq); break; + case DPP_PA_RECONFIG_AUTH_RESP: + hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len, + freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, @@ -1799,7 +1847,7 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, struct wpabuf *resp; wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa)); - if (!auth || !auth->auth_success || + if (!auth || (!auth->auth_success && !auth->reconfig_success) || os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { #ifdef CONFIG_DPP2 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data, diff --git a/src/common/dpp.c b/src/common/dpp.c index 37f248468..ff63256a4 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -3462,7 +3462,8 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth, #ifdef CONFIG_TESTING_OPTIONS skip_groups: #endif /* CONFIG_TESTING_OPTIONS */ - if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, + if (!auth->peer_protocol_key || + dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, auth->curve) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); goto fail; diff --git a/src/common/dpp.h b/src/common/dpp.h index a2c0f185c..d24e2f888 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -106,6 +106,12 @@ enum dpp_status_error { DPP_STATUS_CSR_BAD = 13, }; +/* DPP Reconfig Flags object - connectorKey values */ +enum dpp_connector_key { + DPP_CONFIG_REUSEKEY = 0, + DPP_CONFIG_REPLACEKEY = 1, +}; + #define DPP_CAPAB_ENROLLEE BIT(0) #define DPP_CAPAB_CONFIGURATOR BIT(1) #define DPP_CAPAB_ROLE_MASK (BIT(0) | BIT(1)) @@ -282,6 +288,7 @@ struct dpp_authentication { int waiting_conf_result; int waiting_conn_status_result; int auth_success; + bool reconfig_success; struct wpabuf *conf_req; const struct wpabuf *conf_resp; /* owned by GAS server */ struct dpp_configuration *conf_ap; @@ -651,6 +658,9 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, const u8 *csign_key, size_t csign_key_len, unsigned int freq, const u8 *hdr, const u8 *attr_start, size_t attr_len); +struct wpabuf * +dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 048f52752..7495746da 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2344,6 +2344,97 @@ fail: } +int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, + const u8 *r_proto, u16 r_proto_len, + struct json_token *net_access_key) +{ + BN_CTX *bnctx = NULL; + EVP_PKEY *pr = NULL, *peer_key = NULL; + EC_POINT *sum = NULL, *m = NULL; + BIGNUM *mx = NULL; + const EC_KEY *cI, *CR, *PR; + const EC_GROUP *group; + const EC_POINT *CR_point, *PR_point; + const BIGNUM *cI_bn; + u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; + u8 prk[DPP_MAX_HASH_LEN]; + int res = -1; + const struct dpp_curve_params *curve; + + pr = dpp_set_pubkey_point(auth->conf->connector_key, + r_proto, r_proto_len); + if (!pr) { + dpp_auth_fail(auth, "Invalid Responder Protocol Key"); + goto fail; + } + dpp_debug_print_key("Peer (Responder) Protocol Key", pr); + EVP_PKEY_free(auth->peer_protocol_key); + auth->peer_protocol_key = pr; + pr = NULL; + + peer_key = dpp_parse_jwk(net_access_key, &curve); + if (!peer_key) + goto fail; + dpp_debug_print_key("DPP: Received netAccessKey", peer_key); + if (auth->curve != curve) { + wpa_printf(MSG_DEBUG, + "DPP: Mismatching netAccessKey curves (%s != %s)", + auth->curve->name, curve->name); + goto fail; + } + + /* M = cI * { CR + PR } */ + cI = EVP_PKEY_get0_EC_KEY(auth->conf->connector_key); + cI_bn = EC_KEY_get0_private_key(cI); + group = EC_KEY_get0_group(cI); + bnctx = BN_CTX_new(); + sum = EC_POINT_new(group); + m = EC_POINT_new(group); + mx = BN_new(); + CR = EVP_PKEY_get0_EC_KEY(peer_key); + PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); + CR_point = EC_KEY_get0_public_key(CR); + PR_point = EC_KEY_get0_public_key(PR); + if (!bnctx || !sum || !m || !mx || + EC_POINT_add(group, sum, CR_point, PR_point, bnctx) != 1 || + EC_POINT_mul(group, m, NULL, sum, cI_bn, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL, + bnctx) != 1 || + dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); + + /* ke = HKDF(I-nonce, "dpp reconfig key", M.x) */ + + /* HKDF-Extract(I-nonce, M.x) */ + if (dpp_hmac(curve->hash_len, auth->i_nonce, curve->nonce_len, + Mx, curve->prime_len, prk) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); + + /* HKDF-Expand(PRK, "dpp reconfig key", L) */ + if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, + "dpp reconfig key", auth->ke, curve->hash_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: ke = HKDF(I-nonce, \"dpp reconfig key\", M.x)", + auth->ke, curve->hash_len); + + res = 0; +fail: + forced_memzero(prk, sizeof(prk)); + forced_memzero(Mx, sizeof(Mx)); + EVP_PKEY_free(pr); + EVP_PKEY_free(peer_key); + EC_POINT_clear_free(sum); + EC_POINT_clear_free(m); + BN_clear_free(mx); + BN_CTX_free(bnctx); + return res; +} + + static char * dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) { diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index c6e9ae471..158f8cb1d 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -123,6 +123,9 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, const u8 *net_access_key, size_t net_access_key_len, struct json_token *peer_net_access_key); +int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, + const u8 *r_proto, u16 r_proto_len, + struct json_token *net_access_key); char * dpp_sign_connector(struct dpp_configurator *conf, const struct wpabuf *dppcon); int dpp_test_gen_invalid_key(struct wpabuf *msg, diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index ba3d6eace..0db0e08b9 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -461,4 +461,297 @@ fail: goto out; } + +static struct wpabuf * +dpp_build_reconfig_flags(enum dpp_connector_key connector_key) +{ + struct wpabuf *json; + + json = wpabuf_alloc(100); + if (!json) + return NULL; + json_start_object(json, NULL); + json_add_int(json, "connectorKey", connector_key); + json_end_object(json); + wpa_hexdump_ascii(MSG_DEBUG, "DPP: Reconfig-Flags JSON", + wpabuf_head(json), wpabuf_len(json)); + + return json; +} + + +struct wpabuf * +dpp_reconfig_build_conf(struct dpp_authentication *auth) +{ + struct wpabuf *msg = NULL, *clear = NULL, *reconfig_flags; + u8 *attr_start, *attr_end; + size_t clear_len, attr_len, len[2]; + const u8 *addr[2]; + u8 *wrapped; + + reconfig_flags = dpp_build_reconfig_flags(DPP_CONFIG_REPLACEKEY); + if (!reconfig_flags) + goto fail; + + /* Build DPP Reconfig Authentication Confirm frame attributes */ + clear_len = 4 + 1 + 4 + 1 + 2 * (4 + auth->curve->nonce_len) + + 4 + wpabuf_len(reconfig_flags); + clear = wpabuf_alloc(clear_len); + if (!clear) + goto fail; + + /* Transaction ID */ + wpabuf_put_le16(clear, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(clear, 1); + wpabuf_put_u8(clear, auth->transaction_id); + + /* Protocol Version */ + wpabuf_put_le16(clear, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(clear, 1); + wpabuf_put_u8(clear, auth->peer_version); + + /* I-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_I_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->i_nonce, auth->curve->nonce_len); + + /* R-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_R_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->r_nonce, auth->curve->nonce_len); + + /* Reconfig-Flags (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_RECONFIG_FLAGS); + wpabuf_put_le16(clear, wpabuf_len(reconfig_flags)); + wpabuf_put_buf(clear, reconfig_flags); + + attr_len = 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_CONF, attr_len); + if (!msg) + goto fail; + + attr_start = wpabuf_put(msg, 0); + attr_end = wpabuf_put(msg, 0); + + /* 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 */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + 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: Reconfig Authentication Confirm frame attributes", + msg); + +out: + wpabuf_free(reconfig_flags); + wpabuf_free(clear); + return msg; +fail: + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +struct wpabuf * +dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + const u8 *trans_id, *version, *r_connector, *r_proto, *wrapped_data, + *i_nonce, *r_nonce, *conn_status; + u16 trans_id_len, version_len, r_connector_len, r_proto_len, + wrapped_data_len, i_nonce_len, r_nonce_len, conn_status_len; + struct wpabuf *conf = NULL; + char *signed_connector = NULL; + struct dpp_signed_connector_info info; + enum dpp_status_error res; + struct json_token *root = NULL, *token, *conn_status_json = NULL; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + + os_memset(&info, 0, sizeof(info)); + + if (!auth->reconfig || !auth->configurator) + goto fail; + + 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_MSGDUMP, "DPP: Wrapped Data", + wrapped_data, wrapped_data_len); + attr_len = wrapped_data - 4 - attr_start; + + trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID, + &trans_id_len); + if (!trans_id || trans_id_len != 1) { + dpp_auth_fail(auth, "Peer did not include Transaction ID"); + goto fail; + } + if (trans_id[0] != auth->transaction_id) { + dpp_auth_fail(auth, "Transaction ID mismatch"); + goto fail; + } + + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (!version || version_len < 1 || version[0] < 2) { + dpp_auth_fail(auth, + "Missing or invalid Protocol Version attribute"); + goto fail; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + + r_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR, + &r_connector_len); + if (!r_connector) { + dpp_auth_fail(auth, " Missing R-Connector attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: R-Connector", + r_connector, r_connector_len); + + r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, + &r_proto_len); + if (!r_proto) { + dpp_auth_fail(auth, + "Missing required Responder Protocol Key attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", + r_proto, r_proto_len); + + signed_connector = os_malloc(r_connector_len + 1); + if (!signed_connector) + goto fail; + os_memcpy(signed_connector, r_connector, r_connector_len); + signed_connector[r_connector_len] = '\0'; + + res = dpp_process_signed_connector(&info, auth->conf->csign, + signed_connector); + if (res != DPP_STATUS_OK) { + dpp_auth_fail(auth, "Invalid R-Connector"); + goto fail; + } + + root = json_parse((const char *) info.payload, info.payload_len); + if (!root) { + dpp_auth_fail(auth, "Invalid Connector payload"); + goto fail; + } + + /* Do not check netAccessKey expiration for reconfiguration to allow + * expired Connector to be updated. */ + + token = json_get_member(root, "netAccessKey"); + if (!token || token->type != JSON_OBJECT) { + dpp_auth_fail(auth, "No netAccessKey object found"); + goto fail; + } + + if (dpp_reconfig_derive_ke_initiator(auth, r_proto, r_proto_len, + token) < 0) + goto fail; + + 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; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len || + os_memcmp(i_nonce, auth->i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid R-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); + os_memcpy(auth->r_nonce, r_nonce, r_nonce_len); + + conn_status = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_CONN_STATUS, &conn_status_len); + if (!conn_status) { + dpp_auth_fail(auth, "Missing Connection Status attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus", + conn_status, conn_status_len); + + conn_status_json = json_parse((const char *) conn_status, + conn_status_len); + if (!conn_status_json) { + dpp_auth_fail(auth, "Could not parse connStatus"); + goto fail; + } + /* TODO: use connStatus information */ + + conf = dpp_reconfig_build_conf(auth); + if (conf) + auth->reconfig_success = true; + +out: + json_free(root); + json_free(conn_status_json); + bin_clear_free(unwrapped, unwrapped_len); + os_free(info.payload); + os_free(signed_connector); + return conf; +fail: + wpabuf_free(conf); + conf = NULL; + goto out; +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 3f88f372c..8fd6ece79 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1962,6 +1962,51 @@ wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, } } + +static void +wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct dpp_authentication *auth = wpa_s->dpp_auth; + struct wpabuf *conf; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from " + MACSTR, MAC2STR(src)); + + if (!auth || !auth->reconfig || !auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - 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; + } + + conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); + if (!conf) + return; + + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL); + + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF); + if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, + wpabuf_head(conf), wpabuf_len(conf), + 500, wpas_dpp_tx_status, 0) < 0) { + wpabuf_free(conf); + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + return; + } + wpabuf_free(conf); + + wpas_dpp_start_gas_server(wpa_s); +} + #endif /* CONFIG_DPP2 */ @@ -2530,6 +2575,9 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, case DPP_PA_RECONFIG_AUTH_REQ: wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq); break; + case DPP_PA_RECONFIG_AUTH_RESP: + wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, @@ -2560,7 +2608,7 @@ wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query, wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa)); - if (!auth || !auth->auth_success || + if (!auth || (!auth->auth_success && !auth->reconfig_success) || os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return NULL;