Cumulative patch from commit 7bf86e44161fe1bcadaf4ca2cc3b6358fb7f3bf9

7bf86e441 Define test config QCA vendor attribute for HE MU EDCA params
6cc77193c Define test config QCA vendor attribute for Tx beamformee NSTS
73d3f8841 HS 2.0: CoA-Request from Terms and Conditions server
abed6136a RADIUS: Add DAC implementation in hostapd(AS)
72aad113c RADIUS: Allow 0.0.0.0 to be used as wildard radius_das_client
2122fc83a RADIUS server: Add current_sessions SQLite table
d4e39c51f HS 2.0: Move Terms and Conditions Server URL generation from AP to AS
de3885fcc HS 2.0: Process Credential/UsernamePassword/EAPMethod nodes in PPS MO
3a8dd390c SAE: Allow authentication restart on AP
a10f5714c HS 2.0: Allow Hotspot 2.0 version number to be overridden for build
e8cf9fc33 P2P: Use more compact debug print of common group frequencies
26eac0a99 P2P: Improve common group channel selection if GO needs to be moved
616178a2a P2P/AP: More detailed debug prints on HT/VHT parameter selection
c6f01fbf2 nl80211: Add more command/event names to debug prints
4a0e01156 AP: Fix HT 20/40 co-ex transition timer cancellation on iface removal
b915f2cdf nl80211: Handle NL80211_CMD_WIPHY_REG_CHANGE event
c3e4f40cd FT: Derive PMKR0Name/PMKR1Name using SHA-384 with AKM 00-0F-AC:13
e8d08cf37 SAE: Do not drop STA entry on reauthentication in infrastructure BSS
ef13b33af FT: Support BIP-CMAC-256, BIP-GMAC-128, BIP-GMAC-256 in STA case
ff168f8c2 FT: Support 256-bit IGTK in AP case
2cf36d608 FT: Handle AssocResp generation failures as fatal errors
657b4c45a FILS: Fix KEK2 use in FT-FILS use cases
88bf44be4 FT: Fix potential NULL pointer dereference in MDE addition
661afb2ed FT: Fix RRB error path handling
df3bf6870 FT: Debug print of IE parsing element details
d8e8c992c FT: Add key management value FT-EAP-SHA384 for wpa_supplicant
c6f2eceb8 FT: Add key management value FT-EAP-SHA384 for hostapd
3d9cd0841 FT: Add support for variable length PMK-R1 receiving in RRB
a7968ea56 FT: FTE generation for SHA384-based AKM on AP
06f128660 FT: FTE generation for SHA384-based AKM on STA
9a33737a0 FT: FTE parsing for SHA384-based AKM
8c2715b35 FT: Connection settings for SHA384-based AKM
994eac7e6 FT: PMK-R0 derivation using SHA384-based AKM
1655e81c9 FT: PMKID derivation using SHA384-based AKM
40a2eb116 FT: PTK derivation using SHA384-based AKM
7880a6a2b FT: PMK-R1 derivation using SHA384-based AKM
b327026a7 FT: FTE MIC calculation using SHA384-based AKM
c49a9d6b9 FT: EAPOL-Key MIC calculation using SHA384-based AKM
9f12271b2 FT: XXKey derivation for SHA384-based AKM
a3e18dbb6 FT: Support variable length keys
c22bb5bba FT: SHA384-based AKM in RSNE processing
3a11c69e0 EAP-TLS: Derive Session-Id using TLS-Exporter when TLS v1.3 is used
2d26434ac EAP-TLS server: Fix EMSK derivation with TLS v1.3
f8aed720e EAP-TLS: Update key derivation label per draft-ietf-emu-eap-tls13-00
20c2ea412 wpa_supplicant: Fix parsing of max_oper_chwidth
8fd29a043 mesh: Fix crash with CONFIG_TAXONOMY enabled
8518326b2 Add some missing driver flags strings
b375b04b6 WNM: Fix time_zone advertisement without time_zone configuration
0928b6294 nl80211: Allow mesh interface to send channel switch request
f5a602168 HS 2.0: Allow OSEN connection to be used in an RSN BSS
8d660a4ba HS 2.0: Allow OSEN connection to be enabled in an RSN BSS
0fe3ede0a macsec_qca: Fix byte order of TX SCI port
22ac3dfeb EAP-pwd: Mask timing of PWE derivation
b8acd5011 EAP-pwd peer: Add SHA512 hash based salt mechanism
fb3675848 EAP-pwd peer: Add SHA256 hash based salt mechanism
7ef8adc7d EAP-pwd peer: Add SHA-1 hash based salt mechanism
7280723fb EAP-pwd peer: Check for unexpected state for ID exchange
44136f6ca EAP-pwd peer: Add support for salted password databases
0744e303c EAP-pwd peer: Move PWE derivation to commit exchange
d52ead3db EAP-pwd server: Add support for salted password databases
a8712ce5b EAP-pwd: Pre-processing method definitions from RFC 8146
2a5c29188 EAP-pwd: Move EC group initialization to earlier step
b829e4b69 Add a QCA vendor command attribute to enable/disable GTX
833bb2ab1 FT: Disable PMKSA caching with FT
91db940ff fst: Fix compile error in fst_ctrl_aux.h with C++ compilers
9be19d0b9 SAE: Add support for using the optional Password Identifier
d6a65a83f mesh: Register msg_ctx for hostapd/AP code
4e47eec5a Add QCA NAN vendor attributes to provide IPv6 information
997312964 wolfSSL: Fix crypto_bignum_rshift() wrapper
4b2e03c42 wolfSSL: DH initialization to call TEST_FAIL() for error tests
2b01270c8 wolfSSL: Fix ECDH set peer to use the index when importing point
ffff7f709 OWE: Mark connection failed in the unlikely no-bss-entry case
0cc41ee63 Move wpa_supplicant_event() EVENT_ASSOC_REJECT handling into a function
bda9c0859 hostapd: Fix CHAN_SWITCH command for VHT20 and VHT40
16d5c9637 OWE: Get the bss from bssid of assoc_reject to try for next group
c4dd3afa3 ACS: Avoid invalid interference factor when survey channel time is zero
6965705bf Fix style issues in qca-vendor.h
7d66e7c40 Define new QCA feature flag for self managed regulatory support
38f60142d Define test config vendor attribute for Tx beamformee configuration
d109aa6ca SAE: Flush PMKSA if an assoc reject without timeout is received
46053a4c9 wext: Avoid gcc warnings on restricted pointer aliasing
ce2a9644b Silence a gcc warning on switch statement fallthrough
d267bdf9b Silence new gcc warnings on switch statement fallthroughs
60a5737e8 FT: Clear SME FT data on disassoc
98b806b03 Add QCA vendor attribute for spectral hardware generation
d57e06170 wpa_supplicant: Make channel switch event available for non-AP builds
d7f038ded wpa_supplicant: Add ieee80211ac information in STATUS
ab35793ec wolfSSL: Fix EAP-FAST key derivation
71faf06cb wolfSSL: Do not free cert store after setting it
b7f5b0ec6 wolfSSL: Fix OCSP ifdefs
ca620a364 wolfSSL: Fix altSubjectName handling
7be462084 wolfSSL: Use defines from wolfssl/options.h
312212174 wolfSSL: Remove aes-omac1.o from hostapd build
385dd7189 wolfSSL: Use wolfSSL memory allocation in dh5_init()
6590d8466 wolfSSL: Load certificates using 'chain' APIs
fc5e88e3e wolfSSL: Changes for memory allocation failure testing
06657d316 wolfSSL: Fix crypto_hash_init() memory clearing
d39605710 wolfSSL: Fix crypto_ec_point_y_sqr()
e3501ac18 wolfSSL: Fix crypto_ec_point_solve_y_coord()
187ad3a30 wolfSSL: Add crypto_ecdh_*()
3d2f638d6 wolfSSL: Use new digest namespace
847665ebe wolfSSL: Fix conditional EAP-FAST compilation issue
d501c27cf EAP-TLS server: Disable TLS v1.3 by default
e8a7af9a3 EAP-TLS peer: Disable TLS v1.3 by default
bbbc7e801 EAP-TLS: Extend TLS version config to allow TLS v1.3 to be disabled
53b34578f OpenSSL: Move server vs. client information into connection data
0de820b33 EAP-TLS peer: MSK/EMSK derivation with TLS v1.3
1854981c7 EAP-TLS peer: Allow NewSessionTicket after Client Finished with TLS v1.3
6dd98483e EAP-TLS peer: Support fragmentation of last message
a80423b52 EAP-TLS server: MSK/EMSK derivation with TLS v1.3
bac1bdba3 EAP-TLS peer: Determine whether TLS v1.3 or newer is used
fe7b06c5e EAP-TLS server: Determine whether TLS v1.3 or newer is used
c26ac1895 Mark eap_server_tls_derive_key() label argument const
34c6949fb EAP-TLS server: Remove trailing whitespace
4a576c473 OpenSSL: Terminate TLS handshake if ClientHello cannot be generated
2439714f9 DPP: Fix testing code for invalid keys with OpenSSL 1.1.1
c456e6e3f HS 2.0: Terms and Conditions server and management
42f416916 HS 2.0: Update server SQL DB initialization to cover new fields
5bd5eb54d HS 2.0: Update server instructions for Ubuntu 16.04
04ee197f8 HS 2.0: Maintain a database of pending T&C acceptance sessions
625a8c86b wpa_cli: Indicate HS20-T-C-ACCEPTANCE to action scripts
6b21df0bb Add QCA vendor command/attr to filter frames from other BSSs
452603809 HS 2.0: Terms and Conditions testing feature in authentication server
f456940ef HS 2.0: CoA-Request processing for Terms and Conditions filtering
d239ab396 DFS: Mark channels required DFS based on reg-domain info from the driver
7fc6a024f HS 2.0: Process received Terms and Conditions Acceptance notification
8760b9848 HS 2.0: Send Terms and Conditions Acceptance notification
6cb8f4f38 HS 2.0: Terms and Conditions attributes in Access-Request messages
1952b626b hostapd: Add ctrl iface indications for WDS STA interface
2598e6930 FILS: Enable SHA256 KDF even without PMF/SAE in the build
1baa130bd nl80211: Print NL80211_CMD_SET_POWER_SAVE errors in debug log
72b6e5d1e Do not remove CCMP group cipher if any CCMP/GCMP cipher is enabled
c4315e662 AP: Handle AP initalization failure in async flow
86c998d37 FT: Add FT auth algorithm to connect params when roaming
3dc3afe29 FT: Add MDE to assoc request IEs in connect params
b55c623e4 Make CENTER_FRQ1 available independently in SIGNAL_POLL
4204669c6 HS 2.0: Add Roaming Consortium Selection element into AssocReq
6311547e7 HS 2.0: Add Roaming Consortium Selection network profile parameter
5b7695275 HS 2.0: Use roaming_consortiums list to match OIs for access
2e88032f1 HS 2.0: OSU client to send HomeSP/RoamingConsortiumOI to wpa_supplicant
909a948b0 HS 2.0: Add a new cred block parameter roaming_consortiums
9b6f93e4d HS 2.0: Document credential parameter required_roaming_consortium
67cca3464 HS 2.0: Copy Roaming Consortium OI from (Re)AssocReq to Access-Request
0e450db28 HS 2.0: Allow configuration of operator icons
6a8a04d74 HS 2.0: Add fetching of Operator Icon Metadata ANQP-element
37547ad63 wpa_supplicant: Increase authentication timeout if CAC is started
2dd5fbbff wpa_supplicant: Rename wpas_event_*() to wpas_ap_event_*()
f875da044 nl80211: Add MLME auth work-around for -EEXIST errno
4449efeb1 Fix building nt_password_hash with gnutls
5ecdf06c8 DPP: Fix build with LibreSSL v2.5
4b603f01d DPP: Fix X509_ALGOR_get0() use with LibreSSL
dee566d98 OpenSSL: Skip SSL_OP_NO_TLSv1_3 if not defined to fix LibreSSL build
ba3658cff Fix build with LibreSSL 2.7
a2ab37308 Fix sae_password documentation in wpa_supplicant to refer correct field
d5906fbb7 mesh: Properly handle sae_password
d6d7debb5 Fix wpa_supplicant build with CONFIG_NO_WPA
852b2f273 SAE: Only allow SAE AKMP for PMKSA caching attempts
06b1a1043 SAE: Fix default PMK configuration for PMKSA caching case
8e402d165 WPA: Fix a typo in a debug message
1bd131105 Clear pmk_len more consistently for extra protection
66dbc8d9c Add more debug prints for wpa_sm_set_pmk() calls
26e0ada47 Define new test config attribute for HE LTF configuration
4d6eb9f2e Fix hostapd wmm_enabled setup on config reload path
a6509e850 FT: Add session_timeout to push/resp
3cb286ca4 FT: Add set/get session_timeout callback functions
13f118dc5 Convert STA session_timeout to os_reltime
069b4e304 FT: Include identity and radius_cui in pull/resp frames
9fbe292ff FT: Move wpa_ft_rrb_build_r0() special case to caller
8c345234f FT: Add set/get identity/radius_cui callback functions
17a8a9893 Fix potential memory leak with identity/radius_cui
17010c38d FT: Add IEEE VLAN support (including tagged VLANs)
47a039b01 FT: Add set_vlan()/get_vlan() callback functions
3a3e28320 FT: Add expiration to PMK-R0 and PMK-R1 cache
09211c989 FT: Use dl_list for PMK-R0/R1 cache
89dea17e1 FT: Add helper function for FILS key storing
83fe4bd3b FT: Convert r0_key_lifetime to seconds
ee2c6bb5e Remove CONFIG_IEEE80211R_AP=y build option from wpa_supplicant
c6b5b9a33 hostapd: Add more authentication error case debugging
e2fc13d0a hostapd: Add logging around Michael MIC related failures
e7525a295 hostapd: Add send_auth_reply() caller info in debug logging
d89edb611 wpa_supplicant: Don't reply to EAPOL if pkt_type is PACKET_OTHERHOST
8fb2b3573 Clean up setting of iface->p2p_mgmt flag
d53401c54 dbus: Redirect signal processing to the management device if present
e48021276 dbus: Add FILS to global capabilities
208263c01 Add config information related to MACsec
e360010c3 dbus: Add mesh to global capabilities
9f917339c tests: Fix clearing of IGTK PN in handshake retransmit test functions
45f7574d3 Propagate the EAP method error code
77a020a11 wpa_supplicant: Fix auth failure when the MAC is updated externally
2ff9696d3 Add definitions for RADIUS attributes standardised in RFC 7055
c17915462 nl80211: Add DFS offload support using upstream nl80211 definitions
1841086ad Sync with mac80211-next.git include/uapi/linux/nl80211.h
7cfe2f001 Add SAR V2 power selection capability (QCA vendor attributes)
7e1d3ee96 Add hostapd.conf venue_url to set Venue URL ANQP-element
64624f31c OWE: Fix CONFIG_OWE=y build without CONFIG_IEEE80211R=y
d555c39c4 FILS: Fix CONFIG_FILS=y build without CONFIG_IEEE80211R=y
f6de72534 Add NOTE control interface command for hostapd
2f3738781 FILS: Add more complete support for FT-FILS use cases
4ddca8142 FT: Derive PMK-R1 locally if requested PMKR0Name is found
1dc0945cc FT: Do not send PMK-R1 pull request to own R0KH address
1778f1e9a SAE: Fix PTK derivation to use KDF-SHA256
9d94e4bb6 SAE: Fix PMKID in EAPOL-Key msg 1/4
a03f9d17e SAE: Fix FT-SAE key derivation for a case where PMKID in msg 1/4 matches
0fa669bca Fix a resource leak on hostapd maclist parsing error path
10949e248 Do not disable 40 MHz based on co-ex report with matching primary channel
8cbd9c3ed Support multiple 20/40 BSS Intolerant Channel Report elements
8127a0ac0 Ignore intra-BSS 20/40 BSS Coexistence Management from not-associated STA
8aa599d45 Add more debug prints for 20/40 BSS Coexistence Management frame Rx
d58c3bd8b hostapd: Ignore LOW_ACK event for co-operative steering clients
ec2b5173c Make STA opmode change event available to upper layers
e8ada1600 nl80211: Add support for STA opmode change events
72123a84c hostapd: Add last_ack_rssi into ctrl iface cmd STA
2df73f52e Add hostapd_cli poll_sta command
f5701cc66 OWE: Clean up pointer check in a testing code path
ebe61e564 Sync with mac80211-next.git include/uapi/linux/nl80211.h
8179ae3a2 DPP: Support retrieving of configurator's private key
4bc801ab4 SAE: Fix EAPOL-Key integrity and key-wrap algorithm selection
d74963d41 DPP: Extend dpp_test 89 functionality to transmit side
f8bfc9cbd Use correct WPA_ALG_* values to compare for enum wpa_alg
cce16e43f mka: Mark ieee802_1x_kay_create_mka() ckn and cak arguments const
22151b111 wpa_supplicant: Fix memory leaks in ieee802_1x_create_preshared_mka()
3a52f6b38 mka: Do not print contents of SAK to debug log
77977b3d5 mka: Detect duplicate MAC addresses during key server election
5762855ab mka: Loss of live peers to result in connect PENDING not AUTHENTICATED
8fb546d8e mka: Ignore MACsec SAK Use Old Key parameter if we don't have our old key
b54b53e64 mka: When matching CKNs ensure that lengths are identical
fec03f983 Add support for wolfSSL cryptographic library
92eb00aec Extend ACL check for Probe Request frames
01542e651 Add new WiFi test config attributes to configure BA params
ba6080441 Add new WiFi test config attribute to allow WEP/TKIP in HE
c05f96a38 FILS: Check kde more consistently to avoid static analyzer warnings
087474512 SAE: Debug print group support in the crypto library
f5e0a3324 SAE: Fix potential infinite loop in mismatching PMK case on AP
427729ee6 Reject eap_server_erp hostapd.conf parameter without CONFIG_ERP=y
c54cc8bb1 BoringSSL: Set appropriate sigalgs for Suite B RSA 3K cases
aa6de8e6b BoringSSL: Map OpenSSL SUITEB192 cipher into appropriate sigalgs
7a47f34b1 BoringSSL: Map OpenSSL SUITEB192 cipher into appropriate parameters
355250234 OpenSSL: Replace SSL_set1_curves_list() with SSL_set1_curves()
4ab0f11b8 Allow HT40 on 5 GHz channels 165 and 169
299d21e8e nl80211: Use the new NL80211_MFP_OPTIONAL option
b8e88d357 wpa_supplicant: Handle port authorized event
a8c45d47d nl80211: Handle port authorized event
0a20bd7d9 driver: Add port authorized event
05fc7c68f nl80211: Add API to set the PMK to the driver
0ff08f963 nl80211: Check 4-way handshake offload support
730c5a1d0 nl80211: Support passing PSK on connect
14dcb22a5 wpa_passphrase: Include $(LIBS) for linking
4b07484c3 DPP: Do not include common/dpp.h without CONFIG_DPP=y
9ec0dfa31 Define host_to_le64() for Windows builds
6e3726c09 Fix a typo in disassoc_low_ack documentation
19e20c14f Add ap_isolate configuration option for wpa_supplicant AP mode
a4016163e Extend APF interface for read/write and enable/disable ops
b2e4074ca OpenSSL: Fix EAP-FAST with OpenSSL 1.1.1-pre1
a22e235fd OWE: Add testing RSNE for OWE assoc response with driver SME/MLME
aca4d84e3 DPP: Use wildcard BSSID in GAS query frames
0887215d9 nl80211: Do not try to add too large NL80211_ATTR_PMK for set/del PMKSA
e7f6e6ee1 nl80211: Print NL80211_CMD_{SET,DEL}_PMKSA failures in debug log
3988046de hostapd: Dynamic MAC ACL management over control interface
6a252ece2 DPP: Fix GAS query removal race condition on DPP_STOP_LISTEN
3b50f8a46 DPP: PKEX initiation on other bands
659ac96d7 ieee802_11_mgmt: Handle frame info more consistently
458d8984d SAE: Reject request with mismatching PMKID (no PMKSA cache entry)
5ac434642 Define new QCA vendor sub command for wifi test configuration
70e190137 DPP: Require use of PMF for DPP AKM
79ce2d519 OWE: Rename function to match use (driver-SME/MLME)
759da93a8 OWE: Check for ECDH availability before use (driver-SME/MLME)
af65ef28f OWE: Add RSNE when not using PMKSA caching (driver-SME/MLME)
5850cba38 OWE: Support DH groups 20 and 21 with driver-SME/MLME
f9854c183 hostapd: Fix wpa_psk_file support for FT-PSK
3bd35b681 wpa_supplicant: Fix parsing errors on additional config file
9c5fe742a wpa_supplicant: Free config only if it was allocated in same call
9f8d459d4 OWE: Fix association IEs for transition mode open AP connection
c6096c6ee wpa_cli: Enable add/remove/get vendor elements without P2P
d1e3d40d0 common: Fix the description of wpa_ctrl_request() function
82424732a Fix compiler issue with CONFIG_TESTING_OPTIONS
ebf404373 D-Bus: Report error on starting P2P find
66b9f3ca8 wpa_cli: Fix cred_fields[] declaration
5ff39c138 SAE: Support external authentication offload for driver-SME cases
40a68f338 nl80211: Create a netlink socket handle for the Connect interface
ba71cb821 nl80211: Introduce the interface for external authentication
8678b14fa Add new QCA vendor commands for thermal shutdown
99576f6f3 Sync with mac80211-next.git include/uapi/linux/nl80211.h
cd483be25 OWE: Use PMKSA caching if available with driver AP MLME
a4668c681 OWE: Handle unsupported finite cyclic group with driver MLME
f811cc83b atheros: Send correct SSID length to the driver
e005725a6 nl80211: Add DPP and OWE AKM selectors to CONNECT/ASSOC request
2cc2a0a7e Extend QCA vendor NDP params to support schedule update indication
a7769f6da Update QCA vendor commands to match ASOP
18e3e9c6e OWE: Transition mode with non-AP-MLME
92b6e0c58 hostapd: Send broadcast Public Action frame with wildcard BSSID address
fe3f81e6a DPP: Update PKEX role-specific points
b4cd8b7e1 Add QCA vendor command and attributes for MSDU queue depth threshold
703470bfa FILS: Fix extended capability bit setting for FILS in AP mode
9e834fc64 EAP-SIM/AKA: Separate identity for MK derivation
b6b5e3554 DPP: Get rid of compiler warnings on signed/unsigned comparison
630ea1334 DPP: Track M.x/N.x/L.x availability for ke derivation
c1790a5ff OWE: Allow station in transition mode to connect to an open BSS
c103c0b51 Extend NUD Stats to collect the data packet statistics
5d5ee699a Copy WLAN-Reason-Code value from Access-Reject to Deauthentication
f75ed556c RADIUS: Add WLAN-Reason-Code attribute to Access-Reject
727e9aacb HS 2.0: Set appropriate permission(s) for cert file/folders on Android
feba5848b Replace RSNE group key management mismatch status/reason codes
9cc8303d3 Add QCA vendor command to get the WLAN MAC information
fd9209549 DPP: Report reception of Config Request to upper layers
80f71b71d DPP: Authentication exchange retries and channel iteration in hostapd
c5cc7a59a Report offchannel RX frame frequency to hostapd
b7ed94834 GnuTLS: Add option to build with libnettle instead of libgcrypt
c36d82241 GnuTLS: Suite B validation
dd227e67a GnuTLS: Add support for disabling TLS versions
5d292fcfb GnuTLS: Implement tls_get_cipher()
5791d2117 GnuTLS: Make debug prints clearer for cert/key parsing
622d4d49e GnuTLS: Add TEST_FAIL() to crypto routines for testing purposes
f8697e810 GnuTLS: Implement tls_get_version()
133f8d09f GnuTLS: Implement HMAC functions using libgcrypt
85c12a62e GnuTLS: Implement sha{256,384,512}_vector() using libgcrypt
cc3e7bfc3 GnuTLS: Use a helper function for hash functions
2cb40e9f4 OWE: Try all supported DH groups automatically on STA
02b38d0ad Fix MFP-enabled test for disallowed TKIP
ba3d435fe SAE: Add option to require MFP for SAE associations
c4fc7e31c SAE: Set special Sc value when moving to Accepted state
abcbd0604 SAE: Add Rc variable and peer send-confirm validation
9249afc8e SAE: Print state changes in debug log
d8b841eba SAE: Make dot11RSNASAESync configurable
9596a7565 PAE: Remove OpenSSL header dependency
04b1bcc5f EAP-pwd: Use abstract crypto API
0c3d49afd EAP-EKE: Use abstract crypto API
c335507c8 Enhance crypto abstract API for DH
0e02f2a9f crypto: Implement new crypto API functions for DH
eac084cb3 OpenSSL: Implement new crypto API functions
23ff5d73d Enhance crypto abstract API
441e8bfbb Fix copy-paste errors in function comments
47e966aba DH: Remove trailing whitespace
3546ef510 EAP-pwd: Remove trailing empty line
61536b5f4 Add new QCA vendor attribute for getting preferred channel
1a2cb20d5 Fix couple of QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS comments
2fca2d214 Vendor parameter for forcing RSNE override
12bce14b1 wpa_cli: Add completion for get/set cred commands
6240424a7 dbus: Add FILS key mgmt values into BSS security properties
2d942ec4a Define a QCA vendor command to retrieve SAR Power limits
d98038bb0 FILS: Driver configuration to disable/enable FILS features
af832aa99 hostapd: Add average channel utilization in STATUS
802c0fd0c hostapd: Update BSS load update period dynamically
778d87054 Fix error handling in bss_load_update_period parser
dff5ab97e hostapd_cli: Add dpp_listen and dpp_stop_listen
5f30b69cd OWE: Allow DH Parameters element overriding with driver SME
04ded82ef OWE: Fix error case handling with drivers that implement AP SME
c23e87d0d OpenSSL: Replace EVP_PKEY_paramgen() with EC_KEY_new_by_curve_name()
7641d485d BoringSSL: Use EC_KEY_new_by_curve_name() to simplify implementation
a5da39607 Revert "BoringSSL: Add DPP special cases regardless of claimed version number"
0f3084472 Revert "BoringSSL: Define RSA_bits() helper"
a2c442be2 OpenSSL: Allow cipher list to be overridden for tls_suiteb=1 case
e5c7c2f28 Fix ap-mgmt-fuzzer build
63942cf0f OpenSSL: Avoid SSL*_use_default_passwd_cb()
149143e31 OpenSSL: Remove unnecessary os_strdup() from password callback
b65353a76 Android: Set CONFIG_NO_RANDOM_POOL=y
ff28df739 Android: Move hostapd to vendor partition
9b0de99fa Add new QCA vendor attribute for WLAN Latency Module (WLM)
055cd3978 tests: DPP P-256 test vectors
f55269753 DPP: Allow protocol key to be overridden for testing purposes
afd3cf14a WPS: Add GCMP-256 and CCMP-256 cipher options on Enrollee
5f481b6fd WPS: Check BSS table against current BSSID if credential does not match
402c8e00b WPS: Map GCMP-256 and CCMP-256 to AES encryption type
a2660890a WPS: Allow WPS to be enabled in CCMP-256 and GCMP-256 only cases
163fc3d56 DPP: Indicate to upper layers whether mutual authentication was used
34603767b DPP: Extend protocol testing to allow exchange termination
ed2c493e9 DPP: Change Authentication Response retry time to 1 second
963d3149a nl80211: Fix NL80211_MESHCONF_AUTO_OPEN_PLINKS encoding
a2426829c nl80211: Fix NL80211_ATTR_SMPS_MODE encoding
f0a383a98 DPP: Extend dpp_test with invalid E-Nonce in Config Req
55c6c8585 DPP: Extend dpp_test with invalid Transaction ID in Peer Disc Req
364039d22 Add QCA vendor command and attributes for RROP
0e19300d5 nl80211: Use consistent "0x" prefix for the cookie values
fa5c90749 DPP: Call wpas_dpp_stop() from wpas_dpp_deinit()
1866dfb52 DPP: Stop pending GAS client operation on DPP_STOP_LISTEN
f981ce729 DPP: Do not continue if public key hash derivation fails
8a37d54ea DPP: Fix memory leak on dpp_auth_build_conf() error paths
281f480c5 JSON: Fix a memory leak on an error path
622934128 DPP: Fix a memory leak on an error path
ed62d4011 DPP: Deinit PKEX instance on DPP_STOP_LISTEN
634a130a5 DPP: Clear authentication instance on configuration completion in AP
d3cb7ebe1 DPP: Do not process dpp_auth_ok_on_ack multiple times
dc2f24f1b DPP: Fix compilation without CONFIG_TESTING_OPTIONS=y
82feacced DPP: Ignore GAS server status callback for unknown response
a2588be82 DPP: Add DPP_CONFIGURATOR_SIGN support to hostapd
7eb6bfb45 DPP: Move hostapd Configurator/bootstrap data into global context
73f21929a DPP: Auto-generate Initiator bootstrapping info if needed
725a953ae nl80211: Filter global events based on wiphy
0bd7f104c hostapd: Add supported rate information into STATUS and STA
1489fcf87 FILS: Do not leave error value in left counter
beae255a7 WPA: Check wpa_eapol_key_mic() result on TX
acc555f9e DPP: Allow PKEX x/X and y/Y keypairs to be overridden
d722c50d0 DPP: Print more interim EC_POINT results into debug log
2bdc47a94 DPP: Allow PKEX own/peer MAC addresses to be overridden
af4103e5e DPP: Provide peer_mac to PKEX Initiator through function argument
918a2ac40 DPP: Work around missing EVP_PKEY_CTX_set_ec_param_enc()
3ca4be1ea DPP: Remove compiler warnings about signed/unsigned comparisons
116454f46 DPP: Fix error return value in dpp_auth_conf_rx()
63dc0f9c4 hostapd: Disassoc STA without WPA/RSN IE if AP proto is WPA/RSN
cc79e06f0 hostapd: Add wpa_msg_ctrl() to report Probe Request frames from STA
0db637ca8 DPP: Fix number of Authentication Request retry cases
921f5acd1 DPP: Take response wait time into account for init retries
248264c62 DPP: Stop Authentication Request attempts if no response after ACK
e3a5882b3 DPP: Add SAE credential support to Configurator
5dd745b73 DPP: Add akm=sae and akm=psk+sae support in Enrollee role
a44467395 DPP: Protocol testing capability to send invalid I-Nonce in Auth Req
00d2d13db DPP: Retry PKEX Exchange Request frame up to five times
ab0375508 TDLS: Add testing capability to send TPK M2 twice
4b8de0c92 DPP: Protocol testing for invalid Peer Discovery Req/Resp values
f9cf7d03f DPP: Protocol testing for invalid Config Attrib Object value
3f35ec2dc DPP: Protocol testing for invalid DPP Status value
9efa53149 DPP: Use helper functions to build Bootstrap Key Hash attributes
acdf703d5 DPP: Replace custom undefined attr with DPP Status in after-wrapped data
56f24d1da DPP: Use a helper function to build DPP Status attribute
65ecce87f DPP: Protocol testing for writing invalid I/R Bootstrap Key Hash
b6b4226bd DPP: Protocol testing capability to generate invalid Protocol Key
c6eb3e34b Stronger GTK derivation routine
94619905c DPP: Fix dpp_test_gen_invalid_key() with BoringSSL
746c1792a DPP: Build bootstrapping key DER encoding using custom routine
f2d27ef94 DPP: Use a helper function to DER encode bootstrapping key
c1564149a BoringSSL: Add AES support with 192-bit keys
edd72f55f OpenSSL: Debug message if requested AES key length is not supported
5548453a2 BoringSSL: Add DPP special cases regardless of claimed version number
f29761297 BoringSSL: Implement crypto_ecdh_init()
7721fe082 BoringSSL: Comment out SSL_set_default_passwd_cb*() calls
b9dc63c26 BoringSSL: Comment out SSL_set1_sigalgs_list() call
3cfbd3b0f BoringSSL: Define RSA_bits() helper
27781c0ab Allow group cipher selection to be overridden
af6614ca1 Fix block comment style in QCA vendor attribute definition
2115603a4 Add QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING
27987b67f Add new QCA vendor attribute for LL stats
41db74cf7 atheros: Process SAE authentication frames using EVENT_RX_MGMT
3d9dd4b77 atheros: Generate EVENT_TX_STATUS events for management frames
f5b74b966 common: Avoid conflict with __bitwise macro from linux/types.h
4109555ef DPP: Fix compiler warning of testing code
1d624a070 Reject PMK-to-PTK derivation with unsupported cipher
762fb4f06 DPP: Testing capability to send unexpected Authentication Response
03abb6b54 DPP: Reject unexpected Req/Resp message based on Auth/PKEX role
95b0104a3 DPP: Retransmit DPP Authentication Response frame if it is not ACKed
c1d377396 DPP: Stop authentication exchange of DPP_STOP_LISTEN
d1f082644 DPP: Allowed initiator to indicate either role
f97ace34c DPP: Support multiple channels for initiating DPP Authentication
de0298618 DPP: Share a helper function for PKEX final steps
a306ed5a5 DPP: Protocol testing to allow missing attributes in peer discovery
1fafdf112 DPP: Add DPP_LISTEN and DPP_STOP_LISTEN to hostapd
fbfceef3a Add QCA vendor commands for spectral scan
bb9808fa9 P2P: Continue P2P_WAIT_PEER_(IDLE/CONNECT) sequence on a listen cancel
37ed3254d P2P: ACS offload for the autonomous GO
962b8fcf4 Add new QCA vendor attributes for MAC counters
af7f10fcd DPP: Protocol testing for invalid Config Resp attribute values
8c99e6264 DPP: Report Config Request/Response failure reasons on control interface
f411ad1b8 DPP: Protocol testing to remove attributes from Config Req/Resp
7e0ebe21b DPP: Protocol testing - invalid I/R-Auth value in PKEX Commit-Reveal
89d0bf678 DPP: Protocol testing - invalid Bootstrap Key value in PKEX Commit-Reveal
f31ef96dc DPP: Protocol testing - invalid Status value in PKEX Exchange Response
d05c82c4d DPP: Move PKEX z derivation on Responder to earlier phase
578c9ea1a DPP: Fix a typo in a debug print
5f5fff436 DPP: Explicitly check that PKEX Qr is not the point-at-infinity
29ab69e4b DPP: PKEX counter t
039b8e736 DPP: Terminate PKEX exchange on detection of a mismatching code
fc0efa2a1 DPP: Use dpp_bn2bin_pad() helper to simplify code
e0247e798 DPP: PKEX and STATUS_BAD_GROUP
2265353a4 DPP: Remove obsolete TODO comment on discovery object
fe12ae777 Fix Status Code in TKIP countermeasures case
1cfcbd32a DPP: Testing capability to generate invalid PKEX encrypted key (M and N)
d7e7b7122 DPP: Report PKEX failure reasons over control interface
61f9f27f8 DPP: Extend protocol testing to cover missing attributes in PKEX
b3e4cc5cb DPP: Move PKEX Commit-Reveal Response building to a helper function
b0626c2a6 DPP: Move PKEX Commit-Reveal Request building to a helper function
a5c3b41b2 DPP: Move PKEX Exchange Response building to a helper function
60b9dd86f DPP: Fix couple of typos in debug messages
06f2df069 DPP: Fix hostapd control interface events for initiator case
219d4c9fc DPP: Report possible PKEX code mismatch in control interface
69d8d029f DPP: Enable PMF when adding wpa_supplicant network profile
0c3bc1be0 Fix test build breakage when not compiling with ieee80211w support
ea4ace9c7 hostapd: Add max_txpower into STATUS command
bf6c65afc hostapd: Add Beacon interval and DTIM period into STATUS command
c7ae2b310 hostapd: Add HT/VHT capability info into STATUS command
1f91a8bde hostapd: Add HT/VHT capability info into STA command
65f9db6bc hostapd: Add extended capabilities into STA command
d1f3a8144 hostapd: Add [HT] flag into STA command
ba72b4b12 hostapd: Add Min/Max Transmit Power Capability into STA command
33c8bbd8c OWE: Add AP mode handling of OWE with drivers that implement SME
28d126413 Check hostapd current_mode before dereferencing it in additional places
348c93847 AP-side workaround for WNM-Sleep Mode GTK/IGTK reinstallation issues
3f5a1860a wpa_auth: Deplete group rekey eloop handler for strict rekeying
92662fb28 Allow forcing group rekeying for testing purposes
d27092069 DPP: Negotiation channel change request from Initiator
b7dddab7b DPP: Allow testing override values to be cleared
e85b66012 DPP: Add DPP Status attribute into Peer Discovery Response
19ef4289c DPP: Process Authentication Confirm failure cases
7d917ab04 DPP: Send Authentication Confirm failure reports
978bc3f2a DPP: Auth Resp/Conf incorrect attribute values for protocol testing
9b5111203 DPP: Allow Responder to decide not to use mutual authentication
dcdaeab79 DPP: Report Auth Conf failures in control interface
f9c7d7702 DPP: Omission of Auth Conf attributes for protocol testing
26806abe8 DPP: Report invalid messages and failure conditions in control interface
ce9acce00 DPP: Omission of Auth Resp attributes for protocol testing
a03406dbe DPP: Move Authentication Response building into a separate function
0e7cb8c6c DPP: Omission of Auth Req attributes for protocol testing
606a8e8d5 DPP: Move Authentication Request building into a separate function
3749ad0e1 DPP: Explicitly check and reject 0x00 and 0x03 I/R-capab role
af48810ba DPP: Report transmitted messages as control interface events
a70739349 DPP: Report received messages as control interface events
27fefbbb7 DPP: Remove unnecessary Wrapped Data checks from callers
0c881807b DPP: Verify that Wrapped Data attribute is the last one in the message
60239f60a DPP: Protocol testing framework
7ed5337d8 Fix a typo in a debug message
5f7c9e50f EAP server: Add event messages for more EAP states
a68e0d869 Fix a typo in a comment (the variable is ptk, not pkt)
de41b960b wpa_supplicant: Increase UDP control interface RX buffer
74e55b658 Fix test build breakage when not compiling with mesh support
3d0fb9558 WNM: Ignore BSS Transition Management frames in bss_transition=0 case
114f2830d WNM: Ignore WNM-Sleep Mode Request in wnm_sleep_mode=0 case

Bug: 111131936
Test: Device boots up and connects to wifi networks.
Test: Able to turn on/off softap.
Test: Sent for regression tests (b/111209415).
Change-Id: I85cbeeee6a4ff52a5e23f8917b15633c896c0cf3
Signed-off-by: Roshan Pius <rpius@google.com>
diff --git a/src/common/ctrl_iface_common.c b/src/common/ctrl_iface_common.c
index ebbe6ff..e26407d 100644
--- a/src/common/ctrl_iface_common.c
+++ b/src/common/ctrl_iface_common.c
@@ -113,17 +113,53 @@
 }
 
 
+static int ctrl_set_events(struct wpa_ctrl_dst *dst, const char *input)
+{
+	const char *value;
+	int val;
+
+	if (!input)
+		return 0;
+
+	value = os_strchr(input, '=');
+	if (!value)
+		return -1;
+	value++;
+	val = atoi(value);
+	if (val < 0 || val > 1)
+		return -1;
+
+	if (str_starts(input, "probe_rx_events=")) {
+		if (val)
+			dst->events |= WPA_EVENT_RX_PROBE_REQUEST;
+		else
+			dst->events &= ~WPA_EVENT_RX_PROBE_REQUEST;
+	}
+
+	return 0;
+}
+
+
 int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
-		      socklen_t fromlen)
+		      socklen_t fromlen, const char *input)
 {
 	struct wpa_ctrl_dst *dst;
 
+	/* Update event registration if already attached */
+	dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
+		if (!sockaddr_compare(from, fromlen,
+				      &dst->addr, dst->addrlen))
+			return ctrl_set_events(dst, input);
+	}
+
+	/* New attachment */
 	dst = os_zalloc(sizeof(*dst));
 	if (dst == NULL)
 		return -1;
 	os_memcpy(&dst->addr, from, fromlen);
 	dst->addrlen = fromlen;
 	dst->debug_level = MSG_INFO;
+	ctrl_set_events(dst, input);
 	dl_list_add(ctrl_dst, &dst->list);
 
 	sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor attached", from, fromlen);
diff --git a/src/common/ctrl_iface_common.h b/src/common/ctrl_iface_common.h
index 0b6e3e7..85e258e 100644
--- a/src/common/ctrl_iface_common.h
+++ b/src/common/ctrl_iface_common.h
@@ -11,6 +11,9 @@
 
 #include "utils/list.h"
 
+/* Events enable bits (wpa_ctrl_dst::events) */
+#define WPA_EVENT_RX_PROBE_REQUEST BIT(0)
+
 /**
  * struct wpa_ctrl_dst - Data structure of control interface monitors
  *
@@ -23,13 +26,14 @@
 	socklen_t addrlen;
 	int debug_level;
 	int errors;
+	u32 events; /* WPA_EVENT_* bitmap */
 };
 
 void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
 		    socklen_t socklen);
 
 int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
-		       socklen_t fromlen);
+		       socklen_t fromlen, const char *input);
 int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
 		      socklen_t fromlen);
 int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
diff --git a/src/common/defs.h b/src/common/defs.h
index 1de099f..c968cd6 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - Common definitions
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -57,11 +57,13 @@
 #define WPA_KEY_MGMT_FT_FILS_SHA384 BIT(21)
 #define WPA_KEY_MGMT_OWE BIT(22)
 #define WPA_KEY_MGMT_DPP BIT(23)
+#define WPA_KEY_MGMT_FT_IEEE8021X_SHA384 BIT(24)
 
 static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
 {
 	return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
 			 WPA_KEY_MGMT_FT_IEEE8021X |
+			 WPA_KEY_MGMT_FT_IEEE8021X_SHA384 |
 			 WPA_KEY_MGMT_CCKM |
 			 WPA_KEY_MGMT_OSEN |
 			 WPA_KEY_MGMT_IEEE8021X_SHA256 |
@@ -86,6 +88,7 @@
 {
 	return !!(akm & (WPA_KEY_MGMT_FT_PSK |
 			 WPA_KEY_MGMT_FT_IEEE8021X |
+			 WPA_KEY_MGMT_FT_IEEE8021X_SHA384 |
 			 WPA_KEY_MGMT_FT_SAE |
 			 WPA_KEY_MGMT_FT_FILS_SHA256 |
 			 WPA_KEY_MGMT_FT_FILS_SHA384));
@@ -114,6 +117,8 @@
 {
 	return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
 			 WPA_KEY_MGMT_IEEE8021X_SHA256 |
+			 WPA_KEY_MGMT_SAE |
+			 WPA_KEY_MGMT_FT_SAE |
 			 WPA_KEY_MGMT_OSEN |
 			 WPA_KEY_MGMT_IEEE8021X_SUITE_B |
 			 WPA_KEY_MGMT_FILS_SHA256 |
@@ -123,6 +128,7 @@
 static inline int wpa_key_mgmt_sha384(int akm)
 {
 	return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 |
+			 WPA_KEY_MGMT_FT_IEEE8021X_SHA384 |
 			 WPA_KEY_MGMT_FILS_SHA384 |
 			 WPA_KEY_MGMT_FT_FILS_SHA384));
 }
diff --git a/src/common/dpp.c b/src/common/dpp.c
index 5107950..ea00c93 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -9,6 +9,8 @@
 #include "utils/includes.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"
@@ -22,10 +24,28 @@
 #include "crypto/aes_siv.h"
 #include "crypto/sha384.h"
 #include "crypto/sha512.h"
+#include "drivers/driver.h"
 #include "dpp.h"
 
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#ifdef CONFIG_TESTING_OPTIONS
+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 || \
+	(defined(LIBRESSL_VERSION_NUMBER) && \
+	 LIBRESSL_VERSION_NUMBER < 0x20700000L)
 /* Compatibility wrappers for older versions. */
 
 static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
@@ -83,10 +103,10 @@
 	0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
 };
 static const u8 pkex_resp_y_p256[32] = {
-	0x26, 0x04, 0x09, 0x45, 0x0a, 0x05, 0x20, 0xe7,
-	0xa7, 0x27, 0xc1, 0x36, 0x76, 0x85, 0xca, 0x3e,
-	0x42, 0x16, 0xf4, 0x89, 0x85, 0x34, 0x6e, 0xd5,
-	0x17, 0xde, 0xc0, 0xb8, 0xad, 0xfd, 0xb2, 0x98
+	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 */
@@ -99,12 +119,12 @@
 	0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
 };
 static const u8 pkex_init_y_p384[48] = {
-	0x89, 0xd0, 0x97, 0x7b, 0x59, 0x4f, 0xa6, 0xd6,
-	0x7c, 0x5d, 0x93, 0x5b, 0x93, 0xc4, 0x07, 0xa9,
-	0x89, 0xee, 0xd5, 0xcd, 0x6f, 0x42, 0xf8, 0x38,
-	0xc8, 0xc6, 0x62, 0x24, 0x69, 0x0c, 0xd4, 0x48,
-	0xd8, 0x44, 0xd6, 0xc2, 0xe8, 0xcc, 0x62, 0x6b,
-	0x3c, 0x25, 0x53, 0xba, 0x4f, 0x71, 0xf8, 0xe7
+	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,
@@ -115,12 +135,12 @@
 	0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
 };
 static const u8 pkex_resp_y_p384[48] = {
-	0x54, 0x58, 0x20, 0xad, 0x55, 0x1d, 0xca, 0xf3,
-	0x1c, 0x8a, 0xcd, 0x19, 0x40, 0xf9, 0x37, 0x83,
-	0xc7, 0xd6, 0xb3, 0x13, 0x7d, 0x53, 0x28, 0x5c,
-	0xf6, 0x2d, 0xf1, 0xdd, 0xa5, 0x8b, 0xad, 0x5d,
-	0x81, 0xab, 0xb1, 0x00, 0x39, 0xd6, 0xcc, 0x9c,
-	0xea, 0x1e, 0x84, 0x1d, 0xbf, 0xe3, 0x35, 0xf9
+	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 */
@@ -136,15 +156,15 @@
 	0x97, 0x76
 };
 static const u8 pkex_init_y_p521[66] = {
-	0x01, 0x4c, 0x71, 0xfd, 0x1b, 0xd5, 0x9c, 0xa6,
-	0xed, 0x39, 0xef, 0x45, 0xc5, 0x06, 0xfd, 0x66,
-	0xc0, 0xeb, 0x0f, 0xbf, 0x21, 0xa3, 0x36, 0x74,
-	0xfd, 0xaa, 0x05, 0x6e, 0x4e, 0x33, 0x95, 0x42,
-	0x1a, 0x9d, 0x3f, 0x3a, 0x1c, 0x5e, 0xa8, 0x60,
-	0xf7, 0xe5, 0x59, 0x1d, 0x07, 0xaa, 0x6f, 0x40,
-	0x0a, 0x59, 0x3c, 0x27, 0xad, 0xe0, 0x48, 0xfd,
-	0xd1, 0x83, 0x37, 0x4c, 0xdf, 0xe1, 0x86, 0x72,
-	0xfc, 0x57
+	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,
@@ -158,15 +178,15 @@
 	0x84, 0xb4
 };
 static const u8 pkex_resp_y_p521[66] = {
-	0x01, 0xb9, 0x9c, 0xc6, 0x41, 0x32, 0x5b, 0xd2,
-	0x35, 0xd8, 0x8b, 0x2b, 0xe4, 0x6e, 0xcc, 0xdf,
-	0x7c, 0x38, 0xc4, 0x5b, 0xf6, 0x74, 0x71, 0x5c,
-	0x77, 0x16, 0x8a, 0x80, 0xa9, 0x84, 0xc7, 0x7b,
-	0x9d, 0xfd, 0x83, 0x6f, 0xae, 0xf8, 0x24, 0x16,
-	0x2f, 0x21, 0x25, 0x65, 0xa2, 0x1a, 0x6b, 0x2d,
-	0x30, 0x62, 0xb3, 0xcc, 0x6e, 0x59, 0x3c, 0x7f,
-	0x58, 0x91, 0x81, 0x72, 0x07, 0x8c, 0x91, 0xac,
-	0x31, 0x1e
+	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 */
@@ -177,10 +197,10 @@
 	0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
 };
 static const u8 pkex_init_y_bp_p256r1[32] = {
-	0x16, 0x30, 0x68, 0x32, 0x3b, 0xb0, 0x21, 0xee,
-	0xeb, 0xf7, 0xb6, 0x7c, 0xae, 0x52, 0x26, 0x42,
-	0x59, 0x28, 0x58, 0xb6, 0x14, 0x90, 0xed, 0x69,
-	0xd0, 0x67, 0xea, 0x25, 0x60, 0x0f, 0xa9, 0x6c
+	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,
@@ -241,14 +261,14 @@
 	0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
 };
 static const u8 pkex_init_y_bp_p512r1[64] = {
-	0x5a, 0x28, 0x01, 0xbe, 0x96, 0x82, 0x4e, 0xf6,
-	0xfa, 0xed, 0x7d, 0xfd, 0x48, 0x8b, 0x48, 0x4e,
-	0xd1, 0x97, 0x87, 0xc4, 0x05, 0x5d, 0x15, 0x2a,
-	0xf4, 0x91, 0x4b, 0x75, 0x90, 0xd9, 0x34, 0x2c,
-	0x3c, 0x12, 0xf2, 0xf5, 0x25, 0x94, 0x24, 0x34,
-	0xa7, 0x6d, 0x66, 0xbc, 0x27, 0xa4, 0xa0, 0x8d,
-	0xd5, 0xe1, 0x54, 0xa3, 0x55, 0x26, 0xd4, 0x14,
-	0x17, 0x0f, 0xc1, 0xc7, 0x3d, 0x68, 0x7f, 0x5a
+	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,
@@ -261,17 +281,50 @@
 	0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
 };
 static const u8 pkex_resp_y_bp_p512r1[64] = {
-	0x2a, 0xbe, 0x59, 0xe6, 0xc4, 0xb3, 0xd8, 0x09,
-	0x66, 0x89, 0x0a, 0x2d, 0x19, 0xf0, 0x9c, 0x9f,
-	0xb4, 0xab, 0x8f, 0x50, 0x68, 0x3c, 0x74, 0x64,
-	0x4e, 0x19, 0x55, 0x81, 0x9b, 0x48, 0x5c, 0xf4,
-	0x12, 0x8d, 0xb9, 0xd8, 0x02, 0x5b, 0xe1, 0x26,
-	0x7e, 0x19, 0x5c, 0xfd, 0x70, 0xf7, 0x4b, 0xdc,
-	0xb5, 0x5d, 0xc1, 0x7a, 0xe9, 0xd1, 0x05, 0x2e,
-	0xd1, 0xfd, 0x2f, 0xce, 0x63, 0x77, 0x48, 0x2c
+	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)
@@ -335,6 +388,20 @@
 }
 
 
+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;
@@ -418,6 +485,7 @@
 		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 ||
@@ -479,6 +547,12 @@
 }
 
 
+static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
+{
+	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
+}
+
+
 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
 			      size_t len)
 {
@@ -523,6 +597,7 @@
 int dpp_check_attrs(const u8 *buf, size_t len)
 {
 	const u8 *pos, *end;
+	int wrapped_data = 0;
 
 	pos = buf;
 	end = buf + len;
@@ -540,6 +615,13 @@
 				   "DPP: Truncated message - not enough room for the attribute - dropped");
 			return -1;
 		}
+		if (wrapped_data) {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: An unexpected attribute included after the Wrapped Data attribute");
+			return -1;
+		}
+		if (id == DPP_ATTR_WRAPPED_DATA)
+			wrapped_data = 1;
 		pos += alen;
 	}
 
@@ -731,7 +813,7 @@
 	const unsigned char *pk;
 	int ppklen;
 	X509_ALGOR *pa;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
 	ASN1_OBJECT *pa_oid;
 #else
 	const ASN1_OBJECT *pa_oid;
@@ -939,6 +1021,8 @@
 	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)
@@ -961,6 +1045,11 @@
 	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);
@@ -979,13 +1068,8 @@
 
 static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
 {
-#ifdef OPENSSL_IS_BORINGSSL
 	EVP_PKEY_CTX *kctx = NULL;
-	const EC_GROUP *group;
 	EC_KEY *ec_params;
-#else
-	EVP_PKEY_CTX *pctx, *kctx = NULL;
-#endif
 	EVP_PKEY *params = NULL, *key = NULL;
 	int nid;
 
@@ -996,10 +1080,9 @@
 		wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name);
 		return NULL;
 	}
-#ifdef OPENSSL_IS_BORINGSSL
-	group = EC_GROUP_new_by_curve_name(nid);
-	ec_params = EC_KEY_new();
-	if (!ec_params || EC_KEY_set_group(ec_params, group) != 1) {
+
+	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;
@@ -1011,20 +1094,6 @@
 			   "DPP: Failed to generate EVP_PKEY parameters");
 		goto fail;
 	}
-#else
-	pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
-	if (!pctx ||
-	    EVP_PKEY_paramgen_init(pctx) != 1 ||
-	    EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) != 1 ||
-	    EVP_PKEY_CTX_set_ec_param_enc(pctx, OPENSSL_EC_NAMED_CURVE) != 1 ||
-	    EVP_PKEY_paramgen(pctx, &params) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to generate EVP_PKEY parameters");
-		EVP_PKEY_CTX_free(pctx);
-		goto fail;
-	}
-	EVP_PKEY_CTX_free(pctx);
-#endif
 
 	kctx = EVP_PKEY_CTX_new(params, NULL);
 	if (!kctx ||
@@ -1121,34 +1190,111 @@
 }
 
 
-int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
+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;
-	int res;
+	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;
 
-	/* Need to get the compressed form of the public key through EC_KEY, so
-	 * cannot use the simpler i2d_PUBKEY() here. */
-	eckey = EVP_PKEY_get1_EC_KEY(bi->pubkey);
-	if (!eckey)
-		return -1;
-	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
-	der_len = i2d_EC_PUBKEY(eckey, &der);
-	EC_KEY_free(eckey);
+	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");
-		OPENSSL_free(der);
-		return -1;
+		goto fail;
 	}
 
-	len = der_len;
-	res = sha256_vector(1, (const u8 **) &der, &len, bi->pubkey_hash);
+	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;
+}
+
+
+int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
+{
+	struct wpabuf *der;
+	int res;
+	const u8 *addr[1];
+	size_t len[1];
+
+	der = dpp_bootstrap_key_der(bi->pubkey);
+	if (!der)
+		return -1;
+	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
+			der);
+
+	addr[0] = wpabuf_head(der);
+	len[0] = wpabuf_len(der);
+	res = sha256_vector(1, addr, len, bi->pubkey_hash);
 	if (res < 0)
 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
+	else
+		wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash,
+			    SHA256_MAC_LEN);
+	wpabuf_free(der);
 	return res;
 }
 
@@ -1159,9 +1305,9 @@
 	unsigned char *base64 = NULL;
 	char *pos, *end;
 	size_t len;
-	unsigned char *der = NULL;
-	int der_len;
-	EC_KEY *eckey;
+	struct wpabuf *der = NULL;
+	const u8 *addr[1];
+	int res;
 
 	if (!curve) {
 		bi->curve = &dpp_curves[0];
@@ -1181,28 +1327,24 @@
 		goto fail;
 	bi->own = 1;
 
-	/* Need to get the compressed form of the public key through EC_KEY, so
-	 * cannot use the simpler i2d_PUBKEY() here. */
-	eckey = EVP_PKEY_get1_EC_KEY(bi->pubkey);
-	if (!eckey)
+	der = dpp_bootstrap_key_der(bi->pubkey);
+	if (!der)
 		goto fail;
-	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
-	der_len = i2d_EC_PUBKEY(eckey, &der);
-	EC_KEY_free(eckey);
-	if (der_len <= 0) {
-		wpa_printf(MSG_ERROR,
-			   "DDP: Failed to build DER encoded public key");
-		goto fail;
-	}
+	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
+			der);
 
-	len = der_len;
-	if (sha256_vector(1, (const u8 **) &der, &len, bi->pubkey_hash) < 0) {
+	addr[0] = wpabuf_head(der);
+	len = wpabuf_len(der);
+	res = sha256_vector(1, addr, &len, bi->pubkey_hash);
+	if (res < 0) {
 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
 		goto fail;
 	}
+	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash,
+		    SHA256_MAC_LEN);
 
-	base64 = base64_encode(der, der_len, &len);
-	OPENSSL_free(der);
+	base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len);
+	wpabuf_free(der);
 	der = NULL;
 	if (!base64)
 		goto fail;
@@ -1217,7 +1359,7 @@
 	return (char *) base64;
 fail:
 	os_free(base64);
-	OPENSSL_free(der);
+	wpabuf_free(der);
 	return NULL;
 }
 
@@ -1291,6 +1433,12 @@
 	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]) */
@@ -1298,12 +1446,17 @@
 	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->secret_len;
+	len[num_elem] = auth->Mx_len;
 	num_elem++;
 	addr[num_elem] = auth->Nx;
-	len[num_elem] = auth->secret_len;
+	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++;
@@ -1327,16 +1480,48 @@
 }
 
 
-struct dpp_authentication * dpp_auth_init(void *msg_ctx,
-					  struct dpp_bootstrap_info *peer_bi,
-					  struct dpp_bootstrap_info *own_bi,
-					  int configurator)
+static void dpp_build_attr_status(struct wpabuf *msg,
+				  enum dpp_status_error status)
 {
-	struct dpp_authentication *auth;
-	size_t nonce_len;
-	EVP_PKEY_CTX *ctx = NULL;
-	size_t secret_len;
-	struct wpabuf *msg, *pi = NULL;
+	wpa_printf(MSG_DEBUG, "DPP: Status %d", status);
+	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
+	wpabuf_put_le16(msg, 1);
+	wpabuf_put_u8(msg, status);
+}
+
+
+static 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");
+		wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
+		wpabuf_put_le16(msg, SHA256_MAC_LEN);
+		wpabuf_put_data(msg, hash, SHA256_MAC_LEN);
+	}
+}
+
+
+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;
@@ -1344,24 +1529,593 @@
 	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_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_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_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);
+	}
+
+	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)
+{
+	u16 m;
+	int c, flag;
+
+	if (!own_modes || !num_modes)
+		return 1;
+
+	for (m = 0; m < num_modes; m++) {
+		for (c = 0; c < own_modes[m].num_channels; c++) {
+			if ((unsigned int) own_modes[m].channels[c].freq !=
+			    freq)
+				continue;
+			flag = own_modes[m].channels[c].flag;
+			if (!(flag & (HOSTAPD_CHAN_DISABLED |
+				      HOSTAPD_CHAN_NO_IR |
+				      HOSTAPD_CHAN_RADAR)))
+				return 1;
+		}
+	}
+
+	wpa_printf(MSG_DEBUG, "DPP: Peer channel %u MHz not supported", freq);
+	return 0;
+}
+
+
+static int freq_included(const unsigned int freqs[], unsigned int num,
+			 unsigned int freq)
+{
+	while (num > 0) {
+		if (freqs[--num] == freq)
+			return 1;
+	}
+	return 0;
+}
+
+
+static void freq_to_start(unsigned int freqs[], unsigned int num,
+			  unsigned int freq)
+{
+	unsigned int i;
+
+	for (i = 0; i < num; i++) {
+		if (freqs[i] == freq)
+			break;
+	}
+	if (i == 0 || i >= num)
+		return;
+	os_memmove(&freqs[1], &freqs[0], i * sizeof(freqs[0]));
+	freqs[0] = freq;
+}
+
+
+static int dpp_channel_intersect(struct dpp_authentication *auth,
+				 struct hostapd_hw_modes *own_modes,
+				 u16 num_modes)
+{
+	struct dpp_bootstrap_info *peer_bi = auth->peer_bi;
+	unsigned int i, freq;
+
+	for (i = 0; i < peer_bi->num_freq; i++) {
+		freq = peer_bi->freq[i];
+		if (freq_included(auth->freq, auth->num_freq, freq))
+			continue;
+		if (dpp_channel_ok_init(own_modes, num_modes, freq))
+			auth->freq[auth->num_freq++] = freq;
+	}
+	if (!auth->num_freq) {
+		wpa_printf(MSG_INFO,
+			   "DPP: No available channels for initiating DPP Authentication");
+		return -1;
+	}
+	auth->curr_freq = auth->freq[0];
+	return 0;
+}
+
+
+static int dpp_channel_local_list(struct dpp_authentication *auth,
+				  struct hostapd_hw_modes *own_modes,
+				  u16 num_modes)
+{
+	u16 m;
+	int c, flag;
+	unsigned int freq;
+
+	auth->num_freq = 0;
+
+	if (!own_modes || !num_modes) {
+		auth->freq[0] = 2412;
+		auth->freq[1] = 2437;
+		auth->freq[2] = 2462;
+		auth->num_freq = 3;
+		return 0;
+	}
+
+	for (m = 0; m < num_modes; m++) {
+		for (c = 0; c < own_modes[m].num_channels; c++) {
+			freq = own_modes[m].channels[c].freq;
+			flag = own_modes[m].channels[c].flag;
+			if (flag & (HOSTAPD_CHAN_DISABLED |
+				    HOSTAPD_CHAN_NO_IR |
+				    HOSTAPD_CHAN_RADAR))
+				continue;
+			if (freq_included(auth->freq, auth->num_freq, freq))
+				continue;
+			auth->freq[auth->num_freq++] = freq;
+			if (auth->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
+				m = num_modes;
+				break;
+			}
+		}
+	}
+
+	return auth->num_freq == 0 ? -1 : 0;
+}
+
+
+static int dpp_prepare_channel_list(struct dpp_authentication *auth,
+				    struct hostapd_hw_modes *own_modes,
+				    u16 num_modes)
+{
+	int res;
+	char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end;
+	unsigned int i;
+
+	if (auth->peer_bi->num_freq > 0)
+		res = dpp_channel_intersect(auth, own_modes, num_modes);
+	else
+		res = dpp_channel_local_list(auth, own_modes, num_modes);
+	if (res < 0)
+		return res;
+
+	/* Prioritize 2.4 GHz channels 6, 1, 11 (in this order) to hit the most
+	 * likely channels first. */
+	freq_to_start(auth->freq, auth->num_freq, 2462);
+	freq_to_start(auth->freq, auth->num_freq, 2412);
+	freq_to_start(auth->freq, auth->num_freq, 2437);
+
+	auth->freq_idx = 0;
+	auth->curr_freq = auth->freq[0];
+
+	pos = freqs;
+	end = pos + sizeof(freqs);
+	for (i = 0; i < auth->num_freq; i++) {
+		res = os_snprintf(pos, end - pos, " %u", auth->freq[i]);
+		if (os_snprintf_error(end - pos, res))
+			break;
+		pos += res;
+	}
+	*pos = '\0';
+	wpa_printf(MSG_DEBUG, "DPP: Possible frequencies for initiating:%s",
+		   freqs);
+
+	return 0;
+}
+
+
+static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth)
+{
+	struct dpp_bootstrap_info *bi;
+	char *pk = NULL;
+	size_t len;
+
+	if (auth->own_bi)
+		return 0; /* already generated */
+
+	bi = os_zalloc(sizeof(*bi));
+	if (!bi)
+		return -1;
+	bi->type = DPP_BOOTSTRAP_QR_CODE;
+	pk = dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0);
+	if (!pk)
+		goto fail;
+
+	len = 4; /* "DPP:" */
+	len += 4 + os_strlen(pk);
+	bi->uri = os_malloc(len + 1);
+	if (!bi->uri)
+		goto fail;
+	os_snprintf(bi->uri, len + 1, "DPP:K:%s;;", pk);
+	wpa_printf(MSG_DEBUG,
+		   "DPP: Auto-generated own bootstrapping key info: URI %s",
+		   bi->uri);
+
+	auth->tmp_own_bi = auth->own_bi = bi;
+
+	os_free(pk);
+
+	return 0;
+fail:
+	os_free(pk);
+	dpp_bootstrap_info_free(bi);
+	return -1;
+}
+
+
+struct dpp_authentication * dpp_auth_init(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;
+	EVP_PKEY_CTX *ctx = NULL;
+	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 = os_zalloc(sizeof(*auth));
 	if (!auth)
 		return NULL;
 	auth->msg_ctx = msg_ctx;
 	auth->initiator = 1;
-	auth->configurator = configurator;
+	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, 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;
 
@@ -1388,93 +2142,60 @@
 
 	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;
 
-	/* Build DPP Authentication Request frame attributes */
-	attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + wpabuf_len(pi) +
-		4 + sizeof(wrapped_data);
-	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len);
-	if (!msg)
+	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 */
+
+	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;
-	auth->req_msg = msg;
 
-	attr_start = wpabuf_put(msg, 0);
-
-	/* Responder Bootstrapping Key Hash */
-	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
-	wpabuf_put_le16(msg, SHA256_MAC_LEN);
-	wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
-
-	/* Initiator Bootstrapping Key Hash */
-	wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
-	wpabuf_put_le16(msg, SHA256_MAC_LEN);
-	if (auth->own_bi)
-		wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
-	else
-		os_memset(wpabuf_put(msg, SHA256_MAC_LEN), 0, SHA256_MAC_LEN);
-
-	/* Initiator Protocol Key */
-	wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY);
-	wpabuf_put_le16(msg, wpabuf_len(pi));
-	wpabuf_put_buf(msg, pi);
-	wpabuf_free(pi);
-	pi = NULL;
-
-	/* Wrapped data ({I-nonce, I-capabilities}k1) */
-	pos = clear;
-	/* 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;
-	/* I-capabilities */
-	WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES);
-	pos += 2;
-	WPA_PUT_LE16(pos, 1);
-	pos += 2;
-	auth->i_capab = configurator ? DPP_CAPAB_CONFIGURATOR :
-		DPP_CAPAB_ENROLLEE;
-	*pos++ = auth->i_capab;
-
-	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)
-		goto fail;
-	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);
-
-	wpa_hexdump_buf(MSG_DEBUG,
-			"DPP: Authentication Request frame attributes", msg);
-
-	return auth;
-fail:
+out:
 	wpabuf_free(pi);
 	EVP_PKEY_CTX_free(ctx);
+	return auth;
+fail:
 	dpp_auth_deinit(auth);
-	return NULL;
+	auth = NULL;
+	goto out;
 }
 
 
@@ -1485,6 +2206,7 @@
 	size_t json_len, clear_len;
 	struct wpabuf *clear = NULL, *msg = NULL;
 	u8 *wrapped;
+	size_t attr_len;
 
 	wpa_printf(MSG_DEBUG, "DPP: Build configuration request");
 
@@ -1500,20 +2222,55 @@
 	/* { E-nonce, configAttrib }ke */
 	clear_len = 4 + nonce_len + 4 + json_len;
 	clear = wpabuf_alloc(clear_len);
-	msg = wpabuf_alloc(4 + clear_len + AES_BLOCK_SIZE);
+	attr_len = 4 + clear_len + AES_BLOCK_SIZE;
+#ifdef CONFIG_TESTING_OPTIONS
+	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ)
+		attr_len += 5;
+#endif /* CONFIG_TESTING_OPTIONS */
+	msg = wpabuf_alloc(attr_len);
 	if (!clear || !msg)
 		goto fail;
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_REQ) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
+		goto skip_e_nonce;
+	}
+	if (dpp_test == DPP_TEST_INVALID_E_NONCE_CONF_REQ) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - invalid E-nonce");
+		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
+		wpabuf_put_le16(clear, nonce_len - 1);
+		wpabuf_put_data(clear, auth->e_nonce, nonce_len - 1);
+		goto skip_e_nonce;
+	}
+	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_REQ) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
+		goto skip_wrapped_data;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	/* E-nonce */
 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
 	wpabuf_put_le16(clear, nonce_len);
 	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
 
+#ifdef CONFIG_TESTING_OPTIONS
+skip_e_nonce:
+	if (dpp_test == DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - no configAttrib");
+		goto skip_conf_attr_obj;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	/* configAttrib */
 	wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ);
 	wpabuf_put_le16(clear, json_len);
 	wpabuf_put_data(clear, json, json_len);
 
+#ifdef CONFIG_TESTING_OPTIONS
+skip_conf_attr_obj:
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	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);
@@ -1527,6 +2284,14 @@
 	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_CONF_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: Configuration Request frame attributes", msg);
 	wpabuf_free(clear);
@@ -1544,8 +2309,11 @@
 	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));
 
@@ -1725,7 +2493,6 @@
 	BIGNUM *lx, *sum, *q;
 	const BIGNUM *bR_bn, *pR_bn;
 	int ret = -1;
-	int num_bytes, offset;
 
 	/* L = ((bR + pR) modulo q) * BI */
 
@@ -1765,17 +2532,10 @@
 		goto fail;
 	}
 
-	num_bytes = BN_num_bytes(lx);
-	if ((size_t) num_bytes > auth->secret_len)
+	if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
 		goto fail;
-	if (auth->secret_len > (size_t) num_bytes)
-		offset = auth->secret_len - num_bytes;
-	else
-		offset = 0;
-
-	os_memset(auth->Lx, 0, offset);
-	BN_bn2bin(lx, auth->Lx + offset);
 	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);
@@ -1800,7 +2560,6 @@
 	BIGNUM *lx;
 	const BIGNUM *bI_bn;
 	int ret = -1;
-	int num_bytes, offset;
 
 	/* L = bI * (BR + PR) */
 
@@ -1835,17 +2594,10 @@
 		goto fail;
 	}
 
-	num_bytes = BN_num_bytes(lx);
-	if ((size_t) num_bytes > auth->secret_len)
+	if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
 		goto fail;
-	if (auth->secret_len > (size_t) num_bytes)
-		offset = auth->secret_len - num_bytes;
-	else
-		offset = 0;
-
-	os_memset(auth->Lx, 0, offset);
-	BN_bn2bin(lx, auth->Lx + offset);
 	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);
@@ -1858,34 +2610,63 @@
 }
 
 
-static int dpp_auth_build_resp(struct dpp_authentication *auth)
+static int dpp_auth_build_resp_ok(struct dpp_authentication *auth)
 {
 	size_t nonce_len;
 	EVP_PKEY_CTX *ctx = NULL;
 	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];
-#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \
-		4 + sizeof(wrapped_r_auth)
+	u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth;
 	size_t wrapped_r_auth_len;
-	u8 clear[DPP_AUTH_RESP_CLEAR_LEN];
-	u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE];
-	u8 *pos;
-	const u8 *addr[2];
-	size_t len[2], siv_len, attr_len;
-	u8 *attr_start, *attr_end;
+	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);
 
+#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;
 
@@ -1911,6 +2692,7 @@
 
 	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)
@@ -1928,215 +2710,163 @@
 	/* 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 ||
-	    aes_siv_encrypt(auth->ke, 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;
 
-	/* Build DPP Authentication Response frame attributes */
-	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
-		4 + wpabuf_len(pr) + 4 + sizeof(wrapped_data);
-	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
+	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;
-
-	attr_start = wpabuf_put(msg, 0);
-
-	/* DPP Status */
-	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
-	wpabuf_put_le16(msg, 1);
-	wpabuf_put_u8(msg, DPP_STATUS_OK);
-
-	/* Responder Bootstrapping Key Hash */
-	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
-	wpabuf_put_le16(msg, SHA256_MAC_LEN);
-	wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
-
-	if (auth->peer_bi) {
-		/* Mutual authentication */
-		/* Initiator Bootstrapping Key Hash */
-		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
-		wpabuf_put_le16(msg, SHA256_MAC_LEN);
-		wpabuf_put_data(msg, auth->peer_bi->pubkey_hash,
-				SHA256_MAC_LEN);
-	}
-
-	/* Responder Protocol Key */
-	wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
-	wpabuf_put_le16(msg, wpabuf_len(pr));
-	wpabuf_put_buf(msg, pr);
-	wpabuf_free(pr);
-	pr = NULL;
-
-	attr_end = wpabuf_put(msg, 0);
-
-	/* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */
-	pos = clear;
-	/* R-nonce */
-	WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE);
-	pos += 2;
-	WPA_PUT_LE16(pos, nonce_len);
-	pos += 2;
-	os_memcpy(pos, auth->r_nonce, nonce_len);
-	pos += nonce_len;
-	/* 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;
-	/* 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;
-	/* {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(auth->k2, auth->curve->hash_len, clear, siv_len,
-			    2, addr, len, wrapped_data) < 0)
-		goto fail;
-	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);
-
-	wpa_hexdump_buf(MSG_DEBUG,
-			"DPP: Authentication Response frame attributes", msg);
-
-	return 0;
-
+	ret = 0;
 fail:
 	wpabuf_free(pr);
-	return -1;
+	return ret;
 }
 
 
 static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
 				      enum dpp_status_error status)
 {
-	size_t nonce_len;
 	struct wpabuf *msg;
-#define DPP_AUTH_RESP_CLEAR_LEN2 4 + DPP_MAX_NONCE_LEN + 4 + 1
-	u8 clear[DPP_AUTH_RESP_CLEAR_LEN2];
-	u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN2 + AES_BLOCK_SIZE];
-	u8 *pos;
-	const u8 *addr[2];
-	size_t len[2], siv_len, attr_len;
-	u8 *attr_start, *attr_end;
+	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");
 
-	/* Build DPP Authentication Response frame attributes */
-	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + 4 + sizeof(wrapped_data);
-	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
+	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 = -1;
+	} 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)
-		goto fail;
+		return -1;
 	wpabuf_free(auth->resp_msg);
 	auth->resp_msg = msg;
-
-	attr_start = wpabuf_put(msg, 0);
-
-	/* DPP Status */
-	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
-	wpabuf_put_le16(msg, 1);
-	wpabuf_put_u8(msg, status);
-
-	/* Responder Bootstrapping Key Hash */
-	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
-	wpabuf_put_le16(msg, SHA256_MAC_LEN);
-	wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
-
-	if (auth->peer_bi) {
-		/* Mutual authentication */
-		/* Initiator Bootstrapping Key Hash */
-		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
-		wpabuf_put_le16(msg, SHA256_MAC_LEN);
-		wpabuf_put_data(msg, auth->peer_bi->pubkey_hash,
-				SHA256_MAC_LEN);
-	}
-
-	attr_end = wpabuf_put(msg, 0);
-
-	/* Wrapped data ({I-nonce, R-capabilities}k1) */
-	pos = clear;
-	/* I-nonce */
-	nonce_len = auth->curve->nonce_len;
-	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;
-	/* 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;
-
-	/* 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)
-		goto fail;
-	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);
-
-	wpa_hexdump_buf(MSG_DEBUG,
-			"DPP: Authentication Response frame attributes", msg);
-
 	return 0;
-
-fail:
-	return -1;
 }
 
 
@@ -2145,7 +2875,7 @@
 		struct dpp_bootstrap_info *peer_bi,
 		struct dpp_bootstrap_info *own_bi,
 		unsigned int freq, const u8 *hdr, const u8 *attr_start,
-		const u8 *wrapped_data,	u16 wrapped_data_len)
+		size_t attr_len)
 {
 	EVP_PKEY *pi = NULL;
 	EVP_PKEY_CTX *ctx = NULL;
@@ -2154,14 +2884,29 @@
 	size_t len[2];
 	u8 *unwrapped = NULL;
 	size_t unwrapped_len = 0;
-	const u8 *i_proto, *i_nonce, *i_capab, *i_bootstrap;
-	u16 i_proto_len, i_nonce_len, i_capab_len, i_bootstrap_len;
+	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;
-	size_t attr_len;
 
-	if (wrapped_data_len < AES_BLOCK_SIZE)
+#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 = os_zalloc(sizeof(*auth));
@@ -2173,11 +2918,39 @@
 	auth->curve = own_bi->curve;
 	auth->curr_freq = freq;
 
+	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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing required Initiator Protocol Key attribute");
+		dpp_auth_fail(auth,
+			      "Missing required Initiator Protocol Key attribute");
 		goto fail;
 	}
 	wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key",
@@ -2186,7 +2959,7 @@
 	/* M = bR * PI */
 	pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len);
 	if (!pi) {
-		wpa_printf(MSG_DEBUG, "DPP: Invalid Initiator Protocol Key");
+		dpp_auth_fail(auth, "Invalid Initiator Protocol Key");
 		goto fail;
 	}
 	dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
@@ -2201,6 +2974,7 @@
 		wpa_printf(MSG_ERROR,
 			   "DPP: Failed to derive ECDH shared secret: %s",
 			   ERR_error_string(ERR_get_error(), NULL));
+		dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
 		goto fail;
 	}
 	auth->secret_len = secret_len;
@@ -2209,6 +2983,7 @@
 
 	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)
@@ -2229,22 +3004,21 @@
 	if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
 			    wrapped_data, wrapped_data_len,
 			    2, addr, len, unwrapped) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in unwrapped data");
+		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) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
+		dpp_auth_fail(auth, "Missing or invalid I-nonce");
 		goto fail;
 	}
 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
@@ -2254,7 +3028,7 @@
 			       DPP_ATTR_I_CAPABILITIES,
 			       &i_capab_len);
 	if (!i_capab || i_capab_len < 1) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-capabilities");
+		dpp_auth_fail(auth, "Missing or invalid I-capabilities");
 		goto fail;
 	}
 	auth->i_capab = i_capab[0];
@@ -2282,9 +3056,25 @@
 		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");
-		goto not_compatible;
+		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;
@@ -2314,7 +3104,7 @@
 			"%s", hex);
 		return auth;
 	}
-	if (dpp_auth_build_resp(auth) < 0)
+	if (dpp_auth_build_resp_ok(auth) < 0)
 		goto fail;
 
 	return auth;
@@ -2355,52 +3145,107 @@
 		   MACSTR, MAC2STR(auth->peer_mac_addr));
 	auth->peer_bi = peer_bi;
 
-	if (dpp_auth_build_resp(auth) < 0)
+	if (dpp_auth_build_resp_ok(auth) < 0)
 		return -1;
 
 	return 1;
 }
 
 
-static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth)
+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 + AES_BLOCK_SIZE;
+		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 */
-	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
-	wpabuf_put_le16(msg, 1);
-	wpabuf_put_u8(msg, DPP_STATUS_OK);
+	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 */
-	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
-	wpabuf_put_le16(msg, SHA256_MAC_LEN);
-	wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
+	dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash);
 
-	if (auth->own_bi) {
-		/* Mutual authentication */
-		/* Initiator Bootstrapping Key Hash */
-		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
-		wpabuf_put_le16(msg, SHA256_MAC_LEN);
-		wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
-	}
+	/* 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);
 
@@ -2414,28 +3259,73 @@
 	len[1] = attr_end - attr_start;
 	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, i_auth_len + AES_BLOCK_SIZE);
-	wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE);
-	/* 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 ||
-	    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);
+	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);
-	dpp_auth_success(auth);
+	if (status == DPP_STATUS_OK)
+		dpp_auth_success(auth);
 
 	return msg;
 
 fail:
+	wpabuf_free(msg);
 	return NULL;
 }
 
@@ -2463,6 +3353,7 @@
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Responder reported failure (status %d)",
 			   status);
+		dpp_auth_fail(auth, "Responder reported failure");
 		return;
 	}
 
@@ -2481,27 +3372,26 @@
 	if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
 			    wrapped_data, wrapped_data_len,
 			    2, addr, len, unwrapped) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in unwrapped data");
+		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) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
+		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) {
-		wpa_printf(MSG_DEBUG, "DPP: I-nonce mismatch");
+		dpp_auth_fail(auth, "I-nonce mismatch");
 		goto fail;
 	}
 
@@ -2509,7 +3399,7 @@
 			       DPP_ATTR_R_CAPABILITIES,
 			       &r_capab_len);
 	if (!r_capab || r_capab_len < 1) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-capabilities");
+		dpp_auth_fail(auth, "Missing or invalid R-capabilities");
 		goto fail;
 	}
 	auth->r_capab = r_capab[0];
@@ -2518,9 +3408,20 @@
 		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Continue waiting for full DPP Authentication Response");
-		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_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);
@@ -2544,34 +3445,49 @@
 		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_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) {
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing required Wrapped data attribute");
+	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);
 
-	if (wrapped_data_len < AES_BLOCK_SIZE)
-		return NULL;
-
 	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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
+		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);
@@ -2583,8 +3499,8 @@
 				   &i_bootstrap_len);
 	if (i_bootstrap) {
 		if (i_bootstrap_len != SHA256_MAC_LEN) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Invalid Initiator Bootstrapping Key Hash attribute");
+			dpp_auth_fail(auth,
+				      "Invalid Initiator Bootstrapping Key Hash attribute");
 			return NULL;
 		}
 		wpa_hexdump(MSG_MSGDUMP,
@@ -2593,17 +3509,22 @@
 		if (!auth->own_bi ||
 		    os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash,
 			      SHA256_MAC_LEN) != 0) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Initiator Bootstrapping Key Hash attribute did not match");
+			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;
 	}
 
 	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
 			      &status_len);
 	if (!status || status_len < 1) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required DPP Status attribute");
+		dpp_auth_fail(auth,
+			      "Missing or invalid required DPP Status attribute");
 		return NULL;
 	}
 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
@@ -2615,11 +3536,20 @@
 		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing required Responder Protocol Key attribute");
+		dpp_auth_fail(auth,
+			      "Missing required Responder Protocol Key attribute");
 		return NULL;
 	}
 	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
@@ -2628,7 +3558,7 @@
 	/* N = pI * PR */
 	pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len);
 	if (!pr) {
-		wpa_printf(MSG_DEBUG, "DPP: Invalid Responder Protocol Key");
+		dpp_auth_fail(auth, "Invalid Responder Protocol Key");
 		return NULL;
 	}
 	dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
@@ -2643,6 +3573,7 @@
 		wpa_printf(MSG_ERROR,
 			   "DPP: Failed to derive ECDH shared secret: %s",
 			   ERR_error_string(ERR_get_error(), NULL));
+		dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
 		goto fail;
 	}
 	EVP_PKEY_CTX_free(ctx);
@@ -2652,6 +3583,7 @@
 
 	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)
@@ -2672,22 +3604,21 @@
 	if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
 			    wrapped_data, wrapped_data_len,
 			    2, addr, len, unwrapped) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in unwrapped data");
+		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) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-nonce");
+		dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce");
 		goto fail;
 	}
 	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
@@ -2696,12 +3627,12 @@
 	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) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
+		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) {
-		wpa_printf(MSG_DEBUG, "DPP: I-nonce mismatch");
+		dpp_auth_fail(auth, "I-nonce mismatch");
 		goto fail;
 	}
 
@@ -2711,34 +3642,52 @@
 			goto fail;
 	}
 
-	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 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) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-capabilities");
+		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 ((auth->configurator && (auth->r_capab & DPP_CAPAB_CONFIGURATOR)) ||
-	    (!auth->configurator && (auth->r_capab & DPP_CAPAB_ENROLLEE))) {
+	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");
-		goto fail;
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid Secondary Wrapped Data");
+		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)
@@ -2746,23 +3695,23 @@
 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
 			    wrapped2, wrapped2_len,
 			    0, NULL, NULL, unwrapped2) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in secondary unwrapped data");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid Responder Authenticating Tag");
+		dpp_auth_fail(auth,
+			      "Missing or invalid Responder Authenticating Tag");
 		goto fail;
 	}
 	wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag",
@@ -2773,15 +3722,27 @@
 	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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Mismatching Responder Authenticating Tag");
-		goto fail;
+		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);
 
-	return dpp_auth_build_conf(auth);
+#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);
@@ -2792,6 +3753,77 @@
 }
 
 
+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)
 {
@@ -2804,28 +3836,39 @@
 	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) {
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing required Wrapped data attribute");
+	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);
 
-	if (wrapped_data_len < AES_BLOCK_SIZE)
-		return -1;
-
 	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 > wrapped_data ||
-	    r_bootstrap_len != SHA256_MAC_LEN) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
+	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",
@@ -2835,6 +3878,8 @@
 		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;
 	}
 
@@ -2842,10 +3887,9 @@
 				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
 				   &i_bootstrap_len);
 	if (i_bootstrap) {
-		if (i_bootstrap > wrapped_data ||
-		    i_bootstrap_len != SHA256_MAC_LEN) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Invalid Initiator Bootstrapping Key Hash attribute");
+		if (i_bootstrap_len != SHA256_MAC_LEN) {
+			dpp_auth_fail(auth,
+				      "Invalid Initiator Bootstrapping Key Hash attribute");
 			return -1;
 		}
 		wpa_hexdump(MSG_MSGDUMP,
@@ -2854,22 +3898,34 @@
 		if (!auth->peer_bi ||
 		    os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash,
 			      SHA256_MAC_LEN) != 0) {
-			wpa_printf(MSG_DEBUG,
-				   "DPP: Initiator Bootstrapping Key Hash attribute did not match");
+			dpp_auth_fail(auth,
+				      "Initiator Bootstrapping Key Hash mismatch");
 			return -1;
 		}
+	} else if (auth->own_bi && 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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required DPP Status attribute");
+		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) {
-		wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
+		dpp_auth_fail(auth, "Authentication failed");
 		return -1;
 	}
 
@@ -2888,23 +3944,22 @@
 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
 			    wrapped_data, wrapped_data_len,
 			    2, addr, len, unwrapped) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in unwrapped data");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid Initiator Authenticating Tag");
+		dpp_auth_fail(auth,
+			      "Missing or invalid Initiator Authenticating Tag");
 		goto fail;
 	}
 	wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag",
@@ -2915,8 +3970,7 @@
 	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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Mismatching Initiator Authenticating Tag");
+		dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag");
 		goto fail;
 	}
 
@@ -2952,6 +4006,7 @@
 	os_free(auth->connector);
 	wpabuf_free(auth->net_access_key);
 	wpabuf_free(auth->c_sign_key);
+	dpp_bootstrap_info_free(auth->tmp_own_bi);
 #ifdef CONFIG_TESTING_OPTIONS
 	os_free(auth->config_obj_override);
 	os_free(auth->discovery_override);
@@ -2990,28 +4045,12 @@
 	json_escape_string(ssid, sizeof(ssid),
 			   (const char *) conf->ssid, conf->ssid_len);
 	wpabuf_put_str(buf, ssid);
-	wpabuf_put_str(buf, "\"");
-	/* TODO: optional channel information */
-	wpabuf_put_str(buf, "},");
+	wpabuf_put_str(buf, "\"},");
 
 	return buf;
 }
 
 
-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 int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
 			 const char *kid, const struct dpp_curve_params *curve)
 {
@@ -3208,7 +4247,7 @@
 	tailroom += signed1_len + signed2_len + signed3_len;
 	buf = dpp_build_conf_start(auth, conf, tailroom);
 	if (!buf)
-		return NULL;
+		goto fail;
 
 	wpabuf_put_str(buf, "\"cred\":{\"akm\":\"dpp\",\"signedConnector\":\"");
 	wpabuf_put_str(buf, signed1);
@@ -3255,7 +4294,7 @@
 	if (!buf)
 		return NULL;
 
-	wpabuf_put_str(buf, "\"cred\":{\"akm\":\"psk\",");
+	wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", dpp_akm_str(conf->akm));
 	if (conf->passphrase) {
 		char pass[63 * 6 + 1];
 
@@ -3308,7 +4347,7 @@
 		return NULL;
 	}
 
-	if (conf->dpp)
+	if (conf->akm == DPP_AKM_DPP)
 		return dpp_build_conf_obj_dpp(auth, ap, conf);
 	return dpp_build_conf_obj_legacy(auth, ap, conf);
 }
@@ -3319,7 +4358,7 @@
 		    u16 e_nonce_len, int ap)
 {
 	struct wpabuf *conf;
-	size_t clear_len;
+	size_t clear_len, attr_len;
 	struct wpabuf *clear = NULL, *msg = NULL;
 	u8 *wrapped;
 	const u8 *addr[1];
@@ -3338,27 +4377,71 @@
 	if (conf)
 		clear_len += 4 + wpabuf_len(conf);
 	clear = wpabuf_alloc(clear_len);
-	msg = wpabuf_alloc(4 + 1 + 4 + clear_len + AES_BLOCK_SIZE);
+	attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
+#ifdef CONFIG_TESTING_OPTIONS
+	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP)
+		attr_len += 5;
+#endif /* CONFIG_TESTING_OPTIONS */
+	msg = wpabuf_alloc(attr_len);
 	if (!clear || !msg)
 		goto fail;
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_RESP) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce");
+		goto skip_e_nonce;
+	}
+	if (dpp_test == DPP_TEST_E_NONCE_MISMATCH_CONF_RESP) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - E-nonce mismatch");
+		wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
+		wpabuf_put_le16(clear, e_nonce_len);
+		wpabuf_put_data(clear, e_nonce, e_nonce_len - 1);
+		wpabuf_put_u8(clear, e_nonce[e_nonce_len - 1] ^ 0x01);
+		goto skip_e_nonce;
+	}
+	if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_RESP) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data");
+		goto skip_wrapped_data;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	/* E-nonce */
 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
 	wpabuf_put_le16(clear, e_nonce_len);
 	wpabuf_put_data(clear, e_nonce, e_nonce_len);
 
+#ifdef CONFIG_TESTING_OPTIONS
+skip_e_nonce:
+	if (dpp_test == DPP_TEST_NO_CONFIG_OBJ_CONF_RESP) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - Config Object");
+		goto skip_config_obj;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	if (conf) {
 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
 		wpabuf_put_le16(clear, wpabuf_len(conf));
 		wpabuf_put_buf(clear, conf);
-		wpabuf_free(conf);
-		conf = NULL;
 	}
 
+#ifdef CONFIG_TESTING_OPTIONS
+skip_config_obj:
+	if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - Status");
+		goto skip_status;
+	}
+	if (dpp_test == DPP_TEST_INVALID_STATUS_CONF_RESP) {
+		wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status");
+		status = 255;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	/* DPP Status */
-	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
-	wpabuf_put_le16(msg, 1);
-	wpabuf_put_u8(msg, status);
+	dpp_build_attr_status(msg, status);
+
+#ifdef CONFIG_TESTING_OPTIONS
+skip_status:
+#endif /* CONFIG_TESTING_OPTIONS */
 
 	addr[0] = wpabuf_head(msg);
 	len[0] = wpabuf_len(msg);
@@ -3375,17 +4458,26 @@
 		goto fail;
 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
-	wpabuf_free(clear);
-	clear = NULL;
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_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: Configuration Response attributes", msg);
-	return msg;
-fail:
+out:
 	wpabuf_free(conf);
 	wpabuf_free(clear);
+
+	return msg;
+fail:
 	wpabuf_free(msg);
-	return NULL;
+	msg = NULL;
+	goto out;
 }
 
 
@@ -3401,17 +4493,24 @@
 	struct json_token *root = NULL, *token;
 	int ap;
 
+#ifdef CONFIG_TESTING_OPTIONS
+	if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) {
+		wpa_printf(MSG_INFO,
+			   "DPP: TESTING - stop at Config Request");
+		return NULL;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
 	if (dpp_check_attrs(attr_start, attr_len) < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in config request");
+		dpp_auth_fail(auth, "Invalid attribute in config request");
 		return NULL;
 	}
 
 	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_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required Wrapped data attribute");
+		dpp_auth_fail(auth,
+			      "Missing or invalid required Wrapped Data attribute");
 		return NULL;
 	}
 
@@ -3424,15 +4523,14 @@
 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
 			    wrapped_data, wrapped_data_len,
 			    0, NULL, NULL, unwrapped) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in unwrapped data");
+		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
 		goto fail;
 	}
 
@@ -3440,8 +4538,8 @@
 			       DPP_ATTR_ENROLLEE_NONCE,
 			       &e_nonce_len);
 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid Enrollee Nonce attribute");
+		dpp_auth_fail(auth,
+			      "Missing or invalid Enrollee Nonce attribute");
 		goto fail;
 	}
 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
@@ -3450,8 +4548,8 @@
 				   DPP_ATTR_CONFIG_ATTR_OBJ,
 				   &config_attr_len);
 	if (!config_attr) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid Config Attributes attribute");
+		dpp_auth_fail(auth,
+			      "Missing or invalid Config Attributes attribute");
 		goto fail;
 	}
 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes",
@@ -3459,32 +4557,33 @@
 
 	root = json_parse((const char *) config_attr, config_attr_len);
 	if (!root) {
-		wpa_printf(MSG_DEBUG, "DPP: Could not parse Config Attributes");
+		dpp_auth_fail(auth, "Could not parse Config Attributes");
 		goto fail;
 	}
 
 	token = json_get_member(root, "name");
 	if (!token || token->type != JSON_STRING) {
-		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - name");
+		dpp_auth_fail(auth, "No Config Attributes - name");
 		goto fail;
 	}
 	wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
 
 	token = json_get_member(root, "wi-fi_tech");
 	if (!token || token->type != JSON_STRING) {
-		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - wi-fi_tech");
+		dpp_auth_fail(auth, "No Config Attributes - wi-fi_tech");
 		goto fail;
 	}
 	wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string);
 	if (os_strcmp(token->string, "infra") != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'",
 			   token->string);
+		dpp_auth_fail(auth, "Unsupported wi-fi_tech");
 		goto fail;
 	}
 
 	token = json_get_member(root, "netRole");
 	if (!token || token->type != JSON_STRING) {
-		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - netRole");
+		dpp_auth_fail(auth, "No Config Attributes - netRole");
 		goto fail;
 	}
 	wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
@@ -3495,6 +4594,7 @@
 	} else {
 		wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
 			   token->string);
+		dpp_auth_fail(auth, "Unsupported netRole");
 		goto fail;
 	}
 
@@ -3607,6 +4707,11 @@
 		os_strlcpy(auth->passphrase, pass->string,
 			   sizeof(auth->passphrase));
 	} else if (psk_hex && psk_hex->type == JSON_STRING) {
+		if (auth->akm == DPP_AKM_SAE) {
+			wpa_printf(MSG_DEBUG,
+				   "DPP: Unexpected psk_hex with akm=sae");
+			return -1;
+		}
 		if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
 		    hexstr2bin(psk_hex->string, auth->psk, PMK_LEN) < 0) {
 			wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
@@ -3620,6 +4725,12 @@
 		return -1;
 	}
 
+	if ((auth->akm == DPP_AKM_SAE || auth->akm == DPP_AKM_PSK_SAE) &&
+	    !auth->passphrase[0]) {
+		wpa_printf(MSG_DEBUG, "DPP: No pass for sae found");
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -3950,11 +5061,11 @@
 	size_t payload_len;
 };
 
-static int
+static enum dpp_status_error
 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
 			     EVP_PKEY *csign_pub, const char *connector)
 {
-	int ret = -1;
+	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;
@@ -3988,6 +5099,7 @@
 	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((const unsigned char *) pos,
@@ -3995,18 +5107,22 @@
 	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)
+	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;
 	}
 
@@ -4015,6 +5131,7 @@
 	if (!end) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Missing dot(2) in signedConnector");
+		ret = DPP_STATUS_INVALID_CONNECTOR;
 		goto fail;
 	}
 	signed_end = end - 1;
@@ -4023,6 +5140,7 @@
 	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,
@@ -4034,18 +5152,22 @@
 	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)
+	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;
 	}
 
@@ -4086,10 +5208,11 @@
 		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 = 0;
+	ret = DPP_STATUS_OK;
 fail:
 	EC_KEY_free(eckey);
 	EVP_MD_CTX_destroy(md_ctx);
@@ -4148,7 +5271,7 @@
 	}
 
 	if (dpp_process_signed_connector(&info, csign_pub,
-					 signed_connector) < 0)
+					 signed_connector) != DPP_STATUS_OK)
 		goto fail;
 
 	if (dpp_parse_connector(auth, info.payload, info.payload_len) < 0) {
@@ -4170,6 +5293,37 @@
 }
 
 
+const char * dpp_akm_str(enum dpp_akm akm)
+{
+	switch (akm) {
+	case DPP_AKM_DPP:
+		return "dpp";
+	case DPP_AKM_PSK:
+		return "psk";
+	case DPP_AKM_SAE:
+		return "sae";
+	case DPP_AKM_PSK_SAE:
+		return "psk+sae";
+	default:
+		return "??";
+	}
+}
+
+
+static enum dpp_akm dpp_akm_from_str(const char *akm)
+{
+	if (os_strcmp(akm, "psk") == 0)
+		return DPP_AKM_PSK;
+	if (os_strcmp(akm, "sae") == 0)
+		return DPP_AKM_SAE;
+	if (os_strcmp(akm, "psk+sae") == 0)
+		return DPP_AKM_PSK_SAE;
+	if (os_strcmp(akm, "dpp") == 0)
+		return DPP_AKM_DPP;
+	return DPP_AKM_UNKNOWN;
+}
+
+
 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
 			      const u8 *conf_obj, u16 conf_obj_len)
 {
@@ -4180,38 +5334,37 @@
 	if (!root)
 		return -1;
 	if (root->type != JSON_OBJECT) {
-		wpa_printf(MSG_DEBUG, "DPP: JSON root is not an object");
+		dpp_auth_fail(auth, "JSON root is not an object");
 		goto fail;
 	}
 
 	token = json_get_member(root, "wi-fi_tech");
 	if (!token || token->type != JSON_STRING) {
-		wpa_printf(MSG_DEBUG, "DPP: No wi-fi_tech string value found");
+		dpp_auth_fail(auth, "No wi-fi_tech string value found");
 		goto fail;
 	}
 	if (os_strcmp(token->string, "infra") != 0) {
 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
 			   token->string);
+		dpp_auth_fail(auth, "Unsupported wi-fi_tech value");
 		goto fail;
 	}
 
 	discovery = json_get_member(root, "discovery");
 	if (!discovery || discovery->type != JSON_OBJECT) {
-		wpa_printf(MSG_DEBUG, "DPP: No discovery object in JSON");
+		dpp_auth_fail(auth, "No discovery object in JSON");
 		goto fail;
 	}
 
 	token = json_get_member(discovery, "ssid");
 	if (!token || token->type != JSON_STRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No discovery::ssid string value found");
+		dpp_auth_fail(auth, "No discovery::ssid string value found");
 		goto fail;
 	}
 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
 			  token->string, os_strlen(token->string));
 	if (os_strlen(token->string) > SSID_MAX_LEN) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Too long discovery::ssid string value");
+		dpp_auth_fail(auth, "Too long discovery::ssid string value");
 		goto fail;
 	}
 	auth->ssid_len = os_strlen(token->string);
@@ -4219,25 +5372,28 @@
 
 	cred = json_get_member(root, "cred");
 	if (!cred || cred->type != JSON_OBJECT) {
-		wpa_printf(MSG_DEBUG, "DPP: No cred object in JSON");
+		dpp_auth_fail(auth, "No cred object in JSON");
 		goto fail;
 	}
 
 	token = json_get_member(cred, "akm");
 	if (!token || token->type != JSON_STRING) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No cred::akm string value found");
+		dpp_auth_fail(auth, "No cred::akm string value found");
 		goto fail;
 	}
-	if (os_strcmp(token->string, "psk") == 0) {
+	auth->akm = dpp_akm_from_str(token->string);
+
+	if (auth->akm == DPP_AKM_PSK || auth->akm == DPP_AKM_SAE ||
+	    auth->akm == DPP_AKM_PSK_SAE) {
 		if (dpp_parse_cred_legacy(auth, cred) < 0)
 			goto fail;
-	} else if (os_strcmp(token->string, "dpp") == 0) {
+	} else if (auth->akm == DPP_AKM_DPP) {
 		if (dpp_parse_cred_dpp(auth, cred) < 0)
 			goto fail;
 	} else {
 		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
 			   token->string);
+		dpp_auth_fail(auth, "Unsupported akm");
 		goto fail;
 	}
 
@@ -4261,8 +5417,7 @@
 	int ret = -1;
 
 	if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in config response");
+		dpp_auth_fail(auth, "Invalid attribute in config response");
 		return -1;
 	}
 
@@ -4270,8 +5425,8 @@
 				    DPP_ATTR_WRAPPED_DATA,
 				    &wrapped_data_len);
 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required Wrapped data attribute");
+		dpp_auth_fail(auth,
+			      "Missing or invalid required Wrapped Data attribute");
 		return -1;
 	}
 
@@ -4289,15 +5444,14 @@
 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
 			    wrapped_data, wrapped_data_len,
 			    1, addr, len, unwrapped) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in unwrapped data");
+		dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
 		goto fail;
 	}
 
@@ -4305,34 +5459,34 @@
 			       DPP_ATTR_ENROLLEE_NONCE,
 			       &e_nonce_len);
 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid Enrollee Nonce attribute");
+		dpp_auth_fail(auth,
+			      "Missing or invalid Enrollee Nonce attribute");
 		goto fail;
 	}
 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
-		wpa_printf(MSG_DEBUG, "Enrollee Nonce mismatch");
+		dpp_auth_fail(auth, "Enrollee Nonce mismatch");
 		goto fail;
 	}
 
 	status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
 			      DPP_ATTR_STATUS, &status_len);
 	if (!status || status_len < 1) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required DPP Status attribute");
+		dpp_auth_fail(auth,
+			      "Missing or invalid required DPP Status attribute");
 		goto fail;
 	}
 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
 	if (status[0] != DPP_STATUS_OK) {
-		wpa_printf(MSG_DEBUG, "DPP: Configuration failed");
+		dpp_auth_fail(auth, "Configurator rejected configuration");
 		goto fail;
 	}
 
 	conf_obj = dpp_get_attr(unwrapped, unwrapped_len,
 				DPP_ATTR_CONFIG_OBJ, &conf_obj_len);
 	if (!conf_obj) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing required Configuration Object attribute");
+		dpp_auth_fail(auth,
+			      "Missing required Configuration Object attribute");
 		goto fail;
 	}
 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
@@ -4358,6 +5512,30 @@
 }
 
 
+int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
+			     size_t buflen)
+{
+	EC_KEY *eckey;
+	int key_len, ret = -1;
+	unsigned char *key = NULL;
+
+	if (!conf->csign)
+		return -1;
+
+	eckey = EVP_PKEY_get1_EC_KEY(conf->csign);
+	if (!eckey)
+		return -1;
+
+	key_len = i2d_ECPrivateKey(eckey, &key);
+	if (key_len > 0)
+		ret = wpa_snprintf_hex(buf, buflen, key, key_len);
+
+	EC_KEY_free(eckey);
+	OPENSSL_free(key);
+	return ret;
+}
+
+
 struct dpp_configurator *
 dpp_keygen_configurator(const char *curve, const u8 *privkey,
 			size_t privkey_len)
@@ -4421,7 +5599,7 @@
 
 
 int dpp_configurator_own_config(struct dpp_authentication *auth,
-				const char *curve)
+				const char *curve, int ap)
 {
 	struct wpabuf *conf_obj;
 	int ret = -1;
@@ -4452,7 +5630,7 @@
 	auth->peer_protocol_key = auth->own_protocol_key;
 	dpp_copy_csign(auth, auth->conf->csign);
 
-	conf_obj = dpp_build_conf_obj(auth, 0);
+	conf_obj = dpp_build_conf_obj(auth, ap);
 	if (!conf_obj)
 		goto fail;
 	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
@@ -4615,15 +5793,16 @@
 }
 
 
-int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
-		   const u8 *net_access_key, size_t net_access_key_len,
-		   const u8 *csign_key, size_t csign_key_len,
-		   const u8 *peer_connector, size_t peer_connector_len,
-		   os_time_t *expiry)
+enum dpp_status_error
+dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
+	       const u8 *net_access_key, size_t net_access_key_len,
+	       const u8 *csign_key, size_t csign_key_len,
+	       const u8 *peer_connector, size_t peer_connector_len,
+	       os_time_t *expiry)
 {
 	struct json_token *root = NULL, *netkey, *token;
 	struct json_token *own_root = NULL;
-	int ret = -1;
+	enum dpp_status_error ret = 255, res;
 	EVP_PKEY *own_key = NULL, *peer_key = NULL;
 	struct wpabuf *own_key_pub = NULL;
 	const struct dpp_curve_params *curve, *own_curve;
@@ -4691,18 +5870,23 @@
 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
 	signed_connector[peer_connector_len] = '\0';
 
-	if (dpp_process_signed_connector(&info, csign, signed_connector) < 0)
+	res = dpp_process_signed_connector(&info, csign, signed_connector);
+	if (res != DPP_STATUS_OK) {
+		ret = res;
 		goto fail;
+	}
 
 	root = json_parse((const char *) info.payload, info.payload_len);
 	if (!root) {
 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
+		ret = DPP_STATUS_INVALID_CONNECTOR;
 		goto fail;
 	}
 
 	if (!dpp_connector_match_groups(own_root, root)) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Peer connector does not include compatible group netrole with own connector");
+		ret = DPP_STATUS_NO_MATCH;
 		goto fail;
 	}
 
@@ -4715,6 +5899,7 @@
 		if (dpp_key_expired(token->string, expiry)) {
 			wpa_printf(MSG_DEBUG,
 				   "DPP: Connector (netAccessKey) has expired");
+			ret = DPP_STATUS_INVALID_CONNECTOR;
 			goto fail;
 		}
 	}
@@ -4722,18 +5907,22 @@
 	netkey = json_get_member(root, "netAccessKey");
 	if (!netkey || netkey->type != JSON_OBJECT) {
 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
+		ret = DPP_STATUS_INVALID_CONNECTOR;
 		goto fail;
 	}
 
 	peer_key = dpp_parse_jwk(netkey, &curve);
-	if (!peer_key)
+	if (!peer_key) {
+		ret = DPP_STATUS_INVALID_CONNECTOR;
 		goto fail;
+	}
 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
 
 	if (own_curve != curve) {
 		wpa_printf(MSG_DEBUG,
 			   "DPP: Mismatching netAccessKey curves (%s != %s)",
 			   own_curve->name, curve->name);
+		ret = DPP_STATUS_INVALID_CONNECTOR;
 		goto fail;
 	}
 
@@ -4767,9 +5956,9 @@
 		goto fail;
 	}
 
-	ret = 0;
+	ret = DPP_STATUS_OK;
 fail:
-	if (ret < 0)
+	if (ret != DPP_STATUS_OK)
 		os_memset(intro, 0, sizeof(*intro));
 	os_memset(Nx, 0, sizeof(Nx));
 	EVP_PKEY_CTX_free(ctx);
@@ -4893,9 +6082,10 @@
 	    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, "PDP: Qi is the point-at-infinity");
+		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);
@@ -4973,6 +6163,11 @@
 	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);
@@ -4987,6 +6182,72 @@
 }
 
 
+#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 >= 0x10101000L || 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.1 or OPENSSL_IS_BORINGSSL */
+			goto fail;
+#endif /* >= 1.1.1 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);
+
+	return ret;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
 static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
 {
 	EC_KEY *X_ec = NULL;
@@ -4999,7 +6260,6 @@
 	struct wpabuf *msg = NULL;
 	size_t attr_len;
 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-	int num_bytes, offset;
 
 	wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
 
@@ -5013,7 +6273,21 @@
 		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;
 
@@ -5024,6 +6298,7 @@
 	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();
@@ -5031,6 +6306,7 @@
 	    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;
@@ -5041,11 +6317,22 @@
 	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);
@@ -5053,31 +6340,32 @@
 		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);
 
-	num_bytes = BN_num_bytes(Mx);
-	if ((size_t) num_bytes > curve->prime_len)
-		goto fail;
-	if (curve->prime_len > (size_t) num_bytes)
-		offset = curve->prime_len - num_bytes;
-	else
-		offset = 0;
-	os_memset(wpabuf_put(msg, offset), 0, offset);
-	BN_bn2bin(Mx, wpabuf_put(msg, num_bytes));
-	os_memset(pkex->Mx, 0, offset);
-	BN_bn2bin(Mx, pkex->Mx + offset);
+#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 */
 
-	num_bytes = BN_num_bytes(My);
-	if ((size_t) num_bytes > curve->prime_len)
+	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;
-	if (curve->prime_len > (size_t) num_bytes)
-		offset = curve->prime_len - num_bytes;
-	else
-		offset = 0;
-	os_memset(wpabuf_put(msg, offset), 0, offset);
-	BN_bn2bin(My, wpabuf_put(msg, num_bytes));
 
 out:
 	wpabuf_free(M_buf);
@@ -5096,16 +6384,31 @@
 }
 
 
-struct dpp_pkex * dpp_pkex_init(struct dpp_bootstrap_info *bi,
+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);
@@ -5127,158 +6430,42 @@
 }
 
 
-struct dpp_pkex * dpp_pkex_rx_exchange_req(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)
+static struct wpabuf *
+dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex,
+			     enum dpp_status_error status,
+			     const BIGNUM *Nx, const BIGNUM *Ny)
 {
-	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;
-	const EC_GROUP *group;
-	BIGNUM *Mx = NULL, *My = NULL;
-	EC_KEY *Y_ec = NULL, *X_ec = NULL;;
-	const EC_POINT *Y_point;
-	BIGNUM *Nx = NULL, *Ny = NULL;
 	struct wpabuf *msg = NULL;
 	size_t attr_len;
-	int num_bytes, offset;
-
-	attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
-			       &attr_id_len);
-	if (!attr_id && identifier) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No PKEX code identifier received, but expected one");
-		return NULL;
-	}
-	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 NULL;
-	}
-
-	attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
-				  &attr_group_len);
-	if (!attr_group || attr_group_len != 2) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid Finite Cyclic Group attribute");
-		return NULL;
-	}
-	ike_group = WPA_GET_LE16(attr_group);
-	if (ike_group != curve->ike_group) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Mismatching PKEX curve: peer=%u own=%u",
-			   ike_group, curve->ike_group);
-		/* TODO: error response with suggested curve:
-		 * DPP Status, group */
-		return NULL;
-	}
-
-	/* 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_printf(MSG_DEBUG, "DPP: 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))
-		goto fail;
-
-	pkex = os_zalloc(sizeof(*pkex));
-	if (!pkex)
-		goto fail;
-	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 */
-	pkex->y = dpp_gen_keypair(curve);
-	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;
-	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;
+	const struct dpp_curve_params *curve = pkex->own_bi->curve;
 
 	/* Initiator -> Responder: DPP Status, [identifier,] N */
 	attr_len = 4 + 1;
-	if (identifier)
-		attr_len += 4 + os_strlen(identifier);
+	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 */
-	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
-	wpabuf_put_le16(msg, 1);
-	wpabuf_put_u8(msg, DPP_STATUS_OK);
+	dpp_build_attr_status(msg, status);
+
+#ifdef CONFIG_TESTING_OPTIONS
+skip_status:
+#endif /* CONFIG_TESTING_OPTIONS */
 
 	/* Code Identifier attribute */
 	if (pkex->identifier) {
@@ -5287,56 +6474,48 @@
 		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);
 
-	num_bytes = BN_num_bytes(Nx);
-	if ((size_t) num_bytes > 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;
-	if (curve->prime_len > (size_t) num_bytes)
-		offset = curve->prime_len - num_bytes;
-	else
-		offset = 0;
-	os_memset(wpabuf_put(msg, offset), 0, offset);
-	BN_bn2bin(Nx, wpabuf_put(msg, num_bytes));
-	os_memset(pkex->Nx, 0, offset);
-	BN_bn2bin(Nx, pkex->Nx + offset);
 
-	num_bytes = BN_num_bytes(Ny);
-	if ((size_t) num_bytes > curve->prime_len)
-		goto fail;
-	if (curve->prime_len > (size_t) num_bytes)
-		offset = curve->prime_len - num_bytes;
-	else
-		offset = 0;
-	os_memset(wpabuf_put(msg, offset), 0, offset);
-	BN_bn2bin(Ny, wpabuf_put(msg, num_bytes));
+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);
+	}
 
-	pkex->exchange_resp = msg;
-	msg = NULL;
-	pkex->exchange_done = 1;
-
-out:
-	wpabuf_free(msg);
-	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);
-	return pkex;
+	return msg;
 fail:
-	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing faileed");
-	dpp_pkex_free(pkex);
-	pkex = NULL;
-	goto out;
+	wpabuf_free(msg);
+	return NULL;
 }
 
 
@@ -5399,16 +6578,376 @@
 }
 
 
-struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
-					  const u8 *buf, size_t buflen)
+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_status, *attr_id, *attr_key;
-	u16 attr_status_len, attr_id_len, attr_key_len;
-	const EC_GROUP *group;
+	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;
-	size_t clear_len;
+	const EC_GROUP *group;
+	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;
+	EVP_PKEY_CTX *ctx = NULL;
+
+	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 = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
+			       &attr_id_len);
+	if (!attr_id && identifier) {
+		wpa_printf(MSG_DEBUG,
+			   "DPP: No PKEX code identifier received, but expected one");
+		return NULL;
+	}
+	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 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' */
+	ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
+	if (!ctx ||
+	    EVP_PKEY_derive_init(ctx) != 1 ||
+	    EVP_PKEY_derive_set_peer(ctx, pkex->x) != 1 ||
+	    EVP_PKEY_derive(ctx, NULL, &Kx_len) != 1 ||
+	    Kx_len > DPP_MAX_SHARED_SECRET_LEN ||
+	    EVP_PKEY_derive(ctx, Kx, &Kx_len) != 1) {
+		wpa_printf(MSG_ERROR,
+			   "DPP: Failed to derive ECDH shared secret: %s",
+			   ERR_error_string(ERR_get_error(), NULL));
+		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:
+	EVP_PKEY_CTX_free(ctx);
+	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);
+	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;
+	const EC_GROUP *group;
+	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;
@@ -5420,18 +6959,50 @@
 	const u8 *addr[4];
 	size_t len[4];
 	u8 u[DPP_MAX_HASH_LEN];
-	u8 octet;
 	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) {
-		wpa_printf(MSG_DEBUG, "DPP: No DPP Status attribute");
+		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) {
-		wpa_printf(MSG_DEBUG, "DPP: PKEX failed");
+		dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)");
 		return NULL;
 	}
 
@@ -5445,7 +7016,7 @@
 	if (attr_id && pkex->identifier &&
 	    (os_strlen(pkex->identifier) != attr_id_len ||
 	     os_memcmp(pkex->identifier, attr_id, attr_id_len) != 0)) {
-		wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
+		dpp_pkex_fail(pkex, "PKEX code identifier mismatch");
 		return NULL;
 	}
 
@@ -5453,7 +7024,7 @@
 	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) {
-		wpa_printf(MSG_DEBUG, "DPP: Missing Encrypted Key attribute");
+		dpp_pkex_fail(pkex, "Missing Encrypted Key attribute");
 		return NULL;
 	}
 
@@ -5478,8 +7049,13 @@
 	    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))
+	    !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;
 
@@ -5556,27 +7132,106 @@
 	if (res < 0)
 		goto fail;
 
-	/* {A, u, [bootstrapping info]}z */
+	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);
+	EVP_PKEY_CTX_free(ctx);
+	BN_CTX_free(bnctx);
+	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);
-	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ,
-			    4 + clear_len + AES_BLOCK_SIZE);
+	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;
 
-	/* 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
+	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 */
 
-	/* u in I-Auth tag attribute */
-	wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
+	/* 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, u, 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 = 0;
+	octet = 1;
 	addr[1] = &octet;
 	len[1] = sizeof(octet);
 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
@@ -5594,22 +7249,19 @@
 	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);
-	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);
-	EVP_PKEY_CTX_free(ctx);
-	BN_CTX_free(bnctx);
 	return msg;
+
 fail:
-	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing faileed");
 	wpabuf_free(msg);
 	msg = NULL;
 	goto out;
@@ -5621,9 +7273,9 @@
 					      const u8 *buf, size_t buflen)
 {
 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
-	EVP_PKEY_CTX *ctx;
-	size_t Jx_len, Kx_len, Lx_len;
-	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
+	EVP_PKEY_CTX *ctx = NULL;
+	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;
@@ -5635,43 +7287,25 @@
 	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];
-	size_t clear_len;
-	struct wpabuf *clear = NULL;
-	u8 *wrapped;
-	int res;
 
-	/* K = y * X' */
-	ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
-	if (!ctx ||
-	    EVP_PKEY_derive_init(ctx) != 1 ||
-	    EVP_PKEY_derive_set_peer(ctx, pkex->x) != 1 ||
-	    EVP_PKEY_derive(ctx, NULL, &Kx_len) != 1 ||
-	    Kx_len > DPP_MAX_SHARED_SECRET_LEN ||
-	    EVP_PKEY_derive(ctx, Kx, &Kx_len) != 1) {
-		wpa_printf(MSG_ERROR,
-			   "DPP: Failed to derive ECDH shared secret: %s",
-			   ERR_error_string(ERR_get_error(), NULL));
-		goto fail;
+#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 */
 
-	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)
+	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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required Wrapped data attribute");
+		dpp_pkex_fail(pkex,
+			      "Missing or invalid required Wrapped Data attribute");
 		goto fail;
 	}
 
@@ -5693,34 +7327,36 @@
 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
 			    wrapped_data, wrapped_data_len,
 			    2, addr, len, unwrapped) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in unwrapped data");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No valid peer bootstrapping key found");
+		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)
+	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' */
-	EVP_PKEY_CTX_free(ctx);
 	ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
 	if (!ctx ||
 	    EVP_PKEY_derive_init(ctx) != 1 ||
@@ -5758,10 +7394,11 @@
 			      &peer_u_len);
 	if (!peer_u || peer_u_len != curve->hash_len ||
 	    os_memcmp(peer_u, u, curve->hash_len) != 0) {
-		wpa_printf(MSG_DEBUG, "DPP: No valid u (I-Auth tag) found");
+		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");
@@ -5800,43 +7437,10 @@
 		goto fail;
 	wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
 
-	/* {B, v [bootstrapping info]}z */
-	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
-	clear = wpabuf_alloc(clear_len);
-	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP,
-			    4 + clear_len + AES_BLOCK_SIZE);
-	if (!clear || !msg)
+	msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v);
+	if (!msg)
 		goto fail;
 
-	/* A 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);
-
-	/* 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);
-
-	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);
 out:
 	EVP_PKEY_CTX_free(ctx);
 	os_free(unwrapped);
@@ -5844,11 +7448,10 @@
 	wpabuf_free(B_pub);
 	wpabuf_free(X_pub);
 	wpabuf_free(Y_pub);
-	wpabuf_free(clear);
 	return msg;
 fail:
-	wpabuf_free(msg);
-	msg = NULL;
+	wpa_printf(MSG_DEBUG,
+		   "DPP: PKEX Commit-Reveal Request processing failed");
 	goto out;
 }
 
@@ -5871,11 +7474,24 @@
 	EVP_PKEY_CTX *ctx = NULL;
 	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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Missing or invalid required Wrapped data attribute");
+		dpp_pkex_fail(pkex,
+			      "Missing or invalid required Wrapped Data attribute");
 		goto fail;
 	}
 
@@ -5897,29 +7513,31 @@
 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
 			    wrapped_data, wrapped_data_len,
 			    2, addr, len, unwrapped) < 0) {
-		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: Invalid attribute in unwrapped data");
+		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) {
-		wpa_printf(MSG_DEBUG,
-			   "DPP: No valid peer bootstrapping key found");
+		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)
+	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);
 
@@ -5961,10 +7579,11 @@
 			      &peer_v_len);
 	if (!peer_v || peer_v_len != curve->hash_len ||
 	    os_memcmp(peer_v, v, curve->hash_len) != 0) {
-		wpa_printf(MSG_DEBUG, "DPP: No valid v (R-Auth tag) found");
+		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");
@@ -5996,3 +7615,56 @@
 	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((const unsigned char *) 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 = (char *) base64_url_encode(signature, signature_len,
+					     &signed3_len, 0);
+	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 */
diff --git a/src/common/dpp.h b/src/common/dpp.h
index dfee499..185a31c 100644
--- a/src/common/dpp.h
+++ b/src/common/dpp.h
@@ -52,6 +52,8 @@
 	DPP_ATTR_ENROLLEE_NONCE = 0x1014,
 	DPP_ATTR_CODE_IDENTIFIER = 0x1015,
 	DPP_ATTR_TRANSACTION_ID = 0x1016,
+	DPP_ATTR_BOOTSTRAP_INFO = 0x1017,
+	DPP_ATTR_CHANNEL = 0x1018,
 };
 
 enum dpp_status_error {
@@ -62,6 +64,8 @@
 	DPP_STATUS_BAD_GROUP = 4,
 	DPP_STATUS_CONFIGURE_FAILURE = 5,
 	DPP_STATUS_RESPONSE_PENDING = 6,
+	DPP_STATUS_INVALID_CONNECTOR = 7,
+	DPP_STATUS_NO_MATCH = 8,
 };
 
 #define DPP_CAPAB_ENROLLEE BIT(0)
@@ -102,11 +106,17 @@
 	EVP_PKEY *pubkey;
 	u8 pubkey_hash[SHA256_MAC_LEN];
 	const struct dpp_curve_params *curve;
+	unsigned int pkex_t; /* number of failures before dpp_pkex
+			      * instantiation */
 };
 
+#define PKEX_COUNTER_T_LIMIT 5
+
 struct dpp_pkex {
+	void *msg_ctx;
 	unsigned int initiator:1;
 	unsigned int exchange_done:1;
+	unsigned int failed:1;
 	struct dpp_bootstrap_info *own_bi;
 	u8 own_mac[ETH_ALEN];
 	u8 peer_mac[ETH_ALEN];
@@ -120,12 +130,24 @@
 	EVP_PKEY *peer_bootstrap_key;
 	struct wpabuf *exchange_req;
 	struct wpabuf *exchange_resp;
+	unsigned int t; /* number of failures on code use */
+	unsigned int exch_req_wait_time;
+	unsigned int exch_req_tries;
+	unsigned int freq;
+};
+
+enum dpp_akm {
+	DPP_AKM_UNKNOWN,
+	DPP_AKM_DPP,
+	DPP_AKM_PSK,
+	DPP_AKM_SAE,
+	DPP_AKM_PSK_SAE
 };
 
 struct dpp_configuration {
 	u8 ssid[32];
 	size_t ssid_len;
-	int dpp; /* whether to use DPP or legacy configuration */
+	enum dpp_akm akm;
 
 	/* For DPP configuration (connector) */
 	os_time_t netaccesskey_expiry;
@@ -142,6 +164,7 @@
 	const struct dpp_curve_params *curve;
 	struct dpp_bootstrap_info *peer_bi;
 	struct dpp_bootstrap_info *own_bi;
+	struct dpp_bootstrap_info *tmp_own_bi;
 	u8 waiting_pubkey_hash[SHA256_MAC_LEN];
 	int response_pending;
 	enum dpp_status_error auth_resp_status;
@@ -155,19 +178,34 @@
 	EVP_PKEY *peer_protocol_key;
 	struct wpabuf *req_msg;
 	struct wpabuf *resp_msg;
+	/* Intersection of possible frequencies for initiating DPP
+	 * Authentication exchange */
+	unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
+	unsigned int num_freq, freq_idx;
 	unsigned int curr_freq;
+	unsigned int neg_freq;
+	unsigned int num_freq_iters;
 	size_t secret_len;
 	u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
+	size_t Mx_len;
 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
+	size_t Nx_len;
 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
+	size_t Lx_len;
 	u8 k1[DPP_MAX_HASH_LEN];
 	u8 k2[DPP_MAX_HASH_LEN];
 	u8 ke[DPP_MAX_HASH_LEN];
 	int initiator;
+	int waiting_auth_resp;
+	int waiting_auth_conf;
+	int auth_req_ack;
+	unsigned int auth_resp_tries;
+	u8 allowed_roles;
 	int configurator;
 	int remove_on_tx_status;
 	int auth_success;
 	struct wpabuf *conf_req;
+	const struct wpabuf *conf_resp; /* owned by GAS server */
 	struct dpp_configuration *conf_ap;
 	struct dpp_configuration *conf_sta;
 	struct dpp_configurator *conf;
@@ -177,6 +215,7 @@
 	char passphrase[64];
 	u8 psk[PMK_LEN];
 	int psk_set;
+	enum dpp_akm akm;
 	struct wpabuf *net_access_key;
 	os_time_t net_access_key_expiry;
 	struct wpabuf *c_sign_key;
@@ -203,6 +242,112 @@
 	size_t pmk_len;
 };
 
+#ifdef CONFIG_TESTING_OPTIONS
+enum dpp_test_behavior {
+	DPP_TEST_DISABLED = 0,
+	DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ = 1,
+	DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP = 2,
+	DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF = 3,
+	DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ = 4,
+	DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP = 5,
+	DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ = 6,
+	DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP = 7,
+	DPP_TEST_ZERO_I_CAPAB = 8,
+	DPP_TEST_ZERO_R_CAPAB = 9,
+	DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ = 10,
+	DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ = 11,
+	DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ = 12,
+	DPP_TEST_NO_I_NONCE_AUTH_REQ = 13,
+	DPP_TEST_NO_I_CAPAB_AUTH_REQ = 14,
+	DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ = 15,
+	DPP_TEST_NO_STATUS_AUTH_RESP = 16,
+	DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP = 17,
+	DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP = 18,
+	DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP = 19,
+	DPP_TEST_NO_R_NONCE_AUTH_RESP = 20,
+	DPP_TEST_NO_I_NONCE_AUTH_RESP = 21,
+	DPP_TEST_NO_R_CAPAB_AUTH_RESP = 22,
+	DPP_TEST_NO_R_AUTH_AUTH_RESP = 23,
+	DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP = 24,
+	DPP_TEST_NO_STATUS_AUTH_CONF = 25,
+	DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF = 26,
+	DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF = 27,
+	DPP_TEST_NO_I_AUTH_AUTH_CONF = 28,
+	DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF = 29,
+	DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP = 30,
+	DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP = 31,
+	DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP = 32,
+	DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF = 33,
+	DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ = 34,
+	DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ = 35,
+	DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP = 36,
+	DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP = 37,
+	DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ = 38,
+	DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ = 39,
+	DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ = 40,
+	DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP = 41,
+	DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP = 42,
+	DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP = 43,
+	DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ = 44,
+	DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP = 45,
+	DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP = 46,
+	DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ = 47,
+	DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP = 48,
+	DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ = 49,
+	DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP = 50,
+	DPP_TEST_NO_E_NONCE_CONF_REQ = 51,
+	DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ = 52,
+	DPP_TEST_NO_WRAPPED_DATA_CONF_REQ = 53,
+	DPP_TEST_NO_E_NONCE_CONF_RESP = 54,
+	DPP_TEST_NO_CONFIG_OBJ_CONF_RESP = 55,
+	DPP_TEST_NO_STATUS_CONF_RESP = 56,
+	DPP_TEST_NO_WRAPPED_DATA_CONF_RESP = 57,
+	DPP_TEST_INVALID_STATUS_CONF_RESP = 58,
+	DPP_TEST_E_NONCE_MISMATCH_CONF_RESP = 59,
+	DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ = 60,
+	DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ = 61,
+	DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP = 62,
+	DPP_TEST_NO_STATUS_PEER_DISC_RESP = 63,
+	DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP = 64,
+	DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF = 65,
+	DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ = 66,
+	DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP = 67,
+	DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ = 68,
+	DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ = 69,
+	DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP = 70,
+	DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP = 71,
+	DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF = 72,
+	DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF = 73,
+	DPP_TEST_INVALID_STATUS_AUTH_RESP = 74,
+	DPP_TEST_INVALID_STATUS_AUTH_CONF = 75,
+	DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ = 76,
+	DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP = 77,
+	DPP_TEST_INVALID_STATUS_PEER_DISC_RESP = 78,
+	DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP = 79,
+	DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ = 80,
+	DPP_TEST_INVALID_I_NONCE_AUTH_REQ = 81,
+	DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ = 82,
+	DPP_TEST_INVALID_E_NONCE_CONF_REQ = 83,
+	DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP = 84,
+	DPP_TEST_STOP_AT_PKEX_CR_REQ = 85,
+	DPP_TEST_STOP_AT_PKEX_CR_RESP = 86,
+	DPP_TEST_STOP_AT_AUTH_REQ = 87,
+	DPP_TEST_STOP_AT_AUTH_RESP = 88,
+	DPP_TEST_STOP_AT_AUTH_CONF = 89,
+	DPP_TEST_STOP_AT_CONF_REQ = 90,
+};
+
+extern enum dpp_test_behavior dpp_test;
+extern u8 dpp_pkex_own_mac_override[ETH_ALEN];
+extern u8 dpp_pkex_peer_mac_override[ETH_ALEN];
+extern u8 dpp_pkex_ephemeral_key_override[600];
+extern size_t dpp_pkex_ephemeral_key_override_len;
+extern u8 dpp_protocol_key_override[600];
+extern size_t dpp_protocol_key_override_len;
+extern u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
+extern size_t dpp_nonce_override_len;
+#endif /* CONFIG_TESTING_OPTIONS */
+
 void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info);
 const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type);
 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi);
@@ -213,16 +358,20 @@
 struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri);
 char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
 		  const u8 *privkey, size_t privkey_len);
+struct hostapd_hw_modes;
 struct dpp_authentication * dpp_auth_init(void *msg_ctx,
 					  struct dpp_bootstrap_info *peer_bi,
 					  struct dpp_bootstrap_info *own_bi,
-					  int configurator);
+					  u8 dpp_allowed_roles,
+					  unsigned int neg_freq,
+					  struct hostapd_hw_modes *own_modes,
+					  u16 num_modes);
 struct dpp_authentication *
 dpp_auth_req_rx(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,
-		const u8 *wrapped_data, u16 wrapped_data_len);
+		size_t attr_len);
 struct wpabuf *
 dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
 		 const u8 *attr_start, size_t attr_len);
@@ -244,28 +393,34 @@
 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len);
 int dpp_check_attrs(const u8 *buf, size_t len);
 int dpp_key_expired(const char *timestamp, os_time_t *expiry);
+const char * dpp_akm_str(enum dpp_akm akm);
+int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
+			     size_t buflen);
 void dpp_configurator_free(struct dpp_configurator *conf);
 struct dpp_configurator *
 dpp_keygen_configurator(const char *curve, const u8 *privkey,
 			size_t privkey_len);
 int dpp_configurator_own_config(struct dpp_authentication *auth,
-				const char *curve);
-int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
-		   const u8 *net_access_key, size_t net_access_key_len,
-		   const u8 *csign_key, size_t csign_key_len,
-		   const u8 *peer_connector, size_t peer_connector_len,
-		   os_time_t *expiry);
-struct dpp_pkex * dpp_pkex_init(struct dpp_bootstrap_info *bi,
+				const char *curve, int ap);
+enum dpp_status_error
+dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
+	       const u8 *net_access_key, size_t net_access_key_len,
+	       const u8 *csign_key, size_t csign_key_len,
+	       const u8 *peer_connector, size_t peer_connector_len,
+	       os_time_t *expiry);
+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 * dpp_pkex_rx_exchange_req(struct dpp_bootstrap_info *bi,
+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);
 struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
+					  const u8 *peer_mac,
 					  const u8 *buf, size_t len);
 struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
 					      const u8 *hdr,
@@ -274,4 +429,6 @@
 				   const u8 *buf, size_t len);
 void dpp_pkex_free(struct dpp_pkex *pkex);
 
+char * dpp_corrupt_connector_signature(const char *connector);
+
 #endif /* DPP_H */
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index fdd5e73..db40379 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -89,7 +89,7 @@
 {
 	int ok, j, first;
 	int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
-			  149, 157, 184, 192 };
+			  149, 157, 165, 184, 192 };
 	size_t k;
 
 	if (pri_chan == sec_chan || !sec_chan)
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 120d4e8..e1ef277 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -11,6 +11,7 @@
 #include "common.h"
 #include "defs.h"
 #include "wpa_common.h"
+#include "drivers/driver.h"
 #include "qca-vendor.h"
 #include "ieee802_11_defs.h"
 #include "ieee802_11_common.h"
@@ -120,6 +121,11 @@
 			elems->mbo = pos;
 			elems->mbo_len = elen;
 			break;
+		case HS20_ROAMING_CONS_SEL_OUI_TYPE:
+			/* Hotspot 2.0 Roaming Consortium Selection */
+			elems->roaming_cons_sel = pos;
+			elems->roaming_cons_sel_len = elen;
+			break;
 		default:
 			wpa_printf(MSG_MSGDUMP, "Unknown WFA "
 				   "information element ignored "
@@ -256,6 +262,10 @@
 		elems->owe_dh = pos;
 		elems->owe_dh_len = elen;
 		break;
+	case WLAN_EID_EXT_PASSWORD_IDENTIFIER:
+		elems->password_id = pos;
+		elems->password_id_len = elen;
+		break;
 	default:
 		if (show_errors) {
 			wpa_printf(MSG_MSGDUMP,
@@ -352,6 +362,10 @@
 			elems->rsn_ie_len = elen;
 			break;
 		case WLAN_EID_PWR_CAPABILITY:
+			if (elen < 2)
+				break;
+			elems->power_capab = pos;
+			elems->power_capab_len = elen;
 			break;
 		case WLAN_EID_SUPPORTED_CHANNELS:
 			elems->supp_channels = pos;
@@ -1169,10 +1183,24 @@
 }
 
 
-int ieee80211_is_dfs(int freq)
+int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
+		     u16 num_modes)
 {
-	/* TODO: this could be more accurate to better cover all domains */
-	return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
+	int i, j;
+
+	if (!modes || !num_modes)
+		return (freq >= 5260 && freq <= 5320) ||
+			(freq >= 5500 && freq <= 5700);
+
+	for (i = 0; i < num_modes; i++) {
+		for (j = 0; j < modes[i].num_channels; j++) {
+			if (modes[i].channels[j].freq == freq &&
+			    (modes[i].channels[j].flag & HOSTAPD_CHAN_RADAR))
+				return 1;
+		}
+	}
+
+	return 0;
 }
 
 
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 9276158..ff7e51d 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -11,6 +11,8 @@
 
 #include "defs.h"
 
+struct hostapd_hw_modes;
+
 #define MAX_NOF_MB_IES_SUPPORTED 5
 
 struct mb_ies_info {
@@ -79,6 +81,9 @@
 	const u8 *fils_pk;
 	const u8 *fils_nonce;
 	const u8 *owe_dh;
+	const u8 *power_capab;
+	const u8 *roaming_cons_sel;
+	const u8 *password_id;
 
 	u8 ssid_len;
 	u8 supp_rates_len;
@@ -122,6 +127,9 @@
 	u8 fils_wrapped_data_len;
 	u8 fils_pk_len;
 	u8 owe_dh_len;
+	u8 power_capab_len;
+	u8 roaming_cons_sel_len;
+	u8 password_id_len;
 
 	struct mb_ies_info mb_ies;
 };
@@ -152,7 +160,8 @@
 enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
 						   int sec_channel, int vht,
 						   u8 *op_class, u8 *channel);
-int ieee80211_is_dfs(int freq);
+int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
+		     u16 num_modes);
 enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
 
 int supp_rates_11b_only(struct ieee802_11_elems *elems);
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index b7fa563..e03a095 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -203,6 +203,7 @@
 #define WLAN_STATUS_AUTHORIZATION_DEENABLED 107
 #define WLAN_STATUS_FILS_AUTHENTICATION_FAILURE 112
 #define WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER 113
+#define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123
 
 /* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
 #define WLAN_REASON_UNSPECIFIED 1
@@ -463,6 +464,7 @@
 #define WLAN_EID_EXT_FILS_NONCE 13
 #define WLAN_EID_EXT_FUTURE_CHANNEL_GUIDANCE 14
 #define WLAN_EID_EXT_OWE_DH_PARAM 32
+#define WLAN_EID_EXT_PASSWORD_IDENTIFIER 33
 #define WLAN_EID_EXT_HE_CAPABILITIES 35
 #define WLAN_EID_EXT_HE_OPERATION 36
 
@@ -1317,6 +1319,7 @@
 #define HS20_INDICATION_OUI_TYPE 16
 #define HS20_ANQP_OUI_TYPE 17
 #define HS20_OSEN_OUI_TYPE 18
+#define HS20_ROAMING_CONS_SEL_OUI_TYPE 29
 #define HS20_STYPE_QUERY_LIST 1
 #define HS20_STYPE_CAPABILITY_LIST 2
 #define HS20_STYPE_OPERATOR_FRIENDLY_NAME 3
@@ -1327,15 +1330,19 @@
 #define HS20_STYPE_OSU_PROVIDERS_LIST 8
 #define HS20_STYPE_ICON_REQUEST 10
 #define HS20_STYPE_ICON_BINARY_FILE 11
+#define HS20_STYPE_OPERATOR_ICON_METADATA 12
 
 #define HS20_DGAF_DISABLED 0x01
 #define HS20_PPS_MO_ID_PRESENT 0x02
 #define HS20_ANQP_DOMAIN_ID_PRESENT 0x04
+#ifndef HS20_VERSION
 #define HS20_VERSION 0x10 /* Release 2 */
+#endif /* HS20_VERSION */
 
 /* WNM-Notification WFA vendors specific subtypes */
 #define HS20_WNM_SUB_REM_NEEDED 0
 #define HS20_WNM_DEAUTH_IMMINENT_NOTICE 1
+#define HS20_WNM_T_C_ACCEPTANCE 2
 
 #define HS20_DEAUTH_REASON_CODE_BSS 0
 #define HS20_DEAUTH_REASON_CODE_ESS 1
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index b4f7d12..7c2be1f 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -1,6 +1,7 @@
 /*
  * Qualcomm Atheros OUI and vendor specific assignments
  * Copyright (c) 2014-2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -90,6 +91,49 @@
  *	which supports DFS offloading, to indicate a radar pattern has been
  *	detected. The channel is now unusable.
  *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET: Get the feature bitmap
+ *	based on enum wifi_logger_supported_features. Attributes defined in
+ *	enum qca_wlan_vendor_attr_get_logger_features.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA: Get the ring data from a particular
+ *	logger ring, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID is passed as the
+ *	attribute for this command. Attributes defined in
+ *	enum qca_wlan_vendor_attr_wifi_logger_start.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES: Get the supported TDLS
+ *	capabilities of the driver, parameters includes the attributes defined
+ *	in enum qca_wlan_vendor_attr_tdls_get_capabilities.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS: Vendor command used to offload
+ *	sending of certain periodic IP packet to firmware, attributes defined in
+ *	enum qca_wlan_vendor_attr_offloaded_packets.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI: Command used to configure RSSI
+ *	monitoring, defines min and max RSSI which are configured for RSSI
+ *	monitoring. Also used to notify the RSSI breach and provides the BSSID
+ *	and RSSI value that was breached. Attributes defined in
+ *	enum qca_wlan_vendor_attr_rssi_monitoring.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_NDP: Command used for performing various NAN
+ *	Data Path (NDP) related operations, attributes defined in
+ *	enum qca_wlan_vendor_attr_ndp_params.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD: Command used to enable/disable
+ *	Neighbour Discovery offload, attributes defined in
+ *	enum qca_wlan_vendor_attr_nd_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER: Used to set/get the various
+ *	configuration parameter for BPF packet filter, attributes defined in
+ *	enum qca_wlan_vendor_attr_packet_filter.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE: Gets the driver-firmware
+ *	maximum supported size, attributes defined in
+ *	enum qca_wlan_vendor_drv_info.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS: Command to get various
+ *	data about wake reasons and datapath IP statistics, attributes defined
+ *	in enum qca_wlan_vendor_attr_wake_stats.
+ *
  * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG: Command used to set configuration
  *	for IEEE 802.11 communicating outside the context of a basic service
  *	set, called OCB command. Uses the attributes defines in
@@ -338,6 +382,77 @@
  *	information indicating the reason that triggered this detection. The
  *	attributes for this command are defined in
  *	enum qca_wlan_vendor_attr_hang.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG: Get the current values
+ *	of spectral parameters used. The spectral scan parameters are specified
+ *	by enum qca_wlan_vendor_attr_spectral_scan.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS: Get the debug stats
+ *	for spectral scan functionality. The debug stats are specified by
+ *	enum qca_wlan_vendor_attr_spectral_diag_stats.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO: Get spectral
+ *	scan system capabilities. The capabilities are specified
+ *	by enum qca_wlan_vendor_attr_spectral_cap.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS: Get the current
+ *	status of spectral scan. The status values are specified
+ *	by enum qca_wlan_vendor_attr_spectral_scan_status.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING: Sub-command to flush
+ *	peer pending packets. Specify the peer MAC address in
+ *	QCA_WLAN_VENDOR_ATTR_PEER_ADDR and the access category of the packets
+ *	in QCA_WLAN_VENDOR_ATTR_AC. The attributes are listed
+ *	in enum qca_wlan_vendor_attr_flush_pending.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO: Get vendor specific Representative
+ *	RF Operating Parameter (RROP) information. The attributes for this
+ *	information are defined in enum qca_wlan_vendor_attr_rrop_info. This is
+ *	intended for use by external Auto Channel Selection applications.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS: Get the Specific Absorption Rate
+ *	(SAR) power limits. This is a companion to the command
+ *	@QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS and is used to retrieve the
+ *	settings currently in use. The attributes returned by this command are
+ *	defined by enum qca_vendor_attr_sar_limits.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO: Provides the current behavior of
+ *	the WLAN hardware MAC. Also, provides the WLAN netdev interface
+ *	information attached to the respective MAC.
+ *	This works both as a query (user space asks the current mode) or event
+ *	interface (driver advertising the current mode to the user space).
+ *	Driver does not trigger this event for temporary hardware mode changes.
+ *	Mode changes w.r.t Wi-Fi connection update (VIZ creation / deletion,
+ *	channel change, etc.) are updated with this event. Attributes for this
+ *	interface are defined in enum qca_wlan_vendor_attr_mac.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH: Set MSDU queue depth threshold
+ *	per peer per TID. Attributes for this command are define in
+ *	enum qca_wlan_set_qdepth_thresh_attr.
+ * @QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD: Provides the thermal shutdown action
+ *	guide for WLAN driver. Request to suspend of driver and FW if the
+ *	temperature is higher than the suspend threshold; resume action is
+ *	requested to driver if the temperature is lower than the resume
+ *	threshold. In user poll mode, request temperature data by user. For test
+ *	purpose, getting thermal shutdown configuration parameters is needed.
+ *	Attributes for this interface are defined in
+ *	enum qca_wlan_vendor_attr_thermal_cmd.
+ * @QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT: Thermal events reported from
+ *	driver. Thermal temperature and indication of resume completion are
+ *	reported as thermal events. The attributes for this command are defined
+ *	in enum qca_wlan_vendor_attr_thermal_event.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION: Sub command to set WiFi
+ *	test configuration. Attributes for this command are defined in
+ *	enum qca_wlan_vendor_attr_wifi_test_config.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER: This command is used to configure an
+ *	RX filter to receive frames from stations that are active on the
+ *	operating channel, but not associated with the local device (e.g., STAs
+ *	associated with other APs). Filtering is done based on a list of BSSIDs
+ *	and STA MAC addresses added by the user. This command is also used to
+ *	fetch the statistics of unassociated stations. The attributes used with
+ *	this command are defined in enum qca_wlan_vendor_attr_bss_filter.
  */
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -405,7 +520,17 @@
 	/* Wi-Fi configuration subcommands */
 	QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74,
 	QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION = 75,
-	/* 76-90 - reserved for QCA */
+	QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET = 76,
+	QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA = 77,
+	QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES = 78,
+	QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS = 79,
+	QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI = 80,
+	QCA_NL80211_VENDOR_SUBCMD_NDP = 81,
+	QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD = 82,
+	QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER = 83,
+	QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE = 84,
+	QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS = 85,
+	/* 86-90 - reserved for QCA */
 	QCA_NL80211_VENDOR_SUBCMD_DATA_OFFLOAD = 91,
 	QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92,
 	QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93,
@@ -470,9 +595,25 @@
 	QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP = 155,
 	QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS = 156,
 	QCA_NL80211_VENDOR_SUBCMD_HANG = 157,
+	QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG = 158,
+	QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS = 159,
+	QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO = 160,
+	QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS = 161,
+	/* Flush peer pending data */
+	QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING = 162,
+	QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO = 163,
+	QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS = 164,
+	QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO = 165,
+	QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH = 166,
+	/* Thermal shutdown commands to protect wifi chip */
+	QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD = 167,
+	QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT = 168,
+	/* Wi-Fi test configuration subcommand */
+	QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION = 169,
+	/* Frame filter operations for other BSSs/unassociated STAs */
+	QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER = 170,
 };
 
-
 enum qca_wlan_vendor_attr {
 	QCA_WLAN_VENDOR_ATTR_INVALID = 0,
 	/* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */
@@ -484,7 +625,8 @@
 	/* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */
 	QCA_WLAN_VENDOR_ATTR_IFINDEX     = 4,
 	/* used by QCA_NL80211_VENDOR_SUBCMD_ROAMING, u32 with values defined
-	 * by enum qca_roaming_policy. */
+	 * by enum qca_roaming_policy.
+	 */
 	QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5,
 	QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
 	/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
@@ -572,10 +714,12 @@
 	QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT = 25,
 	/* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
 	 * to specify the chain number (unsigned 32 bit value) to inquire
-	 * the corresponding antenna RSSI value */
+	 * the corresponding antenna RSSI value
+	 */
 	QCA_WLAN_VENDOR_ATTR_CHAIN_INDEX = 26,
 	/* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
-	 * to report the specific antenna RSSI value (unsigned 32 bit value) */
+	 * to report the specific antenna RSSI value (unsigned 32 bit value)
+	 */
 	QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI = 27,
 	/* Frequency in MHz, various uses. Unsigned 32 bit value */
 	QCA_WLAN_VENDOR_ATTR_FREQ = 28,
@@ -642,7 +786,8 @@
 	 */
 	QCA_WLAN_VENDOR_ATTR_BRP_ANT_NUM_LIMIT = 39,
 	/* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
-	 * to report the corresponding antenna index to the chain RSSI value */
+	 * to report the corresponding antenna index to the chain RSSI value
+	 */
 	QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO = 40,
 
 	/* keep last */
@@ -650,7 +795,6 @@
 	QCA_WLAN_VENDOR_ATTR_MAX	= QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
 };
 
-
 enum qca_roaming_policy {
 	QCA_ROAMING_NOT_ALLOWED,
 	QCA_ROAMING_ALLOWED_WITHIN_ESS,
@@ -778,7 +922,7 @@
  * @QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY: Device supports automatic
  *	band selection based on channel selection results.
  * @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports
- * 	simultaneous off-channel operations.
+ *	simultaneous off-channel operations.
  * @QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P
  *	Listen offload; a mechanism where the station's firmware takes care of
  *	responding to incoming Probe Request frames received from other P2P
@@ -794,6 +938,8 @@
  *	%QCA_WLAN_VENDOR_FEATURE_OCE_AP, the userspace shall assume that
  *	this Device may not support all OCE AP functionalities but can support
  *	only OCE STA-CFON functionalities.
+ * @QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY: Device supports self
+ *	managed regulatory.
  * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
  */
 enum qca_wlan_vendor_features {
@@ -804,6 +950,7 @@
 	QCA_WLAN_VENDOR_FEATURE_OCE_STA                 = 4,
 	QCA_WLAN_VENDOR_FEATURE_OCE_AP                  = 5,
 	QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON            = 6,
+	QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY = 7,
 	NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
 };
 
@@ -947,6 +1094,12 @@
 	 * from kernel space to user space.
 	 */
 	QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
+	/* An array of nested values as per enum qca_wlan_vendor_attr_pcl
+	 * attribute. Each element contains frequency (MHz), weight, and flag
+	 * bit mask indicating how the frequency should be used in P2P
+	 * negotiation; sent from kernel space to user space.
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL,
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX =
@@ -1127,16 +1280,16 @@
  * @QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES: Nested array attribute of supported
  *	rates to be included
  * @QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE: flag used to send probe requests
- * 	at non CCK rate in 2GHz band
+ *	at non CCK rate in 2GHz band
  * @QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS: Unsigned 32-bit scan flags
  * @QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE: Unsigned 64-bit cookie provided by the
- * 	driver for the specific scan request
+ *	driver for the specific scan request
  * @QCA_WLAN_VENDOR_ATTR_SCAN_STATUS: Unsigned 8-bit status of the scan
- * 	request decoded as in enum scan_status
+ *	request decoded as in enum scan_status
  * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC: 6-byte MAC address to use when randomisation
- * 	scan flag is set
+ *	scan flag is set
  * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK: 6-byte MAC address mask to be used with
- * 	randomisation
+ *	randomisation
  * @QCA_WLAN_VENDOR_ATTR_SCAN_BSSID: 6-byte MAC address representing the
  *	specific BSSID to scan for.
  */
@@ -1160,10 +1313,10 @@
 
 /**
  * enum scan_status - Specifies the valid values the vendor scan attribute
- * 	QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take
+ *	QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take
  *
  * @VENDOR_SCAN_STATUS_NEW_RESULTS: implies the vendor scan is successful with
- * 	new scan results
+ *	new scan results
  * @VENDOR_SCAN_STATUS_ABORTED: implies the vendor scan was aborted in-between
  */
 enum scan_status {
@@ -1210,7 +1363,8 @@
 enum qca_vendor_attr_txpower_decr_db {
 	QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_INVALID,
 	/* 8-bit unsigned value to indicate the reduction of TX power in dB for
-	 * a virtual interface. */
+	 * a virtual interface.
+	 */
 	QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB,
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST,
@@ -1260,29 +1414,37 @@
 	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND = 7,
 	/* 8-bit unsigned value to configure the maximum TX MPDU for
-	 * aggregation. */
+	 * aggregation.
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION = 8,
 	/* 8-bit unsigned value to configure the maximum RX MPDU for
-	 * aggregation. */
+	 * aggregation.
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION = 9,
 	/* 8-bit unsigned value to configure the Non aggregrate/11g sw
-	 * retry threshold (0 disable, 31 max). */
+	 * retry threshold (0 disable, 31 max).
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY = 10,
 	/* 8-bit unsigned value to configure the aggregrate sw
-	 * retry threshold (0 disable, 31 max). */
+	 * retry threshold (0 disable, 31 max).
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY = 11,
 	/* 8-bit unsigned value to configure the MGMT frame
-	 * retry threshold (0 disable, 31 max). */
+	 * retry threshold (0 disable, 31 max).
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY = 12,
 	/* 8-bit unsigned value to configure the CTRL frame
-	 * retry threshold (0 disable, 31 max). */
+	 * retry threshold (0 disable, 31 max).
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY = 13,
 	/* 8-bit unsigned value to configure the propagation delay for
-	 * 2G/5G band (0~63, units in us) */
+	 * 2G/5G band (0~63, units in us)
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY = 14,
 	/* Unsigned 32-bit value to configure the number of unicast TX fail
 	 * packet count. The peer is disconnected once this threshold is
-	 * reached. */
+	 * reached.
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT = 15,
 	/* Attribute used to set scan default IEs to the driver.
 	 *
@@ -1293,7 +1455,8 @@
 	 * merged with the IEs received along with scan request coming to the
 	 * driver. If a particular IE is present in the scan default IEs but not
 	 * present in the scan request, then that IE should be added to the IEs
-	 * sent in the Probe Request frames for that scan request. */
+	 * sent in the Probe Request frames for that scan request.
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES = 16,
 	/* Unsigned 32-bit attribute for generic commands */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND = 17,
@@ -1302,41 +1465,50 @@
 	/* Unsigned 32-bit data attribute for generic command response */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA = 19,
 	/* Unsigned 32-bit length attribute for
-	 * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+	 * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH = 20,
 	/* Unsigned 32-bit flags attribute for
-	 * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+	 * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS = 21,
 	/* Unsigned 32-bit, defining the access policy.
 	 * See enum qca_access_policy. Used with
-	 * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST. */
+	 * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST.
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY = 22,
 	/* Sets the list of full set of IEs for which a specific access policy
 	 * has to be applied. Used along with
 	 * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY to control the access.
-	 * Zero length payload can be used to clear this access constraint. */
+	 * Zero length payload can be used to clear this access constraint.
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST = 23,
 	/* Unsigned 32-bit, specifies the interface index (netdev) for which the
 	 * corresponding configurations are applied. If the interface index is
 	 * not specified, the configurations are attributed to the respective
-	 * wiphy. */
+	 * wiphy.
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX = 24,
 	/* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER = 25,
 	/* 8-bit unsigned value to configure the driver and below layers to
 	 * ignore the assoc disallowed set by APs while connecting
-	 * 1-Ignore, 0-Don't ignore */
+	 * 1-Ignore, 0-Don't ignore
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED = 26,
 	/* 32-bit unsigned value to trigger antenna diversity features:
-	 * 1-Enable, 0-Disable */
+	 * 1-Enable, 0-Disable
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA = 27,
 	/* 32-bit unsigned value to configure specific chain antenna */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN = 28,
 	/* 32-bit unsigned value to trigger cycle selftest
-	 * 1-Enable, 0-Disable */
+	 * 1-Enable, 0-Disable
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST = 29,
 	/* 32-bit unsigned to configure the cycle time of selftest
-	 * the unit is micro-second */
+	 * the unit is micro-second
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL = 30,
 	/* 32-bit unsigned value to set reorder timeout for AC_VO */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE = 31,
@@ -1360,10 +1532,12 @@
 	 * NL80211_CHAN_WIDTH_10 means 10 MHz. If set, the device work in 5 or
 	 * 10 MHz channel width, the station will not connect to a BSS using 20
 	 * MHz or higher bandwidth. Set to NL80211_CHAN_WIDTH_20_NOHT to
-	 * clear this constraint. */
+	 * clear this constraint.
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH = 39,
 	/* 32-bit unsigned value to configure the propagation absolute delay
-	 * for 2G/5G band (units in us) */
+	 * for 2G/5G band (units in us)
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY = 40,
 	/* 32-bit unsigned value to set probe period */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD = 41,
@@ -1431,7 +1605,7 @@
 	QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE = 51,
 
 	/* 8-bit unsigned value to set the total beacon miss count
-	 * This paramater will set the total beacon miss count.
+	 * This parameter will set the total beacon miss count.
 	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT = 52,
 
@@ -1443,9 +1617,32 @@
 
 	/* 8-bit unsigned value to configure the driver and below layers to
 	 * enable/disable all FILS features.
-	 * 0-enable, 1-disable */
+	 * 0-enable, 1-disable
+	 */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS = 54,
 
+	/* 16-bit unsigned value to configure the level of WLAN latency
+	 * module. See enum qca_wlan_vendor_attr_config_latency_level.
+	 */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL = 55,
+
+	/* 8-bit unsigned value indicating the driver to use the RSNE as-is from
+	 * the connect interface. Exclusively used for the scenarios where the
+	 * device is used as a test bed device with special functionality and
+	 * not recommended for production. This helps driver to not validate the
+	 * RSNE passed from user space and thus allow arbitrary IE data to be
+	 * used for testing purposes.
+	 * 1-enable, 0-disable.
+	 * Applications set/reset this configuration. If not reset, this
+	 * parameter remains in use until the driver is unloaded.
+	 */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE = 56,
+
+	/* 8-bit unsigned value to trigger green Tx power saving.
+	 * 1-Enable, 0-Disable
+	 */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_GTX = 57,
+
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -1478,7 +1675,8 @@
 enum qca_wlan_vendor_attr_sap_conditional_chan_switch {
 	QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_INVALID = 0,
 	/* Priority based frequency list (an array of u32 values in host byte
-	 * order) */
+	 * order)
+	 */
 	QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST = 1,
 	/* Status of the conditional switch (u32).
 	 * 0: Success, Non-zero: Failure
@@ -1513,6 +1711,36 @@
 };
 
 /**
+ * qca_wlan_set_qdepth_thresh_attr - Parameters for setting
+ * MSDUQ depth threshold per peer per tid in the target
+ *
+ * Associated Vendor Command:
+ * QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH
+ */
+enum qca_wlan_set_qdepth_thresh_attr {
+	QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_INVALID = 0,
+	/* 6-byte MAC address */
+	QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_MAC_ADDR,
+	/* Unsigned 32-bit attribute for holding the TID */
+	QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_TID,
+	/* Unsigned 32-bit attribute for holding the update mask
+	 * bit 0 - Update high priority msdu qdepth threshold
+	 * bit 1 - Update low priority msdu qdepth threshold
+	 * bit 2 - Update UDP msdu qdepth threshold
+	 * bit 3 - Update Non UDP msdu qdepth threshold
+	 * rest of bits are reserved
+	 */
+	QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_UPDATE_MASK,
+	/* Unsigned 32-bit attribute for holding the threshold value */
+	QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_VALUE,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_LAST,
+	QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_MAX =
+		QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_LAST - 1,
+};
+
+/**
  * enum qca_wlan_vendor_attr_get_hw_capability - Wi-Fi hardware capability
  */
 enum qca_wlan_vendor_attr_get_hw_capability {
@@ -1684,6 +1912,12 @@
  * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF: per antenna NF value
  * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON: RSSI of beacon
  * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON: SNR of beacon
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_REPORT_TIME: u64
+ *    Absolute timestamp from 1970/1/1, unit in ms. After receiving the
+ *    message, user layer APP could call gettimeofday to get another
+ *    timestamp and calculate transfer delay for the message.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MEASUREMENT_TIME: u32
+ *    Real period for this measurement, unit in us.
  */
 enum qca_wlan_vendor_attr_ll_stats_ext {
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_INVALID = 0,
@@ -1777,6 +2011,9 @@
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON,
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON,
 
+	QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_REPORT_TIME,
+	QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MEASUREMENT_TIME,
+
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST,
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX =
 		QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST - 1
@@ -1830,7 +2067,7 @@
  * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR: Set if driver
  *	can run FTM sessions. QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION
  *	will be supported if set.
-* @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder
  *	supports immediate (ASAP) response.
  * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA: Set if driver supports standalone
  *	AOA measurement using QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS.
@@ -2393,13 +2630,13 @@
 	/* Unsigned int 8 bit value; 0:20 MHz, 1:40 MHz, 2:80 MHz, 3:160 MHz */
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW = 40,
 	/* Unsigned int 8 bit value; OFDM/CCK rate code would be as per IEEE Std
-	 * in the units of 0.5 Mbps HT/VHT it would be MCS index */
+	 * in the units of 0.5 Mbps HT/VHT it would be MCS index
+	 */
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX = 41,
 
 	/* Unsigned 32 bit value. Bit rate in units of 100 kbps */
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE = 42,
 
-
 	/* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_STAT_* could be
 	 * nested within the peer info stats.
 	 */
@@ -2558,14 +2795,18 @@
 	/* Unsigned 32 bit value */
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_FAIL_CNT = 82,
 
+	/* Unsigned int 32 value.
+	 * Pending MSDUs corresponding to respective AC.
+	 */
+	QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_PENDING_MSDU = 83,
+
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
 	QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST - 1,
 };
 
-enum qca_wlan_vendor_attr_ll_stats_type
-{
+enum qca_wlan_vendor_attr_ll_stats_type {
 	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_INVALID = 0,
 	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_RADIO = 1,
 	QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_IFACE = 2,
@@ -2682,10 +2923,14 @@
  *	limit feature.
  * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER: Select the SAR power
  *	limits configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR.
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0: Select the SAR power
+ *	limits version 2.0 configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR.
  *
  * This enumerates the valid set of values that may be supplied for
  * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT in an instance of
- * the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor command.
+ * the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor command or in
+ * the response to an instance of the
+ * %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS vendor command.
  */
 enum qca_vendor_attr_sar_limits_selections {
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0 = 0,
@@ -2695,6 +2940,7 @@
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4 = 4,
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE = 5,
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER = 6,
+	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0 = 7,
 };
 
 /**
@@ -2709,7 +2955,8 @@
  * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION in an
  * instance of attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC in an
  * instance of the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor
- * command.
+ * command or in the response to an instance of the
+ * %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS vendor command.
  */
 enum qca_vendor_attr_sar_limits_spec_modulations {
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK = 0,
@@ -2740,7 +2987,12 @@
  *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN, and
  *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION and always
  *	contains as a payload the attribute
- *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT.
+ *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT,
+ *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX.
+ *	Either %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT or
+ *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX is
+ *	needed based upon the value of
+ *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE.
  *
  * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND: Optional (u32) value to
  *	indicate for which band this specification applies. Valid
@@ -2765,8 +3017,16 @@
  * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT: Required (u32)
  *	value to specify the actual power limit value in units of 0.5
  *	dBm (i.e., a value of 11 represents 5.5 dBm).
+ *	This is required, when %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT is
+ *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER.
  *
- * These attributes are used with %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS.
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX: Required (u32)
+ *	value to indicate SAR V2 indices (0 - 11) to select SAR V2 profiles.
+ *	This is required, when %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT is
+ *	%QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0.
+ *
+ * These attributes are used with %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS
+ * and %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS.
  */
 enum qca_vendor_attr_sar_limits {
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_INVALID = 0,
@@ -2777,6 +3037,7 @@
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN = 5,
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION = 6,
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT = 7,
+	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX = 8,
 
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX =
@@ -2824,7 +3085,7 @@
 
 	/* Unsigned 32-bit value; used to indicate the size of memory
 	 * dump to be allocated.
-	*/
+	 */
 	QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE = 2,
 
 	/* keep last */
@@ -3528,7 +3789,8 @@
 /**
  * qca_wlan_vendor_attr_pcl: Represents attributes for
  * preferred channel list (PCL). These attributes are sent as part of
- * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL.
+ * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL and
+ * QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST.
  */
 enum qca_wlan_vendor_attr_pcl {
 	QCA_WLAN_VENDOR_ATTR_PCL_INVALID = 0,
@@ -3537,6 +3799,17 @@
 	QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL = 1,
 	/* Channel weightage (u8) */
 	QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT = 2,
+	/* Channel frequency (u32) in MHz */
+	QCA_WLAN_VENDOR_ATTR_PCL_FREQ = 3,
+	/* Channel flags (u32)
+	 * bit 0 set: channel to be used for GO role,
+	 * bit 1 set: channel to be used on CLI role,
+	 * bit 2 set: channel must be considered for operating channel
+	 *                 selection & peer chosen operating channel should be
+	 *                 one of the channels with this flag set,
+	 * bit 3 set: channel should be excluded in GO negotiation
+	 */
+	QCA_WLAN_VENDOR_ATTR_PCL_FLAG = 4,
 };
 
 /**
@@ -3556,12 +3829,14 @@
 	/* Flag attribute to indicate if 11ac is offloaded to firmware */
 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED = 3,
 	/* Flag attribute to indicate if driver provides additional channel
-	 * capability as part of scan operation */
+	 * capability as part of scan operation
+	 */
 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT = 4,
 	/* Flag attribute to indicate interface status is UP */
 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AP_UP = 5,
 	/* Operating mode (u8) of interface. Takes one of enum nl80211_iftype
-	 * values. */
+	 * values.
+	 */
 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_SAP_MODE = 6,
 	/* Channel width (u8). It takes one of enum nl80211_chan_width values.
 	 * This is the upper bound of channel width. ACS logic should try to get
@@ -3572,7 +3847,8 @@
 	/* This (u8) will hold values of one of enum nl80211_bands */
 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND = 8,
 	/* PHY/HW mode (u8). Takes one of enum qca_wlan_vendor_acs_hw_mode
-	 * values */
+	 * values
+	 */
 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE = 9,
 	/* Array of (u32) supported frequency list among which ACS should choose
 	 * best frequency.
@@ -3591,6 +3867,11 @@
 	 * qca_wlan_vendor_attr_external_acs_policy.
 	 */
 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY = 13,
+	/* Reference RF Operating Parameter (RROP) availability information
+	 * (u16). It uses values defined in enum
+	 * qca_wlan_vendor_attr_rropavail_info.
+	 */
+	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_RROPAVAIL_INFO = 14,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST,
@@ -3642,10 +3923,10 @@
 	/* Indicates if the reason for the failure is due to a protocol
 	 * layer/module.
 	 */
-        QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL = 0,
+	QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL = 0,
 	/* Indicates if the reason for the failure is due to a hardware issue.
 	 */
-        QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE = 1,
+	QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE = 1,
 };
 
 /**
@@ -3654,17 +3935,70 @@
  * information leading to the power save failure.
  */
 enum qca_attr_chip_power_save_failure {
-        QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID = 0,
-        /* Reason to cause the power save failure.
+	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID = 0,
+	/* Reason to cause the power save failure.
 	 * These reasons are represented by
 	 * enum qca_chip_power_save_failure_reason.
 	 */
-        QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON = 1,
+	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON = 1,
 
-        /* keep last */
-        QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST,
-        QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX =
-                QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST - 1,
+	/* keep last */
+	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST,
+	QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX =
+		QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_nud_stats_data_pkt_flags: Flag representing the various
+ * data types for which the stats have to get collected.
+ */
+enum qca_wlan_vendor_nud_stats_data_pkt_flags {
+	QCA_WLAN_VENDOR_NUD_STATS_DATA_ARP = 1 << 0,
+	QCA_WLAN_VENDOR_NUD_STATS_DATA_DNS = 1 << 1,
+	QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_HANDSHAKE = 1 << 2,
+	QCA_WLAN_VENDOR_NUD_STATS_DATA_ICMPV4 = 1 << 3,
+	QCA_WLAN_VENDOR_NUD_STATS_DATA_ICMPV6 = 1 << 4,
+	/* Used by QCA_ATTR_NUD_STATS_PKT_TYPE only in nud stats get
+	 * to represent the stats of respective data type.
+	 */
+	QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_SYN = 1 << 5,
+	QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_SYN_ACK = 1 << 6,
+	QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_ACK = 1 << 7,
+};
+
+enum qca_wlan_vendor_nud_stats_set_data_pkt_info {
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_INVALID = 0,
+	/* Represents the data packet type to be monitored (u32).
+	 * Host driver tracks the stats corresponding to each data frame
+	 * represented by these flags.
+	 * These data packets are represented by
+	 * enum qca_wlan_vendor_nud_stats_data_pkt_flags
+	 */
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_TYPE = 1,
+	/* Name corresponding to the DNS frame for which the respective DNS
+	 * stats have to get monitored (string). Max string length 255.
+	 */
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DNS_DOMAIN_NAME = 2,
+	/* source port on which the respective proto stats have to get
+	 * collected (u32).
+	 */
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_SRC_PORT = 3,
+	/* destination port on which the respective proto stats have to get
+	 * collected (u32).
+	 */
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_PORT = 4,
+	/* IPv4 address for which the destined data packets have to be
+	 * monitored. (in network byte order), u32.
+	 */
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV4 = 5,
+	/* IPv6 address for which the destined data packets have to be
+	 * monitored. (in network byte order), 16 bytes array.
+	 */
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV6 = 6,
+
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_LAST,
+	QCA_ATTR_NUD_STATS_DATA_PKT_INFO_MAX =
+		QCA_ATTR_NUD_STATS_DATA_PKT_INFO_LAST - 1,
 };
 
 /**
@@ -3679,8 +4013,15 @@
 	 * Start - If included, Stop - If not included
 	 */
 	QCA_ATTR_NUD_STATS_SET_START = 1,
-	/* IPv4 address of the default gateway (in network byte order) */
+	/* IPv4 address of the default gateway (in network byte order), u32 */
 	QCA_ATTR_NUD_STATS_GW_IPV4 = 2,
+	/* Represents the list of data packet types to be monitored.
+	 * Host driver tracks the stats corresponding to each data frame
+	 * represented by these flags.
+	 * These data packets are represented by
+	 * enum qca_wlan_vendor_nud_stats_set_data_pkt_info
+	 */
+	QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO = 3,
 
 	/* keep last */
 	QCA_ATTR_NUD_STATS_SET_LAST,
@@ -3688,6 +4029,58 @@
 		QCA_ATTR_NUD_STATS_SET_LAST - 1,
 };
 
+enum qca_attr_nud_data_stats {
+	QCA_ATTR_NUD_DATA_STATS_INVALID = 0,
+	/* Data packet type for which the stats are collected (u32).
+	 * Represented by enum qca_wlan_vendor_nud_stats_data_pkt_flags
+	 */
+	QCA_ATTR_NUD_STATS_PKT_TYPE = 1,
+	/* Name corresponding to the DNS frame for which the respective DNS
+	 * stats are monitored (string). Max string length 255.
+	 */
+	QCA_ATTR_NUD_STATS_PKT_DNS_DOMAIN_NAME = 2,
+	/* source port on which the respective proto stats are collected (u32).
+	 */
+	QCA_ATTR_NUD_STATS_PKT_SRC_PORT = 3,
+	/* destination port on which the respective proto stats are collected
+	 * (u32).
+	 */
+	QCA_ATTR_NUD_STATS_PKT_DEST_PORT = 4,
+	/* IPv4 address for which the destined data packets have to be
+	 * monitored. (in network byte order), u32.
+	 */
+	QCA_ATTR_NUD_STATS_PKT_DEST_IPV4 = 5,
+	/* IPv6 address for which the destined data packets have to be
+	 * monitored. (in network byte order), 16 bytes array.
+	 */
+	QCA_ATTR_NUD_STATS_PKT_DEST_IPV6 = 6,
+	/* Data packet Request count received from netdev (u32). */
+	QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_FROM_NETDEV = 7,
+	/* Data packet Request count sent to lower MAC from upper MAC (u32). */
+	QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TO_LOWER_MAC = 8,
+	/* Data packet Request count received by lower MAC from upper MAC
+	 * (u32)
+	 */
+	QCA_ATTR_NUD_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC = 9,
+	/* Data packet Request count successfully transmitted by the device
+	 * (u32)
+	 */
+	QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TX_SUCCESS = 10,
+	/* Data packet Response count received by lower MAC (u32) */
+	QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC = 11,
+	/* Data packet Response count received by upper MAC (u32) */
+	QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC = 12,
+	/* Data packet Response count delivered to netdev (u32) */
+	QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_TO_NETDEV = 13,
+	/* Data Packet Response count that are dropped out of order (u32) */
+	QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP = 14,
+
+	/* keep last */
+	QCA_ATTR_NUD_DATA_STATS_LAST,
+	QCA_ATTR_NUD_DATA_STATS_MAX =
+		QCA_ATTR_NUD_DATA_STATS_LAST - 1,
+};
+
 /**
  * qca_attr_nud_stats_get: Attributes to vendor subcmd
  * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET. This carries the requisite
@@ -3695,21 +4088,21 @@
  */
 enum qca_attr_nud_stats_get {
 	QCA_ATTR_NUD_STATS_GET_INVALID = 0,
-	/* ARP Request count from netdev */
+	/* ARP Request count from netdev (u32) */
 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV = 1,
-	/* ARP Request count sent to lower MAC from upper MAC */
+	/* ARP Request count sent to lower MAC from upper MAC (u32) */
 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC = 2,
-	/* ARP Request count received by lower MAC from upper MAC */
+	/* ARP Request count received by lower MAC from upper MAC (u32) */
 	QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC = 3,
-	/* ARP Request count successfully transmitted by the device */
+	/* ARP Request count successfully transmitted by the device (u32) */
 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS = 4,
-	/* ARP Response count received by lower MAC */
+	/* ARP Response count received by lower MAC (u32) */
 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC = 5,
-	/* ARP Response count received by upper MAC */
+	/* ARP Response count received by upper MAC (u32) */
 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC = 6,
-	/* ARP Response count delivered to netdev */
+	/* ARP Response count delivered to netdev (u32) */
 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV = 7,
-	/* ARP Response count delivered to netdev */
+	/* ARP Response count dropped due to out of order reception (u32) */
 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP = 8,
 	/* Flag indicating if the station's link to the AP is active.
 	 * Active Link - If included, Inactive link - If not included
@@ -3719,6 +4112,11 @@
 	 * Yes - If detected, No - If not detected.
 	 */
 	QCA_ATTR_NUD_STATS_IS_DAD = 10,
+	/* List of Data packet types for which the stats are requested.
+	 * This list does not carry ARP stats as they are done by the
+	 * above attributes. Represented by enum qca_attr_nud_data_stats.
+	 */
+	QCA_ATTR_NUD_STATS_DATA_PKT_STATS = 11,
 
 	/* keep last */
 	QCA_ATTR_NUD_STATS_GET_LAST,
@@ -3784,7 +4182,8 @@
 enum qca_wlan_vendor_attr_get_he_capabilities {
 	QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_INVALID = 0,
 	/* Whether HE capabilities is supported
-	 * (u8 attribute: 0 = not supported, 1 = supported) */
+	 * (u8 attribute: 0 = not supported, 1 = supported)
+	 */
 	QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED = 1,
 	/* HE PHY capabilities, array of 3 u32 values  */
 	QCA_WLAN_VENDOR_ATTR_PHY_CAPAB = 2,
@@ -3895,12 +4294,138 @@
 	 * specific scan to be stopped.
 	 */
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE = 19,
+	/* Skip interval for FFT reports. u32 attribute */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD = 20,
+	/* Set to report only one set of FFT results.
+	 * u32 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT = 21,
+	/* Debug level for spectral module in driver.
+	 * 0 : Verbosity level 0
+	 * 1 : Verbosity level 1
+	 * 2 : Verbosity level 2
+	 * 3 : Matched filterID display
+	 * 4 : One time dump of FFT report
+	 * u32 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL = 22,
+	/* Type of spectral scan request. u32 attribute.
+	 * It uses values defined in enum
+	 * qca_wlan_vendor_attr_spectral_scan_request_type.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE = 23,
 
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST,
 	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX =
 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST - 1,
 };
 
+/**
+ * enum qca_wlan_vendor_attr_spectral_diag_stats - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS.
+ */
+enum qca_wlan_vendor_attr_spectral_diag_stats {
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_INVALID = 0,
+	/* Number of spectral TLV signature mismatches.
+	 * u64 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH = 1,
+	/* Number of spectral phyerror events with insufficient length when
+	 * parsing for secondary 80 search FFT report. u64 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN = 2,
+	/* Number of spectral phyerror events without secondary 80
+	 * search FFT report. u64 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT = 3,
+	/* Number of spectral phyerror events with vht operation segment 1 id
+	 * mismatches in search fft report. u64 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH = 4,
+	/* Number of spectral phyerror events with vht operation segment 2 id
+	 * mismatches in search fft report. u64 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH = 5,
+
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX =
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_spectral_cap - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO.
+ */
+enum qca_wlan_vendor_attr_spectral_cap {
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_INVALID = 0,
+	/* Flag attribute to indicate phydiag capability */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG = 1,
+	/* Flag attribute to indicate radar detection capability */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR = 2,
+	/* Flag attribute to indicate spectral capability */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL = 3,
+	/* Flag attribute to indicate advanced spectral capability */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL = 4,
+	/* Spectral hardware generation. u32 attribute.
+	 * It uses values defined in enum
+	 * qca_wlan_vendor_spectral_scan_cap_hw_gen.
+	 */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN = 5,
+
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX =
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_spectral_scan_status - used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS.
+ */
+enum qca_wlan_vendor_attr_spectral_scan_status {
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_INVALID = 0,
+	/* Flag attribute to indicate whether spectral scan is enabled */
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED = 1,
+	/* Flag attribute to indicate whether spectral scan is in progress*/
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE = 2,
+
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX =
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_attr_spectral_scan_request_type: Attribute values for
+ * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE to the vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START. This represents the
+ * spectral scan request types.
+ * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG: Request to
+ * set the spectral parameters and start scan.
+ * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN: Request to
+ * only set the spectral parameters.
+ * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG: Request to
+ * only start the spectral scan.
+ */
+enum qca_wlan_vendor_attr_spectral_scan_request_type {
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG,
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN,
+	QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG,
+};
+
+/**
+ * qca_wlan_vendor_spectral_scan_cap_hw_gen: Attribute values for
+ * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN to the vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. This represents the
+ * spectral hardware generation.
+ * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_1: generation 1
+ * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_2: generation 2
+ * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_3: generation 3
+ */
+enum qca_wlan_vendor_spectral_scan_cap_hw_gen {
+	QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_1 = 0,
+	QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_2 = 1,
+	QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_3 = 2,
+};
+
 enum qca_wlan_vendor_tos {
 	QCA_WLAN_VENDOR_TOS_BK = 0,
 	QCA_WLAN_VENDOR_TOS_BE = 1,
@@ -3969,4 +4494,1113 @@
 		QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST - 1,
 };
 
+/**
+ * enum qca_wlan_vendor_attr_flush_pending - Attributes for
+ * flushing pending traffic in firmware.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_ADDR: Configure peer MAC address.
+ * @QCA_WLAN_VENDOR_ATTR_AC: Configure access category of the pending
+ * packets. It is u8 value with bit 0~3 represent AC_BE, AC_BK,
+ * AC_VI, AC_VO respectively. Set the corresponding bit to 1 to
+ * flush packets with access category.
+ */
+enum qca_wlan_vendor_attr_flush_pending {
+	QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_PEER_ADDR = 1,
+	QCA_WLAN_VENDOR_ATTR_AC = 2,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_MAX =
+	QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_rropavail_info - Specifies whether Representative
+ * RF Operating Parameter (RROP) information is available, and if so, at which
+ * point in the application-driver interaction sequence it can be retrieved by
+ * the application from the driver. This point may vary by architecture and
+ * other factors. This is a u16 value.
+ */
+enum qca_wlan_vendor_attr_rropavail_info {
+	/* RROP information is unavailable. */
+	QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_UNAVAILABLE,
+	/* RROP information is available and the application can retrieve the
+	 * information after receiving an QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
+	 * event from the driver.
+	 */
+	QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_EXTERNAL_ACS_START,
+	/* RROP information is available only after a vendor specific scan
+	 * (requested using QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN) has
+	 * successfully completed. The application can retrieve the information
+	 * after receiving the QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE event from
+	 * the driver.
+	 */
+	QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_VSCAN_END,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_rrop_info - Specifies vendor specific
+ * Representative RF Operating Parameter (RROP) information. It is sent for the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO. This information is
+ * intended for use by external Auto Channel Selection applications. It provides
+ * guidance values for some RF parameters that are used by the system during
+ * operation. These values could vary by channel, band, radio, and so on.
+ */
+enum qca_wlan_vendor_attr_rrop_info {
+	QCA_WLAN_VENDOR_ATTR_RROP_INFO_INVALID = 0,
+
+	/* Representative Tx Power List (RTPL) which has an array of nested
+	 * values as per attributes in enum qca_wlan_vendor_attr_rtplinst.
+	 */
+	QCA_WLAN_VENDOR_ATTR_RROP_INFO_RTPL = 1,
+
+	QCA_WLAN_VENDOR_ATTR_RROP_INFO_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_RROP_INFO_MAX =
+	QCA_WLAN_VENDOR_ATTR_RROP_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_rtplinst - Specifies attributes for individual list
+ * entry instances in the Representative Tx Power List (RTPL). It provides
+ * simplified power values intended for helping external Auto channel Selection
+ * applications compare potential Tx power performance between channels, other
+ * operating conditions remaining identical. These values are not necessarily
+ * the actual Tx power values that will be used by the system. They are also not
+ * necessarily the max or average values that will be used. Instead, they are
+ * relative, summarized keys for algorithmic use computed by the driver or
+ * underlying firmware considering a number of vendor specific factors.
+ */
+enum qca_wlan_vendor_attr_rtplinst {
+	QCA_WLAN_VENDOR_ATTR_RTPLINST_INVALID = 0,
+
+	/* Primary channel number (u8) */
+	QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY = 1,
+	/* Representative Tx power in dBm (s32) with emphasis on throughput. */
+	QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_THROUGHPUT = 2,
+	/* Representative Tx power in dBm (s32) with emphasis on range. */
+	QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_RANGE = 3,
+
+	QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_RTPLINST_MAX =
+		QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_config_latency_level - Level for
+ * wlan latency module.
+ *
+ * There will be various of Wi-Fi functionality like scan/roaming/adaptive
+ * power saving which would causing data exchange out of service, this
+ * would be a big impact on latency. For latency sensitive applications over
+ * Wi-Fi are intolerant to such operations and thus would configure them
+ * to meet their respective needs. It is well understood by such applications
+ * that altering the default behavior would degrade the Wi-Fi functionality
+ * w.r.t the above pointed WLAN operations.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
+ *	Default WLAN operation level which throughput orientated.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE:
+ *	Use moderate level to improve latency by limit scan duration.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
+ *	Use low latency level to benifit application like concurrent
+ *	downloading or video streaming via constraint scan/adaptive PS.
+ * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
+ *	Use ultra low latency level to benefit for gaming/voice
+ *	application via constraint scan/roaming/adaptive PS.
+ */
+enum qca_wlan_vendor_attr_config_latency_level {
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL = 1,
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = 2,
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3,
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MAX =
+	QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_wlan_mac - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO.
+ */
+enum qca_wlan_vendor_attr_mac {
+	QCA_WLAN_VENDOR_ATTR_MAC_INVALID = 0,
+
+	/* MAC mode info list which has an array of nested values as
+	 * per attributes in enum qca_wlan_vendor_attr_mac_mode_info.
+	 */
+	QCA_WLAN_VENDOR_ATTR_MAC_INFO = 1,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_MAC_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_MAC_MAX =
+	QCA_WLAN_VENDOR_ATTR_MAC_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mac_iface_info - Information of the connected
+ *	Wi-Fi netdev interface on a respective MAC.
+ *	Used by the attribute QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO.
+ */
+enum qca_wlan_vendor_attr_mac_iface_info {
+	QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_INVALID = 0,
+	/* Wi-Fi netdev's interface index (u32) */
+	QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX = 1,
+	/* Associated frequency in MHz of the connected Wi-Fi interface (u32) */
+	QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ = 2,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_MAX =
+	QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mac_info - Points to MAC the information.
+ *	Used by the attribute QCA_WLAN_VENDOR_ATTR_MAC_INFO of the
+ *	vendor command QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO.
+ */
+enum qca_wlan_vendor_attr_mac_info {
+	QCA_WLAN_VENDOR_ATTR_MAC_INFO_INVALID = 0,
+	/* Hardware MAC ID associated for the MAC (u32) */
+	QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID = 1,
+	/* Band supported by the MAC at a given point.
+	 * This is a u32 bitmask of BIT(NL80211_BAND_*) as described in %enum
+	 * nl80211_band.
+	 */
+	QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND = 2,
+	/* Refers to list of WLAN netdev interfaces associated with this MAC.
+	 * Represented by enum qca_wlan_vendor_attr_mac_iface_info.
+	 */
+	QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO = 3,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_MAC_INFO_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAX =
+	QCA_WLAN_VENDOR_ATTR_MAC_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_logger_features - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET.
+ */
+enum qca_wlan_vendor_attr_get_logger_features {
+	QCA_WLAN_VENDOR_ATTR_LOGGER_INVALID = 0,
+	/* Unsigned 32-bit enum value of wifi_logger_supported_features */
+	QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED = 1,
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_LOGGER_MAX =
+		QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - 1,
+};
+
+/**
+ * enum wifi_logger_supported_features - Values for supported logger features
+ */
+enum wifi_logger_supported_features {
+	WIFI_LOGGER_MEMORY_DUMP_FEATURE = (1 << (0)),
+	WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_FEATURE = (1 << (1)),
+	WIFI_LOGGER_CONNECT_EVENT_FEATURE = (1 << (2)),
+	WIFI_LOGGER_POWER_EVENT_FEATURE = (1 << (3)),
+	WIFI_LOGGER_WAKE_LOCK_FEATURE = (1 << (4)),
+	WIFI_LOGGER_VERBOSE_FEATURE = (1 << (5)),
+	WIFI_LOGGER_WATCHDOG_TIMER_FEATURE = (1 << (6)),
+	WIFI_LOGGER_DRIVER_DUMP_FEATURE = (1 << (7)),
+	WIFI_LOGGER_PACKET_FATE_FEATURE = (1 << (8)),
+};
+
+/**
+ * enum qca_wlan_tdls_caps_features_supported - Values for TDLS get
+ * capabilities features
+ */
+enum qca_wlan_tdls_caps_features_supported {
+	WIFI_TDLS_SUPPORT = (1 << (0)),
+	WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT = (1 << (1)),
+	WIFI_TDLS_OFFCHANNEL_SUPPORT = (1 << (2))
+};
+
+/**
+ * enum qca_wlan_vendor_attr_tdls_get_capabilities - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES.
+ */
+enum qca_wlan_vendor_attr_tdls_get_capabilities {
+	QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_INVALID = 0,
+	/* Indicates the max concurrent sessions */
+	/* Unsigned 32-bit value */
+	QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS,
+	/* Indicates the support for features */
+	/* Unsigned 32-bit bitmap qca_wlan_tdls_caps_features_supported
+	 */
+	QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX =
+		QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_offloaded_packets_sending_control - Offload packets control
+ * command used as value for the attribute
+ * QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL.
+ */
+enum qca_wlan_offloaded_packets_sending_control {
+	QCA_WLAN_OFFLOADED_PACKETS_SENDING_CONTROL_INVALID = 0,
+	QCA_WLAN_OFFLOADED_PACKETS_SENDING_START,
+	QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP
+};
+
+/**
+ * enum qca_wlan_vendor_attr_offloaded_packets - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS.
+ */
+enum qca_wlan_vendor_attr_offloaded_packets {
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_INVALID = 0,
+	/* Takes valid value from the enum
+	 * qca_wlan_offloaded_packets_sending_control
+	 * Unsigned 32-bit value
+	 */
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
+	/* Unsigned 32-bit value */
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
+	/* array of u8 len: Max packet size */
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA,
+	/* 6-byte MAC address used to represent source MAC address */
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
+	/* 6-byte MAC address used to represent destination MAC address */
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
+	/* Unsigned 32-bit value, in milli seconds */
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX =
+		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_rssi_monitoring_control - RSSI control commands used as values
+ * by the attribute QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL.
+ */
+enum qca_wlan_rssi_monitoring_control {
+	QCA_WLAN_RSSI_MONITORING_CONTROL_INVALID = 0,
+	QCA_WLAN_RSSI_MONITORING_START,
+	QCA_WLAN_RSSI_MONITORING_STOP,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_rssi_monitoring - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI.
+ */
+enum qca_wlan_vendor_attr_rssi_monitoring {
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_INVALID = 0,
+	/* Takes valid value from the enum
+	 * qca_wlan_rssi_monitoring_control
+	 * Unsigned 32-bit value enum qca_wlan_rssi_monitoring_control
+	 */
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL,
+	/* Unsigned 32-bit value */
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
+	/* Signed 8-bit value in dBm */
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI,
+	/* Signed 8-bit value in dBm */
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI,
+	/* attributes to be used/received in callback */
+	/* 6-byte MAC address used to represent current BSSID MAC address */
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
+	/* Signed 8-bit value indicating the current RSSI */
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX =
+		QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ndp_params - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_NDP.
+ */
+enum qca_wlan_vendor_attr_ndp_params {
+	QCA_WLAN_VENDOR_ATTR_NDP_PARAM_INVALID = 0,
+	/* Unsigned 32-bit value
+	 * enum of sub commands values in qca_wlan_ndp_sub_cmd
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+	/* Unsigned 16-bit value */
+	QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+	/* NL attributes for data used NDP SUB cmds */
+	/* Unsigned 32-bit value indicating a service info */
+	QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID,
+	/* Unsigned 32-bit value; channel frequency in MHz */
+	QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL,
+	/* Interface Discovery MAC address. An array of 6 Unsigned int8 */
+	QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR,
+	/* Interface name on which NDP is being created */
+	QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR,
+	/* Unsigned 32-bit value for security */
+	/* CONFIG_SECURITY is deprecated, use NCS_SK_TYPE/PMK/SCID instead */
+	QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY,
+	/* Unsigned 32-bit value for QoS */
+	QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS,
+	/* Array of u8: len = QCA_WLAN_VENDOR_ATTR_NAN_DP_APP_INFO_LEN */
+	QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO,
+	/* Unsigned 32-bit value for NDP instance Id */
+	QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID,
+	/* Array of instance Ids */
+	QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY,
+	/* Unsigned 32-bit value for initiator/responder NDP response code
+	 * accept/reject
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE,
+	/* NDI MAC address. An array of 6 Unsigned int8 */
+	QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR,
+	/* Unsigned 32-bit value errors types returned by driver
+	 * The wifi_nan.h in AOSP project platform/hardware/libhardware_legacy
+	 * NanStatusType includes these values.
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE,
+	/* Unsigned 32-bit value error values returned by driver
+	 * The nan_i.h in AOSP project platform/hardware/qcom/wlan
+	 * NanInternalStatusType includes these values.
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE,
+	/* Unsigned 32-bit value for Channel setup configuration
+	 * The wifi_nan.h in AOSP project platform/hardware/libhardware_legacy
+	 * NanDataPathChannelCfg includes these values.
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_CONFIG,
+	/* Unsigned 32-bit value for Cipher Suite Shared Key Type */
+	QCA_WLAN_VENDOR_ATTR_NDP_CSID,
+	/* Array of u8: len = NAN_PMK_INFO_LEN 32 bytes */
+	QCA_WLAN_VENDOR_ATTR_NDP_PMK,
+	/* Security Context Identifier that contains the PMKID
+	 * Array of u8: len = NAN_SCID_BUF_LEN 1024 bytes
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_SCID,
+	/* Array of u8: len = NAN_SECURITY_MAX_PASSPHRASE_LEN 63 bytes */
+	QCA_WLAN_VENDOR_ATTR_NDP_PASSPHRASE,
+	/* Array of u8: len = NAN_MAX_SERVICE_NAME_LEN 255 bytes */
+	QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_NAME,
+	/* Unsigned 32-bit bitmap indicating schedule update
+	 * BIT_0: NSS Update
+	 * BIT_1: Channel list update
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REASON,
+	/* Unsigned 32-bit value for NSS */
+	QCA_WLAN_VENDOR_ATTR_NDP_NSS,
+	/* Unsigned 32-bit value for NUMBER NDP CHANNEL */
+	QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS,
+	/* Unsigned 32-bit value for CHANNEL BANDWIDTH
+	 * 0:20 MHz, 1:40 MHz, 2:80 MHz, 3:160 MHz
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH,
+	/* Array of channel/band width */
+	QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO,
+	/* IPv6 address used by NDP (in network byte order), 16 bytes array.
+	 * This attribute is used and optional for ndp request, ndp response,
+	 * ndp indication, and ndp confirm.
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_IPV6_ADDR = 27,
+	/* Unsigned 16-bit value indicating transport port used by NDP.
+	 * This attribute is used and optional for ndp response, ndp indication,
+	 * and ndp confirm.
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PORT = 28,
+	/* Unsigned 8-bit value indicating protocol used by NDP and assigned by
+	 * the Internet Assigned Numbers Authority (IANA) as per:
+	 * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
+	 * This attribute is used and optional for ndp response, ndp indication,
+	 * and ndp confirm.
+	 */
+	QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PROTOCOL = 29,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX =
+		QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST - 1,
+};
+
+enum qca_wlan_ndp_sub_cmd {
+	QCA_WLAN_VENDOR_ATTR_NDP_INVALID = 0,
+	/* Command to create a NAN data path interface */
+	QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE = 1,
+	/* Command to delete a NAN data path interface */
+	QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE = 2,
+	/* Command to initiate a NAN data path session */
+	QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST = 3,
+	/* Command to notify if the NAN data path session was sent */
+	QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE = 4,
+	/* Command to respond to NAN data path session */
+	QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST = 5,
+	/* Command to notify on the responder about the response */
+	QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_RESPONSE = 6,
+	/* Command to initiate a NAN data path end */
+	QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST = 7,
+	/* Command to notify the if end request was sent */
+	QCA_WLAN_VENDOR_ATTR_NDP_END_RESPONSE = 8,
+	/* Command to notify the peer about the end request */
+	QCA_WLAN_VENDOR_ATTR_NDP_REQUEST_IND = 9,
+	/* Command to confirm the NAN data path session is complete */
+	QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND = 10,
+	/* Command to indicate the peer about the end request being received */
+	QCA_WLAN_VENDOR_ATTR_NDP_END_IND = 11,
+	/* Command to indicate the peer of schedule update */
+	QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_IND = 12
+};
+
+/**
+ * enum qca_wlan_vendor_attr_nd_offload - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD.
+ */
+enum qca_wlan_vendor_attr_nd_offload {
+	QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_INVALID = 0,
+	/* Flag to set Neighbour Discovery offload */
+	QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG,
+	/* Keep last */
+	QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX =
+		QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST - 1,
+};
+
+/**
+ * enum packet_filter_sub_cmd - Packet filter sub commands
+ */
+enum packet_filter_sub_cmd {
+	/**
+	 * Write packet filter program and/or data. The driver/firmware should
+	 * disable APF before writing into local buffer and re-enable APF after
+	 * writing is done.
+	 */
+	QCA_WLAN_SET_PACKET_FILTER = 1,
+	/* Get packet filter feature capabilities from driver */
+	QCA_WLAN_GET_PACKET_FILTER = 2,
+	/**
+	 * Write packet filter program and/or data. User space will send the
+	 * %QCA_WLAN_DISABLE_PACKET_FILTER command before issuing this command
+	 * and will send the %QCA_WLAN_ENABLE_PACKET_FILTER afterwards. The key
+	 * difference from that %QCA_WLAN_SET_PACKET_FILTER is the control over
+	 * enable/disable is given to user space with this command. Also,
+	 * user space sends the length of program portion in the buffer within
+	 * %QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH.
+	 */
+	QCA_WLAN_WRITE_PACKET_FILTER = 3,
+	/* Read packet filter program and/or data */
+	QCA_WLAN_READ_PACKET_FILTER = 4,
+	/* Enable APF feature */
+	QCA_WLAN_ENABLE_PACKET_FILTER = 5,
+	/* Disable APF feature */
+	QCA_WLAN_DISABLE_PACKET_FILTER = 6,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_packet_filter - BPF control commands used by
+ * vendor QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER.
+ */
+enum qca_wlan_vendor_attr_packet_filter {
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID = 0,
+	/* Unsigned 32-bit enum passed using packet_filter_sub_cmd */
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
+	/* Unsigned 32-bit value indicating the packet filter version */
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION,
+	/* Unsigned 32-bit value indicating the packet filter id */
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
+	/**
+	 * Unsigned 32-bit value indicating the packet filter size including
+	 * program + data.
+	 */
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE,
+	/* Unsigned 32-bit value indicating the packet filter current offset */
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
+	/* Program and/or data in bytes */
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
+	/* Unsigned 32-bit value of the length of the program section in packet
+	 * filter buffer.
+	 */
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH = 7,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX =
+	QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_drv_info - WLAN driver info used by vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE.
+ */
+enum qca_wlan_vendor_drv_info {
+	QCA_WLAN_VENDOR_ATTR_DRV_INFO_INVALID = 0,
+	/* Maximum Message size info between firmware & HOST
+	 * Unsigned 32-bit value
+	 */
+	QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_DRV_INFO_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX =
+		QCA_WLAN_VENDOR_ATTR_DRV_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_wake_stats - Wake lock stats used by vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS.
+ */
+enum qca_wlan_vendor_attr_wake_stats {
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_INVALID = 0,
+	/* Unsigned 32-bit value indicating the total count of wake event */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE,
+	/* Array of individual wake count, each index representing wake reason
+	 */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR,
+	/* Unsigned 32-bit value representing wake count array */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ,
+	/* Unsigned 32-bit total wake count value of driver/fw */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE,
+	/* Array of wake stats of driver/fw */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR,
+	/* Unsigned 32-bit total wake count value of driver/fw */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ,
+	/* Unsigned 32-bit total wake count value of packets received */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE,
+	/* Unsigned 32-bit wake count value unicast packets received */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT,
+	/* Unsigned 32-bit wake count value multicast packets received */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT,
+	/* Unsigned 32-bit wake count value broadcast packets received */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT,
+	/* Unsigned 32-bit wake count value of ICMP packets */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT,
+	/* Unsigned 32-bit wake count value of ICMP6 packets */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT,
+	/* Unsigned 32-bit value ICMP6 router advertisement */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA,
+	/* Unsigned 32-bit value ICMP6 neighbor advertisement */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA,
+	/* Unsigned 32-bit value ICMP6 neighbor solicitation */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS,
+	/* Unsigned 32-bit wake count value of receive side ICMP4 multicast */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT,
+	/* Unsigned 32-bit wake count value of receive side ICMP6 multicast */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT,
+	/* Unsigned 32-bit wake count value of receive side multicast */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT,
+	/* Unsigned 32-bit wake count value of a given RSSI breach */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RSSI_BREACH_CNT,
+	/* Unsigned 32-bit wake count value of low RSSI */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_LOW_RSSI_CNT,
+	/* Unsigned 32-bit value GSCAN count */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_GSCAN_CNT,
+	/* Unsigned 32-bit value PNO complete count */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_COMPLETE_CNT,
+	/* Unsigned 32-bit value PNO match count */
+	QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_MATCH_CNT,
+	/* keep last */
+	QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST,
+	QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX =
+		QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_thermal_cmd - Vendor subcmd attributes to set
+ * cmd value. Used for NL attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command.
+ */
+enum qca_wlan_vendor_attr_thermal_cmd {
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_INVALID = 0,
+	/* The value of command, driver will implement different operations
+	 * according to this value. It uses values defined in
+	 * enum qca_wlan_vendor_attr_thermal_cmd_type.
+	 * u32 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX =
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST - 1
+};
+
+/**
+ * qca_wlan_vendor_attr_thermal_cmd_type: Attribute values for
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE to the vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD. This represents the
+ * thermal command types sent to driver.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS: Request to
+ * get thermal shutdown configuration parameters for display. Parameters
+ * responded from driver are defined in
+ * enum qca_wlan_vendor_attr_get_thermal_params_rsp.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE: Request to
+ * get temperature. Host should respond with a temperature data. It is defined
+ * in enum qca_wlan_vendor_attr_thermal_get_temperature.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND: Request to execute thermal
+ * suspend action.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME: Request to execute thermal
+ * resume action.
+ */
+enum qca_wlan_vendor_attr_thermal_cmd_type {
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_thermal_get_temperature - vendor subcmd attributes
+ * to get chip temperature by user.
+ * enum values are used for NL attributes for data used by
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE command for data used
+ * by QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command.
+ */
+enum qca_wlan_vendor_attr_thermal_get_temperature {
+	QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_INVALID = 0,
+	/* Temperature value (degree Celsius) from driver.
+	 * u32 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_DATA,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_MAX =
+	QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_thermal_params_rsp - vendor subcmd attributes
+ * to get configuration parameters of thermal shutdown feature. Enum values are
+ * used by QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS command for data
+ * used by QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command.
+ */
+enum qca_wlan_vendor_attr_get_thermal_params_rsp {
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_INVALID = 0,
+	/* Indicate if the thermal shutdown feature is enabled.
+	 * NLA_FLAG attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SHUTDOWN_EN,
+	/* Indicate if the auto mode is enabled.
+	 * Enable: Driver triggers the suspend/resume action.
+	 * Disable: User space triggers the suspend/resume action.
+	 * NLA_FLAG attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SHUTDOWN_AUTO_EN,
+	/* Thermal resume threshold (degree Celsius). Issue the resume command
+	 * if the temperature value is lower than this threshold.
+	 * u16 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_RESUME_THRESH,
+	/* Thermal warning threshold (degree Celsius). FW reports temperature
+	 * to driver if it's higher than this threshold.
+	 * u16 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_WARNING_THRESH,
+	/* Thermal suspend threshold (degree Celsius). Issue the suspend command
+	 * if the temperature value is higher than this threshold.
+	 * u16 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SUSPEND_THRESH,
+	/* FW reports temperature data periodically at this interval (ms).
+	 * u16 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SAMPLE_RATE,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_MAX =
+	QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_thermal_event - vendor subcmd attributes to
+ * report thermal events from driver to user space.
+ * enum values are used for NL attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT sub command.
+ */
+enum qca_wlan_vendor_attr_thermal_event {
+	QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_INVALID = 0,
+	/* Temperature value (degree Celsius) from driver.
+	 * u32 attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_TEMPERATURE,
+	/* Indication of resume completion from power save mode.
+	 * NLA_FLAG attribute.
+	 */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_MAX =
+	QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST - 1,
+};
+
+/**
+ * enum he_fragmentation_val - HE fragmentation support values
+ * Indicates level of dynamic fragmentation that is supported by
+ * a STA as a recipient.
+ * HE fragmentation values are defined in IEEE P802.11ax/D2.0, 9.4.2.237.2
+ * (HE MAC Capabilities Information field) and are used in HE Capabilities
+ * element to advertise the support. These values are validated in the driver
+ * to check the device capability and advertised in the HE Capabilities
+ * element. These values are used to configure testbed device to allow the
+ * advertised hardware capabilities to be downgraded for testing purposes.
+ *
+ * @HE_FRAG_DISABLE: no support for dynamic fragmentation
+ * @HE_FRAG_LEVEL1: support for dynamic fragments that are
+ *	contained within an MPDU or S-MPDU, no support for dynamic fragments
+ *	within an A-MPDU that is not an S-MPDU.
+ * @HE_FRAG_LEVEL2: support for dynamic fragments that are
+ *	contained within an MPDU or S-MPDU and support for up to one dynamic
+ *	fragment for each MSDU, each A-MSDU if supported by the recipient, and
+ *	each MMPDU within an A-MPDU or multi-TID A-MPDU that is not an
+ *	MPDU or S-MPDU.
+ * @HE_FRAG_LEVEL3: support for dynamic fragments that are
+ *	contained within an MPDU or S-MPDU and support for multiple dynamic
+ *	fragments for each MSDU and for each A-MSDU if supported by the
+ *	recipient within an A-MPDU or multi-TID AMPDU and up to one dynamic
+ *	fragment for each MMPDU in a multi-TID A-MPDU that is not an S-MPDU.
+ */
+enum he_fragmentation_val {
+	HE_FRAG_DISABLE,
+	HE_FRAG_LEVEL1,
+	HE_FRAG_LEVEL2,
+	HE_FRAG_LEVEL3,
+};
+
+/**
+ * enum he_mcs_config - HE MCS support configuration
+ *
+ * Configures the HE Tx/Rx MCS map in HE capability IE for given bandwidth.
+ * These values are used in driver to configure the HE MCS map to advertise
+ * Tx/Rx MCS map in HE capability and these values are applied for all the
+ * streams supported by the device. To configure MCS for different bandwidths,
+ * vendor command needs to be sent using this attribute with appropriate value.
+ * For example, to configure HE_80_MCS_0_7, send vendor command using HE MCS
+ * attribute with HE_80_MCS0_7. And to configure HE MCS for HE_160_MCS0_11
+ * send this command using HE MCS config attribute with value HE_160_MCS0_11.
+ * These values are used to configure testbed device to allow the advertised
+ * hardware capabilities to be downgraded for testing purposes. The enum values
+ * are defined such that BIT[1:0] indicates the MCS map value. Values 3,7 and
+ * 11 are not used as BIT[1:0] value is 3 which is used to disable MCS map.
+ * These values are validated in the driver before setting the MCS map and
+ * driver returns error if the input is other than these enum values.
+ *
+ * @HE_80_MCS0_7: support for HE 80/40/20 MHz MCS 0 to 7
+ * @HE_80_MCS0_9: support for HE 80/40/20 MHz MCS 0 to 9
+ * @HE_80_MCS0_11: support for HE 80/40/20 MHz MCS 0 to 11
+ * @HE_160_MCS0_7: support for HE 160 MHz MCS 0 to 7
+ * @HE_160_MCS0_9: support for HE 160 MHz MCS 0 to 9
+ * @HE_160_MCS0_11: support for HE 160 MHz MCS 0 to 11
+ * @HE_80P80_MCS0_7: support for HE 80p80 MHz MCS 0 to 7
+ * @HE_80P80_MCS0_9: support for HE 80p80 MHz MCS 0 to 9
+ * @HE_80P80_MCS0_11: support for HE 80p80 MHz MCS 0 to 11
+ */
+enum he_mcs_config {
+	HE_80_MCS0_7 = 0,
+	HE_80_MCS0_9 = 1,
+	HE_80_MCS0_11 = 2,
+	HE_160_MCS0_7 = 4,
+	HE_160_MCS0_9 = 5,
+	HE_160_MCS0_11 = 6,
+	HE_80P80_MCS0_7 = 8,
+	HE_80P80_MCS0_9 = 9,
+	HE_80P80_MCS0_11 = 10,
+};
+
+/**
+ * enum qca_wlan_ba_session_config - BA session configuration
+ *
+ * Indicates the configuration values for BA session configuration attribute.
+ *
+ * @QCA_WLAN_ADD_BA: Establish a new BA session with given configuration.
+ * @QCA_WLAN_DELETE_BA: Delete the existing BA session for given TID.
+ */
+enum qca_wlan_ba_session_config {
+	QCA_WLAN_ADD_BA = 1,
+	QCA_WLAN_DELETE_BA = 2,
+};
+
+/**
+ * enum qca_wlan_ac_type - Access category type
+ *
+ * Indicates the access category type value.
+ *
+ * @QCA_WLAN_AC_BE: BE access category
+ * @QCA_WLAN_AC_BK: BK access category
+ * @QCA_WLAN_AC_VI: VI access category
+ * @QCA_WLAN_AC_VO: VO access category
+ * @QCA_WLAN_AC_ALL: All ACs
+ */
+enum qca_wlan_ac_type {
+	QCA_WLAN_AC_BE = 0,
+	QCA_WLAN_AC_BK = 1,
+	QCA_WLAN_AC_VI = 2,
+	QCA_WLAN_AC_VO = 3,
+	QCA_WLAN_AC_ALL = 4,
+};
+
+/**
+ * enum qca_wlan_he_ltf_cfg - HE LTF configuration
+ *
+ * Indicates the HE LTF configuration value.
+ *
+ * @QCA_WLAN_HE_LTF_AUTO: HE-LTF is automatically set to the mandatory HE-LTF,
+ * based on the GI setting
+ * @QCA_WLAN_HE_LTF_1X: 1X HE LTF is 3.2us LTF
+ * @QCA_WLAN_HE_LTF_2X: 2X HE LTF is 6.4us LTF
+ * @QCA_WLAN_HE_LTF_4X: 4X HE LTF is 12.8us LTF
+ */
+enum qca_wlan_he_ltf_cfg {
+	QCA_WLAN_HE_LTF_AUTO = 0,
+	QCA_WLAN_HE_LTF_1X = 1,
+	QCA_WLAN_HE_LTF_2X = 2,
+	QCA_WLAN_HE_LTF_4X = 3,
+};
+
+/* Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION
+ */
+enum qca_wlan_vendor_attr_wifi_test_config {
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_INVALID = 0,
+	/* 8-bit unsigned value to configure the driver to enable/disable
+	 * WMM feature. This attribute is used to configure testbed device.
+	 * 1-enable, 0-disable
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE = 1,
+
+	/* 8-bit unsigned value to configure the driver to accept/reject
+	 * the addba request from peer. This attribute is used to configure
+	 * the testbed device.
+	 * 1-accept addba, 0-reject addba
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ = 2,
+
+	/* 8-bit unsigned value to configure the driver to send or not to
+	 * send the addba request to peer.
+	 * This attribute is used to configure the testbed device.
+	 * 1-send addba, 0-do not send addba
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ = 3,
+
+	/* 8-bit unsigned value to indicate the HE fragmentation support.
+	 * Uses enum he_fragmentation_val values.
+	 * This attribute is used to configure the testbed device to
+	 * allow the advertised hardware capabilities to be downgraded
+	 * for testing purposes.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION = 4,
+
+	/* 8-bit unsigned value to indicate the HE MCS support.
+	 * Uses enum he_mcs_config values.
+	 * This attribute is used to configure the testbed device to
+	 * allow the advertised hardware capabilities to be downgraded
+	 * for testing purposes.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS = 5,
+
+	/* 8-bit unsigned value to configure the driver to allow or not to
+	 * allow the connection with WEP/TKIP in HT/VHT/HE modes.
+	 * This attribute is used to configure the testbed device.
+	 * 1-allow WEP/TKIP in HT/VHT/HE, 0-do not allow WEP/TKIP.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE = 6,
+
+	/* 8-bit unsigned value to configure the driver to add a
+	 * new BA session or delete the existing BA session for
+	 * given TID. ADDBA command uses the buffer size and TID
+	 * configuration if user specifies the values else default
+	 * value for buffer size is used for all TIDs if the TID
+	 * also not specified. For DEL_BA command TID value is
+	 * required to process the command.
+	 * Uses enum qca_wlan_ba_session_config values.
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION = 7,
+
+	/* 8-bit unsigned value to configure the buffer size in addba
+	 * request and response frames.
+	 * This attribute is used to configure the testbed device.
+	 * The range of the value is 0 to 255.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE = 8,
+
+	/* 8-bit unsigned value to configure the buffer size in addba
+	 * request and response frames.
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID = 9,
+
+	/* 8-bit unsigned value to configure the no ack policy.
+	 * To configure no ack policy, access category value is
+	 * required to process the command.
+	 * This attribute is used to configure the testbed device.
+	 * 1 - enable no ack, 0 - disable no ack.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK = 10,
+
+	/* 8-bit unsigned value to configure the AC for no ack policy
+	 * This attribute is used to configure the testbed device.
+	 * Uses the enum qca_wlan_ac_type values.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC = 11,
+
+	/* 8-bit unsigned value to configure the HE LTF
+	 * This attribute is used to configure the testbed device.
+	 * Uses the enum qca_wlan_he_ltf_cfg values.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF = 12,
+
+	/* 8-bit unsigned value to configure the tx beamformee.
+	 * This attribute is used to configure the testbed device.
+	 * 1-enable, 0-disable.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE = 13,
+
+	/* 8-bit unsigned value to configure the tx beamformee number
+	 * of space-time streams.
+	 * This attribute is used to configure the testbed device.
+	 * The range of the value is 0 to 8.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS = 14,
+
+	/* 8-bit unsigned value to configure the MU EDCA params for given AC
+	 * This attribute is used to configure the testbed device.
+	 * Uses the enum qca_wlan_ac_type values.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC = 15,
+
+	/* 8-bit unsigned value to configure the MU EDCA AIFSN for given AC
+	 * To configure MU EDCA AIFSN value, MU EDCA access category value
+	 * is required to process the command.
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AIFSN = 16,
+
+	/* 8-bit unsigned value to configure the MU EDCA ECW min value for
+	 * given AC.
+	 * To configure MU EDCA ECW min value, MU EDCA access category value
+	 * is required to process the command.
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_ECWMIN = 17,
+
+	/* 8-bit unsigned value to configure the MU EDCA ECW max value for
+	 * given AC.
+	 * To configure MU EDCA ECW max value, MU EDCA access category value
+	 * is required to process the command.
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_ECWMAX = 18,
+
+	/* 8-bit unsigned value to configure the MU EDCA timer for given AC
+	 * To configure MU EDCA timer value, MU EDCA access category value
+	 * is required to process the command.
+	 * This attribute is used to configure the testbed device.
+	 */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_TIMER = 19,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
+	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_bss_filter - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER.
+ * The user can add/delete the filter by specifying the BSSID/STA MAC address in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR, filter type in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE, add/delete action in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION in the request. The user can get the
+ * statistics of an unassociated station by specifying the MAC address in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR, station type in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE, GET action in
+ * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION in the request. The user also can get
+ * the statistics of all unassociated stations by specifying the Broadcast MAC
+ * address (ff:ff:ff:ff:ff:ff) in QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR with
+ * above procedure. In the response, driver shall specify statistics
+ * information nested in QCA_WLAN_VENDOR_ATTR_BSS_FILTER_STA_STATS.
+ */
+enum qca_wlan_vendor_attr_bss_filter {
+	QCA_WLAN_VENDOR_ATTR_BSS_FILTER_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR = 1,
+	/* Other BSS filter type, unsigned 8 bit value. One of the values
+	 * in enum qca_wlan_vendor_bss_filter_type.
+	 */
+	QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE = 2,
+	/* Other BSS filter action, unsigned 8 bit value. One of the values
+	 * in enum qca_wlan_vendor_bss_filter_action.
+	 */
+	QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION = 3,
+	/* Array of nested attributes where each entry is the statistics
+	 * information of the specified station that belong to another BSS.
+	 * Attributes for each entry are taken from enum
+	 * qca_wlan_vendor_bss_filter_sta_stats.
+	 * Other BSS station configured in
+	 * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER with filter type
+	 * QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA.
+	 * Statistics returned by QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER
+	 * with filter action QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET.
+	 */
+	QCA_WLAN_VENDOR_ATTR_BSS_FILTER_STA_STATS = 4,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_BSS_FILTER_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAX =
+	QCA_WLAN_VENDOR_ATTR_BSS_FILTER_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_bss_filter_type - Type of
+ * filter used in other BSS filter operations. Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER.
+ *
+ * @QCA_WLAN_VENDOR_BSS_FILTER_TYPE_BSSID: BSSID filter
+ * @QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA: Station MAC address filter
+ */
+enum qca_wlan_vendor_bss_filter_type {
+	QCA_WLAN_VENDOR_BSS_FILTER_TYPE_BSSID,
+	QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA,
+};
+
+/**
+ * enum qca_wlan_vendor_bss_filter_action - Type of
+ * action in other BSS filter operations. Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER.
+ *
+ * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_ADD: Add filter
+ * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_DEL: Delete filter
+ * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET: Get the statistics
+ */
+enum qca_wlan_vendor_bss_filter_action {
+	QCA_WLAN_VENDOR_BSS_FILTER_ACTION_ADD,
+	QCA_WLAN_VENDOR_BSS_FILTER_ACTION_DEL,
+	QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET,
+};
+
+/**
+ * enum qca_wlan_vendor_bss_filter_sta_stats - Attributes for
+ * the statistics of a specific unassociated station belonging to another BSS.
+ * The statistics provides information of the unassociated station
+ * filtered by other BSS operation - such as MAC, signal value.
+ * Used by the vendor command QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER.
+ *
+ * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAC: MAC address of the station.
+ * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI: Last received signal strength
+ *	of the station. Unsigned 8 bit number containing RSSI.
+ * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI_TS: Time stamp of the host
+ *	driver for the last received RSSI. Unsigned 64 bit number containing
+ *	nanoseconds from the boottime.
+ */
+enum qca_wlan_vendor_bss_filter_sta_stats {
+	QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_INVALID = 0,
+	QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAC = 1,
+	QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI = 2,
+	QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI_TS = 3,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_AFTER_LAST,
+	QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAX =
+	QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_AFTER_LAST - 1
+};
+
 #endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index 9f70f03..981e788 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -29,6 +29,8 @@
 	/* First, check if this is an ECC group */
 	tmp->ec = crypto_ec_init(group);
 	if (tmp->ec) {
+		wpa_printf(MSG_DEBUG, "SAE: Selecting supported ECC group %d",
+			   group);
 		sae->group = group;
 		tmp->prime_len = crypto_ec_prime_len(tmp->ec);
 		tmp->prime = crypto_ec_get_prime(tmp->ec);
@@ -39,6 +41,8 @@
 	/* Not an ECC group, check FFC */
 	tmp->dh = dh_groups_get(group);
 	if (tmp->dh) {
+		wpa_printf(MSG_DEBUG, "SAE: Selecting supported FFC group %d",
+			   group);
 		sae->group = group;
 		tmp->prime_len = tmp->dh->prime_len;
 		if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
@@ -66,6 +70,8 @@
 	}
 
 	/* Unsupported group */
+	wpa_printf(MSG_DEBUG,
+		   "SAE: Group %d not supported by the crypto library", group);
 	return -1;
 }
 
@@ -88,6 +94,7 @@
 	crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
 	crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
 	wpabuf_free(tmp->anti_clogging_token);
+	os_free(tmp->pw_id);
 	bin_clear_free(tmp, sizeof(*tmp));
 	sae->tmp = NULL;
 }
@@ -417,12 +424,13 @@
 
 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
 			      const u8 *addr2, const u8 *password,
-			      size_t password_len)
+			      size_t password_len, const char *identifier)
 {
 	u8 counter, k = 40;
 	u8 addrs[2 * ETH_ALEN];
-	const u8 *addr[2];
-	size_t len[2];
+	const u8 *addr[3];
+	size_t len[3];
+	size_t num_elem;
 	u8 dummy_password[32];
 	size_t dummy_password_len;
 	int pwd_seed_odd = 0;
@@ -454,10 +462,13 @@
 
 	wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
 			      password, password_len);
+	if (identifier)
+		wpa_printf(MSG_DEBUG, "SAE: password identifier: %s",
+			   identifier);
 
 	/*
 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
-	 * base = password
+	 * base = password [|| identifier]
 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
 	 *              base || counter)
 	 */
@@ -465,8 +476,15 @@
 
 	addr[0] = password;
 	len[0] = password_len;
-	addr[1] = &counter;
-	len[1] = sizeof(counter);
+	num_elem = 1;
+	if (identifier) {
+		addr[num_elem] = (const u8 *) identifier;
+		len[num_elem] = os_strlen(identifier);
+		num_elem++;
+	}
+	addr[num_elem] = &counter;
+	len[num_elem] = sizeof(counter);
+	num_elem++;
 
 	/*
 	 * Continue for at least k iterations to protect against side-channel
@@ -484,8 +502,8 @@
 		}
 
 		wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
-		if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
-				       pwd_seed) < 0)
+		if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+				       addr, len, pwd_seed) < 0)
 			break;
 
 		res = sae_test_pwd_seed_ecc(sae, pwd_seed,
@@ -544,12 +562,13 @@
 
 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
 			      const u8 *addr2, const u8 *password,
-			      size_t password_len)
+			      size_t password_len, const char *identifier)
 {
 	u8 counter;
 	u8 addrs[2 * ETH_ALEN];
-	const u8 *addr[2];
-	size_t len[2];
+	const u8 *addr[3];
+	size_t len[3];
+	size_t num_elem;
 	int found = 0;
 
 	if (sae->tmp->pwe_ffc == NULL) {
@@ -564,14 +583,21 @@
 	/*
 	 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
 	 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
-	 *              password || counter)
+	 *              password [|| identifier] || counter)
 	 */
 	sae_pwd_seed_key(addr1, addr2, addrs);
 
 	addr[0] = password;
 	len[0] = password_len;
-	addr[1] = &counter;
-	len[1] = sizeof(counter);
+	num_elem = 1;
+	if (identifier) {
+		addr[num_elem] = (const u8 *) identifier;
+		len[num_elem] = os_strlen(identifier);
+		num_elem++;
+	}
+	addr[num_elem] = &counter;
+	len[num_elem] = sizeof(counter);
+	num_elem++;
 
 	for (counter = 1; !found; counter++) {
 		u8 pwd_seed[SHA256_MAC_LEN];
@@ -584,8 +610,8 @@
 		}
 
 		wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
-		if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
-				       pwd_seed) < 0)
+		if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+				       addr, len, pwd_seed) < 0)
 			break;
 		res = sae_test_pwd_seed_ffc(sae, pwd_seed, sae->tmp->pwe_ffc);
 		if (res < 0)
@@ -696,13 +722,15 @@
 
 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
 		       const u8 *password, size_t password_len,
-		       struct sae_data *sae)
+		       const char *identifier, struct sae_data *sae)
 {
 	if (sae->tmp == NULL ||
 	    (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
-						password_len) < 0) ||
+						password_len,
+						identifier) < 0) ||
 	    (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
-						password_len) < 0) ||
+						password_len,
+						identifier) < 0) ||
 	    sae_derive_commit(sae) < 0)
 		return -1;
 	return 0;
@@ -842,7 +870,7 @@
 
 
 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
-		      const struct wpabuf *token)
+		      const struct wpabuf *token, const char *identifier)
 {
 	u8 *pos;
 
@@ -876,6 +904,16 @@
 		wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
 			    pos, sae->tmp->prime_len);
 	}
+
+	if (identifier) {
+		/* Password Identifier element */
+		wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+		wpabuf_put_u8(buf, 1 + os_strlen(identifier));
+		wpabuf_put_u8(buf, WLAN_EID_EXT_PASSWORD_IDENTIFIER);
+		wpabuf_put_str(buf, identifier);
+		wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s",
+			   identifier);
+	}
 }
 
 
@@ -921,25 +959,70 @@
 }
 
 
+static int sae_is_password_id_elem(const u8 *pos, const u8 *end)
+{
+	return end - pos >= 3 &&
+		pos[0] == WLAN_EID_EXTENSION &&
+		pos[1] >= 1 &&
+		end - pos - 2 >= pos[1] &&
+		pos[2] == WLAN_EID_EXT_PASSWORD_IDENTIFIER;
+}
+
+
 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
 				   const u8 *end, const u8 **token,
 				   size_t *token_len)
 {
-	if ((sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end - *pos) {
-		size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) *
-				     sae->tmp->prime_len);
-		wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
-		if (token)
-			*token = *pos;
-		if (token_len)
-			*token_len = tlen;
-		*pos += tlen;
-	} else {
-		if (token)
-			*token = NULL;
-		if (token_len)
-			*token_len = 0;
+	size_t scalar_elem_len, tlen;
+	const u8 *elem;
+
+	if (token)
+		*token = NULL;
+	if (token_len)
+		*token_len = 0;
+
+	scalar_elem_len = (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len;
+	if (scalar_elem_len >= (size_t) (end - *pos))
+		return; /* No extra data beyond peer scalar and element */
+
+	/* It is a bit difficult to parse this now that there is an
+	 * optional variable length Anti-Clogging Token field and
+	 * optional variable length Password Identifier element in the
+	 * frame. We are sending out fixed length Anti-Clogging Token
+	 * fields, so use that length as a requirement for the received
+	 * token and check for the presence of possible Password
+	 * Identifier element based on the element header information.
+	 */
+	tlen = end - (*pos + scalar_elem_len);
+
+	if (tlen < SHA256_MAC_LEN) {
+		wpa_printf(MSG_DEBUG,
+			   "SAE: Too short optional data (%u octets) to include our Anti-Clogging Token",
+			   (unsigned int) tlen);
+		return;
 	}
+
+	elem = *pos + scalar_elem_len;
+	if (sae_is_password_id_elem(elem, end)) {
+		 /* Password Identifier element takes out all available
+		  * extra octets, so there can be no Anti-Clogging token in
+		  * this frame. */
+		return;
+	}
+
+	elem += SHA256_MAC_LEN;
+	if (sae_is_password_id_elem(elem, end)) {
+		 /* Password Identifier element is included in the end, so
+		  * remove its length from the Anti-Clogging token field. */
+		tlen -= 2 + elem[1];
+	}
+
+	wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
+	if (token)
+		*token = *pos;
+	if (token_len)
+		*token_len = tlen;
+	*pos += tlen;
 }
 
 
@@ -991,12 +1074,12 @@
 }
 
 
-static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos,
+static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos,
 					const u8 *end)
 {
 	u8 prime[SAE_MAX_ECC_PRIME_LEN];
 
-	if (2 * sae->tmp->prime_len > end - pos) {
+	if (2 * sae->tmp->prime_len > end - *pos) {
 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
 			   "commit-element");
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -1007,8 +1090,8 @@
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
 	/* element x and y coordinates < p */
-	if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 ||
-	    os_memcmp(pos + sae->tmp->prime_len, prime,
+	if (os_memcmp(*pos, prime, sae->tmp->prime_len) >= 0 ||
+	    os_memcmp(*pos + sae->tmp->prime_len, prime,
 		      sae->tmp->prime_len) >= 0) {
 		wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
 			   "element");
@@ -1016,13 +1099,13 @@
 	}
 
 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
-		    pos, sae->tmp->prime_len);
+		    *pos, sae->tmp->prime_len);
 	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
-		    pos + sae->tmp->prime_len, sae->tmp->prime_len);
+		    *pos + sae->tmp->prime_len, sae->tmp->prime_len);
 
 	crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
 	sae->tmp->peer_commit_element_ecc =
-		crypto_ec_point_from_bin(sae->tmp->ec, pos);
+		crypto_ec_point_from_bin(sae->tmp->ec, *pos);
 	if (sae->tmp->peer_commit_element_ecc == NULL)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
@@ -1032,27 +1115,29 @@
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 	}
 
+	*pos += 2 * sae->tmp->prime_len;
+
 	return WLAN_STATUS_SUCCESS;
 }
 
 
-static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
+static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos,
 					const u8 *end)
 {
 	struct crypto_bignum *res, *one;
 	const u8 one_bin[1] = { 0x01 };
 
-	if (sae->tmp->prime_len > end - pos) {
+	if (sae->tmp->prime_len > end - *pos) {
 		wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
 			   "commit-element");
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 	}
-	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos,
+	wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", *pos,
 		    sae->tmp->prime_len);
 
 	crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
 	sae->tmp->peer_commit_element_ffc =
-		crypto_bignum_init_set(pos, sae->tmp->prime_len);
+		crypto_bignum_init_set(*pos, sae->tmp->prime_len);
 	if (sae->tmp->peer_commit_element_ffc == NULL)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
 	/* 1 < element < p - 1 */
@@ -1080,11 +1165,13 @@
 	}
 	crypto_bignum_deinit(res, 0);
 
+	*pos += sae->tmp->prime_len;
+
 	return WLAN_STATUS_SUCCESS;
 }
 
 
-static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos,
+static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos,
 				    const u8 *end)
 {
 	if (sae->tmp->dh)
@@ -1093,6 +1180,44 @@
 }
 
 
+static int sae_parse_password_identifier(struct sae_data *sae,
+					 const u8 *pos, const u8 *end)
+{
+	wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
+		    pos, end - pos);
+	if (!sae_is_password_id_elem(pos, end)) {
+		if (sae->tmp->pw_id) {
+			wpa_printf(MSG_DEBUG,
+				   "SAE: No Password Identifier included, but expected one (%s)",
+				   sae->tmp->pw_id);
+			return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
+		}
+		os_free(sae->tmp->pw_id);
+		sae->tmp->pw_id = NULL;
+		return WLAN_STATUS_SUCCESS; /* No Password Identifier */
+	}
+
+	if (sae->tmp->pw_id &&
+	    (pos[1] - 1 != (int) os_strlen(sae->tmp->pw_id) ||
+	     os_memcmp(sae->tmp->pw_id, pos + 3, pos[1] - 1) != 0)) {
+		wpa_printf(MSG_DEBUG,
+			   "SAE: The included Password Identifier does not match the expected one (%s)",
+			   sae->tmp->pw_id);
+		return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
+	}
+
+	os_free(sae->tmp->pw_id);
+	sae->tmp->pw_id = os_malloc(pos[1]);
+	if (!sae->tmp->pw_id)
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	os_memcpy(sae->tmp->pw_id, pos + 3, pos[1] - 1);
+	sae->tmp->pw_id[pos[1] - 1] = '\0';
+	wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
+			  sae->tmp->pw_id, pos[1] -  1);
+	return WLAN_STATUS_SUCCESS;
+}
+
+
 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
 		     const u8 **token, size_t *token_len, int *allowed_groups)
 {
@@ -1116,7 +1241,12 @@
 		return res;
 
 	/* commit-element */
-	res = sae_parse_commit_element(sae, pos, end);
+	res = sae_parse_commit_element(sae, &pos, end);
+	if (res != WLAN_STATUS_SUCCESS)
+		return res;
+
+	/* Optional Password Identifier element */
+	res = sae_parse_password_identifier(sae, pos, end);
 	if (res != WLAN_STATUS_SUCCESS)
 		return res;
 
@@ -1235,7 +1365,8 @@
 	/* Send-Confirm */
 	sc = wpabuf_put(buf, 0);
 	wpabuf_put_le16(buf, sae->send_confirm);
-	sae->send_confirm++;
+	if (sae->send_confirm < 0xffff)
+		sae->send_confirm++;
 
 	if (sae->tmp->ec)
 		sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
@@ -1292,3 +1423,19 @@
 
 	return 0;
 }
+
+
+const char * sae_state_txt(enum sae_state state)
+{
+	switch (state) {
+	case SAE_NOTHING:
+		return "Nothing";
+	case SAE_COMMITTED:
+		return "Committed";
+	case SAE_CONFIRMED:
+		return "Confirmed";
+	case SAE_ACCEPTED:
+		return "Accepted";
+	}
+	return "?";
+}
diff --git a/src/common/sae.h b/src/common/sae.h
index a4270bc..3fbcb58 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -39,16 +39,22 @@
 	struct crypto_bignum *prime_buf;
 	struct crypto_bignum *order_buf;
 	struct wpabuf *anti_clogging_token;
+	char *pw_id;
+};
+
+enum sae_state {
+	SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED
 };
 
 struct sae_data {
-	enum { SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED } state;
+	enum sae_state state;
 	u16 send_confirm;
 	u8 pmk[SAE_PMK_LEN];
 	u8 pmkid[SAE_PMKID_LEN];
 	struct crypto_bignum *peer_commit_scalar;
 	int group;
-	int sync;
+	unsigned int sync; /* protocol instance variable: Sync */
+	u16 rc; /* protocol instance variable: Rc (received send-confirm) */
 	struct sae_temporary_data *tmp;
 };
 
@@ -58,14 +64,15 @@
 
 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
 		       const u8 *password, size_t password_len,
-		       struct sae_data *sae);
+		       const char *identifier, struct sae_data *sae);
 int sae_process_commit(struct sae_data *sae);
 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
-		      const struct wpabuf *token);
+		      const struct wpabuf *token, const char *identifier);
 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
 		     const u8 **token, size_t *token_len, int *allowed_groups);
 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
+const char * sae_state_txt(enum sae_state state);
 
 #endif /* SAE_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 4bab6b9..14c5769 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1,6 +1,6 @@
 /*
  * WPA/RSN - Shared functions for supplicant and authenticator
- * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -25,6 +25,7 @@
 {
 	switch (akmp) {
 	case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
+	case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
 		return 24;
 	case WPA_KEY_MGMT_FILS_SHA256:
 	case WPA_KEY_MGMT_FT_FILS_SHA256:
@@ -41,6 +42,21 @@
 }
 
 
+#ifdef CONFIG_IEEE80211R
+static unsigned int wpa_kck2_len(int akmp)
+{
+	switch (akmp) {
+	case WPA_KEY_MGMT_FT_FILS_SHA256:
+		return 16;
+	case WPA_KEY_MGMT_FT_FILS_SHA384:
+		return 24;
+	default:
+		return 0;
+	}
+}
+#endif /* CONFIG_IEEE80211R */
+
+
 static unsigned int wpa_kek_len(int akmp, size_t pmk_len)
 {
 	switch (akmp) {
@@ -50,6 +66,7 @@
 	case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
 	case WPA_KEY_MGMT_FILS_SHA256:
 	case WPA_KEY_MGMT_FT_FILS_SHA256:
+	case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
 		return 32;
 	case WPA_KEY_MGMT_DPP:
 		return pmk_len <= 32 ? 16 : 32;
@@ -61,10 +78,26 @@
 }
 
 
+#ifdef CONFIG_IEEE80211R
+static unsigned int wpa_kek2_len(int akmp)
+{
+	switch (akmp) {
+	case WPA_KEY_MGMT_FT_FILS_SHA256:
+		return 16;
+	case WPA_KEY_MGMT_FT_FILS_SHA384:
+		return 32;
+	default:
+		return 0;
+	}
+}
+#endif /* CONFIG_IEEE80211R */
+
+
 unsigned int wpa_mic_len(int akmp, size_t pmk_len)
 {
 	switch (akmp) {
 	case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
+	case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
 		return 24;
 	case WPA_KEY_MGMT_FILS_SHA256:
 	case WPA_KEY_MGMT_FILS_SHA384:
@@ -82,6 +115,61 @@
 
 
 /**
+ * wpa_use_akm_defined - Is AKM-defined Key Descriptor Version used
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
+ * Returns: 1 if AKM-defined Key Descriptor Version is used; 0 otherwise
+ */
+int wpa_use_akm_defined(int akmp)
+{
+	return akmp == WPA_KEY_MGMT_OSEN ||
+		akmp == WPA_KEY_MGMT_OWE ||
+		akmp == WPA_KEY_MGMT_DPP ||
+		akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384 ||
+		wpa_key_mgmt_sae(akmp) ||
+		wpa_key_mgmt_suite_b(akmp) ||
+		wpa_key_mgmt_fils(akmp);
+}
+
+
+/**
+ * wpa_use_cmac - Is CMAC integrity algorithm used for EAPOL-Key MIC
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
+ * Returns: 1 if CMAC is used; 0 otherwise
+ */
+int wpa_use_cmac(int akmp)
+{
+	return akmp == WPA_KEY_MGMT_OSEN ||
+		akmp == WPA_KEY_MGMT_OWE ||
+		akmp == WPA_KEY_MGMT_DPP ||
+		wpa_key_mgmt_ft(akmp) ||
+		wpa_key_mgmt_sha256(akmp) ||
+		wpa_key_mgmt_sae(akmp) ||
+		wpa_key_mgmt_suite_b(akmp);
+}
+
+
+/**
+ * wpa_use_aes_key_wrap - Is AES Keywrap algorithm used for EAPOL-Key Key Data
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
+ * Returns: 1 if AES Keywrap is used; 0 otherwise
+ *
+ * Note: AKM 00-0F-AC:1 and 00-0F-AC:2 have special rules for selecting whether
+ * to use AES Keywrap based on the negotiated pairwise cipher. This function
+ * does not cover those special cases.
+ */
+int wpa_use_aes_key_wrap(int akmp)
+{
+	return akmp == WPA_KEY_MGMT_OSEN ||
+		akmp == WPA_KEY_MGMT_OWE ||
+		akmp == WPA_KEY_MGMT_DPP ||
+		wpa_key_mgmt_ft(akmp) ||
+		wpa_key_mgmt_sha256(akmp) ||
+		wpa_key_mgmt_sae(akmp) ||
+		wpa_key_mgmt_suite_b(akmp);
+}
+
+
+/**
  * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
  * @key: EAPOL-Key Key Confirmation Key (KCK)
  * @key_len: KCK length in octets
@@ -131,6 +219,13 @@
 #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
 	case WPA_KEY_INFO_TYPE_AKM_DEFINED:
 		switch (akmp) {
+#ifdef CONFIG_SAE
+		case WPA_KEY_MGMT_SAE:
+		case WPA_KEY_MGMT_FT_SAE:
+			wpa_printf(MSG_DEBUG,
+				   "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - SAE)");
+			return omac1_aes_128(key, buf, len, mic);
+#endif /* CONFIG_SAE */
 #ifdef CONFIG_HS20
 		case WPA_KEY_MGMT_OSEN:
 			wpa_printf(MSG_DEBUG,
@@ -201,6 +296,15 @@
 			os_memcpy(mic, hash, key_len);
 			break;
 #endif /* CONFIG_DPP */
+#if defined(CONFIG_IEEE80211R) && defined(CONFIG_SHA384)
+		case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+			wpa_printf(MSG_DEBUG,
+				   "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - FT 802.1X SHA384)");
+			if (hmac_sha384(key, key_len, buf, len, hash))
+				return -1;
+			os_memcpy(mic, hash, 24);
+			break;
+#endif /* CONFIG_IEEE80211R && CONFIG_SHA384 */
 		default:
 			wpa_printf(MSG_DEBUG,
 				   "WPA: EAPOL-Key MIC algorithm not known (AKM-defined - akmp=0x%x)",
@@ -248,7 +352,7 @@
 	size_t ptk_len;
 
 	if (pmk_len == 0) {
-		wpa_printf(MSG_ERROR, "WPA: No PMK set for PT derivation");
+		wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation");
 		return -1;
 	}
 
@@ -273,6 +377,12 @@
 	ptk->kck_len = wpa_kck_len(akmp, pmk_len);
 	ptk->kek_len = wpa_kek_len(akmp, pmk_len);
 	ptk->tk_len = wpa_cipher_key_len(cipher);
+	if (ptk->tk_len == 0) {
+		wpa_printf(MSG_ERROR,
+			   "WPA: Unsupported cipher (0x%x) used in PTK derivation",
+			   cipher);
+		return -1;
+	}
 	ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
 
 	if (wpa_key_mgmt_sha384(akmp)) {
@@ -285,14 +395,14 @@
 		return -1;
 #endif /* CONFIG_SUITEB192 || CONFIG_FILS */
 	} else if (wpa_key_mgmt_sha256(akmp) || akmp == WPA_KEY_MGMT_OWE) {
-#ifdef CONFIG_IEEE80211W
+#if defined(CONFIG_IEEE80211W) || defined(CONFIG_SAE) || defined(CONFIG_FILS)
 		wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)");
 		if (sha256_prf(pmk, pmk_len, label, data, sizeof(data),
 			       tmp, ptk_len) < 0)
 			return -1;
-#else /* CONFIG_IEEE80211W */
+#else /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */
 		return -1;
-#endif /* CONFIG_IEEE80211W */
+#endif /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */
 #ifdef CONFIG_DPP
 	} else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 32) {
 		wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)");
@@ -337,6 +447,9 @@
 	os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
 	wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len);
 
+	ptk->kek2_len = 0;
+	ptk->kck2_len = 0;
+
 	os_memset(tmp, 0, sizeof(tmp));
 	return 0;
 }
@@ -386,6 +499,8 @@
 					 addr, len, pmk);
 	if (res == 0)
 		wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, *pmk_len);
+	else
+		*pmk_len = 0;
 	return res;
 }
 
@@ -515,6 +630,9 @@
 				fils_ft, *fils_ft_len);
 	}
 
+	ptk->kek2_len = 0;
+	ptk->kck2_len = 0;
+
 	os_memset(tmp, 0, sizeof(tmp));
 	ret = 0;
 err:
@@ -625,14 +743,23 @@
 	const u8 *addr[9];
 	size_t len[9];
 	size_t i, num_elem = 0;
-	u8 zero_mic[16];
+	u8 zero_mic[24];
+	size_t mic_len, fte_fixed_len;
 
-	if (kck_len != 16) {
+	if (kck_len == 16) {
+		mic_len = 16;
+#ifdef CONFIG_SHA384
+	} else if (kck_len == 24) {
+		mic_len = 24;
+#endif /* CONFIG_SHA384 */
+	} else {
 		wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
 			   (unsigned int) kck_len);
 		return -1;
 	}
 
+	fte_fixed_len = sizeof(struct rsn_ftie) - 16 + mic_len;
+
 	addr[num_elem] = sta_addr;
 	len[num_elem] = ETH_ALEN;
 	num_elem++;
@@ -656,7 +783,7 @@
 		num_elem++;
 	}
 	if (ftie) {
-		if (ftie_len < 2 + sizeof(struct rsn_ftie))
+		if (ftie_len < 2 + fte_fixed_len)
 			return -1;
 
 		/* IE hdr and mic_control */
@@ -665,14 +792,14 @@
 		num_elem++;
 
 		/* MIC field with all zeros */
-		os_memset(zero_mic, 0, sizeof(zero_mic));
+		os_memset(zero_mic, 0, mic_len);
 		addr[num_elem] = zero_mic;
-		len[num_elem] = sizeof(zero_mic);
+		len[num_elem] = mic_len;
 		num_elem++;
 
 		/* Rest of FTIE */
-		addr[num_elem] = ftie + 2 + 2 + 16;
-		len[num_elem] = ftie_len - (2 + 2 + 16);
+		addr[num_elem] = ftie + 2 + 2 + mic_len;
+		len[num_elem] = ftie_len - (2 + 2 + mic_len);
 		num_elem++;
 	}
 	if (ric) {
@@ -683,7 +810,17 @@
 
 	for (i = 0; i < num_elem; i++)
 		wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]);
-	if (omac1_aes_128_vector(kck, num_elem, addr, len, mic))
+#ifdef CONFIG_SHA384
+	if (kck_len == 24) {
+		u8 hash[SHA384_MAC_LEN];
+
+		if (hmac_sha384_vector(kck, kck_len, num_elem, addr, len, hash))
+			return -1;
+		os_memcpy(mic, hash, 24);
+	}
+#endif /* CONFIG_SHA384 */
+	if (kck_len == 16 &&
+	    omac1_aes_128_vector(kck, num_elem, addr, len, mic))
 		return -1;
 
 	return 0;
@@ -691,23 +828,27 @@
 
 
 static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
-			     struct wpa_ft_ies *parse)
+			     struct wpa_ft_ies *parse, int use_sha384)
 {
 	const u8 *end, *pos;
 
 	parse->ftie = ie;
 	parse->ftie_len = ie_len;
 
-	pos = ie + sizeof(struct rsn_ftie);
+	pos = ie + (use_sha384 ? sizeof(struct rsn_ftie_sha384) :
+		    sizeof(struct rsn_ftie));
 	end = ie + ie_len;
+	wpa_hexdump(MSG_DEBUG, "FT: Parse FTE subelements", pos, end - pos);
 
 	while (end - pos >= 2) {
 		u8 id, len;
 
 		id = *pos++;
 		len = *pos++;
-		if (len > end - pos)
+		if (len > end - pos) {
+			wpa_printf(MSG_DEBUG, "FT: Truncated subelement");
 			break;
+		}
 
 		switch (id) {
 		case FTIE_SUBELEM_R1KH_ID:
@@ -739,6 +880,9 @@
 			parse->igtk_len = len;
 			break;
 #endif /* CONFIG_IEEE80211W */
+		default:
+			wpa_printf(MSG_DEBUG, "FT: Unknown subelem id %u", id);
+			break;
 		}
 
 		pos += len;
@@ -749,13 +893,19 @@
 
 
 int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
-		     struct wpa_ft_ies *parse)
+		     struct wpa_ft_ies *parse, int use_sha384)
 {
 	const u8 *end, *pos;
 	struct wpa_ie_data data;
 	int ret;
 	const struct rsn_ftie *ftie;
 	int prot_ie_count = 0;
+	int update_use_sha384 = 0;
+
+	if (use_sha384 < 0) {
+		use_sha384 = 0;
+		update_use_sha384 = 1;
+	}
 
 	os_memset(parse, 0, sizeof(*parse));
 	if (ies == NULL)
@@ -773,6 +923,7 @@
 
 		switch (id) {
 		case WLAN_EID_RSN:
+			wpa_hexdump(MSG_DEBUG, "FT: RSNE", pos, len);
 			parse->rsn = pos;
 			parse->rsn_len = len;
 			ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
@@ -787,22 +938,63 @@
 				parse->rsn_pmkid = data.pmkid;
 			parse->key_mgmt = data.key_mgmt;
 			parse->pairwise_cipher = data.pairwise_cipher;
+			if (update_use_sha384) {
+				use_sha384 =
+					wpa_key_mgmt_sha384(parse->key_mgmt);
+				update_use_sha384 = 0;
+			}
 			break;
 		case WLAN_EID_MOBILITY_DOMAIN:
+			wpa_hexdump(MSG_DEBUG, "FT: MDE", pos, len);
 			if (len < sizeof(struct rsn_mdie))
 				return -1;
 			parse->mdie = pos;
 			parse->mdie_len = len;
 			break;
 		case WLAN_EID_FAST_BSS_TRANSITION:
+			wpa_hexdump(MSG_DEBUG, "FT: FTE", pos, len);
+			if (use_sha384) {
+				const struct rsn_ftie_sha384 *ftie_sha384;
+
+				if (len < sizeof(*ftie_sha384))
+					return -1;
+				ftie_sha384 =
+					(const struct rsn_ftie_sha384 *) pos;
+				wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
+					    ftie_sha384->mic_control, 2);
+				wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
+					    ftie_sha384->mic,
+					    sizeof(ftie_sha384->mic));
+				wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
+					    ftie_sha384->anonce,
+					    WPA_NONCE_LEN);
+				wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
+					    ftie_sha384->snonce,
+					    WPA_NONCE_LEN);
+				prot_ie_count = ftie_sha384->mic_control[1];
+				if (wpa_ft_parse_ftie(pos, len, parse, 1) < 0)
+					return -1;
+				break;
+			}
+
 			if (len < sizeof(*ftie))
 				return -1;
 			ftie = (const struct rsn_ftie *) pos;
+			wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
+				    ftie->mic_control, 2);
+			wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
+				    ftie->mic, sizeof(ftie->mic));
+			wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
+				    ftie->anonce, WPA_NONCE_LEN);
+			wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
+				    ftie->snonce, WPA_NONCE_LEN);
 			prot_ie_count = ftie->mic_control[1];
-			if (wpa_ft_parse_ftie(pos, len, parse) < 0)
+			if (wpa_ft_parse_ftie(pos, len, parse, 0) < 0)
 				return -1;
 			break;
 		case WLAN_EID_TIMEOUT_INTERVAL:
+			wpa_hexdump(MSG_DEBUG, "FT: Timeout Interval",
+				    pos, len);
 			if (len != 5)
 				break;
 			parse->tie = pos;
@@ -904,6 +1096,10 @@
 		return WPA_KEY_MGMT_FT_IEEE8021X;
 	if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
 		return WPA_KEY_MGMT_FT_PSK;
+#ifdef CONFIG_SHA384
+	if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384)
+		return WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+#endif /* CONFIG_SHA384 */
 #endif /* CONFIG_IEEE80211R */
 #ifdef CONFIG_IEEE80211W
 	if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
@@ -1279,24 +1475,36 @@
 int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
 		      const u8 *ssid, size_t ssid_len,
 		      const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
-		      const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
+		      const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
+		      int use_sha384)
 {
 	u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
 	       FT_R0KH_ID_MAX_LEN + ETH_ALEN];
-	u8 *pos, r0_key_data[48], hash[32];
+	u8 *pos, r0_key_data[64], hash[48];
 	const u8 *addr[2];
 	size_t len[2];
+	size_t q = use_sha384 ? 48 : 32;
+	size_t r0_key_data_len = q + 16;
 
 	/*
 	 * R0-Key-Data = KDF-384(XXKey, "FT-R0",
 	 *                       SSIDlength || SSID || MDID || R0KHlength ||
 	 *                       R0KH-ID || S0KH-ID)
-	 * XXKey is either the second 256 bits of MSK or PSK.
-	 * PMK-R0 = L(R0-Key-Data, 0, 256)
-	 * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
+	 * XXKey is either the second 256 bits of MSK or PSK; or the first
+	 * 384 bits of MSK for FT-EAP-SHA384.
+	 * PMK-R0 = L(R0-Key-Data, 0, Q)
+	 * PMK-R0Name-Salt = L(R0-Key-Data, Q, 128)
+	 * Q = 384 for FT-EAP-SHA384; otherwise, 256
 	 */
 	if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
 		return -1;
+	wpa_printf(MSG_DEBUG, "FT: Derive PMK-R0 using KDF-%s",
+		   use_sha384 ? "SHA384" : "SHA256");
+	wpa_hexdump_key(MSG_DEBUG, "FT: XXKey", xxkey, xxkey_len);
+	wpa_hexdump_ascii(MSG_DEBUG, "FT: SSID", ssid, ssid_len);
+	wpa_hexdump(MSG_DEBUG, "FT: MDID", mdid, MOBILITY_DOMAIN_ID_LEN);
+	wpa_hexdump_ascii(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len);
+	wpa_printf(MSG_DEBUG, "FT: S0KH-ID: " MACSTR, MAC2STR(s0kh_id));
 	pos = buf;
 	*pos++ = ssid_len;
 	os_memcpy(pos, ssid, ssid_len);
@@ -1309,22 +1517,50 @@
 	os_memcpy(pos, s0kh_id, ETH_ALEN);
 	pos += ETH_ALEN;
 
-	if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
-		       r0_key_data, sizeof(r0_key_data)) < 0)
-		return -1;
-	os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
+#ifdef CONFIG_SHA384
+	if (use_sha384) {
+		if (xxkey_len != SHA384_MAC_LEN) {
+			wpa_printf(MSG_ERROR,
+				   "FT: Unexpected XXKey length %d (expected %d)",
+				   (int) xxkey_len, SHA384_MAC_LEN);
+			return -1;
+		}
+		if (sha384_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
+			       r0_key_data, r0_key_data_len) < 0)
+			return -1;
+	}
+#endif /* CONFIG_SHA384 */
+	if (!use_sha384) {
+		if (xxkey_len != PMK_LEN) {
+			wpa_printf(MSG_ERROR,
+				   "FT: Unexpected XXKey length %d (expected %d)",
+				   (int) xxkey_len, PMK_LEN);
+			return -1;
+		}
+		if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
+			       r0_key_data, r0_key_data_len) < 0)
+			return -1;
+	}
+	os_memcpy(pmk_r0, r0_key_data, q);
+	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, q);
+	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0Name-Salt", &r0_key_data[q], 16);
 
 	/*
-	 * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
+	 * PMKR0Name = Truncate-128(Hash("FT-R0N" || PMK-R0Name-Salt)
 	 */
 	addr[0] = (const u8 *) "FT-R0N";
 	len[0] = 6;
-	addr[1] = r0_key_data + PMK_LEN;
+	addr[1] = &r0_key_data[q];
 	len[1] = 16;
 
-	if (sha256_vector(2, addr, len, hash) < 0)
+#ifdef CONFIG_SHA384
+	if (use_sha384 && sha384_vector(2, addr, len, hash) < 0)
+		return -1;
+#endif /* CONFIG_SHA384 */
+	if (!use_sha384 && sha256_vector(2, addr, len, hash) < 0)
 		return -1;
 	os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
+	os_memset(r0_key_data, 0, sizeof(r0_key_data));
 	return 0;
 }
 
@@ -1335,15 +1571,15 @@
  * IEEE Std 802.11r-2008 - 8.5.1.5.4
  */
 int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
-			   const u8 *s1kh_id, u8 *pmk_r1_name)
+			   const u8 *s1kh_id, u8 *pmk_r1_name, int use_sha384)
 {
-	u8 hash[32];
+	u8 hash[48];
 	const u8 *addr[4];
 	size_t len[4];
 
 	/*
-	 * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
-	 *                                  R1KH-ID || S1KH-ID))
+	 * PMKR1Name = Truncate-128(Hash("FT-R1N" || PMKR0Name ||
+	 *                               R1KH-ID || S1KH-ID))
 	 */
 	addr[0] = (const u8 *) "FT-R1N";
 	len[0] = 6;
@@ -1354,7 +1590,11 @@
 	addr[3] = s1kh_id;
 	len[3] = ETH_ALEN;
 
-	if (sha256_vector(4, addr, len, hash) < 0)
+#ifdef CONFIG_SHA384
+	if (use_sha384 && sha384_vector(4, addr, len, hash) < 0)
+		return -1;
+#endif /* CONFIG_SHA384 */
+	if (!use_sha384 && sha256_vector(4, addr, len, hash) < 0)
 		return -1;
 	os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
 	return 0;
@@ -1366,7 +1606,8 @@
  *
  * IEEE Std 802.11r-2008 - 8.5.1.5.4
  */
-int wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
+int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
+		      const u8 *pmk_r0_name,
 		      const u8 *r1kh_id, const u8 *s1kh_id,
 		      u8 *pmk_r1, u8 *pmk_r1_name)
 {
@@ -1374,18 +1615,37 @@
 	u8 *pos;
 
 	/* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
+	wpa_printf(MSG_DEBUG, "FT: Derive PMK-R1 using KDF-%s",
+		   pmk_r0_len == SHA384_MAC_LEN ? "SHA384" : "SHA256");
+	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len);
+	wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN);
+	wpa_printf(MSG_DEBUG, "FT: S1KH-ID: " MACSTR, MAC2STR(s1kh_id));
 	pos = buf;
 	os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
 	pos += FT_R1KH_ID_LEN;
 	os_memcpy(pos, s1kh_id, ETH_ALEN);
 	pos += ETH_ALEN;
 
-	if (sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf,
-		       pmk_r1, PMK_LEN) < 0)
+#ifdef CONFIG_SHA384
+	if (pmk_r0_len == SHA384_MAC_LEN &&
+	    sha384_prf(pmk_r0, pmk_r0_len, "FT-R1",
+		       buf, pos - buf, pmk_r1, pmk_r0_len) < 0)
 		return -1;
+#endif /* CONFIG_SHA384 */
+	if (pmk_r0_len == PMK_LEN &&
+	    sha256_prf(pmk_r0, pmk_r0_len, "FT-R1",
+		       buf, pos - buf, pmk_r1, pmk_r0_len) < 0)
+		return -1;
+	if (pmk_r0_len != SHA384_MAC_LEN && pmk_r0_len != PMK_LEN) {
+		wpa_printf(MSG_ERROR, "FT: Unexpected PMK-R0 length %d",
+			   (int) pmk_r0_len);
+		return -1;
+	}
+	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r0_len);
 
 	return wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id,
-				      pmk_r1_name);
+				      pmk_r1_name,
+				      pmk_r0_len == SHA384_MAC_LEN);
 }
 
 
@@ -1394,7 +1654,8 @@
  *
  * IEEE Std 802.11r-2008 - 8.5.1.5.5
  */
-int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
+int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len,
+		      const u8 *snonce, const u8 *anonce,
 		      const u8 *sta_addr, const u8 *bssid,
 		      const u8 *pmk_r1_name,
 		      struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
@@ -1403,13 +1664,21 @@
 	u8 *pos, hash[32];
 	const u8 *addr[6];
 	size_t len[6];
-	u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
-	size_t ptk_len;
+	u8 tmp[2 * WPA_KCK_MAX_LEN + 2 * WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
+	size_t ptk_len, offset;
+	int use_sha384 = wpa_key_mgmt_sha384(akmp);
 
 	/*
 	 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
 	 *                  BSSID || STA-ADDR)
 	 */
+	wpa_printf(MSG_DEBUG, "FT: Derive PTK using KDF-%s",
+		   use_sha384 ? "SHA384" : "SHA256");
+	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len);
+	wpa_hexdump(MSG_DEBUG, "FT: SNonce", snonce, WPA_NONCE_LEN);
+	wpa_hexdump(MSG_DEBUG, "FT: ANonce", anonce, WPA_NONCE_LEN);
+	wpa_printf(MSG_DEBUG, "FT: BSSID=" MACSTR " STA-ADDR=" MACSTR,
+		   MAC2STR(bssid), MAC2STR(sta_addr));
 	pos = buf;
 	os_memcpy(pos, snonce, WPA_NONCE_LEN);
 	pos += WPA_NONCE_LEN;
@@ -1421,18 +1690,44 @@
 	pos += ETH_ALEN;
 
 	ptk->kck_len = wpa_kck_len(akmp, PMK_LEN);
+	ptk->kck2_len = wpa_kck2_len(akmp);
 	ptk->kek_len = wpa_kek_len(akmp, PMK_LEN);
+	ptk->kek2_len = wpa_kek2_len(akmp);
 	ptk->tk_len = wpa_cipher_key_len(cipher);
-	ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
+	ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len +
+		ptk->kck2_len + ptk->kek2_len;
 
-	if (sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf,
-		       tmp, ptk_len) < 0)
-		return -1;
+#ifdef CONFIG_SHA384
+	if (use_sha384) {
+		if (pmk_r1_len != SHA384_MAC_LEN) {
+			wpa_printf(MSG_ERROR,
+				   "FT: Unexpected PMK-R1 length %d (expected %d)",
+				   (int) pmk_r1_len, SHA384_MAC_LEN);
+			return -1;
+		}
+		if (sha384_prf(pmk_r1, pmk_r1_len, "FT-PTK",
+			       buf, pos - buf, tmp, ptk_len) < 0)
+			return -1;
+	}
+#endif /* CONFIG_SHA384 */
+	if (!use_sha384) {
+		if (pmk_r1_len != PMK_LEN) {
+			wpa_printf(MSG_ERROR,
+				   "FT: Unexpected PMK-R1 length %d (expected %d)",
+				   (int) pmk_r1_len, PMK_LEN);
+			return -1;
+		}
+		if (sha256_prf(pmk_r1, pmk_r1_len, "FT-PTK",
+			       buf, pos - buf, tmp, ptk_len) < 0)
+			return -1;
+	}
+	wpa_hexdump_key(MSG_DEBUG, "FT: PTK", tmp, ptk_len);
 
 	/*
 	 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
 	 *                                ANonce || BSSID || STA-ADDR))
 	 */
+	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
 	addr[0] = pmk_r1_name;
 	len[0] = WPA_PMK_NAME_LEN;
 	addr[1] = (const u8 *) "FT-PTKN";
@@ -1451,11 +1746,23 @@
 	os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
 
 	os_memcpy(ptk->kck, tmp, ptk->kck_len);
-	os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
-	os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
+	offset = ptk->kck_len;
+	os_memcpy(ptk->kek, tmp + offset, ptk->kek_len);
+	offset += ptk->kek_len;
+	os_memcpy(ptk->tk, tmp + offset, ptk->tk_len);
+	offset += ptk->tk_len;
+	os_memcpy(ptk->kck2, tmp + offset, ptk->kck2_len);
+	offset = ptk->kck2_len;
+	os_memcpy(ptk->kek2, tmp + offset, ptk->kek2_len);
 
 	wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
 	wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
+	if (ptk->kck2_len)
+		wpa_hexdump_key(MSG_DEBUG, "FT: KCK2",
+				ptk->kck2, ptk->kck2_len);
+	if (ptk->kek2_len)
+		wpa_hexdump_key(MSG_DEBUG, "FT: KEK2",
+				ptk->kek2, ptk->kek2_len);
 	wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
 	wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
 
@@ -1483,7 +1790,7 @@
  * See rsn_pmkid_suite_b()
  * AKM: 00-0F-AC:12
  * See rsn_pmkid_suite_b_192()
- * AKM: 00-0F-AC:15, 00-0F-AC:17
+ * AKM: 00-0F-AC:13, 00-0F-AC:15, 00-0F-AC:17
  * PMKID = Truncate-128(HMAC-SHA-384(PMK, "PMK Name" || AA || SPA))
  * Otherwise:
  * PMKID = Truncate-128(HMAC-SHA-1(PMK, "PMK Name" || AA || SPA))
@@ -1501,11 +1808,11 @@
 	addr[2] = spa;
 
 	if (0) {
-#ifdef CONFIG_FILS
+#if defined(CONFIG_FILS) || defined(CONFIG_SHA384)
 	} else if (wpa_key_mgmt_sha384(akmp)) {
 		wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-384");
 		hmac_sha384_vector(pmk, pmk_len, 3, addr, len, hash);
-#endif /* CONFIG_FILS */
+#endif /* CONFIG_FILS || CONFIG_SHA384 */
 #if defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS)
 	} else if (wpa_key_mgmt_sha256(akmp)) {
 		wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-256");
@@ -1656,6 +1963,8 @@
 #ifdef CONFIG_IEEE80211R
 	case WPA_KEY_MGMT_FT_IEEE8021X:
 		return "FT-EAP";
+	case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+		return "FT-EAP-SHA384";
 	case WPA_KEY_MGMT_FT_PSK:
 		return "FT-PSK";
 #endif /* CONFIG_IEEE80211R */
@@ -1697,6 +2006,8 @@
 
 u32 wpa_akm_to_suite(int akm)
 {
+	if (akm & WPA_KEY_MGMT_FT_IEEE8021X_SHA384)
+		return RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384;
 	if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
 		return RSN_AUTH_KEY_MGMT_FT_802_1X;
 	if (akm & WPA_KEY_MGMT_FT_PSK)
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 3b8c1fb..6261744 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -1,6 +1,6 @@
 /*
  * WPA definitions shared between hostapd and wpa_supplicant
- * Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -62,8 +62,7 @@
 #define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
 #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
 #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192 RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
-#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \
-RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
+#define RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384 RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
 #define RSN_AUTH_KEY_MGMT_FILS_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 14)
 #define RSN_AUTH_KEY_MGMT_FILS_SHA384 RSN_SELECTOR(0x00, 0x0f, 0xac, 15)
 #define RSN_AUTH_KEY_MGMT_FT_FILS_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 16)
@@ -210,9 +209,13 @@
 	u8 kck[WPA_KCK_MAX_LEN]; /* EAPOL-Key Key Confirmation Key (KCK) */
 	u8 kek[WPA_KEK_MAX_LEN]; /* EAPOL-Key Key Encryption Key (KEK) */
 	u8 tk[WPA_TK_MAX_LEN]; /* Temporal Key (TK) */
+	u8 kck2[WPA_KCK_MAX_LEN]; /* FT reasoc Key Confirmation Key (KCK2) */
+	u8 kek2[WPA_KEK_MAX_LEN]; /* FT reassoc Key Encryption Key (KEK2) */
 	size_t kck_len;
 	size_t kek_len;
 	size_t tk_len;
+	size_t kck2_len;
+	size_t kek2_len;
 	int installed; /* 1 if key has already been installed to driver */
 };
 
@@ -311,6 +314,14 @@
 	/* followed by optional parameters */
 } STRUCT_PACKED;
 
+struct rsn_ftie_sha384 {
+	u8 mic_control[2];
+	u8 mic[24];
+	u8 anonce[WPA_NONCE_LEN];
+	u8 snonce[WPA_NONCE_LEN];
+	/* followed by optional parameters */
+} STRUCT_PACKED;
+
 #define FTIE_SUBELEM_R1KH_ID 1
 #define FTIE_SUBELEM_GTK 2
 #define FTIE_SUBELEM_R0KH_ID 3
@@ -361,14 +372,16 @@
 int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
 		      const u8 *ssid, size_t ssid_len,
 		      const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
-		      const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name);
+		      const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
+		      int use_sha384);
 int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
-			   const u8 *s1kh_id, u8 *pmk_r1_name);
-int wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
+			   const u8 *s1kh_id, u8 *pmk_r1_name, int use_sha384);
+int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
+		      const u8 *pmk_r0_name,
 		      const u8 *r1kh_id, const u8 *s1kh_id,
 		      u8 *pmk_r1, u8 *pmk_r1_name);
-int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
-		      const u8 *sta_addr, const u8 *bssid,
+int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len, const u8 *snonce,
+		      const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
 		      const u8 *pmk_r1_name,
 		      struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher);
 #endif /* CONFIG_IEEE80211R */
@@ -444,7 +457,8 @@
 	int pairwise_cipher;
 };
 
-int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse);
+int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
+		     int use_sha384);
 
 int wpa_cipher_key_len(int cipher);
 int wpa_cipher_rsc_len(int cipher);
@@ -461,6 +475,9 @@
 int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim);
 int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise);
 unsigned int wpa_mic_len(int akmp, size_t pmk_len);
+int wpa_use_akm_defined(int akmp);
+int wpa_use_cmac(int akmp);
+int wpa_use_aes_key_wrap(int akmp);
 int fils_domain_name_hash(const char *domain, u8 *hash);
 
 #endif /* WPA_COMMON_H */
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index c59bc60..4eb7356 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -50,10 +50,19 @@
 #define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
 /** EAP status */
 #define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS "
+/** Retransmit the previous request packet */
+#define WPA_EVENT_EAP_RETRANSMIT "CTRL-EVENT-EAP-RETRANSMIT "
+#define WPA_EVENT_EAP_RETRANSMIT2 "CTRL-EVENT-EAP-RETRANSMIT2 "
 /** EAP authentication completed successfully */
 #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
+#define WPA_EVENT_EAP_SUCCESS2 "CTRL-EVENT-EAP-SUCCESS2 "
 /** EAP authentication failed (EAP-Failure received) */
 #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
+#define WPA_EVENT_EAP_FAILURE2 "CTRL-EVENT-EAP-FAILURE2 "
+/** EAP authentication failed due to no response received */
+#define WPA_EVENT_EAP_TIMEOUT_FAILURE "CTRL-EVENT-EAP-TIMEOUT-FAILURE "
+#define WPA_EVENT_EAP_TIMEOUT_FAILURE2 "CTRL-EVENT-EAP-TIMEOUT-FAILURE2 "
+#define WPA_EVENT_EAP_ERROR_CODE "EAP-ERROR-CODE "
 /** Network block temporarily disabled (e.g., due to authentication failure) */
 #define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED "
 /** Temporarily disabled network block re-enabled */
@@ -80,6 +89,9 @@
 #define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
 /** Channel switch (followed by freq=<MHz> and other channel parameters) */
 #define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH "
+/** SAE authentication failed due to unknown password identifier */
+#define WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER \
+	"CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER "
 
 /** IP subnet status change notification
  *
@@ -145,12 +157,15 @@
 
 /* DPP events */
 #define DPP_EVENT_AUTH_SUCCESS "DPP-AUTH-SUCCESS "
+#define DPP_EVENT_AUTH_INIT_FAILED "DPP-AUTH-INIT-FAILED "
 #define DPP_EVENT_NOT_COMPATIBLE "DPP-NOT-COMPATIBLE "
 #define DPP_EVENT_RESPONSE_PENDING "DPP-RESPONSE-PENDING "
 #define DPP_EVENT_SCAN_PEER_QR_CODE "DPP-SCAN-PEER-QR-CODE "
+#define DPP_EVENT_AUTH_DIRECTION "DPP-AUTH-DIRECTION "
 #define DPP_EVENT_CONF_RECEIVED "DPP-CONF-RECEIVED "
 #define DPP_EVENT_CONF_SENT "DPP-CONF-SENT "
 #define DPP_EVENT_CONF_FAILED "DPP-CONF-FAILED "
+#define DPP_EVENT_CONFOBJ_AKM "DPP-CONFOBJ-AKM "
 #define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
 #define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
 #define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
@@ -159,6 +174,13 @@
 #define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY "
 #define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR "
 #define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID "
+#define DPP_EVENT_RX "DPP-RX "
+#define DPP_EVENT_TX "DPP-TX "
+#define DPP_EVENT_TX_STATUS "DPP-TX-STATUS "
+#define DPP_EVENT_FAIL "DPP-FAIL "
+#define DPP_EVENT_PKEX_T_LIMIT "DPP-PKEX-T-LIMIT "
+#define DPP_EVENT_INTRO "DPP-INTRO "
+#define DPP_EVENT_CONF_REQ_RX "DPP-CONF-REQ-RX "
 
 /* MESH events */
 #define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
@@ -255,6 +277,7 @@
 
 #define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION "
 #define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE "
+#define HS20_T_C_ACCEPTANCE "HS20-T-C-ACCEPTANCE "
 
 #define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START "
 #define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT "
@@ -278,6 +301,9 @@
 #define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA "
 #define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA "
 
+#define HS20_T_C_FILTERING_ADD "HS20-T-C-FILTERING-ADD "
+#define HS20_T_C_FILTERING_REMOVE "HS20-T-C-FILTERING-REMOVE "
+
 #define AP_EVENT_ENABLED "AP-ENABLED "
 #define AP_EVENT_DISABLED "AP-DISABLED "
 
@@ -323,6 +349,19 @@
  */
 #define FILS_HLP_RX "FILS-HLP-RX "
 
+/* Event to indicate Probe Request frame;
+ * parameters: sa=<STA MAC address> signal=<signal> */
+#define RX_PROBE_REQUEST "RX-PROBE-REQUEST "
+
+/* Event to indicate station's HT/VHT operation mode change information */
+#define STA_OPMODE_MAX_BW_CHANGED "STA-OPMODE-MAX-BW-CHANGED "
+#define STA_OPMODE_SMPS_MODE_CHANGED "STA-OPMODE-SMPS-MODE-CHANGED "
+#define STA_OPMODE_N_SS_CHANGED "STA-OPMODE-N_SS-CHANGED "
+
+/* New interface addition or removal for 4addr WDS SDA */
+#define WDS_STA_INTERFACE_ADDED "WDS-STA-INTERFACE-ADDED "
+#define WDS_STA_INTERFACE_REMOVED "WDS-STA-INTERFACE-REMOVED "
+
 /* BSS command information masks */
 
 #define WPA_BSS_MASK_ALL		0xFFFDFFFF
@@ -424,7 +463,7 @@
  *
  * This function is used to send commands to wpa_supplicant/hostapd. Received
  * response will be written to reply and reply_len is set to the actual length
- * of the reply. This function will block for up to two seconds while waiting
+ * of the reply. This function will block for up to 10 seconds while waiting
  * for the reply. If unsolicited messages are received, the blocking time may
  * be longer.
  *