[wpa_supplicant] Cumulative patch from commit dd2daf084

Bug: 156933657
Test: Confirm random dialog token usage from logs
Test: Verify Passpoint ANQP functionality and Passpoint association
Test: act.py -c ../WifiDppConfig.json -tc WifiDppTest
Test: Connect to Passpoint, Open, WPA2, WPA3 networks and run traffic
Test: Regression test passed (Bug: 156969218)

dd2daf084 HE: Process HE 6 GHz band capab from associating HE STA
db603634a HE: Add 6 GHz Band Capabilities element in Beacon and response frames
88911a0aa HE: Add HE 6 GHz Band Capabilities into ieee802_11_parse_elems()
b2c0b83c6 HE: Remove VHT Operation Information from HE Operation element
e297a5bfd HE: Define 6 GHz band capability elements
39f29f250 defconfig: Enable TDLS
025ab330b ACS: Channel selection based freqlist
4ae3f3972 Add a helper function for recognizing BIP enum wpa_alg values
d3cab56c0 Rename WPA_ALG_IGTK to use the correct cipher name for BIP
bd1aebbd0 hostapd: Extend RESET_PN for BIGTK
df49c53f4 Fix a typo in a comment
4294d221d D-Bus: Increase introspection buffer size
79488da57 wolfssl: Do not hardcode include directory in wpa_supplicant build
eb595b3e3 wolfssl: Fix crypto_bignum_rand() implementation
6a28c4dbc wolfssl: Fix compiler warnings on size_t printf format use
f2dbaa8ac SAE: Fix a typo in a comment
038899290 wpa_gui: Fix build with Inkscape 1.0
3e1a13010 nl80211: Change AKM suite limit from warning to debug print
5a04a76aa Ignore Management frames while AP interface is not fully enabled
c82535edd Move deauthentication at AP start to be after beacon configuration
094c8a621 Remove unnecessary key clearing at AP start with nl80211
04030e8c0 nl80211: Remove AP mode interface from bridge for STA-mode-scan
7adea21d2 dpp-nfc: Enable hostapd beaconing for listen state
134ad50b0 dpp-nfc: Clean up debug prints when handover select is received
5d49c1bf7 dpp-nfc: Do not indicate a single channel 1 by default
d0e2d8091 dpp-nfc: Make handover request collision detection more robust
8791e7461 dpp-nfc: Write debug info to summary log
1e0bc897a dpp-nfc: Collision detection for handover request
9ad3fe934 dpp-nfc: Start handover server regardless of init-on-touch setting
24efcdf74 dpp-nfc: Own MAC address fetching from hostapd
8f96f2c3b dpp-nfc: Be more graceful when wpa_supplicant is not available
0b04d3c57 dpp-nfc: Allow wpa_supplicant control interface directory to be set
69dfbe6a9 dpp-nfc: Use Configurator/Enrollee parameters with tag reading
f85fb349f dpp-nfc: More robust determination of the script directory
98e4b3840 DPP2: Chirping in hostapd Enrollee
95471fc3e Handle hostapd_for_each_interface() at the process termination
99809c7a4 nl80211: Disable offchannel-ok in AP mode only if beaconing
0f58c88fc DPP2: Fix CONFIG_DPP2=y build with OpenSSL 1.0.2
44f786678 Clean up GET_CAPABILITY handling of 'strict' argument
3790f3a6e Use per-interface type driver key_mgmt capabilities when possible
8d7502809 Allow per interface type AKM capabilities to be fetched
b67bedf2e nl80211: Fetch information on supported AKMs from the driver
6fffb320f nl80211: Remove QCA vendor specific AKM capability handling
db59827a3 DPP2: Extend TCP encapsulation case to support Configurator as Initiator
0086c1452 DPP: Extend NFC bootstrapping script for more control by caller
890ae336c DPP2: Clean up CONFIG_DPP2 use with configurator connectivity IE
670e15337 DPP2: Fix DPP_CHIRP listen parameter value validation
7f20a3ebd DPP2: Reconfiguration support in Controller
6dcb8aaf1 DPP2: Reconfig Announcement relaying from AP to Controller
3b4f7dfaa DPP2: Fix Presence Announcement processing in Controller
5e2d877cc DPP: Mark internal-to-file functions static
3aaf269f6 DPP: Move TCP encapsulation into a separate source code file
21c612017 DPP: Move configurator backup into a separate source code file
fdbbb7406 DPP: Move authentication functionality into a separate source code file
182f6ae90 DPP2: Remove reconfigured network
3e48c5d4b DPP2: Reconfig Authentication Confirm processing
24b01c706 DPP2: Reconfig Authentication Response processing and Confirm generation
65e94351d DPP2: Reconfig Authentication Request processing and Response generation
3774b6bd0 DPP2: Reconfig Authentication Request generation and transmission
66ac616cd DPP2: Process received Reconfig Announcement frame
0c043d9de DPP2: Reconfig Announcement transmission
92492dd3a DPP2: Extend connector matching for reconfiguration
961435097 DPP2: Move connStatus object building into a helper function
94f73f90e DPP: Move signed connector checking into a helper function
94a28a494 DPP: Move parsing of own connector into a helper function
d4ae12355 DPP: Move PKEX functionality into a separate source code file
87b657261 DPP: Move crypto routines into a separate source code file
16626dff9 DPP2: Derive bk ("base key")
76029c6e1 DPP: Use EVP_PKEY_get0_EC_KEY() when a const reference is sufficient
0a488ef35 DPP: Track ending time for remain-on-channel operations
481fdfc46 DPP2: Fix URI version parser
7dd768c3c DPP2: Version information in bootstrapping info URI
cbafc8ef4 Fix truncated control interface command detection
5a0718a19 DPP2: Report MUD URL and bandSupport in control interface events
769139c49 DPP2: Do not include Protocol Version in Auth Req when testing v1
fad64b416 DPP: Move dppCon signing to a set of helper functions
12c8eacf7 DPP: Allow version number to be overridden for testing purposes
c3c38bc8b DPP2: Detect PFS downgrade attack while processing EAPOL-Key msg 3/4
9561925b4 DPP2: Detect PFS downgrade attack while processing EAPOL-Key msg 2/4
68422fedb DPP2: Parse DPP KDE in EAPOL-Key Key Data field
143e3d8bc DPP2: Add DPP KDE into EAPOL-Key msg 2/4 when using DPP AKM
b11a12401 DPP2: Add DPP KDE into EAPOL-Key msg 3/4 when using DPP AKM
85d545699 DPP2: Indicate if PFS was used in control interface STATUS
1f5f00008 DPP2: Try to negotiate PFS only if AP supports version 2 or newer
f6c22dcde Use a local pointer to simply current_ssid accesses in sme_associate()
42acf1292 DPP2: Add Protocol Version attribute to network introduction messages
96b6dd21a Increase wpa_supplicant control interface buffer size
a7d6098fb Add PRINTF_FORMAT for printf wrapper functions

Change-Id: I26a15ac578ce81d1e35f426085661e5c7b43b6ef
diff --git a/src/common/dpp.c b/src/common/dpp.c
index b33ab15..d09f0d1 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -8,47 +8,33 @@
  */
 
 #include "utils/includes.h"
-#include <fcntl.h>
 #include <openssl/opensslv.h>
 #include <openssl/err.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
 
 #include "utils/common.h"
 #include "utils/base64.h"
 #include "utils/json.h"
-#include "utils/ip_addr.h"
-#include "utils/eloop.h"
 #include "common/ieee802_11_common.h"
-#include "common/ieee802_11_defs.h"
 #include "common/wpa_ctrl.h"
 #include "common/gas.h"
 #include "crypto/crypto.h"
 #include "crypto/random.h"
 #include "crypto/aes.h"
 #include "crypto/aes_siv.h"
-#include "crypto/sha384.h"
-#include "crypto/sha512.h"
-#include "tls/asn1.h"
 #include "drivers/driver.h"
 #include "dpp.h"
+#include "dpp_i.h"
 
 
 static const char * dpp_netrole_str(enum dpp_netrole netrole);
 
 #ifdef CONFIG_TESTING_OPTIONS
+#ifdef CONFIG_DPP2
+int dpp_version_override = 2;
+#else
+int dpp_version_override = 1;
+#endif
 enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
-u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
-u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
-u8 dpp_pkex_ephemeral_key_override[600];
-size_t dpp_pkex_ephemeral_key_override_len = 0;
-u8 dpp_protocol_key_override[600];
-size_t dpp_protocol_key_override_len = 0;
-u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
-size_t dpp_nonce_override_len = 0;
-
-static int dpp_test_gen_invalid_key(struct wpabuf *msg,
-				    const struct dpp_curve_params *curve);
 #endif /* CONFIG_TESTING_OPTIONS */
 
 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
@@ -56,24 +42,6 @@
 	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
 /* Compatibility wrappers for older versions. */
 
-static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
-{
-	sig->r = r;
-	sig->s = s;
-	return 1;
-}
-
-
-static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
-			   const BIGNUM **ps)
-{
-	if (pr)
-		*pr = sig->r;
-	if (ps)
-		*ps = sig->s;
-}
-
-
 #ifdef CONFIG_DPP2
 static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
 {
@@ -86,700 +54,7 @@
 #endif
 
 
-struct dpp_connection {
-	struct dl_list list;
-	struct dpp_controller *ctrl;
-	struct dpp_relay_controller *relay;
-	struct dpp_global *global;
-	struct dpp_authentication *auth;
-	int sock;
-	u8 mac_addr[ETH_ALEN];
-	unsigned int freq;
-	u8 msg_len[4];
-	size_t msg_len_octets;
-	struct wpabuf *msg;
-	struct wpabuf *msg_out;
-	size_t msg_out_pos;
-	unsigned int read_eloop:1;
-	unsigned int write_eloop:1;
-	unsigned int on_tcp_tx_complete_gas_done:1;
-	unsigned int on_tcp_tx_complete_remove:1;
-	unsigned int on_tcp_tx_complete_auth_ok:1;
-};
-
-/* Remote Controller */
-struct dpp_relay_controller {
-	struct dl_list list;
-	struct dpp_global *global;
-	u8 pkhash[SHA256_MAC_LEN];
-	struct hostapd_ip_addr ipaddr;
-	void *cb_ctx;
-	void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg,
-		   size_t len);
-	void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token,
-			    int prot, struct wpabuf *buf);
-	struct dl_list conn; /* struct dpp_connection */
-};
-
-/* Local Controller */
-struct dpp_controller {
-	struct dpp_global *global;
-	u8 allowed_roles;
-	int qr_mutual;
-	int sock;
-	struct dl_list conn; /* struct dpp_connection */
-	char *configurator_params;
-};
-
-struct dpp_global {
-	void *msg_ctx;
-	struct dl_list bootstrap; /* struct dpp_bootstrap_info */
-	struct dl_list configurator; /* struct dpp_configurator */
-#ifdef CONFIG_DPP2
-	struct dl_list controllers; /* struct dpp_relay_controller */
-	struct dpp_controller *controller;
-	struct dl_list tcp_init; /* struct dpp_connection */
-	void *cb_ctx;
-	int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
-	void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi);
-#endif /* CONFIG_DPP2 */
-};
-
-static const struct dpp_curve_params dpp_curves[] = {
-	/* The mandatory to support and the default NIST P-256 curve needs to
-	 * be the first entry on this list. */
-	{ "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" },
-	{ "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
-	{ "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
-	{ "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
-	{ "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
-	{ "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
-	{ NULL, 0, 0, 0, 0, NULL, 0, NULL }
-};
-
-
-/* Role-specific elements for PKEX */
-
-/* NIST P-256 */
-static const u8 pkex_init_x_p256[32] = {
-	0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
-	0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
-	0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
-	0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
- };
-static const u8 pkex_init_y_p256[32] = {
-	0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
-	0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
-	0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
-	0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
- };
-static const u8 pkex_resp_x_p256[32] = {
-	0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
-	0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
-	0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
-	0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
-};
-static const u8 pkex_resp_y_p256[32] = {
-	0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19,
-	0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1,
-	0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a,
-	0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67
-};
-
-/* NIST P-384 */
-static const u8 pkex_init_x_p384[48] = {
-	0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
-	0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
-	0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
-	0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
-	0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
-	0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
-};
-static const u8 pkex_init_y_p384[48] = {
-	0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29,
-	0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56,
-	0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7,
-	0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6,
-	0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94,
-	0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18
-};
-static const u8 pkex_resp_x_p384[48] = {
-	0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
-	0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
-	0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
-	0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
-	0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
-	0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
-};
-static const u8 pkex_resp_y_p384[48] = {
-	0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c,
-	0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c,
-	0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3,
-	0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1,
-	0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63,
-	0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06
-};
-
-/* NIST P-521 */
-static const u8 pkex_init_x_p521[66] = {
-	0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
-	0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
-	0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
-	0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
-	0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
-	0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
-	0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
-	0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
-	0x97, 0x76
-};
-static const u8 pkex_init_y_p521[66] = {
-	0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59,
-	0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99,
-	0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b,
-	0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd,
-	0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f,
-	0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf,
-	0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02,
-	0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d,
-	0x03, 0xa8
-};
-static const u8 pkex_resp_x_p521[66] = {
-	0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
-	0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
-	0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
-	0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
-	0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
-	0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
-	0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
-	0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
-	0x84, 0xb4
-};
-static const u8 pkex_resp_y_p521[66] = {
-	0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d,
-	0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20,
-	0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3,
-	0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84,
-	0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9,
-	0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2,
-	0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80,
-	0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53,
-	0xce, 0xe1
-};
-
-/* Brainpool P-256r1 */
-static const u8 pkex_init_x_bp_p256r1[32] = {
-	0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
-	0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
-	0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
-	0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
-};
-static const u8 pkex_init_y_bp_p256r1[32] = {
-	0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd,
-	0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30,
-	0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe,
-	0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b
-};
-static const u8 pkex_resp_x_bp_p256r1[32] = {
-	0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
-	0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
-	0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
-	0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
-};
-static const u8 pkex_resp_y_bp_p256r1[32] = {
-	0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
-	0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
-	0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
-	0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
-};
-
-/* Brainpool P-384r1 */
-static const u8 pkex_init_x_bp_p384r1[48] = {
-	0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
-	0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
-	0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
-	0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
-	0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
-	0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
-};
-static const u8 pkex_init_y_bp_p384r1[48] = {
-	0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
-	0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
-	0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
-	0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
-	0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
-	0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
-};
-static const u8 pkex_resp_x_bp_p384r1[48] = {
-	0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
-	0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
-	0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
-	0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
-	0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
-	0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
-};
-static const u8 pkex_resp_y_bp_p384r1[48] = {
-	0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
-	0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
-	0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
-	0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
-	0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
-	0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
-};
-
-/* Brainpool P-512r1 */
-static const u8 pkex_init_x_bp_p512r1[64] = {
-	0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
-	0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
-	0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
-	0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
-	0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
-	0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
-	0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
-	0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
-};
-static const u8 pkex_init_y_bp_p512r1[64] = {
-	0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94,
-	0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8,
-	0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3,
-	0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45,
-	0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e,
-	0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58,
-	0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71,
-	0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99
-};
-static const u8 pkex_resp_x_bp_p512r1[64] = {
-	0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
-	0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
-	0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
-	0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
-	0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
-	0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
-	0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
-	0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
-};
-static const u8 pkex_resp_y_bp_p512r1[64] = {
-	0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81,
-	0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68,
-	0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa,
-	0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d,
-	0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c,
-	0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09,
-	0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56,
-	0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7
-};
-
-
-static void dpp_debug_print_point(const char *title, const EC_GROUP *group,
-				  const EC_POINT *point)
-{
-	BIGNUM *x, *y;
-	BN_CTX *ctx;
-	char *x_str = NULL, *y_str = NULL;
-
-	if (!wpa_debug_show_keys)
-		return;
-
-	ctx = BN_CTX_new();
-	x = BN_new();
-	y = BN_new();
-	if (!ctx || !x || !y ||
-	    EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1)
-		goto fail;
-
-	x_str = BN_bn2hex(x);
-	y_str = BN_bn2hex(y);
-	if (!x_str || !y_str)
-		goto fail;
-
-	wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str);
-
-fail:
-	OPENSSL_free(x_str);
-	OPENSSL_free(y_str);
-	BN_free(x);
-	BN_free(y);
-	BN_CTX_free(ctx);
-}
-
-
-static int dpp_hash_vector(const struct dpp_curve_params *curve,
-			   size_t num_elem, const u8 *addr[], const size_t *len,
-			   u8 *mac)
-{
-	if (curve->hash_len == 32)
-		return sha256_vector(num_elem, addr, len, mac);
-	if (curve->hash_len == 48)
-		return sha384_vector(num_elem, addr, len, mac);
-	if (curve->hash_len == 64)
-		return sha512_vector(num_elem, addr, len, mac);
-	return -1;
-}
-
-
-static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
-			   const char *label, u8 *out, size_t outlen)
-{
-	if (hash_len == 32)
-		return hmac_sha256_kdf(secret, secret_len, NULL,
-				       (const u8 *) label, os_strlen(label),
-				       out, outlen);
-	if (hash_len == 48)
-		return hmac_sha384_kdf(secret, secret_len, NULL,
-				       (const u8 *) label, os_strlen(label),
-				       out, outlen);
-	if (hash_len == 64)
-		return hmac_sha512_kdf(secret, secret_len, NULL,
-				       (const u8 *) label, os_strlen(label),
-				       out, outlen);
-	return -1;
-}
-
-
-static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
-			   size_t num_elem, const u8 *addr[],
-			   const size_t *len, u8 *mac)
-{
-	if (hash_len == 32)
-		return hmac_sha256_vector(key, key_len, num_elem, addr, len,
-					  mac);
-	if (hash_len == 48)
-		return hmac_sha384_vector(key, key_len, num_elem, addr, len,
-					  mac);
-	if (hash_len == 64)
-		return hmac_sha512_vector(key, key_len, num_elem, addr, len,
-					  mac);
-	return -1;
-}
-
-
-static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
-		    const u8 *data, size_t data_len, u8 *mac)
-{
-	if (hash_len == 32)
-		return hmac_sha256(key, key_len, data, data_len, mac);
-	if (hash_len == 48)
-		return hmac_sha384(key, key_len, data, data_len, mac);
-	if (hash_len == 64)
-		return hmac_sha512(key, key_len, data, data_len, mac);
-	return -1;
-}
-
-
-#ifdef CONFIG_DPP2
-
-static int dpp_pbkdf2_f(size_t hash_len,
-			const u8 *password, size_t password_len,
-			const u8 *salt, size_t salt_len,
-			unsigned int iterations, unsigned int count, u8 *digest)
-{
-	unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN];
-	unsigned int i;
-	size_t j;
-	u8 count_buf[4];
-	const u8 *addr[2];
-	size_t len[2];
-
-	addr[0] = salt;
-	len[0] = salt_len;
-	addr[1] = count_buf;
-	len[1] = 4;
-
-	/* F(P, S, c, i) = U1 xor U2 xor ... Uc
-	 * U1 = PRF(P, S || i)
-	 * U2 = PRF(P, U1)
-	 * Uc = PRF(P, Uc-1)
-	 */
-
-	WPA_PUT_BE32(count_buf, count);
-	if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len,
-			    tmp))
-		return -1;
-	os_memcpy(digest, tmp, hash_len);
-
-	for (i = 1; i < iterations; i++) {
-		if (dpp_hmac(hash_len, password, password_len, tmp, hash_len,
-			     tmp2))
-			return -1;
-		os_memcpy(tmp, tmp2, hash_len);
-		for (j = 0; j < hash_len; j++)
-			digest[j] ^= tmp2[j];
-	}
-
-	return 0;
-}
-
-
-static int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len,
-		      const u8 *salt, size_t salt_len, unsigned int iterations,
-		      u8 *buf, size_t buflen)
-{
-	unsigned int count = 0;
-	unsigned char *pos = buf;
-	size_t left = buflen, plen;
-	unsigned char digest[DPP_MAX_HASH_LEN];
-
-	while (left > 0) {
-		count++;
-		if (dpp_pbkdf2_f(hash_len, password, password_len,
-				 salt, salt_len, iterations, count, digest))
-			return -1;
-		plen = left > hash_len ? hash_len : left;
-		os_memcpy(pos, digest, plen);
-		pos += plen;
-		left -= plen;
-	}
-
-	return 0;
-}
-
-#endif /* CONFIG_DPP2 */
-
-
-static int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len)
-{
-	int num_bytes, offset;
-
-	num_bytes = BN_num_bytes(bn);
-	if ((size_t) num_bytes > len)
-		return -1;
-	offset = len - num_bytes;
-	os_memset(pos, 0, offset);
-	BN_bn2bin(bn, pos + offset);
-	return 0;
-}
-
-
-static struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix)
-{
-	int len, res;
-	EC_KEY *eckey;
-	struct wpabuf *buf;
-	unsigned char *pos;
-
-	eckey = EVP_PKEY_get1_EC_KEY(pkey);
-	if (!eckey)
-		return NULL;
-	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
-	len = i2o_ECPublicKey(eckey, NULL);
-	if (len <= 0) {
-		wpa_printf(MSG_ERROR,
-			   "DDP: Failed to determine public key encoding length");
-		EC_KEY_free(eckey);
-		return NULL;
-	}
-
-	buf = wpabuf_alloc(len);
-	if (!buf) {
-		EC_KEY_free(eckey);
-		return NULL;
-	}
-
-	pos = wpabuf_put(buf, len);
-	res = i2o_ECPublicKey(eckey, &pos);
-	EC_KEY_free(eckey);
-	if (res != len) {
-		wpa_printf(MSG_ERROR,
-			   "DDP: Failed to encode public key (res=%d/%d)",
-			   res, len);
-		wpabuf_free(buf);
-		return NULL;
-	}
-
-	if (!prefix) {
-		/* Remove 0x04 prefix to match DPP definition */
-		pos = wpabuf_mhead(buf);
-		os_memmove(pos, pos + 1, len - 1);
-		buf->used--;
-	}
-
-	return buf;
-}
-
-
-static EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
-					     const u8 *buf_x, const u8 *buf_y,
-					     size_t len)
-{
-	EC_KEY *eckey = NULL;
-	BN_CTX *ctx;
-	EC_POINT *point = NULL;
-	BIGNUM *x = NULL, *y = NULL;
-	EVP_PKEY *pkey = NULL;
-
-	ctx = BN_CTX_new();
-	if (!ctx) {
-		wpa_printf(MSG_ERROR, "DPP: Out of memory");
-		return NULL;
-	}
-
-	point = EC_POINT_new(group);
-	x = BN_bin2bn(buf_x, len, NULL);
-	y = BN_bin2bn(buf_y, len, NULL);
-	if (!point || !x || !y) {
-		wpa_printf(MSG_ERROR, "DPP: Out of memory");
-		goto fail;
-	}
-
-	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	if (!EC_POINT_is_on_curve(group, point, ctx) ||
-	    EC_POINT_is_at_infinity(group, point)) {
-		wpa_printf(MSG_ERROR, "DPP: Invalid point");
-		goto fail;
-	}
-	dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point);
-
-	eckey = EC_KEY_new();
-	if (!eckey ||
-	    EC_KEY_set_group(eckey, group) != 1 ||
-	    EC_KEY_set_public_key(eckey, point) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to set EC_KEY: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
-
-	pkey = EVP_PKEY_new();
-	if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
-		goto fail;
-	}
-
-out:
-	BN_free(x);
-	BN_free(y);
-	EC_KEY_free(eckey);
-	EC_POINT_free(point);
-	BN_CTX_free(ctx);
-	return pkey;
-fail:
-	EVP_PKEY_free(pkey);
-	pkey = NULL;
-	goto out;
-}
-
-
-static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key,
-				       const u8 *buf, size_t len)
-{
-	EC_KEY *eckey;
-	const EC_GROUP *group;
-	EVP_PKEY *pkey = NULL;
-
-	if (len & 1)
-		return NULL;
-
-	eckey = EVP_PKEY_get1_EC_KEY(group_key);
-	if (!eckey) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Could not get EC_KEY from group_key");
-		return NULL;
-	}
-
-	group = EC_KEY_get0_group(eckey);
-	if (group)
-		pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2,
-						  len / 2);
-	else
-		wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
-
-	EC_KEY_free(eckey);
-	return pkey;
-}
-
-
-static int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer,
-		    u8 *secret, size_t *secret_len)
-{
-	EVP_PKEY_CTX *ctx;
-	int ret = -1;
-
-	ERR_clear_error();
-	*secret_len = 0;
-
-	ctx = EVP_PKEY_CTX_new(own, NULL);
-	if (!ctx) {
-		wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		return -1;
-	}
-
-	if (EVP_PKEY_derive_init(ctx) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: EVP_PKEY_derive_set_peet failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
-		u8 buf[200];
-		int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG;
-
-		/* It looks like OpenSSL can return unexpectedly large buffer
-		 * need for shared secret from EVP_PKEY_derive(NULL) in some
-		 * cases. For example, group 19 has shown cases where secret_len
-		 * is set to 72 even though the actual length ends up being
-		 * updated to 32 when EVP_PKEY_derive() is called with a buffer
-		 * for the value. Work around this by trying to fetch the value
-		 * and continue if it is within supported range even when the
-		 * initial buffer need is claimed to be larger. */
-		wpa_printf(level,
-			   "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
-			   (int) *secret_len);
-		if (*secret_len > 200)
-			goto fail;
-		if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) {
-			wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
-				   ERR_error_string(ERR_get_error(), NULL));
-			goto fail;
-		}
-		if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
-			wpa_printf(MSG_ERROR,
-				   "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
-				   (int) *secret_len);
-			goto fail;
-		}
-		wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change",
-				buf, *secret_len);
-		os_memcpy(secret, buf, *secret_len);
-		forced_memzero(buf, sizeof(buf));
-		goto done;
-	}
-
-	if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-done:
-	ret = 0;
-
-fail:
-	EVP_PKEY_CTX_free(ctx);
-	return ret;
-}
-
-
-static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
+void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
 {
 	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
 }
@@ -1037,57 +312,21 @@
 }
 
 
-static const struct dpp_curve_params *
-dpp_get_curve_oid(const ASN1_OBJECT *poid)
+int dpp_parse_uri_version(struct dpp_bootstrap_info *bi, const char *version)
 {
-	ASN1_OBJECT *oid;
-	int i;
+#ifdef CONFIG_DPP2
+	if (!version || DPP_VERSION < 2)
+		return 0;
 
-	for (i = 0; dpp_curves[i].name; i++) {
-		oid = OBJ_txt2obj(dpp_curves[i].name, 0);
-		if (oid && OBJ_cmp(poid, oid) == 0)
-			return &dpp_curves[i];
-	}
-	return NULL;
-}
+	if (*version == '1')
+		bi->version = 1;
+	else if (*version == '2')
+		bi->version = 2;
+	else
+		wpa_printf(MSG_DEBUG, "DPP: Unknown URI version");
 
-
-static const struct dpp_curve_params * dpp_get_curve_nid(int nid)
-{
-	int i, tmp;
-
-	if (!nid)
-		return NULL;
-	for (i = 0; dpp_curves[i].name; i++) {
-		tmp = OBJ_txt2nid(dpp_curves[i].name);
-		if (tmp == nid)
-			return &dpp_curves[i];
-	}
-	return NULL;
-}
-
-
-static int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
-			      const u8 *data, size_t data_len)
-{
-	const u8 *addr[2];
-	size_t len[2];
-
-	addr[0] = data;
-	len[0] = data_len;
-	if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0)
-		return -1;
-	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
-		    bi->pubkey_hash, SHA256_MAC_LEN);
-
-	addr[0] = (const u8 *) "chirp";
-	len[0] = 5;
-	addr[1] = data;
-	len[1] = data_len;
-	if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0)
-		return -1;
-	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)",
-		    bi->pubkey_hash_chirp, SHA256_MAC_LEN);
+	wpa_printf(MSG_DEBUG, "DPP: URI version: %d", bi->version);
+#endif /* CONFIG_DPP2 */
 
 	return 0;
 }
@@ -1095,28 +334,10 @@
 
 static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
 {
-	const char *end;
 	u8 *data;
 	size_t data_len;
-	EVP_PKEY *pkey;
-	const unsigned char *p;
 	int res;
-	X509_PUBKEY *pub = NULL;
-	ASN1_OBJECT *ppkalg;
-	const unsigned char *pk;
-	int ppklen;
-	X509_ALGOR *pa;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-	(defined(LIBRESSL_VERSION_NUMBER) && \
-	 LIBRESSL_VERSION_NUMBER < 0x20800000L)
-	ASN1_OBJECT *pa_oid;
-#else
-	const ASN1_OBJECT *pa_oid;
-#endif
-	const void *pval;
-	int ptype;
-	const ASN1_OBJECT *poid;
-	char buf[100];
+	const char *end;
 
 	end = os_strchr(info, ';');
 	if (!end)
@@ -1131,101 +352,9 @@
 	wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
 		    data, data_len);
 
-	if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
-		os_free(data);
-		return -1;
-	}
-
-	/* DER encoded ASN.1 SubjectPublicKeyInfo
-	 *
-	 * SubjectPublicKeyInfo  ::=  SEQUENCE  {
-	 *      algorithm            AlgorithmIdentifier,
-	 *      subjectPublicKey     BIT STRING  }
-	 *
-	 * AlgorithmIdentifier  ::=  SEQUENCE  {
-	 *      algorithm               OBJECT IDENTIFIER,
-	 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
-	 *
-	 * subjectPublicKey = compressed format public key per ANSI X9.63
-	 * algorithm = ecPublicKey (1.2.840.10045.2.1)
-	 * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
-	 *       prime256v1 (1.2.840.10045.3.1.7)
-	 */
-
-	p = data;
-	pkey = d2i_PUBKEY(NULL, &p, data_len);
+	res = dpp_get_subject_public_key(bi, data, data_len);
 	os_free(data);
-
-	if (!pkey) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
-		return -1;
-	}
-
-	if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: SubjectPublicKeyInfo does not describe an EC key");
-		EVP_PKEY_free(pkey);
-		return -1;
-	}
-
-	res = X509_PUBKEY_set(&pub, pkey);
-	if (res != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey");
-		goto fail;
-	}
-
-	res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub);
-	if (res != 1) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not extract SubjectPublicKeyInfo parameters");
-		goto fail;
-	}
-	res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0);
-	if (res < 0 || (size_t) res >= sizeof(buf)) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not extract SubjectPublicKeyInfo algorithm");
-		goto fail;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf);
-	if (os_strcmp(buf, "id-ecPublicKey") != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported SubjectPublicKeyInfo algorithm");
-		goto fail;
-	}
-
-	X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa);
-	if (ptype != V_ASN1_OBJECT) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: SubjectPublicKeyInfo parameters did not contain an OID");
-		goto fail;
-	}
-	poid = pval;
-	res = OBJ_obj2txt(buf, sizeof(buf), poid, 0);
-	if (res < 0 || (size_t) res >= sizeof(buf)) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not extract SubjectPublicKeyInfo parameters OID");
-		goto fail;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf);
-	bi->curve = dpp_get_curve_oid(poid);
-	if (!bi->curve) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported SubjectPublicKeyInfo curve: %s",
-			   buf);
-		goto fail;
-	}
-
-	wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen);
-
-	X509_PUBKEY_free(pub);
-	bi->pubkey = pkey;
-	return 0;
-fail:
-	X509_PUBKEY_free(pub);
-	EVP_PKEY_free(pkey);
-	return -1;
+	return res;
 }
 
 
@@ -1234,6 +363,7 @@
 	const char *pos = uri;
 	const char *end;
 	const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
+	const char *version = NULL;
 	struct dpp_bootstrap_info *bi;
 
 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri));
@@ -1264,6 +394,8 @@
 			info = pos + 2;
 		else if (pos[0] == 'K' && pos[1] == ':' && !pk)
 			pk = pos + 2;
+		else if (pos[0] == 'V' && pos[1] == ':' && !version)
+			version = pos + 2;
 		else
 			wpa_hexdump_ascii(MSG_DEBUG,
 					  "DPP: Ignore unrecognized URI parameter",
@@ -1284,6 +416,7 @@
 	    dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
 	    dpp_parse_uri_mac(bi, mac) < 0 ||
 	    dpp_parse_uri_info(bi, info) < 0 ||
+	    dpp_parse_uri_version(bi, version) < 0 ||
 	    dpp_parse_uri_pk(bi, pk) < 0) {
 		dpp_bootstrap_info_free(bi);
 		bi = NULL;
@@ -1293,462 +426,7 @@
 }
 
 
-static void dpp_debug_print_key(const char *title, EVP_PKEY *key)
-{
-	EC_KEY *eckey;
-	BIO *out;
-	size_t rlen;
-	char *txt;
-	int res;
-	unsigned char *der = NULL;
-	int der_len;
-	const EC_GROUP *group;
-	const EC_POINT *point;
-
-	out = BIO_new(BIO_s_mem());
-	if (!out)
-		return;
-
-	EVP_PKEY_print_private(out, key, 0, NULL);
-	rlen = BIO_ctrl_pending(out);
-	txt = os_malloc(rlen + 1);
-	if (txt) {
-		res = BIO_read(out, txt, rlen);
-		if (res > 0) {
-			txt[res] = '\0';
-			wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
-		}
-		os_free(txt);
-	}
-	BIO_free(out);
-
-	eckey = EVP_PKEY_get1_EC_KEY(key);
-	if (!eckey)
-		return;
-
-	group = EC_KEY_get0_group(eckey);
-	point = EC_KEY_get0_public_key(eckey);
-	if (group && point)
-		dpp_debug_print_point(title, group, point);
-
-	der_len = i2d_ECPrivateKey(eckey, &der);
-	if (der_len > 0)
-		wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len);
-	OPENSSL_free(der);
-	if (der_len <= 0) {
-		der = NULL;
-		der_len = i2d_EC_PUBKEY(eckey, &der);
-		if (der_len > 0)
-			wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
-		OPENSSL_free(der);
-	}
-
-	EC_KEY_free(eckey);
-}
-
-
-static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
-{
-	EVP_PKEY_CTX *kctx = NULL;
-	EC_KEY *ec_params = NULL;
-	EVP_PKEY *params = NULL, *key = NULL;
-	int nid;
-
-	wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
-
-	nid = OBJ_txt2nid(curve->name);
-	if (nid == NID_undef) {
-		wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name);
-		return NULL;
-	}
-
-	ec_params = EC_KEY_new_by_curve_name(nid);
-	if (!ec_params) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to generate EC_KEY parameters");
-		goto fail;
-	}
-	EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
-	params = EVP_PKEY_new();
-	if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to generate EVP_PKEY parameters");
-		goto fail;
-	}
-
-	kctx = EVP_PKEY_CTX_new(params, NULL);
-	if (!kctx ||
-	    EVP_PKEY_keygen_init(kctx) != 1 ||
-	    EVP_PKEY_keygen(kctx, &key) != 1) {
-		wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key");
-		key = NULL;
-		goto fail;
-	}
-
-	if (wpa_debug_show_keys)
-		dpp_debug_print_key("Own generated key", key);
-
-fail:
-	EC_KEY_free(ec_params);
-	EVP_PKEY_free(params);
-	EVP_PKEY_CTX_free(kctx);
-	return key;
-}
-
-
-static const struct dpp_curve_params *
-dpp_get_curve_name(const char *name)
-{
-	int i;
-
-	for (i = 0; dpp_curves[i].name; i++) {
-		if (os_strcmp(name, dpp_curves[i].name) == 0 ||
-		    (dpp_curves[i].jwk_crv &&
-		     os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
-			return &dpp_curves[i];
-	}
-	return NULL;
-}
-
-
-static const struct dpp_curve_params *
-dpp_get_curve_jwk_crv(const char *name)
-{
-	int i;
-
-	for (i = 0; dpp_curves[i].name; i++) {
-		if (dpp_curves[i].jwk_crv &&
-		    os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
-			return &dpp_curves[i];
-	}
-	return NULL;
-}
-
-
-static EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
-				  const u8 *privkey, size_t privkey_len)
-{
-	EVP_PKEY *pkey;
-	EC_KEY *eckey;
-	const EC_GROUP *group;
-	int nid;
-
-	pkey = EVP_PKEY_new();
-	if (!pkey)
-		return NULL;
-	eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len);
-	if (!eckey) {
-		wpa_printf(MSG_INFO,
-			   "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		EVP_PKEY_free(pkey);
-		return NULL;
-	}
-	group = EC_KEY_get0_group(eckey);
-	if (!group) {
-		EC_KEY_free(eckey);
-		EVP_PKEY_free(pkey);
-		return NULL;
-	}
-	nid = EC_GROUP_get_curve_name(group);
-	*curve = dpp_get_curve_nid(nid);
-	if (!*curve) {
-		wpa_printf(MSG_INFO,
-			   "DPP: Unsupported curve (nid=%d) in pre-assigned key",
-			   nid);
-		EC_KEY_free(eckey);
-		EVP_PKEY_free(pkey);
-		return NULL;
-	}
-
-	if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
-		EC_KEY_free(eckey);
-		EVP_PKEY_free(pkey);
-		return NULL;
-	}
-	return pkey;
-}
-
-
-typedef struct {
-	/* AlgorithmIdentifier ecPublicKey with optional parameters present
-	 * as an OID identifying the curve */
-	X509_ALGOR *alg;
-	/* Compressed format public key per ANSI X9.63 */
-	ASN1_BIT_STRING *pub_key;
-} DPP_BOOTSTRAPPING_KEY;
-
-ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = {
-	ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR),
-	ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING)
-} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY);
-
-IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY);
-
-
-static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key)
-{
-	unsigned char *der = NULL;
-	int der_len;
-	EC_KEY *eckey;
-	struct wpabuf *ret = NULL;
-	size_t len;
-	const EC_GROUP *group;
-	const EC_POINT *point;
-	BN_CTX *ctx;
-	DPP_BOOTSTRAPPING_KEY *bootstrap = NULL;
-	int nid;
-
-	ctx = BN_CTX_new();
-	eckey = EVP_PKEY_get1_EC_KEY(key);
-	if (!ctx || !eckey)
-		goto fail;
-
-	group = EC_KEY_get0_group(eckey);
-	point = EC_KEY_get0_public_key(eckey);
-	if (!group || !point)
-		goto fail;
-	dpp_debug_print_point("DPP: bootstrap public key", group, point);
-	nid = EC_GROUP_get_curve_name(group);
-
-	bootstrap = DPP_BOOTSTRAPPING_KEY_new();
-	if (!bootstrap ||
-	    X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC),
-			    V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1)
-		goto fail;
-
-	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
-				 NULL, 0, ctx);
-	if (len == 0)
-		goto fail;
-
-	der = OPENSSL_malloc(len);
-	if (!der)
-		goto fail;
-	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
-				 der, len, ctx);
-
-	OPENSSL_free(bootstrap->pub_key->data);
-	bootstrap->pub_key->data = der;
-	der = NULL;
-	bootstrap->pub_key->length = len;
-	/* No unused bits */
-	bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
-	bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
-	der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der);
-	if (der_len <= 0) {
-		wpa_printf(MSG_ERROR,
-			   "DDP: Failed to build DER encoded public key");
-		goto fail;
-	}
-
-	ret = wpabuf_alloc_copy(der, der_len);
-fail:
-	DPP_BOOTSTRAPPING_KEY_free(bootstrap);
-	OPENSSL_free(der);
-	EC_KEY_free(eckey);
-	BN_CTX_free(ctx);
-	return ret;
-}
-
-
-static int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
-{
-	struct wpabuf *der;
-	int res;
-
-	der = dpp_bootstrap_key_der(bi->pubkey);
-	if (!der)
-		return -1;
-	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
-			der);
-	res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der));
-	if (res < 0)
-		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
-	wpabuf_free(der);
-	return res;
-}
-
-
-static int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
-		      const u8 *privkey, size_t privkey_len)
-{
-	char *base64 = NULL;
-	char *pos, *end;
-	size_t len;
-	struct wpabuf *der = NULL;
-
-	if (!curve) {
-		bi->curve = &dpp_curves[0];
-	} else {
-		bi->curve = dpp_get_curve_name(curve);
-		if (!bi->curve) {
-			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
-				   curve);
-			return -1;
-		}
-	}
-	if (privkey)
-		bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
-	else
-		bi->pubkey = dpp_gen_keypair(bi->curve);
-	if (!bi->pubkey)
-		goto fail;
-	bi->own = 1;
-
-	der = dpp_bootstrap_key_der(bi->pubkey);
-	if (!der)
-		goto fail;
-	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
-			der);
-
-	if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
-		goto fail;
-	}
-
-	base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
-	wpabuf_free(der);
-	der = NULL;
-	if (!base64)
-		goto fail;
-	pos = base64;
-	end = pos + len;
-	for (;;) {
-		pos = os_strchr(pos, '\n');
-		if (!pos)
-			break;
-		os_memmove(pos, pos + 1, end - pos);
-	}
-	os_free(bi->pk);
-	bi->pk = base64;
-	return 0;
-fail:
-	os_free(base64);
-	wpabuf_free(der);
-	return -1;
-}
-
-
-static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1,
-			 unsigned int hash_len)
-{
-	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
-	const char *info = "first intermediate key";
-	int res;
-
-	/* k1 = HKDF(<>, "first intermediate key", M.x) */
-
-	/* HKDF-Extract(<>, M.x) */
-	os_memset(salt, 0, hash_len);
-	if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
-		return -1;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
-			prk, hash_len);
-
-	/* HKDF-Expand(PRK, info, L) */
-	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
-	os_memset(prk, 0, hash_len);
-	if (res < 0)
-		return -1;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
-			k1, hash_len);
-	return 0;
-}
-
-
-static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2,
-			 unsigned int hash_len)
-{
-	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
-	const char *info = "second intermediate key";
-	int res;
-
-	/* k2 = HKDF(<>, "second intermediate key", N.x) */
-
-	/* HKDF-Extract(<>, N.x) */
-	os_memset(salt, 0, hash_len);
-	res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
-	if (res < 0)
-		return -1;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
-			prk, hash_len);
-
-	/* HKDF-Expand(PRK, info, L) */
-	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
-	os_memset(prk, 0, hash_len);
-	if (res < 0)
-		return -1;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
-			k2, hash_len);
-	return 0;
-}
-
-
-static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke,
-			 unsigned int hash_len)
-{
-	size_t nonce_len;
-	u8 nonces[2 * DPP_MAX_NONCE_LEN];
-	const char *info_ke = "DPP Key";
-	u8 prk[DPP_MAX_HASH_LEN];
-	int res;
-	const u8 *addr[3];
-	size_t len[3];
-	size_t num_elem = 0;
-
-	if (!auth->Mx_len || !auth->Nx_len) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Mx/Nx not available - cannot derive ke");
-		return -1;
-	}
-
-	/* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */
-
-	/* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
-	nonce_len = auth->curve->nonce_len;
-	os_memcpy(nonces, auth->i_nonce, nonce_len);
-	os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
-	addr[num_elem] = auth->Mx;
-	len[num_elem] = auth->Mx_len;
-	num_elem++;
-	addr[num_elem] = auth->Nx;
-	len[num_elem] = auth->Nx_len;
-	num_elem++;
-	if (auth->peer_bi && auth->own_bi) {
-		if (!auth->Lx_len) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Lx not available - cannot derive ke");
-			return -1;
-		}
-		addr[num_elem] = auth->Lx;
-		len[num_elem] = auth->secret_len;
-		num_elem++;
-	}
-	res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
-			      num_elem, addr, len, prk);
-	if (res < 0)
-		return -1;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
-			prk, hash_len);
-
-	/* HKDF-Expand(PRK, info, L) */
-	res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len);
-	os_memset(prk, 0, hash_len);
-	if (res < 0)
-		return -1;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)",
-			ke, hash_len);
-	return 0;
-}
-
-
-static void dpp_build_attr_status(struct wpabuf *msg,
-				  enum dpp_status_error status)
+void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status)
 {
 	wpa_printf(MSG_DEBUG, "DPP: Status %d", status);
 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
@@ -1757,8 +435,7 @@
 }
 
 
-static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg,
-						const u8 *hash)
+void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash)
 {
 	if (hash) {
 		wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash");
@@ -1769,374 +446,6 @@
 }
 
 
-static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg,
-						const u8 *hash)
-{
-	if (hash) {
-		wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash");
-		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
-		wpabuf_put_le16(msg, SHA256_MAC_LEN);
-		wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
-	}
-}
-
-
-static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth,
-					  const struct wpabuf *pi,
-					  size_t nonce_len,
-					  const u8 *r_pubkey_hash,
-					  const u8 *i_pubkey_hash,
-					  unsigned int neg_freq)
-{
-	struct wpabuf *msg;
-	u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1];
-	u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE];
-	u8 *pos;
-	const u8 *addr[2];
-	size_t len[2], siv_len, attr_len;
-	u8 *attr_start, *attr_end;
-
-	/* Build DPP Authentication Request frame attributes */
-	attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) +
-		4 + sizeof(wrapped_data);
-	if (neg_freq > 0)
-		attr_len += 4 + 2;
-#ifdef CONFIG_DPP2
-	attr_len += 5;
-#endif /* CONFIG_DPP2 */
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ)
-		attr_len += 5;
-#endif /* CONFIG_TESTING_OPTIONS */
-	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len);
-	if (!msg)
-		return NULL;
-
-	attr_start = wpabuf_put(msg, 0);
-
-	/* Responder Bootstrapping Key Hash */
-	dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
-
-	/* Initiator Bootstrapping Key Hash */
-	dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
-
-	/* Initiator Protocol Key */
-	if (pi) {
-		wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY);
-		wpabuf_put_le16(msg, wpabuf_len(pi));
-		wpabuf_put_buf(msg, pi);
-	}
-
-	/* Channel */
-	if (neg_freq > 0) {
-		u8 op_class, channel;
-
-		if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class,
-						  &channel) ==
-		    NUM_HOSTAPD_MODES) {
-			wpa_printf(MSG_INFO,
-				   "DPP: Unsupported negotiation frequency request: %d",
-				   neg_freq);
-			wpabuf_free(msg);
-			return NULL;
-		}
-		wpabuf_put_le16(msg, DPP_ATTR_CHANNEL);
-		wpabuf_put_le16(msg, 2);
-		wpabuf_put_u8(msg, op_class);
-		wpabuf_put_u8(msg, channel);
-	}
-
-#ifdef CONFIG_DPP2
-	/* Protocol Version */
-	wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
-	wpabuf_put_le16(msg, 1);
-	wpabuf_put_u8(msg, 2);
-#endif /* CONFIG_DPP2 */
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
-		goto skip_wrapped_data;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* Wrapped data ({I-nonce, I-capabilities}k1) */
-	pos = clear;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
-		goto skip_i_nonce;
-	}
-	if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce");
-		WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
-		pos += 2;
-		WPA_PUT_LE16(pos, nonce_len - 1);
-		pos += 2;
-		os_memcpy(pos, auth->i_nonce, nonce_len - 1);
-		pos += nonce_len - 1;
-		goto skip_i_nonce;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* I-nonce */
-	WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
-	pos += 2;
-	WPA_PUT_LE16(pos, nonce_len);
-	pos += 2;
-	os_memcpy(pos, auth->i_nonce, nonce_len);
-	pos += nonce_len;
-
-#ifdef CONFIG_TESTING_OPTIONS
-skip_i_nonce:
-	if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab");
-		goto skip_i_capab;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* I-capabilities */
-	WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES);
-	pos += 2;
-	WPA_PUT_LE16(pos, 1);
-	pos += 2;
-	auth->i_capab = auth->allowed_roles;
-	*pos++ = auth->i_capab;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_ZERO_I_CAPAB) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities");
-		pos[-1] = 0;
-	}
-skip_i_capab:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	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]);
-
-	siv_len = pos - clear;
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
-	if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
-			    2, addr, len, wrapped_data) < 0) {
-		wpabuf_free(msg);
-		return NULL;
-	}
-	siv_len += AES_BLOCK_SIZE;
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
-		    wrapped_data, siv_len);
-
-	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
-	wpabuf_put_le16(msg, siv_len);
-	wpabuf_put_data(msg, wrapped_data, siv_len);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
-		dpp_build_attr_status(msg, DPP_STATUS_OK);
-	}
-skip_wrapped_data:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	wpa_hexdump_buf(MSG_DEBUG,
-			"DPP: Authentication Request frame attributes", msg);
-
-	return msg;
-}
-
-
-static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth,
-					   enum dpp_status_error status,
-					   const struct wpabuf *pr,
-					   size_t nonce_len,
-					   const u8 *r_pubkey_hash,
-					   const u8 *i_pubkey_hash,
-					   const u8 *r_nonce, const u8 *i_nonce,
-					   const u8 *wrapped_r_auth,
-					   size_t wrapped_r_auth_len,
-					   const u8 *siv_key)
-{
-	struct wpabuf *msg;
-#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \
-		4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE
-	u8 clear[DPP_AUTH_RESP_CLEAR_LEN];
-	u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE];
-	const u8 *addr[2];
-	size_t len[2], siv_len, attr_len;
-	u8 *attr_start, *attr_end, *pos;
-
-	auth->waiting_auth_conf = 1;
-	auth->auth_resp_tries = 0;
-
-	/* Build DPP Authentication Response frame attributes */
-	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
-		4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data);
-#ifdef CONFIG_DPP2
-	attr_len += 5;
-#endif /* CONFIG_DPP2 */
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP)
-		attr_len += 5;
-#endif /* CONFIG_TESTING_OPTIONS */
-	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
-	if (!msg)
-		return NULL;
-
-	attr_start = wpabuf_put(msg, 0);
-
-	/* DPP Status */
-	if (status != 255)
-		dpp_build_attr_status(msg, status);
-
-	/* Responder Bootstrapping Key Hash */
-	dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
-
-	/* Initiator Bootstrapping Key Hash (mutual authentication) */
-	dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
-
-	/* Responder Protocol Key */
-	if (pr) {
-		wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
-		wpabuf_put_le16(msg, wpabuf_len(pr));
-		wpabuf_put_buf(msg, pr);
-	}
-
-#ifdef CONFIG_DPP2
-	/* Protocol Version */
-	if (auth->peer_version >= 2) {
-		wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
-		wpabuf_put_le16(msg, 1);
-		wpabuf_put_u8(msg, 2);
-	}
-#endif /* CONFIG_DPP2 */
-
-	attr_end = wpabuf_put(msg, 0);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
-		goto skip_wrapped_data;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */
-	pos = clear;
-
-	if (r_nonce) {
-		/* R-nonce */
-		WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE);
-		pos += 2;
-		WPA_PUT_LE16(pos, nonce_len);
-		pos += 2;
-		os_memcpy(pos, r_nonce, nonce_len);
-		pos += nonce_len;
-	}
-
-	if (i_nonce) {
-		/* I-nonce */
-		WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
-		pos += 2;
-		WPA_PUT_LE16(pos, nonce_len);
-		pos += 2;
-		os_memcpy(pos, i_nonce, nonce_len);
-#ifdef CONFIG_TESTING_OPTIONS
-		if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) {
-			wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch");
-			pos[nonce_len / 2] ^= 0x01;
-		}
-#endif /* CONFIG_TESTING_OPTIONS */
-		pos += nonce_len;
-	}
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab");
-		goto skip_r_capab;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* R-capabilities */
-	WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
-	pos += 2;
-	WPA_PUT_LE16(pos, 1);
-	pos += 2;
-	auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
-		DPP_CAPAB_ENROLLEE;
-	*pos++ = auth->r_capab;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_ZERO_R_CAPAB) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities");
-		pos[-1] = 0;
-	} else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - incompatible R-capabilities");
-		if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) ==
-		    (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE))
-			pos[-1] = 0;
-		else
-			pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE :
-				DPP_CAPAB_CONFIGURATOR;
-	}
-skip_r_capab:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (wrapped_r_auth) {
-		/* {R-auth}ke */
-		WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA);
-		pos += 2;
-		WPA_PUT_LE16(pos, wrapped_r_auth_len);
-		pos += 2;
-		os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len);
-		pos += wrapped_r_auth_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 */
-	addr[1] = attr_start;
-	len[1] = attr_end - attr_start;
-	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
-
-	siv_len = pos - clear;
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
-	if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len,
-			    2, addr, len, wrapped_data) < 0) {
-		wpabuf_free(msg);
-		return NULL;
-	}
-	siv_len += AES_BLOCK_SIZE;
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
-		    wrapped_data, siv_len);
-
-	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
-	wpabuf_put_le16(msg, siv_len);
-	wpabuf_put_data(msg, wrapped_data, siv_len);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
-		dpp_build_attr_status(msg, DPP_STATUS_OK);
-	}
-skip_wrapped_data:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	wpa_hexdump_buf(MSG_DEBUG,
-			"DPP: Authentication Response frame attributes", msg);
-	return msg;
-}
-
-
 static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes,
 			       u16 num_modes, unsigned int freq)
 {
@@ -2255,10 +564,9 @@
 }
 
 
-static int dpp_prepare_channel_list(struct dpp_authentication *auth,
-				    unsigned int neg_freq,
-				    struct hostapd_hw_modes *own_modes,
-				    u16 num_modes)
+int dpp_prepare_channel_list(struct dpp_authentication *auth,
+			     unsigned int neg_freq,
+			     struct hostapd_hw_modes *own_modes, u16 num_modes)
 {
 	int res;
 	char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end;
@@ -2269,6 +577,7 @@
 			return -1;
 		auth->num_freq = 1;
 		auth->freq[0] = neg_freq;
+		auth->curr_freq = neg_freq;
 		return 0;
 	}
 
@@ -2304,7 +613,7 @@
 }
 
 
-static int dpp_gen_uri(struct dpp_bootstrap_info *bi)
+int dpp_gen_uri(struct dpp_bootstrap_info *bi)
 {
 	char macstr[ETH_ALEN * 2 + 10];
 	size_t len;
@@ -2320,50 +629,27 @@
 	len += os_strlen(macstr); /* M:...; */
 	if (bi->info)
 		len += 3 + os_strlen(bi->info); /* I:...; */
+#ifdef CONFIG_DPP2
+	len += 4; /* V:2; */
+#endif /* CONFIG_DPP2 */
 	len += 4 + os_strlen(bi->pk); /* K:...;; */
 
 	os_free(bi->uri);
 	bi->uri = os_malloc(len + 1);
 	if (!bi->uri)
 		return -1;
-	os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%sK:%s;;",
+	os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%sK:%s;;",
 		    bi->chan ? "C:" : "", bi->chan ? bi->chan : "",
 		    bi->chan ? ";" : "",
 		    macstr,
 		    bi->info ? "I:" : "", bi->info ? bi->info : "",
 		    bi->info ? ";" : "",
+		    DPP_VERSION == 2 ? "V:2;" : "",
 		    bi->pk);
 	return 0;
 }
 
 
-static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth)
-{
-	struct dpp_bootstrap_info *bi;
-
-	if (auth->own_bi)
-		return 0; /* already generated */
-
-	bi = os_zalloc(sizeof(*bi));
-	if (!bi)
-		return -1;
-	bi->type = DPP_BOOTSTRAP_QR_CODE;
-	if (dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0) < 0 ||
-	    dpp_gen_uri(bi) < 0)
-		goto fail;
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Auto-generated own bootstrapping key info: URI %s",
-		   bi->uri);
-
-	auth->tmp_own_bi = auth->own_bi = bi;
-
-	return 0;
-fail:
-	dpp_bootstrap_info_free(bi);
-	return -1;
-}
-
-
 struct dpp_authentication *
 dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx)
 {
@@ -2379,151 +665,6 @@
 }
 
 
-struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx,
-					  struct dpp_bootstrap_info *peer_bi,
-					  struct dpp_bootstrap_info *own_bi,
-					  u8 dpp_allowed_roles,
-					  unsigned int neg_freq,
-					  struct hostapd_hw_modes *own_modes,
-					  u16 num_modes)
-{
-	struct dpp_authentication *auth;
-	size_t nonce_len;
-	size_t secret_len;
-	struct wpabuf *pi = NULL;
-	const u8 *r_pubkey_hash, *i_pubkey_hash;
-#ifdef CONFIG_TESTING_OPTIONS
-	u8 test_hash[SHA256_MAC_LEN];
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	auth = dpp_alloc_auth(dpp, msg_ctx);
-	if (!auth)
-		return NULL;
-	if (peer_bi->configurator_params &&
-	    dpp_set_configurator(auth, peer_bi->configurator_params) < 0)
-		goto fail;
-	auth->initiator = 1;
-	auth->waiting_auth_resp = 1;
-	auth->allowed_roles = dpp_allowed_roles;
-	auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR);
-	auth->peer_bi = peer_bi;
-	auth->own_bi = own_bi;
-	auth->curve = peer_bi->curve;
-
-	if (dpp_autogen_bootstrap_key(auth) < 0 ||
-	    dpp_prepare_channel_list(auth, neg_freq, own_modes, num_modes) < 0)
-		goto fail;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_nonce_override_len > 0) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce");
-		nonce_len = dpp_nonce_override_len;
-		os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len);
-	} else {
-		nonce_len = auth->curve->nonce_len;
-		if (random_get_bytes(auth->i_nonce, nonce_len)) {
-			wpa_printf(MSG_ERROR,
-				   "DPP: Failed to generate I-nonce");
-			goto fail;
-		}
-	}
-#else /* CONFIG_TESTING_OPTIONS */
-	nonce_len = auth->curve->nonce_len;
-	if (random_get_bytes(auth->i_nonce, nonce_len)) {
-		wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce");
-		goto fail;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_protocol_key_override_len) {
-		const struct dpp_curve_params *tmp_curve;
-
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - override protocol key");
-		auth->own_protocol_key = dpp_set_keypair(
-			&tmp_curve, dpp_protocol_key_override,
-			dpp_protocol_key_override_len);
-	} else {
-		auth->own_protocol_key = dpp_gen_keypair(auth->curve);
-	}
-#else /* CONFIG_TESTING_OPTIONS */
-	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
-#endif /* CONFIG_TESTING_OPTIONS */
-	if (!auth->own_protocol_key)
-		goto fail;
-
-	pi = dpp_get_pubkey_point(auth->own_protocol_key, 0);
-	if (!pi)
-		goto fail;
-
-	/* ECDH: M = pI * BR */
-	if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey,
-		     auth->Mx, &secret_len) < 0)
-		goto fail;
-	auth->secret_len = secret_len;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
-			auth->Mx, auth->secret_len);
-	auth->Mx_len = auth->secret_len;
-
-	if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
-			  auth->curve->hash_len) < 0)
-		goto fail;
-
-	r_pubkey_hash = auth->peer_bi->pubkey_hash;
-	i_pubkey_hash = auth->own_bi->pubkey_hash;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
-		r_pubkey_hash = NULL;
-	} else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
-		os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
-		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
-		r_pubkey_hash = test_hash;
-	} else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
-		i_pubkey_hash = NULL;
-	} else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
-		os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
-		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
-		i_pubkey_hash = test_hash;
-	} else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key");
-		wpabuf_free(pi);
-		pi = NULL;
-	} else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key");
-		wpabuf_free(pi);
-		pi = wpabuf_alloc(2 * auth->curve->prime_len);
-		if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0)
-			goto fail;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (neg_freq && auth->num_freq == 1 && auth->freq[0] == neg_freq)
-		neg_freq = 0;
-	auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash,
-					   i_pubkey_hash, neg_freq);
-	if (!auth->req_msg)
-		goto fail;
-
-out:
-	wpabuf_free(pi);
-	return auth;
-fail:
-	dpp_auth_deinit(auth);
-	auth = NULL;
-	goto out;
-}
-
-
 static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth,
 					       const char *json)
 {
@@ -2629,7 +770,7 @@
 }
 
 
-static void dpp_write_adv_proto(struct wpabuf *buf)
+void dpp_write_adv_proto(struct wpabuf *buf)
 {
 	/* Advertisement Protocol IE */
 	wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
@@ -2643,7 +784,7 @@
 }
 
 
-static void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query)
+void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query)
 {
 	/* GAS Query */
 	wpabuf_put_le16(buf, wpabuf_len(query));
@@ -2738,1704 +879,6 @@
 }
 
 
-static void dpp_auth_success(struct dpp_authentication *auth)
-{
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Authentication success - clear temporary keys");
-	os_memset(auth->Mx, 0, sizeof(auth->Mx));
-	auth->Mx_len = 0;
-	os_memset(auth->Nx, 0, sizeof(auth->Nx));
-	auth->Nx_len = 0;
-	os_memset(auth->Lx, 0, sizeof(auth->Lx));
-	auth->Lx_len = 0;
-	os_memset(auth->k1, 0, sizeof(auth->k1));
-	os_memset(auth->k2, 0, sizeof(auth->k2));
-
-	auth->auth_success = 1;
-}
-
-
-static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
-{
-	struct wpabuf *pix, *prx, *bix, *brx;
-	const u8 *addr[7];
-	size_t len[7];
-	size_t i, num_elem = 0;
-	size_t nonce_len;
-	u8 zero = 0;
-	int res = -1;
-
-	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
-	nonce_len = auth->curve->nonce_len;
-
-	if (auth->initiator) {
-		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
-		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
-		if (auth->own_bi)
-			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
-		else
-			bix = NULL;
-		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
-	} else {
-		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
-		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
-		if (auth->peer_bi)
-			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
-		else
-			bix = NULL;
-		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
-	}
-	if (!pix || !prx || !brx)
-		goto fail;
-
-	addr[num_elem] = auth->i_nonce;
-	len[num_elem] = nonce_len;
-	num_elem++;
-
-	addr[num_elem] = auth->r_nonce;
-	len[num_elem] = nonce_len;
-	num_elem++;
-
-	addr[num_elem] = wpabuf_head(pix);
-	len[num_elem] = wpabuf_len(pix) / 2;
-	num_elem++;
-
-	addr[num_elem] = wpabuf_head(prx);
-	len[num_elem] = wpabuf_len(prx) / 2;
-	num_elem++;
-
-	if (bix) {
-		addr[num_elem] = wpabuf_head(bix);
-		len[num_elem] = wpabuf_len(bix) / 2;
-		num_elem++;
-	}
-
-	addr[num_elem] = wpabuf_head(brx);
-	len[num_elem] = wpabuf_len(brx) / 2;
-	num_elem++;
-
-	addr[num_elem] = &zero;
-	len[num_elem] = 1;
-	num_elem++;
-
-	wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
-	for (i = 0; i < num_elem; i++)
-		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
-	res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
-	if (res == 0)
-		wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
-			    auth->curve->hash_len);
-fail:
-	wpabuf_free(pix);
-	wpabuf_free(prx);
-	wpabuf_free(bix);
-	wpabuf_free(brx);
-	return res;
-}
-
-
-static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
-{
-	struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
-	const u8 *addr[7];
-	size_t len[7];
-	size_t i, num_elem = 0;
-	size_t nonce_len;
-	u8 one = 1;
-	int res = -1;
-
-	/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
-	nonce_len = auth->curve->nonce_len;
-
-	if (auth->initiator) {
-		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
-		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
-		if (auth->own_bi)
-			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
-		else
-			bix = NULL;
-		if (!auth->peer_bi)
-			goto fail;
-		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
-	} else {
-		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
-		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
-		if (auth->peer_bi)
-			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
-		else
-			bix = NULL;
-		if (!auth->own_bi)
-			goto fail;
-		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
-	}
-	if (!pix || !prx || !brx)
-		goto fail;
-
-	addr[num_elem] = auth->r_nonce;
-	len[num_elem] = nonce_len;
-	num_elem++;
-
-	addr[num_elem] = auth->i_nonce;
-	len[num_elem] = nonce_len;
-	num_elem++;
-
-	addr[num_elem] = wpabuf_head(prx);
-	len[num_elem] = wpabuf_len(prx) / 2;
-	num_elem++;
-
-	addr[num_elem] = wpabuf_head(pix);
-	len[num_elem] = wpabuf_len(pix) / 2;
-	num_elem++;
-
-	addr[num_elem] = wpabuf_head(brx);
-	len[num_elem] = wpabuf_len(brx) / 2;
-	num_elem++;
-
-	if (bix) {
-		addr[num_elem] = wpabuf_head(bix);
-		len[num_elem] = wpabuf_len(bix) / 2;
-		num_elem++;
-	}
-
-	addr[num_elem] = &one;
-	len[num_elem] = 1;
-	num_elem++;
-
-	wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
-	for (i = 0; i < num_elem; i++)
-		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
-	res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
-	if (res == 0)
-		wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
-			    auth->curve->hash_len);
-fail:
-	wpabuf_free(pix);
-	wpabuf_free(prx);
-	wpabuf_free(bix);
-	wpabuf_free(brx);
-	return res;
-}
-
-
-static int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
-{
-	const EC_GROUP *group;
-	EC_POINT *l = NULL;
-	EC_KEY *BI = NULL, *bR = NULL, *pR = NULL;
-	const EC_POINT *BI_point;
-	BN_CTX *bnctx;
-	BIGNUM *lx, *sum, *q;
-	const BIGNUM *bR_bn, *pR_bn;
-	int ret = -1;
-
-	/* L = ((bR + pR) modulo q) * BI */
-
-	bnctx = BN_CTX_new();
-	sum = BN_new();
-	q = BN_new();
-	lx = BN_new();
-	if (!bnctx || !sum || !q || !lx)
-		goto fail;
-	BI = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
-	if (!BI)
-		goto fail;
-	BI_point = EC_KEY_get0_public_key(BI);
-	group = EC_KEY_get0_group(BI);
-	if (!group)
-		goto fail;
-
-	bR = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
-	pR = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
-	if (!bR || !pR)
-		goto fail;
-	bR_bn = EC_KEY_get0_private_key(bR);
-	pR_bn = EC_KEY_get0_private_key(pR);
-	if (!bR_bn || !pR_bn)
-		goto fail;
-	if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
-	    BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1)
-		goto fail;
-	l = EC_POINT_new(group);
-	if (!l ||
-	    EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
-						bnctx) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "OpenSSL: failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
-		goto fail;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
-	auth->Lx_len = auth->secret_len;
-	ret = 0;
-fail:
-	EC_POINT_clear_free(l);
-	EC_KEY_free(BI);
-	EC_KEY_free(bR);
-	EC_KEY_free(pR);
-	BN_clear_free(lx);
-	BN_clear_free(sum);
-	BN_free(q);
-	BN_CTX_free(bnctx);
-	return ret;
-}
-
-
-static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
-{
-	const EC_GROUP *group;
-	EC_POINT *l = NULL, *sum = NULL;
-	EC_KEY *bI = NULL, *BR = NULL, *PR = NULL;
-	const EC_POINT *BR_point, *PR_point;
-	BN_CTX *bnctx;
-	BIGNUM *lx;
-	const BIGNUM *bI_bn;
-	int ret = -1;
-
-	/* L = bI * (BR + PR) */
-
-	bnctx = BN_CTX_new();
-	lx = BN_new();
-	if (!bnctx || !lx)
-		goto fail;
-	BR = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
-	PR = EVP_PKEY_get1_EC_KEY(auth->peer_protocol_key);
-	if (!BR || !PR)
-		goto fail;
-	BR_point = EC_KEY_get0_public_key(BR);
-	PR_point = EC_KEY_get0_public_key(PR);
-
-	bI = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
-	if (!bI)
-		goto fail;
-	group = EC_KEY_get0_group(bI);
-	bI_bn = EC_KEY_get0_private_key(bI);
-	if (!group || !bI_bn)
-		goto fail;
-	sum = EC_POINT_new(group);
-	l = EC_POINT_new(group);
-	if (!sum || !l ||
-	    EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 ||
-	    EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
-						bnctx) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "OpenSSL: failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-
-	if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
-		goto fail;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
-	auth->Lx_len = auth->secret_len;
-	ret = 0;
-fail:
-	EC_POINT_clear_free(l);
-	EC_POINT_clear_free(sum);
-	EC_KEY_free(bI);
-	EC_KEY_free(BR);
-	EC_KEY_free(PR);
-	BN_clear_free(lx);
-	BN_CTX_free(bnctx);
-	return ret;
-}
-
-
-static int dpp_auth_build_resp_ok(struct dpp_authentication *auth)
-{
-	size_t nonce_len;
-	size_t secret_len;
-	struct wpabuf *msg, *pr = NULL;
-	u8 r_auth[4 + DPP_MAX_HASH_LEN];
-	u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth;
-	size_t wrapped_r_auth_len;
-	int ret = -1;
-	const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce;
-	enum dpp_status_error status = DPP_STATUS_OK;
-#ifdef CONFIG_TESTING_OPTIONS
-	u8 test_hash[SHA256_MAC_LEN];
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
-	if (!auth->own_bi)
-		return -1;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_nonce_override_len > 0) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce");
-		nonce_len = dpp_nonce_override_len;
-		os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len);
-	} else {
-		nonce_len = auth->curve->nonce_len;
-		if (random_get_bytes(auth->r_nonce, nonce_len)) {
-			wpa_printf(MSG_ERROR,
-				   "DPP: Failed to generate R-nonce");
-			goto fail;
-		}
-	}
-#else /* CONFIG_TESTING_OPTIONS */
-	nonce_len = auth->curve->nonce_len;
-	if (random_get_bytes(auth->r_nonce, nonce_len)) {
-		wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce");
-		goto fail;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
-
-	EVP_PKEY_free(auth->own_protocol_key);
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_protocol_key_override_len) {
-		const struct dpp_curve_params *tmp_curve;
-
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - override protocol key");
-		auth->own_protocol_key = dpp_set_keypair(
-			&tmp_curve, dpp_protocol_key_override,
-			dpp_protocol_key_override_len);
-	} else {
-		auth->own_protocol_key = dpp_gen_keypair(auth->curve);
-	}
-#else /* CONFIG_TESTING_OPTIONS */
-	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
-#endif /* CONFIG_TESTING_OPTIONS */
-	if (!auth->own_protocol_key)
-		goto fail;
-
-	pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
-	if (!pr)
-		goto fail;
-
-	/* ECDH: N = pR * PI */
-	if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
-		     auth->Nx, &secret_len) < 0)
-		goto fail;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
-			auth->Nx, auth->secret_len);
-	auth->Nx_len = auth->secret_len;
-
-	if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
-			  auth->curve->hash_len) < 0)
-		goto fail;
-
-	if (auth->own_bi && auth->peer_bi) {
-		/* Mutual authentication */
-		if (dpp_auth_derive_l_responder(auth) < 0)
-			goto fail;
-	}
-
-	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
-		goto fail;
-
-	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
-	WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG);
-	WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len);
-	if (dpp_gen_r_auth(auth, r_auth + 4) < 0)
-		goto fail;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch");
-		r_auth[4 + auth->curve->hash_len / 2] ^= 0x01;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
-			    r_auth, 4 + auth->curve->hash_len,
-			    0, NULL, NULL, wrapped_r_auth) < 0)
-		goto fail;
-	wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE;
-	wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke",
-		    wrapped_r_auth, wrapped_r_auth_len);
-	w_r_auth = wrapped_r_auth;
-
-	r_pubkey_hash = auth->own_bi->pubkey_hash;
-	if (auth->peer_bi)
-		i_pubkey_hash = auth->peer_bi->pubkey_hash;
-	else
-		i_pubkey_hash = NULL;
-
-	i_nonce = auth->i_nonce;
-	r_nonce = auth->r_nonce;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
-		r_pubkey_hash = NULL;
-	} else if (dpp_test ==
-		   DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
-		os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
-		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
-		r_pubkey_hash = test_hash;
-	} else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
-		i_pubkey_hash = NULL;
-	} else if (dpp_test ==
-		   DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
-		if (i_pubkey_hash)
-			os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
-		else
-			os_memset(test_hash, 0, SHA256_MAC_LEN);
-		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
-		i_pubkey_hash = test_hash;
-	} else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key");
-		wpabuf_free(pr);
-		pr = NULL;
-	} else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key");
-		wpabuf_free(pr);
-		pr = wpabuf_alloc(2 * auth->curve->prime_len);
-		if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0)
-			goto fail;
-	} else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth");
-		w_r_auth = NULL;
-		wrapped_r_auth_len = 0;
-	} else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
-		status = 255;
-	} else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
-		status = 254;
-	} else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce");
-		r_nonce = NULL;
-	} else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
-		i_nonce = NULL;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	msg = dpp_auth_build_resp(auth, status, pr, nonce_len,
-				  r_pubkey_hash, i_pubkey_hash,
-				  r_nonce, i_nonce,
-				  w_r_auth, wrapped_r_auth_len,
-				  auth->k2);
-	if (!msg)
-		goto fail;
-	wpabuf_free(auth->resp_msg);
-	auth->resp_msg = msg;
-	ret = 0;
-fail:
-	wpabuf_free(pr);
-	return ret;
-}
-
-
-static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
-				      enum dpp_status_error status)
-{
-	struct wpabuf *msg;
-	const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce;
-#ifdef CONFIG_TESTING_OPTIONS
-	u8 test_hash[SHA256_MAC_LEN];
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (!auth->own_bi)
-		return -1;
-	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
-
-	r_pubkey_hash = auth->own_bi->pubkey_hash;
-	if (auth->peer_bi)
-		i_pubkey_hash = auth->peer_bi->pubkey_hash;
-	else
-		i_pubkey_hash = NULL;
-
-	i_nonce = auth->i_nonce;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
-		r_pubkey_hash = NULL;
-	} else if (dpp_test ==
-		   DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
-		os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
-		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
-		r_pubkey_hash = test_hash;
-	} else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
-		i_pubkey_hash = NULL;
-	} else if (dpp_test ==
-		   DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
-		if (i_pubkey_hash)
-			os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
-		else
-			os_memset(test_hash, 0, SHA256_MAC_LEN);
-		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
-		i_pubkey_hash = test_hash;
-	} else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
-		status = 255;
-	} else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
-		i_nonce = NULL;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len,
-				  r_pubkey_hash, i_pubkey_hash,
-				  NULL, i_nonce, NULL, 0, auth->k1);
-	if (!msg)
-		return -1;
-	wpabuf_free(auth->resp_msg);
-	auth->resp_msg = msg;
-	return 0;
-}
-
-
-struct dpp_authentication *
-dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles,
-		int qr_mutual, struct dpp_bootstrap_info *peer_bi,
-		struct dpp_bootstrap_info *own_bi,
-		unsigned int freq, const u8 *hdr, const u8 *attr_start,
-		size_t attr_len)
-{
-	EVP_PKEY *pi = NULL;
-	EVP_PKEY_CTX *ctx = NULL;
-	size_t secret_len;
-	const u8 *addr[2];
-	size_t len[2];
-	u8 *unwrapped = NULL;
-	size_t unwrapped_len = 0;
-	const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap,
-		*channel;
-	u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len,
-		i_bootstrap_len, channel_len;
-	struct dpp_authentication *auth = NULL;
-#ifdef CONFIG_DPP2
-	const u8 *version;
-	u16 version_len;
-#endif /* CONFIG_DPP2 */
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - stop at Authentication Request");
-		return NULL;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	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) {
-		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-			"Missing or invalid required Wrapped Data attribute");
-		return NULL;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data",
-		    wrapped_data, wrapped_data_len);
-	attr_len = wrapped_data - 4 - attr_start;
-
-	auth = dpp_alloc_auth(dpp, msg_ctx);
-	if (!auth)
-		goto fail;
-	if (peer_bi && peer_bi->configurator_params &&
-	    dpp_set_configurator(auth, peer_bi->configurator_params) < 0)
-		goto fail;
-	auth->peer_bi = peer_bi;
-	auth->own_bi = own_bi;
-	auth->curve = own_bi->curve;
-	auth->curr_freq = freq;
-
-	auth->peer_version = 1; /* default to the first version */
-#ifdef CONFIG_DPP2
-	version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
-			       &version_len);
-	if (version) {
-		if (version_len < 1 || version[0] == 0) {
-			dpp_auth_fail(auth,
-				      "Invalid Protocol Version attribute");
-			goto fail;
-		}
-		auth->peer_version = version[0];
-		wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
-			   auth->peer_version);
-	}
-#endif /* CONFIG_DPP2 */
-
-	channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL,
-			       &channel_len);
-	if (channel) {
-		int neg_freq;
-
-		if (channel_len < 2) {
-			dpp_auth_fail(auth, "Too short Channel attribute");
-			goto fail;
-		}
-
-		neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]);
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d",
-			   channel[0], channel[1], neg_freq);
-		if (neg_freq < 0) {
-			dpp_auth_fail(auth,
-				      "Unsupported Channel attribute value");
-			goto fail;
-		}
-
-		if (auth->curr_freq != (unsigned int) neg_freq) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Changing negotiation channel from %u MHz to %u MHz",
-				   freq, neg_freq);
-			auth->curr_freq = neg_freq;
-		}
-	}
-
-	i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
-			       &i_proto_len);
-	if (!i_proto) {
-		dpp_auth_fail(auth,
-			      "Missing required Initiator Protocol Key attribute");
-		goto fail;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key",
-		    i_proto, i_proto_len);
-
-	/* M = bR * PI */
-	pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len);
-	if (!pi) {
-		dpp_auth_fail(auth, "Invalid Initiator Protocol Key");
-		goto fail;
-	}
-	dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
-
-	if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0)
-		goto fail;
-	auth->secret_len = secret_len;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
-			auth->Mx, auth->secret_len);
-	auth->Mx_len = auth->secret_len;
-
-	if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
-			  auth->curve->hash_len) < 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->k1, 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) {
-		dpp_auth_fail(auth, "Missing or invalid I-nonce");
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
-	os_memcpy(auth->i_nonce, i_nonce, i_nonce_len);
-
-	i_capab = dpp_get_attr(unwrapped, unwrapped_len,
-			       DPP_ATTR_I_CAPABILITIES,
-			       &i_capab_len);
-	if (!i_capab || i_capab_len < 1) {
-		dpp_auth_fail(auth, "Missing or invalid I-capabilities");
-		goto fail;
-	}
-	auth->i_capab = i_capab[0];
-	wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab);
-
-	bin_clear_free(unwrapped, unwrapped_len);
-	unwrapped = NULL;
-
-	switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) {
-	case DPP_CAPAB_ENROLLEE:
-		if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Local policy does not allow Configurator role");
-			goto not_compatible;
-		}
-		wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
-		auth->configurator = 1;
-		break;
-	case DPP_CAPAB_CONFIGURATOR:
-		if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Local policy does not allow Enrollee role");
-			goto not_compatible;
-		}
-		wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
-		auth->configurator = 0;
-		break;
-	case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE:
-		if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) {
-			wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
-			auth->configurator = 0;
-		} else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) {
-			wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
-			auth->configurator = 1;
-		} else {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Local policy does not allow Configurator/Enrollee role");
-			goto not_compatible;
-		}
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities");
-		wpa_msg(auth->msg_ctx, MSG_INFO,
-			DPP_EVENT_FAIL "Invalid role in I-capabilities 0x%02x",
-			auth->i_capab & DPP_CAPAB_ROLE_MASK);
-		goto fail;
-	}
-
-	auth->peer_protocol_key = pi;
-	pi = NULL;
-	if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) {
-		char hex[SHA256_MAC_LEN * 2 + 1];
-
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
-		if (dpp_auth_build_resp_status(auth,
-					       DPP_STATUS_RESPONSE_PENDING) < 0)
-			goto fail;
-		i_bootstrap = dpp_get_attr(attr_start, attr_len,
-					   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
-					   &i_bootstrap_len);
-		if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) {
-			auth->response_pending = 1;
-			os_memcpy(auth->waiting_pubkey_hash,
-				  i_bootstrap, i_bootstrap_len);
-			wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap,
-					 i_bootstrap_len);
-		} else {
-			hex[0] = '\0';
-		}
-
-		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE
-			"%s", hex);
-		return auth;
-	}
-	if (dpp_auth_build_resp_ok(auth) < 0)
-		goto fail;
-
-	return auth;
-
-not_compatible:
-	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
-		"i-capab=0x%02x", auth->i_capab);
-	if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)
-		auth->configurator = 1;
-	else
-		auth->configurator = 0;
-	auth->peer_protocol_key = pi;
-	pi = NULL;
-	if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
-		goto fail;
-
-	auth->remove_on_tx_status = 1;
-	return auth;
-fail:
-	bin_clear_free(unwrapped, unwrapped_len);
-	EVP_PKEY_free(pi);
-	EVP_PKEY_CTX_free(ctx);
-	dpp_auth_deinit(auth);
-	return NULL;
-}
-
-
-int dpp_notify_new_qr_code(struct dpp_authentication *auth,
-			   struct dpp_bootstrap_info *peer_bi)
-{
-	if (!auth || !auth->response_pending ||
-	    os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash,
-		      SHA256_MAC_LEN) != 0)
-		return 0;
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with "
-		   MACSTR, MAC2STR(auth->peer_mac_addr));
-	auth->peer_bi = peer_bi;
-
-	if (dpp_auth_build_resp_ok(auth) < 0)
-		return -1;
-
-	return 1;
-}
-
-
-static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth,
-					   enum dpp_status_error status)
-{
-	struct wpabuf *msg;
-	u8 i_auth[4 + DPP_MAX_HASH_LEN];
-	size_t i_auth_len;
-	u8 r_nonce[4 + DPP_MAX_NONCE_LEN];
-	size_t r_nonce_len;
-	const u8 *addr[2];
-	size_t len[2], attr_len;
-	u8 *wrapped_i_auth;
-	u8 *wrapped_r_nonce;
-	u8 *attr_start, *attr_end;
-	const u8 *r_pubkey_hash, *i_pubkey_hash;
-#ifdef CONFIG_TESTING_OPTIONS
-	u8 test_hash[SHA256_MAC_LEN];
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation");
-
-	i_auth_len = 4 + auth->curve->hash_len;
-	r_nonce_len = 4 + auth->curve->nonce_len;
-	/* Build DPP Authentication Confirmation frame attributes */
-	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
-		4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF)
-		attr_len += 5;
-#endif /* CONFIG_TESTING_OPTIONS */
-	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len);
-	if (!msg)
-		goto fail;
-
-	attr_start = wpabuf_put(msg, 0);
-
-	r_pubkey_hash = auth->peer_bi->pubkey_hash;
-	if (auth->own_bi)
-		i_pubkey_hash = auth->own_bi->pubkey_hash;
-	else
-		i_pubkey_hash = NULL;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
-		goto skip_status;
-	} else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
-		status = 254;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* DPP Status */
-	dpp_build_attr_status(msg, status);
-
-#ifdef CONFIG_TESTING_OPTIONS
-skip_status:
-	if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash");
-		r_pubkey_hash = NULL;
-	} else if (dpp_test ==
-		   DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - invalid R-Bootstrap Key Hash");
-		os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN);
-		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
-		r_pubkey_hash = test_hash;
-	} else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash");
-		i_pubkey_hash = NULL;
-	} else if (dpp_test ==
-		   DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - invalid I-Bootstrap Key Hash");
-		if (i_pubkey_hash)
-			os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN);
-		else
-			os_memset(test_hash, 0, SHA256_MAC_LEN);
-		test_hash[SHA256_MAC_LEN - 1] ^= 0x01;
-		i_pubkey_hash = test_hash;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* Responder Bootstrapping Key Hash */
-	dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
-
-	/* Initiator Bootstrapping Key Hash (mutual authentication) */
-	dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF)
-		goto skip_wrapped_data;
-	if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
-		i_auth_len = 0;
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	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]);
-
-	if (status == DPP_STATUS_OK) {
-		/* I-auth wrapped with ke */
-		wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
-		wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE);
-		wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE);
-
-#ifdef CONFIG_TESTING_OPTIONS
-		if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF)
-			goto skip_i_auth;
-#endif /* CONFIG_TESTING_OPTIONS */
-
-		/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |]
-		 *	      1) */
-		WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG);
-		WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len);
-		if (dpp_gen_i_auth(auth, i_auth + 4) < 0)
-			goto fail;
-
-#ifdef CONFIG_TESTING_OPTIONS
-		if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) {
-			wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch");
-			i_auth[4 + auth->curve->hash_len / 2] ^= 0x01;
-		}
-skip_i_auth:
-#endif /* CONFIG_TESTING_OPTIONS */
-		if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
-				    i_auth, i_auth_len,
-				    2, addr, len, wrapped_i_auth) < 0)
-			goto fail;
-		wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke",
-			    wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE);
-	} else {
-		/* R-nonce wrapped with k2 */
-		wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
-		wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE);
-		wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE);
-
-		WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE);
-		WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len);
-		os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len);
-
-		if (aes_siv_encrypt(auth->k2, auth->curve->hash_len,
-				    r_nonce, r_nonce_len,
-				    2, addr, len, wrapped_r_nonce) < 0)
-			goto fail;
-		wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2",
-			    wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE);
-	}
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
-		dpp_build_attr_status(msg, DPP_STATUS_OK);
-	}
-skip_wrapped_data:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	wpa_hexdump_buf(MSG_DEBUG,
-			"DPP: Authentication Confirmation frame attributes",
-			msg);
-	if (status == DPP_STATUS_OK)
-		dpp_auth_success(auth);
-
-	return msg;
-
-fail:
-	wpabuf_free(msg);
-	return NULL;
-}
-
-
-static void
-dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr,
-			const u8 *attr_start, size_t attr_len,
-			const u8 *wrapped_data, u16 wrapped_data_len,
-			enum dpp_status_error status)
-{
-	const u8 *addr[2];
-	size_t len[2];
-	u8 *unwrapped = NULL;
-	size_t unwrapped_len = 0;
-	const u8 *i_nonce, *r_capab;
-	u16 i_nonce_len, r_capab_len;
-
-	if (status == DPP_STATUS_NOT_COMPATIBLE) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Responder reported incompatible roles");
-	} else if (status == DPP_STATUS_RESPONSE_PENDING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Responder reported more time needed");
-	} else {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Responder reported failure (status %d)",
-			   status);
-		dpp_auth_fail(auth, "Responder reported failure");
-		return;
-	}
-
-	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->k1, 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) {
-		dpp_auth_fail(auth, "Missing or invalid I-nonce");
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
-	if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
-		dpp_auth_fail(auth, "I-nonce mismatch");
-		goto fail;
-	}
-
-	r_capab = dpp_get_attr(unwrapped, unwrapped_len,
-			       DPP_ATTR_R_CAPABILITIES,
-			       &r_capab_len);
-	if (!r_capab || r_capab_len < 1) {
-		dpp_auth_fail(auth, "Missing or invalid R-capabilities");
-		goto fail;
-	}
-	auth->r_capab = r_capab[0];
-	wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
-	if (status == DPP_STATUS_NOT_COMPATIBLE) {
-		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
-			"r-capab=0x%02x", auth->r_capab);
-	} else if (status == DPP_STATUS_RESPONSE_PENDING) {
-		u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK;
-
-		if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) ||
-		    (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) {
-			wpa_msg(auth->msg_ctx, MSG_INFO,
-				DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x",
-				role);
-		} else {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Continue waiting for full DPP Authentication Response");
-			wpa_msg(auth->msg_ctx, MSG_INFO,
-				DPP_EVENT_RESPONSE_PENDING "%s",
-				auth->tmp_own_bi ? auth->tmp_own_bi->uri : "");
-		}
-	}
-fail:
-	bin_clear_free(unwrapped, unwrapped_len);
-}
-
-
-struct wpabuf *
-dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
-		 const u8 *attr_start, size_t attr_len)
-{
-	EVP_PKEY *pr;
-	size_t secret_len;
-	const u8 *addr[2];
-	size_t len[2];
-	u8 *unwrapped = NULL, *unwrapped2 = NULL;
-	size_t unwrapped_len = 0, unwrapped2_len = 0;
-	const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto,
-		*r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth;
-	u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
-		r_proto_len, r_nonce_len, i_nonce_len, r_capab_len,
-		wrapped2_len, r_auth_len;
-	u8 r_auth2[DPP_MAX_HASH_LEN];
-	u8 role;
-#ifdef CONFIG_DPP2
-	const u8 *version;
-	u16 version_len;
-#endif /* CONFIG_DPP2 */
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - stop at Authentication Response");
-		return NULL;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (!auth->initiator || !auth->peer_bi) {
-		dpp_auth_fail(auth, "Unexpected Authentication Response");
-		return NULL;
-	}
-
-	auth->waiting_auth_resp = 0;
-
-	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");
-		return NULL;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
-		    wrapped_data, wrapped_data_len);
-
-	attr_len = wrapped_data - 4 - attr_start;
-
-	r_bootstrap = dpp_get_attr(attr_start, attr_len,
-				   DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
-				   &r_bootstrap_len);
-	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
-		dpp_auth_fail(auth,
-			      "Missing or invalid required Responder Bootstrapping Key Hash attribute");
-		return NULL;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
-		    r_bootstrap, r_bootstrap_len);
-	if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash,
-		      SHA256_MAC_LEN) != 0) {
-		dpp_auth_fail(auth,
-			      "Unexpected Responder Bootstrapping Key Hash value");
-		wpa_hexdump(MSG_DEBUG,
-			    "DPP: Expected Responder Bootstrapping Key Hash",
-			    auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
-		return NULL;
-	}
-
-	i_bootstrap = dpp_get_attr(attr_start, attr_len,
-				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
-				   &i_bootstrap_len);
-	if (i_bootstrap) {
-		if (i_bootstrap_len != SHA256_MAC_LEN) {
-			dpp_auth_fail(auth,
-				      "Invalid Initiator Bootstrapping Key Hash attribute");
-			return NULL;
-		}
-		wpa_hexdump(MSG_MSGDUMP,
-			    "DPP: Initiator Bootstrapping Key Hash",
-			    i_bootstrap, i_bootstrap_len);
-		if (!auth->own_bi ||
-		    os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash,
-			      SHA256_MAC_LEN) != 0) {
-			dpp_auth_fail(auth,
-				      "Initiator Bootstrapping Key Hash attribute did not match");
-			return NULL;
-		}
-	} else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) {
-		/* PKEX bootstrapping mandates use of mutual authentication */
-		dpp_auth_fail(auth,
-			      "Missing Initiator Bootstrapping Key Hash attribute");
-		return NULL;
-	} else if (auth->own_bi &&
-		   auth->own_bi->type == DPP_BOOTSTRAP_NFC_URI &&
-		   auth->own_bi->nfc_negotiated) {
-		/* NFC negotiated connection handover bootstrapping mandates
-		 * use of mutual authentication */
-		dpp_auth_fail(auth,
-			      "Missing Initiator Bootstrapping Key Hash attribute");
-		return NULL;
-	}
-
-	auth->peer_version = 1; /* default to the first version */
-#ifdef CONFIG_DPP2
-	version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION,
-			       &version_len);
-	if (version) {
-		if (version_len < 1 || version[0] == 0) {
-			dpp_auth_fail(auth,
-				      "Invalid Protocol Version attribute");
-			return NULL;
-		}
-		auth->peer_version = version[0];
-		wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
-			   auth->peer_version);
-	}
-#endif /* CONFIG_DPP2 */
-
-	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
-			      &status_len);
-	if (!status || status_len < 1) {
-		dpp_auth_fail(auth,
-			      "Missing or invalid required DPP Status attribute");
-		return NULL;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
-	auth->auth_resp_status = status[0];
-	if (status[0] != DPP_STATUS_OK) {
-		dpp_auth_resp_rx_status(auth, hdr, attr_start,
-					attr_len, wrapped_data,
-					wrapped_data_len, status[0]);
-		return NULL;
-	}
-
-	if (!i_bootstrap && auth->own_bi) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Responder decided not to use mutual authentication");
-		auth->own_bi = NULL;
-	}
-
-	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d",
-		auth->own_bi != NULL);
-
-	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");
-		return NULL;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
-		    r_proto, r_proto_len);
-
-	/* N = pI * PR */
-	pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len);
-	if (!pr) {
-		dpp_auth_fail(auth, "Invalid Responder Protocol Key");
-		return NULL;
-	}
-	dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
-
-	if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) {
-		dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
-		goto fail;
-	}
-	EVP_PKEY_free(auth->peer_protocol_key);
-	auth->peer_protocol_key = pr;
-	pr = NULL;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
-			auth->Nx, auth->secret_len);
-	auth->Nx_len = auth->secret_len;
-
-	if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
-			  auth->curve->hash_len) < 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->k2, 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;
-	}
-
-	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, "DPP: 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);
-
-	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) {
-		dpp_auth_fail(auth, "Missing or invalid I-nonce");
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
-	if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
-		dpp_auth_fail(auth, "I-nonce mismatch");
-		goto fail;
-	}
-
-	if (auth->own_bi) {
-		/* Mutual authentication */
-		if (dpp_auth_derive_l_initiator(auth) < 0)
-			goto fail;
-	}
-
-	r_capab = dpp_get_attr(unwrapped, unwrapped_len,
-			       DPP_ATTR_R_CAPABILITIES,
-			       &r_capab_len);
-	if (!r_capab || r_capab_len < 1) {
-		dpp_auth_fail(auth, "Missing or invalid R-capabilities");
-		goto fail;
-	}
-	auth->r_capab = r_capab[0];
-	wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
-	role = auth->r_capab & DPP_CAPAB_ROLE_MASK;
-	if ((auth->allowed_roles ==
-	     (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) &&
-	    (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) {
-		/* Peer selected its role, so move from "either role" to the
-		 * role that is compatible with peer's selection. */
-		auth->configurator = role == DPP_CAPAB_ENROLLEE;
-		wpa_printf(MSG_DEBUG, "DPP: Acting as %s",
-			   auth->configurator ? "Configurator" : "Enrollee");
-	} else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) ||
-		   (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) {
-		wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection");
-		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-			"Unexpected role in R-capabilities 0x%02x",
-			role);
-		if (role != DPP_CAPAB_ENROLLEE &&
-		    role != DPP_CAPAB_CONFIGURATOR)
-			goto fail;
-		bin_clear_free(unwrapped, unwrapped_len);
-		auth->remove_on_tx_status = 1;
-		return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE);
-	}
-
-	wrapped2 = dpp_get_attr(unwrapped, unwrapped_len,
-				DPP_ATTR_WRAPPED_DATA, &wrapped2_len);
-	if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) {
-		dpp_auth_fail(auth,
-			      "Missing or invalid Secondary Wrapped Data");
-		goto fail;
-	}
-
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
-		    wrapped2, wrapped2_len);
-
-	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
-		goto fail;
-
-	unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE;
-	unwrapped2 = os_malloc(unwrapped2_len);
-	if (!unwrapped2)
-		goto fail;
-	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
-			    wrapped2, wrapped2_len,
-			    0, NULL, NULL, unwrapped2) < 0) {
-		dpp_auth_fail(auth, "AES-SIV decryption failed");
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
-		    unwrapped2, unwrapped2_len);
-
-	if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) {
-		dpp_auth_fail(auth,
-			      "Invalid attribute in secondary unwrapped data");
-		goto fail;
-	}
-
-	r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG,
-			       &r_auth_len);
-	if (!r_auth || r_auth_len != auth->curve->hash_len) {
-		dpp_auth_fail(auth,
-			      "Missing or invalid Responder Authenticating Tag");
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag",
-		    r_auth, r_auth_len);
-	/* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
-	if (dpp_gen_r_auth(auth, r_auth2) < 0)
-		goto fail;
-	wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag",
-		    r_auth2, r_auth_len);
-	if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) {
-		dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag");
-		bin_clear_free(unwrapped, unwrapped_len);
-		bin_clear_free(unwrapped2, unwrapped2_len);
-		auth->remove_on_tx_status = 1;
-		return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE);
-	}
-
-	bin_clear_free(unwrapped, unwrapped_len);
-	bin_clear_free(unwrapped2, unwrapped2_len);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - Authentication Response in place of Confirm");
-		if (dpp_auth_build_resp_ok(auth) < 0)
-			return NULL;
-		return wpabuf_dup(auth->resp_msg);
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	return dpp_auth_build_conf(auth, DPP_STATUS_OK);
-
-fail:
-	bin_clear_free(unwrapped, unwrapped_len);
-	bin_clear_free(unwrapped2, unwrapped2_len);
-	EVP_PKEY_free(pr);
-	return NULL;
-}
-
-
-static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth,
-				    const u8 *hdr,
-				    const u8 *attr_start, size_t attr_len,
-				    const u8 *wrapped_data,
-				    u16 wrapped_data_len,
-				    enum dpp_status_error status)
-{
-	const u8 *addr[2];
-	size_t len[2];
-	u8 *unwrapped = NULL;
-	size_t unwrapped_len = 0;
-	const u8 *r_nonce;
-	u16 r_nonce_len;
-
-	/* Authentication Confirm failure cases are expected to include
-	 * {R-nonce}k2 in the Wrapped Data attribute. */
-
-	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) {
-		dpp_auth_fail(auth, "Authentication failed");
-		goto fail;
-	}
-	if (aes_siv_decrypt(auth->k2, 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;
-	}
-
-	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, "DPP: Missing or invalid R-nonce");
-		goto fail;
-	}
-	if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) {
-		wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce",
-			    r_nonce, r_nonce_len);
-		wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce",
-			    auth->r_nonce, r_nonce_len);
-		dpp_auth_fail(auth, "R-nonce mismatch");
-		goto fail;
-	}
-
-	if (status == DPP_STATUS_NOT_COMPATIBLE)
-		dpp_auth_fail(auth, "Peer reported incompatible R-capab role");
-	else if (status == DPP_STATUS_AUTH_FAILURE)
-		dpp_auth_fail(auth, "Peer reported authentication failure)");
-
-fail:
-	bin_clear_free(unwrapped, unwrapped_len);
-	return -1;
-}
-
-
-int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
-		     const u8 *attr_start, size_t attr_len)
-{
-	const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth;
-	u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
-		i_auth_len;
-	const u8 *addr[2];
-	size_t len[2];
-	u8 *unwrapped = NULL;
-	size_t unwrapped_len = 0;
-	u8 i_auth2[DPP_MAX_HASH_LEN];
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - stop at Authentication Confirm");
-		return -1;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (auth->initiator || !auth->own_bi || !auth->waiting_auth_conf) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: initiator=%d own_bi=%d waiting_auth_conf=%d",
-			   auth->initiator, !!auth->own_bi,
-			   auth->waiting_auth_conf);
-		dpp_auth_fail(auth, "Unexpected Authentication Confirm");
-		return -1;
-	}
-
-	auth->waiting_auth_conf = 0;
-
-	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");
-		return -1;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
-		    wrapped_data, wrapped_data_len);
-
-	attr_len = wrapped_data - 4 - attr_start;
-
-	r_bootstrap = dpp_get_attr(attr_start, attr_len,
-				   DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
-				   &r_bootstrap_len);
-	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
-		dpp_auth_fail(auth,
-			      "Missing or invalid required Responder Bootstrapping Key Hash attribute");
-		return -1;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
-		    r_bootstrap, r_bootstrap_len);
-	if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash,
-		      SHA256_MAC_LEN) != 0) {
-		wpa_hexdump(MSG_DEBUG,
-			    "DPP: Expected Responder Bootstrapping Key Hash",
-			    auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
-		dpp_auth_fail(auth,
-			      "Responder Bootstrapping Key Hash mismatch");
-		return -1;
-	}
-
-	i_bootstrap = dpp_get_attr(attr_start, attr_len,
-				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
-				   &i_bootstrap_len);
-	if (i_bootstrap) {
-		if (i_bootstrap_len != SHA256_MAC_LEN) {
-			dpp_auth_fail(auth,
-				      "Invalid Initiator Bootstrapping Key Hash attribute");
-			return -1;
-		}
-		wpa_hexdump(MSG_MSGDUMP,
-			    "DPP: Initiator Bootstrapping Key Hash",
-			    i_bootstrap, i_bootstrap_len);
-		if (!auth->peer_bi ||
-		    os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash,
-			      SHA256_MAC_LEN) != 0) {
-			dpp_auth_fail(auth,
-				      "Initiator Bootstrapping Key Hash mismatch");
-			return -1;
-		}
-	} else if (auth->peer_bi) {
-		/* Mutual authentication and peer did not include its
-		 * Bootstrapping Key Hash attribute. */
-		dpp_auth_fail(auth,
-			      "Missing Initiator Bootstrapping Key Hash attribute");
-		return -1;
-	}
-
-	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
-			      &status_len);
-	if (!status || status_len < 1) {
-		dpp_auth_fail(auth,
-			      "Missing or invalid required DPP Status attribute");
-		return -1;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
-	if (status[0] == DPP_STATUS_NOT_COMPATIBLE ||
-	    status[0] == DPP_STATUS_AUTH_FAILURE)
-		return dpp_auth_conf_rx_failure(auth, hdr, attr_start,
-						attr_len, wrapped_data,
-						wrapped_data_len, status[0]);
-
-	if (status[0] != DPP_STATUS_OK) {
-		dpp_auth_fail(auth, "Authentication failed");
-		return -1;
-	}
-
-	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)
-		return -1;
-	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_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
-			      &i_auth_len);
-	if (!i_auth || i_auth_len != auth->curve->hash_len) {
-		dpp_auth_fail(auth,
-			      "Missing or invalid Initiator Authenticating Tag");
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag",
-		    i_auth, i_auth_len);
-	/* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
-	if (dpp_gen_i_auth(auth, i_auth2) < 0)
-		goto fail;
-	wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag",
-		    i_auth2, i_auth_len);
-	if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) {
-		dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag");
-		goto fail;
-	}
-
-	bin_clear_free(unwrapped, unwrapped_len);
-	dpp_auth_success(auth);
-	return 0;
-fail:
-	bin_clear_free(unwrapped, unwrapped_len);
-	return -1;
-}
-
-
 static int bin_str_eq(const char *val, size_t len, const char *cmp)
 {
 	return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0;
@@ -4747,7 +1190,7 @@
 	wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
 
 	pos = os_strstr(cmd, " configurator=");
-	if (pos) {
+	if (!auth->conf && pos) {
 		pos += 14;
 		auth->conf = dpp_configurator_get_id(auth->global, atoi(pos));
 		if (!auth->conf) {
@@ -4781,20 +1224,6 @@
 }
 
 
-static void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key)
-{
-	while (key) {
-		struct dpp_asymmetric_key *next = key->next;
-
-		EVP_PKEY_free(key->csign);
-		str_clear_free(key->config_template);
-		str_clear_free(key->connector_template);
-		os_free(key);
-		key = next;
-	}
-}
-
-
 void dpp_auth_deinit(struct dpp_authentication *auth)
 {
 	unsigned int i;
@@ -4807,16 +1236,21 @@
 	dpp_configuration_free(auth->conf2_sta);
 	EVP_PKEY_free(auth->own_protocol_key);
 	EVP_PKEY_free(auth->peer_protocol_key);
+	EVP_PKEY_free(auth->reconfig_old_protocol_key);
 	wpabuf_free(auth->req_msg);
 	wpabuf_free(auth->resp_msg);
 	wpabuf_free(auth->conf_req);
+	wpabuf_free(auth->reconfig_req_msg);
+	wpabuf_free(auth->reconfig_resp_msg);
 	for (i = 0; i < auth->num_conf_obj; i++) {
 		struct dpp_config_obj *conf = &auth->conf_obj[i];
 
 		os_free(conf->connector);
 		wpabuf_free(conf->c_sign_key);
 	}
+#ifdef CONFIG_DPP2
 	dpp_free_asymmetric_key(auth->conf_key_pkg);
+#endif /* CONFIG_DPP2 */
 	wpabuf_free(auth->net_access_key);
 	dpp_bootstrap_info_free(auth->tmp_own_bi);
 #ifdef CONFIG_TESTING_OPTIONS
@@ -4876,8 +1310,8 @@
 }
 
 
-static int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
-			 const char *kid, const struct dpp_curve_params *curve)
+int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
+		  const char *kid, const struct dpp_curve_params *curve)
 {
 	struct wpabuf *pub;
 	const u8 *pos;
@@ -4948,20 +1382,10 @@
 		       struct dpp_configuration *conf)
 {
 	struct wpabuf *buf = NULL;
-	char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
+	char *signed_conn = NULL;
 	size_t tailroom;
 	const struct dpp_curve_params *curve;
-	struct wpabuf *jws_prot_hdr;
-	size_t signed1_len, signed2_len, signed3_len;
 	struct wpabuf *dppcon = NULL;
-	unsigned char *signature = NULL;
-	const unsigned char *p;
-	size_t signature_len;
-	EVP_MD_CTX *md_ctx = NULL;
-	ECDSA_SIG *sig = NULL;
-	char *dot = ".";
-	const EVP_MD *sign_md;
-	const BIGNUM *r, *s;
 	size_t extra_len = 1000;
 	int incl_legacy;
 	enum dpp_akm akm;
@@ -4973,16 +1397,6 @@
 		goto fail;
 	}
 	curve = auth->conf->curve;
-	if (curve->hash_len == SHA256_MAC_LEN) {
-		sign_md = EVP_sha256();
-	} else if (curve->hash_len == SHA384_MAC_LEN) {
-		sign_md = EVP_sha384();
-	} else if (curve->hash_len == SHA512_MAC_LEN) {
-		sign_md = EVP_sha512();
-	} else {
-		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
-		goto fail;
-	}
 
 	akm = conf->akm;
 	if (dpp_akm_ver2(akm) && auth->peer_version < 2) {
@@ -5030,7 +1444,8 @@
 #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;
@@ -5055,79 +1470,14 @@
 	wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
 		   (const char *) wpabuf_head(dppcon));
 
-	jws_prot_hdr = wpabuf_alloc(100);
-	if (!jws_prot_hdr)
-		goto fail;
-	json_start_object(jws_prot_hdr, NULL);
-	json_add_string(jws_prot_hdr, "typ", "dppCon");
-	json_value_sep(jws_prot_hdr);
-	json_add_string(jws_prot_hdr, "kid", auth->conf->kid);
-	json_value_sep(jws_prot_hdr);
-	json_add_string(jws_prot_hdr, "alg", curve->jws_alg);
-	json_end_object(jws_prot_hdr);
-	signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
-				    wpabuf_len(jws_prot_hdr),
-				    &signed1_len);
-	wpabuf_free(jws_prot_hdr);
-	signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
-				    &signed2_len);
-	if (!signed1 || !signed2)
-		goto fail;
-
-	md_ctx = EVP_MD_CTX_create();
-	if (!md_ctx)
-		goto fail;
-
-	ERR_clear_error();
-	if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL,
-			       auth->conf->csign) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 ||
-	    EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 ||
-	    EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	signature = os_malloc(signature_len);
-	if (!signature)
-		goto fail;
-	if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)",
-		    signature, signature_len);
-	/* Convert to raw coordinates r,s */
-	p = signature;
-	sig = d2i_ECDSA_SIG(NULL, &p, signature_len);
-	if (!sig)
-		goto fail;
-	ECDSA_SIG_get0(sig, &r, &s);
-	if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(s, signature + curve->prime_len,
-			   curve->prime_len) < 0)
-		goto fail;
-	signature_len = 2 * curve->prime_len;
-	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
-		    signature, signature_len);
-	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
-	if (!signed3)
+	signed_conn = dpp_sign_connector(auth->conf, dppcon);
+	if (!signed_conn)
 		goto fail;
 
 	incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm);
 	tailroom = 1000;
 	tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
-	tailroom += signed1_len + signed2_len + signed3_len;
+	tailroom += os_strlen(signed_conn);
 	if (incl_legacy)
 		tailroom += 1000;
 	buf = dpp_build_conf_start(auth, conf, tailroom);
@@ -5146,11 +1496,7 @@
 		json_value_sep(buf);
 	}
 	wpabuf_put_str(buf, "\"signedConnector\":\"");
-	wpabuf_put_str(buf, signed1);
-	wpabuf_put_u8(buf, '.');
-	wpabuf_put_str(buf, signed2);
-	wpabuf_put_u8(buf, '.');
-	wpabuf_put_str(buf, signed3);
+	wpabuf_put_str(buf, signed_conn);
 	wpabuf_put_str(buf, "\"");
 	json_value_sep(buf);
 	if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
@@ -5166,12 +1512,7 @@
 			      wpabuf_head(buf), wpabuf_len(buf));
 
 out:
-	EVP_MD_CTX_destroy(md_ctx);
-	ECDSA_SIG_free(sig);
-	os_free(signed1);
-	os_free(signed2);
-	os_free(signed3);
-	os_free(signature);
+	os_free(signed_conn);
 	wpabuf_free(dppcon);
 	return buf;
 fail:
@@ -5252,488 +1593,6 @@
 }
 
 
-#ifdef CONFIG_DPP2
-
-static struct wpabuf * dpp_build_conf_params(void)
-{
-	struct wpabuf *buf;
-	size_t len;
-	/* TODO: proper template values */
-	const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}";
-	const char *connector_template = NULL;
-
-	len = 100 + os_strlen(conf_template);
-	if (connector_template)
-		len += os_strlen(connector_template);
-	buf = wpabuf_alloc(len);
-	if (!buf)
-		return NULL;
-
-	/*
-	 * DPPConfigurationParameters ::= SEQUENCE {
-	 *    configurationTemplate	UTF8String,
-	 *    connectorTemplate		UTF8String OPTIONAL}
-	 */
-
-	asn1_put_utf8string(buf, conf_template);
-	if (connector_template)
-		asn1_put_utf8string(buf, connector_template);
-	return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
-}
-
-
-static struct wpabuf * dpp_build_attribute(void)
-{
-	struct wpabuf *conf_params, *attr;
-
-	/*
-	 * aa-DPPConfigurationParameters ATTRIBUTE ::=
-	 * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams }
-	 *
-	 * Attribute ::= SEQUENCE {
-	 *    type OBJECT IDENTIFIER,
-	 *    values SET SIZE(1..MAX) OF Type
-	 */
-	conf_params = dpp_build_conf_params();
-	conf_params = asn1_encaps(conf_params, ASN1_CLASS_UNIVERSAL,
-				  ASN1_TAG_SET);
-	if (!conf_params)
-		return NULL;
-
-	attr = wpabuf_alloc(100 + wpabuf_len(conf_params));
-	if (!attr) {
-		wpabuf_clear_free(conf_params);
-		return NULL;
-	}
-
-	asn1_put_oid(attr, &asn1_dpp_config_params_oid);
-	wpabuf_put_buf(attr, conf_params);
-	wpabuf_clear_free(conf_params);
-
-	return asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
-}
-
-
-static struct wpabuf * dpp_build_key_alg(const struct dpp_curve_params *curve)
-{
-	const struct asn1_oid *oid;
-	struct wpabuf *params, *res;
-
-	switch (curve->ike_group) {
-	case 19:
-		oid = &asn1_prime256v1_oid;
-		break;
-	case 20:
-		oid = &asn1_secp384r1_oid;
-		break;
-	case 21:
-		oid = &asn1_secp521r1_oid;
-		break;
-	case 28:
-		oid = &asn1_brainpoolP256r1_oid;
-		break;
-	case 29:
-		oid = &asn1_brainpoolP384r1_oid;
-		break;
-	case 30:
-		oid = &asn1_brainpoolP512r1_oid;
-		break;
-	default:
-		return NULL;
-	}
-
-	params = wpabuf_alloc(20);
-	if (!params)
-		return NULL;
-	asn1_put_oid(params, oid); /* namedCurve */
-
-	res = asn1_build_alg_id(&asn1_ec_public_key_oid, params);
-	wpabuf_free(params);
-	return res;
-}
-
-
-static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth)
-{
-	struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL;
-	EC_KEY *eckey;
-	unsigned char *der = NULL;
-	int der_len;
-
-	eckey = EVP_PKEY_get0_EC_KEY(auth->conf->csign);
-	if (!eckey)
-		return NULL;
-
-	EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
-	der_len = i2d_ECPrivateKey(eckey, &der);
-	if (der_len > 0)
-		priv_key = wpabuf_alloc_copy(der, der_len);
-	OPENSSL_free(der);
-
-	alg = dpp_build_key_alg(auth->conf->curve);
-
-	/* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */
-	attr = dpp_build_attribute();
-	attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET);
-	if (!priv_key || !attr || !alg)
-		goto fail;
-
-	/*
-	 * OneAsymmetricKey ::= SEQUENCE {
-	 *    version			Version,
-	 *    privateKeyAlgorithm	PrivateKeyAlgorithmIdentifier,
-	 *    privateKey		PrivateKey,
-	 *    attributes		[0] Attributes OPTIONAL,
-	 *    ...,
-	 *    [[2: publicKey		[1] BIT STRING OPTIONAL ]],
-	 *    ...
-	 * }
-	 */
-
-	key = wpabuf_alloc(100 + wpabuf_len(alg) + wpabuf_len(priv_key) +
-			   wpabuf_len(attr));
-	if (!key)
-		goto fail;
-
-	asn1_put_integer(key, 1); /* version = v2(1) */
-
-	/* PrivateKeyAlgorithmIdentifier */
-	wpabuf_put_buf(key, alg);
-
-	/* PrivateKey ::= OCTET STRING */
-	asn1_put_octet_string(key, priv_key);
-
-	/* [0] Attributes OPTIONAL */
-	asn1_put_hdr(key, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, wpabuf_len(attr));
-	wpabuf_put_buf(key, attr);
-
-fail:
-	wpabuf_clear_free(attr);
-	wpabuf_clear_free(priv_key);
-	wpabuf_free(alg);
-
-	/*
-	 * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage
-	 *
-	 * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey
-	 *
-	 * OneAsymmetricKey ::= SEQUENCE
-	 */
-	return asn1_encaps(asn1_encaps(key,
-				       ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE),
-			   ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
-}
-
-
-static struct wpabuf * dpp_build_pbkdf2_alg_id(const struct wpabuf *salt,
-					       size_t hash_len)
-{
-	struct wpabuf *params = NULL, *buf = NULL, *prf = NULL;
-	const struct asn1_oid *oid;
-
-	/*
-	 * PBKDF2-params ::= SEQUENCE {
-	 *    salt CHOICE {
-	 *       specified OCTET STRING,
-	 *       otherSource AlgorithmIdentifier}
-	 *    iterationCount INTEGER (1..MAX),
-	 *    keyLength INTEGER (1..MAX),
-	 *    prf AlgorithmIdentifier}
-	 *
-	 * salt is an 64 octet value, iterationCount is 1000, keyLength is based
-	 * on Configurator signing key length, prf is
-	 * id-hmacWithSHA{256,384,512} based on Configurator signing key.
-	 */
-
-	if (hash_len == 32)
-		oid = &asn1_pbkdf2_hmac_sha256_oid;
-	else if (hash_len == 48)
-		oid = &asn1_pbkdf2_hmac_sha384_oid;
-	else if (hash_len == 64)
-		oid = &asn1_pbkdf2_hmac_sha512_oid;
-	else
-		goto fail;
-	prf = asn1_build_alg_id(oid, NULL);
-	if (!prf)
-		goto fail;
-	params = wpabuf_alloc(100 + wpabuf_len(salt) + wpabuf_len(prf));
-	if (!params)
-		goto fail;
-	asn1_put_octet_string(params, salt); /* salt.specified */
-	asn1_put_integer(params, 1000); /* iterationCount */
-	asn1_put_integer(params, hash_len); /* keyLength */
-	wpabuf_put_buf(params, prf);
-	params = asn1_encaps(params, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
-	if (!params)
-		goto fail;
-	buf = asn1_build_alg_id(&asn1_pbkdf2_oid, params);
-fail:
-	wpabuf_free(params);
-	wpabuf_free(prf);
-	return buf;
-}
-
-
-static struct wpabuf *
-dpp_build_pw_recipient_info(struct dpp_authentication *auth, size_t hash_len,
-			    const struct wpabuf *cont_enc_key)
-{
-	struct wpabuf *pwri = NULL, *enc_key = NULL, *key_der_alg = NULL,
-		*key_enc_alg = NULL, *salt;
-	u8 kek[DPP_MAX_HASH_LEN];
-	const u8 *key;
-	size_t key_len;
-
-	salt = wpabuf_alloc(64);
-	if (!salt || os_get_random(wpabuf_put(salt, 64), 64) < 0)
-		goto fail;
-	wpa_hexdump_buf(MSG_DEBUG, "DPP: PBKDF2 salt", salt);
-
-	/* TODO: For initial testing, use ke as the key. Replace this with a
-	 * new key once that has been defined. */
-	key = auth->ke;
-	key_len = auth->curve->hash_len;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len);
-
-	if (dpp_pbkdf2(hash_len, key, key_len, wpabuf_head(salt), 64, 1000,
-		       kek, hash_len)) {
-		wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed");
-		goto fail;
-	}
-	wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2",
-			kek, hash_len);
-
-	enc_key = wpabuf_alloc(hash_len + AES_BLOCK_SIZE);
-	if (!enc_key ||
-	    aes_siv_encrypt(kek, hash_len, wpabuf_head(cont_enc_key),
-			    wpabuf_len(cont_enc_key), 0, NULL, NULL,
-			    wpabuf_put(enc_key, hash_len + AES_BLOCK_SIZE)) < 0)
-		goto fail;
-	wpa_hexdump_buf(MSG_DEBUG, "DPP: encryptedKey", enc_key);
-
-	/*
-	 * PasswordRecipientInfo ::= SEQUENCE {
-	 *    version			CMSVersion,
-	 *    keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL,
-	 *    keyEncryptionAlgorithm	KeyEncryptionAlgorithmIdentifier,
-	 *    encryptedKey		EncryptedKey}
-	 *
-	 * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the
-	 * parameters contains PBKDF2-params SEQUENCE.
-	 */
-
-	key_der_alg = dpp_build_pbkdf2_alg_id(salt, hash_len);
-	key_enc_alg = asn1_build_alg_id(&asn1_aes_siv_cmac_aead_256_oid, NULL);
-	if (!key_der_alg || !key_enc_alg)
-		goto fail;
-	pwri = wpabuf_alloc(100 + wpabuf_len(key_der_alg) +
-			    wpabuf_len(key_enc_alg) + wpabuf_len(enc_key));
-	if (!pwri)
-		goto fail;
-
-	/* version = 0 */
-	asn1_put_integer(pwri, 0);
-
-	/* [0] KeyDerivationAlgorithmIdentifier */
-	asn1_put_hdr(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0,
-		     wpabuf_len(key_der_alg));
-	wpabuf_put_buf(pwri, key_der_alg);
-
-	/* KeyEncryptionAlgorithmIdentifier */
-	wpabuf_put_buf(pwri, key_enc_alg);
-
-	/* EncryptedKey ::= OCTET STRING */
-	asn1_put_octet_string(pwri, enc_key);
-
-fail:
-	wpabuf_clear_free(key_der_alg);
-	wpabuf_free(key_enc_alg);
-	wpabuf_free(enc_key);
-	wpabuf_free(salt);
-	forced_memzero(kek, sizeof(kek));
-	return asn1_encaps(pwri, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
-}
-
-
-static struct wpabuf *
-dpp_build_recipient_info(struct dpp_authentication *auth, size_t hash_len,
-			 const struct wpabuf *cont_enc_key)
-{
-	struct wpabuf *pwri;
-
-	/*
-	 * RecipientInfo ::= CHOICE {
-	 *    ktri		KeyTransRecipientInfo,
-	 *    kari	[1]	KeyAgreeRecipientInfo,
-	 *    kekri	[2]	KEKRecipientInfo,
-	 *    pwri	[3]	PasswordRecipientInfo,
-	 *    ori	[4]	OtherRecipientInfo}
-	 *
-	 * Shall always use the pwri CHOICE.
-	 */
-
-	pwri = dpp_build_pw_recipient_info(auth, hash_len, cont_enc_key);
-	return asn1_encaps(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 3);
-}
-
-
-static struct wpabuf *
-dpp_build_enc_cont_info(struct dpp_authentication *auth, size_t hash_len,
-			const struct wpabuf *cont_enc_key)
-{
-	struct wpabuf *key_pkg, *enc_cont_info = NULL, *enc_cont = NULL,
-		*enc_alg;
-	const struct asn1_oid *oid;
-	size_t enc_cont_len;
-
-	/*
-	 * EncryptedContentInfo ::= SEQUENCE {
-	 *    contentType			ContentType,
-	 *    contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
-	 *    encryptedContent	[0] IMPLICIT	EncryptedContent OPTIONAL}
-	 */
-
-	if (hash_len == 32)
-		oid = &asn1_aes_siv_cmac_aead_256_oid;
-	else if (hash_len == 48)
-		oid = &asn1_aes_siv_cmac_aead_384_oid;
-	else if (hash_len == 64)
-		oid = &asn1_aes_siv_cmac_aead_512_oid;
-	else
-		return NULL;
-
-	key_pkg = dpp_build_key_pkg(auth);
-	enc_alg = asn1_build_alg_id(oid, NULL);
-	if (!key_pkg || !enc_alg)
-		goto fail;
-
-	wpa_hexdump_buf_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage",
-			    key_pkg);
-
-	enc_cont_len = wpabuf_len(key_pkg) + AES_BLOCK_SIZE;
-	enc_cont = wpabuf_alloc(enc_cont_len);
-	if (!enc_cont ||
-	    aes_siv_encrypt(wpabuf_head(cont_enc_key), wpabuf_len(cont_enc_key),
-			    wpabuf_head(key_pkg), wpabuf_len(key_pkg),
-			    0, NULL, NULL,
-			    wpabuf_put(enc_cont, enc_cont_len)) < 0)
-		goto fail;
-
-	enc_cont_info = wpabuf_alloc(100 + wpabuf_len(enc_alg) +
-				     wpabuf_len(enc_cont));
-	if (!enc_cont_info)
-		goto fail;
-
-	/* ContentType ::= OBJECT IDENTIFIER */
-	asn1_put_oid(enc_cont_info, &asn1_dpp_asymmetric_key_package_oid);
-
-	/* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
-	wpabuf_put_buf(enc_cont_info, enc_alg);
-
-	/* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
-	 * EncryptedContent ::= OCTET STRING */
-	asn1_put_hdr(enc_cont_info, ASN1_CLASS_CONTEXT_SPECIFIC, 0, 0,
-		     wpabuf_len(enc_cont));
-	wpabuf_put_buf(enc_cont_info, enc_cont);
-
-fail:
-	wpabuf_clear_free(key_pkg);
-	wpabuf_free(enc_cont);
-	wpabuf_free(enc_alg);
-	return enc_cont_info;
-}
-
-
-static struct wpabuf * dpp_gen_random(size_t len)
-{
-	struct wpabuf *key;
-
-	key = wpabuf_alloc(len);
-	if (!key || os_get_random(wpabuf_put(key, len), len) < 0) {
-		wpabuf_free(key);
-		key = NULL;
-	}
-	wpa_hexdump_buf_key(MSG_DEBUG, "DPP: content-encryption key", key);
-	return key;
-}
-
-
-static struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth)
-{
-	struct wpabuf *env = NULL;
-	struct wpabuf *recipient_info = NULL, *enc_cont_info = NULL;
-	struct wpabuf *cont_enc_key = NULL;
-	size_t hash_len;
-
-	if (!auth->conf) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No Configurator instance selected for the session - cannot build DPPEnvelopedData");
-		return NULL;
-	}
-
-	if (!auth->provision_configurator) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Configurator provisioning not allowed");
-		return NULL;
-	}
-
-	wpa_printf(MSG_DEBUG, "DPP: Building DPPEnvelopedData");
-
-	hash_len = auth->conf->curve->hash_len;
-	cont_enc_key = dpp_gen_random(hash_len);
-	if (!cont_enc_key)
-		goto fail;
-	recipient_info = dpp_build_recipient_info(auth, hash_len, cont_enc_key);
-	enc_cont_info = dpp_build_enc_cont_info(auth, hash_len, cont_enc_key);
-	if (!recipient_info || !enc_cont_info)
-		goto fail;
-
-	env = wpabuf_alloc(wpabuf_len(recipient_info) +
-			   wpabuf_len(enc_cont_info) +
-			   100);
-	if (!env)
-		goto fail;
-
-	/*
-	 * DPPEnvelopedData ::= EnvelopedData
-	 *
-	 * EnvelopedData ::= SEQUENCE {
-	 *    version			CMSVersion,
-	 *    originatorInfo	[0]	IMPLICIT OriginatorInfo OPTIONAL,
-	 *    recipientInfos		RecipientInfos,
-	 *    encryptedContentInfo	EncryptedContentInfo,
-	 *    unprotectedAttrs  [1] IMPLICIT	UnprotectedAttributes OPTIONAL}
-	 *
-	 * For DPP, version is 3, both originatorInfo and
-	 * unprotectedAttrs are omitted, and recipientInfos contains a single
-	 * RecipientInfo.
-	 */
-
-	/* EnvelopedData.version = 3 */
-	asn1_put_integer(env, 3);
-
-	/* RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo */
-	asn1_put_set(env, recipient_info);
-
-	/* EncryptedContentInfo ::= SEQUENCE */
-	asn1_put_sequence(env, enc_cont_info);
-
-	env = asn1_encaps(env, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
-	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: DPPEnvelopedData", env);
-out:
-	wpabuf_clear_free(cont_enc_key);
-	wpabuf_clear_free(recipient_info);
-	wpabuf_free(enc_cont_info);
-	return env;
-fail:
-	wpabuf_free(env);
-	env = NULL;
-	goto out;
-}
-
-#endif /* CONFIG_DPP2 */
-
-
 static struct wpabuf *
 dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
 		    u16 e_nonce_len, enum dpp_netrole netrole)
@@ -6022,12 +1881,19 @@
 	}
 
 	token = json_get_member(root, "mudurl");
-	if (token && token->type == JSON_STRING)
+	if (token && token->type == JSON_STRING) {
 		wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string);
+		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s",
+			token->string);
+	}
 
 	token = json_get_member(root, "bandSupport");
 	auth->band_list_size = 0;
 	if (token && token->type == JSON_ARRAY) {
+		int *opclass = NULL;
+		char txt[200], *pos, *end;
+		int i, res;
+
 		memset(auth->band_list, 0, sizeof(auth->band_list));
 		wpa_printf(MSG_DEBUG, "DPP: bandSupport");
 		token = token->child;
@@ -6042,9 +1908,26 @@
 				wpa_printf(MSG_DEBUG,
 					   "DPP: Supported global operating class: %d",
 					   token->number);
+				int_array_add_unique(&opclass, token->number);
 			}
 			token = token->sibling;
 		}
+
+		txt[0] = '\0';
+		pos = txt;
+		end = txt + sizeof(txt);
+		for (i = 0; opclass && opclass[i]; i++) {
+			res = os_snprintf(pos, end - pos, "%s%d",
+					  pos == txt ? "" : ",", opclass[i]);
+			if (os_snprintf_error(end - pos, res)) {
+				*pos = '\0';
+				break;
+			}
+			pos += res;
+		}
+		os_free(opclass);
+		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s",
+			txt);
 	}
 
 	resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole);
@@ -6056,86 +1939,6 @@
 }
 
 
-static struct wpabuf *
-dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
-		       const u8 *prot_hdr, u16 prot_hdr_len,
-		       const EVP_MD **ret_md)
-{
-	struct json_token *root, *token;
-	struct wpabuf *kid = NULL;
-
-	root = json_parse((const char *) prot_hdr, prot_hdr_len);
-	if (!root) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: JSON parsing failed for JWS Protected Header");
-		goto fail;
-	}
-
-	if (root->type != JSON_OBJECT) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: JWS Protected Header root is not an object");
-		goto fail;
-	}
-
-	token = json_get_member(root, "typ");
-	if (!token || token->type != JSON_STRING) {
-		wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
-		goto fail;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
-		   token->string);
-	if (os_strcmp(token->string, "dppCon") != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported JWS Protected Header typ=%s",
-			   token->string);
-		goto fail;
-	}
-
-	token = json_get_member(root, "alg");
-	if (!token || token->type != JSON_STRING) {
-		wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
-		goto fail;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
-		   token->string);
-	if (os_strcmp(token->string, curve->jws_alg) != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
-			   token->string, curve->jws_alg);
-		goto fail;
-	}
-	if (os_strcmp(token->string, "ES256") == 0 ||
-	    os_strcmp(token->string, "BS256") == 0)
-		*ret_md = EVP_sha256();
-	else if (os_strcmp(token->string, "ES384") == 0 ||
-		 os_strcmp(token->string, "BS384") == 0)
-		*ret_md = EVP_sha384();
-	else if (os_strcmp(token->string, "ES512") == 0 ||
-		 os_strcmp(token->string, "BS512") == 0)
-		*ret_md = EVP_sha512();
-	else
-		*ret_md = NULL;
-	if (!*ret_md) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported JWS Protected Header alg=%s",
-			   token->string);
-		goto fail;
-	}
-
-	kid = json_get_member_base64url(root, "kid");
-	if (!kid) {
-		wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
-		goto fail;
-	}
-	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
-			kid);
-
-fail:
-	json_free(root);
-	return kid;
-}
-
-
 static int dpp_parse_cred_legacy(struct dpp_config_obj *conf,
 				 struct json_token *cred)
 {
@@ -6183,8 +1986,8 @@
 }
 
 
-static EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
-				const struct dpp_curve_params **key_curve)
+EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
+			 const struct dpp_curve_params **key_curve)
 {
 	struct json_token *token;
 	const struct dpp_curve_params *curve;
@@ -6438,38 +2241,6 @@
 }
 
 
-static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash)
-{
-	struct wpabuf *uncomp;
-	int res;
-	u8 hash[SHA256_MAC_LEN];
-	const u8 *addr[1];
-	size_t len[1];
-
-	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
-		return -1;
-	uncomp = dpp_get_pubkey_point(pub, 1);
-	if (!uncomp)
-		return -1;
-	addr[0] = wpabuf_head(uncomp);
-	len[0] = wpabuf_len(uncomp);
-	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
-		    addr[0], len[0]);
-	res = sha256_vector(1, addr, len, hash);
-	wpabuf_free(uncomp);
-	if (res < 0)
-		return -1;
-	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Received hash value does not match calculated public key hash value");
-		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
-			    hash, SHA256_MAC_LEN);
-		return -1;
-	}
-	return 0;
-}
-
-
 static void dpp_copy_csign(struct dpp_config_obj *conf, EVP_PKEY *csign)
 {
 	unsigned char *der = NULL;
@@ -6490,8 +2261,15 @@
 	unsigned char *der = NULL;
 	int der_len;
 	EC_KEY *eckey;
+	EVP_PKEY *own_key;
 
-	eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
+	own_key = auth->own_protocol_key;
+#ifdef CONFIG_DPP2
+	if (auth->reconfig_connector_key == DPP_CONFIG_REUSEKEY &&
+	    auth->reconfig_old_protocol_key)
+		own_key = auth->reconfig_old_protocol_key;
+#endif /* CONFIG_DPP2 */
+	eckey = EVP_PKEY_get1_EC_KEY(own_key);
 	if (!eckey)
 		return;
 
@@ -6507,174 +2285,6 @@
 }
 
 
-struct dpp_signed_connector_info {
-	unsigned char *payload;
-	size_t payload_len;
-};
-
-static enum dpp_status_error
-dpp_process_signed_connector(struct dpp_signed_connector_info *info,
-			     EVP_PKEY *csign_pub, const char *connector)
-{
-	enum dpp_status_error ret = 255;
-	const char *pos, *end, *signed_start, *signed_end;
-	struct wpabuf *kid = NULL;
-	unsigned char *prot_hdr = NULL, *signature = NULL;
-	size_t prot_hdr_len = 0, signature_len = 0;
-	const EVP_MD *sign_md = NULL;
-	unsigned char *der = NULL;
-	int der_len;
-	int res;
-	EVP_MD_CTX *md_ctx = NULL;
-	ECDSA_SIG *sig = NULL;
-	BIGNUM *r = NULL, *s = NULL;
-	const struct dpp_curve_params *curve;
-	EC_KEY *eckey;
-	const EC_GROUP *group;
-	int nid;
-
-	eckey = EVP_PKEY_get1_EC_KEY(csign_pub);
-	if (!eckey)
-		goto fail;
-	group = EC_KEY_get0_group(eckey);
-	if (!group)
-		goto fail;
-	nid = EC_GROUP_get_curve_name(group);
-	curve = dpp_get_curve_nid(nid);
-	if (!curve)
-		goto fail;
-	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
-	os_memset(info, 0, sizeof(*info));
-
-	signed_start = pos = connector;
-	end = os_strchr(pos, '.');
-	if (!end) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-	}
-	prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
-	if (!prot_hdr) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-	}
-	wpa_hexdump_ascii(MSG_DEBUG,
-			  "DPP: signedConnector - JWS Protected Header",
-			  prot_hdr, prot_hdr_len);
-	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md);
-	if (!kid) {
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-	}
-	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
-			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-	}
-
-	pos = end + 1;
-	end = os_strchr(pos, '.');
-	if (!end) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing dot(2) in signedConnector");
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-	}
-	signed_end = end - 1;
-	info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
-	if (!info->payload) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Failed to base64url decode signedConnector JWS Payload");
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-	}
-	wpa_hexdump_ascii(MSG_DEBUG,
-			  "DPP: signedConnector - JWS Payload",
-			  info->payload, info->payload_len);
-	pos = end + 1;
-	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
-	if (!signature) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Failed to base64url decode signedConnector signature");
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-		}
-	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
-		    signature, signature_len);
-
-	if (dpp_check_pubkey_match(csign_pub, kid) < 0) {
-		ret = DPP_STATUS_NO_MATCH;
-		goto fail;
-	}
-
-	if (signature_len & 0x01) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unexpected signedConnector signature length (%d)",
-			   (int) signature_len);
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-	}
-
-	/* JWS Signature encodes the signature (r,s) as two octet strings. Need
-	 * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
-	r = BN_bin2bn(signature, signature_len / 2, NULL);
-	s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL);
-	sig = ECDSA_SIG_new();
-	if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1)
-		goto fail;
-	r = NULL;
-	s = NULL;
-
-	der_len = i2d_ECDSA_SIG(sig, &der);
-	if (der_len <= 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature");
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len);
-	md_ctx = EVP_MD_CTX_create();
-	if (!md_ctx)
-		goto fail;
-
-	ERR_clear_error();
-	if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	if (EVP_DigestVerifyUpdate(md_ctx, signed_start,
-				   signed_end - signed_start + 1) != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	res = EVP_DigestVerifyFinal(md_ctx, der, der_len);
-	if (res != 1) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: EVP_DigestVerifyFinal failed (res=%d): %s",
-			   res, ERR_error_string(ERR_get_error(), NULL));
-		ret = DPP_STATUS_INVALID_CONNECTOR;
-		goto fail;
-	}
-
-	ret = DPP_STATUS_OK;
-fail:
-	EC_KEY_free(eckey);
-	EVP_MD_CTX_destroy(md_ctx);
-	os_free(prot_hdr);
-	wpabuf_free(kid);
-	os_free(signature);
-	ECDSA_SIG_free(sig);
-	BN_free(r);
-	BN_free(s);
-	OPENSSL_free(der);
-	return ret;
-}
-
-
 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
 			      struct dpp_config_obj *conf,
 			      struct json_token *cred)
@@ -6974,709 +2584,6 @@
 }
 
 
-#ifdef CONFIG_DPP2
-
-struct dpp_enveloped_data {
-	const u8 *enc_cont;
-	size_t enc_cont_len;
-	const u8 *enc_key;
-	size_t enc_key_len;
-	const u8 *salt;
-	size_t pbkdf2_key_len;
-	size_t prf_hash_len;
-};
-
-
-static int dpp_parse_recipient_infos(const u8 *pos, size_t len,
-				     struct dpp_enveloped_data *data)
-{
-	struct asn1_hdr hdr;
-	const u8 *end = pos + len;
-	const u8 *next, *e_end;
-	struct asn1_oid oid;
-	int val;
-	const u8 *params;
-	size_t params_len;
-
-	wpa_hexdump(MSG_MSGDUMP, "DPP: RecipientInfos", pos, len);
-
-	/*
-	 * RecipientInfo ::= CHOICE {
-	 *    ktri		KeyTransRecipientInfo,
-	 *    kari	[1]	KeyAgreeRecipientInfo,
-	 *    kekri	[2]	KEKRecipientInfo,
-	 *    pwri	[3]	PasswordRecipientInfo,
-	 *    ori	[4]	OtherRecipientInfo}
-	 *
-	 * Shall always use the pwri CHOICE.
-	 */
-
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 3) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected CHOICE [3] (pwri) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		return -1;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo",
-		    hdr.payload, hdr.length);
-	pos = hdr.payload;
-	end = pos + hdr.length;
-
-	/*
-	 * PasswordRecipientInfo ::= SEQUENCE {
-	 *    version			CMSVersion,
-	 *    keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL,
-	 *    keyEncryptionAlgorithm	KeyEncryptionAlgorithmIdentifier,
-	 *    encryptedKey		EncryptedKey}
-	 *
-	 * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the
-	 * parameters contains PBKDF2-params SEQUENCE.
-	 */
-
-	if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0)
-		return -1;
-	pos = hdr.payload;
-
-	if (asn1_get_integer(pos, end - pos, &val, &pos) < 0)
-		return -1;
-	if (val != 0) {
-		wpa_printf(MSG_DEBUG, "DPP: pwri.version != 0");
-		return -1;
-	}
-
-	wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version",
-		    pos, end - pos);
-
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected keyDerivationAlgorithm [0] - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		return -1;
-	}
-	pos = hdr.payload;
-	e_end = pos + hdr.length;
-
-	/* KeyDerivationAlgorithmIdentifier ::= AlgorithmIdentifier */
-	if (asn1_get_alg_id(pos, e_end - pos, &oid, &params, &params_len,
-			    &next) < 0)
-		return -1;
-	if (!asn1_oid_equal(&oid, &asn1_pbkdf2_oid)) {
-		char buf[80];
-
-		asn1_oid_to_str(&oid, buf, sizeof(buf));
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unexpected KeyDerivationAlgorithmIdentifier %s",
-			   buf);
-		return -1;
-	}
-
-	/*
-	 * PBKDF2-params ::= SEQUENCE {
-	 *    salt CHOICE {
-	 *       specified OCTET STRING,
-	 *       otherSource AlgorithmIdentifier}
-	 *    iterationCount INTEGER (1..MAX),
-	 *    keyLength INTEGER (1..MAX),
-	 *    prf AlgorithmIdentifier}
-	 *
-	 * salt is an 64 octet value, iterationCount is 1000, keyLength is based
-	 * on Configurator signing key length, prf is
-	 * id-hmacWithSHA{256,384,512} based on Configurator signing key.
-	 */
-	if (!params ||
-	    asn1_get_sequence(params, params_len, &hdr, &e_end) < 0)
-		return -1;
-	pos = hdr.payload;
-
-	if (asn1_get_next(pos, e_end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected OCTETSTRING (salt.specified) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		return -1;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified",
-		    hdr.payload, hdr.length);
-	if (hdr.length != 64) {
-		wpa_printf(MSG_DEBUG, "DPP: Unexpected salt length %u",
-			   hdr.length);
-		return -1;
-	}
-	data->salt = hdr.payload;
-	pos = hdr.payload + hdr.length;
-
-	if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0)
-		return -1;
-	if (val != 1000) {
-		wpa_printf(MSG_DEBUG, "DPP: Unexpected iterationCount %d", val);
-		return -1;
-	}
-
-	if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0)
-		return -1;
-	if (val != 32 && val != 48 && val != 64) {
-		wpa_printf(MSG_DEBUG, "DPP: Unexpected keyLength %d", val);
-		return -1;
-	}
-	data->pbkdf2_key_len = val;
-
-	if (asn1_get_sequence(pos, e_end - pos, &hdr, NULL) < 0 ||
-	    asn1_get_oid(hdr.payload, hdr.length, &oid, &pos) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Could not parse prf");
-		return -1;
-	}
-	if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha256_oid)) {
-		data->prf_hash_len = 32;
-	} else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha384_oid)) {
-		data->prf_hash_len = 48;
-	} else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha512_oid)) {
-		data->prf_hash_len = 64;
-	} else {
-		char buf[80];
-
-		asn1_oid_to_str(&oid, buf, sizeof(buf));
-		wpa_printf(MSG_DEBUG, "DPP: Unexpected PBKDF2-params.prf %s",
-			   buf);
-		return -1;
-	}
-
-	pos = next;
-
-	/* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier
-	 *
-	 * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
-	 *
-	 * id-alg-AES-SIV-CMAC-aed-256, id-alg-AES-SIV-CMAC-aed-384, or
-	 * id-alg-AES-SIV-CMAC-aed-512. */
-	if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0)
-		return -1;
-	if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) &&
-	    !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) &&
-	    !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) {
-		char buf[80];
-
-		asn1_oid_to_str(&oid, buf, sizeof(buf));
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unexpected KeyEncryptionAlgorithmIdentifier %s",
-			   buf);
-		return -1;
-	}
-
-	/*
-	 * encryptedKey EncryptedKey
-	 *
-	 * EncryptedKey ::= OCTET STRING
-	 */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected OCTETSTRING (pwri.encryptedKey) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		return -1;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey",
-		    hdr.payload, hdr.length);
-	data->enc_key = hdr.payload;
-	data->enc_key_len = hdr.length;
-
-	return 0;
-}
-
-
-static int dpp_parse_encrypted_content_info(const u8 *pos, const u8 *end,
-					    struct dpp_enveloped_data *data)
-{
-	struct asn1_hdr hdr;
-	struct asn1_oid oid;
-
-	/*
-	 * EncryptedContentInfo ::= SEQUENCE {
-	 *    contentType			ContentType,
-	 *    contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
-	 *    encryptedContent	[0] IMPLICIT	EncryptedContent OPTIONAL}
-	 */
-	if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0)
-		return -1;
-	wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContentInfo",
-		    hdr.payload, hdr.length);
-	if (pos < end) {
-		wpa_hexdump(MSG_DEBUG,
-			    "DPP: Unexpected extra data after EncryptedContentInfo",
-			    pos, end - pos);
-		return -1;
-	}
-
-	end = pos;
-	pos = hdr.payload;
-
-	/* ContentType ::= OBJECT IDENTIFIER */
-	if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Could not parse ContentType");
-		return -1;
-	}
-	if (!asn1_oid_equal(&oid, &asn1_dpp_asymmetric_key_package_oid)) {
-		char buf[80];
-
-		asn1_oid_to_str(&oid, buf, sizeof(buf));
-		wpa_printf(MSG_DEBUG, "DPP: Unexpected ContentType %s", buf);
-		return -1;
-	}
-
-	/* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
-	if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0)
-		return -1;
-	if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) &&
-	    !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) &&
-	    !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) {
-		char buf[80];
-
-		asn1_oid_to_str(&oid, buf, sizeof(buf));
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unexpected ContentEncryptionAlgorithmIdentifier %s",
-			   buf);
-		return -1;
-	}
-	/* ignore optional parameters */
-
-	/* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
-	 * EncryptedContent ::= OCTET STRING */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected [0] IMPLICIT (EncryptedContent) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		return -1;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent",
-		    hdr.payload, hdr.length);
-	data->enc_cont = hdr.payload;
-	data->enc_cont_len = hdr.length;
-	return 0;
-}
-
-
-static int dpp_parse_enveloped_data(const u8 *env_data, size_t env_data_len,
-				    struct dpp_enveloped_data *data)
-{
-	struct asn1_hdr hdr;
-	const u8 *pos, *end;
-	int val;
-
-	os_memset(data, 0, sizeof(*data));
-
-	/*
-	 * DPPEnvelopedData ::= EnvelopedData
-	 *
-	 * EnvelopedData ::= SEQUENCE {
-	 *    version			CMSVersion,
-	 *    originatorInfo	[0]	IMPLICIT OriginatorInfo OPTIONAL,
-	 *    recipientInfos		RecipientInfos,
-	 *    encryptedContentInfo	EncryptedContentInfo,
-	 *    unprotectedAttrs  [1] IMPLICIT	UnprotectedAttributes OPTIONAL}
-	 *
-	 * CMSVersion ::= INTEGER
-	 *
-	 * RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo
-	 *
-	 * For DPP, version is 3, both originatorInfo and
-	 * unprotectedAttrs are omitted, and recipientInfos contains a single
-	 * RecipientInfo.
-	 */
-	if (asn1_get_sequence(env_data, env_data_len, &hdr, &end) < 0)
-		return -1;
-	pos = hdr.payload;
-	if (end < env_data + env_data_len) {
-		wpa_hexdump(MSG_DEBUG,
-			    "DPP: Unexpected extra data after DPPEnvelopedData",
-			    end, env_data + env_data_len - end);
-		return -1;
-	}
-
-	if (asn1_get_integer(pos, end - pos, &val, &pos) < 0)
-		return -1;
-	if (val != 3) {
-		wpa_printf(MSG_DEBUG, "DPP: EnvelopedData.version != 3");
-		return -1;
-	}
-
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected SET (RecipientInfos) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		return -1;
-	}
-
-	if (dpp_parse_recipient_infos(hdr.payload, hdr.length, data) < 0)
-		return -1;
-	return dpp_parse_encrypted_content_info(hdr.payload + hdr.length, end,
-						data);
-}
-
-
-static struct dpp_asymmetric_key *
-dpp_parse_one_asymmetric_key(const u8 *buf, size_t len)
-{
-	struct asn1_hdr hdr;
-	const u8 *pos = buf, *end = buf + len, *next;
-	int val;
-	const u8 *params;
-	size_t params_len;
-	struct asn1_oid oid;
-	char txt[80];
-	struct dpp_asymmetric_key *key;
-	EC_KEY *eckey;
-
-	wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len);
-
-	key = os_zalloc(sizeof(*key));
-	if (!key)
-		return NULL;
-
-	/*
-	 * OneAsymmetricKey ::= SEQUENCE {
-	 *    version			Version,
-	 *    privateKeyAlgorithm	PrivateKeyAlgorithmIdentifier,
-	 *    privateKey		PrivateKey,
-	 *    attributes		[0] Attributes OPTIONAL,
-	 *    ...,
-	 *    [[2: publicKey		[1] BIT STRING OPTIONAL ]],
-	 *    ...
-	 * }
-	 */
-	if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0)
-		goto fail;
-	pos = hdr.payload;
-
-	/* Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) */
-	if (asn1_get_integer(pos, end - pos, &val, &pos) < 0)
-		goto fail;
-	if (val != 1) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported DPPAsymmetricKeyPackage version %d",
-			   val);
-		goto fail;
-	}
-
-	/* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier */
-	if (asn1_get_alg_id(pos, end - pos, &oid, &params, &params_len,
-			    &pos) < 0)
-		goto fail;
-	if (!asn1_oid_equal(&oid, &asn1_ec_public_key_oid)) {
-		asn1_oid_to_str(&oid, txt, sizeof(txt));
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported PrivateKeyAlgorithmIdentifier %s",
-			   txt);
-		goto fail;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: PrivateKeyAlgorithmIdentifier params",
-		    params, params_len);
-	/*
-	 * ECParameters ::= CHOICE {
-	 *    namedCurve	OBJECT IDENTIFIER
-	 *    -- implicitCurve	NULL
-	 *    -- specifiedCurve	SpecifiedECDomain}
-	 */
-	if (!params || asn1_get_oid(params, params_len, &oid, &next) < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Could not parse ECParameters.namedCurve");
-		goto fail;
-	}
-	asn1_oid_to_str(&oid, txt, sizeof(txt));
-	wpa_printf(MSG_MSGDUMP, "DPP: namedCurve %s", txt);
-	/* Assume the curve is identified within ECPrivateKey, so that this
-	 * separate indication is not really needed. */
-
-	/*
-	 * PrivateKey ::= OCTET STRING
-	 *    (Contains DER encoding of ECPrivateKey)
-	 */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		goto fail;
-	}
-	wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey",
-			hdr.payload, hdr.length);
-	pos = hdr.payload + hdr.length;
-	eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length);
-	if (!eckey) {
-		wpa_printf(MSG_INFO,
-			   "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
-	}
-	key->csign = EVP_PKEY_new();
-	if (!key->csign || EVP_PKEY_assign_EC_KEY(key->csign, eckey) != 1) {
-		EC_KEY_free(eckey);
-		goto fail;
-	}
-	if (wpa_debug_show_keys)
-		dpp_debug_print_key("DPP: Received c-sign-key", key->csign);
-
-	/*
-	 * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } }
-	 *
-	 * Exactly one instance of type Attribute in OneAsymmetricKey.
-	 */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected [0] Attributes - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		goto fail;
-	}
-	wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes",
-			hdr.payload, hdr.length);
-	if (hdr.payload + hdr.length < end) {
-		wpa_hexdump_key(MSG_MSGDUMP,
-				"DPP: Ignore additional data at the end of OneAsymmetricKey",
-				hdr.payload + hdr.length,
-				end - (hdr.payload + hdr.length));
-	}
-	pos = hdr.payload;
-	end = hdr.payload + hdr.length;
-
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected SET (Attributes) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		goto fail;
-	}
-	if (hdr.payload + hdr.length < end) {
-		wpa_hexdump_key(MSG_MSGDUMP,
-				"DPP: Ignore additional data at the end of OneAsymmetricKey (after SET)",
-				hdr.payload + hdr.length,
-				end - (hdr.payload + hdr.length));
-	}
-	pos = hdr.payload;
-	end = hdr.payload + hdr.length;
-
-	/*
-	 * OneAsymmetricKeyAttributes ATTRIBUTE ::= {
-	 *    aa-DPPConfigurationParameters,
-	 *    ... -- For local profiles
-	 * }
-	 *
-	 * aa-DPPConfigurationParameters ATTRIBUTE ::=
-	 * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams }
-	 *
-	 * Attribute ::= SEQUENCE {
-	 *    type OBJECT IDENTIFIER,
-	 *    values SET SIZE(1..MAX) OF Type
-	 *
-	 * Exactly one instance of ATTRIBUTE in attrValues.
-	 */
-	if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0)
-		goto fail;
-	if (pos < end) {
-		wpa_hexdump_key(MSG_MSGDUMP,
-				"DPP: Ignore additional data at the end of ATTRIBUTE",
-				pos, end - pos);
-	}
-	end = pos;
-	pos = hdr.payload;
-
-	if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0)
-		goto fail;
-	if (!asn1_oid_equal(&oid, &asn1_dpp_config_params_oid)) {
-		asn1_oid_to_str(&oid, txt, sizeof(txt));
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unexpected Attribute identifier %s", txt);
-		goto fail;
-	}
-
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected SET (Attribute) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		goto fail;
-	}
-	pos = hdr.payload;
-	end = hdr.payload + hdr.length;
-
-	/*
-	 * DPPConfigurationParameters ::= SEQUENCE {
-	 *    configurationTemplate	UTF8String,
-	 *    connectorTemplate		UTF8String OPTIONAL}
-	 */
-
-	wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPConfigurationParameters",
-			pos, end - pos);
-	if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0)
-		goto fail;
-	if (pos < end) {
-		wpa_hexdump_key(MSG_MSGDUMP,
-				"DPP: Ignore additional data after DPPConfigurationParameters",
-				pos, end - pos);
-	}
-	end = pos;
-	pos = hdr.payload;
-
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_UTF8STRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Expected UTF8STRING (configurationTemplate) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		goto fail;
-	}
-	wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate",
-			      hdr.payload, hdr.length);
-	key->config_template = os_zalloc(hdr.length + 1);
-	if (!key->config_template)
-		goto fail;
-	os_memcpy(key->config_template, hdr.payload, hdr.length);
-
-	pos = hdr.payload + hdr.length;
-
-	if (pos < end) {
-		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_UTF8STRING) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Expected UTF8STRING (connectorTemplate) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
-			goto fail;
-		}
-		wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate",
-				      hdr.payload, hdr.length);
-		key->connector_template = os_zalloc(hdr.length + 1);
-		if (!key->connector_template)
-			goto fail;
-		os_memcpy(key->connector_template, hdr.payload, hdr.length);
-	}
-
-	return key;
-fail:
-	wpa_printf(MSG_DEBUG, "DPP: Failed to parse OneAsymmetricKey");
-	dpp_free_asymmetric_key(key);
-	return NULL;
-}
-
-
-static struct dpp_asymmetric_key *
-dpp_parse_dpp_asymmetric_key_package(const u8 *key_pkg, size_t key_pkg_len)
-{
-	struct asn1_hdr hdr;
-	const u8 *pos = key_pkg, *end = key_pkg + key_pkg_len;
-	struct dpp_asymmetric_key *first = NULL, *last = NULL, *key;
-
-	wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage",
-			key_pkg, key_pkg_len);
-
-	/*
-	 * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage
-	 *
-	 * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey
-	 */
-	while (pos < end) {
-		if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0 ||
-		    !(key = dpp_parse_one_asymmetric_key(hdr.payload,
-							 hdr.length))) {
-			dpp_free_asymmetric_key(first);
-			return NULL;
-		}
-		if (!last) {
-			first = last = key;
-		} else {
-			last->next = key;
-			last = key;
-		}
-	}
-
-	return first;
-}
-
-
-static int dpp_conf_resp_env_data(struct dpp_authentication *auth,
-				  const u8 *env_data, size_t env_data_len)
-{
-	const u8 *key;
-	size_t key_len;
-	u8 kek[DPP_MAX_HASH_LEN];
-	u8 cont_encr_key[DPP_MAX_HASH_LEN];
-	size_t cont_encr_key_len;
-	int res;
-	u8 *key_pkg;
-	size_t key_pkg_len;
-	struct dpp_enveloped_data data;
-	struct dpp_asymmetric_key *keys;
-
-	wpa_hexdump(MSG_DEBUG, "DPP: DPPEnvelopedData", env_data, env_data_len);
-
-	if (dpp_parse_enveloped_data(env_data, env_data_len, &data) < 0)
-		return -1;
-
-	/* TODO: For initial testing, use ke as the key. Replace this with a
-	 * new key once that has been defined. */
-	key = auth->ke;
-	key_len = auth->curve->hash_len;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len);
-
-	if (dpp_pbkdf2(data.prf_hash_len, key, key_len, data.salt, 64, 1000,
-		       kek, data.pbkdf2_key_len)) {
-		wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed");
-		return -1;
-	}
-	wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2",
-			kek, data.pbkdf2_key_len);
-
-	if (data.enc_key_len < AES_BLOCK_SIZE ||
-	    data.enc_key_len > sizeof(cont_encr_key) + AES_BLOCK_SIZE) {
-		wpa_printf(MSG_DEBUG, "DPP: Invalid encryptedKey length");
-		return -1;
-	}
-	res = aes_siv_decrypt(kek, data.pbkdf2_key_len,
-			      data.enc_key, data.enc_key_len,
-			      0, NULL, NULL, cont_encr_key);
-	forced_memzero(kek, data.pbkdf2_key_len);
-	if (res < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: AES-SIV decryption of encryptedKey failed");
-		return -1;
-	}
-	cont_encr_key_len = data.enc_key_len - AES_BLOCK_SIZE;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: content-encryption key",
-			cont_encr_key, cont_encr_key_len);
-
-	if (data.enc_cont_len < AES_BLOCK_SIZE)
-		return -1;
-	key_pkg_len = data.enc_cont_len - AES_BLOCK_SIZE;
-	key_pkg = os_malloc(key_pkg_len);
-	if (!key_pkg)
-		return -1;
-	res = aes_siv_decrypt(cont_encr_key, cont_encr_key_len,
-			      data.enc_cont, data.enc_cont_len,
-			      0, NULL, NULL, key_pkg);
-	forced_memzero(cont_encr_key, cont_encr_key_len);
-	if (res < 0) {
-		bin_clear_free(key_pkg, key_pkg_len);
-		wpa_printf(MSG_DEBUG,
-			   "DPP: AES-SIV decryption of encryptedContent failed");
-		return -1;
-	}
-
-	keys = dpp_parse_dpp_asymmetric_key_package(key_pkg, key_pkg_len);
-	bin_clear_free(key_pkg, key_pkg_len);
-	dpp_free_asymmetric_key(auth->conf_key_pkg);
-	auth->conf_key_pkg = keys;
-
-	return keys != NULL;;
-}
-
-#endif /* CONFIG_DPP2 */
-
-
 int dpp_conf_resp_rx(struct dpp_authentication *auth,
 		     const struct wpabuf *resp)
 {
@@ -8072,6 +2979,36 @@
 }
 
 
+struct wpabuf * dpp_build_conn_status(enum dpp_status_error result,
+				      const u8 *ssid, size_t ssid_len,
+				      const char *channel_list)
+{
+	struct wpabuf *json;
+
+	json = wpabuf_alloc(1000);
+	if (!json)
+		return NULL;
+	json_start_object(json, NULL);
+	json_add_int(json, "result", result);
+	if (ssid) {
+		json_value_sep(json);
+		if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0) {
+			wpabuf_free(json);
+			return NULL;
+		}
+	}
+	if (channel_list) {
+		json_value_sep(json);
+		json_add_string(json, "channelList", channel_list);
+	}
+	json_end_object(json);
+	wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
+			  wpabuf_head(json), wpabuf_len(json));
+
+	return json;
+}
+
+
 struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth,
 					     enum dpp_status_error result,
 					     const u8 *ssid, size_t ssid_len,
@@ -8083,23 +3020,9 @@
 	size_t len[2];
 	u8 *wrapped;
 
-	json = wpabuf_alloc(1000);
+	json = dpp_build_conn_status(result, ssid, ssid_len, channel_list);
 	if (!json)
 		return NULL;
-	json_start_object(json, NULL);
-	json_add_int(json, "result", result);
-	if (ssid) {
-		json_value_sep(json);
-		if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0)
-			goto fail;
-	}
-	if (channel_list) {
-		json_value_sep(json);
-		json_add_string(json, "channelList", channel_list);
-	}
-	json_end_object(json);
-	wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
-			  wpabuf_head(json), wpabuf_len(json));
 
 	nonce_len = auth->curve->nonce_len;
 	clear_len = 5 + 4 + nonce_len + 4 + wpabuf_len(json);
@@ -8161,6 +3084,8 @@
 		return;
 	EVP_PKEY_free(conf->csign);
 	os_free(conf->kid);
+	os_free(conf->connector);
+	EVP_PKEY_free(conf->connector_key);
 	os_free(conf);
 }
 
@@ -8192,7 +3117,6 @@
 static int dpp_configurator_gen_kid(struct dpp_configurator *conf)
 {
 	struct wpabuf *csign_pub = NULL;
-	u8 kid_hash[SHA256_MAC_LEN];
 	const u8 *addr[1];
 	size_t len[1];
 	int res;
@@ -8206,7 +3130,7 @@
 	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
 	addr[0] = wpabuf_head(csign_pub);
 	len[0] = wpabuf_len(csign_pub);
-	res = sha256_vector(1, addr, len, kid_hash);
+	res = sha256_vector(1, addr, len, conf->kid_hash);
 	wpabuf_free(csign_pub);
 	if (res < 0) {
 		wpa_printf(MSG_DEBUG,
@@ -8214,7 +3138,8 @@
 		return -1;
 	}
 
-	conf->kid = base64_url_encode(kid_hash, sizeof(kid_hash), NULL);
+	conf->kid = base64_url_encode(conf->kid_hash, sizeof(conf->kid_hash),
+				      NULL);
 	return conf->kid ? 0 : -1;
 }
 
@@ -8229,17 +3154,13 @@
 	if (!conf)
 		return NULL;
 
-	if (!curve) {
-		conf->curve = &dpp_curves[0];
-	} else {
-		conf->curve = dpp_get_curve_name(curve);
-		if (!conf->curve) {
-			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
-				   curve);
-			os_free(conf);
-			return NULL;
-		}
+	conf->curve = dpp_get_curve_name(curve);
+	if (!conf->curve) {
+		wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
+		os_free(conf);
+		return NULL;
 	}
+
 	if (privkey)
 		conf->csign = dpp_set_keypair(&conf->curve, privkey,
 					      privkey_len);
@@ -8269,16 +3190,12 @@
 		return -1;
 	}
 
-	if (!curve) {
-		auth->curve = &dpp_curves[0];
-	} else {
-		auth->curve = dpp_get_curve_name(curve);
-		if (!auth->curve) {
-			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
-				   curve);
-			return -1;
-		}
+	auth->curve = dpp_get_curve_name(curve);
+	if (!auth->curve) {
+		wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve);
+		return -1;
 	}
+
 	wpa_printf(MSG_DEBUG,
 		   "DPP: Building own configuration/connector with curve %s",
 		   auth->curve->name);
@@ -8314,7 +3231,8 @@
 
 static int dpp_connector_compatible_group(struct json_token *root,
 					  const char *group_id,
-					  const char *net_role)
+					  const char *net_role,
+					  bool reconfig)
 {
 	struct json_token *groups, *token;
 
@@ -8338,7 +3256,9 @@
 		    os_strcmp(id->string, group_id) != 0)
 			continue;
 
-		if (dpp_compatible_netrole(role->string, net_role))
+		if (reconfig && os_strcmp(net_role, "configurator") == 0)
+			return 1;
+		if (!reconfig && dpp_compatible_netrole(role->string, net_role))
 			return 1;
 	}
 
@@ -8346,8 +3266,8 @@
 }
 
 
-static int dpp_connector_match_groups(struct json_token *own_root,
-				      struct json_token *peer_root)
+int dpp_connector_match_groups(struct json_token *own_root,
+			       struct json_token *peer_root, bool reconfig)
 {
 	struct json_token *groups, *token;
 
@@ -8377,7 +3297,7 @@
 			   "DPP: peer connector group: groupId='%s' netRole='%s'",
 			   id->string, role->string);
 		if (dpp_connector_compatible_group(own_root, id->string,
-						   role->string)) {
+						   role->string, reconfig)) {
 			wpa_printf(MSG_DEBUG,
 				   "DPP: Compatible group/netRole in own connector");
 			return 1;
@@ -8388,71 +3308,37 @@
 }
 
 
-static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk,
-			  unsigned int hash_len)
+struct json_token * dpp_parse_own_connector(const char *own_connector)
 {
-	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
-	const char *info = "DPP PMK";
-	int res;
+	unsigned char *own_conn;
+	size_t own_conn_len;
+	const char *pos, *end;
+	struct json_token *own_root;
 
-	/* PMK = HKDF(<>, "DPP PMK", N.x) */
-
-	/* HKDF-Extract(<>, N.x) */
-	os_memset(salt, 0, hash_len);
-	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
-		return -1;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
-			prk, hash_len);
-
-	/* HKDF-Expand(PRK, info, L) */
-	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
-	os_memset(prk, 0, hash_len);
-	if (res < 0)
-		return -1;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
-			pmk, hash_len);
-	return 0;
-}
-
-
-static int dpp_derive_pmkid(const struct dpp_curve_params *curve,
-			    EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid)
-{
-	struct wpabuf *nkx, *pkx;
-	int ret = -1, res;
-	const u8 *addr[2];
-	size_t len[2];
-	u8 hash[SHA256_MAC_LEN];
-
-	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
-	nkx = dpp_get_pubkey_point(own_key, 0);
-	pkx = dpp_get_pubkey_point(peer_key, 0);
-	if (!nkx || !pkx)
-		goto fail;
-	addr[0] = wpabuf_head(nkx);
-	len[0] = wpabuf_len(nkx) / 2;
-	addr[1] = wpabuf_head(pkx);
-	len[1] = wpabuf_len(pkx) / 2;
-	if (len[0] != len[1])
-		goto fail;
-	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
-		addr[0] = wpabuf_head(pkx);
-		addr[1] = wpabuf_head(nkx);
+	pos = os_strchr(own_connector, '.');
+	if (!pos) {
+		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
+		return NULL;
 	}
-	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
-	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
-	res = sha256_vector(2, addr, len, hash);
-	if (res < 0)
-		goto fail;
-	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
-	os_memcpy(pmkid, hash, PMKID_LEN);
-	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
-	ret = 0;
-fail:
-	wpabuf_free(nkx);
-	wpabuf_free(pkx);
-	return ret;
+	pos++;
+	end = os_strchr(pos, '.');
+	if (!end) {
+		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
+		return NULL;
+	}
+	own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
+	if (!own_conn) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
+		return NULL;
+	}
+
+	own_root = json_parse((const char *) own_conn, own_conn_len);
+	os_free(own_conn);
+	if (!own_root)
+		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
+
+	return own_root;
 }
 
 
@@ -8470,12 +3356,6 @@
 	struct wpabuf *own_key_pub = NULL;
 	const struct dpp_curve_params *curve, *own_curve;
 	struct dpp_signed_connector_info info;
-	const unsigned char *p;
-	EVP_PKEY *csign = NULL;
-	char *signed_connector = NULL;
-	const char *pos, *end;
-	unsigned char *own_conn = NULL;
-	size_t own_conn_len;
 	size_t Nx_len;
 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
 
@@ -8484,14 +3364,6 @@
 	if (expiry)
 		*expiry = 0;
 
-	p = csign_key;
-	csign = d2i_PUBKEY(NULL, &p, csign_key_len);
-	if (!csign) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to parse local C-sign-key information");
-		goto fail;
-	}
-
 	own_key = dpp_set_keypair(&own_curve, net_access_key,
 				  net_access_key_len);
 	if (!own_key) {
@@ -8499,39 +3371,12 @@
 		goto fail;
 	}
 
-	pos = os_strchr(own_connector, '.');
-	if (!pos) {
-		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
+	own_root = dpp_parse_own_connector(own_connector);
+	if (!own_root)
 		goto fail;
-	}
-	pos++;
-	end = os_strchr(pos, '.');
-	if (!end) {
-		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
-		goto fail;
-	}
-	own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
-	if (!own_conn) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
-		goto fail;
-	}
 
-	own_root = json_parse((const char *) own_conn, own_conn_len);
-	if (!own_root) {
-		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
-		goto fail;
-	}
-
-	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
-			  peer_connector, peer_connector_len);
-	signed_connector = os_malloc(peer_connector_len + 1);
-	if (!signed_connector)
-		goto fail;
-	os_memcpy(signed_connector, peer_connector, peer_connector_len);
-	signed_connector[peer_connector_len] = '\0';
-
-	res = dpp_process_signed_connector(&info, csign, signed_connector);
+	res = dpp_check_signed_connector(&info, csign_key, csign_key_len,
+					 peer_connector, peer_connector_len);
 	if (res != DPP_STATUS_OK) {
 		ret = res;
 		goto fail;
@@ -8544,7 +3389,7 @@
 		goto fail;
 	}
 
-	if (!dpp_connector_match_groups(own_root, root)) {
+	if (!dpp_connector_match_groups(own_root, root, false)) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Peer connector does not include compatible group netrole with own connector");
 		ret = DPP_STATUS_NO_MATCH;
@@ -8612,1751 +3457,17 @@
 	if (ret != DPP_STATUS_OK)
 		os_memset(intro, 0, sizeof(*intro));
 	os_memset(Nx, 0, sizeof(Nx));
-	os_free(own_conn);
-	os_free(signed_connector);
 	os_free(info.payload);
 	EVP_PKEY_free(own_key);
 	wpabuf_free(own_key_pub);
 	EVP_PKEY_free(peer_key);
-	EVP_PKEY_free(csign);
 	json_free(root);
 	json_free(own_root);
 	return ret;
 }
 
 
-static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve,
-					 int init)
-{
-	EC_GROUP *group;
-	size_t len = curve->prime_len;
-	const u8 *x, *y;
-	EVP_PKEY *res;
-
-	switch (curve->ike_group) {
-	case 19:
-		x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
-		y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
-		break;
-	case 20:
-		x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
-		y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
-		break;
-	case 21:
-		x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
-		y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
-		break;
-	case 28:
-		x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
-		y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
-		break;
-	case 29:
-		x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
-		y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
-		break;
-	case 30:
-		x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
-		y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
-		break;
-	default:
-		return NULL;
-	}
-
-	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
-	if (!group)
-		return NULL;
-	res = dpp_set_pubkey_point_group(group, x, y, len);
-	EC_GROUP_free(group);
-	return res;
-}
-
-
-static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
-				     const u8 *mac_init, const char *code,
-				     const char *identifier, BN_CTX *bnctx,
-				     EC_GROUP **ret_group)
-{
-	u8 hash[DPP_MAX_HASH_LEN];
-	const u8 *addr[3];
-	size_t len[3];
-	unsigned int num_elem = 0;
-	EC_POINT *Qi = NULL;
-	EVP_PKEY *Pi = NULL;
-	EC_KEY *Pi_ec = NULL;
-	const EC_POINT *Pi_point;
-	BIGNUM *hash_bn = NULL;
-	const EC_GROUP *group = NULL;
-	EC_GROUP *group2 = NULL;
-
-	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
-
-	wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init));
-	addr[num_elem] = mac_init;
-	len[num_elem] = ETH_ALEN;
-	num_elem++;
-	if (identifier) {
-		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
-			   identifier);
-		addr[num_elem] = (const u8 *) identifier;
-		len[num_elem] = os_strlen(identifier);
-		num_elem++;
-	}
-	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
-	addr[num_elem] = (const u8 *) code;
-	len[num_elem] = os_strlen(code);
-	num_elem++;
-	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
-		goto fail;
-	wpa_hexdump_key(MSG_DEBUG,
-			"DPP: H(MAC-Initiator | [identifier |] code)",
-			hash, curve->hash_len);
-	Pi = dpp_pkex_get_role_elem(curve, 1);
-	if (!Pi)
-		goto fail;
-	dpp_debug_print_key("DPP: Pi", Pi);
-	Pi_ec = EVP_PKEY_get1_EC_KEY(Pi);
-	if (!Pi_ec)
-		goto fail;
-	Pi_point = EC_KEY_get0_public_key(Pi_ec);
-
-	group = EC_KEY_get0_group(Pi_ec);
-	if (!group)
-		goto fail;
-	group2 = EC_GROUP_dup(group);
-	if (!group2)
-		goto fail;
-	Qi = EC_POINT_new(group2);
-	if (!Qi) {
-		EC_GROUP_free(group2);
-		goto fail;
-	}
-	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
-	if (!hash_bn ||
-	    EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1)
-		goto fail;
-	if (EC_POINT_is_at_infinity(group, Qi)) {
-		wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
-		goto fail;
-	}
-	dpp_debug_print_point("DPP: Qi", group, Qi);
-out:
-	EC_KEY_free(Pi_ec);
-	EVP_PKEY_free(Pi);
-	BN_clear_free(hash_bn);
-	if (ret_group && Qi)
-		*ret_group = group2;
-	else
-		EC_GROUP_free(group2);
-	return Qi;
-fail:
-	EC_POINT_free(Qi);
-	Qi = NULL;
-	goto out;
-}
-
-
-static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
-				     const u8 *mac_resp, const char *code,
-				     const char *identifier, BN_CTX *bnctx,
-				     EC_GROUP **ret_group)
-{
-	u8 hash[DPP_MAX_HASH_LEN];
-	const u8 *addr[3];
-	size_t len[3];
-	unsigned int num_elem = 0;
-	EC_POINT *Qr = NULL;
-	EVP_PKEY *Pr = NULL;
-	EC_KEY *Pr_ec = NULL;
-	const EC_POINT *Pr_point;
-	BIGNUM *hash_bn = NULL;
-	const EC_GROUP *group = NULL;
-	EC_GROUP *group2 = NULL;
-
-	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
-
-	wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp));
-	addr[num_elem] = mac_resp;
-	len[num_elem] = ETH_ALEN;
-	num_elem++;
-	if (identifier) {
-		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
-			   identifier);
-		addr[num_elem] = (const u8 *) identifier;
-		len[num_elem] = os_strlen(identifier);
-		num_elem++;
-	}
-	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
-	addr[num_elem] = (const u8 *) code;
-	len[num_elem] = os_strlen(code);
-	num_elem++;
-	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
-		goto fail;
-	wpa_hexdump_key(MSG_DEBUG,
-			"DPP: H(MAC-Responder | [identifier |] code)",
-			hash, curve->hash_len);
-	Pr = dpp_pkex_get_role_elem(curve, 0);
-	if (!Pr)
-		goto fail;
-	dpp_debug_print_key("DPP: Pr", Pr);
-	Pr_ec = EVP_PKEY_get1_EC_KEY(Pr);
-	if (!Pr_ec)
-		goto fail;
-	Pr_point = EC_KEY_get0_public_key(Pr_ec);
-
-	group = EC_KEY_get0_group(Pr_ec);
-	if (!group)
-		goto fail;
-	group2 = EC_GROUP_dup(group);
-	if (!group2)
-		goto fail;
-	Qr = EC_POINT_new(group2);
-	if (!Qr) {
-		EC_GROUP_free(group2);
-		goto fail;
-	}
-	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
-	if (!hash_bn ||
-	    EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1)
-		goto fail;
-	if (EC_POINT_is_at_infinity(group, Qr)) {
-		wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
-		goto fail;
-	}
-	dpp_debug_print_point("DPP: Qr", group, Qr);
-out:
-	EC_KEY_free(Pr_ec);
-	EVP_PKEY_free(Pr);
-	BN_clear_free(hash_bn);
-	if (ret_group && Qr)
-		*ret_group = group2;
-	else
-		EC_GROUP_free(group2);
-	return Qr;
-fail:
-	EC_POINT_free(Qr);
-	Qr = NULL;
-	goto out;
-}
-
-
-#ifdef CONFIG_TESTING_OPTIONS
-static int dpp_test_gen_invalid_key(struct wpabuf *msg,
-				    const struct dpp_curve_params *curve)
-{
-	BN_CTX *ctx;
-	BIGNUM *x, *y;
-	int ret = -1;
-	EC_GROUP *group;
-	EC_POINT *point;
-
-	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
-	if (!group)
-		return -1;
-
-	ctx = BN_CTX_new();
-	point = EC_POINT_new(group);
-	x = BN_new();
-	y = BN_new();
-	if (!ctx || !point || !x || !y)
-		goto fail;
-
-	if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1)
-		goto fail;
-
-	/* Generate a random y coordinate that results in a point that is not
-	 * on the curve. */
-	for (;;) {
-		if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1)
-			goto fail;
-
-		if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y,
-							ctx) != 1) {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
-		/* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL
-		 * return an error from EC_POINT_set_affine_coordinates_GFp()
-		 * when the point is not on the curve. */
-			break;
-#else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */
-			goto fail;
-#endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */
-		}
-
-		if (!EC_POINT_is_on_curve(group, point, ctx))
-			break;
-	}
-
-	if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0)
-		goto fail;
-
-	ret = 0;
-fail:
-	if (ret < 0)
-		wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key");
-	BN_free(x);
-	BN_free(y);
-	EC_POINT_free(point);
-	BN_CTX_free(ctx);
-	EC_GROUP_free(group);
-
-	return ret;
-}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-
-static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
-{
-	EC_KEY *X_ec = NULL;
-	const EC_POINT *X_point;
-	BN_CTX *bnctx = NULL;
-	EC_GROUP *group = NULL;
-	EC_POINT *Qi = NULL, *M = NULL;
-	struct wpabuf *M_buf = NULL;
-	BIGNUM *Mx = NULL, *My = NULL;
-	struct wpabuf *msg = NULL;
-	size_t attr_len;
-	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-
-	wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
-
-	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
-	bnctx = BN_CTX_new();
-	if (!bnctx)
-		goto fail;
-	Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
-				pkex->identifier, bnctx, &group);
-	if (!Qi)
-		goto fail;
-
-	/* Generate a random ephemeral keypair x/X */
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_pkex_ephemeral_key_override_len) {
-		const struct dpp_curve_params *tmp_curve;
-
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - override ephemeral key x/X");
-		pkex->x = dpp_set_keypair(&tmp_curve,
-					  dpp_pkex_ephemeral_key_override,
-					  dpp_pkex_ephemeral_key_override_len);
-	} else {
-		pkex->x = dpp_gen_keypair(curve);
-	}
-#else /* CONFIG_TESTING_OPTIONS */
-	pkex->x = dpp_gen_keypair(curve);
-#endif /* CONFIG_TESTING_OPTIONS */
-	if (!pkex->x)
-		goto fail;
-
-	/* M = X + Qi */
-	X_ec = EVP_PKEY_get1_EC_KEY(pkex->x);
-	if (!X_ec)
-		goto fail;
-	X_point = EC_KEY_get0_public_key(X_ec);
-	if (!X_point)
-		goto fail;
-	dpp_debug_print_point("DPP: X", group, X_point);
-	M = EC_POINT_new(group);
-	Mx = BN_new();
-	My = BN_new();
-	if (!M || !Mx || !My ||
-	    EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1)
-		goto fail;
-	dpp_debug_print_point("DPP: M", group, M);
-
-	/* Initiator -> Responder: group, [identifier,] M */
-	attr_len = 4 + 2;
-	if (pkex->identifier)
-		attr_len += 4 + os_strlen(pkex->identifier);
-	attr_len += 4 + 2 * curve->prime_len;
-	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len);
-	if (!msg)
-		goto fail;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group");
-		goto skip_finite_cyclic_group;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* Finite Cyclic Group attribute */
-	wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
-	wpabuf_put_le16(msg, 2);
-	wpabuf_put_le16(msg, curve->ike_group);
-
-#ifdef CONFIG_TESTING_OPTIONS
-skip_finite_cyclic_group:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* Code Identifier attribute */
-	if (pkex->identifier) {
-		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
-		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
-		wpabuf_put_str(msg, pkex->identifier);
-	}
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key");
-		goto out;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* M in Encrypted Key attribute */
-	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
-	wpabuf_put_le16(msg, 2 * curve->prime_len);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key");
-		if (dpp_test_gen_invalid_key(msg, curve) < 0)
-			goto fail;
-		goto out;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0)
-		goto fail;
-
-out:
-	wpabuf_free(M_buf);
-	EC_KEY_free(X_ec);
-	EC_POINT_free(M);
-	EC_POINT_free(Qi);
-	BN_clear_free(Mx);
-	BN_clear_free(My);
-	BN_CTX_free(bnctx);
-	EC_GROUP_free(group);
-	return msg;
-fail:
-	wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request");
-	wpabuf_free(msg);
-	msg = NULL;
-	goto out;
-}
-
-
-static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt)
-{
-	wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
-}
-
-
-struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
-				const u8 *own_mac,
-				const char *identifier,
-				const char *code)
-{
-	struct dpp_pkex *pkex;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR,
-			   MAC2STR(dpp_pkex_own_mac_override));
-		own_mac = dpp_pkex_own_mac_override;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	pkex = os_zalloc(sizeof(*pkex));
-	if (!pkex)
-		return NULL;
-	pkex->msg_ctx = msg_ctx;
-	pkex->initiator = 1;
-	pkex->own_bi = bi;
-	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
-	if (identifier) {
-		pkex->identifier = os_strdup(identifier);
-		if (!pkex->identifier)
-			goto fail;
-	}
-	pkex->code = os_strdup(code);
-	if (!pkex->code)
-		goto fail;
-	pkex->exchange_req = dpp_pkex_build_exchange_req(pkex);
-	if (!pkex->exchange_req)
-		goto fail;
-	return pkex;
-fail:
-	dpp_pkex_free(pkex);
-	return NULL;
-}
-
-
-static struct wpabuf *
-dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
-			     enum dpp_status_error status,
-			     const BIGNUM *Nx, const BIGNUM *Ny)
-{
-	struct wpabuf *msg = NULL;
-	size_t attr_len;
-	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-
-	/* Initiator -> Responder: DPP Status, [identifier,] N */
-	attr_len = 4 + 1;
-	if (pkex->identifier)
-		attr_len += 4 + os_strlen(pkex->identifier);
-	attr_len += 4 + 2 * curve->prime_len;
-	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len);
-	if (!msg)
-		goto fail;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
-		goto skip_status;
-	}
-
-	if (dpp_test == DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
-		status = 255;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* DPP Status */
-	dpp_build_attr_status(msg, status);
-
-#ifdef CONFIG_TESTING_OPTIONS
-skip_status:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* Code Identifier attribute */
-	if (pkex->identifier) {
-		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
-		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
-		wpabuf_put_str(msg, pkex->identifier);
-	}
-
-	if (status != DPP_STATUS_OK)
-		goto skip_encrypted_key;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key");
-		goto skip_encrypted_key;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* N in Encrypted Key attribute */
-	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
-	wpabuf_put_le16(msg, 2 * curve->prime_len);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key");
-		if (dpp_test_gen_invalid_key(msg, curve) < 0)
-			goto fail;
-		goto skip_encrypted_key;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (dpp_bn2bin_pad(Nx, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(Nx, pkex->Nx, curve->prime_len) < 0 ||
-	    dpp_bn2bin_pad(Ny, wpabuf_put(msg, curve->prime_len),
-			   curve->prime_len) < 0)
-		goto fail;
-
-skip_encrypted_key:
-	if (status == DPP_STATUS_BAD_GROUP) {
-		/* Finite Cyclic Group attribute */
-		wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
-		wpabuf_put_le16(msg, 2);
-		wpabuf_put_le16(msg, curve->ike_group);
-	}
-
-	return msg;
-fail:
-	wpabuf_free(msg);
-	return NULL;
-}
-
-
-static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
-			     const u8 *Mx, size_t Mx_len,
-			     const u8 *Nx, size_t Nx_len,
-			     const char *code,
-			     const u8 *Kx, size_t Kx_len,
-			     u8 *z, unsigned int hash_len)
-{
-	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
-	int res;
-	u8 *info, *pos;
-	size_t info_len;
-
-	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
-	 */
-
-	/* HKDF-Extract(<>, IKM=K.x) */
-	os_memset(salt, 0, hash_len);
-	if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
-		return -1;
-	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
-			prk, hash_len);
-	info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
-	info = os_malloc(info_len);
-	if (!info)
-		return -1;
-	pos = info;
-	os_memcpy(pos, mac_init, ETH_ALEN);
-	pos += ETH_ALEN;
-	os_memcpy(pos, mac_resp, ETH_ALEN);
-	pos += ETH_ALEN;
-	os_memcpy(pos, Mx, Mx_len);
-	pos += Mx_len;
-	os_memcpy(pos, Nx, Nx_len);
-	pos += Nx_len;
-	os_memcpy(pos, code, os_strlen(code));
-
-	/* HKDF-Expand(PRK, info, L) */
-	if (hash_len == 32)
-		res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
-				      z, hash_len);
-	else if (hash_len == 48)
-		res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
-				      z, hash_len);
-	else if (hash_len == 64)
-		res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
-				      z, hash_len);
-	else
-		res = -1;
-	os_free(info);
-	os_memset(prk, 0, hash_len);
-	if (res < 0)
-		return -1;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
-			z, hash_len);
-	return 0;
-}
-
-
-static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len,
-				     const char *identifier)
-{
-	if (!attr_id && identifier) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No PKEX code identifier received, but expected one");
-		return 0;
-	}
-
-	if (attr_id && !identifier) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: PKEX code identifier received, but not expecting one");
-		return 0;
-	}
-
-	if (attr_id && identifier &&
-	    (os_strlen(identifier) != attr_id_len ||
-	     os_memcmp(identifier, attr_id, attr_id_len) != 0)) {
-		wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
-		return 0;
-	}
-
-	return 1;
-}
-
-
-struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
-					   struct dpp_bootstrap_info *bi,
-					   const u8 *own_mac,
-					   const u8 *peer_mac,
-					   const char *identifier,
-					   const char *code,
-					   const u8 *buf, size_t len)
-{
-	const u8 *attr_group, *attr_id, *attr_key;
-	u16 attr_group_len, attr_id_len, attr_key_len;
-	const struct dpp_curve_params *curve = bi->curve;
-	u16 ike_group;
-	struct dpp_pkex *pkex = NULL;
-	EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL;
-	BN_CTX *bnctx = NULL;
-	EC_GROUP *group = NULL;
-	BIGNUM *Mx = NULL, *My = NULL;
-	EC_KEY *Y_ec = NULL, *X_ec = NULL;;
-	const EC_POINT *Y_point;
-	BIGNUM *Nx = NULL, *Ny = NULL;
-	u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
-	size_t Kx_len;
-	int res;
-
-	if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
-		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-			"PKEX counter t limit reached - ignore message");
-		return NULL;
-	}
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
-			   MAC2STR(dpp_pkex_peer_mac_override));
-		peer_mac = dpp_pkex_peer_mac_override;
-	}
-	if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR,
-			   MAC2STR(dpp_pkex_own_mac_override));
-		own_mac = dpp_pkex_own_mac_override;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	attr_id_len = 0;
-	attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
-			       &attr_id_len);
-	if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier))
-		return NULL;
-
-	attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
-				  &attr_group_len);
-	if (!attr_group || attr_group_len != 2) {
-		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-			"Missing or invalid Finite Cyclic Group attribute");
-		return NULL;
-	}
-	ike_group = WPA_GET_LE16(attr_group);
-	if (ike_group != curve->ike_group) {
-		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-			"Mismatching PKEX curve: peer=%u own=%u",
-			ike_group, curve->ike_group);
-		pkex = os_zalloc(sizeof(*pkex));
-		if (!pkex)
-			goto fail;
-		pkex->own_bi = bi;
-		pkex->failed = 1;
-		pkex->exchange_resp = dpp_pkex_build_exchange_resp(
-			pkex, DPP_STATUS_BAD_GROUP, NULL, NULL);
-		if (!pkex->exchange_resp)
-			goto fail;
-		return pkex;
-	}
-
-	/* M in Encrypted Key attribute */
-	attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY,
-				&attr_key_len);
-	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 ||
-	    attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) {
-		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-			"Missing Encrypted Key attribute");
-		return NULL;
-	}
-
-	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
-	bnctx = BN_CTX_new();
-	if (!bnctx)
-		goto fail;
-	Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx,
-				&group);
-	if (!Qi)
-		goto fail;
-
-	/* X' = M - Qi */
-	X = EC_POINT_new(group);
-	M = EC_POINT_new(group);
-	Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
-	My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
-	if (!X || !M || !Mx || !My ||
-	    EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 ||
-	    EC_POINT_is_at_infinity(group, M) ||
-	    !EC_POINT_is_on_curve(group, M, bnctx) ||
-	    EC_POINT_invert(group, Qi, bnctx) != 1 ||
-	    EC_POINT_add(group, X, M, Qi, bnctx) != 1 ||
-	    EC_POINT_is_at_infinity(group, X) ||
-	    !EC_POINT_is_on_curve(group, X, bnctx)) {
-		wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-			"Invalid Encrypted Key value");
-		bi->pkex_t++;
-		goto fail;
-	}
-	dpp_debug_print_point("DPP: M", group, M);
-	dpp_debug_print_point("DPP: X'", group, X);
-
-	pkex = os_zalloc(sizeof(*pkex));
-	if (!pkex)
-		goto fail;
-	pkex->t = bi->pkex_t;
-	pkex->msg_ctx = msg_ctx;
-	pkex->own_bi = bi;
-	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
-	os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
-	if (identifier) {
-		pkex->identifier = os_strdup(identifier);
-		if (!pkex->identifier)
-			goto fail;
-	}
-	pkex->code = os_strdup(code);
-	if (!pkex->code)
-		goto fail;
-
-	os_memcpy(pkex->Mx, attr_key, attr_key_len / 2);
-
-	X_ec = EC_KEY_new();
-	if (!X_ec ||
-	    EC_KEY_set_group(X_ec, group) != 1 ||
-	    EC_KEY_set_public_key(X_ec, X) != 1)
-		goto fail;
-	pkex->x = EVP_PKEY_new();
-	if (!pkex->x ||
-	    EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1)
-		goto fail;
-
-	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
-	Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL);
-	if (!Qr)
-		goto fail;
-
-	/* Generate a random ephemeral keypair y/Y */
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_pkex_ephemeral_key_override_len) {
-		const struct dpp_curve_params *tmp_curve;
-
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - override ephemeral key y/Y");
-		pkex->y = dpp_set_keypair(&tmp_curve,
-					  dpp_pkex_ephemeral_key_override,
-					  dpp_pkex_ephemeral_key_override_len);
-	} else {
-		pkex->y = dpp_gen_keypair(curve);
-	}
-#else /* CONFIG_TESTING_OPTIONS */
-	pkex->y = dpp_gen_keypair(curve);
-#endif /* CONFIG_TESTING_OPTIONS */
-	if (!pkex->y)
-		goto fail;
-
-	/* N = Y + Qr */
-	Y_ec = EVP_PKEY_get1_EC_KEY(pkex->y);
-	if (!Y_ec)
-		goto fail;
-	Y_point = EC_KEY_get0_public_key(Y_ec);
-	if (!Y_point)
-		goto fail;
-	dpp_debug_print_point("DPP: Y", group, Y_point);
-	N = EC_POINT_new(group);
-	Nx = BN_new();
-	Ny = BN_new();
-	if (!N || !Nx || !Ny ||
-	    EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 ||
-	    EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1)
-		goto fail;
-	dpp_debug_print_point("DPP: N", group, N);
-
-	pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK,
-							   Nx, Ny);
-	if (!pkex->exchange_resp)
-		goto fail;
-
-	/* K = y * X' */
-	if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0)
-		goto fail;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
-			Kx, Kx_len);
-
-	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
-	 */
-	res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
-				pkex->Mx, curve->prime_len,
-				pkex->Nx, curve->prime_len, pkex->code,
-				Kx, Kx_len, pkex->z, curve->hash_len);
-	os_memset(Kx, 0, Kx_len);
-	if (res < 0)
-		goto fail;
-
-	pkex->exchange_done = 1;
-
-out:
-	BN_CTX_free(bnctx);
-	EC_POINT_free(Qi);
-	EC_POINT_free(Qr);
-	BN_free(Mx);
-	BN_free(My);
-	BN_free(Nx);
-	BN_free(Ny);
-	EC_POINT_free(M);
-	EC_POINT_free(N);
-	EC_POINT_free(X);
-	EC_KEY_free(X_ec);
-	EC_KEY_free(Y_ec);
-	EC_GROUP_free(group);
-	return pkex;
-fail:
-	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed");
-	dpp_pkex_free(pkex);
-	pkex = NULL;
-	goto out;
-}
-
-
-static struct wpabuf *
-dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex,
-				 const struct wpabuf *A_pub, const u8 *u)
-{
-	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-	struct wpabuf *msg = NULL;
-	size_t clear_len, attr_len;
-	struct wpabuf *clear = NULL;
-	u8 *wrapped;
-	u8 octet;
-	const u8 *addr[2];
-	size_t len[2];
-
-	/* {A, u, [bootstrapping info]}z */
-	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
-	clear = wpabuf_alloc(clear_len);
-	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ)
-		attr_len += 5;
-#endif /* CONFIG_TESTING_OPTIONS */
-	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len);
-	if (!clear || !msg)
-		goto fail;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key");
-		goto skip_bootstrap_key;
-	}
-	if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key");
-		wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
-		wpabuf_put_le16(clear, 2 * curve->prime_len);
-		if (dpp_test_gen_invalid_key(clear, curve) < 0)
-			goto fail;
-		goto skip_bootstrap_key;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* A in Bootstrap Key attribute */
-	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
-	wpabuf_put_le16(clear, wpabuf_len(A_pub));
-	wpabuf_put_buf(clear, A_pub);
-
-#ifdef CONFIG_TESTING_OPTIONS
-skip_bootstrap_key:
-	if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag");
-		goto skip_i_auth_tag;
-	}
-	if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch");
-		wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
-		wpabuf_put_le16(clear, curve->hash_len);
-		wpabuf_put_data(clear, u, curve->hash_len - 1);
-		wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01);
-		goto skip_i_auth_tag;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* u in I-Auth tag attribute */
-	wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
-	wpabuf_put_le16(clear, curve->hash_len);
-	wpabuf_put_data(clear, u, curve->hash_len);
-
-#ifdef CONFIG_TESTING_OPTIONS
-skip_i_auth_tag:
-	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
-		goto skip_wrapped_data;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	addr[0] = wpabuf_head_u8(msg) + 2;
-	len[0] = DPP_HDR_LEN;
-	octet = 0;
-	addr[1] = &octet;
-	len[1] = sizeof(octet);
-	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]);
-
-	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(pkex->z, curve->hash_len,
-			    wpabuf_head(clear), wpabuf_len(clear),
-			    2, addr, len, wrapped) < 0)
-		goto fail;
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
-		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
-		dpp_build_attr_status(msg, DPP_STATUS_OK);
-	}
-skip_wrapped_data:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-out:
-	wpabuf_free(clear);
-	return msg;
-
-fail:
-	wpabuf_free(msg);
-	msg = NULL;
-	goto out;
-}
-
-
-struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
-					  const u8 *peer_mac,
-					  const u8 *buf, size_t buflen)
-{
-	const u8 *attr_status, *attr_id, *attr_key, *attr_group;
-	u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len;
-	EC_GROUP *group = NULL;
-	BN_CTX *bnctx = NULL;
-	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
-	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-	EC_POINT *Qr = NULL, *Y = NULL, *N = NULL;
-	BIGNUM *Nx = NULL, *Ny = NULL;
-	EC_KEY *Y_ec = NULL;
-	size_t Jx_len, Kx_len;
-	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
-	const u8 *addr[4];
-	size_t len[4];
-	u8 u[DPP_MAX_HASH_LEN];
-	int res;
-
-	if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator)
-		return NULL;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - stop at PKEX Exchange Response");
-		pkex->failed = 1;
-		return NULL;
-	}
-
-	if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
-			   MAC2STR(dpp_pkex_peer_mac_override));
-		peer_mac = dpp_pkex_peer_mac_override;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
-
-	attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
-				   &attr_status_len);
-	if (!attr_status || attr_status_len != 1) {
-		dpp_pkex_fail(pkex, "No DPP Status attribute");
-		return NULL;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]);
-
-	if (attr_status[0] == DPP_STATUS_BAD_GROUP) {
-		attr_group = dpp_get_attr(buf, buflen,
-					  DPP_ATTR_FINITE_CYCLIC_GROUP,
-					  &attr_group_len);
-		if (attr_group && attr_group_len == 2) {
-			wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-				"Peer indicated mismatching PKEX group - proposed %u",
-				WPA_GET_LE16(attr_group));
-			return NULL;
-		}
-	}
-
-	if (attr_status[0] != DPP_STATUS_OK) {
-		dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)");
-		return NULL;
-	}
-
-	attr_id_len = 0;
-	attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER,
-			       &attr_id_len);
-	if (!dpp_pkex_identifier_match(attr_id, attr_id_len,
-				       pkex->identifier)) {
-		dpp_pkex_fail(pkex, "PKEX code identifier mismatch");
-		return NULL;
-	}
-
-	/* N in Encrypted Key attribute */
-	attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY,
-				&attr_key_len);
-	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) {
-		dpp_pkex_fail(pkex, "Missing Encrypted Key attribute");
-		return NULL;
-	}
-
-	/* Qr = H(MAC-Responder | [identifier |] code) * Pr */
-	bnctx = BN_CTX_new();
-	if (!bnctx)
-		goto fail;
-	Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
-				pkex->identifier, bnctx, &group);
-	if (!Qr)
-		goto fail;
-
-	/* Y' = N - Qr */
-	Y = EC_POINT_new(group);
-	N = EC_POINT_new(group);
-	Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
-	Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
-	if (!Y || !N || !Nx || !Ny ||
-	    EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 ||
-	    EC_POINT_is_at_infinity(group, N) ||
-	    !EC_POINT_is_on_curve(group, N, bnctx) ||
-	    EC_POINT_invert(group, Qr, bnctx) != 1 ||
-	    EC_POINT_add(group, Y, N, Qr, bnctx) != 1 ||
-	    EC_POINT_is_at_infinity(group, Y) ||
-	    !EC_POINT_is_on_curve(group, Y, bnctx)) {
-		dpp_pkex_fail(pkex, "Invalid Encrypted Key value");
-		pkex->t++;
-		goto fail;
-	}
-	dpp_debug_print_point("DPP: N", group, N);
-	dpp_debug_print_point("DPP: Y'", group, Y);
-
-	pkex->exchange_done = 1;
-
-	/* ECDH: J = a * Y’ */
-	Y_ec = EC_KEY_new();
-	if (!Y_ec ||
-	    EC_KEY_set_group(Y_ec, group) != 1 ||
-	    EC_KEY_set_public_key(Y_ec, Y) != 1)
-		goto fail;
-	pkex->y = EVP_PKEY_new();
-	if (!pkex->y ||
-	    EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1)
-		goto fail;
-	if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0)
-		goto fail;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
-			Jx, Jx_len);
-
-	/* u = HMAC(J.x,  MAC-Initiator | A.x | Y’.x | X.x ) */
-	A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
-	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
-	X_pub = dpp_get_pubkey_point(pkex->x, 0);
-	if (!A_pub || !Y_pub || !X_pub)
-		goto fail;
-	addr[0] = pkex->own_mac;
-	len[0] = ETH_ALEN;
-	addr[1] = wpabuf_head(A_pub);
-	len[1] = wpabuf_len(A_pub) / 2;
-	addr[2] = wpabuf_head(Y_pub);
-	len[2] = wpabuf_len(Y_pub) / 2;
-	addr[3] = wpabuf_head(X_pub);
-	len[3] = wpabuf_len(X_pub) / 2;
-	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
-		goto fail;
-	wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
-
-	/* K = x * Y’ */
-	if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0)
-		goto fail;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
-			Kx, Kx_len);
-
-	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
-	 */
-	res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
-				pkex->Mx, curve->prime_len,
-				attr_key /* N.x */, attr_key_len / 2,
-				pkex->code, Kx, Kx_len,
-				pkex->z, curve->hash_len);
-	os_memset(Kx, 0, Kx_len);
-	if (res < 0)
-		goto fail;
-
-	msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u);
-	if (!msg)
-		goto fail;
-
-out:
-	wpabuf_free(A_pub);
-	wpabuf_free(X_pub);
-	wpabuf_free(Y_pub);
-	EC_POINT_free(Qr);
-	EC_POINT_free(Y);
-	EC_POINT_free(N);
-	BN_free(Nx);
-	BN_free(Ny);
-	EC_KEY_free(Y_ec);
-	BN_CTX_free(bnctx);
-	EC_GROUP_free(group);
-	return msg;
-fail:
-	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed");
-	goto out;
-}
-
-
-static struct wpabuf *
-dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex,
-				  const struct wpabuf *B_pub, const u8 *v)
-{
-	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-	struct wpabuf *msg = NULL;
-	const u8 *addr[2];
-	size_t len[2];
-	u8 octet;
-	u8 *wrapped;
-	struct wpabuf *clear = NULL;
-	size_t clear_len, attr_len;
-
-	/* {B, v [bootstrapping info]}z */
-	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
-	clear = wpabuf_alloc(clear_len);
-	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP)
-		attr_len += 5;
-#endif /* CONFIG_TESTING_OPTIONS */
-	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len);
-	if (!clear || !msg)
-		goto fail;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key");
-		goto skip_bootstrap_key;
-	}
-	if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key");
-		wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
-		wpabuf_put_le16(clear, 2 * curve->prime_len);
-		if (dpp_test_gen_invalid_key(clear, curve) < 0)
-			goto fail;
-		goto skip_bootstrap_key;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* B in Bootstrap Key attribute */
-	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
-	wpabuf_put_le16(clear, wpabuf_len(B_pub));
-	wpabuf_put_buf(clear, B_pub);
-
-#ifdef CONFIG_TESTING_OPTIONS
-skip_bootstrap_key:
-	if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag");
-		goto skip_r_auth_tag;
-	}
-	if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch");
-		wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
-		wpabuf_put_le16(clear, curve->hash_len);
-		wpabuf_put_data(clear, v, curve->hash_len - 1);
-		wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01);
-		goto skip_r_auth_tag;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	/* v in R-Auth tag attribute */
-	wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
-	wpabuf_put_le16(clear, curve->hash_len);
-	wpabuf_put_data(clear, v, curve->hash_len);
-
-#ifdef CONFIG_TESTING_OPTIONS
-skip_r_auth_tag:
-	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
-		goto skip_wrapped_data;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	addr[0] = wpabuf_head_u8(msg) + 2;
-	len[0] = DPP_HDR_LEN;
-	octet = 1;
-	addr[1] = &octet;
-	len[1] = sizeof(octet);
-	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]);
-
-	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(pkex->z, curve->hash_len,
-			    wpabuf_head(clear), wpabuf_len(clear),
-			    2, addr, len, wrapped) < 0)
-		goto fail;
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
-		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) {
-		wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data");
-		dpp_build_attr_status(msg, DPP_STATUS_OK);
-	}
-skip_wrapped_data:
-#endif /* CONFIG_TESTING_OPTIONS */
-
-out:
-	wpabuf_free(clear);
-	return msg;
-
-fail:
-	wpabuf_free(msg);
-	msg = NULL;
-	goto out;
-}
-
-
-struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
-					      const u8 *hdr,
-					      const u8 *buf, size_t buflen)
-{
-	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-	size_t Jx_len, Lx_len;
-	u8 Jx[DPP_MAX_SHARED_SECRET_LEN];
-	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
-	const u8 *wrapped_data, *b_key, *peer_u;
-	u16 wrapped_data_len, b_key_len, peer_u_len = 0;
-	const u8 *addr[4];
-	size_t len[4];
-	u8 octet;
-	u8 *unwrapped = NULL;
-	size_t unwrapped_len = 0;
-	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
-	struct wpabuf *B_pub = NULL;
-	u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN];
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - stop at PKEX CR Request");
-		pkex->failed = 1;
-		return NULL;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (!pkex->exchange_done || pkex->failed ||
-	    pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator)
-		goto fail;
-
-	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
-				    &wrapped_data_len);
-	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
-		dpp_pkex_fail(pkex,
-			      "Missing or invalid required Wrapped Data attribute");
-		goto fail;
-	}
-
-	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;
-
-	addr[0] = hdr;
-	len[0] = DPP_HDR_LEN;
-	octet = 0;
-	addr[1] = &octet;
-	len[1] = sizeof(octet);
-	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]);
-
-	if (aes_siv_decrypt(pkex->z, curve->hash_len,
-			    wrapped_data, wrapped_data_len,
-			    2, addr, len, unwrapped) < 0) {
-		dpp_pkex_fail(pkex,
-			      "AES-SIV decryption failed - possible PKEX code mismatch");
-		pkex->failed = 1;
-		pkex->t++;
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
-		    unwrapped, unwrapped_len);
-
-	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
-		dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data");
-		goto fail;
-	}
-
-	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
-			     &b_key_len);
-	if (!b_key || b_key_len != 2 * curve->prime_len) {
-		dpp_pkex_fail(pkex, "No valid peer bootstrapping key found");
-		goto fail;
-	}
-	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
-							b_key_len);
-	if (!pkex->peer_bootstrap_key) {
-		dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid");
-		goto fail;
-	}
-	dpp_debug_print_key("DPP: Peer bootstrap public key",
-			    pkex->peer_bootstrap_key);
-
-	/* ECDH: J' = y * A' */
-	if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0)
-		goto fail;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
-			Jx, Jx_len);
-
-	/* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */
-	A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
-	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
-	X_pub = dpp_get_pubkey_point(pkex->x, 0);
-	if (!A_pub || !Y_pub || !X_pub)
-		goto fail;
-	addr[0] = pkex->peer_mac;
-	len[0] = ETH_ALEN;
-	addr[1] = wpabuf_head(A_pub);
-	len[1] = wpabuf_len(A_pub) / 2;
-	addr[2] = wpabuf_head(Y_pub);
-	len[2] = wpabuf_len(Y_pub) / 2;
-	addr[3] = wpabuf_head(X_pub);
-	len[3] = wpabuf_len(X_pub) / 2;
-	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
-		goto fail;
-
-	peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
-			      &peer_u_len);
-	if (!peer_u || peer_u_len != curve->hash_len ||
-	    os_memcmp(peer_u, u, curve->hash_len) != 0) {
-		dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found");
-		wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'",
-			    u, curve->hash_len);
-		wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len);
-		pkex->t++;
-		goto fail;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received");
-
-	/* ECDH: L = b * X' */
-	if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0)
-		goto fail;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
-			Lx, Lx_len);
-
-	/* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */
-	B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
-	if (!B_pub)
-		goto fail;
-	addr[0] = pkex->own_mac;
-	len[0] = ETH_ALEN;
-	addr[1] = wpabuf_head(B_pub);
-	len[1] = wpabuf_len(B_pub) / 2;
-	addr[2] = wpabuf_head(X_pub);
-	len[2] = wpabuf_len(X_pub) / 2;
-	addr[3] = wpabuf_head(Y_pub);
-	len[3] = wpabuf_len(Y_pub) / 2;
-	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
-		goto fail;
-	wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
-
-	msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v);
-	if (!msg)
-		goto fail;
-
-out:
-	os_free(unwrapped);
-	wpabuf_free(A_pub);
-	wpabuf_free(B_pub);
-	wpabuf_free(X_pub);
-	wpabuf_free(Y_pub);
-	return msg;
-fail:
-	wpa_printf(MSG_DEBUG,
-		   "DPP: PKEX Commit-Reveal Request processing failed");
-	goto out;
-}
-
-
-int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
-				   const u8 *buf, size_t buflen)
-{
-	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-	const u8 *wrapped_data, *b_key, *peer_v;
-	u16 wrapped_data_len, b_key_len, peer_v_len = 0;
-	const u8 *addr[4];
-	size_t len[4];
-	u8 octet;
-	u8 *unwrapped = NULL;
-	size_t unwrapped_len = 0;
-	int ret = -1;
-	u8 v[DPP_MAX_HASH_LEN];
-	size_t Lx_len;
-	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
-	struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
-
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - stop at PKEX CR Response");
-		pkex->failed = 1;
-		goto fail;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (!pkex->exchange_done || pkex->failed ||
-	    pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator)
-		goto fail;
-
-	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
-				    &wrapped_data_len);
-	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
-		dpp_pkex_fail(pkex,
-			      "Missing or invalid required Wrapped Data attribute");
-		goto fail;
-	}
-
-	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;
-
-	addr[0] = hdr;
-	len[0] = DPP_HDR_LEN;
-	octet = 1;
-	addr[1] = &octet;
-	len[1] = sizeof(octet);
-	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]);
-
-	if (aes_siv_decrypt(pkex->z, curve->hash_len,
-			    wrapped_data, wrapped_data_len,
-			    2, addr, len, unwrapped) < 0) {
-		dpp_pkex_fail(pkex,
-			      "AES-SIV decryption failed - possible PKEX code mismatch");
-		pkex->t++;
-		goto fail;
-	}
-	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
-		    unwrapped, unwrapped_len);
-
-	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
-		dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data");
-		goto fail;
-	}
-
-	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
-			     &b_key_len);
-	if (!b_key || b_key_len != 2 * curve->prime_len) {
-		dpp_pkex_fail(pkex, "No valid peer bootstrapping key found");
-		goto fail;
-	}
-	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
-							b_key_len);
-	if (!pkex->peer_bootstrap_key) {
-		dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid");
-		goto fail;
-	}
-	dpp_debug_print_key("DPP: Peer bootstrap public key",
-			    pkex->peer_bootstrap_key);
-
-	/* ECDH: L' = x * B' */
-	if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0)
-		goto fail;
-
-	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
-			Lx, Lx_len);
-
-	/* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */
-	B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
-	X_pub = dpp_get_pubkey_point(pkex->x, 0);
-	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
-	if (!B_pub || !X_pub || !Y_pub)
-		goto fail;
-	addr[0] = pkex->peer_mac;
-	len[0] = ETH_ALEN;
-	addr[1] = wpabuf_head(B_pub);
-	len[1] = wpabuf_len(B_pub) / 2;
-	addr[2] = wpabuf_head(X_pub);
-	len[2] = wpabuf_len(X_pub) / 2;
-	addr[3] = wpabuf_head(Y_pub);
-	len[3] = wpabuf_len(Y_pub) / 2;
-	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
-		goto fail;
-
-	peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
-			      &peer_v_len);
-	if (!peer_v || peer_v_len != curve->hash_len ||
-	    os_memcmp(peer_v, v, curve->hash_len) != 0) {
-		dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found");
-		wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'",
-			    v, curve->hash_len);
-		wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len);
-		pkex->t++;
-		goto fail;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received");
-
-	ret = 0;
-out:
-	wpabuf_free(B_pub);
-	wpabuf_free(X_pub);
-	wpabuf_free(Y_pub);
-	os_free(unwrapped);
-	return ret;
-fail:
-	goto out;
-}
-
-
-void dpp_pkex_free(struct dpp_pkex *pkex)
-{
-	if (!pkex)
-		return;
-
-	os_free(pkex->identifier);
-	os_free(pkex->code);
-	EVP_PKEY_free(pkex->x);
-	EVP_PKEY_free(pkex->y);
-	EVP_PKEY_free(pkex->peer_bootstrap_key);
-	wpabuf_free(pkex->exchange_req);
-	wpabuf_free(pkex->exchange_resp);
-	os_free(pkex);
-}
-
-
-#ifdef CONFIG_TESTING_OPTIONS
-char * dpp_corrupt_connector_signature(const char *connector)
-{
-	char *tmp, *pos, *signed3 = NULL;
-	unsigned char *signature = NULL;
-	size_t signature_len = 0, signed3_len;
-
-	tmp = os_zalloc(os_strlen(connector) + 5);
-	if (!tmp)
-		goto fail;
-	os_memcpy(tmp, connector, os_strlen(connector));
-
-	pos = os_strchr(tmp, '.');
-	if (!pos)
-		goto fail;
-
-	pos = os_strchr(pos + 1, '.');
-	if (!pos)
-		goto fail;
-	pos++;
-
-	wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
-		   pos);
-	signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
-	if (!signature || signature_len == 0)
-		goto fail;
-	wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
-		    signature, signature_len);
-	signature[signature_len - 1] ^= 0x01;
-	wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
-		    signature, signature_len);
-	signed3 = base64_url_encode(signature, signature_len, &signed3_len);
-	if (!signed3)
-		goto fail;
-	os_memcpy(pos, signed3, signed3_len);
-	pos[signed3_len] = '\0';
-	wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s",
-		   pos);
-
-out:
-	os_free(signature);
-	os_free(signed3);
-	return tmp;
-fail:
-	os_free(tmp);
-	tmp = NULL;
-	goto out;
-}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-
-#ifdef CONFIG_DPP2
-
-struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
-			      size_t net_access_key_len)
-{
-	struct wpabuf *pub = NULL;
-	EVP_PKEY *own_key;
-	struct dpp_pfs *pfs;
-
-	pfs = os_zalloc(sizeof(*pfs));
-	if (!pfs)
-		return NULL;
-
-	own_key = dpp_set_keypair(&pfs->curve, net_access_key,
-				  net_access_key_len);
-	if (!own_key) {
-		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
-		goto fail;
-	}
-	EVP_PKEY_free(own_key);
-
-	pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
-	if (!pfs->ecdh)
-		goto fail;
-
-	pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0);
-	pub = wpabuf_zeropad(pub, pfs->curve->prime_len);
-	if (!pub)
-		goto fail;
-
-	pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub));
-	if (!pfs->ie)
-		goto fail;
-	wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION);
-	wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub));
-	wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM);
-	wpabuf_put_le16(pfs->ie, pfs->curve->ike_group);
-	wpabuf_put_buf(pfs->ie, pub);
-	wpabuf_free(pub);
-	wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element",
-			pfs->ie);
-
-	return pfs;
-fail:
-	wpabuf_free(pub);
-	dpp_pfs_free(pfs);
-	return NULL;
-}
-
-
-int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len)
-{
-	if (peer_ie_len < 2)
-		return -1;
-	if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) {
-		wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS");
-		return -1;
-	}
-
-	pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2,
-					      peer_ie_len - 2);
-	pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len);
-	if (!pfs->secret) {
-		wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key");
-		return -1;
-	}
-	wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret);
-	return 0;
-}
-
-
-void dpp_pfs_free(struct dpp_pfs *pfs)
-{
-	if (!pfs)
-		return;
-	crypto_ecdh_deinit(pfs->ecdh);
-	wpabuf_free(pfs->ie);
-	wpabuf_clear_free(pfs->secret);
-	os_free(pfs);
-}
-
-#endif /* CONFIG_DPP2 */
-
-
-static unsigned int dpp_next_id(struct dpp_global *dpp)
+unsigned int dpp_next_id(struct dpp_global *dpp)
 {
 	struct dpp_bootstrap_info *bi;
 	unsigned int max_id = 0;
@@ -10527,33 +3638,6 @@
 }
 
 
-struct dpp_bootstrap_info *
-dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer,
-		unsigned int freq)
-{
-	struct dpp_bootstrap_info *bi;
-
-	bi = os_zalloc(sizeof(*bi));
-	if (!bi)
-		return NULL;
-	bi->id = dpp_next_id(dpp);
-	bi->type = DPP_BOOTSTRAP_PKEX;
-	os_memcpy(bi->mac_addr, peer, ETH_ALEN);
-	bi->num_freq = 1;
-	bi->freq[0] = freq;
-	bi->curve = pkex->own_bi->curve;
-	bi->pubkey = pkex->peer_bootstrap_key;
-	pkex->peer_bootstrap_key = NULL;
-	if (dpp_bootstrap_key_hash(bi) < 0) {
-		dpp_bootstrap_info_free(bi);
-		return NULL;
-	}
-	dpp_pkex_free(pkex);
-	dl_list_add(&dpp->bootstrap, &bi->list);
-	return bi;
-}
-
-
 const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id)
 {
 	struct dpp_bootstrap_info *bi;
@@ -10582,14 +3666,16 @@
 			   "num_freq=%u\n"
 			   "use_freq=%u\n"
 			   "curve=%s\n"
-			   "pkhash=%s\n",
+			   "pkhash=%s\n"
+			   "version=%d\n",
 			   dpp_bootstrap_type_txt(bi->type),
 			   MAC2STR(bi->mac_addr),
 			   bi->info ? bi->info : "",
 			   bi->num_freq,
 			   bi->num_freq == 1 ? bi->freq[0] : 0,
 			   bi->curve->name,
-			   pkhash);
+			   pkhash,
+			   bi->version);
 }
 
 
@@ -10897,68 +3983,20 @@
 }
 
 
-static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
-							   void *timeout_ctx);
-
-
-static void dpp_connection_free(struct dpp_connection *conn)
+struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp,
+						    const u8 *kid)
 {
-	if (conn->sock >= 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d",
-			   conn->sock);
-		eloop_unregister_sock(conn->sock, EVENT_TYPE_READ);
-		eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
-		close(conn->sock);
-	}
-	eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout,
-			     conn, NULL);
-	wpabuf_free(conn->msg);
-	wpabuf_free(conn->msg_out);
-	dpp_auth_deinit(conn->auth);
-	os_free(conn);
-}
-
-
-static void dpp_connection_remove(struct dpp_connection *conn)
-{
-	dl_list_del(&conn->list);
-	dpp_connection_free(conn);
-}
-
-
-static void dpp_tcp_init_flush(struct dpp_global *dpp)
-{
-	struct dpp_connection *conn, *tmp;
-
-	dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection,
-			      list)
-		dpp_connection_remove(conn);
-}
-
-
-static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl)
-{
-	struct dpp_connection *conn, *tmp;
-
-	dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
-			      list)
-		dpp_connection_remove(conn);
-	os_free(ctrl);
-}
-
-
-static void dpp_relay_flush_controllers(struct dpp_global *dpp)
-{
-	struct dpp_relay_controller *ctrl, *tmp;
+	struct dpp_configurator *conf;
 
 	if (!dpp)
-		return;
+		return NULL;
 
-	dl_list_for_each_safe(ctrl, tmp, &dpp->controllers,
-			      struct dpp_relay_controller, list) {
-		dl_list_del(&ctrl->list);
-		dpp_relay_controller_free(ctrl);
+	dl_list_for_each(conf, &dpp->configurator,
+			 struct dpp_configurator, list) {
+		if (os_memcmp(conf->kid_hash, kid, SHA256_MAC_LEN) == 0)
+			return conf;
 	}
+	return NULL;
 }
 
 #endif /* CONFIG_DPP2 */
@@ -11012,1301 +4050,6 @@
 
 
 #ifdef CONFIG_DPP2
-
-static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
-static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
-static void dpp_controller_auth_success(struct dpp_connection *conn,
-					int initiator);
-
-
-int dpp_relay_add_controller(struct dpp_global *dpp,
-			     struct dpp_relay_config *config)
-{
-	struct dpp_relay_controller *ctrl;
-
-	if (!dpp)
-		return -1;
-
-	ctrl = os_zalloc(sizeof(*ctrl));
-	if (!ctrl)
-		return -1;
-	dl_list_init(&ctrl->conn);
-	ctrl->global = dpp;
-	os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr));
-	os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN);
-	ctrl->cb_ctx = config->cb_ctx;
-	ctrl->tx = config->tx;
-	ctrl->gas_resp_tx = config->gas_resp_tx;
-	dl_list_add(&dpp->controllers, &ctrl->list);
-	return 0;
-}
-
-
-static struct dpp_relay_controller *
-dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash)
-{
-	struct dpp_relay_controller *ctrl;
-
-	if (!dpp)
-		return NULL;
-
-	dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
-			 list) {
-		if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0)
-			return ctrl;
-	}
-
-	return NULL;
-}
-
-
-static void dpp_controller_gas_done(struct dpp_connection *conn)
-{
-	struct dpp_authentication *auth = conn->auth;
-
-	if (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;
-		return;
-	}
-
-	wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
-	dpp_connection_remove(conn);
-}
-
-
-static int dpp_tcp_send(struct dpp_connection *conn)
-{
-	int res;
-
-	if (!conn->msg_out) {
-		eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
-		conn->write_eloop = 0;
-		return -1;
-	}
-	res = send(conn->sock,
-		   wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos,
-		   wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0);
-	if (res < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s",
-			   strerror(errno));
-		dpp_connection_remove(conn);
-		return -1;
-	}
-
-	conn->msg_out_pos += res;
-	if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: %u/%u bytes of message sent to Controller",
-			   (unsigned int) conn->msg_out_pos,
-			   (unsigned int) wpabuf_len(conn->msg_out));
-		if (!conn->write_eloop &&
-		    eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
-					dpp_conn_tx_ready, conn, NULL) == 0)
-			conn->write_eloop = 1;
-		return 1;
-	}
-
-	wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP");
-	wpabuf_free(conn->msg_out);
-	conn->msg_out = NULL;
-	conn->msg_out_pos = 0;
-	eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
-	conn->write_eloop = 0;
-	if (!conn->read_eloop &&
-	    eloop_register_sock(conn->sock, EVENT_TYPE_READ,
-				dpp_controller_rx, conn, NULL) == 0)
-		conn->read_eloop = 1;
-	if (conn->on_tcp_tx_complete_remove) {
-		dpp_connection_remove(conn);
-	} else if (conn->ctrl && conn->on_tcp_tx_complete_gas_done &&
-		   conn->auth) {
-		dpp_controller_gas_done(conn);
-	} else if (conn->on_tcp_tx_complete_auth_ok) {
-		conn->on_tcp_tx_complete_auth_ok = 0;
-		dpp_controller_auth_success(conn, 1);
-	}
-
-	return 0;
-}
-
-
-static int dpp_tcp_send_msg(struct dpp_connection *conn,
-			    const struct wpabuf *msg)
-{
-	wpabuf_free(conn->msg_out);
-	conn->msg_out_pos = 0;
-	conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1);
-	if (!conn->msg_out)
-		return -1;
-	wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1);
-	wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1,
-			wpabuf_len(msg) - 1);
-
-	if (dpp_tcp_send(conn) == 1) {
-		if (!conn->write_eloop) {
-			if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
-						dpp_conn_tx_ready,
-						conn, NULL) < 0)
-				return -1;
-			conn->write_eloop = 1;
-		}
-	}
-
-	return 0;
-}
-
-
-static void dpp_controller_start_gas_client(struct dpp_connection *conn)
-{
-	struct dpp_authentication *auth = conn->auth;
-	struct wpabuf *buf;
-	int netrole_ap = 0; /* TODO: make this configurable */
-
-	buf = dpp_build_conf_req_helper(auth, "Test", netrole_ap, NULL, NULL);
-	if (!buf) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No configuration request data available");
-		return;
-	}
-
-	dpp_tcp_send_msg(conn, buf);
-	wpabuf_free(buf);
-}
-
-
-static void dpp_controller_auth_success(struct dpp_connection *conn,
-					int initiator)
-{
-	struct dpp_authentication *auth = conn->auth;
-
-	if (!auth)
-		return;
-
-	wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
-	wpa_msg(conn->global->msg_ctx, MSG_INFO,
-		DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
-#ifdef CONFIG_TESTING_OPTIONS
-	if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
-		wpa_printf(MSG_INFO,
-			   "DPP: TESTING - stop at Authentication Confirm");
-		if (auth->configurator) {
-			/* Prevent GAS response */
-			auth->auth_success = 0;
-		}
-		return;
-	}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-	if (!auth->configurator)
-		dpp_controller_start_gas_client(conn);
-}
-
-
-static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
-{
-	struct dpp_connection *conn = eloop_ctx;
-
-	wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock);
-	dpp_tcp_send(conn);
-}
-
-
-static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen,
-				  const struct hostapd_ip_addr *ipaddr,
-				  int port)
-{
-	struct sockaddr_in *dst;
-#ifdef CONFIG_IPV6
-	struct sockaddr_in6 *dst6;
-#endif /* CONFIG_IPV6 */
-
-	switch (ipaddr->af) {
-	case AF_INET:
-		dst = (struct sockaddr_in *) addr;
-		os_memset(dst, 0, sizeof(*dst));
-		dst->sin_family = AF_INET;
-		dst->sin_addr.s_addr = ipaddr->u.v4.s_addr;
-		dst->sin_port = htons(port);
-		*addrlen = sizeof(*dst);
-		break;
-#ifdef CONFIG_IPV6
-	case AF_INET6:
-		dst6 = (struct sockaddr_in6 *) addr;
-		os_memset(dst6, 0, sizeof(*dst6));
-		dst6->sin6_family = AF_INET6;
-		os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6,
-			  sizeof(struct in6_addr));
-		dst6->sin6_port = htons(port);
-		*addrlen = sizeof(*dst6);
-		break;
-#endif /* CONFIG_IPV6 */
-	default:
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static struct dpp_connection *
-dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src,
-		   unsigned int freq)
-{
-	struct dpp_connection *conn;
-	struct sockaddr_storage addr;
-	socklen_t addrlen;
-	char txt[100];
-
-	if (dl_list_len(&ctrl->conn) >= 15) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one");
-		return NULL;
-	}
-
-	if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen,
-				   &ctrl->ipaddr, DPP_TCP_PORT) < 0)
-		return NULL;
-
-	conn = os_zalloc(sizeof(*conn));
-	if (!conn)
-		return NULL;
-
-	conn->global = ctrl->global;
-	conn->relay = ctrl;
-	os_memcpy(conn->mac_addr, src, ETH_ALEN);
-	conn->freq = freq;
-
-	conn->sock = socket(AF_INET, SOCK_STREAM, 0);
-	if (conn->sock < 0)
-		goto fail;
-	wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s",
-		   conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
-
-	if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
-		wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
-			   strerror(errno));
-		goto fail;
-	}
-
-	if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) {
-		if (errno != EINPROGRESS) {
-			wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
-				   strerror(errno));
-			goto fail;
-		}
-
-		/*
-		 * Continue connecting in the background; eloop will call us
-		 * once the connection is ready (or failed).
-		 */
-	}
-
-	if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
-				dpp_conn_tx_ready, conn, NULL) < 0)
-		goto fail;
-	conn->write_eloop = 1;
-
-	/* TODO: eloop timeout to clear a connection if it does not complete
-	 * properly */
-
-	dl_list_add(&ctrl->conn, &conn->list);
-	return conn;
-fail:
-	dpp_connection_free(conn);
-	return NULL;
-}
-
-
-static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len)
-{
-	struct wpabuf *msg;
-
-	msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len);
-	if (!msg)
-		return NULL;
-	wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len);
-	wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
-	wpabuf_put_data(msg, hdr, DPP_HDR_LEN);
-	wpabuf_put_data(msg, buf, len);
-	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
-	return msg;
-}
-
-
-static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr,
-			const u8 *buf, size_t len)
-{
-	u8 type = hdr[DPP_HDR_LEN - 1];
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Continue already established Relay/Controller connection for this session");
-	wpabuf_free(conn->msg_out);
-	conn->msg_out_pos = 0;
-	conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
-	if (!conn->msg_out) {
-		dpp_connection_remove(conn);
-		return -1;
-	}
-
-	/* TODO: for proto ver 1, need to do remove connection based on GAS Resp
-	 * TX status */
-	if (type == DPP_PA_CONFIGURATION_RESULT)
-		conn->on_tcp_tx_complete_remove = 1;
-	dpp_tcp_send(conn);
-	return 0;
-}
-
-
-int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
-			const u8 *buf, size_t len, unsigned int freq,
-			const u8 *i_bootstrap, const u8 *r_bootstrap)
-{
-	struct dpp_relay_controller *ctrl;
-	struct dpp_connection *conn;
-	u8 type = hdr[DPP_HDR_LEN - 1];
-
-	/* Check if there is an already started session for this peer and if so,
-	 * continue that session (send this over TCP) and return 0.
-	 */
-	if (type != DPP_PA_PEER_DISCOVERY_REQ &&
-	    type != DPP_PA_PEER_DISCOVERY_RESP &&
-	    type != DPP_PA_PRESENCE_ANNOUNCEMENT) {
-		dl_list_for_each(ctrl, &dpp->controllers,
-				 struct dpp_relay_controller, list) {
-			dl_list_for_each(conn, &ctrl->conn,
-					 struct dpp_connection, list) {
-				if (os_memcmp(src, conn->mac_addr,
-					      ETH_ALEN) == 0)
-					return dpp_relay_tx(conn, hdr, buf, len);
-			}
-		}
-	}
-
-	if (!r_bootstrap)
-		return -1;
-
-	if (type == DPP_PA_PRESENCE_ANNOUNCEMENT) {
-		/* TODO: Could send this to all configured Controllers. For now,
-		 * only the first Controller is supported. */
-		ctrl = dl_list_first(&dpp->controllers,
-				     struct dpp_relay_controller, list);
-	} else {
-		ctrl = dpp_relay_controller_get(dpp, r_bootstrap);
-	}
-	if (!ctrl)
-		return -1;
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Authentication Request for a configured Controller");
-	conn = dpp_relay_new_conn(ctrl, src, freq);
-	if (!conn)
-		return -1;
-
-	conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
-	if (!conn->msg_out) {
-		dpp_connection_remove(conn);
-		return -1;
-	}
-	/* Message will be sent in dpp_conn_tx_ready() */
-
-	return 0;
-}
-
-
-int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
-			 size_t data_len)
-{
-	struct dpp_relay_controller *ctrl;
-	struct dpp_connection *conn, *found = NULL;
-	struct wpabuf *msg;
-
-	/* Check if there is a successfully completed authentication for this
-	 * and if so, continue that session (send this over TCP) and return 0.
-	 */
-	dl_list_for_each(ctrl, &dpp->controllers,
-			 struct dpp_relay_controller, list) {
-		if (found)
-			break;
-		dl_list_for_each(conn, &ctrl->conn,
-				 struct dpp_connection, list) {
-			if (os_memcmp(src, conn->mac_addr,
-				      ETH_ALEN) == 0) {
-				found = conn;
-				break;
-			}
-		}
-	}
-
-	if (!found)
-		return -1;
-
-	msg = wpabuf_alloc(4 + 1 + data_len);
-	if (!msg)
-		return -1;
-	wpabuf_put_be32(msg, 1 + data_len);
-	wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ);
-	wpabuf_put_data(msg, data, data_len);
-	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
-
-	wpabuf_free(conn->msg_out);
-	conn->msg_out_pos = 0;
-	conn->msg_out = msg;
-	dpp_tcp_send(conn);
-	return 0;
-}
-
-
-static void dpp_controller_free(struct dpp_controller *ctrl)
-{
-	struct dpp_connection *conn, *tmp;
-
-	if (!ctrl)
-		return;
-
-	dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
-			      list)
-		dpp_connection_remove(conn);
-
-	if (ctrl->sock >= 0) {
-		close(ctrl->sock);
-		eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
-	}
-	os_free(ctrl->configurator_params);
-	os_free(ctrl);
-}
-
-
-static int dpp_controller_rx_auth_req(struct dpp_connection *conn,
-				      const u8 *hdr, const u8 *buf, size_t len)
-{
-	const u8 *r_bootstrap, *i_bootstrap;
-	u16 r_bootstrap_len, i_bootstrap_len;
-	struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
-
-	if (!conn->ctrl)
-		return 0;
-
-	wpa_printf(MSG_DEBUG, "DPP: Authentication Request");
-
-	r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
-				   &r_bootstrap_len);
-	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
-		wpa_printf(MSG_INFO,
-			   "Missing or invalid required Responder Bootstrapping Key Hash attribute");
-		return -1;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
-		    r_bootstrap, r_bootstrap_len);
-
-	i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
-				   &i_bootstrap_len);
-	if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
-		wpa_printf(MSG_INFO,
-			   "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
-		return -1;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
-		    i_bootstrap, i_bootstrap_len);
-
-	/* Try to find own and peer bootstrapping key matches based on the
-	 * received hash values */
-	dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap,
-				&own_bi, &peer_bi);
-	if (!own_bi) {
-		wpa_printf(MSG_INFO,
-			"No matching own bootstrapping key found - ignore message");
-		return -1;
-	}
-
-	if (conn->auth) {
-		wpa_printf(MSG_INFO,
-			   "Already in DPP authentication exchange - ignore new one");
-		return 0;
-	}
-
-	conn->auth = dpp_auth_req_rx(conn->ctrl->global,
-				     conn->ctrl->global->msg_ctx,
-				     conn->ctrl->allowed_roles,
-				     conn->ctrl->qr_mutual,
-				     peer_bi, own_bi, -1, hdr, buf, len);
-	if (!conn->auth) {
-		wpa_printf(MSG_DEBUG, "DPP: No response generated");
-		return -1;
-	}
-
-	if (dpp_set_configurator(conn->auth,
-				 conn->ctrl->configurator_params) < 0) {
-		dpp_connection_remove(conn);
-		return -1;
-	}
-
-	return dpp_tcp_send_msg(conn, conn->auth->resp_msg);
-}
-
-
-static int dpp_controller_rx_auth_resp(struct dpp_connection *conn,
-				       const u8 *hdr, const u8 *buf, size_t len)
-{
-	struct dpp_authentication *auth = conn->auth;
-	struct wpabuf *msg;
-	int res;
-
-	if (!auth)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "DPP: Authentication Response");
-
-	msg = dpp_auth_resp_rx(auth, hdr, buf, len);
-	if (!msg) {
-		if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Start wait for full response");
-			return -1;
-		}
-		wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
-		dpp_connection_remove(conn);
-		return -1;
-	}
-
-	conn->on_tcp_tx_complete_auth_ok = 1;
-	res = dpp_tcp_send_msg(conn, msg);
-	wpabuf_free(msg);
-	return res;
-}
-
-
-static int dpp_controller_rx_auth_conf(struct dpp_connection *conn,
-				       const u8 *hdr, const u8 *buf, size_t len)
-{
-	struct dpp_authentication *auth = conn->auth;
-
-	wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation");
-
-	if (!auth) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No DPP Authentication in progress - drop");
-		return -1;
-	}
-
-	if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
-		return -1;
-	}
-
-	dpp_controller_auth_success(conn, 0);
-	return 0;
-}
-
-
-static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
-							   void *timeout_ctx)
-{
-	struct dpp_connection *conn = eloop_ctx;
-
-	if (!conn->auth->waiting_conf_result)
-		return;
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Timeout while waiting for Connection Status Result");
-	wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
-		DPP_EVENT_CONN_STATUS_RESULT "timeout");
-	dpp_connection_remove(conn);
-}
-
-
-static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
-					 const u8 *hdr, const u8 *buf,
-					 size_t len)
-{
-	struct dpp_authentication *auth = conn->auth;
-	enum dpp_status_error status;
-
-	if (!conn->ctrl)
-		return 0;
-
-	wpa_printf(MSG_DEBUG, "DPP: Configuration Result");
-
-	if (!auth || !auth->waiting_conf_result) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No DPP Configuration waiting for result - drop");
-		return -1;
-	}
-
-	status = dpp_conf_result_rx(auth, hdr, buf, len);
-	if (status == DPP_STATUS_OK && auth->send_conn_status) {
-		wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
-			DPP_EVENT_CONF_SENT "wait_conn_status=1");
-		wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
-		eloop_cancel_timeout(
-			dpp_controller_conn_status_result_wait_timeout,
-			conn, NULL);
-		eloop_register_timeout(
-			16, 0, dpp_controller_conn_status_result_wait_timeout,
-			conn, NULL);
-		return 0;
-	}
-	if (status == DPP_STATUS_OK)
-		wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
-			DPP_EVENT_CONF_SENT);
-	else
-		wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
-			DPP_EVENT_CONF_FAILED);
-	return -1; /* to remove the completed connection */
-}
-
-
-static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn,
-						const u8 *hdr, const u8 *buf,
-						size_t len)
-{
-	struct dpp_authentication *auth = conn->auth;
-	enum dpp_status_error status;
-	u8 ssid[SSID_MAX_LEN];
-	size_t ssid_len = 0;
-	char *channel_list = NULL;
-
-	if (!conn->ctrl)
-		return 0;
-
-	wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
-
-	if (!auth || !auth->waiting_conn_status_result) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No DPP Configuration waiting for connection status result - drop");
-		return -1;
-	}
-
-	status = dpp_conn_status_result_rx(auth, hdr, buf, len,
-					   ssid, &ssid_len, &channel_list);
-	wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
-		DPP_EVENT_CONN_STATUS_RESULT
-		"result=%d ssid=%s channel_list=%s",
-		status, wpa_ssid_txt(ssid, ssid_len),
-		channel_list ? channel_list : "N/A");
-	os_free(channel_list);
-	return -1; /* to remove the completed connection */
-}
-
-
-static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn,
-						   const u8 *hdr, const u8 *buf,
-						   size_t len)
-{
-	const u8 *r_bootstrap;
-	u16 r_bootstrap_len;
-	struct dpp_bootstrap_info *peer_bi;
-	struct dpp_authentication *auth;
-	struct dpp_global *dpp = conn->ctrl->global;
-
-	if (conn->auth) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Ignore Presence Announcement during ongoing Authentication");
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "DPP: Presence Announcement");
-
-	r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
-				   &r_bootstrap_len);
-	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
-		wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
-			"Missing or invalid required Responder Bootstrapping Key Hash attribute");
-		return -1;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
-		    r_bootstrap, r_bootstrap_len);
-	peer_bi = dpp_bootstrap_find_chirp(dpp, r_bootstrap);
-	if (!peer_bi) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No matching bootstrapping information found");
-		return -1;
-	}
-
-	auth = dpp_auth_init(dpp, dpp->msg_ctx, peer_bi, NULL,
-			     DPP_CAPAB_CONFIGURATOR, -1, NULL, 0);
-	if (!auth)
-		return -1;
-	if (dpp_set_configurator(conn->auth,
-				 conn->ctrl->configurator_params) < 0) {
-		dpp_auth_deinit(auth);
-		dpp_connection_remove(conn);
-		return -1;
-	}
-
-	conn->auth = auth;
-	return dpp_tcp_send_msg(conn, conn->auth->req_msg);
-}
-
-
-static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
-				    size_t len)
-{
-	const u8 *pos, *end;
-	u8 type;
-
-	wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP");
-	pos = msg;
-	end = msg + len;
-
-	if (end - pos < DPP_HDR_LEN ||
-	    WPA_GET_BE24(pos) != OUI_WFA ||
-	    pos[3] != DPP_OUI_TYPE) {
-		wpa_printf(MSG_DEBUG, "DPP: Unrecognized header");
-		return -1;
-	}
-
-	if (pos[4] != 1) {
-		wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u",
-			   pos[4]);
-		return -1;
-	}
-	type = pos[5];
-	wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type);
-	pos += DPP_HDR_LEN;
-
-	wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes",
-		    pos, end - pos);
-	if (dpp_check_attrs(pos, end - pos) < 0)
-		return -1;
-
-	if (conn->relay) {
-		wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
-		conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr,
-				conn->freq, msg, len);
-		return 0;
-	}
-
-	switch (type) {
-	case DPP_PA_AUTHENTICATION_REQ:
-		return dpp_controller_rx_auth_req(conn, msg, pos, end - pos);
-	case DPP_PA_AUTHENTICATION_RESP:
-		return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos);
-	case DPP_PA_AUTHENTICATION_CONF:
-		return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos);
-	case DPP_PA_CONFIGURATION_RESULT:
-		return dpp_controller_rx_conf_result(conn, msg, pos, end - pos);
-	case DPP_PA_CONNECTION_STATUS_RESULT:
-		return dpp_controller_rx_conn_status_result(conn, msg, pos,
-							    end - pos);
-	case DPP_PA_PRESENCE_ANNOUNCEMENT:
-		return dpp_controller_rx_presence_announcement(conn, msg, pos,
-							       end - pos);
-	default:
-		/* TODO: missing messages types */
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Unsupported frame subtype %d", type);
-		return -1;
-	}
-}
-
-
-static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg,
-				     size_t len)
-{
-	const u8 *pos, *end, *next;
-	u8 dialog_token;
-	const u8 *adv_proto;
-	u16 slen;
-	struct wpabuf *resp, *buf;
-	struct dpp_authentication *auth = conn->auth;
-
-	if (len < 1 + 2)
-		return -1;
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Received DPP Configuration Request over TCP");
-
-	if (!conn->ctrl || !auth || !auth->auth_success) {
-		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
-		return -1;
-	}
-
-	pos = msg;
-	end = msg + len;
-
-	dialog_token = *pos++;
-	adv_proto = pos++;
-	slen = *pos++;
-	if (*adv_proto != WLAN_EID_ADV_PROTO ||
-	    slen > end - pos || slen < 2)
-		return -1;
-
-	next = pos + slen;
-	pos++; /* skip QueryRespLenLimit and PAME-BI */
-
-	if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
-	    pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
-	    pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
-		return -1;
-
-	pos = next;
-	/* Query Request */
-	if (end - pos < 2)
-		return -1;
-	slen = WPA_GET_LE16(pos);
-	pos += 2;
-	if (slen > end - pos)
-		return -1;
-
-	resp = dpp_conf_req_rx(auth, pos, slen);
-	if (!resp)
-		return -1;
-
-	buf = wpabuf_alloc(4 + 18 + wpabuf_len(resp));
-	if (!buf) {
-		wpabuf_free(resp);
-		return -1;
-	}
-
-	wpabuf_put_be32(buf, 18 + wpabuf_len(resp));
-
-	wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP);
-	wpabuf_put_u8(buf, dialog_token);
-	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
-	wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */
-
-	dpp_write_adv_proto(buf);
-	dpp_write_gas_query(buf, resp);
-	wpabuf_free(resp);
-
-	/* Send Config Response over TCP; GAS fragmentation is taken care of by
-	 * the Relay */
-	wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf);
-	wpabuf_free(conn->msg_out);
-	conn->msg_out_pos = 0;
-	conn->msg_out = buf;
-	conn->on_tcp_tx_complete_gas_done = 1;
-	dpp_tcp_send(conn);
-	return 0;
-}
-
-
-static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
-{
-	struct dpp_authentication *auth = conn->auth;
-	int res;
-	struct wpabuf *msg;
-	enum dpp_status_error status;
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Configuration Response for local stack from TCP");
-
-	res = dpp_conf_resp_rx(auth, resp);
-	wpabuf_free(resp);
-	if (res < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
-		return -1;
-	}
-
-	if (conn->global->process_conf_obj)
-		res = conn->global->process_conf_obj(conn->global->cb_ctx,
-						     auth);
-	else
-		res = 0;
-
-	if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
-	status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK;
-	msg = dpp_build_conf_result(auth, status);
-	if (!msg)
-		return -1;
-
-	conn->on_tcp_tx_complete_remove = 1;
-	res = dpp_tcp_send_msg(conn, msg);
-	wpabuf_free(msg);
-
-	/* This exchange will be terminated in the TX status handler */
-
-	return res;
-}
-
-
-static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg,
-			   size_t len)
-{
-	struct wpabuf *buf;
-	u8 dialog_token;
-	const u8 *pos, *end, *next, *adv_proto;
-	u16 status, slen;
-
-	if (len < 5 + 2)
-		return -1;
-
-	wpa_printf(MSG_DEBUG,
-		   "DPP: Received DPP Configuration Response over TCP");
-
-	pos = msg;
-	end = msg + len;
-
-	dialog_token = *pos++;
-	status = WPA_GET_LE16(pos);
-	if (status != WLAN_STATUS_SUCCESS) {
-		wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status);
-		return -1;
-	}
-	pos += 2;
-	pos += 2; /* ignore GAS Comeback Delay */
-
-	adv_proto = pos++;
-	slen = *pos++;
-	if (*adv_proto != WLAN_EID_ADV_PROTO ||
-	    slen > end - pos || slen < 2)
-		return -1;
-
-	next = pos + slen;
-	pos++; /* skip QueryRespLenLimit and PAME-BI */
-
-	if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
-	    pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
-	    pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
-		return -1;
-
-	pos = next;
-	/* Query Response */
-	if (end - pos < 2)
-		return -1;
-	slen = WPA_GET_LE16(pos);
-	pos += 2;
-	if (slen > end - pos)
-		return -1;
-
-	buf = wpabuf_alloc(slen);
-	if (!buf)
-		return -1;
-	wpabuf_put_data(buf, pos, slen);
-
-	if (!conn->relay && !conn->ctrl)
-		return dpp_tcp_rx_gas_resp(conn, buf);
-
-	if (!conn->relay) {
-		wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
-		wpabuf_free(buf);
-		return -1;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
-	conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr,
-				 dialog_token, 0, buf);
-
-	return 0;
-}
-
-
-static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx)
-{
-	struct dpp_connection *conn = eloop_ctx;
-	int res;
-	const u8 *pos;
-
-	wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)",
-		   sd);
-
-	if (conn->msg_len_octets < 4) {
-		u32 msglen;
-
-		res = recv(sd, &conn->msg_len[conn->msg_len_octets],
-			   4 - conn->msg_len_octets, 0);
-		if (res < 0) {
-			wpa_printf(MSG_DEBUG, "DPP: recv failed: %s",
-				   strerror(errno));
-			dpp_connection_remove(conn);
-			return;
-		}
-		if (res == 0) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: No more data available over TCP");
-			dpp_connection_remove(conn);
-			return;
-		}
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Received %d/%d octet(s) of message length field",
-			   res, (int) (4 - conn->msg_len_octets));
-		conn->msg_len_octets += res;
-
-		if (conn->msg_len_octets < 4) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Need %d more octets of message length field",
-				   (int) (4 - conn->msg_len_octets));
-			return;
-		}
-
-		msglen = WPA_GET_BE32(conn->msg_len);
-		wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen);
-		if (msglen > 65535) {
-			wpa_printf(MSG_INFO, "DPP: Unexpectedly long message");
-			dpp_connection_remove(conn);
-			return;
-		}
-
-		wpabuf_free(conn->msg);
-		conn->msg = wpabuf_alloc(msglen);
-	}
-
-	if (!conn->msg) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No buffer available for receiving the message");
-		dpp_connection_remove(conn);
-		return;
-	}
-
-	wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload",
-		   (unsigned int) wpabuf_tailroom(conn->msg));
-
-	res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0);
-	if (res < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno));
-		dpp_connection_remove(conn);
-		return;
-	}
-	if (res == 0) {
-		wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP");
-		dpp_connection_remove(conn);
-		return;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res);
-	wpabuf_put(conn->msg, res);
-
-	if (wpabuf_tailroom(conn->msg) > 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Need %u more octets of message payload",
-			   (unsigned int) wpabuf_tailroom(conn->msg));
-		return;
-	}
-
-	conn->msg_len_octets = 0;
-	wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg);
-	if (wpabuf_len(conn->msg) < 1) {
-		dpp_connection_remove(conn);
-		return;
-	}
-
-	pos = wpabuf_head(conn->msg);
-	switch (*pos) {
-	case WLAN_PA_VENDOR_SPECIFIC:
-		if (dpp_controller_rx_action(conn, pos + 1,
-					     wpabuf_len(conn->msg) - 1) < 0)
-			dpp_connection_remove(conn);
-		break;
-	case WLAN_PA_GAS_INITIAL_REQ:
-		if (dpp_controller_rx_gas_req(conn, pos + 1,
-					      wpabuf_len(conn->msg) - 1) < 0)
-			dpp_connection_remove(conn);
-		break;
-	case WLAN_PA_GAS_INITIAL_RESP:
-		if (dpp_rx_gas_resp(conn, pos + 1,
-				    wpabuf_len(conn->msg) - 1) < 0)
-			dpp_connection_remove(conn);
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u",
-			   *pos);
-		break;
-	}
-}
-
-
-static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
-{
-	struct dpp_controller *ctrl = eloop_ctx;
-	struct sockaddr_in addr;
-	socklen_t addr_len = sizeof(addr);
-	int fd;
-	struct dpp_connection *conn;
-
-	wpa_printf(MSG_DEBUG, "DPP: New TCP connection");
-
-	fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len);
-	if (fd < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Failed to accept new connection: %s",
-			   strerror(errno));
-		return;
-	}
-	wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d",
-		   inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
-
-	conn = os_zalloc(sizeof(*conn));
-	if (!conn)
-		goto fail;
-
-	conn->global = ctrl->global;
-	conn->ctrl = ctrl;
-	conn->sock = fd;
-
-	if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
-		wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
-			   strerror(errno));
-		goto fail;
-	}
-
-	if (eloop_register_sock(conn->sock, EVENT_TYPE_READ,
-				dpp_controller_rx, conn, NULL) < 0)
-		goto fail;
-	conn->read_eloop = 1;
-
-	/* TODO: eloop timeout to expire connections that do not complete in
-	 * reasonable time */
-	dl_list_add(&ctrl->conn, &conn->list);
-	return;
-
-fail:
-	close(fd);
-	os_free(conn);
-}
-
-
-int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
-		 const struct hostapd_ip_addr *addr, int port)
-{
-	struct dpp_connection *conn;
-	struct sockaddr_storage saddr;
-	socklen_t addrlen;
-	const u8 *hdr, *pos, *end;
-	char txt[100];
-
-	wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
-		   hostapd_ip_txt(addr, txt, sizeof(txt)), port);
-	if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
-				   addr, port) < 0) {
-		dpp_auth_deinit(auth);
-		return -1;
-	}
-
-	conn = os_zalloc(sizeof(*conn));
-	if (!conn) {
-		dpp_auth_deinit(auth);
-		return -1;
-	}
-
-	conn->global = dpp;
-	conn->auth = auth;
-	conn->sock = socket(AF_INET, SOCK_STREAM, 0);
-	if (conn->sock < 0)
-		goto fail;
-
-	if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
-		wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
-			   strerror(errno));
-		goto fail;
-	}
-
-	if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
-		if (errno != EINPROGRESS) {
-			wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
-				   strerror(errno));
-			goto fail;
-		}
-
-		/*
-		 * Continue connecting in the background; eloop will call us
-		 * once the connection is ready (or failed).
-		 */
-	}
-
-	if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
-				dpp_conn_tx_ready, conn, NULL) < 0)
-		goto fail;
-	conn->write_eloop = 1;
-
-	hdr = wpabuf_head(auth->req_msg);
-	end = hdr + wpabuf_len(auth->req_msg);
-	hdr += 2; /* skip Category and Actiom */
-	pos = hdr + DPP_HDR_LEN;
-	conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
-	if (!conn->msg_out)
-		goto fail;
-	/* Message will be sent in dpp_conn_tx_ready() */
-
-	/* TODO: eloop timeout to clear a connection if it does not complete
-	 * properly */
-	dl_list_add(&dpp->tcp_init, &conn->list);
-	return 0;
-fail:
-	dpp_connection_free(conn);
-	return -1;
-}
-
-
-int dpp_controller_start(struct dpp_global *dpp,
-			 struct dpp_controller_config *config)
-{
-	struct dpp_controller *ctrl;
-	int on = 1;
-	struct sockaddr_in sin;
-	int port;
-
-	if (!dpp || dpp->controller)
-		return -1;
-
-	ctrl = os_zalloc(sizeof(*ctrl));
-	if (!ctrl)
-		return -1;
-	ctrl->global = dpp;
-	if (config->configurator_params)
-		ctrl->configurator_params =
-			os_strdup(config->configurator_params);
-	dl_list_init(&ctrl->conn);
-	/* TODO: configure these somehow */
-	ctrl->allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR;
-	ctrl->qr_mutual = 0;
-
-	ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
-	if (ctrl->sock < 0)
-		goto fail;
-
-	if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR,
-		       &on, sizeof(on)) < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: setsockopt(SO_REUSEADDR) failed: %s",
-			   strerror(errno));
-		/* try to continue anyway */
-	}
-
-	if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) {
-		wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s",
-			   strerror(errno));
-		goto fail;
-	}
-
-	/* TODO: IPv6 */
-	os_memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = INADDR_ANY;
-	port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT;
-	sin.sin_port = htons(port);
-	if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
-		wpa_printf(MSG_INFO,
-			   "DPP: Failed to bind Controller TCP port: %s",
-			   strerror(errno));
-		goto fail;
-	}
-	if (listen(ctrl->sock, 10 /* max backlog */) < 0 ||
-	    fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 ||
-	    eloop_register_sock(ctrl->sock, EVENT_TYPE_READ,
-				dpp_controller_tcp_cb, ctrl, NULL))
-		goto fail;
-
-	dpp->controller = ctrl;
-	wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port);
-	return 0;
-fail:
-	dpp_controller_free(ctrl);
-	return -1;
-}
-
-
-void dpp_controller_stop(struct dpp_global *dpp)
-{
-	if (dpp) {
-		dpp_controller_free(dpp->controller);
-		dpp->controller = NULL;
-	}
-}
-
-
 struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi)
 {
 	struct wpabuf *msg;
@@ -12323,5 +4066,4 @@
 			"DPP: Presence Announcement frame attributes", msg);
 	return msg;
 }
-
 #endif /* CONFIG_DPP2 */