[wpa_supplicant] Cumulative patch from commit ac1e3a7f0
Bug: 217966931
Test: Verify Passpoint ANQP functionality and Passpoint association
Test: Connect to Passpoint, Open, WPA2, WPA3 networks and run traffic
Test: Regression test b/218404053 (Bug: TBD)
BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from Open source
ac1e3a7f0 Add QCA vendor MCC channel quota command and event
1d1e3184b Whitespace/coding style cleanup for QCA vendor attribute definitions
1646883f4 Vendor command to configure rate mask
2faaa193f Rename moderate latency level to XR latency level in vendor attributes
f9905f8d9 nl80211: Clear frequency information on leaving mesh
1f26a0a34 DPP: Use a 120 second timeout for GAS query
07e26b292 GAS server: Increase query timeout to 60 seconds for DPP
a6d157b6f DPP: Start a listen operation for GAS server if needed
da65e7136 nl80211: Add a handler for NL80211_CMD_FRAME_WAIT_CANCEL events
9aaf3e1d1 P2P: Update GO operating frequency after interface setup is completed
033ad6ffa DPP: Allow Configurator parameters to be provided during config exchange
d4961a775 GAS server: Asynchronous request handler comeback time indication
9a90aab12 DPP: Store Enrollee config request information
6751fb060 DPP: Make dpp_netrole_str() non-static
34575ad72 EAP-pwd: Fix the prefix in a debug message
e07000e74 nl80211: Partial support for radio_disable
33cb47cf0 DPP: Fix connection result reporting when using TCP
1822bd378 DPP: Testing capability for invalid Protocol Version in Network Intro
d7be74933 DPP3: PKEX over TCP
bdcccbc27 DPP: Change PKEX version configuration design
9d3f347a2 DPP3: Add PKEX initiator retries and fallback from v2 to v1 for hostapd
3f67ab587 DPP: Handle TX status events for broadcast DPP messages
802136299 DPP3: Start with PKEXv2 and fall back to v1
f32f99df1 P2P: Send response frame on channel where the request is received
b678a3aa3 Extend QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING
fc4bc342e Replace "blacklist" with "denylist" in vendor interface definition
bc9fd8adc Replace "whitelist" with "allowlist" in vendor interface definition
ffe80cb8e wpa_supplicant: ap: Update comment
c76545033 The main branch is now used for v2.11 development
cff80b4f7 Preparations for v2.10 release
7a57eb315 Update copyright notices for the new year 2022
9b14aed90 crypto: Remove unused crypto_ec_point_solve_y_coord()
8c502336d EAP-pwd: Derive the y coordinate for PWE with own implementation
6c380f4c8 SAE: Derive the y coordinate for PWE with own implementation
8ebd8aacc SAE: Move sqrt() implementation into a helper function
41c7f3f20 Defined a driver interface for periodic TSF sync feature
5758d0929 Add a QCA vendor attribute to indicate ACS over EHT
7ffcbd08c Clear roam/BSS TM in progress flags for additional cases
16b5ea9e9 Reject authentication start during BSS TM requests
af6d4031d D-Bus: Fix build without CONFIG_INTERWORKING
58bbcfa31 OpenSSL: Update security level drop for TLS 1.0/1.1 with OpenSSL 3.0
682fce579 OpenSSL: Fix compressed form encoding for subjectPublicKey with 3.0
ff2eccbdf OpenSSL: Load legacy provider when needed for OpenSSL 3.0
ddcdd6286 OpenSSL: Clean up EVP_PKEY_get{0,1}_EC_KEY() use
384aa245e OpenSSL: Speed up crypto_ec_point_compute_y_sqr()
b26f5c0fe DPP: Remove dpp-listen radio work when stopping
3f8c83a65 SAE: Make sure BSS entry is available to determine RSNXE information
43f600a1f Add new vendor attributes to avoid coex unsafe frequencies
cab51021c DPP3: Update version capability indication for hostapd
bc24a8a09 Update supported channel width set (HT40) after channel switch
ff7e403f0 Fix channel switch wrapper when switching from HT to VHT/HE
5606ede12 Update ieee80211ac when channel switching
e6db1bc5d mesh: Make forwarding configurable
5ef9277d0 ACS/DFS: Support min_tx_power configuration
5530688b9 MBO: Fix the allowed range of mbo_assoc_disallow values
c8e4283f9 D-Bus: Interworking network selection
b44e19967 D-Bus: Interworking/Hotspot 2.0 credential operations
4262e6ca4 Move credential removal operations into helper functions
e232d9777 HS 2.0: Crypto engine support for creds
97607de5e D-Bus: Capture group ifname before switching to global P2P instance
36973aac2 SME: No need for OBSS scan if HT40 is disabled
7db757aac Revert "Extract BSS coex 40 MHz check into a separate function"
e480321f8 Revert "STA OBSS: Add check for overlapping BSSs"
b57273d06 DPP2: PKEXv2 core protocol changes
b21b31014 DPP: Testing functionality to omit Protocol Version from Peer Discovery
341e7cd66 DPP3: Verify version match during Network Introduction
f26fd5ee6 DPP3: Use Connector version instead of current version in Peer Discovery
0cfb72689 DPP3: Add version member to Connector
77ddd38b6 DPP3: Add build option for version 3 functionality
14ab4a816 Reject ap_vendor_elements if its length is odd
2c2bfebca Fix bool type values for setband
7dc7b8814 P2P: Remove 6 GHz channels from full scan if 6 GHz not enabled for P2P
147932add Add a QCA vendor attribute to indicate puncture pattern in ACS
0b853303a Update AKMP, cipher, PMF for driver-based SME while roaming
c8b94bc7b mesh: Enable 160 MHz bandwidth support for 6 GHz in IEEE 802.11s mesh
ab0af709d mesh: Enable MFP by default for 6 GHz 11s mesh
d10a01e22 mesh: Enable 80 MHz support for 11s mesh in 6 GHz
d6c5feb8c mesh: Change channel to frequency based lookup for starting mesh
b16b88acd RNR: Do not allow FILS Discovery and unsolicited Probe Response simultaneously
15f099ec7 RNR: Allow Probe Response frame for a colocated 6 GHz AP
f17f7ca4e RNR: Update Beacon frames for 6 GHz colocation
01efcc292 RNR: Addition in Beacon, Probe Response, and FILS Discovery frames
0c9457ee2 RNR: Additions for a 6 GHz AP
b2bbedcb2 RNR: Add co-located BSSes
a7c152d6b RNR: Add data from neighbor database
847f76760 RNR: Add configuration option
3db24e4ee RNR: Define element format
b389d88a7 Share a common error path for SET_NEIGHBOR control interface command
1b8eb3975 RNR: Add bss_parameters to the neighbor_db
9d0948ecc RNR: Short SSID assignment
8d881d942 Update AKMP and proto for driver-based SME while roaming
f969bd22d Add QCA vendor attribute to configure ARP/NS offload feature
8f4d7e8f0 OpenSSL: Fix build with OpenSSL 1.0.2
2086ae46b DPP: Replace dpp_bootstrap_key_der() with crypto_ec_key_get_subject_public_key()
e9f8f81a8 DPP: Use ECDH from crypto.h
4aed5668b OpenSSL: Clear the correct flag in crypto_ec_key_get_ecprivate_key()
bf161b660 Ignore CONFIG_WIFI_DISPLAY without CONFIG_P2P
b306a92df Fix compiler error on CONFIG_AP without CONFIG_P2P builds
726eda65f wolfSSL: Fix a link error when WPS NFC is disabled
b8402ab08 DPP: Use crypto_ec_key_get_subject_public_key() when possible
d51939f2c DPP: Move CSR routines to use crypto.h
d56352b55 DPP: Move dpp_pkcs7_certs() into crypto_pkcs7_get_certificates()
b89176fa6 DPP: Move debug print of EC key to crypto.h
87f2fb886 DPP: Remove direct call to OpenSSL in dpp_test_gen_invalid_key()
c88b7fcae DPP: Add crypto_ec_key_cmp() in crypto.h and use it
984faf963 DPP: Use crypto_ec_key_group() to compare EC key's group
f5334f9b5 DPP: Use crypto API for reconfig part
eac41656e DPP: Update connector signing to use crypto.h
da63d3099 DPP: Remove unused EVP_PKEY_CTX variable
4767de3a4 DPP: Use crypto.h for authentication computation
0d1d74107 DPP: Update PKEX part to use crypto.h API
50708770f DPP: Use crypto_ec_key_parse_priv() when possible
e294a73d0 DPP: Use crypto_ec_key_parse_pub() in dpp_get_subject_public_key()
9c1632908 DPP: Move dpp_set_pubkey_point_group() to crypto.h
e84b143e1 OpenSSL: Add Brainpool curves to crypto_ec_key_group()
c6f2103ca DPP: Replace dpp_get_pubkey_point() with crypto_ec_key_get_pubkey_point()
2d5772e69 DPP: Factorize conversion to ASN.1 ECPrivateKey
63bf3d25a OpenSSL: Mark crypto_ec_key_gen() key compressed
86cde01cb DPP: Move dpp_gen_keypair() to crypto
0517948d7 DPP: Replace EVP_PKEY by struct crypto_ec_key
cd0c1d256 OpenSSL: Use EVP_PKEY as struct crypto_ec_key
15275c53d Complete documentation in crypto.h
cb285e80c SAE: Fix sm->cur_pmksa assignment
aa5c4f932 Add QCA vendor attribute to configure priority of vendor scan
aca4d4963 Fix handling of complex configuration lines with mixed "" and #
0ae677c7b eloop: Extend overflow check in eloop_register_timeout() to cover usec
979f19716 WNM: Allow specifying dialog token for BSS transition request
3f6c02f29 Use pkg-config for libpcsclite linkage flags
e797959b8 systemd: Order wpa_supplicant after dbus
95bf9fc93 Remove extra slash from BIN/INC/LIBDIR defaults
5a4ae6e3a Replace "native" with a more specific description
2fb33ce4b wpa_supplicant: hostapd: Remove man-in-the-middle
2e122945f DPP2: Do not try to remove Controller TCP connection twice on error
5bac420e5 DPP2: Clean up Controller on hostapd interface removal
d8b3d0815 macsec_qca: Support macsec secy id getting from driver
08bdf4f90 proxyarp: Fix compilation with Hotspot 2.0 disabled
b0f457b61 SAE: Do not expire the current PMKSA cache entry
f332f6951 wpa_supplicant: Try all drivers by default
4775a5f82 Add support to reconfigure or flush PMKSA cache on interface enable
6f634b003 PMKSA: Make sure reauth time is not greater than expiration time
973f3e244 Fix hostapd segfault on WPS_CONFIG control interface command to non-WPS AP
9ef8491d9 Add TWT attribute to configure TWT related parameters
321dc403e Replace "dummy" with "stub" in crypto/random
95e140e20 Replace "dummy" with "stub" in NDIS driver interface
c53fa9225 Replace "dummy" with "stub" in EAP-TEAP testing
575dc1f3b Replace "dummy" with "stub" in preauth_test
ed5e1b722 Replace "dummy" with "stub" in comments/documentation
3955d2af7 Replace "dummy" with "stub" in wps_testing_dummy_cred
77dd71243 Replace "dummy" with "stub" in Authenticator group keys
fb1bae2a7 Replace "dummy" with "stub" in SAE
e69ea242a hostap: Remove unused driver enum values with "master" in them
7b50f2f04 Replace "sanity" with "validity"
891bb1305 P2P: Enforce SAE-H2E for P2P GO in 6 GHz
afcadbbf4 wpa_cli: Add support for SCS, MSCS, and DSCP commands
bcaa1ea08 HE: Disable HE in hostapd_set_freq_params() if driver does not support
fe1d743a1 Add QCA vendor attributes to indicate 320 MHz spectral scan capabilities
2b3e64a0f Update ciphers to address GTK renewal failures while roaming
9cf4bb0ef Vendor command to configure/trigger the roam events
dd3a2960a Add TWT vendor attribute to configure announce timeout value
afa0b9b6c P2P: Make p2p_check_pref_chan_no_recv() easier for static analyzers
857c4dfa8 Make get_mode() easier for static analyzers
9651deba5 Support vendor element configuration for AP mode from wpa_supplicant
d144b7f34 DSCP: Add support to send DSCP Policy Query frame
c903257fb DSCP: Parse WFA Capabilities element in (Re)Association Response frame
a4aae9f9b DSCP: Indicate DSCP Policy support in (Re)Association Request frame
d57456c1f DSCP: Allow DSCP Policy Response Action frame to be sent
2033e318e DSCP: Parsing and processing of DSCP Policy Request frames
fe2a44485 DSCP: DSCP policy capability configuration
8471d940e Move pmf_in_use() into a more generic file
41ec97cd0 HE: Use a random BSS Color if not defined in the config file
1518638b7 QCA vendor command to configure the parameters for monitor mode
8f7b2c898 Add attributes to support MBSSID multi groups notifications
a75fdcdcd Extend the roam reason codes in QCA vendor attribute
9ff0c8af5 Correct the documentation in enum qca_roam_reason
ce267f4da P2P: DFS offload for the autonomous GO
6ba665c5c Reserve QCA vendor sub command id 201
51d73d991 Add QCA vendor interface to configure background scan parameters
61c075761 EDMG: Validate pri channel lookup result before using it
a95144cf3 Add frequency to operating class determination for 5 GHz channel 144
e5173e8b1 P2P: Enable multiple channel widths for P2P in 6 GHz band
f725254cc P2P: Enhance determination of secondary offset to support 6 GHz channels
575a8e6ca P2P: Clone 6 GHz related parameters to new group interface config
f18433760 Add TWT attribute to send Responder PM Mode value to userspace
11a342775 Add time slice duty cycle attribute into QCA vendor command
d408e3d19 Update QCA mDNS Offload vendor command
2341585c3 ACS: Fix channel 100 frequency
ed369613f P2P: Align p2p_buf_add_pref_channel_list() prototype with definition
75a6d44a4 hostapd: Allow HT40 on 5 GHz channels 173 and 177
7dd2e2369 hostapd: Always allow HE AP with a 20 MHz channel width
9f2217c51 P2P: Consider p2p_no_go_freq for GO preferred frequency
882c53be5 P2P: Avoid integer overflow in channel
a58f7e61c Add QCA vendor interface to configure allowed bands for roaming
be81bbdc3 doc: Fix grammar in wpa_supplicant overview
362d9a49d utils: FreeBSD supports fdatasync(2)
9bd943410 nl80211: Fix send_mlme to use monitor interface only for AP interface
f02ac5140 HE: Option to disable HE ER SU in HE operation in AP mode
63f043f4f Generalize the function name as it is not dealing with only TX & RX params
3cdc6d381 mesh: Show peer connected time in the wpa_cli STA cmd output for Mesh mode
eddcd2753 Fix some compiler warnings on 32 bit platform
4c80937c7 nl80211: Reduce the number of nlctrl name resolution calls
cce33c7e7 openssl: Support private_key blob in PEM encoded PKCS#8 format
0030590fb Generate an event when a network is added or removed
f23861061 Add a --conf option to eapol_test.py
99c1789ab PASN: Fix ASAN error in ptksa_cache_add()
e2e9adc3d openssl: Disable padding after initializing the cipher suite
d265dd2d9 openssl: Remove deprecated functions from des_encrypt()
46b60299a wpa_supplicant: src: Replace Sane with Valid.
12388313a RADIUS client: Fix void-pointer-to-enum-cast warning
e433d06dd Allow MSCS support to be disabled for testing purposes
025f8ab52 SCS: Processing of SCS Response frames
b4e01ae92 Allow SCS supported to be disabled for testing purposes
c005283c4 SCS: Sending of SCS Request frames
445dbe2cd P2P: Do not stop Listen state if it is moving to correct channel
e99aaf706 Add QCA vendor attribute for TWT termination due to power save exit
a147951ee Add QCA vendor attribute indicating the spectral scan bandwidth
51f89565f Add QCA vendor interface to fetch thermal statistics from the driver
24774dcc2 P2P: Require PMF for P2P GO in the 6 GHz band
49442194c SAE: Derive H2E PT while reconnecting to same SSID also
ac79ed499 HE: Obtain correct AP mode capabilities for hw_mode with 6 GHz support
dfabf1e5c QCA vendor command for mDNS offload
1071f7539 DPP2: Fix channel 6 inclusion for chirping with non-2 GHz interfaces
84b3de809 TDLS: Support TDLS operations in HE mode for 6 GHz
1990ee7ee QCA vendor attributes to configure BTWT and Rx control frame to MultiBSS
f5f2985a2 Update TWT attribute to send TSF value in TWT setup command
b4f7506ff FILS: Flush external-PMKSA when connection fails without ERP keys
80bcd7ecd FILS: Flush PMKSA entries on FILS connection failure
914a2f518 SAE: Report authentication rejection over control interface
9557ba336 AP: Don't increment auth_transaction upon SAE authentication failure
84f6492ea Extend QCA vendor command for TSF to enable and disable auto report
7ef420058 QCA vendor attribute to configure BSS max idle support
ef83e0f90 QCA vendor attribute to use BSSID in Probe Request frame RA
e2ff06c91 Add channel load percentage attribute into QCA vendor command
ac6a0293d Add uplink delay attribute in QCA vendor command get_sta_info responses
84f894773 PTKSA: Fix a potential hostapd memory leak during reconfiguration
311091eb4 P2P: Use SAE+PMF for P2P connection in 6 GHz
f0cdacacb P2P: Allow connection on 6 GHz channels if requested
b36142a74 P2P: Add allow_6ghz parameter to control interface
f7d4f1cbe P2P: Add a mechanism for allowing 6 GHz channels in channel lists
6423c23e3 P2P: Allow 6 GHz channels to be included in the P2P_FIND operation
a06c7d50f P2P: Helper functions to check for WFD capability of a P2P device
eaf850867 P2P: Extend channel determination/validation to 6 GHz channels
9b50746f5 P2P: Introduce 6 GHz band capability bit in P2P Device Capability
9f901e65b WNM: Ignore SSID check for hidden SSID in transition candidates
525ec045f P2P: Use correct return type for has_channel()
09fb9b0cb DFS offload: Use hostapd_is_dfs_required() to check if DFS required
e8662e9d4 Use a helper function to remove struct wpa_bss_tmp_disallowed entries
ecaacb47b OCE: Remove AP from driver disallow list with sufficient AP RSSI
c25b50306 hostapd: Reject 40 MHz channel config if regulatory rules do not allow it
20a522b9e AP: Add user configuration for TWT responder role
9efed6684 Android: Pass the vendor events to $(BOARD_HOSTAPD_PRIVATE_LIB)
39a1d55b7 Add QCA vendor interface to transport CFR data using netlink events
da3335c92 QCA vendor attribute to configure keep alive data type
98f1259cd QCA vendor attribute to configure ER SU PPDU type
e2e2655ce FILS: Fix PMKID derivation for OKC
6abfb1418 Use estimated throughputs irrespective of RSSI delta for 6 GHz APs
5e1e4cceb Add QCA vendor attribute to enable/disable FT over DS
586afb8fa Add QCA interface to configure band specific RSSI thresholds for roaming
800e34550 Fix documentation for QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR
7d2302f87 Add EAPOL-4WAY-HS-COMPLETED indication to AP
1c5aa2579 Add EAPOL_TX command to extend ext_eapol_frame_io possibilities
7f0a2e422 Report EAPOL-RX events for testing purposes
04283cf36 Add REKEY_PTK to allow upper layer request to force PTK rekeying
82d8d631e Skip GTK rekeying request if rekeying already in process
de4d62dbc Add QCA vendor definitions for DFS radar history
46f897619 Prefer 6 GHz APs for connection in BSS selection
84008457e Add support to calculate estimated throughputs for HE rates
658b6a0b0 Add support to estimate throughput for VHT 160/80+80 MHz supporting APs
1d2118b50 Check local supported features for estimating BSS throughputs accurately
2950851ac Rename the Frame Control field subfield Order define to +HTC
11821ab3d Add QCA vendor interface to query usable channels
6ae0d78b8 Determine 6 GHz bandwidth in AP mode ACS using op_class parameter
0822de037 Add AP mode ACS support for the 6 GHz band
bef5eee4f Convert channel to frequency based selection for AP mode ACS
15742566f 6 GHz: Fix operating class in Supported Operating Classes element
79e8f0c16 hostapd: Update 160 MHz center freq calculation in 6 GHz
9c6b0a941 hostapd: Disable VHT/HE when WMM is not enabled
15b1831a2 nl80211: Map internal TDLS_PEER_* to NL80211_TDLS_PEER_*
742018f44 Add support to indicate TDLS peer's HE capability to driver
2be5777a9 Sync with mac80211-next.git include/uapi/linux/nl80211.h
1f2fbf41d Fix UPDATE_BEACON processing when disabled
b8d337c63 DPP2: Fix channel 6 inclusion for chirping with non-2 GHz interfaces
80d975695 DPP2: Get DPP Relay Controller context based on hostapd callback context
e63d45690 Add vendor reason code for TWT setup reject due to scan in progress
7d513b5b2 Add vendor hang reason code for tasklet/credit latency
a6cae954e Vendor command to configure concurrent STA connection policies
c2d7b027b DPP2: Close incomplete Relay connections
f91680c15 OpenSSL: Fix compilation for version < 1.1.0 without CONFIG_ECC
d675d3b15 Add helper functions for parsing RSNXE capabilities
663e190b7 SAE: Remove now unused password identifier argument from non-H2E case
79f87f473 PASN: Change PASN flows to use SAE H2E only
8c786e068 PASN: Derive KDK only when required
655edc19c Vendor attributes to configure broadcast TWT parameters
49ad86b0c Add vendor reason codes for TWT setup reject on roaming/channel switch
0bae16122 Set last_eapol_matches_bssid=1 on a roam+auth indication from driver
527be9ce7 SAE: Increment the Sc counter before generating each Confirm
47f51c8ba tests: Update SAE test vector to IEEE Std 802.11-2020
5f082c158 nl80211: Support larger number of MAC ACL entries
f1fc9cf74 nl80211: Fix the size of the maximum MAC ACL size
93576264b WPS: Share a single error handling path in wps_set_ie()
2445e18b6 tests: assoc+auth driver event
00bec7b5b tests: IEEE 802.1X and FORCE_UNAUTH state
e72e32253 hostapd: Enable WMM automatically when HE is configured
8ca330bd7 Flush pending control interface message for an interface to be removed
4a841a218 Fix WNM-Sleep Mode exit debug print of BIGTK
354f87e2e MSCS: Fix MSCS Response frame Status field parsing
b8673baea Add REGISTER_FRAME hostapd control interface command for testing purposes
60974eb3f Allow AP mode extended capabilities to be overridden
7365eb43e Make hostapd_config_fill() easier to auto indent
8ca09293e Simplify extended capability determination in AP mode
37306a004 PASN: Use a helper function to free radio work data
349e9eafb PASN: Mark pubkey/comeback arguments constant for frame construction
67014b3f7 PASN: Add support for comeback flow to wpa_supplicant
ab623ac75 PASN: Add support for comeback flow in AP mode
4ed10754e DPP: Fix GAS client error case handling in hostapd
3ae18d4bd EAP-SIM/AKA: Fix check for anonymous decorated identity
512d973cc DPP: Indicate authentication success on ConfReqRX if needed (hostapd)
6c8842f0e Fix full EAP authentication after PMKSA cache add failure
6bbbd9729 DPP2: Fix connection status result wait in hostapd
c0c74f0c6 Testing functionality for airtime policy
2f7789149 nl80211: Debug print error from airtime weight configuration
38fa5e657 More documentation for HE Spatial Reuse Parameter Set configuration
73d9891bd EAP-SIM/AKA peer: Support decorated anonymous identity prefix
7831b10a8 Introduce reason code for TWT teardown due to concurrency
eaeec4da2 PASN: Add support for deauthentication flow in station
4f436d537 nl80211: Allow sending Deauthentication frame with off channel for PASN
1ca1c3cfe AP: Handle deauthentication frame from PASN station
166e357e6 AP: Enable anti clogging handling code in PASN builds without SAE
6fe0d56e8 AP: Rename SAE anti clogging variables and functions
b86678633 PASN: For testing purposes allow to corrupt MIC
2efa60344 PASN: Encode the public key properly
cd0813763 PASN: Include PMKID in RSNE in PASN response from AP
da3ac9809 PASN: Fix setting frame and data lengths in AP mode PASN response
c733664be EAP peer: Make EAP-Success handling more robust against race conditions
72a17937c DPP: Add init/respond retries parameter configuration to hostapd
6ed0c212e TLS: Fix highest TLS version disabling with internal TLS client
57550cb27 DPP2: Use ASN.1 helper functions
626035bec TLS: Use ASN.1 helper functions
d4e1d76db X509: Use ASN.1 helper functions
173e7eede RSA: Use ASN.1 helper functions
72b0217ab PKCS: Use ASN.1 helper functions
a0541334a ASN.1: Validate DigestAlgorithmIdentifier parameters
94beb8e36 ASN.1: Fix AlgorithmInfo parsing for signatures
ee76493bb ASN.1: Reject invalid definite long form length values in DER encoding
3af75f23b ASN.1: Reject invalid extended tags in DER encoding
d6831a0e9 ASN.1: Explicitly validate constructed bit while parsing DER
b421a7cf2 ASN.1: Use the helper functions for recognizing tags and debug prints
9a990e8c4 ASN.1: Add helper functions for recognizing tag values
9bf4c0539 ASN.1: Verify that NULL value has zero length
f629bfe22 ASN.1: Add helper functions for debug printing identifier/length info
429f725d9 ASN.1: Define tag value for TIME
4481b03ee ASN.1: Fix a typo in a not-used tag name
2f2a57075 nl80211: Restore station mode on deinit only if station when started
a746393dc TWT: Allow specifying Control field value in TWT Request
a6b2007c2 nl80211: Support disabling HE in infrastructure BSS as station
01f2e54ce P2P: Clear pending_listen_freq when stopping listen
82a348eda wpa_supplicant: Don't process EAPOL frames while disconnecting
e80e6a2f1 eapol_test: Add address family for IPv4 in Windows build
cd2f8151e Add support to return bandwidth for channel 2 of the 6 GHz band
6b4e32da8 New vendor attribute to configure TWT mantissa in microseconds
7fd2f2496 TWT: Support sending TWT Setup and Teardown Action frames
edbaffc4f wpabuf: Add helper functions for writing 64-bit integers
17d85158c Fix hostapd PMKSA_ADD with Authenticator disabled
147d6d372 Update VHT capabilities info on channel switch event
dc587c479 nl80211: Determine secondary channel offset for CS to 80+80 MHz
0a8095d72 nl80211: Debug print for channel switch request parameters
a20ace3a1 nl80211: Add command-to-string mapping for previously missed commands
0f37b8142 More specific set_freq_params debug prints for 80/80+80 MHz errors
ab8929192 nl80211: Use process_bss_event() for the nl_connect handler
7c5442e74 DPP: Clear hapd->gas pointer on deinit
076e0abdd SQLite: Fix temporary eap_user data freeing on interface restart
2da3105ac Fix use after free with hapd->time_adv on interface restart
5ac977758 Reject authentication start during explicit roam requests
800fb6997 QCA vendor attribute to allow 6 GHz connection with all security types
1a60099f2 QCA vendor attribute to ignore SAE H2E requirement mismatch
e9d598d8a Update old link to ACS wiki documentation
b5e3d92ee OCV: Fix OCV-FAILURE event address for FT Reassociation Response frame
40551a15c Fix a memory leak in WPS with ap_scan=2
900adb3c9 FILS: Simplify code paths
4a5f6e88b SAE: Use more explicit IE payload validation steps
57fec19da Use more consistent iface->conf checks
b8211e1e7 PASN: Avoid unreachable code with CONFIG_NO_RADIUS
9a1136b7f FILS: Fix RSN info in FD frame for no-group-addressed
6035969e0 Fix dynamic EAP library building
a826ff2d9 Ignore group-addressed SA Query frames
d314213f6 P2P: Pick a 5 GHz channel from more possible channels
205c35cef nl80211: Allow compilation with both vendor do_acs() handlers
61a258e78 nl80211: Add ACS support for Broadcom device
827b43b3c RADIUS client: Support SO_BINDTODEVICE
3a05f89ed Android: Add DRIVER command support on hostapd and hostapd_cli
50baf345b TDLS: Support TDLS operations in HE mode
184c82468 P2P: Add device address to the debug entry on oldest peer removal
8460e3230 P2P: Fix a corner case in peer addition based on PD Request
Change-Id: Ieec0678b1a5c72fef3f3363cb54b20ac1cb8ab7f
diff --git a/src/common/brcm_vendor.h b/src/common/brcm_vendor.h
index 0a44a6c..03a178e 100644
--- a/src/common/brcm_vendor.h
+++ b/src/common/brcm_vendor.h
@@ -1,6 +1,6 @@
/*
* Broadcom Corporation OUI and vendor specific assignments
- * Copyright (c) 2015, Broadcom Corporation.
+ * Copyright (c) 2020, Broadcom Corporation.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -16,19 +16,51 @@
* hostap.git repository.
*/
-#define OUI_BRCM 0x001018
+#define OUI_BRCM 0x001018
/**
* enum brcm_nl80211_vendor_subcmds - BRCM nl80211 vendor command identifiers
*
- * @BRCM_VENDOR_SUBCMD_UNSPEC: Reserved value 0
+ * @BRCM_VENDOR_SCMD_UNSPEC: Reserved value 0
*
- * @BRCM_VENDOR_SUBCMD_PRIV_STR: String command/event
+ * @BRCM_VENDOR_SCMD_PRIV_STR: Provide vendor private cmds to send to FW.
+ *
+ * @BRCM_VENDOR_SCMD_BCM_STR: Provide vendor cmds to BCMDHD driver.
+ *
+ * @BRCM_VENDOR_SCMD_BCM_PSK: Used to set SAE password.
+ *
+ * @BRCM_VENDOR_SCMD_SET_PMK: Command to check driver support
+ * for DFS offloading.
+ *
+ * @BRCM_VENDOR_SCMD_GET_FEATURES: Command to get the features
+ * supported by the driver.
+ *
+ * @BRCM_VENDOR_SCMD_SET_MAC: Set random mac address for P2P interface.
+ *
+ * @BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS: Set some connect parameters.
+ * Used for the case that FW handle SAE.
+ *
+ * @BRCM_VENDOR_SCMD_SET_START_AP_PARAMS: Set SoftAP paramters.
+ * Used for the case that FW handle SAE.
+ *
+ * @BRCM_VENDOR_SCMD_ACS: ACS command/event which is used to
+ * invoke the ACS function in device and pass selected channels to
+ * hostapd. Uses enum qca_wlan_vendor_attr_acs_offload attributes.
+ *
+ * @BRCM_VENDOR_SCMD_MAX: This acts as a the tail of cmds list.
+ * Make sure it located at the end of the list.
+ *
*/
enum brcm_nl80211_vendor_subcmds {
- BRCM_VENDOR_SUBCMD_UNSPEC = 0,
- BRCM_VENDOR_SUBCMD_SET_PMK = 4,
- BRCM_VENDOR_SUBCMD_SET_MAC = 6,
+ BRCM_VENDOR_SCMD_UNSPEC = 0,
+ BRCM_VENDOR_SCMD_PRIV_STR = 1,
+ BRCM_VENDOR_SCMD_BCM_STR = 2,
+ BRCM_VENDOR_SCMD_BCM_PSK = 3,
+ BRCM_VENDOR_SCMD_SET_PMK = 4,
+ BRCM_VENDOR_SCMD_GET_FEATURES = 5,
+ BRCM_VENDOR_SCMD_SET_MAC = 6,
+ BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS = 7,
+ BRCM_VENDOR_SCMD_SET_START_AP_PARAMS = 8,
BRCM_VENDOR_SCMD_ACS = 9,
BRCM_VENDOR_SCMD_MAX = 10
};
@@ -41,11 +73,67 @@
* @BRCM_VENDOR_EVENT_PRIV_STR: String command/event
*/
enum brcm_nl80211_vendor_events {
- BRCM_VENDOR_EVENT_UNSPEC,
+ BRCM_VENDOR_EVENT_UNSPEC = 0,
+ BRCM_VENDOR_EVENT_PRIV_STR = 1,
+ GOOGLE_GSCAN_SIGNIFICANT_EVENT = 2,
+ GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT = 3,
+ GOOGLE_GSCAN_BATCH_SCAN_EVENT = 4,
+ GOOGLE_SCAN_FULL_RESULTS_EVENT = 5,
+ GOOGLE_RTT_COMPLETE_EVENT = 6,
+ GOOGLE_SCAN_COMPLETE_EVENT = 7,
+ GOOGLE_GSCAN_GEOFENCE_LOST_EVENT = 8,
+ GOOGLE_SCAN_EPNO_EVENT = 9,
+ GOOGLE_DEBUG_RING_EVENT = 10,
+ GOOGLE_FW_DUMP_EVENT = 11,
+ GOOGLE_PNO_HOTSPOT_FOUND_EVENT = 12,
+ GOOGLE_RSSI_MONITOR_EVENT = 13,
+ GOOGLE_MKEEP_ALIVE_EVENT = 14,
+
+ /*
+ * BRCM specific events should be placed after
+ * the Generic events so that enums don't mismatch
+ * between the DHD and HAL
+ */
+ GOOGLE_NAN_EVENT_ENABLED = 15,
+ GOOGLE_NAN_EVENT_DISABLED = 16,
+ GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH = 17,
+ GOOGLE_NAN_EVENT_REPLIED = 18,
+ GOOGLE_NAN_EVENT_PUBLISH_TERMINATED = 19,
+ GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED = 20,
+ GOOGLE_NAN_EVENT_DE_EVENT = 21,
+ GOOGLE_NAN_EVENT_FOLLOWUP = 22,
+ GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND = 23,
+ GOOGLE_NAN_EVENT_DATA_REQUEST = 24,
+ GOOGLE_NAN_EVENT_DATA_CONFIRMATION = 25,
+ GOOGLE_NAN_EVENT_DATA_END = 26,
+ GOOGLE_NAN_EVENT_BEACON = 27,
+ GOOGLE_NAN_EVENT_SDF = 28,
+ GOOGLE_NAN_EVENT_TCA = 29,
+ GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH = 30,
+ GOOGLE_NAN_EVENT_UNKNOWN = 31,
+ GOOGLE_ROAM_EVENT_START = 32,
+ BRCM_VENDOR_EVENT_HANGED = 33,
+ BRCM_VENDOR_EVENT_SAE_KEY = 34,
+ BRCM_VENDOR_EVENT_BEACON_RECV = 35,
+ BRCM_VENDOR_EVENT_PORT_AUTHORIZED = 36,
+ GOOGLE_FILE_DUMP_EVENT = 37,
+ BRCM_VENDOR_EVENT_CU = 38,
+ BRCM_VENDOR_EVENT_WIPS = 39,
+ NAN_ASYNC_RESPONSE_DISABLED = 40,
+ BRCM_VENDOR_EVENT_RCC_INFO = 41,
BRCM_VENDOR_EVENT_ACS = 42,
- BRCM_VENDOR_EVENT_LAST = 44
+ BRCM_VENDOR_EVENT_LAST
+
};
+#ifdef CONFIG_BRCM_SAE
+enum wifi_sae_key_attr {
+ BRCM_SAE_KEY_ATTR_BSSID,
+ BRCM_SAE_KEY_ATTR_PMK,
+ BRCM_SAE_KEY_ATTR_PMKID
+};
+#endif /* CONFIG_BRCM_SAE */
+
enum wl_vendor_attr_acs_offload {
BRCM_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
BRCM_VENDOR_ATTR_ACS_PRIMARY_FREQ,
diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c
index 50ce192..8aba713 100644
--- a/src/common/common_module_tests.c
+++ b/src/common/common_module_tests.c
@@ -256,87 +256,69 @@
#ifdef CONFIG_SAE
struct sae_data sae;
int ret = -1;
- /* IEEE P802.11-REVmd/D2.1, Annex J.10 */
- const u8 addr1[ETH_ALEN] = { 0x82, 0x7b, 0x91, 0x9d, 0xd4, 0xb9 };
- const u8 addr2[ETH_ALEN] = { 0x1e, 0xec, 0x49, 0xea, 0x64, 0x88 };
+ /* IEEE Std 802.11-2020, Annex J.10 */
+ const u8 addr1[ETH_ALEN] = { 0x4d, 0x3f, 0x2f, 0xff, 0xe3, 0x87 };
+ const u8 addr2[ETH_ALEN] = { 0xa5, 0xd8, 0xaa, 0x95, 0x8e, 0x3c };
const char *ssid = "byteme";
const char *pw = "mekmitasdigoat";
const char *pwid = "psk4internet";
const u8 local_rand[] = {
- 0xa9, 0x06, 0xf6, 0x1e, 0x4d, 0x3a, 0x5d, 0x4e,
- 0xb2, 0x96, 0x5f, 0xf3, 0x4c, 0xf9, 0x17, 0xdd,
- 0x04, 0x44, 0x45, 0xc8, 0x78, 0xc1, 0x7c, 0xa5,
- 0xd5, 0xb9, 0x37, 0x86, 0xda, 0x9f, 0x83, 0xcf
+ 0x99, 0x24, 0x65, 0xfd, 0x3d, 0xaa, 0x3c, 0x60,
+ 0xaa, 0x65, 0x65, 0xb7, 0xf6, 0x2a, 0x2a, 0x7f,
+ 0x2e, 0x12, 0xdd, 0x12, 0xf1, 0x98, 0xfa, 0xf4,
+ 0xfb, 0xed, 0x89, 0xd7, 0xff, 0x1a, 0xce, 0x94
};
const u8 local_mask[] = {
- 0x42, 0x34, 0xb4, 0xfb, 0x17, 0xaa, 0x43, 0x5c,
- 0x52, 0xfb, 0xfd, 0xeb, 0xe6, 0x40, 0x39, 0xb4,
- 0x34, 0x78, 0x20, 0x0e, 0x54, 0xff, 0x7b, 0x6e,
- 0x07, 0xb6, 0x9c, 0xad, 0x74, 0x15, 0x3c, 0x15
+ 0x95, 0x07, 0xa9, 0x0f, 0x77, 0x7a, 0x04, 0x4d,
+ 0x6a, 0x08, 0x30, 0xb9, 0x1e, 0xa3, 0xd5, 0xdd,
+ 0x70, 0xbe, 0xce, 0x44, 0xe1, 0xac, 0xff, 0xb8,
+ 0x69, 0x83, 0xb5, 0xe1, 0xbf, 0x9f, 0xb3, 0x22
};
const u8 local_commit[] = {
- 0x13, 0x00, 0xeb, 0x3b, 0xab, 0x19, 0x64, 0xe4,
- 0xa0, 0xab, 0x05, 0x92, 0x5d, 0xdf, 0x33, 0x39,
- 0x51, 0x91, 0x38, 0xbc, 0x65, 0xd6, 0xcd, 0xc0,
- 0xf8, 0x13, 0xdd, 0x6f, 0xd4, 0x34, 0x4e, 0xb4,
- 0xbf, 0xe4, 0x4b, 0x5c, 0x21, 0x59, 0x76, 0x58,
- 0xf4, 0xe3, 0xed, 0xdf, 0xb4, 0xb9, 0x9f, 0x25,
- 0xb4, 0xd6, 0x54, 0x0f, 0x32, 0xff, 0x1f, 0xd5,
- 0xc5, 0x30, 0xc6, 0x0a, 0x79, 0x44, 0x48, 0x61,
- 0x0b, 0xc6, 0xde, 0x3d, 0x92, 0xbd, 0xbb, 0xd4,
- 0x7d, 0x93, 0x59, 0x80, 0xca, 0x6c, 0xf8, 0x98,
- 0x8a, 0xb6, 0x63, 0x0b, 0xe6, 0x76, 0x4c, 0x88,
- 0x5c, 0xeb, 0x97, 0x93, 0x97, 0x0f, 0x69, 0x52,
- 0x17, 0xee, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
- 0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
- 0x74
+ 0x13, 0x00, 0x2e, 0x2c, 0x0f, 0x0d, 0xb5, 0x24,
+ 0x40, 0xad, 0x14, 0x6d, 0x96, 0x71, 0x14, 0xce,
+ 0x00, 0x5c, 0xe1, 0xea, 0xb0, 0xaa, 0x2c, 0x2e,
+ 0x5c, 0x28, 0x71, 0xb7, 0x74, 0xf6, 0xc2, 0x57,
+ 0x5c, 0x65, 0xd5, 0xad, 0x9e, 0x00, 0x82, 0x97,
+ 0x07, 0xaa, 0x36, 0xba, 0x8b, 0x85, 0x97, 0x38,
+ 0xfc, 0x96, 0x1d, 0x08, 0x24, 0x35, 0x05, 0xf4,
+ 0x7c, 0x03, 0x53, 0x76, 0xd7, 0xac, 0x4b, 0xc8,
+ 0xd7, 0xb9, 0x50, 0x83, 0xbf, 0x43, 0x82, 0x7d,
+ 0x0f, 0xc3, 0x1e, 0xd7, 0x78, 0xdd, 0x36, 0x71,
+ 0xfd, 0x21, 0xa4, 0x6d, 0x10, 0x91, 0xd6, 0x4b,
+ 0x6f, 0x9a, 0x1e, 0x12, 0x72, 0x62, 0x13, 0x25,
+ 0xdb, 0xe1
};
const u8 peer_commit[] = {
- 0x13, 0x00, 0x55, 0x64, 0xf0, 0x45, 0xb2, 0xea,
- 0x1e, 0x56, 0x6c, 0xf1, 0xdd, 0x74, 0x1f, 0x70,
- 0xd9, 0xbe, 0x35, 0xd2, 0xdf, 0x5b, 0x9a, 0x55,
- 0x02, 0x94, 0x6e, 0xe0, 0x3c, 0xf8, 0xda, 0xe2,
- 0x7e, 0x1e, 0x05, 0xb8, 0x43, 0x0e, 0xb7, 0xa9,
- 0x9e, 0x24, 0x87, 0x7c, 0xe6, 0x9b, 0xaf, 0x3d,
- 0xc5, 0x80, 0xe3, 0x09, 0x63, 0x3d, 0x6b, 0x38,
- 0x5f, 0x83, 0xee, 0x1c, 0x3e, 0xc3, 0x59, 0x1f,
- 0x1a, 0x53, 0x93, 0xc0, 0x6e, 0x80, 0x5d, 0xdc,
- 0xeb, 0x2f, 0xde, 0x50, 0x93, 0x0d, 0xd7, 0xcf,
- 0xeb, 0xb9, 0x87, 0xc6, 0xff, 0x96, 0x66, 0xaf,
- 0x16, 0x4e, 0xb5, 0x18, 0x4d, 0x8e, 0x66, 0x62,
- 0xed, 0x6a, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
- 0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
- 0x74
+ 0x13, 0x00, 0x59, 0x1b, 0x96, 0xf3, 0x39, 0x7f,
+ 0xb9, 0x45, 0x10, 0x08, 0x48, 0xe7, 0xb5, 0x50,
+ 0x54, 0x3b, 0x67, 0x20, 0xd8, 0x83, 0x37, 0xee,
+ 0x93, 0xfc, 0x49, 0xfd, 0x6d, 0xf7, 0xe0, 0x8b,
+ 0x52, 0x23, 0xe7, 0x1b, 0x9b, 0xb0, 0x48, 0xd3,
+ 0x87, 0x3f, 0x20, 0x55, 0x69, 0x53, 0xa9, 0x6c,
+ 0x91, 0x53, 0x6f, 0xd8, 0xee, 0x6c, 0xa9, 0xb4,
+ 0xa6, 0x8a, 0x14, 0x8b, 0x05, 0x6a, 0x90, 0x9b,
+ 0xe0, 0x3e, 0x83, 0xae, 0x20, 0x8f, 0x60, 0xf8,
+ 0xef, 0x55, 0x37, 0x85, 0x80, 0x74, 0xdb, 0x06,
+ 0x68, 0x70, 0x32, 0x39, 0x98, 0x62, 0x99, 0x9b,
+ 0x51, 0x1e, 0x0a, 0x15, 0x52, 0xa5, 0xfe, 0xa3,
+ 0x17, 0xc2
};
const u8 kck[] = {
- 0x59, 0x9d, 0x6f, 0x1e, 0x27, 0x54, 0x8b, 0xe8,
- 0x49, 0x9d, 0xce, 0xed, 0x2f, 0xec, 0xcf, 0x94,
- 0x81, 0x8c, 0xe1, 0xc7, 0x9f, 0x1b, 0x4e, 0xb3,
- 0xd6, 0xa5, 0x32, 0x28, 0xa0, 0x9b, 0xf3, 0xed
+ 0x1e, 0x73, 0x3f, 0x6d, 0x9b, 0xd5, 0x32, 0x56,
+ 0x28, 0x73, 0x04, 0x33, 0x88, 0x31, 0xb0, 0x9a,
+ 0x39, 0x40, 0x6d, 0x12, 0x10, 0x17, 0x07, 0x3a,
+ 0x5c, 0x30, 0xdb, 0x36, 0xf3, 0x6c, 0xb8, 0x1a
};
const u8 pmk[] = {
- 0x7a, 0xea, 0xd8, 0x6f, 0xba, 0x4c, 0x32, 0x21,
- 0xfc, 0x43, 0x7f, 0x5f, 0x14, 0xd7, 0x0d, 0x85,
- 0x4e, 0xa5, 0xd5, 0xaa, 0xc1, 0x69, 0x01, 0x16,
- 0x79, 0x30, 0x81, 0xed, 0xa4, 0xd5, 0x57, 0xc5
+ 0x4e, 0x4d, 0xfa, 0xb1, 0xa2, 0xdd, 0x8a, 0xc1,
+ 0xa9, 0x17, 0x90, 0xf9, 0x53, 0xfa, 0xaa, 0x45,
+ 0x2a, 0xe5, 0xc6, 0x87, 0x3a, 0xb7, 0x5b, 0x63,
+ 0x60, 0x5b, 0xa6, 0x63, 0xf8, 0xa7, 0xfe, 0x59
};
const u8 pmkid[] = {
- 0x40, 0xa0, 0x9b, 0x60, 0x17, 0xce, 0xbf, 0x00,
- 0x72, 0x84, 0x3b, 0x53, 0x52, 0xaa, 0x2b, 0x4f
- };
- const u8 local_confirm[] = {
- 0x01, 0x00, 0x12, 0xd9, 0xd5, 0xc7, 0x8c, 0x50,
- 0x05, 0x26, 0xd3, 0x6c, 0x41, 0xdb, 0xc5, 0x6a,
- 0xed, 0xf2, 0x91, 0x4c, 0xed, 0xdd, 0xd7, 0xca,
- 0xd4, 0xa5, 0x8c, 0x48, 0xf8, 0x3d, 0xbd, 0xe9,
- 0xfc, 0x77
- };
- const u8 peer_confirm[] = {
- 0x01, 0x00, 0x02, 0x87, 0x1c, 0xf9, 0x06, 0x89,
- 0x8b, 0x80, 0x60, 0xec, 0x18, 0x41, 0x43, 0xbe,
- 0x77, 0xb8, 0xc0, 0x8a, 0x80, 0x19, 0xb1, 0x3e,
- 0xb6, 0xd0, 0xae, 0xf0, 0xd8, 0x38, 0x3d, 0xfa,
- 0xc2, 0xfd
+ 0x87, 0x47, 0xa6, 0x00, 0xee, 0xa3, 0xf9, 0xf2,
+ 0x24, 0x75, 0xdf, 0x58, 0xca, 0x1e, 0x54, 0x98
};
struct wpabuf *buf = NULL;
struct crypto_bignum *mask = NULL;
@@ -412,7 +394,7 @@
if (!buf ||
sae_set_group(&sae, 19) < 0 ||
sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
- pwid, &sae) < 0)
+ &sae) < 0)
goto fail;
/* Override local values based on SAE test vector */
@@ -434,7 +416,7 @@
goto fail;
/* Check that output matches the test vector */
- if (sae_write_commit(&sae, buf, NULL, pwid) < 0)
+ if (sae_write_commit(&sae, buf, NULL, NULL) < 0)
goto fail;
wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
@@ -465,21 +447,6 @@
goto fail;
}
- buf->used = 0;
- sae.send_confirm = 1;
- sae_write_confirm(&sae, buf);
- wpa_hexdump_buf(MSG_DEBUG, "SAE: Confirm message", buf);
-
- if (wpabuf_len(buf) != sizeof(local_confirm) ||
- os_memcmp(wpabuf_head(buf), local_confirm,
- sizeof(local_confirm)) != 0) {
- wpa_printf(MSG_ERROR, "SAE: Mismatch in local confirm");
- goto fail;
- }
-
- if (sae_check_confirm(&sae, peer_confirm, sizeof(peer_confirm)) < 0)
- goto fail;
-
pt_info = sae_derive_pt(pt_groups,
(const u8 *) ssid, os_strlen(ssid),
(const u8 *) pw, os_strlen(pw), pwid);
diff --git a/src/common/dpp.c b/src/common/dpp.c
index e8697c5..42a9302 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -2,14 +2,13 @@
* DPP functionality shared between hostapd and wpa_supplicant
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
#include "utils/common.h"
#include "utils/base64.h"
@@ -27,10 +26,10 @@
#include "dpp_i.h"
-static const char * dpp_netrole_str(enum dpp_netrole netrole);
-
#ifdef CONFIG_TESTING_OPTIONS
-#ifdef CONFIG_DPP2
+#ifdef CONFIG_DPP3
+int dpp_version_override = 3;
+#elif defined(CONFIG_DPP2)
int dpp_version_override = 2;
#else
int dpp_version_override = 1;
@@ -38,22 +37,6 @@
enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
#endif /* CONFIG_TESTING_OPTIONS */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- (defined(LIBRESSL_VERSION_NUMBER) && \
- LIBRESSL_VERSION_NUMBER < 0x20700000L)
-/* Compatibility wrappers for older versions. */
-
-#ifdef CONFIG_DPP2
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
-{
- if (pkey->type != EVP_PKEY_EC)
- return NULL;
- return pkey->pkey.ec;
-}
-#endif /* CONFIG_DPP2 */
-
-#endif
-
void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
{
@@ -180,7 +163,7 @@
os_free(info->info);
os_free(info->chan);
os_free(info->pk);
- EVP_PKEY_free(info->pubkey);
+ crypto_ec_key_deinit(info->pubkey);
str_clear_free(info->configurator_params);
os_free(info);
}
@@ -324,6 +307,8 @@
bi->version = 1;
else if (*version == '2')
bi->version = 2;
+ else if (*version == '3')
+ bi->version = 3;
else
wpa_printf(MSG_DEBUG, "DPP: Unknown URI version");
@@ -646,7 +631,8 @@
macstr,
bi->info ? "I:" : "", bi->info ? bi->info : "",
bi->info ? ";" : "",
- DPP_VERSION == 2 ? "V:2;" : "",
+ DPP_VERSION == 3 ? "V:3;" :
+ (DPP_VERSION == 2 ? "V:2;" : ""),
bi->pk);
return 0;
}
@@ -1223,6 +1209,13 @@
wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
+ if (os_strstr(cmd, " conf=query")) {
+ auth->configurator_set = 0;
+ auth->use_config_query = true;
+ ret = 0;
+ goto fail;
+ }
+
pos = os_strstr(cmd, " configurator=");
if (!auth->conf && pos) {
pos += 14;
@@ -1268,9 +1261,9 @@
dpp_configuration_free(auth->conf2_ap);
dpp_configuration_free(auth->conf_sta);
dpp_configuration_free(auth->conf2_sta);
- EVP_PKEY_free(auth->own_protocol_key);
- EVP_PKEY_free(auth->peer_protocol_key);
- EVP_PKEY_free(auth->reconfig_old_protocol_key);
+ crypto_ec_key_deinit(auth->own_protocol_key);
+ crypto_ec_key_deinit(auth->peer_protocol_key);
+ crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
wpabuf_free(auth->req_msg);
wpabuf_free(auth->resp_msg);
wpabuf_free(auth->conf_req);
@@ -1303,6 +1296,9 @@
dl_list_del(&auth->tmp_peer_bi->list);
dpp_bootstrap_info_free(auth->tmp_peer_bi);
}
+ os_free(auth->e_name);
+ os_free(auth->e_mud_url);
+ os_free(auth->e_band_support);
#ifdef CONFIG_TESTING_OPTIONS
os_free(auth->config_obj_override);
os_free(auth->discovery_override);
@@ -1360,14 +1356,15 @@
}
-int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
- const char *kid, const struct dpp_curve_params *curve)
+int dpp_build_jwk(struct wpabuf *buf, const char *name,
+ struct crypto_ec_key *key, const char *kid,
+ const struct dpp_curve_params *curve)
{
struct wpabuf *pub;
const u8 *pos;
int ret = -1;
- pub = dpp_get_pubkey_point(key, 0);
+ pub = crypto_ec_key_get_pubkey_point(key, 0);
if (!pub)
goto fail;
@@ -1412,7 +1409,7 @@
}
-static const char * dpp_netrole_str(enum dpp_netrole netrole)
+const char * dpp_netrole_str(enum dpp_netrole netrole)
{
switch (netrole) {
case DPP_NETROLE_STA:
@@ -1516,6 +1513,10 @@
json_value_sep(dppcon);
json_add_string(dppcon, "expiry", expiry);
}
+#ifdef CONFIG_DPP3
+ json_value_sep(dppcon);
+ json_add_int(dppcon, "version", auth->peer_version);
+#endif /* CONFIG_DPP3 */
json_end_object(dppcon);
wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
(const char *) wpabuf_head(dppcon));
@@ -1645,6 +1646,25 @@
}
+static int dpp_get_peer_bi_id(struct dpp_authentication *auth)
+{
+ struct dpp_bootstrap_info *bi;
+
+ if (auth->peer_bi)
+ return auth->peer_bi->id;
+ if (auth->tmp_peer_bi)
+ return auth->tmp_peer_bi->id;
+
+ bi = os_zalloc(sizeof(*bi));
+ if (!bi)
+ return -1;
+ bi->id = dpp_next_id(auth->global);
+ dl_list_add(&auth->global->bootstrap, &bi->list);
+ auth->tmp_peer_bi = bi;
+ return bi->id;
+}
+
+
static struct wpabuf *
dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
int idx, bool cert_req)
@@ -1673,10 +1693,19 @@
conf = auth->conf2_ap;
}
if (!conf) {
- if (idx == 0)
+ if (idx == 0) {
+ if (auth->use_config_query) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No configuration available for Enrollee(%s) - waiting for configuration",
+ dpp_netrole_str(netrole));
+ auth->waiting_config = true;
+ dpp_get_peer_bi_id(auth);
+ return NULL;
+ }
wpa_printf(MSG_DEBUG,
"DPP: No configuration available for Enrollee(%s) - reject configuration request",
dpp_netrole_str(netrole));
+ }
return NULL;
}
@@ -1730,6 +1759,8 @@
}
}
+ if (!conf && auth->waiting_config)
+ return NULL;
if (conf || env_data)
status = DPP_STATUS_OK;
else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta &&
@@ -1978,6 +2009,8 @@
goto fail;
}
wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
+ os_free(auth->e_name);
+ auth->e_name = os_strdup(token->string);
token = json_get_member(root, "wi-fi_tech");
if (!token || token->type != JSON_STRING) {
@@ -2017,6 +2050,8 @@
wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string);
wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s",
token->string);
+ os_free(auth->e_mud_url);
+ auth->e_mud_url = os_strdup(token->string);
}
token = json_get_member(root, "bandSupport");
@@ -2057,7 +2092,8 @@
}
pos += res;
}
- os_free(opclass);
+ os_free(auth->e_band_support);
+ auth->e_band_support = opclass;
wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s",
txt);
}
@@ -2075,21 +2111,9 @@
goto cont;
}
- if (auth->peer_bi) {
- id = auth->peer_bi->id;
- } else if (auth->tmp_peer_bi) {
- id = auth->tmp_peer_bi->id;
- } else {
- struct dpp_bootstrap_info *bi;
-
- bi = os_zalloc(sizeof(*bi));
- if (!bi)
- goto fail;
- bi->id = dpp_next_id(auth->global);
- dl_list_add(&auth->global->bootstrap, &bi->list);
- auth->tmp_peer_bi = bi;
- id = bi->id;
- }
+ id = dpp_get_peer_bi_id(auth);
+ if (id < 0)
+ goto fail;
wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA");
txt = base64_encode_no_lf(wpabuf_head(cert_req),
@@ -2165,14 +2189,13 @@
}
-EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
- const struct dpp_curve_params **key_curve)
+struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk,
+ const struct dpp_curve_params **key_curve)
{
struct json_token *token;
const struct dpp_curve_params *curve;
struct wpabuf *x = NULL, *y = NULL;
- EC_GROUP *group;
- EVP_PKEY *pkey = NULL;
+ struct crypto_ec_key *key = NULL;
token = json_get_member(jwk, "kty");
if (!token || token->type != JSON_STRING) {
@@ -2225,22 +2248,18 @@
goto fail;
}
- group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
- if (!group) {
- wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK");
+ key = crypto_ec_key_set_pub(curve->ike_group, wpabuf_head(x),
+ wpabuf_head(y), wpabuf_len(x));
+ if (!key)
goto fail;
- }
- pkey = dpp_set_pubkey_point_group(group, wpabuf_head(x), wpabuf_head(y),
- wpabuf_len(x));
- EC_GROUP_free(group);
*key_curve = curve;
fail:
wpabuf_free(x);
wpabuf_free(y);
- return pkey;
+ return key;
}
@@ -2330,7 +2349,7 @@
{
struct json_token *root, *groups, *netkey, *token;
int ret = -1;
- EVP_PKEY *key = NULL;
+ struct crypto_ec_key *key = NULL;
const struct dpp_curve_params *curve;
unsigned int rules = 0;
@@ -2397,7 +2416,7 @@
goto fail;
dpp_debug_print_key("DPP: Received netAccessKey", key);
- if (EVP_PKEY_cmp(key, auth->own_protocol_key) != 1) {
+ if (crypto_ec_key_cmp(key, auth->own_protocol_key)) {
wpa_printf(MSG_DEBUG,
"DPP: netAccessKey in connector does not match own protocol key");
#ifdef CONFIG_TESTING_OPTIONS
@@ -2414,47 +2433,45 @@
ret = 0;
fail:
- EVP_PKEY_free(key);
+ crypto_ec_key_deinit(key);
json_free(root);
return ret;
}
-static void dpp_copy_csign(struct dpp_config_obj *conf, EVP_PKEY *csign)
+static void dpp_copy_csign(struct dpp_config_obj *conf,
+ struct crypto_ec_key *csign)
{
- unsigned char *der = NULL;
- int der_len;
+ struct wpabuf *c_sign_key;
- der_len = i2d_PUBKEY(csign, &der);
- if (der_len <= 0)
+ c_sign_key = crypto_ec_key_get_subject_public_key(csign);
+ if (!c_sign_key)
return;
+
wpabuf_free(conf->c_sign_key);
- conf->c_sign_key = wpabuf_alloc_copy(der, der_len);
- OPENSSL_free(der);
+ conf->c_sign_key = c_sign_key;
}
-static void dpp_copy_ppkey(struct dpp_config_obj *conf, EVP_PKEY *ppkey)
+static void dpp_copy_ppkey(struct dpp_config_obj *conf,
+ struct crypto_ec_key *ppkey)
{
- unsigned char *der = NULL;
- int der_len;
+ struct wpabuf *pp_key;
- der_len = i2d_PUBKEY(ppkey, &der);
- if (der_len <= 0)
+ pp_key = crypto_ec_key_get_subject_public_key(ppkey);
+ if (!pp_key)
return;
+
wpabuf_free(conf->pp_key);
- conf->pp_key = wpabuf_alloc_copy(der, der_len);
- OPENSSL_free(der);
+ conf->pp_key = pp_key;
}
static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
struct dpp_config_obj *conf)
{
- unsigned char *der = NULL;
- int der_len;
- EC_KEY *eckey;
- EVP_PKEY *own_key;
+ struct wpabuf *net_access_key;
+ struct crypto_ec_key *own_key;
own_key = auth->own_protocol_key;
#ifdef CONFIG_DPP2
@@ -2462,19 +2479,13 @@
auth->reconfig_old_protocol_key)
own_key = auth->reconfig_old_protocol_key;
#endif /* CONFIG_DPP2 */
- eckey = EVP_PKEY_get1_EC_KEY(own_key);
- if (!eckey)
+
+ net_access_key = crypto_ec_key_get_ecprivate_key(own_key, true);
+ if (!net_access_key)
return;
- der_len = i2d_ECPrivateKey(eckey, &der);
- if (der_len <= 0) {
- EC_KEY_free(eckey);
- return;
- }
wpabuf_free(auth->net_access_key);
- auth->net_access_key = wpabuf_alloc_copy(der, der_len);
- OPENSSL_free(der);
- EC_KEY_free(eckey);
+ auth->net_access_key = net_access_key;
}
@@ -2485,7 +2496,7 @@
struct dpp_signed_connector_info info;
struct json_token *token, *csign, *ppkey;
int ret = -1;
- EVP_PKEY *csign_pub = NULL, *pp_pub = NULL;
+ struct crypto_ec_key *csign_pub = NULL, *pp_pub = NULL;
const struct dpp_curve_params *key_curve = NULL, *pp_curve = NULL;
const char *signed_connector;
@@ -2565,8 +2576,8 @@
ret = 0;
fail:
- EVP_PKEY_free(csign_pub);
- EVP_PKEY_free(pp_pub);
+ crypto_ec_key_deinit(csign_pub);
+ crypto_ec_key_deinit(pp_pub);
os_free(info.payload);
return ret;
}
@@ -2591,7 +2602,7 @@
return -1;
}
wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received certBag", conf->certbag);
- conf->certs = dpp_pkcs7_certs(conf->certbag);
+ conf->certs = crypto_pkcs7_get_certificates(conf->certbag);
if (!conf->certs) {
dpp_auth_fail(auth, "No certificates in certBag");
return -1;
@@ -3399,11 +3410,11 @@
{
if (!conf)
return;
- EVP_PKEY_free(conf->csign);
+ crypto_ec_key_deinit(conf->csign);
os_free(conf->kid);
os_free(conf->connector);
- EVP_PKEY_free(conf->connector_key);
- EVP_PKEY_free(conf->pp_key);
+ crypto_ec_key_deinit(conf->connector_key);
+ crypto_ec_key_deinit(conf->pp_key);
os_free(conf);
}
@@ -3411,23 +3422,19 @@
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;
+ struct wpabuf *key;
+ int ret = -1;
if (!conf->csign)
return -1;
- eckey = EVP_PKEY_get1_EC_KEY(conf->csign);
- if (!eckey)
+ key = crypto_ec_key_get_ecprivate_key(conf->csign, true);
+ if (!key)
return -1;
- key_len = i2d_ECPrivateKey(eckey, &key);
- if (key_len > 0)
- ret = wpa_snprintf_hex(buf, buflen, key, key_len);
+ ret = wpa_snprintf_hex(buf, buflen, wpabuf_head(key), wpabuf_len(key));
- EC_KEY_free(eckey);
- OPENSSL_free(key);
+ wpabuf_clear_free(key);
return ret;
}
@@ -3439,7 +3446,7 @@
size_t len[1];
int res;
- csign_pub = dpp_get_pubkey_point(conf->csign, 1);
+ csign_pub = crypto_ec_key_get_pubkey_point(conf->csign, 1);
if (!csign_pub) {
wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
return -1;
@@ -3675,7 +3682,7 @@
struct json_token *root = NULL, *netkey, *token;
struct json_token *own_root = NULL;
enum dpp_status_error ret = 255, res;
- EVP_PKEY *own_key = NULL, *peer_key = NULL;
+ struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
struct wpabuf *own_key_pub = NULL;
const struct dpp_curve_params *curve, *own_curve;
struct dpp_signed_connector_info info;
@@ -3733,6 +3740,14 @@
}
}
+#ifdef CONFIG_DPP3
+ token = json_get_member(root, "version");
+ if (token && token->type == JSON_NUMBER) {
+ wpa_printf(MSG_DEBUG, "DPP: version = %d", token->number);
+ intro->peer_version = token->number;
+ }
+#endif /* CONFIG_DPP3 */
+
netkey = json_get_member(root, "netAccessKey");
if (!netkey || netkey->type != JSON_OBJECT) {
wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
@@ -3781,15 +3796,35 @@
os_memset(intro, 0, sizeof(*intro));
os_memset(Nx, 0, sizeof(Nx));
os_free(info.payload);
- EVP_PKEY_free(own_key);
+ crypto_ec_key_deinit(own_key);
wpabuf_free(own_key_pub);
- EVP_PKEY_free(peer_key);
+ crypto_ec_key_deinit(peer_key);
json_free(root);
json_free(own_root);
return ret;
}
+#ifdef CONFIG_DPP3
+int dpp_get_connector_version(const char *connector)
+{
+ struct json_token *root, *token;
+ int ver = -1;
+
+ root = dpp_parse_own_connector(connector);
+ if (!root)
+ return -1;
+
+ token = json_get_member(root, "version");
+ if (token && token->type == JSON_NUMBER)
+ ver = token->number;
+
+ json_free(root);
+ return ver;
+}
+#endif /* CONFIG_DPP3 */
+
+
unsigned int dpp_next_id(struct dpp_global *dpp)
{
struct dpp_bootstrap_info *bi;
@@ -4134,7 +4169,7 @@
wpa_printf(MSG_DEBUG,
"DPP: Update own bootstrapping key to match peer curve from NFC handover");
- EVP_PKEY_free(own_bi->pubkey);
+ crypto_ec_key_deinit(own_bi->pubkey);
own_bi->pubkey = NULL;
if (dpp_keygen(own_bi, peer_bi->curve->name, NULL, 0) < 0 ||
@@ -4280,33 +4315,24 @@
struct dpp_asymmetric_key *key)
{
struct dpp_configurator *conf;
- const EC_KEY *eckey, *eckey_pp;
- const EC_GROUP *group, *group_pp;
- int nid;
- const struct dpp_curve_params *curve;
+ const struct dpp_curve_params *curve, *curve_pp;
if (!key->csign || !key->pp_key)
return -1;
- eckey = EVP_PKEY_get0_EC_KEY(key->csign);
- if (!eckey)
- return -1;
- group = EC_KEY_get0_group(eckey);
- if (!group)
- return -1;
- nid = EC_GROUP_get_curve_name(group);
- curve = dpp_get_curve_nid(nid);
+
+ curve = dpp_get_curve_ike_group(crypto_ec_key_group(key->csign));
if (!curve) {
wpa_printf(MSG_INFO, "DPP: Unsupported group in c-sign-key");
return -1;
}
- eckey_pp = EVP_PKEY_get0_EC_KEY(key->pp_key);
- if (!eckey_pp)
+
+ curve_pp = dpp_get_curve_ike_group(crypto_ec_key_group(key->pp_key));
+ if (!curve_pp) {
+ wpa_printf(MSG_INFO, "DPP: Unsupported group in ppKey");
return -1;
- group_pp = EC_KEY_get0_group(eckey_pp);
- if (!group_pp)
- return -1;
- if (EC_GROUP_get_curve_name(group) !=
- EC_GROUP_get_curve_name(group_pp)) {
+ }
+
+ if (curve != curve_pp) {
wpa_printf(MSG_INFO,
"DPP: Mismatch in c-sign-key and ppKey groups");
return -1;
diff --git a/src/common/dpp.h b/src/common/dpp.h
index 6e397c3..2f85ebd 100644
--- a/src/common/dpp.h
+++ b/src/common/dpp.h
@@ -2,6 +2,7 @@
* DPP functionality shared between hostapd and wpa_supplicant
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -11,13 +12,11 @@
#define DPP_H
#ifdef CONFIG_DPP
-#include <openssl/x509.h>
-
#include "utils/list.h"
#include "common/wpa_common.h"
#include "crypto/sha256.h"
+#include "crypto/crypto.h"
-struct crypto_ecdh;
struct hostapd_ip_addr;
struct dpp_global;
struct json_token;
@@ -27,7 +26,9 @@
#define DPP_VERSION (dpp_version_override)
extern int dpp_version_override;
#else /* CONFIG_TESTING_OPTIONS */
-#ifdef CONFIG_DPP2
+#ifdef CONFIG_DPP3
+#define DPP_VERSION 3
+#elif defined(CONFIG_DPP2)
#define DPP_VERSION 2
#else
#define DPP_VERSION 1
@@ -43,7 +44,7 @@
DPP_PA_AUTHENTICATION_CONF = 2,
DPP_PA_PEER_DISCOVERY_REQ = 5,
DPP_PA_PEER_DISCOVERY_RESP = 6,
- DPP_PA_PKEX_EXCHANGE_REQ = 7,
+ DPP_PA_PKEX_V1_EXCHANGE_REQ = 7,
DPP_PA_PKEX_EXCHANGE_RESP = 8,
DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9,
DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10,
@@ -54,6 +55,7 @@
DPP_PA_RECONFIG_AUTH_REQ = 15,
DPP_PA_RECONFIG_AUTH_RESP = 16,
DPP_PA_RECONFIG_AUTH_CONF = 17,
+ DPP_PA_PKEX_EXCHANGE_REQ = 18,
};
enum dpp_attribute_id {
@@ -157,7 +159,7 @@
bool channels_listed;
u8 version;
int own;
- EVP_PKEY *pubkey;
+ struct crypto_ec_key *pubkey;
u8 pubkey_hash[SHA256_MAC_LEN];
u8 pubkey_hash_chirp[SHA256_MAC_LEN];
const struct dpp_curve_params *curve;
@@ -175,23 +177,26 @@
unsigned int initiator:1;
unsigned int exchange_done:1;
unsigned int failed:1;
+ unsigned int v2:1;
+ unsigned int forced_ver:1;
struct dpp_bootstrap_info *own_bi;
u8 own_mac[ETH_ALEN];
u8 peer_mac[ETH_ALEN];
char *identifier;
char *code;
- EVP_PKEY *x;
- EVP_PKEY *y;
+ struct crypto_ec_key *x;
+ struct crypto_ec_key *y;
u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
u8 z[DPP_MAX_HASH_LEN];
- EVP_PKEY *peer_bootstrap_key;
+ struct crypto_ec_key *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;
+ u8 peer_version;
};
enum dpp_akm {
@@ -234,8 +239,8 @@
struct dpp_asymmetric_key {
struct dpp_asymmetric_key *next;
- EVP_PKEY *csign;
- EVP_PKEY *pp_key;
+ struct crypto_ec_key *csign;
+ struct crypto_ec_key *pp_key;
char *config_template;
char *connector_template;
};
@@ -267,9 +272,9 @@
u8 i_capab;
u8 r_capab;
enum dpp_netrole e_netrole;
- EVP_PKEY *own_protocol_key;
- EVP_PKEY *peer_protocol_key;
- EVP_PKEY *reconfig_old_protocol_key;
+ struct crypto_ec_key *own_protocol_key;
+ struct crypto_ec_key *peer_protocol_key;
+ struct crypto_ec_key *reconfig_old_protocol_key;
struct wpabuf *req_msg;
struct wpabuf *resp_msg;
struct wpabuf *reconfig_req_msg;
@@ -348,8 +353,13 @@
char *trusted_eap_server_name;
struct wpabuf *cacert;
struct wpabuf *certbag;
- void *cert_resp_ctx;
+ void *config_resp_ctx;
void *gas_server_ctx;
+ bool use_config_query;
+ bool waiting_config;
+ char *e_name;
+ char *e_mud_url;
+ int *e_band_support;
#ifdef CONFIG_TESTING_OPTIONS
char *config_obj_override;
char *discovery_override;
@@ -364,19 +374,20 @@
struct dl_list list;
unsigned int id;
int own;
- EVP_PKEY *csign;
+ struct crypto_ec_key *csign;
u8 kid_hash[SHA256_MAC_LEN];
char *kid;
const struct dpp_curve_params *curve;
char *connector; /* own Connector for reconfiguration */
- EVP_PKEY *connector_key;
- EVP_PKEY *pp_key;
+ struct crypto_ec_key *connector_key;
+ struct crypto_ec_key *pp_key;
};
struct dpp_introduction {
u8 pmkid[PMKID_LEN];
u8 pmk[PMK_LEN_MAX];
size_t pmk_len;
+ int peer_version;
};
struct dpp_relay_config {
@@ -400,6 +411,7 @@
void *msg_ctx;
void *cb_ctx;
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+ bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
};
#ifdef CONFIG_TESTING_OPTIONS
@@ -496,6 +508,10 @@
DPP_TEST_STOP_AT_AUTH_CONF = 89,
DPP_TEST_STOP_AT_CONF_REQ = 90,
DPP_TEST_REJECT_CONFIG = 91,
+ DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ = 92,
+ DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP = 93,
+ DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ = 94,
+ DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP = 95,
};
extern enum dpp_test_behavior dpp_test;
@@ -517,6 +533,7 @@
int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi,
struct dpp_bootstrap_info *peer_bi);
+const char * dpp_netrole_str(enum dpp_netrole netrole);
struct dpp_authentication *
dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx);
struct hostapd_hw_modes;
@@ -546,6 +563,9 @@
const u8 *attr_start, size_t attr_len);
int dpp_notify_new_qr_code(struct dpp_authentication *auth,
struct dpp_bootstrap_info *peer_bi);
+void dpp_controller_pkex_add(struct dpp_global *dpp,
+ struct dpp_bootstrap_info *bi,
+ const char *code, const char *identifier);
struct dpp_configuration * dpp_configuration_alloc(const char *type);
int dpp_akm_psk(enum dpp_akm akm);
int dpp_akm_sae(enum dpp_akm akm);
@@ -598,17 +618,18 @@
const u8 *csign_key, size_t csign_key_len,
const u8 *peer_connector, size_t peer_connector_len,
os_time_t *expiry);
+int dpp_get_connector_version(const char *connector);
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
const u8 *own_mac,
- const char *identifier,
- const char *code);
+ const char *identifier, const char *code,
+ bool v2);
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 *buf, size_t len, bool v2);
struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
const u8 *peer_mac,
const u8 *buf, size_t len);
@@ -636,7 +657,6 @@
struct wpabuf * dpp_build_csr(struct dpp_authentication *auth,
const char *name);
-struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7);
int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr);
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
@@ -672,22 +692,43 @@
struct dpp_relay_config *config);
int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
const u8 *buf, size_t len, unsigned int freq,
- const u8 *i_bootstrap, const u8 *r_bootstrap);
+ const u8 *i_bootstrap, const u8 *r_bootstrap,
+ void *cb_ctx);
int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
size_t data_len);
int dpp_controller_start(struct dpp_global *dpp,
struct dpp_controller_config *config);
void dpp_controller_stop(struct dpp_global *dpp);
+void dpp_controller_stop_for_ctx(struct dpp_global *dpp, void *cb_ctx);
struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp,
unsigned int id);
void dpp_controller_new_qr_code(struct dpp_global *dpp,
struct dpp_bootstrap_info *bi);
+int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex,
+ const struct hostapd_ip_addr *addr, int port,
+ void *msg_ctx, void *cb_ctx,
+ int (*pkex_done)(void *ctx, void *conn,
+ struct dpp_bootstrap_info *bi));
int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
const struct hostapd_ip_addr *addr, int port,
const char *name, enum dpp_netrole netrole, void *msg_ctx,
void *cb_ctx,
int (*process_conf_obj)(void *ctx,
- struct dpp_authentication *auth));
+ struct dpp_authentication *auth),
+ bool (*tcp_msg_sent)(void *ctx,
+ struct dpp_authentication *auth));
+int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
+ struct dpp_authentication *auth, const char *name,
+ enum dpp_netrole netrole,
+ int (*process_conf_obj)(void *ctx,
+ struct dpp_authentication *auth),
+ bool (*tcp_msg_sent)(void *ctx,
+ struct dpp_authentication *auth));
+bool dpp_tcp_conn_status_requested(struct dpp_global *dpp);
+void dpp_tcp_send_conn_status(struct dpp_global *dpp,
+ enum dpp_status_error result,
+ const u8 *ssid, size_t ssid_len,
+ const char *channel_list);
struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi);
void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
diff --git a/src/common/dpp_auth.c b/src/common/dpp_auth.c
index 0cabd64..f81f1ee 100644
--- a/src/common/dpp_auth.c
+++ b/src/common/dpp_auth.c
@@ -456,7 +456,7 @@
#endif /* CONFIG_TESTING_OPTIONS */
wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
- EVP_PKEY_free(auth->own_protocol_key);
+ crypto_ec_key_deinit(auth->own_protocol_key);
#ifdef CONFIG_TESTING_OPTIONS
if (dpp_protocol_key_override_len) {
const struct dpp_curve_params *tmp_curve;
@@ -475,7 +475,7 @@
if (!auth->own_protocol_key)
goto fail;
- pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+ pr = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
if (!pr)
goto fail;
@@ -671,8 +671,7 @@
unsigned int freq, const u8 *hdr, const u8 *attr_start,
size_t attr_len)
{
- EVP_PKEY *pi = NULL;
- EVP_PKEY_CTX *ctx = NULL;
+ struct crypto_ec_key *pi = NULL;
size_t secret_len;
const u8 *addr[2];
size_t len[2];
@@ -928,8 +927,7 @@
return auth;
fail:
bin_clear_free(unwrapped, unwrapped_len);
- EVP_PKEY_free(pi);
- EVP_PKEY_CTX_free(ctx);
+ crypto_ec_key_deinit(pi);
dpp_auth_deinit(auth);
return NULL;
}
@@ -1235,7 +1233,7 @@
if (!auth->own_protocol_key)
goto fail;
- pi = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+ pi = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
if (!pi)
goto fail;
@@ -1405,7 +1403,7 @@
dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
const u8 *attr_start, size_t attr_len)
{
- EVP_PKEY *pr;
+ struct crypto_ec_key *pr;
size_t secret_len;
const u8 *addr[2];
size_t len[2];
@@ -1567,7 +1565,7 @@
dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
goto fail;
}
- EVP_PKEY_free(auth->peer_protocol_key);
+ crypto_ec_key_deinit(auth->peer_protocol_key);
auth->peer_protocol_key = pr;
pr = NULL;
@@ -1737,7 +1735,7 @@
fail:
bin_clear_free(unwrapped, unwrapped_len);
bin_clear_free(unwrapped2, unwrapped2_len);
- EVP_PKEY_free(pr);
+ crypto_ec_key_deinit(pr);
return NULL;
}
diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c
index 3b81f09..fb3f776 100644
--- a/src/common/dpp_backup.c
+++ b/src/common/dpp_backup.c
@@ -7,8 +7,6 @@
*/
#include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
#include "utils/common.h"
#include "crypto/aes.h"
@@ -19,28 +17,13 @@
#ifdef CONFIG_DPP2
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- (defined(LIBRESSL_VERSION_NUMBER) && \
- LIBRESSL_VERSION_NUMBER < 0x20700000L)
-/* Compatibility wrappers for older versions. */
-
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
-{
- if (pkey->type != EVP_PKEY_EC)
- return NULL;
- return pkey->pkey.ec;
-}
-
-#endif
-
-
void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key)
{
while (key) {
struct dpp_asymmetric_key *next = key->next;
- EVP_PKEY_free(key->csign);
- EVP_PKEY_free(key->pp_key);
+ crypto_ec_key_deinit(key->csign);
+ crypto_ec_key_deinit(key->pp_key);
str_clear_free(key->config_template);
str_clear_free(key->connector_template);
os_free(key);
@@ -56,23 +39,13 @@
/* TODO: proper template values */
const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}";
const char *connector_template = NULL;
- EC_KEY *eckey;
- unsigned char *der = NULL;
- int der_len;
if (!conf->pp_key)
return NULL;
- eckey = EVP_PKEY_get0_EC_KEY(conf->pp_key);
- if (!eckey)
- return NULL;
- EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
- der_len = i2d_ECPrivateKey(eckey, &der);
- if (der_len > 0)
- priv_key = wpabuf_alloc_copy(der, der_len);
- OPENSSL_free(der);
+ priv_key = crypto_ec_key_get_ecprivate_key(conf->pp_key, false);
if (!priv_key)
- goto fail;
+ return NULL;
len = 100 + os_strlen(conf_template);
if (connector_template)
@@ -178,20 +151,11 @@
static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth)
{
struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL;
- EC_KEY *eckey;
- unsigned char *der = NULL;
- int der_len;
- eckey = EVP_PKEY_get0_EC_KEY(auth->conf->csign);
- if (!eckey)
+ priv_key = crypto_ec_key_get_ecprivate_key(auth->conf->csign, false);
+ if (!priv_key)
return NULL;
- EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
- der_len = i2d_ECPrivateKey(eckey, &der);
- if (der_len > 0)
- priv_key = wpabuf_alloc_copy(der, der_len);
- OPENSSL_free(der);
-
alg = dpp_build_key_alg(auth->conf->curve);
/* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */
@@ -592,11 +556,9 @@
* Shall always use the pwri CHOICE.
*/
- if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 3) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected CHOICE [3] (pwri) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+ !asn1_is_cs_tag(&hdr, 3)) {
+ asn1_unexpected(&hdr, "DPP: Expected CHOICE [3] (pwri)");
return -1;
}
wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo",
@@ -629,11 +591,10 @@
wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version",
pos, end - pos);
- if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected keyDerivationAlgorithm [0] - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+ !asn1_is_cs_tag(&hdr, 0)) {
+ asn1_unexpected(&hdr,
+ "DPP: Expected keyDerivationAlgorithm [0]");
return -1;
}
pos = hdr.payload;
@@ -672,11 +633,9 @@
pos = hdr.payload;
if (asn1_get_next(pos, e_end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL ||
- hdr.tag != ASN1_TAG_OCTETSTRING) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected OCTETSTRING (salt.specified) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ !asn1_is_octetstring(&hdr)) {
+ asn1_unexpected(&hdr,
+ "DPP: Expected OCTETSTRING (salt.specified)");
return -1;
}
wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified",
@@ -752,11 +711,9 @@
* EncryptedKey ::= OCTET STRING
*/
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL ||
- hdr.tag != ASN1_TAG_OCTETSTRING) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected OCTETSTRING (pwri.encryptedKey) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ !asn1_is_octetstring(&hdr)) {
+ asn1_unexpected(&hdr,
+ "DPP: Expected OCTETSTRING (pwri.encryptedKey)");
return -1;
}
wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey",
@@ -825,11 +782,10 @@
/* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
* EncryptedContent ::= OCTET STRING */
- if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected [0] IMPLICIT (EncryptedContent) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.constructed ||
+ !asn1_is_cs_tag(&hdr, 0)) {
+ asn1_unexpected(&hdr,
+ "DPP: Expected [0] IMPLICIT (EncryptedContent)");
return -1;
}
wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent",
@@ -884,11 +840,9 @@
return -1;
}
- if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected SET (RecipientInfos) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
+ asn1_unexpected(&hdr,
+ "DPP: Expected SET (RecipientInfos)");
return -1;
}
@@ -910,7 +864,6 @@
struct asn1_oid oid;
char txt[80];
struct dpp_asymmetric_key *key;
- EC_KEY *eckey;
wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len);
@@ -977,28 +930,17 @@
* (Contains DER encoding of ECPrivateKey)
*/
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL ||
- hdr.tag != ASN1_TAG_OCTETSTRING) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ !asn1_is_octetstring(&hdr)) {
+ asn1_unexpected(&hdr,
+ "DPP: Expected OCTETSTRING (PrivateKey)");
goto fail;
}
wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey",
hdr.payload, hdr.length);
pos = hdr.payload + hdr.length;
- eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length);
- if (!eckey) {
- wpa_printf(MSG_INFO,
- "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ key->csign = crypto_ec_key_parse_priv(hdr.payload, hdr.length);
+ if (!key->csign)
goto fail;
- }
- key->csign = EVP_PKEY_new();
- if (!key->csign || EVP_PKEY_assign_EC_KEY(key->csign, eckey) != 1) {
- EC_KEY_free(eckey);
- goto fail;
- }
if (wpa_debug_show_keys)
dpp_debug_print_key("DPP: Received c-sign-key", key->csign);
@@ -1007,11 +949,9 @@
*
* Exactly one instance of type Attribute in OneAsymmetricKey.
*/
- if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected [0] Attributes - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+ !asn1_is_cs_tag(&hdr, 0)) {
+ asn1_unexpected(&hdr, "DPP: Expected [0] Attributes");
goto fail;
}
wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes",
@@ -1025,11 +965,8 @@
pos = hdr.payload;
end = hdr.payload + hdr.length;
- if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected SET (Attributes) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
+ asn1_unexpected(&hdr, "DPP: Expected SET (Attributes)");
goto fail;
}
if (hdr.payload + hdr.length < end) {
@@ -1075,11 +1012,8 @@
goto fail;
}
- if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected SET (Attribute) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
+ asn1_unexpected(&hdr, "DPP: Expected SET (Attribute)");
goto fail;
}
pos = hdr.payload;
@@ -1109,38 +1043,24 @@
* (Contains DER encoding of ECPrivateKey)
*/
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL ||
- hdr.tag != ASN1_TAG_OCTETSTRING) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ !asn1_is_octetstring(&hdr)) {
+ asn1_unexpected(&hdr, "DPP: Expected OCTETSTRING (PrivateKey)");
goto fail;
}
wpa_hexdump_key(MSG_MSGDUMP, "DPP: privacyProtectionKey",
hdr.payload, hdr.length);
pos = hdr.payload + hdr.length;
- eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length);
- if (!eckey) {
- wpa_printf(MSG_INFO,
- "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ key->pp_key = crypto_ec_key_parse_priv(hdr.payload, hdr.length);
+ if (!key->pp_key)
goto fail;
- }
- key->pp_key = EVP_PKEY_new();
- if (!key->pp_key || EVP_PKEY_assign_EC_KEY(key->pp_key, eckey) != 1) {
- EC_KEY_free(eckey);
- goto fail;
- }
if (wpa_debug_show_keys)
dpp_debug_print_key("DPP: Received privacyProtectionKey",
key->pp_key);
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL ||
- hdr.tag != ASN1_TAG_UTF8STRING) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected UTF8STRING (configurationTemplate) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ !asn1_is_utf8string(&hdr)) {
+ asn1_unexpected(&hdr,
+ "DPP: Expected UTF8STRING (configurationTemplate)");
goto fail;
}
wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate",
@@ -1154,11 +1074,9 @@
if (pos < end) {
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
- hdr.class != ASN1_CLASS_UNIVERSAL ||
- hdr.tag != ASN1_TAG_UTF8STRING) {
- wpa_printf(MSG_DEBUG,
- "DPP: Expected UTF8STRING (connectorTemplate) - found class %d tag 0x%x",
- hdr.class, hdr.tag);
+ !asn1_is_utf8string(&hdr)) {
+ asn1_unexpected(&hdr,
+ "DPP: Expected UTF8STRING (connectorTemplate)");
goto fail;
}
wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate",
diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c
index c75fc78..4fac7de 100644
--- a/src/common/dpp_crypto.c
+++ b/src/common/dpp_crypto.c
@@ -8,11 +8,6 @@
*/
#include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/pem.h>
#include "utils/common.h"
#include "utils/base64.h"
@@ -22,42 +17,11 @@
#include "crypto/random.h"
#include "crypto/sha384.h"
#include "crypto/sha512.h"
+#include "tls/asn1.h"
#include "dpp.h"
#include "dpp_i.h"
-#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)
-{
- sig->r = r;
- sig->s = s;
- return 1;
-}
-
-
-static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
- const BIGNUM **ps)
-{
- if (pr)
- *pr = sig->r;
- if (ps)
- *ps = sig->s;
-}
-
-
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
-{
- if (pkey->type != EVP_PKEY_EC)
- return NULL;
- return pkey->pkey.ec;
-}
-
-#endif
-
static const struct dpp_curve_params dpp_curves[] = {
/* The mandatory to support and the default NIST P-256 curve needs to
* be the first entry on this list. */
@@ -101,36 +65,6 @@
}
-static const struct dpp_curve_params *
-dpp_get_curve_oid(const ASN1_OBJECT *poid)
-{
- ASN1_OBJECT *oid;
- int i;
-
- for (i = 0; dpp_curves[i].name; i++) {
- oid = OBJ_txt2obj(dpp_curves[i].name, 0);
- if (oid && OBJ_cmp(poid, oid) == 0)
- return &dpp_curves[i];
- }
- return NULL;
-}
-
-
-const struct dpp_curve_params * dpp_get_curve_nid(int nid)
-{
- int i, tmp;
-
- if (!nid)
- return NULL;
- for (i = 0; dpp_curves[i].name; i++) {
- tmp = OBJ_txt2nid(dpp_curves[i].name);
- if (tmp == nid)
- return &dpp_curves[i];
- }
- return NULL;
-}
-
-
const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group)
{
int i;
@@ -143,90 +77,22 @@
}
-void dpp_debug_print_point(const char *title, const EC_GROUP *group,
- const EC_POINT *point)
+void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
{
- BIGNUM *x, *y;
- BN_CTX *ctx;
- char *x_str = NULL, *y_str = NULL;
+ struct wpabuf *der = NULL;
- if (!wpa_debug_show_keys)
- return;
+ crypto_ec_key_debug_print(key, title);
- 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);
-}
-
-
-void dpp_debug_print_key(const char *title, EVP_PKEY *key)
-{
- EC_KEY *eckey;
- BIO *out;
- size_t rlen;
- char *txt;
- int res;
- unsigned char *der = NULL;
- int der_len;
- const EC_GROUP *group;
- const EC_POINT *point;
-
- out = BIO_new(BIO_s_mem());
- if (!out)
- return;
-
- EVP_PKEY_print_private(out, key, 0, NULL);
- rlen = BIO_ctrl_pending(out);
- txt = os_malloc(rlen + 1);
- if (txt) {
- res = BIO_read(out, txt, rlen);
- if (res > 0) {
- txt[res] = '\0';
- wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
- }
- os_free(txt);
- }
- BIO_free(out);
-
- eckey = EVP_PKEY_get1_EC_KEY(key);
- if (!eckey)
- return;
-
- group = EC_KEY_get0_group(eckey);
- point = EC_KEY_get0_public_key(eckey);
- if (group && point)
- dpp_debug_print_point(title, group, point);
-
- der_len = i2d_ECPrivateKey(eckey, &der);
- if (der_len > 0)
- wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len);
- OPENSSL_free(der);
- if (der_len <= 0) {
- der = NULL;
- der_len = i2d_EC_PUBKEY(eckey, &der);
- if (der_len > 0)
- wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
- OPENSSL_free(der);
+ der = crypto_ec_key_get_ecprivate_key(key, true);
+ if (der) {
+ wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der);
+ } else {
+ der = crypto_ec_key_get_subject_public_key(key);
+ if (der)
+ wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der);
}
- EC_KEY_free(eckey);
+ wpabuf_clear_free(der);
}
@@ -363,336 +229,65 @@
#endif /* CONFIG_DPP2 */
-int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len)
+struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key,
+ const u8 *buf, 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;
-}
-
-
-struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix)
-{
- int len, res;
- EC_KEY *eckey;
- struct wpabuf *buf;
- unsigned char *pos;
-
- eckey = EVP_PKEY_get1_EC_KEY(pkey);
- if (!eckey)
- return NULL;
- EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
- len = i2o_ECPublicKey(eckey, NULL);
- if (len <= 0) {
- wpa_printf(MSG_ERROR,
- "DDP: Failed to determine public key encoding length");
- EC_KEY_free(eckey);
- return NULL;
- }
-
- buf = wpabuf_alloc(len);
- if (!buf) {
- EC_KEY_free(eckey);
- return NULL;
- }
-
- pos = wpabuf_put(buf, len);
- res = i2o_ECPublicKey(eckey, &pos);
- EC_KEY_free(eckey);
- if (res != len) {
- wpa_printf(MSG_ERROR,
- "DDP: Failed to encode public key (res=%d/%d)",
- res, len);
- wpabuf_free(buf);
- return NULL;
- }
-
- if (!prefix) {
- /* Remove 0x04 prefix to match DPP definition */
- pos = wpabuf_mhead(buf);
- os_memmove(pos, pos + 1, len - 1);
- buf->used--;
- }
-
- return buf;
-}
-
-
-EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
- const u8 *buf_x, const u8 *buf_y,
- size_t len)
-{
- EC_KEY *eckey = NULL;
- BN_CTX *ctx;
- EC_POINT *point = NULL;
- BIGNUM *x = NULL, *y = NULL;
- EVP_PKEY *pkey = NULL;
-
- ctx = BN_CTX_new();
- if (!ctx) {
- wpa_printf(MSG_ERROR, "DPP: Out of memory");
- return NULL;
- }
-
- point = EC_POINT_new(group);
- x = BN_bin2bn(buf_x, len, NULL);
- y = BN_bin2bn(buf_y, len, NULL);
- if (!point || !x || !y) {
- wpa_printf(MSG_ERROR, "DPP: Out of memory");
- goto fail;
- }
-
- if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
- wpa_printf(MSG_ERROR,
- "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
-
- if (!EC_POINT_is_on_curve(group, point, ctx) ||
- EC_POINT_is_at_infinity(group, point)) {
- wpa_printf(MSG_ERROR, "DPP: Invalid point");
- goto fail;
- }
- dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point);
-
- eckey = EC_KEY_new();
- if (!eckey ||
- EC_KEY_set_group(eckey, group) != 1 ||
- EC_KEY_set_public_key(eckey, point) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to set EC_KEY: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
-
- pkey = EVP_PKEY_new();
- if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
- wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
- goto fail;
- }
-
-out:
- BN_free(x);
- BN_free(y);
- EC_KEY_free(eckey);
- EC_POINT_free(point);
- BN_CTX_free(ctx);
- return pkey;
-fail:
- EVP_PKEY_free(pkey);
- pkey = NULL;
- goto out;
-}
-
-
-EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len)
-{
- const EC_KEY *eckey;
- const EC_GROUP *group;
- EVP_PKEY *pkey = NULL;
+ int ike_group = crypto_ec_key_group(group_key);
if (len & 1)
return NULL;
- eckey = EVP_PKEY_get0_EC_KEY(group_key);
- if (!eckey) {
- wpa_printf(MSG_ERROR,
- "DPP: Could not get EC_KEY from group_key");
+ if (ike_group < 0) {
+ wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
return NULL;
}
- group = EC_KEY_get0_group(eckey);
- if (group)
- pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2,
- len / 2);
- else
- wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
-
- return pkey;
+ return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2);
}
-EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
+struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
{
- EVP_PKEY_CTX *kctx = NULL;
- EC_KEY *ec_params = NULL;
- EVP_PKEY *params = NULL, *key = NULL;
- int nid;
+ struct crypto_ec_key *key;
wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
- nid = OBJ_txt2nid(curve->name);
- if (nid == NID_undef) {
- wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name);
- return NULL;
- }
+ key = crypto_ec_key_gen(curve->ike_group);
+ if (key && wpa_debug_show_keys)
+ dpp_debug_print_key("Own generated key", key);
- ec_params = EC_KEY_new_by_curve_name(nid);
- if (!ec_params) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to generate EC_KEY parameters");
- goto fail;
- }
- EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
- params = EVP_PKEY_new();
- if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to generate EVP_PKEY parameters");
- goto fail;
- }
-
- kctx = EVP_PKEY_CTX_new(params, NULL);
- if (!kctx ||
- EVP_PKEY_keygen_init(kctx) != 1 ||
- EVP_PKEY_keygen(kctx, &key) != 1) {
- wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key");
- key = NULL;
- goto fail;
- }
-
- if (wpa_debug_show_keys)
- dpp_debug_print_key("Own generated key", key);
-
-fail:
- EC_KEY_free(ec_params);
- EVP_PKEY_free(params);
- EVP_PKEY_CTX_free(kctx);
return key;
}
-EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
- const u8 *privkey, size_t privkey_len)
+struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
+ const u8 *privkey, size_t privkey_len)
{
- EVP_PKEY *pkey;
- EC_KEY *eckey;
- const EC_GROUP *group;
- int nid;
+ struct crypto_ec_key *key;
+ int group;
- pkey = EVP_PKEY_new();
- if (!pkey)
- return NULL;
- eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len);
- if (!eckey) {
- wpa_printf(MSG_INFO,
- "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- EVP_PKEY_free(pkey);
+ key = crypto_ec_key_parse_priv(privkey, privkey_len);
+ if (!key) {
+ wpa_printf(MSG_INFO, "DPP: Failed to parse private key");
return NULL;
}
- group = EC_KEY_get0_group(eckey);
- if (!group) {
- EC_KEY_free(eckey);
- EVP_PKEY_free(pkey);
+
+ group = crypto_ec_key_group(key);
+ if (group < 0) {
+ crypto_ec_key_deinit(key);
return NULL;
}
- nid = EC_GROUP_get_curve_name(group);
- *curve = dpp_get_curve_nid(nid);
+
+ *curve = dpp_get_curve_ike_group(group);
if (!*curve) {
wpa_printf(MSG_INFO,
- "DPP: Unsupported curve (nid=%d) in pre-assigned key",
- nid);
- EC_KEY_free(eckey);
- EVP_PKEY_free(pkey);
+ "DPP: Unsupported curve (group=%d) in pre-assigned key",
+ group);
+ crypto_ec_key_deinit(key);
return NULL;
}
- if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
- EC_KEY_free(eckey);
- EVP_PKEY_free(pkey);
- return NULL;
- }
- return pkey;
-}
-
-
-typedef struct {
- /* AlgorithmIdentifier ecPublicKey with optional parameters present
- * as an OID identifying the curve */
- X509_ALGOR *alg;
- /* Compressed format public key per ANSI X9.63 */
- ASN1_BIT_STRING *pub_key;
-} DPP_BOOTSTRAPPING_KEY;
-
-ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = {
- ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR),
- ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING)
-} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY);
-
-IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY);
-
-
-static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key)
-{
- unsigned char *der = NULL;
- int der_len;
- const EC_KEY *eckey;
- struct wpabuf *ret = NULL;
- size_t len;
- const EC_GROUP *group;
- const EC_POINT *point;
- BN_CTX *ctx;
- DPP_BOOTSTRAPPING_KEY *bootstrap = NULL;
- int nid;
-
- ctx = BN_CTX_new();
- eckey = EVP_PKEY_get0_EC_KEY(key);
- if (!ctx || !eckey)
- goto fail;
-
- group = EC_KEY_get0_group(eckey);
- point = EC_KEY_get0_public_key(eckey);
- if (!group || !point)
- goto fail;
- dpp_debug_print_point("DPP: bootstrap public key", group, point);
- nid = EC_GROUP_get_curve_name(group);
-
- bootstrap = DPP_BOOTSTRAPPING_KEY_new();
- if (!bootstrap ||
- X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC),
- V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1)
- goto fail;
-
- len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
- NULL, 0, ctx);
- if (len == 0)
- goto fail;
-
- der = OPENSSL_malloc(len);
- if (!der)
- goto fail;
- len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
- der, len, ctx);
-
- OPENSSL_free(bootstrap->pub_key->data);
- bootstrap->pub_key->data = der;
- der = NULL;
- bootstrap->pub_key->length = len;
- /* No unused bits */
- bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
- bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
- der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der);
- if (der_len <= 0) {
- wpa_printf(MSG_ERROR,
- "DDP: Failed to build DER encoded public key");
- goto fail;
- }
-
- ret = wpabuf_alloc_copy(der, der_len);
-fail:
- DPP_BOOTSTRAPPING_KEY_free(bootstrap);
- OPENSSL_free(der);
- BN_CTX_free(ctx);
- return ret;
+ return key;
}
@@ -701,7 +296,7 @@
struct wpabuf *der;
int res;
- der = dpp_bootstrap_key_der(bi->pubkey);
+ der = crypto_ec_key_get_subject_public_key(bi->pubkey);
if (!der)
return -1;
wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
@@ -736,7 +331,7 @@
goto fail;
bi->own = 1;
- der = dpp_bootstrap_key_der(bi->pubkey);
+ der = crypto_ec_key_get_subject_public_key(bi->pubkey);
if (!der)
goto fail;
wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
@@ -883,86 +478,48 @@
}
-int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len)
+int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
+ u8 *secret, size_t *secret_len)
{
- EVP_PKEY_CTX *ctx;
+ struct crypto_ecdh *ecdh;
+ struct wpabuf *peer_pub, *secret_buf = NULL;
int ret = -1;
- ERR_clear_error();
*secret_len = 0;
- ctx = EVP_PKEY_CTX_new(own, NULL);
- if (!ctx) {
- wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own);
+ if (!ecdh) {
+ wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed");
return -1;
}
- if (EVP_PKEY_derive_init(ctx) != 1) {
- wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
-
- if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) {
+ peer_pub = crypto_ec_key_get_pubkey_point(peer, 0);
+ if (!peer_pub) {
wpa_printf(MSG_ERROR,
- "DPP: EVP_PKEY_derive_set_peet failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ "DPP: crypto_ec_key_get_pubkey_point() failed");
goto fail;
}
- if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) {
- wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub),
+ wpabuf_len(peer_pub));
+ if (!secret_buf) {
+ wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed");
goto fail;
}
- if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
- u8 buf[200];
- int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG;
-
- /* It looks like OpenSSL can return unexpectedly large buffer
- * need for shared secret from EVP_PKEY_derive(NULL) in some
- * cases. For example, group 19 has shown cases where secret_len
- * is set to 72 even though the actual length ends up being
- * updated to 32 when EVP_PKEY_derive() is called with a buffer
- * for the value. Work around this by trying to fetch the value
- * and continue if it is within supported range even when the
- * initial buffer need is claimed to be larger. */
- wpa_printf(level,
- "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
- (int) *secret_len);
- if (*secret_len > 200)
- goto fail;
- if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) {
- wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
- wpa_printf(MSG_ERROR,
- "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
- (int) *secret_len);
- goto fail;
- }
- wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change",
- buf, *secret_len);
- os_memcpy(secret, buf, *secret_len);
- forced_memzero(buf, sizeof(buf));
- goto done;
- }
-
- if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) {
- wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) {
+ wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected");
goto fail;
}
-done:
+ *secret_len = wpabuf_len(secret_buf);
+ os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf));
ret = 0;
fail:
- EVP_PKEY_CTX_free(ctx);
+ wpabuf_clear_free(secret_buf);
+ wpabuf_free(peer_pub);
+ crypto_ecdh_deinit(ecdh);
return ret;
}
@@ -996,118 +553,32 @@
int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
const u8 *data, size_t data_len)
{
- EVP_PKEY *pkey;
- const unsigned char *p;
- int res;
- X509_PUBKEY *pub = NULL;
- ASN1_OBJECT *ppkalg;
- const unsigned char *pk;
- int ppklen;
- X509_ALGOR *pa;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- (defined(LIBRESSL_VERSION_NUMBER) && \
- LIBRESSL_VERSION_NUMBER < 0x20800000L)
- ASN1_OBJECT *pa_oid;
-#else
- const ASN1_OBJECT *pa_oid;
-#endif
- const void *pval;
- int ptype;
- const ASN1_OBJECT *poid;
- char buf[100];
+ struct crypto_ec_key *key;
if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) {
wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
return -1;
}
- /* DER encoded ASN.1 SubjectPublicKeyInfo
- *
- * SubjectPublicKeyInfo ::= SEQUENCE {
- * algorithm AlgorithmIdentifier,
- * subjectPublicKey BIT STRING }
- *
- * AlgorithmIdentifier ::= SEQUENCE {
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL }
- *
- * subjectPublicKey = compressed format public key per ANSI X9.63
- * algorithm = ecPublicKey (1.2.840.10045.2.1)
- * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
- * prime256v1 (1.2.840.10045.3.1.7)
- */
-
- p = data;
- pkey = d2i_PUBKEY(NULL, &p, data_len);
-
- if (!pkey) {
+ key = crypto_ec_key_parse_pub(data, data_len);
+ if (!key) {
wpa_printf(MSG_DEBUG,
"DPP: Could not parse URI public-key SubjectPublicKeyInfo");
return -1;
}
- if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
- wpa_printf(MSG_DEBUG,
- "DPP: SubjectPublicKeyInfo does not describe an EC key");
- EVP_PKEY_free(pkey);
- return -1;
- }
-
- res = X509_PUBKEY_set(&pub, pkey);
- if (res != 1) {
- wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey");
- goto fail;
- }
-
- res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub);
- if (res != 1) {
- wpa_printf(MSG_DEBUG,
- "DPP: Could not extract SubjectPublicKeyInfo parameters");
- goto fail;
- }
- res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0);
- if (res < 0 || (size_t) res >= sizeof(buf)) {
- wpa_printf(MSG_DEBUG,
- "DPP: Could not extract SubjectPublicKeyInfo algorithm");
- goto fail;
- }
- wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf);
- if (os_strcmp(buf, "id-ecPublicKey") != 0) {
- wpa_printf(MSG_DEBUG,
- "DPP: Unsupported SubjectPublicKeyInfo algorithm");
- goto fail;
- }
-
- X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa);
- if (ptype != V_ASN1_OBJECT) {
- wpa_printf(MSG_DEBUG,
- "DPP: SubjectPublicKeyInfo parameters did not contain an OID");
- goto fail;
- }
- poid = pval;
- res = OBJ_obj2txt(buf, sizeof(buf), poid, 0);
- if (res < 0 || (size_t) res >= sizeof(buf)) {
- wpa_printf(MSG_DEBUG,
- "DPP: Could not extract SubjectPublicKeyInfo parameters OID");
- goto fail;
- }
- wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf);
- bi->curve = dpp_get_curve_oid(poid);
+ bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key));
if (!bi->curve) {
wpa_printf(MSG_DEBUG,
- "DPP: Unsupported SubjectPublicKeyInfo curve: %s",
- buf);
+ "DPP: Unsupported SubjectPublicKeyInfo curve: group %d",
+ crypto_ec_key_group(key));
goto fail;
}
- wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen);
-
- X509_PUBKEY_free(pub);
- bi->pubkey = pkey;
+ bi->pubkey = key;
return 0;
fail:
- X509_PUBKEY_free(pub);
- EVP_PKEY_free(pkey);
+ crypto_ec_key_deinit(key);
return -1;
}
@@ -1115,7 +586,7 @@
static struct wpabuf *
dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
const u8 *prot_hdr, u16 prot_hdr_len,
- const EVP_MD **ret_md)
+ int *hash_func)
{
struct json_token *root, *token;
struct wpabuf *kid = NULL;
@@ -1161,17 +632,16 @@
goto fail;
}
if (os_strcmp(token->string, "ES256") == 0 ||
- os_strcmp(token->string, "BS256") == 0)
- *ret_md = EVP_sha256();
- else if (os_strcmp(token->string, "ES384") == 0 ||
- os_strcmp(token->string, "BS384") == 0)
- *ret_md = EVP_sha384();
- else if (os_strcmp(token->string, "ES512") == 0 ||
- os_strcmp(token->string, "BS512") == 0)
- *ret_md = EVP_sha512();
- else
- *ret_md = NULL;
- if (!*ret_md) {
+ os_strcmp(token->string, "BS256") == 0) {
+ *hash_func = CRYPTO_HASH_ALG_SHA256;
+ } else if (os_strcmp(token->string, "ES384") == 0 ||
+ os_strcmp(token->string, "BS384") == 0) {
+ *hash_func = CRYPTO_HASH_ALG_SHA384;
+ } else if (os_strcmp(token->string, "ES512") == 0 ||
+ os_strcmp(token->string, "BS512") == 0) {
+ *hash_func = CRYPTO_HASH_ALG_SHA512;
+ } else {
+ *hash_func = -1;
wpa_printf(MSG_DEBUG,
"DPP: Unsupported JWS Protected Header alg=%s",
token->string);
@@ -1192,7 +662,8 @@
}
-static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash)
+static int dpp_check_pubkey_match(struct crypto_ec_key *pub,
+ struct wpabuf *r_hash)
{
struct wpabuf *uncomp;
int res;
@@ -1202,7 +673,7 @@
if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
return -1;
- uncomp = dpp_get_pubkey_point(pub, 1);
+ uncomp = crypto_ec_key_get_pubkey_point(pub, 1);
if (!uncomp)
return -1;
addr[0] = wpabuf_head(uncomp);
@@ -1226,33 +697,19 @@
enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info *info,
- EVP_PKEY *csign_pub, const char *connector)
+ struct crypto_ec_key *csign_pub,
+ const char *connector)
{
enum dpp_status_error ret = 255;
const char *pos, *end, *signed_start, *signed_end;
struct wpabuf *kid = NULL;
unsigned char *prot_hdr = NULL, *signature = NULL;
- size_t prot_hdr_len = 0, signature_len = 0;
- const EVP_MD *sign_md = NULL;
- unsigned char *der = NULL;
- int der_len;
- int res;
- EVP_MD_CTX *md_ctx = NULL;
- ECDSA_SIG *sig = NULL;
- BIGNUM *r = NULL, *s = NULL;
+ size_t prot_hdr_len = 0, signature_len = 0, signed_len;
+ int res, hash_func = -1;
const struct dpp_curve_params *curve;
- const EC_KEY *eckey;
- const EC_GROUP *group;
- int nid;
+ u8 *hash = NULL;
- eckey = EVP_PKEY_get0_EC_KEY(csign_pub);
- if (!eckey)
- goto fail;
- group = EC_KEY_get0_group(eckey);
- if (!group)
- goto fail;
- nid = EC_GROUP_get_curve_name(group);
- curve = dpp_get_curve_nid(nid);
+ curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub));
if (!curve)
goto fail;
wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
@@ -1275,7 +732,7 @@
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);
+ kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func);
if (!kid) {
ret = DPP_STATUS_INVALID_CONNECTOR;
goto fail;
@@ -1331,57 +788,45 @@
goto fail;
}
- /* JWS Signature encodes the signature (r,s) as two octet strings. Need
- * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
- r = BN_bin2bn(signature, signature_len / 2, NULL);
- s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL);
- sig = ECDSA_SIG_new();
- if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1)
- goto fail;
- r = NULL;
- s = NULL;
-
- der_len = i2d_ECDSA_SIG(sig, &der);
- if (der_len <= 0) {
- wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature");
- goto fail;
- }
- wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len);
- md_ctx = EVP_MD_CTX_create();
- if (!md_ctx)
+ hash = os_malloc(curve->hash_len);
+ if (!hash)
goto fail;
- ERR_clear_error();
- if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) {
- wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ signed_len = signed_end - signed_start + 1;
+ if (hash_func == CRYPTO_HASH_ALG_SHA256)
+ res = sha256_vector(1, (const u8 **) &signed_start, &signed_len,
+ hash);
+ else if (hash_func == CRYPTO_HASH_ALG_SHA384)
+ res = sha384_vector(1, (const u8 **) &signed_start, &signed_len,
+ hash);
+ else if (hash_func == CRYPTO_HASH_ALG_SHA512)
+ res = sha512_vector(1, (const u8 **) &signed_start, &signed_len,
+ hash);
+ else
goto fail;
- }
- if (EVP_DigestVerifyUpdate(md_ctx, signed_start,
- signed_end - signed_start + 1) != 1) {
- wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+
+ if (res)
goto fail;
- }
- res = EVP_DigestVerifyFinal(md_ctx, der, der_len);
+
+ res = crypto_ec_key_verify_signature_r_s(csign_pub,
+ hash, curve->hash_len,
+ signature, signature_len / 2,
+ signature + signature_len / 2,
+ signature_len / 2);
if (res != 1) {
wpa_printf(MSG_DEBUG,
- "DPP: EVP_DigestVerifyFinal failed (res=%d): %s",
- res, ERR_error_string(ERR_get_error(), NULL));
+ "DPP: signedConnector signature check failed (res=%d)",
+ res);
ret = DPP_STATUS_INVALID_CONNECTOR;
goto fail;
}
ret = DPP_STATUS_OK;
fail:
- EVP_MD_CTX_destroy(md_ctx);
+ os_free(hash);
os_free(prot_hdr);
wpabuf_free(kid);
os_free(signature);
- ECDSA_SIG_free(sig);
- BN_free(r);
- BN_free(s);
- OPENSSL_free(der);
return ret;
}
@@ -1391,13 +836,11 @@
const u8 *csign_key, size_t csign_key_len,
const u8 *peer_connector, size_t peer_connector_len)
{
- const unsigned char *p;
- EVP_PKEY *csign = NULL;
+ struct crypto_ec_key *csign;
char *signed_connector = NULL;
enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR;
- p = csign_key;
- csign = d2i_PUBKEY(NULL, &p, csign_key_len);
+ csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
if (!csign) {
wpa_printf(MSG_ERROR,
"DPP: Failed to parse local C-sign-key information");
@@ -1414,7 +857,7 @@
res = dpp_process_signed_connector(info, csign, signed_connector);
fail:
os_free(signed_connector);
- EVP_PKEY_free(csign);
+ crypto_ec_key_deinit(csign);
return res;
}
@@ -1433,21 +876,25 @@
nonce_len = auth->curve->nonce_len;
if (auth->initiator) {
- pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
- prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
+ pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
+ prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
+ 0);
if (auth->own_bi)
- bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
+ bix = crypto_ec_key_get_pubkey_point(
+ auth->own_bi->pubkey, 0);
else
bix = NULL;
- brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
+ brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
} else {
- pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
- prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+ pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
+ 0);
+ prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
if (auth->peer_bi)
- bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
+ bix = crypto_ec_key_get_pubkey_point(
+ auth->peer_bi->pubkey, 0);
else
bix = NULL;
- brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
+ brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
}
if (!pix || !prx || !brx)
goto fail;
@@ -1512,25 +959,29 @@
nonce_len = auth->curve->nonce_len;
if (auth->initiator) {
- pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
- prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
+ pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
+ prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
+ 0);
if (auth->own_bi)
- bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
+ bix = crypto_ec_key_get_pubkey_point(
+ auth->own_bi->pubkey, 0);
else
bix = NULL;
if (!auth->peer_bi)
goto fail;
- brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
+ brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0);
} else {
- pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
- prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+ pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
+ 0);
+ prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
if (auth->peer_bi)
- bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
+ bix = crypto_ec_key_get_pubkey_point(
+ auth->peer_bi->pubkey, 0);
else
bix = NULL;
if (!auth->own_bi)
goto fail;
- brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
+ brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0);
}
if (!pix || !prx || !brx)
goto fail;
@@ -1583,122 +1034,83 @@
int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
{
- const EC_GROUP *group;
- EC_POINT *l = NULL;
- const EC_KEY *BI, *bR, *pR;
- const EC_POINT *BI_point;
- BN_CTX *bnctx;
- BIGNUM *lx, *sum, *q;
- const BIGNUM *bR_bn, *pR_bn;
+ struct crypto_ec *ec;
+ struct crypto_ec_point *L = NULL;
+ const struct crypto_ec_point *BI;
+ const struct crypto_bignum *bR, *pR, *q;
+ struct crypto_bignum *sum = NULL, *lx = NULL;
int ret = -1;
/* L = ((bR + pR) modulo q) * BI */
- bnctx = BN_CTX_new();
- sum = BN_new();
- q = BN_new();
- lx = BN_new();
- if (!bnctx || !sum || !q || !lx)
- goto fail;
- BI = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey);
- if (!BI)
- goto fail;
- BI_point = EC_KEY_get0_public_key(BI);
- group = EC_KEY_get0_group(BI);
- if (!group)
+ ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
+ if (!ec)
goto fail;
- bR = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey);
- pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key);
- if (!bR || !pR)
+ q = crypto_ec_get_order(ec);
+ BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
+ bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
+ pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
+ sum = crypto_bignum_init();
+ L = crypto_ec_point_init(ec);
+ lx = crypto_bignum_init();
+ if (!q || !BI || !bR || !pR || !sum || !L || !lx ||
+ crypto_bignum_addmod(bR, pR, q, sum) ||
+ crypto_ec_point_mul(ec, BI, sum, L) ||
+ crypto_ec_point_x(ec, L, lx) ||
+ crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
+ auth->secret_len) < 0)
goto fail;
- bR_bn = EC_KEY_get0_private_key(bR);
- pR_bn = EC_KEY_get0_private_key(pR);
- if (!bR_bn || !pR_bn)
- goto fail;
- if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
- BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1)
- goto fail;
- l = EC_POINT_new(group);
- if (!l ||
- EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 ||
- EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
- bnctx) != 1) {
- wpa_printf(MSG_ERROR,
- "OpenSSL: failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
- goto fail;
wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
auth->Lx_len = auth->secret_len;
ret = 0;
fail:
- EC_POINT_clear_free(l);
- BN_clear_free(lx);
- BN_clear_free(sum);
- BN_free(q);
- BN_CTX_free(bnctx);
+ crypto_bignum_deinit(lx, 1);
+ crypto_bignum_deinit(sum, 1);
+ crypto_ec_point_deinit(L, 1);
+ crypto_ec_deinit(ec);
return ret;
}
int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
{
- const EC_GROUP *group;
- EC_POINT *l = NULL, *sum = NULL;
- const EC_KEY *bI, *BR, *PR;
- const EC_POINT *BR_point, *PR_point;
- BN_CTX *bnctx;
- BIGNUM *lx;
- const BIGNUM *bI_bn;
+ struct crypto_ec *ec;
+ struct crypto_ec_point *L = NULL, *sum = NULL;
+ const struct crypto_ec_point *BR, *PR;
+ const struct crypto_bignum *bI;
+ struct crypto_bignum *lx = NULL;
int ret = -1;
/* L = bI * (BR + PR) */
- bnctx = BN_CTX_new();
- lx = BN_new();
- if (!bnctx || !lx)
+ ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey));
+ if (!ec)
goto fail;
- BR = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey);
- PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key);
- if (!BR || !PR)
- goto fail;
- BR_point = EC_KEY_get0_public_key(BR);
- PR_point = EC_KEY_get0_public_key(PR);
- bI = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey);
- if (!bI)
+ BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey);
+ PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
+ bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey);
+ sum = crypto_ec_point_init(ec);
+ L = crypto_ec_point_init(ec);
+ lx = crypto_bignum_init();
+ if (!BR || !PR || !bI || !sum || !L || !lx ||
+ crypto_ec_point_add(ec, BR, PR, sum) ||
+ crypto_ec_point_mul(ec, sum, bI, L) ||
+ crypto_ec_point_x(ec, L, lx) ||
+ crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx),
+ auth->secret_len) < 0)
goto fail;
- group = EC_KEY_get0_group(bI);
- bI_bn = EC_KEY_get0_private_key(bI);
- if (!group || !bI_bn)
- goto fail;
- sum = EC_POINT_new(group);
- l = EC_POINT_new(group);
- if (!sum || !l ||
- EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 ||
- EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 ||
- EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
- bnctx) != 1) {
- wpa_printf(MSG_ERROR,
- "OpenSSL: failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0)
- goto fail;
wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
auth->Lx_len = auth->secret_len;
ret = 0;
fail:
- EC_POINT_clear_free(l);
- EC_POINT_clear_free(sum);
- BN_clear_free(lx);
- BN_CTX_free(bnctx);
+ crypto_bignum_deinit(lx, 1);
+ crypto_ec_point_deinit(sum, 1);
+ crypto_ec_point_deinit(L, 1);
+ crypto_ec_deinit(ec);
return ret;
}
@@ -1731,7 +1143,8 @@
int dpp_derive_pmkid(const struct dpp_curve_params *curve,
- EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid)
+ struct crypto_ec_key *own_key,
+ struct crypto_ec_key *peer_key, u8 *pmkid)
{
struct wpabuf *nkx, *pkx;
int ret = -1, res;
@@ -1740,8 +1153,8 @@
u8 hash[SHA256_MAC_LEN];
/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
- nkx = dpp_get_pubkey_point(own_key, 0);
- pkx = dpp_get_pubkey_point(peer_key, 0);
+ nkx = crypto_ec_key_get_pubkey_point(own_key, 0);
+ pkx = crypto_ec_key_get_pubkey_point(peer_key, 0);
if (!nkx || !pkx)
goto fail;
addr[0] = wpabuf_head(nkx);
@@ -1981,13 +1394,10 @@
};
-static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve,
- int init)
+static struct crypto_ec_key *
+dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
{
- EC_GROUP *group;
- size_t len = curve->prime_len;
const u8 *x, *y;
- EVP_PKEY *res;
switch (curve->ike_group) {
case 19:
@@ -2018,38 +1428,34 @@
return NULL;
}
- group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
- if (!group)
- return NULL;
- res = dpp_set_pubkey_point_group(group, x, y, len);
- EC_GROUP_free(group);
- return res;
+ return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len);
}
-EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
- const u8 *mac_init, const char *code,
- const char *identifier, BN_CTX *bnctx,
- EC_GROUP **ret_group)
+struct crypto_ec_point *
+dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
+ const char *code, const char *identifier,
+ struct crypto_ec **ret_ec)
{
u8 hash[DPP_MAX_HASH_LEN];
const u8 *addr[3];
size_t len[3];
unsigned int num_elem = 0;
- EC_POINT *Qi = NULL;
- EVP_PKEY *Pi = NULL;
- const EC_KEY *Pi_ec;
- const EC_POINT *Pi_point;
- BIGNUM *hash_bn = NULL;
- const EC_GROUP *group = NULL;
- EC_GROUP *group2 = NULL;
+ struct crypto_ec_point *Qi = NULL;
+ struct crypto_ec_key *Pi_key = NULL;
+ const struct crypto_ec_point *Pi = NULL;
+ struct crypto_bignum *hash_bn = NULL;
+ struct crypto_ec *ec = NULL;
- /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
+ /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
- wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init));
- addr[num_elem] = mac_init;
- len[num_elem] = ETH_ALEN;
- num_elem++;
+ if (mac_init) {
+ wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR,
+ MAC2STR(mac_init));
+ addr[num_elem] = mac_init;
+ len[num_elem] = ETH_ALEN;
+ num_elem++;
+ }
if (identifier) {
wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
identifier);
@@ -2064,75 +1470,67 @@
if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
goto fail;
wpa_hexdump_key(MSG_DEBUG,
- "DPP: H(MAC-Initiator | [identifier |] code)",
+ "DPP: H([MAC-Initiator |] [identifier |] code)",
hash, curve->hash_len);
- Pi = dpp_pkex_get_role_elem(curve, 1);
- if (!Pi)
+ Pi_key = dpp_pkex_get_role_elem(curve, 1);
+ if (!Pi_key)
goto fail;
- dpp_debug_print_key("DPP: Pi", Pi);
- Pi_ec = EVP_PKEY_get0_EC_KEY(Pi);
- if (!Pi_ec)
- goto fail;
- Pi_point = EC_KEY_get0_public_key(Pi_ec);
+ dpp_debug_print_key("DPP: Pi", Pi_key);
- group = EC_KEY_get0_group(Pi_ec);
- if (!group)
+ ec = crypto_ec_init(curve->ike_group);
+ if (!ec)
goto fail;
- group2 = EC_GROUP_dup(group);
- if (!group2)
+
+ Pi = crypto_ec_key_get_public_key(Pi_key);
+ Qi = crypto_ec_point_init(ec);
+ hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
+ if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi))
goto fail;
- Qi = EC_POINT_new(group2);
- if (!Qi) {
- EC_GROUP_free(group2);
- goto fail;
- }
- hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
- if (!hash_bn ||
- EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1)
- goto fail;
- if (EC_POINT_is_at_infinity(group, Qi)) {
+
+ if (crypto_ec_point_is_at_infinity(ec, Qi)) {
wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity");
goto fail;
}
- dpp_debug_print_point("DPP: Qi", group, Qi);
+ crypto_ec_point_debug_print(ec, Qi, "DPP: Qi");
out:
- EVP_PKEY_free(Pi);
- BN_clear_free(hash_bn);
- if (ret_group && Qi)
- *ret_group = group2;
+ crypto_ec_key_deinit(Pi_key);
+ crypto_bignum_deinit(hash_bn, 1);
+ if (ret_ec && Qi)
+ *ret_ec = ec;
else
- EC_GROUP_free(group2);
+ crypto_ec_deinit(ec);
return Qi;
fail:
- EC_POINT_free(Qi);
+ crypto_ec_point_deinit(Qi, 1);
Qi = NULL;
goto out;
}
-EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
- const u8 *mac_resp, const char *code,
- const char *identifier, BN_CTX *bnctx,
- EC_GROUP **ret_group)
+struct crypto_ec_point *
+dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
+ const char *code, const char *identifier,
+ struct crypto_ec **ret_ec)
{
u8 hash[DPP_MAX_HASH_LEN];
const u8 *addr[3];
size_t len[3];
unsigned int num_elem = 0;
- EC_POINT *Qr = NULL;
- EVP_PKEY *Pr = NULL;
- const EC_KEY *Pr_ec;
- const EC_POINT *Pr_point;
- BIGNUM *hash_bn = NULL;
- const EC_GROUP *group = NULL;
- EC_GROUP *group2 = NULL;
+ struct crypto_ec_point *Qr = NULL;
+ struct crypto_ec_key *Pr_key = NULL;
+ const struct crypto_ec_point *Pr = NULL;
+ struct crypto_bignum *hash_bn = NULL;
+ struct crypto_ec *ec = NULL;
- /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
+ /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
- wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp));
- addr[num_elem] = mac_resp;
- len[num_elem] = ETH_ALEN;
- num_elem++;
+ if (mac_resp) {
+ wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR,
+ MAC2STR(mac_resp));
+ addr[num_elem] = mac_resp;
+ len[num_elem] = ETH_ALEN;
+ num_elem++;
+ }
if (identifier) {
wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
identifier);
@@ -2147,53 +1545,46 @@
if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
goto fail;
wpa_hexdump_key(MSG_DEBUG,
- "DPP: H(MAC-Responder | [identifier |] code)",
+ "DPP: H([MAC-Responder |] [identifier |] code)",
hash, curve->hash_len);
- Pr = dpp_pkex_get_role_elem(curve, 0);
- if (!Pr)
+ Pr_key = dpp_pkex_get_role_elem(curve, 0);
+ if (!Pr_key)
goto fail;
- dpp_debug_print_key("DPP: Pr", Pr);
- Pr_ec = EVP_PKEY_get0_EC_KEY(Pr);
- if (!Pr_ec)
- goto fail;
- Pr_point = EC_KEY_get0_public_key(Pr_ec);
+ dpp_debug_print_key("DPP: Pr", Pr_key);
- group = EC_KEY_get0_group(Pr_ec);
- if (!group)
+ ec = crypto_ec_init(curve->ike_group);
+ if (!ec)
goto fail;
- group2 = EC_GROUP_dup(group);
- if (!group2)
+
+ Pr = crypto_ec_key_get_public_key(Pr_key);
+ Qr = crypto_ec_point_init(ec);
+ hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
+ if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
goto fail;
- Qr = EC_POINT_new(group2);
- if (!Qr) {
- EC_GROUP_free(group2);
- goto fail;
- }
- hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
- if (!hash_bn ||
- EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1)
- goto fail;
- if (EC_POINT_is_at_infinity(group, Qr)) {
+
+ if (crypto_ec_point_is_at_infinity(ec, Qr)) {
wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity");
goto fail;
}
- dpp_debug_print_point("DPP: Qr", group, Qr);
+ crypto_ec_point_debug_print(ec, Qr, "DPP: Qr");
+
out:
- EVP_PKEY_free(Pr);
- BN_clear_free(hash_bn);
- if (ret_group && Qr)
- *ret_group = group2;
+ crypto_ec_key_deinit(Pr_key);
+ crypto_bignum_deinit(hash_bn, 1);
+ if (ret_ec && Qr)
+ *ret_ec = ec;
else
- EC_GROUP_free(group2);
+ crypto_ec_deinit(ec);
return Qr;
fail:
- EC_POINT_free(Qr);
+ crypto_ec_point_deinit(Qr, 1);
Qr = NULL;
goto out;
}
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
+ u8 ver_init, u8 ver_resp,
const u8 *Mx, size_t Mx_len,
const u8 *Nx, size_t Nx_len,
const char *code,
@@ -2205,7 +1596,10 @@
u8 *info, *pos;
size_t info_len;
- /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
+ /*
+ * v1: info = MAC-Initiator | MAC-Responder
+ * v2: info = Protocol Version-Initiator | Protocol Version-Responder
+ * z = HKDF(<>, info | M.x | N.x | code, K.x)
*/
/* HKDF-Extract(<>, IKM=K.x) */
@@ -2214,15 +1608,24 @@
return -1;
wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
prk, hash_len);
- info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
+ if (mac_init && mac_resp)
+ info_len = 2 * ETH_ALEN;
+ else
+ info_len = 2;
+ info_len += Mx_len + Nx_len + os_strlen(code);
info = os_malloc(info_len);
if (!info)
return -1;
pos = info;
- os_memcpy(pos, mac_init, ETH_ALEN);
- pos += ETH_ALEN;
- os_memcpy(pos, mac_resp, ETH_ALEN);
- pos += ETH_ALEN;
+ if (mac_init && mac_resp) {
+ os_memcpy(pos, mac_init, ETH_ALEN);
+ pos += ETH_ALEN;
+ os_memcpy(pos, mac_resp, ETH_ALEN);
+ pos += ETH_ALEN;
+ } else {
+ *pos++ = ver_init;
+ *pos++ = ver_resp;
+ }
os_memcpy(pos, Mx, Mx_len);
pos += Mx_len;
os_memcpy(pos, Nx, Nx_len);
@@ -2257,15 +1660,12 @@
size_t net_access_key_len,
struct json_token *peer_net_access_key)
{
- BN_CTX *bnctx = NULL;
- EVP_PKEY *own_key = NULL, *peer_key = NULL;
- BIGNUM *sum = NULL, *q = NULL, *mx = NULL;
- EC_POINT *m = NULL;
- const EC_KEY *cR, *pR;
- const EC_GROUP *group;
- const BIGNUM *cR_bn, *pR_bn;
- const EC_POINT *CI_point;
- const EC_KEY *CI;
+ struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
+ struct crypto_bignum *sum = NULL;
+ const struct crypto_bignum *q, *cR, *pR;
+ struct crypto_ec *ec = NULL;
+ struct crypto_ec_point *M = NULL;
+ const struct crypto_ec_point *CI;
u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
u8 prk[DPP_MAX_HASH_LEN];
const struct dpp_curve_params *curve;
@@ -2303,37 +1703,23 @@
auth->e_nonce, auth->curve->nonce_len);
/* M = { cR + pR } * CI */
- cR = EVP_PKEY_get0_EC_KEY(own_key);
- pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key);
- if (!pR)
+ ec = crypto_ec_init(curve->ike_group);
+ if (!ec)
goto fail;
- group = EC_KEY_get0_group(pR);
- bnctx = BN_CTX_new();
- sum = BN_new();
- mx = BN_new();
- q = BN_new();
- m = EC_POINT_new(group);
- if (!cR || !bnctx || !sum || !mx || !q || !m)
- goto fail;
- cR_bn = EC_KEY_get0_private_key(cR);
- pR_bn = EC_KEY_get0_private_key(pR);
- if (!cR_bn || !pR_bn)
- goto fail;
- CI = EVP_PKEY_get0_EC_KEY(peer_key);
- CI_point = EC_KEY_get0_public_key(CI);
- if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
- BN_mod_add(sum, cR_bn, pR_bn, q, bnctx) != 1 ||
- EC_POINT_mul(group, m, NULL, CI_point, sum, bnctx) != 1 ||
- EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL,
- bnctx) != 1) {
- wpa_printf(MSG_ERROR,
- "OpenSSL: failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
+
+ sum = crypto_bignum_init();
+ q = crypto_ec_get_order(ec);
+ M = crypto_ec_point_init(ec);
+ cR = crypto_ec_key_get_private_key(own_key);
+ pR = crypto_ec_key_get_private_key(auth->own_protocol_key);
+ CI = crypto_ec_key_get_public_key(peer_key);
+ if (!sum || !q || !M || !cR || !pR || !CI ||
+ crypto_bignum_addmod(cR, pR, q, sum) ||
+ crypto_ec_point_mul(ec, CI, sum, M) ||
+ crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
+ wpa_printf(MSG_ERROR, "DPP: Error during M computation");
goto fail;
}
-
- if (dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0)
- goto fail;
wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
/* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
@@ -2355,19 +1741,17 @@
auth->ke, curve->hash_len);
res = 0;
- EVP_PKEY_free(auth->reconfig_old_protocol_key);
+ crypto_ec_key_deinit(auth->reconfig_old_protocol_key);
auth->reconfig_old_protocol_key = own_key;
own_key = NULL;
fail:
forced_memzero(prk, sizeof(prk));
forced_memzero(Mx, sizeof(Mx));
- EC_POINT_clear_free(m);
- BN_free(q);
- BN_clear_free(mx);
- BN_clear_free(sum);
- EVP_PKEY_free(own_key);
- EVP_PKEY_free(peer_key);
- BN_CTX_free(bnctx);
+ crypto_ec_point_deinit(M, 1);
+ crypto_bignum_deinit(sum, 1);
+ crypto_ec_key_deinit(own_key);
+ crypto_ec_key_deinit(peer_key);
+ crypto_ec_deinit(ec);
return res;
}
@@ -2376,14 +1760,11 @@
const u8 *r_proto, u16 r_proto_len,
struct json_token *net_access_key)
{
- BN_CTX *bnctx = NULL;
- EVP_PKEY *pr = NULL, *peer_key = NULL;
- EC_POINT *sum = NULL, *m = NULL;
- BIGNUM *mx = NULL;
- const EC_KEY *cI, *CR, *PR;
- const EC_GROUP *group;
- const EC_POINT *CR_point, *PR_point;
- const BIGNUM *cI_bn;
+ struct crypto_ec_key *pr = NULL, *peer_key = NULL;
+ const struct crypto_ec_point *CR, *PR;
+ const struct crypto_bignum *cI;
+ struct crypto_ec *ec = NULL;
+ struct crypto_ec_point *sum = NULL, *M = NULL;
u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
u8 prk[DPP_MAX_HASH_LEN];
int res = -1;
@@ -2397,7 +1778,7 @@
goto fail;
}
dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
- EVP_PKEY_free(auth->peer_protocol_key);
+ crypto_ec_key_deinit(auth->peer_protocol_key);
auth->peer_protocol_key = pr;
pr = NULL;
@@ -2413,25 +1794,23 @@
}
/* M = cI * { CR + PR } */
- cI = EVP_PKEY_get0_EC_KEY(auth->conf->connector_key);
- cI_bn = EC_KEY_get0_private_key(cI);
- group = EC_KEY_get0_group(cI);
- bnctx = BN_CTX_new();
- sum = EC_POINT_new(group);
- m = EC_POINT_new(group);
- mx = BN_new();
- CR = EVP_PKEY_get0_EC_KEY(peer_key);
- PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key);
- CR_point = EC_KEY_get0_public_key(CR);
- PR_point = EC_KEY_get0_public_key(PR);
- if (!bnctx || !sum || !m || !mx ||
- EC_POINT_add(group, sum, CR_point, PR_point, bnctx) != 1 ||
- EC_POINT_mul(group, m, NULL, sum, cI_bn, bnctx) != 1 ||
- EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL,
- bnctx) != 1 ||
- dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0)
+ ec = crypto_ec_init(curve->ike_group);
+ if (!ec)
goto fail;
+ cI = crypto_ec_key_get_private_key(auth->conf->connector_key);
+ sum = crypto_ec_point_init(ec);
+ M = crypto_ec_point_init(ec);
+ CR = crypto_ec_key_get_public_key(peer_key);
+ PR = crypto_ec_key_get_public_key(auth->peer_protocol_key);
+ if (!cI || !sum || !M || !CR || !PR ||
+ crypto_ec_point_add(ec, CR, PR, sum) ||
+ crypto_ec_point_mul(ec, sum, cI, M) ||
+ crypto_ec_point_to_bin(ec, M, Mx, NULL)) {
+ wpa_printf(MSG_ERROR, "DPP: Error during M computation");
+ goto fail;
+ }
+
wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len);
/* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */
@@ -2456,12 +1835,11 @@
fail:
forced_memzero(prk, sizeof(prk));
forced_memzero(Mx, sizeof(Mx));
- EVP_PKEY_free(pr);
- EVP_PKEY_free(peer_key);
- EC_POINT_clear_free(sum);
- EC_POINT_clear_free(m);
- BN_clear_free(mx);
- BN_CTX_free(bnctx);
+ crypto_ec_key_deinit(pr);
+ crypto_ec_key_deinit(peer_key);
+ crypto_ec_point_deinit(sum, 1);
+ crypto_ec_point_deinit(M, 1);
+ crypto_ec_deinit(ec);
return res;
}
@@ -2497,78 +1875,56 @@
size_t *signed3_len)
{
const struct dpp_curve_params *curve;
+ struct wpabuf *sig = NULL;
char *signed3 = NULL;
- unsigned char *signature = NULL;
- const unsigned char *p;
- size_t signature_len;
- EVP_MD_CTX *md_ctx = NULL;
- ECDSA_SIG *sig = NULL;
char *dot = ".";
- const EVP_MD *sign_md;
- const BIGNUM *r, *s;
+ const u8 *vector[3];
+ size_t vector_len[3];
+ u8 *hash;
+ int ret;
+
+ vector[0] = (const u8 *) signed1;
+ vector[1] = (const u8 *) dot;
+ vector[2] = (const u8 *) signed2;
+ vector_len[0] = signed1_len;
+ vector_len[1] = 1;
+ vector_len[2] = signed2_len;
curve = conf->curve;
+ hash = os_malloc(curve->hash_len);
+ if (!hash)
+ goto fail;
if (curve->hash_len == SHA256_MAC_LEN) {
- sign_md = EVP_sha256();
+ ret = sha256_vector(3, vector, vector_len, hash);
} else if (curve->hash_len == SHA384_MAC_LEN) {
- sign_md = EVP_sha384();
+ ret = sha384_vector(3, vector, vector_len, hash);
} else if (curve->hash_len == SHA512_MAC_LEN) {
- sign_md = EVP_sha512();
+ ret = sha512_vector(3, vector, vector_len, hash);
} else {
wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
goto fail;
}
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "DPP: Hash computation failed");
+ goto fail;
+ }
+ wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature",
+ hash, curve->hash_len);
- md_ctx = EVP_MD_CTX_create();
- if (!md_ctx)
+ sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len);
+ if (!sig) {
+ wpa_printf(MSG_ERROR, "DPP: Signature computation failed");
goto fail;
+ }
- ERR_clear_error();
- if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, conf->csign) != 1) {
- wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 ||
- EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 ||
- EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) {
- wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) {
- wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- signature = os_malloc(signature_len);
- if (!signature)
- goto fail;
- if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) {
- wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)",
- signature, signature_len);
- /* Convert to raw coordinates r,s */
- p = signature;
- sig = d2i_ECDSA_SIG(NULL, &p, signature_len);
- if (!sig)
- goto fail;
- ECDSA_SIG_get0(sig, &r, &s);
- if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
- dpp_bn2bin_pad(s, signature + curve->prime_len,
- curve->prime_len) < 0)
- goto fail;
- signature_len = 2 * curve->prime_len;
wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
- signature, signature_len);
- signed3 = base64_url_encode(signature, signature_len, signed3_len);
+ wpabuf_head(sig), wpabuf_len(sig));
+ signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig),
+ signed3_len);
+
fail:
- EVP_MD_CTX_destroy(md_ctx);
- ECDSA_SIG_free(sig);
- os_free(signature);
+ os_free(hash);
+ wpabuf_free(sig);
return signed3;
}
@@ -2618,7 +1974,7 @@
size_t net_access_key_len)
{
struct wpabuf *pub = NULL;
- EVP_PKEY *own_key;
+ struct crypto_ec_key *own_key;
struct dpp_pfs *pfs;
pfs = os_zalloc(sizeof(*pfs));
@@ -2631,7 +1987,7 @@
wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
goto fail;
}
- EVP_PKEY_free(own_key);
+ crypto_ec_key_deinit(own_key);
pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group);
if (!pfs->ecdh)
@@ -2696,19 +2052,15 @@
struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
{
- X509_REQ *req = NULL;
+ struct crypto_csr *csr = NULL;
struct wpabuf *buf = NULL;
- unsigned char *der;
- int der_len;
- EVP_PKEY *key;
- const EVP_MD *sign_md;
+ struct crypto_ec_key *key;
unsigned int hash_len = auth->curve->hash_len;
- EC_KEY *eckey;
- BIO *out = NULL;
+ struct wpabuf *priv_key;
u8 cp[DPP_CP_LEN];
- char *password;
- size_t password_len;
- int res;
+ char *password = NULL;
+ size_t password_len = 0;
+ int hash_sign_algo;
/* TODO: use auth->csrattrs */
@@ -2716,36 +2068,19 @@
* a specific group to be used */
key = auth->own_protocol_key;
- eckey = EVP_PKEY_get1_EC_KEY(key);
- if (!eckey)
- goto fail;
- der = NULL;
- der_len = i2d_ECPrivateKey(eckey, &der);
- if (der_len <= 0)
+ priv_key = crypto_ec_key_get_ecprivate_key(key, true);
+ if (!priv_key)
goto fail;
wpabuf_free(auth->priv_key);
- auth->priv_key = wpabuf_alloc_copy(der, der_len);
- OPENSSL_free(der);
- if (!auth->priv_key)
+ auth->priv_key = priv_key;
+
+ csr = crypto_csr_init();
+ if (!csr || crypto_csr_set_ec_public_key(csr, key))
goto fail;
- req = X509_REQ_new();
- if (!req || !X509_REQ_set_pubkey(req, key))
+ if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name))
goto fail;
- if (name) {
- X509_NAME *n;
-
- n = X509_REQ_get_subject_name(req);
- if (!n)
- goto fail;
-
- if (X509_NAME_add_entry_by_txt(
- n, "CN", MBSTRING_UTF8,
- (const unsigned char *) name, -1, -1, 0) != 1)
- goto fail;
- }
-
/* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
"CSR challengePassword", cp, DPP_CP_LEN) < 0)
@@ -2755,222 +2090,75 @@
cp, DPP_CP_LEN);
password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len);
forced_memzero(cp, DPP_CP_LEN);
- if (!password)
+ if (!password ||
+ crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
+ ASN1_TAG_UTF8STRING, (const u8 *) password,
+ password_len))
goto fail;
- res = X509_REQ_add1_attr_by_NID(req, NID_pkcs9_challengePassword,
- V_ASN1_UTF8STRING,
- (const unsigned char *) password,
- password_len);
- bin_clear_free(password, password_len);
- if (!res)
- goto fail;
-
- /* TODO */
-
/* TODO: hash func selection based on csrAttrs */
if (hash_len == SHA256_MAC_LEN) {
- sign_md = EVP_sha256();
+ hash_sign_algo = CRYPTO_HASH_ALG_SHA256;
} else if (hash_len == SHA384_MAC_LEN) {
- sign_md = EVP_sha384();
+ hash_sign_algo = CRYPTO_HASH_ALG_SHA384;
} else if (hash_len == SHA512_MAC_LEN) {
- sign_md = EVP_sha512();
+ hash_sign_algo = CRYPTO_HASH_ALG_SHA512;
} else {
wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
goto fail;
}
- if (!X509_REQ_sign(req, key, sign_md))
+ buf = crypto_csr_sign(csr, key, hash_sign_algo);
+ if (!buf)
goto fail;
-
- der = NULL;
- der_len = i2d_X509_REQ(req, &der);
- if (der_len < 0)
- goto fail;
- buf = wpabuf_alloc_copy(der, der_len);
- OPENSSL_free(der);
-
wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
fail:
- BIO_free_all(out);
- X509_REQ_free(req);
+ bin_clear_free(password, password_len);
+ crypto_csr_deinit(csr);
return buf;
}
-struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7)
+int dpp_validate_csr(struct dpp_authentication *auth,
+ const struct wpabuf *csrbuf)
{
-#ifdef OPENSSL_IS_BORINGSSL
- CBS pkcs7_cbs;
-#else /* OPENSSL_IS_BORINGSSL */
- PKCS7 *p7 = NULL;
- const unsigned char *p = wpabuf_head(pkcs7);
-#endif /* OPENSSL_IS_BORINGSSL */
- STACK_OF(X509) *certs;
- int i, num;
- BIO *out = NULL;
- size_t rlen;
- struct wpabuf *pem = NULL;
- int res;
-
-#ifdef OPENSSL_IS_BORINGSSL
- certs = sk_X509_new_null();
- if (!certs)
- goto fail;
- CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7));
- if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
- wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
-#else /* OPENSSL_IS_BORINGSSL */
- p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7));
- if (!p7) {
- wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
-
- switch (OBJ_obj2nid(p7->type)) {
- case NID_pkcs7_signed:
- certs = p7->d.sign->cert;
- break;
- case NID_pkcs7_signedAndEnveloped:
- certs = p7->d.signed_and_enveloped->cert;
- break;
- default:
- certs = NULL;
- break;
- }
-#endif /* OPENSSL_IS_BORINGSSL */
-
- if (!certs || ((num = sk_X509_num(certs)) == 0)) {
- wpa_printf(MSG_INFO,
- "DPP: No certificates found in PKCS#7 object");
- goto fail;
- }
-
- out = BIO_new(BIO_s_mem());
- if (!out)
- goto fail;
-
- for (i = 0; i < num; i++) {
- X509 *cert = sk_X509_value(certs, i);
-
- PEM_write_bio_X509(out, cert);
- }
-
- rlen = BIO_ctrl_pending(out);
- pem = wpabuf_alloc(rlen);
- if (!pem)
- goto fail;
- res = BIO_read(out, wpabuf_put(pem, 0), rlen);
- if (res <= 0) {
- wpabuf_free(pem);
- pem = NULL;
- goto fail;
- }
- wpabuf_put(pem, res);
-
-fail:
-#ifdef OPENSSL_IS_BORINGSSL
- if (certs)
- sk_X509_pop_free(certs, X509_free);
-#else /* OPENSSL_IS_BORINGSSL */
- PKCS7_free(p7);
-#endif /* OPENSSL_IS_BORINGSSL */
- if (out)
- BIO_free_all(out);
-
- return pem;
-}
-
-
-int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr)
-{
- X509_REQ *req;
- const unsigned char *pos;
- EVP_PKEY *pkey;
- int res, loc, ret = -1;
- X509_ATTRIBUTE *attr;
- ASN1_TYPE *type;
- ASN1_STRING *str;
- unsigned char *utf8 = NULL;
+ struct crypto_csr *csr;
+ const u8 *attr;
+ size_t attr_len;
+ int attr_type;
unsigned char *cp = NULL;
size_t cp_len;
u8 exp_cp[DPP_CP_LEN];
unsigned int hash_len = auth->curve->hash_len;
+ int ret = -1;
- pos = wpabuf_head(csr);
- req = d2i_X509_REQ(NULL, &pos, wpabuf_len(csr));
- if (!req) {
- wpa_printf(MSG_DEBUG, "DPP: Failed to parse CSR");
- return -1;
- }
-
- pkey = X509_REQ_get_pubkey(req);
- if (!pkey) {
- wpa_printf(MSG_DEBUG, "DPP: Failed to get public key from CSR");
- goto fail;
- }
-
- res = X509_REQ_verify(req, pkey);
- EVP_PKEY_free(pkey);
- if (res != 1) {
+ csr = crypto_csr_verify(csrbuf);
+ if (!csr) {
wpa_printf(MSG_DEBUG,
- "DPP: CSR does not have a valid signature");
+ "DPP: CSR invalid or invalid signature");
goto fail;
}
- loc = X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1);
- if (loc < 0) {
+ attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD,
+ &attr_len, &attr_type);
+ if (!attr) {
wpa_printf(MSG_DEBUG,
"DPP: CSR does not include challengePassword");
goto fail;
}
-
- attr = X509_REQ_get_attr(req, loc);
- if (!attr) {
- wpa_printf(MSG_DEBUG,
- "DPP: Could not get challengePassword attribute");
- goto fail;
- }
-
- type = X509_ATTRIBUTE_get0_type(attr, 0);
- if (!type) {
- wpa_printf(MSG_DEBUG,
- "DPP: Could not get challengePassword attribute type");
- goto fail;
- }
-
- res = ASN1_TYPE_get(type);
/* This is supposed to be UTF8String, but allow other strings as well
* since challengePassword is using ASCII (base64 encoded). */
- if (res != V_ASN1_UTF8STRING && res != V_ASN1_PRINTABLESTRING &&
- res != V_ASN1_IA5STRING) {
+ if (attr_type != ASN1_TAG_UTF8STRING &&
+ attr_type != ASN1_TAG_PRINTABLESTRING &&
+ attr_type != ASN1_TAG_IA5STRING) {
wpa_printf(MSG_DEBUG,
"DPP: Unexpected challengePassword attribute type %d",
- res);
+ attr_type);
goto fail;
}
- str = X509_ATTRIBUTE_get0_data(attr, 0, res, NULL);
- if (!str) {
- wpa_printf(MSG_DEBUG,
- "DPP: Could not get ASN.1 string for challengePassword");
- goto fail;
- }
-
- res = ASN1_STRING_to_UTF8(&utf8, str);
- if (res < 0) {
- wpa_printf(MSG_DEBUG,
- "DPP: Could not get UTF8 version of challengePassword");
- goto fail;
- }
-
- cp = base64_decode((const char *) utf8, res, &cp_len);
- OPENSSL_free(utf8);
+ cp = base64_decode((const char *) attr, attr_len, &cp_len);
if (!cp) {
wpa_printf(MSG_DEBUG,
"DPP: Could not base64 decode challengePassword");
@@ -3001,7 +2189,7 @@
ret = 0;
fail:
os_free(cp);
- X509_REQ_free(req);
+ crypto_csr_deinit(csr);
return ret;
}
@@ -3011,50 +2199,46 @@
const u8 *pp_key,
size_t pp_key_len)
{
- const unsigned char *p;
- EVP_PKEY *csign = NULL, *ppkey = NULL;
+ struct crypto_ec_key *csign = NULL, *ppkey = NULL;
struct dpp_reconfig_id *id = NULL;
- BN_CTX *ctx = NULL;
- BIGNUM *bn = NULL, *q = NULL;
- const EC_KEY *eckey;
- const EC_GROUP *group;
- EC_POINT *e_id = NULL;
+ struct crypto_ec *ec = NULL;
+ const struct crypto_bignum *q;
+ struct crypto_bignum *bn = NULL;
+ struct crypto_ec_point *e_id = NULL;
+ const struct crypto_ec_point *generator;
- p = csign_key;
- csign = d2i_PUBKEY(NULL, &p, csign_key_len);
+ csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
if (!csign)
goto fail;
if (!pp_key)
goto fail;
- p = pp_key;
- ppkey = d2i_PUBKEY(NULL, &p, pp_key_len);
+ ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len);
if (!ppkey)
goto fail;
- eckey = EVP_PKEY_get0_EC_KEY(csign);
- if (!eckey)
- goto fail;
- group = EC_KEY_get0_group(eckey);
- if (!group)
+ ec = crypto_ec_init(crypto_ec_key_group(csign));
+ if (!ec)
goto fail;
- e_id = EC_POINT_new(group);
- ctx = BN_CTX_new();
- bn = BN_new();
- q = BN_new();
- if (!e_id || !ctx || !bn || !q ||
- !EC_GROUP_get_order(group, q, ctx) ||
- !BN_rand_range(bn, q) ||
- !EC_POINT_mul(group, e_id, bn, NULL, NULL, ctx))
+ e_id = crypto_ec_point_init(ec);
+ bn = crypto_bignum_init();
+ q = crypto_ec_get_order(ec);
+ generator = crypto_ec_get_generator(ec);
+ if (!e_id || !bn || !q || !generator ||
+ crypto_bignum_rand(bn, q) ||
+ crypto_ec_point_mul(ec, generator, bn, e_id))
goto fail;
- dpp_debug_print_point("DPP: Generated random point E-id", group, e_id);
+ crypto_ec_point_debug_print(ec, e_id,
+ "DPP: Generated random point E-id");
id = os_zalloc(sizeof(*id));
if (!id)
goto fail;
- id->group = group;
+
+ id->ec = ec;
+ ec = NULL;
id->e_id = e_id;
e_id = NULL;
id->csign = csign;
@@ -3062,93 +2246,58 @@
id->pp_key = ppkey;
ppkey = NULL;
fail:
- EC_POINT_free(e_id);
- EVP_PKEY_free(csign);
- EVP_PKEY_free(ppkey);
- BN_clear_free(bn);
- BN_CTX_free(ctx);
+ crypto_ec_point_deinit(e_id, 1);
+ crypto_ec_key_deinit(csign);
+ crypto_ec_key_deinit(ppkey);
+ crypto_bignum_deinit(bn, 1);
+ crypto_ec_deinit(ec);
return id;
}
-static EVP_PKEY * dpp_pkey_from_point(const EC_GROUP *group,
- const EC_POINT *point)
-{
- EC_KEY *eckey;
- EVP_PKEY *pkey = NULL;
-
- eckey = EC_KEY_new();
- if (!eckey ||
- EC_KEY_set_group(eckey, group) != 1 ||
- EC_KEY_set_public_key(eckey, point) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to set EC_KEY: %s",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- }
- EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
-
- pkey = EVP_PKEY_new();
- if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
- wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
- EVP_PKEY_free(pkey);
- pkey = NULL;
- goto fail;
- }
-
-fail:
- EC_KEY_free(eckey);
- return pkey;
-}
-
-
int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
{
- BN_CTX *ctx = NULL;
- BIGNUM *bn = NULL, *q = NULL;
- EC_POINT *e_prime_id = NULL, *a_nonce = NULL;
+ const struct crypto_bignum *q;
+ struct crypto_bignum *bn;
+ const struct crypto_ec_point *pp, *generator;
+ struct crypto_ec_point *e_prime_id, *a_nonce;
int ret = -1;
- const EC_KEY *pp;
- const EC_POINT *pp_point;
- pp = EVP_PKEY_get0_EC_KEY(id->pp_key);
- if (!pp)
- goto fail;
- pp_point = EC_KEY_get0_public_key(pp);
- e_prime_id = EC_POINT_new(id->group);
- a_nonce = EC_POINT_new(id->group);
- ctx = BN_CTX_new();
- bn = BN_new();
- q = BN_new();
+ pp = crypto_ec_key_get_public_key(id->pp_key);
+ e_prime_id = crypto_ec_point_init(id->ec);
+ a_nonce = crypto_ec_point_init(id->ec);
+ bn = crypto_bignum_init();
+ q = crypto_ec_get_order(id->ec);
+ generator = crypto_ec_get_generator(id->ec);
+
/* Generate random 0 <= a-nonce < q
* A-NONCE = a-nonce * G
* E'-id = E-id + a-nonce * P_pk */
- if (!pp_point || !e_prime_id || !a_nonce || !ctx || !bn || !q ||
- !EC_GROUP_get_order(id->group, q, ctx) ||
- !BN_rand_range(bn, q) || /* bn = a-nonce */
- !EC_POINT_mul(id->group, a_nonce, bn, NULL, NULL, ctx) ||
- !EC_POINT_mul(id->group, e_prime_id, NULL, pp_point, bn, ctx) ||
- !EC_POINT_add(id->group, e_prime_id, id->e_id, e_prime_id, ctx))
+ if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator ||
+ crypto_bignum_rand(bn, q) || /* bn = a-nonce */
+ crypto_ec_point_mul(id->ec, generator, bn, a_nonce) ||
+ crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) ||
+ crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id))
goto fail;
- dpp_debug_print_point("DPP: Generated A-NONCE", id->group, a_nonce);
- dpp_debug_print_point("DPP: Encrypted E-id to E'-id",
- id->group, e_prime_id);
+ crypto_ec_point_debug_print(id->ec, a_nonce,
+ "DPP: Generated A-NONCE");
+ crypto_ec_point_debug_print(id->ec, e_prime_id,
+ "DPP: Encrypted E-id to E'-id");
- EVP_PKEY_free(id->a_nonce);
- EVP_PKEY_free(id->e_prime_id);
- id->a_nonce = dpp_pkey_from_point(id->group, a_nonce);
- id->e_prime_id = dpp_pkey_from_point(id->group, e_prime_id);
+ crypto_ec_key_deinit(id->a_nonce);
+ crypto_ec_key_deinit(id->e_prime_id);
+ id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce);
+ id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id);
if (!id->a_nonce || !id->e_prime_id)
goto fail;
ret = 0;
fail:
- EC_POINT_free(e_prime_id);
- EC_POINT_free(a_nonce);
- BN_clear_free(bn);
- BN_CTX_free(ctx);
+ crypto_ec_point_deinit(e_prime_id, 1);
+ crypto_ec_point_deinit(a_nonce, 1);
+ crypto_bignum_deinit(bn, 1);
return ret;
}
@@ -3156,55 +2305,50 @@
void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
{
if (id) {
- EC_POINT_clear_free(id->e_id);
- EVP_PKEY_free(id->csign);
- EVP_PKEY_free(id->a_nonce);
- EVP_PKEY_free(id->e_prime_id);
- EVP_PKEY_free(id->pp_key);
+ crypto_ec_point_deinit(id->e_id, 1);
+ crypto_ec_key_deinit(id->csign);
+ crypto_ec_key_deinit(id->a_nonce);
+ crypto_ec_key_deinit(id->e_prime_id);
+ crypto_ec_key_deinit(id->pp_key);
+ crypto_ec_deinit(id->ec);
os_free(id);
}
}
-EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce,
- EVP_PKEY *e_prime_id)
+struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
+ struct crypto_ec_key *a_nonce,
+ struct crypto_ec_key *e_prime_id)
{
- const EC_KEY *pp_ec, *a_nonce_ec, *e_prime_id_ec;
- const BIGNUM *pp_bn;
- const EC_GROUP *group;
- EC_POINT *e_id = NULL;
- const EC_POINT *a_nonce_point, *e_prime_id_point;
- BN_CTX *ctx = NULL;
+ struct crypto_ec *ec;
+ const struct crypto_bignum *pp;
+ struct crypto_ec_point *e_id = NULL;
+ const struct crypto_ec_point *a_nonce_point, *e_prime_id_point;
if (!ppkey)
return NULL;
/* E-id = E'-id - s_C * A-NONCE */
- pp_ec = EVP_PKEY_get0_EC_KEY(ppkey);
- a_nonce_ec = EVP_PKEY_get0_EC_KEY(a_nonce);
- e_prime_id_ec = EVP_PKEY_get0_EC_KEY(e_prime_id);
- if (!pp_ec || !a_nonce_ec || !e_prime_id_ec)
+ ec = crypto_ec_init(crypto_ec_key_group(ppkey));
+ if (!ec)
return NULL;
- pp_bn = EC_KEY_get0_private_key(pp_ec);
- group = EC_KEY_get0_group(pp_ec);
- a_nonce_point = EC_KEY_get0_public_key(a_nonce_ec);
- e_prime_id_point = EC_KEY_get0_public_key(e_prime_id_ec);
- ctx = BN_CTX_new();
- if (!pp_bn || !group || !a_nonce_point || !e_prime_id_point || !ctx)
- goto fail;
- e_id = EC_POINT_new(group);
- if (!e_id ||
- !EC_POINT_mul(group, e_id, NULL, a_nonce_point, pp_bn, ctx) ||
- !EC_POINT_invert(group, e_id, ctx) ||
- !EC_POINT_add(group, e_id, e_prime_id_point, e_id, ctx)) {
- EC_POINT_clear_free(e_id);
+
+ pp = crypto_ec_key_get_private_key(ppkey);
+ a_nonce_point = crypto_ec_key_get_public_key(a_nonce);
+ e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id);
+ e_id = crypto_ec_point_init(ec);
+ if (!pp || !a_nonce_point || !e_prime_id_point || !e_id ||
+ crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) ||
+ crypto_ec_point_invert(ec, e_id) ||
+ crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) {
+ crypto_ec_point_deinit(e_id, 1);
goto fail;
}
- dpp_debug_print_point("DPP: Decrypted E-id", group, e_id);
+ crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id");
fail:
- BN_CTX_free(ctx);
+ crypto_ec_deinit(ec);
return e_id;
}
@@ -3216,64 +2360,46 @@
int dpp_test_gen_invalid_key(struct wpabuf *msg,
const struct dpp_curve_params *curve)
{
- BN_CTX *ctx;
- BIGNUM *x, *y;
+ struct crypto_ec *ec;
+ struct crypto_ec_key *key = NULL;
+ const struct crypto_ec_point *pub_key;
+ struct crypto_ec_point *p = NULL;
+ u8 *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)
+ ec = crypto_ec_init(curve->ike_group);
+ x = wpabuf_put(msg, curve->prime_len);
+ y = wpabuf_put(msg, curve->prime_len);
+ if (!ec)
goto fail;
- if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1)
+retry:
+ /* Generate valid key pair */
+ key = crypto_ec_key_gen(curve->ike_group);
+ if (!key)
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;
+ /* Retrieve public key coordinates */
+ pub_key = crypto_ec_key_get_public_key(key);
+ if (!pub_key)
+ goto fail;
- if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y,
- ctx) != 1) {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
- /* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL
- * return an error from EC_POINT_set_affine_coordinates_GFp()
- * when the point is not on the curve. */
- break;
-#else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */
- goto fail;
-#endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */
- }
+ crypto_ec_point_to_bin(ec, pub_key, x, y);
- if (!EC_POINT_is_on_curve(group, point, ctx))
- break;
+ /* And corrupt them */
+ y[curve->prime_len - 1] ^= 0x01;
+ p = crypto_ec_point_from_bin(ec, x);
+ if (p && crypto_ec_point_is_on_curve(ec, p)) {
+ crypto_ec_point_deinit(p, 0);
+ p = NULL;
+ goto retry;
}
- if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len),
- curve->prime_len) < 0 ||
- dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len),
- curve->prime_len) < 0)
- goto fail;
-
ret = 0;
fail:
- if (ret < 0)
- wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key");
- BN_free(x);
- BN_free(y);
- EC_POINT_free(point);
- BN_CTX_free(ctx);
- EC_GROUP_free(group);
-
+ crypto_ec_point_deinit(p, 0);
+ crypto_ec_key_deinit(key);
+ crypto_ec_deinit(ec);
return ret;
}
diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h
index af12467..0f31ae5 100644
--- a/src/common/dpp_i.h
+++ b/src/common/dpp_i.h
@@ -2,6 +2,7 @@
* DPP module internal definitions
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -22,6 +23,7 @@
struct dl_list tcp_init; /* struct dpp_connection */
void *cb_ctx;
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+ bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi);
#endif /* CONFIG_DPP2 */
};
@@ -37,10 +39,11 @@
struct json_token * dpp_parse_own_connector(const char *own_connector);
int dpp_connector_match_groups(struct json_token *own_root,
struct json_token *peer_root, bool reconfig);
-int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
- const char *kid, const struct dpp_curve_params *curve);
-EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
- const struct dpp_curve_params **key_curve);
+int dpp_build_jwk(struct wpabuf *buf, const char *name,
+ struct crypto_ec_key *key, const char *kid,
+ const struct dpp_curve_params *curve);
+struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk,
+ const struct dpp_curve_params **key_curve);
int dpp_prepare_channel_list(struct dpp_authentication *auth,
unsigned int neg_freq,
struct hostapd_hw_modes *own_modes, u16 num_modes);
@@ -65,32 +68,27 @@
enum dpp_status_error
dpp_process_signed_connector(struct dpp_signed_connector_info *info,
- EVP_PKEY *csign_pub, const char *connector);
+ struct crypto_ec_key *csign_pub,
+ const char *connector);
enum dpp_status_error
dpp_check_signed_connector(struct dpp_signed_connector_info *info,
const u8 *csign_key, size_t csign_key_len,
const u8 *peer_connector, size_t peer_connector_len);
const struct dpp_curve_params * dpp_get_curve_name(const char *name);
const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name);
-const struct dpp_curve_params * dpp_get_curve_nid(int nid);
const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group);
int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi,
const u8 *data, size_t data_len);
-struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix);
-EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
- const u8 *buf_x, const u8 *buf_y,
- size_t len);
-EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len);
-int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len);
+struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key,
+ const u8 *buf, size_t len);
int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
const char *label, u8 *out, size_t outlen);
int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac);
-int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len);
-void dpp_debug_print_point(const char *title, const EC_GROUP *group,
- const EC_POINT *point);
-void dpp_debug_print_key(const char *title, EVP_PKEY *key);
+int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer,
+ u8 *secret, size_t *secret_len);
+void dpp_debug_print_key(const char *title, struct crypto_ec_key *key);
int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len,
const u8 *salt, size_t salt_len, unsigned int iterations,
u8 *buf, size_t buflen);
@@ -99,9 +97,9 @@
int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi);
int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
const u8 *privkey, size_t privkey_len);
-EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
- const u8 *privkey, size_t privkey_len);
-EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve);
+struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
+ const u8 *privkey, size_t privkey_len);
+struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve);
int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len);
int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len);
int dpp_derive_bk_ke(struct dpp_authentication *auth);
@@ -111,16 +109,18 @@
int dpp_auth_derive_l_initiator(struct dpp_authentication *auth);
int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len);
int dpp_derive_pmkid(const struct dpp_curve_params *curve,
- EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid);
-EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
- const u8 *mac_init, const char *code,
- const char *identifier, BN_CTX *bnctx,
- EC_GROUP **ret_group);
-EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
- const u8 *mac_resp, const char *code,
- const char *identifier, BN_CTX *bnctx,
- EC_GROUP **ret_group);
+ struct crypto_ec_key *own_key,
+ struct crypto_ec_key *peer_key, u8 *pmkid);
+struct crypto_ec_point *
+dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
+ const char *code, const char *identifier,
+ struct crypto_ec **ret_ec);
+struct crypto_ec_point *
+dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
+ const char *code, const char *identifier,
+ struct crypto_ec **ret_ec);
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
+ u8 ver_init, u8 ver_resp,
const u8 *Mx, size_t Mx_len,
const u8 *Nx, size_t Nx_len,
const char *code,
@@ -133,20 +133,21 @@
int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
const u8 *r_proto, u16 r_proto_len,
struct json_token *net_access_key);
-EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce,
- EVP_PKEY *e_prime_id);
+struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
+ struct crypto_ec_key *a_nonce,
+ struct crypto_ec_key *e_prime_id);
char * dpp_sign_connector(struct dpp_configurator *conf,
const struct wpabuf *dppcon);
int dpp_test_gen_invalid_key(struct wpabuf *msg,
const struct dpp_curve_params *curve);
struct dpp_reconfig_id {
- const EC_GROUP *group;
- EC_POINT *e_id; /* E-id */
- EVP_PKEY *csign;
- EVP_PKEY *a_nonce; /* A-NONCE */
- EVP_PKEY *e_prime_id; /* E'-id */
- EVP_PKEY *pp_key;
+ struct crypto_ec *ec;
+ struct crypto_ec_point *e_id; /* E-id */
+ struct crypto_ec_key *csign;
+ struct crypto_ec_key *a_nonce; /* A-NONCE */
+ struct crypto_ec_key *e_prime_id; /* E'-id */
+ struct crypto_ec_key *pp_key;
};
/* dpp_tcp.c */
diff --git a/src/common/dpp_pkex.c b/src/common/dpp_pkex.c
index 807ab7d..72084d9 100644
--- a/src/common/dpp_pkex.c
+++ b/src/common/dpp_pkex.c
@@ -8,8 +8,6 @@
*/
#include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
#include "utils/common.h"
#include "common/wpa_ctrl.h"
@@ -27,42 +25,24 @@
size_t dpp_pkex_ephemeral_key_override_len = 0;
#endif /* CONFIG_TESTING_OPTIONS */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
- (defined(LIBRESSL_VERSION_NUMBER) && \
- LIBRESSL_VERSION_NUMBER < 0x20700000L)
-/* Compatibility wrappers for older versions. */
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
+static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex,
+ bool v2)
{
- if (pkey->type != EVP_PKEY_EC)
- return NULL;
- return pkey->pkey.ec;
-}
-
-#endif
-
-
-static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
-{
- const EC_KEY *X_ec;
- const EC_POINT *X_point;
- BN_CTX *bnctx = NULL;
- EC_GROUP *group = NULL;
- EC_POINT *Qi = NULL, *M = NULL;
- struct wpabuf *M_buf = NULL;
- BIGNUM *Mx = NULL, *My = NULL;
+ struct crypto_ec *ec = NULL;
+ const struct crypto_ec_point *X;
+ struct crypto_ec_point *Qi = NULL, *M = NULL;
+ u8 *Mx, *My;
struct wpabuf *msg = NULL;
size_t attr_len;
const struct dpp_curve_params *curve = pkex->own_bi->curve;
- wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
+ wpa_printf(MSG_DEBUG, "DPP: Build PKEX %sExchange Request",
+ v2 ? "" : "Version 1 ");
- /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
- bnctx = BN_CTX_new();
- if (!bnctx)
- goto fail;
- Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
- pkex->identifier, bnctx, &group);
+ /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
+ Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : pkex->own_mac, pkex->code,
+ pkex->identifier, &ec);
if (!Qi)
goto fail;
@@ -86,31 +66,39 @@
goto fail;
/* M = X + Qi */
- X_ec = EVP_PKEY_get0_EC_KEY(pkex->x);
- if (!X_ec)
+ X = crypto_ec_key_get_public_key(pkex->x);
+ M = crypto_ec_point_init(ec);
+ if (!X || !M)
goto fail;
- X_point = EC_KEY_get0_public_key(X_ec);
- if (!X_point)
+ crypto_ec_point_debug_print(ec, X, "DPP: X");
+
+ if (crypto_ec_point_add(ec, X, Qi, M))
goto fail;
- dpp_debug_print_point("DPP: X", group, X_point);
- M = EC_POINT_new(group);
- Mx = BN_new();
- My = BN_new();
- if (!M || !Mx || !My ||
- EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 ||
- EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1)
- goto fail;
- dpp_debug_print_point("DPP: M", group, M);
+ crypto_ec_point_debug_print(ec, M, "DPP: M");
/* Initiator -> Responder: group, [identifier,] M */
attr_len = 4 + 2;
+#ifdef CONFIG_DPP2
+ if (v2)
+ attr_len += 4 + 1;
+#endif /* CONFIG_DPP2 */
if (pkex->identifier)
attr_len += 4 + os_strlen(pkex->identifier);
attr_len += 4 + 2 * curve->prime_len;
- msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len);
+ msg = dpp_alloc_msg(v2 ? DPP_PA_PKEX_EXCHANGE_REQ :
+ DPP_PA_PKEX_V1_EXCHANGE_REQ, attr_len);
if (!msg)
goto fail;
+#ifdef CONFIG_DPP2
+ if (v2) {
+ /* Protocol Version */
+ wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
+ wpabuf_put_le16(msg, 1);
+ wpabuf_put_u8(msg, DPP_VERSION);
+ }
+#endif /* CONFIG_DPP2 */
+
#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");
@@ -154,21 +142,17 @@
}
#endif /* CONFIG_TESTING_OPTIONS */
- if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len),
- curve->prime_len) < 0 ||
- dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 ||
- dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len),
- curve->prime_len) < 0)
+ Mx = wpabuf_put(msg, curve->prime_len);
+ My = wpabuf_put(msg, curve->prime_len);
+ if (crypto_ec_point_to_bin(ec, M, Mx, My))
goto fail;
+ os_memcpy(pkex->Mx, Mx, curve->prime_len);
+
out:
- wpabuf_free(M_buf);
- EC_POINT_free(M);
- EC_POINT_free(Qi);
- BN_clear_free(Mx);
- BN_clear_free(My);
- BN_CTX_free(bnctx);
- EC_GROUP_free(group);
+ crypto_ec_point_deinit(M, 1);
+ crypto_ec_point_deinit(Qi, 1);
+ crypto_ec_deinit(ec);
return msg;
fail:
wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request");
@@ -186,8 +170,8 @@
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
const u8 *own_mac,
- const char *identifier,
- const char *code)
+ const char *identifier, const char *code,
+ bool v2)
{
struct dpp_pkex *pkex;
@@ -204,6 +188,7 @@
return NULL;
pkex->msg_ctx = msg_ctx;
pkex->initiator = 1;
+ pkex->v2 = v2;
pkex->own_bi = bi;
os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
if (identifier) {
@@ -214,7 +199,7 @@
pkex->code = os_strdup(code);
if (!pkex->code)
goto fail;
- pkex->exchange_req = dpp_pkex_build_exchange_req(pkex);
+ pkex->exchange_req = dpp_pkex_build_exchange_req(pkex, v2);
if (!pkex->exchange_req)
goto fail;
return pkex;
@@ -227,14 +212,19 @@
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 *Nx, const u8 *Ny)
{
struct wpabuf *msg = NULL;
size_t attr_len;
const struct dpp_curve_params *curve = pkex->own_bi->curve;
- /* Initiator -> Responder: DPP Status, [identifier,] N */
+ /* Initiator -> Responder: DPP Status, [Protocol Version,] [identifier,]
+ * N */
attr_len = 4 + 1;
+#ifdef CONFIG_DPP2
+ if (pkex->v2)
+ attr_len += 4 + 1;
+#endif /* CONFIG_DPP2 */
if (pkex->identifier)
attr_len += 4 + os_strlen(pkex->identifier);
attr_len += 4 + 2 * curve->prime_len;
@@ -261,6 +251,15 @@
skip_status:
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_DPP2
+ if (pkex->v2) {
+ /* Protocol Version */
+ wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION);
+ wpabuf_put_le16(msg, 1);
+ wpabuf_put_u8(msg, DPP_VERSION);
+ }
+#endif /* CONFIG_DPP2 */
+
/* Code Identifier attribute */
if (pkex->identifier) {
wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
@@ -291,12 +290,9 @@
}
#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;
+ wpabuf_put_data(msg, Nx, curve->prime_len);
+ wpabuf_put_data(msg, Ny, curve->prime_len);
+ os_memcpy(pkex->Nx, Nx, curve->prime_len);
skip_encrypted_key:
if (status == DPP_STATUS_BAD_GROUP) {
@@ -345,24 +341,22 @@
const u8 *peer_mac,
const char *identifier,
const char *code,
- const u8 *buf, size_t len)
+ const u8 *buf, size_t len, bool v2)
{
const u8 *attr_group, *attr_id, *attr_key;
u16 attr_group_len, attr_id_len, attr_key_len;
const struct dpp_curve_params *curve = bi->curve;
u16 ike_group;
struct dpp_pkex *pkex = NULL;
- EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL;
- BN_CTX *bnctx = NULL;
- EC_GROUP *group = NULL;
- BIGNUM *Mx = NULL, *My = NULL;
- const EC_KEY *Y_ec;
- EC_KEY *X_ec = NULL;
- const EC_POINT *Y_point;
- BIGNUM *Nx = NULL, *Ny = NULL;
+ struct crypto_ec_point *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL,
+ *N = NULL;
+ struct crypto_ec *ec = NULL;
+ const struct crypto_ec_point *Y;
+ u8 *x_coord = NULL, *y_coord = NULL;
u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
size_t Kx_len;
int res;
+ u8 peer_version = 0;
if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
@@ -370,6 +364,24 @@
return NULL;
}
+#ifdef CONFIG_DPP2
+ if (v2) {
+ const u8 *version;
+ u16 version_len;
+
+ version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION,
+ &version_len);
+ if (!version || version_len < 1 || version[0] == 0) {
+ wpa_msg(msg_ctx, MSG_INFO,
+ "Missing or invalid Protocol Version attribute");
+ return NULL;
+ }
+ peer_version = version[0];
+ wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
+ peer_version);
+ }
+#endif /* CONFIG_DPP2 */
+
#ifdef CONFIG_TESTING_OPTIONS
if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) {
wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR,
@@ -404,6 +416,8 @@
pkex = os_zalloc(sizeof(*pkex));
if (!pkex)
goto fail;
+ pkex->v2 = v2;
+ pkex->peer_version = peer_version;
pkex->own_bi = bi;
pkex->failed = 1;
pkex->exchange_resp = dpp_pkex_build_exchange_resp(
@@ -423,44 +437,42 @@
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);
+ /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
+ Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : peer_mac, code, identifier,
+ &ec);
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)) {
+ X = crypto_ec_point_init(ec);
+ M = crypto_ec_point_from_bin(ec, attr_key);
+ if (!X || !M ||
+ crypto_ec_point_is_at_infinity(ec, M) ||
+ !crypto_ec_point_is_on_curve(ec, M) ||
+ crypto_ec_point_invert(ec, Qi) ||
+ crypto_ec_point_add(ec, M, Qi, X) ||
+ crypto_ec_point_is_at_infinity(ec, X) ||
+ !crypto_ec_point_is_on_curve(ec, X)) {
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);
+ crypto_ec_point_debug_print(ec, M, "DPP: M");
+ crypto_ec_point_debug_print(ec, X, "DPP: X'");
pkex = os_zalloc(sizeof(*pkex));
if (!pkex)
goto fail;
+ pkex->v2 = v2;
+ pkex->peer_version = peer_version;
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 (own_mac)
+ os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
+ if (peer_mac)
+ os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
if (identifier) {
pkex->identifier = os_strdup(identifier);
if (!pkex->identifier)
@@ -472,18 +484,20 @@
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)
+ x_coord = os_malloc(curve->prime_len);
+ y_coord = os_malloc(curve->prime_len);
+ if (!x_coord || !y_coord ||
+ crypto_ec_point_to_bin(ec, X, x_coord, y_coord))
goto fail;
- /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
- Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL);
+ pkex->x = crypto_ec_key_set_pub(curve->ike_group, x_coord,
+ y_coord, crypto_ec_prime_len(ec));
+ if (!pkex->x)
+ goto fail;
+
+ /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
+ Qr = dpp_pkex_derive_Qr(curve, v2 ? NULL : own_mac, code, identifier,
+ NULL);
if (!Qr)
goto fail;
@@ -507,24 +521,20 @@
goto fail;
/* N = Y + Qr */
- Y_ec = EVP_PKEY_get0_EC_KEY(pkex->y);
- if (!Y_ec)
+ Y = crypto_ec_key_get_public_key(pkex->y);
+ if (!Y)
goto fail;
- Y_point = EC_KEY_get0_public_key(Y_ec);
- if (!Y_point)
+ crypto_ec_point_debug_print(ec, Y, "DPP: Y");
+
+ N = crypto_ec_point_init(ec);
+ if (!N ||
+ crypto_ec_point_add(ec, Y, Qr, N) ||
+ crypto_ec_point_to_bin(ec, N, x_coord, y_coord))
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);
+ crypto_ec_point_debug_print(ec, N, "DPP: N");
pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK,
- Nx, Ny);
+ x_coord, y_coord);
if (!pkex->exchange_resp)
goto fail;
@@ -535,9 +545,10 @@
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,
+ /* z = HKDF(<>, info | M.x | N.x | code, K.x) */
+ res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->peer_mac,
+ pkex->v2 ? NULL : pkex->own_mac,
+ pkex->peer_version, DPP_VERSION,
pkex->Mx, curve->prime_len,
pkex->Nx, curve->prime_len, pkex->code,
Kx, Kx_len, pkex->z, curve->hash_len);
@@ -548,18 +559,14 @@
pkex->exchange_done = 1;
out:
- BN_CTX_free(bnctx);
- EC_POINT_free(Qi);
- EC_POINT_free(Qr);
- BN_free(Mx);
- BN_free(My);
- BN_free(Nx);
- BN_free(Ny);
- EC_POINT_free(M);
- EC_POINT_free(N);
- EC_POINT_free(X);
- EC_KEY_free(X_ec);
- EC_GROUP_free(group);
+ os_free(x_coord);
+ os_free(y_coord);
+ crypto_ec_point_deinit(Qi, 1);
+ crypto_ec_point_deinit(Qr, 1);
+ crypto_ec_point_deinit(M, 1);
+ crypto_ec_point_deinit(N, 1);
+ crypto_ec_point_deinit(X, 1);
+ crypto_ec_deinit(ec);
return pkex;
fail:
wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed");
@@ -688,17 +695,16 @@
{
const u8 *attr_status, *attr_id, *attr_key, *attr_group;
u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len;
- EC_GROUP *group = NULL;
- BN_CTX *bnctx = NULL;
+ struct crypto_ec *ec = NULL;
struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
const struct dpp_curve_params *curve = pkex->own_bi->curve;
- EC_POINT *Qr = NULL, *Y = NULL, *N = NULL;
- BIGNUM *Nx = NULL, *Ny = NULL;
- EC_KEY *Y_ec = NULL;
+ struct crypto_ec_point *Qr = NULL, *Y = NULL, *N = NULL;
+ u8 *x_coord = NULL, *y_coord = NULL;
size_t Jx_len, Kx_len;
u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
const u8 *addr[4];
size_t len[4];
+ size_t num_elem;
u8 u[DPP_MAX_HASH_LEN];
int res;
@@ -720,7 +726,26 @@
}
#endif /* CONFIG_TESTING_OPTIONS */
- os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
+#ifdef CONFIG_DPP2
+ if (pkex->v2) {
+ const u8 *version;
+ u16 version_len;
+
+ version = dpp_get_attr(buf, buflen, DPP_ATTR_PROTOCOL_VERSION,
+ &version_len);
+ if (!version || version_len < 1 || version[0] == 0) {
+ dpp_pkex_fail(pkex,
+ "Missing or invalid Protocol Version attribute");
+ return NULL;
+ }
+ pkex->peer_version = version[0];
+ wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u",
+ pkex->peer_version);
+ }
+#endif /* CONFIG_DPP2 */
+
+ if (peer_mac)
+ os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
&attr_status_len);
@@ -764,46 +789,40 @@
return NULL;
}
- /* Qr = H(MAC-Responder | [identifier |] code) * Pr */
- bnctx = BN_CTX_new();
- if (!bnctx)
- goto fail;
- Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
- pkex->identifier, bnctx, &group);
+ /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
+ Qr = dpp_pkex_derive_Qr(curve, pkex->v2 ? NULL : pkex->peer_mac,
+ pkex->code, pkex->identifier, &ec);
if (!Qr)
goto fail;
/* Y' = N - Qr */
- Y = EC_POINT_new(group);
- N = EC_POINT_new(group);
- Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
- Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
- if (!Y || !N || !Nx || !Ny ||
- EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 ||
- EC_POINT_is_at_infinity(group, N) ||
- !EC_POINT_is_on_curve(group, N, bnctx) ||
- EC_POINT_invert(group, Qr, bnctx) != 1 ||
- EC_POINT_add(group, Y, N, Qr, bnctx) != 1 ||
- EC_POINT_is_at_infinity(group, Y) ||
- !EC_POINT_is_on_curve(group, Y, bnctx)) {
+ Y = crypto_ec_point_init(ec);
+ N = crypto_ec_point_from_bin(ec, attr_key);
+ if (!Y || !N ||
+ crypto_ec_point_is_at_infinity(ec, N) ||
+ !crypto_ec_point_is_on_curve(ec, N) ||
+ crypto_ec_point_invert(ec, Qr) ||
+ crypto_ec_point_add(ec, N, Qr, Y) ||
+ crypto_ec_point_is_at_infinity(ec, Y) ||
+ !crypto_ec_point_is_on_curve(ec, Y)) {
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);
+ crypto_ec_point_debug_print(ec, N, "DPP: N");
+ crypto_ec_point_debug_print(ec, Y, "DPP: Y'");
pkex->exchange_done = 1;
/* ECDH: J = a * Y' */
- Y_ec = EC_KEY_new();
- if (!Y_ec ||
- EC_KEY_set_group(Y_ec, group) != 1 ||
- EC_KEY_set_public_key(Y_ec, Y) != 1)
+ x_coord = os_malloc(curve->prime_len);
+ y_coord = os_malloc(curve->prime_len);
+ if (!x_coord || !y_coord ||
+ crypto_ec_point_to_bin(ec, Y, x_coord, y_coord))
goto fail;
- pkex->y = EVP_PKEY_new();
- if (!pkex->y ||
- EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1)
+ pkex->y = crypto_ec_key_set_pub(curve->ike_group, x_coord, y_coord,
+ curve->prime_len);
+ if (!pkex->y)
goto fail;
if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0)
goto fail;
@@ -811,21 +830,29 @@
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
Jx, Jx_len);
- /* u = HMAC(J.x, MAC-Initiator | A.x | Y'.x | X.x) */
- A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
- Y_pub = dpp_get_pubkey_point(pkex->y, 0);
- X_pub = dpp_get_pubkey_point(pkex->x, 0);
+ /* u = HMAC(J.x, [MAC-Initiator |] A.x | Y'.x | X.x) */
+ A_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
+ Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
+ X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
if (!A_pub || !Y_pub || !X_pub)
goto fail;
- addr[0] = pkex->own_mac;
- len[0] = ETH_ALEN;
- addr[1] = wpabuf_head(A_pub);
- len[1] = wpabuf_len(A_pub) / 2;
- addr[2] = wpabuf_head(Y_pub);
- len[2] = wpabuf_len(Y_pub) / 2;
- addr[3] = wpabuf_head(X_pub);
- len[3] = wpabuf_len(X_pub) / 2;
- if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
+ num_elem = 0;
+ if (!pkex->v2) {
+ addr[num_elem] = pkex->own_mac;
+ len[num_elem] = ETH_ALEN;
+ num_elem++;
+ }
+ addr[num_elem] = wpabuf_head(A_pub);
+ len[num_elem] = wpabuf_len(A_pub) / 2;
+ num_elem++;
+ addr[num_elem] = wpabuf_head(Y_pub);
+ len[num_elem] = wpabuf_len(Y_pub) / 2;
+ num_elem++;
+ addr[num_elem] = wpabuf_head(X_pub);
+ len[num_elem] = wpabuf_len(X_pub) / 2;
+ num_elem++;
+ if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u)
+ < 0)
goto fail;
wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
@@ -836,9 +863,10 @@
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
Kx, Kx_len);
- /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
- */
- res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
+ /* z = HKDF(<>, info | M.x | N.x | code, K.x) */
+ res = dpp_pkex_derive_z(pkex->v2 ? NULL : pkex->own_mac,
+ pkex->v2 ? NULL : pkex->peer_mac,
+ DPP_VERSION, pkex->peer_version,
pkex->Mx, curve->prime_len,
attr_key /* N.x */, attr_key_len / 2,
pkex->code, Kx, Kx_len,
@@ -855,14 +883,12 @@
wpabuf_free(A_pub);
wpabuf_free(X_pub);
wpabuf_free(Y_pub);
- EC_POINT_free(Qr);
- EC_POINT_free(Y);
- EC_POINT_free(N);
- BN_free(Nx);
- BN_free(Ny);
- EC_KEY_free(Y_ec);
- BN_CTX_free(bnctx);
- EC_GROUP_free(group);
+ os_free(x_coord);
+ os_free(y_coord);
+ crypto_ec_point_deinit(Qr, 1);
+ crypto_ec_point_deinit(Y, 1);
+ crypto_ec_point_deinit(N, 1);
+ crypto_ec_deinit(ec);
return msg;
fail:
wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed");
@@ -995,6 +1021,7 @@
u16 wrapped_data_len, b_key_len, peer_u_len = 0;
const u8 *addr[4];
size_t len[4];
+ size_t num_elem;
u8 octet;
u8 *unwrapped = NULL;
size_t unwrapped_len = 0;
@@ -1077,21 +1104,29 @@
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
Jx, Jx_len);
- /* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */
- A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
- Y_pub = dpp_get_pubkey_point(pkex->y, 0);
- X_pub = dpp_get_pubkey_point(pkex->x, 0);
+ /* u' = HMAC(J'.x, [MAC-Initiator |] A'.x | Y.x | X'.x) */
+ A_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
+ Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
+ X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
if (!A_pub || !Y_pub || !X_pub)
goto fail;
- addr[0] = pkex->peer_mac;
- len[0] = ETH_ALEN;
- addr[1] = wpabuf_head(A_pub);
- len[1] = wpabuf_len(A_pub) / 2;
- addr[2] = wpabuf_head(Y_pub);
- len[2] = wpabuf_len(Y_pub) / 2;
- addr[3] = wpabuf_head(X_pub);
- len[3] = wpabuf_len(X_pub) / 2;
- if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
+ num_elem = 0;
+ if (!pkex->v2) {
+ addr[num_elem] = pkex->peer_mac;
+ len[num_elem] = ETH_ALEN;
+ num_elem++;
+ }
+ addr[num_elem] = wpabuf_head(A_pub);
+ len[num_elem] = wpabuf_len(A_pub) / 2;
+ num_elem++;
+ addr[num_elem] = wpabuf_head(Y_pub);
+ len[num_elem] = wpabuf_len(Y_pub) / 2;
+ num_elem++;
+ addr[num_elem] = wpabuf_head(X_pub);
+ len[num_elem] = wpabuf_len(X_pub) / 2;
+ num_elem++;
+ if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, num_elem, addr, len, u)
+ < 0)
goto fail;
peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
@@ -1114,19 +1149,27 @@
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
Lx, Lx_len);
- /* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */
- B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
+ /* v = HMAC(L.x, [MAC-Responder |] B.x | X'.x | Y.x) */
+ B_pub = crypto_ec_key_get_pubkey_point(pkex->own_bi->pubkey, 0);
if (!B_pub)
goto fail;
- addr[0] = pkex->own_mac;
- len[0] = ETH_ALEN;
- addr[1] = wpabuf_head(B_pub);
- len[1] = wpabuf_len(B_pub) / 2;
- addr[2] = wpabuf_head(X_pub);
- len[2] = wpabuf_len(X_pub) / 2;
- addr[3] = wpabuf_head(Y_pub);
- len[3] = wpabuf_len(Y_pub) / 2;
- if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
+ num_elem = 0;
+ if (!pkex->v2) {
+ addr[num_elem] = pkex->own_mac;
+ len[num_elem] = ETH_ALEN;
+ num_elem++;
+ }
+ addr[num_elem] = wpabuf_head(B_pub);
+ len[num_elem] = wpabuf_len(B_pub) / 2;
+ num_elem++;
+ addr[num_elem] = wpabuf_head(X_pub);
+ len[num_elem] = wpabuf_len(X_pub) / 2;
+ num_elem++;
+ addr[num_elem] = wpabuf_head(Y_pub);
+ len[num_elem] = wpabuf_len(Y_pub) / 2;
+ num_elem++;
+ if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v)
+ < 0)
goto fail;
wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
@@ -1156,6 +1199,7 @@
u16 wrapped_data_len, b_key_len, peer_v_len = 0;
const u8 *addr[4];
size_t len[4];
+ size_t num_elem;
u8 octet;
u8 *unwrapped = NULL;
size_t unwrapped_len = 0;
@@ -1239,21 +1283,29 @@
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
Lx, Lx_len);
- /* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */
- B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
- X_pub = dpp_get_pubkey_point(pkex->x, 0);
- Y_pub = dpp_get_pubkey_point(pkex->y, 0);
+ /* v' = HMAC(L.x, [MAC-Responder |] B'.x | X.x | Y'.x) */
+ B_pub = crypto_ec_key_get_pubkey_point(pkex->peer_bootstrap_key, 0);
+ X_pub = crypto_ec_key_get_pubkey_point(pkex->x, 0);
+ Y_pub = crypto_ec_key_get_pubkey_point(pkex->y, 0);
if (!B_pub || !X_pub || !Y_pub)
goto fail;
- addr[0] = pkex->peer_mac;
- len[0] = ETH_ALEN;
- addr[1] = wpabuf_head(B_pub);
- len[1] = wpabuf_len(B_pub) / 2;
- addr[2] = wpabuf_head(X_pub);
- len[2] = wpabuf_len(X_pub) / 2;
- addr[3] = wpabuf_head(Y_pub);
- len[3] = wpabuf_len(Y_pub) / 2;
- if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
+ num_elem = 0;
+ if (!pkex->v2) {
+ addr[num_elem] = pkex->peer_mac;
+ len[num_elem] = ETH_ALEN;
+ num_elem++;
+ }
+ addr[num_elem] = wpabuf_head(B_pub);
+ len[num_elem] = wpabuf_len(B_pub) / 2;
+ num_elem++;
+ addr[num_elem] = wpabuf_head(X_pub);
+ len[num_elem] = wpabuf_len(X_pub) / 2;
+ num_elem++;
+ addr[num_elem] = wpabuf_head(Y_pub);
+ len[num_elem] = wpabuf_len(Y_pub) / 2;
+ num_elem++;
+ if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, num_elem, addr, len, v)
+ < 0)
goto fail;
peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
@@ -1292,9 +1344,12 @@
return NULL;
bi->id = dpp_next_id(dpp);
bi->type = DPP_BOOTSTRAP_PKEX;
- os_memcpy(bi->mac_addr, peer, ETH_ALEN);
- bi->num_freq = 1;
- bi->freq[0] = freq;
+ if (peer)
+ os_memcpy(bi->mac_addr, peer, ETH_ALEN);
+ if (freq) {
+ bi->num_freq = 1;
+ bi->freq[0] = freq;
+ }
bi->curve = pkex->own_bi->curve;
bi->pubkey = pkex->peer_bootstrap_key;
pkex->peer_bootstrap_key = NULL;
@@ -1315,9 +1370,9 @@
os_free(pkex->identifier);
os_free(pkex->code);
- EVP_PKEY_free(pkex->x);
- EVP_PKEY_free(pkex->y);
- EVP_PKEY_free(pkex->peer_bootstrap_key);
+ crypto_ec_key_deinit(pkex->x);
+ crypto_ec_key_deinit(pkex->y);
+ crypto_ec_key_deinit(pkex->peer_bootstrap_key);
wpabuf_free(pkex->exchange_req);
wpabuf_free(pkex->exchange_resp);
os_free(pkex);
diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c
index c4a0273..7137bc5 100644
--- a/src/common/dpp_reconfig.c
+++ b/src/common/dpp_reconfig.c
@@ -7,8 +7,6 @@
*/
#include "utils/includes.h"
-#include <openssl/opensslv.h>
-#include <openssl/err.h>
#include "utils/common.h"
#include "utils/json.h"
@@ -40,8 +38,7 @@
struct dpp_reconfig_id *id)
{
struct wpabuf *msg = NULL;
- EVP_PKEY *csign = NULL;
- const unsigned char *p;
+ struct crypto_ec_key *csign = NULL;
struct wpabuf *uncomp;
u8 hash[SHA256_MAC_LEN];
const u8 *addr[1];
@@ -49,7 +46,7 @@
int res;
size_t attr_len;
const struct dpp_curve_params *own_curve;
- EVP_PKEY *own_key;
+ struct crypto_ec_key *own_key;
struct wpabuf *a_nonce = NULL, *e_id = NULL;
wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame");
@@ -61,16 +58,15 @@
goto fail;
}
- p = csign_key;
- csign = d2i_PUBKEY(NULL, &p, csign_key_len);
+ csign = crypto_ec_key_parse_pub(csign_key, csign_key_len);
if (!csign) {
wpa_printf(MSG_ERROR,
"DPP: Failed to parse local C-sign-key information");
goto fail;
}
- uncomp = dpp_get_pubkey_point(csign, 1);
- EVP_PKEY_free(csign);
+ uncomp = crypto_ec_key_get_pubkey_point(csign, 1);
+ crypto_ec_key_deinit(csign);
if (!uncomp)
goto fail;
addr[0] = wpabuf_head(uncomp);
@@ -88,8 +84,8 @@
goto fail;
}
- a_nonce = dpp_get_pubkey_point(id->a_nonce, 0);
- e_id = dpp_get_pubkey_point(id->e_prime_id, 0);
+ a_nonce = crypto_ec_key_get_pubkey_point(id->a_nonce, 0);
+ e_id = crypto_ec_key_get_pubkey_point(id->e_prime_id, 0);
if (!a_nonce || !e_id)
goto fail;
@@ -126,7 +122,7 @@
fail:
wpabuf_free(a_nonce);
wpabuf_free(e_id);
- EVP_PKEY_free(own_key);
+ crypto_ec_key_deinit(own_key);
return msg;
}
@@ -230,8 +226,8 @@
{
struct dpp_authentication *auth;
const struct dpp_curve_params *curve;
- EVP_PKEY *a_nonce, *e_prime_id;
- EC_POINT *e_id;
+ struct crypto_ec_key *a_nonce, *e_prime_id;
+ struct crypto_ec_point *e_id;
curve = dpp_get_curve_ike_group(group);
if (!curve) {
@@ -260,13 +256,13 @@
e_prime_id = dpp_set_pubkey_point(conf->csign, e_id_attr, e_id_len);
if (!e_prime_id) {
wpa_printf(MSG_INFO, "DPP: Invalid E'-id");
- EVP_PKEY_free(a_nonce);
+ crypto_ec_key_deinit(a_nonce);
return NULL;
}
dpp_debug_print_key("E'-id", e_prime_id);
e_id = dpp_decrypt_e_id(conf->pp_key, a_nonce, e_prime_id);
- EVP_PKEY_free(a_nonce);
- EVP_PKEY_free(e_prime_id);
+ crypto_ec_key_deinit(a_nonce);
+ crypto_ec_key_deinit(e_prime_id);
if (!e_id) {
wpa_printf(MSG_INFO, "DPP: Could not decrypt E'-id");
return NULL;
@@ -275,7 +271,7 @@
* Enrollee has already been started and is waiting for updated
* configuration instead of replying again before such configuration
* becomes available */
- EC_POINT_clear_free(e_id);
+ crypto_ec_point_deinit(e_id, 1);
auth = dpp_alloc_auth(dpp, msg_ctx);
if (!auth)
@@ -341,7 +337,7 @@
wpabuf_put_le16(clear, wpabuf_len(conn_status));
wpabuf_put_buf(clear, conn_status);
- pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
+ pr = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
if (!pr)
goto fail;
diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c
index 609c243..e88c6de 100644
--- a/src/common/dpp_tcp.c
+++ b/src/common/dpp_tcp.c
@@ -1,6 +1,7 @@
/*
* DPP over TCP
* Copyright (c) 2019-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -24,10 +25,13 @@
struct dpp_controller *ctrl;
struct dpp_relay_controller *relay;
struct dpp_global *global;
+ struct dpp_pkex *pkex;
struct dpp_authentication *auth;
void *msg_ctx;
void *cb_ctx;
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+ int (*pkex_done)(void *ctx, void *conn, struct dpp_bootstrap_info *bi);
+ bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
int sock;
u8 mac_addr[ETH_ALEN];
unsigned int freq;
@@ -71,9 +75,13 @@
struct dl_list conn; /* struct dpp_connection */
char *configurator_params;
enum dpp_netrole netrole;
+ struct dpp_bootstrap_info *pkex_bi;
+ char *pkex_code;
+ char *pkex_identifier;
void *msg_ctx;
void *cb_ctx;
int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+ bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
};
static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
@@ -82,6 +90,7 @@
int initiator);
static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx);
static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx);
+static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx);
static void dpp_connection_free(struct dpp_connection *conn)
@@ -97,9 +106,11 @@
conn, NULL);
eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL);
eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
+ eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
wpabuf_free(conn->msg);
wpabuf_free(conn->msg_out);
dpp_auth_deinit(conn->auth);
+ dpp_pkex_free(conn->pkex);
os_free(conn->name);
os_free(conn);
}
@@ -154,6 +165,24 @@
}
+static struct dpp_relay_controller *
+dpp_relay_controller_get_ctx(struct dpp_global *dpp, void *cb_ctx)
+{
+ struct dpp_relay_controller *ctrl;
+
+ if (!dpp)
+ return NULL;
+
+ dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
+ list) {
+ if (cb_ctx == ctrl->cb_ctx)
+ return ctrl;
+ }
+
+ return NULL;
+}
+
+
static void dpp_controller_gas_done(struct dpp_connection *conn)
{
struct dpp_authentication *auth = conn->auth;
@@ -219,6 +248,10 @@
dpp_controller_rx, conn, NULL) == 0)
conn->read_eloop = 1;
if (conn->on_tcp_tx_complete_remove) {
+ if (conn->auth && conn->auth->connect_on_tx_status &&
+ conn->tcp_msg_sent &&
+ conn->tcp_msg_sent(conn->cb_ctx, conn->auth))
+ return 0;
dpp_connection_remove(conn);
} else if (conn->auth && (conn->ctrl || conn->auth->configurator) &&
conn->on_tcp_tx_complete_gas_done) {
@@ -352,6 +385,16 @@
}
+static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct dpp_connection *conn = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Timeout while waiting for relayed connection to complete");
+ dpp_connection_remove(conn);
+}
+
+
static struct dpp_connection *
dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src,
unsigned int freq)
@@ -412,8 +455,8 @@
goto fail;
conn->write_eloop = 1;
- /* TODO: eloop timeout to clear a connection if it does not complete
- * properly */
+ eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
+ eloop_register_timeout(20, 0, dpp_relay_conn_timeout, conn, NULL);
dl_list_add(&ctrl->conn, &conn->list);
return conn;
@@ -465,7 +508,8 @@
int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
const u8 *buf, size_t len, unsigned int freq,
- const u8 *i_bootstrap, const u8 *r_bootstrap)
+ const u8 *i_bootstrap, const u8 *r_bootstrap,
+ void *cb_ctx)
{
struct dpp_relay_controller *ctrl;
struct dpp_connection *conn;
@@ -493,8 +537,9 @@
type == DPP_PA_RECONFIG_ANNOUNCEMENT) {
/* TODO: Could send this to all configured Controllers. For now,
* only the first Controller is supported. */
- ctrl = dl_list_first(&dpp->controllers,
- struct dpp_relay_controller, list);
+ ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
+ } else if (type == DPP_PA_PKEX_EXCHANGE_REQ) {
+ ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
} else {
if (!r_bootstrap)
return -1;
@@ -579,6 +624,8 @@
eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
}
os_free(ctrl->configurator_params);
+ os_free(ctrl->pkex_code);
+ os_free(ctrl->pkex_identifier);
os_free(ctrl);
}
@@ -641,10 +688,8 @@
}
if (dpp_set_configurator(conn->auth,
- conn->ctrl->configurator_params) < 0) {
- dpp_connection_remove(conn);
+ conn->ctrl->configurator_params) < 0)
return -1;
- }
return dpp_tcp_send_msg(conn, conn->auth->resp_msg);
}
@@ -670,7 +715,6 @@
return 0;
}
wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
- dpp_connection_remove(conn);
return -1;
}
@@ -744,6 +788,7 @@
wpa_msg(msg_ctx, MSG_INFO,
DPP_EVENT_CONF_SENT "wait_conn_status=1");
wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
+ auth->waiting_conn_status_result = 1;
eloop_cancel_timeout(
dpp_controller_conn_status_result_wait_timeout,
conn, NULL);
@@ -832,7 +877,6 @@
return -1;
if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
dpp_auth_deinit(auth);
- dpp_connection_remove(conn);
return -1;
}
@@ -929,6 +973,143 @@
}
+static int dpp_controller_rx_pkex_exchange_req(struct dpp_connection *conn,
+ const u8 *hdr, const u8 *buf,
+ size_t len)
+{
+ struct dpp_controller *ctrl = conn->ctrl;
+
+ if (!ctrl)
+ return 0;
+
+ wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request");
+
+ /* TODO: Support multiple PKEX codes by iterating over all the enabled
+ * values here */
+
+ if (!ctrl->pkex_code || !ctrl->pkex_bi) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No PKEX code configured - ignore request");
+ return 0;
+ }
+
+ if (conn->pkex || conn->auth) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Already in PKEX/Authentication session - ignore new PKEX request");
+ return 0;
+ }
+
+ conn->pkex = dpp_pkex_rx_exchange_req(conn->ctrl->global, ctrl->pkex_bi,
+ NULL, NULL,
+ ctrl->pkex_identifier,
+ ctrl->pkex_code,
+ buf, len, true);
+ if (!conn->pkex) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Failed to process the request");
+ return -1;
+ }
+
+ return dpp_tcp_send_msg(conn, conn->pkex->exchange_resp);
+}
+
+
+static int dpp_controller_rx_pkex_exchange_resp(struct dpp_connection *conn,
+ const u8 *hdr, const u8 *buf,
+ size_t len)
+{
+ struct dpp_pkex *pkex = conn->pkex;
+ struct wpabuf *msg;
+ int res;
+
+ wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response");
+
+ if (!pkex || !pkex->initiator || pkex->exchange_done) {
+ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+ return 0;
+ }
+
+ msg = dpp_pkex_rx_exchange_resp(pkex, NULL, buf, len);
+ if (!msg) {
+ wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request");
+ res = dpp_tcp_send_msg(conn, msg);
+ wpabuf_free(msg);
+ return res;
+}
+
+
+static int dpp_controller_rx_pkex_commit_reveal_req(struct dpp_connection *conn,
+ const u8 *hdr,
+ const u8 *buf, size_t len)
+{
+ struct dpp_pkex *pkex = conn->pkex;
+ struct wpabuf *msg;
+ int res;
+ struct dpp_bootstrap_info *bi;
+
+ wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request");
+
+ if (!pkex || pkex->initiator || !pkex->exchange_done) {
+ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+ return 0;
+ }
+
+ msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
+ if (!msg) {
+ wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response");
+ res = dpp_tcp_send_msg(conn, msg);
+ wpabuf_free(msg);
+ if (res < 0)
+ return res;
+ bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
+ if (!bi)
+ return -1;
+ conn->pkex = NULL;
+ return 0;
+}
+
+
+static int
+dpp_controller_rx_pkex_commit_reveal_resp(struct dpp_connection *conn,
+ const u8 *hdr,
+ const u8 *buf, size_t len)
+{
+ struct dpp_pkex *pkex = conn->pkex;
+ int res;
+ struct dpp_bootstrap_info *bi;
+
+ wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response");
+
+ if (!pkex || !pkex->initiator || !pkex->exchange_done) {
+ wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
+ return 0;
+ }
+
+ res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
+ if (res < 0) {
+ wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
+ return res;
+ }
+
+ bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
+ if (!bi)
+ return -1;
+ conn->pkex = NULL;
+
+ if (!conn->pkex_done)
+ return -1;
+ return conn->pkex_done(conn->cb_ctx, conn, bi);
+}
+
+
static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
size_t len)
{
@@ -988,6 +1169,22 @@
case DPP_PA_RECONFIG_AUTH_RESP:
return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos,
end - pos);
+ case DPP_PA_PKEX_V1_EXCHANGE_REQ:
+ wpa_printf(MSG_DEBUG,
+ "DPP: Ignore PKEXv1 Exchange Request - not supported over TCP");
+ return -1;
+ case DPP_PA_PKEX_EXCHANGE_REQ:
+ return dpp_controller_rx_pkex_exchange_req(conn, msg, pos,
+ end - pos);
+ case DPP_PA_PKEX_EXCHANGE_RESP:
+ return dpp_controller_rx_pkex_exchange_resp(conn, msg, pos,
+ end - pos);
+ case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
+ return dpp_controller_rx_pkex_commit_reveal_req(conn, msg, pos,
+ end - pos);
+ case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
+ return dpp_controller_rx_pkex_commit_reveal_resp(conn, msg, pos,
+ end - pos);
default:
/* TODO: missing messages types */
wpa_printf(MSG_DEBUG,
@@ -1131,6 +1328,52 @@
WLAN_PA_GAS_INITIAL_RESP);
}
+ if (!resp && auth->waiting_config && auth->peer_bi) {
+ char *buf = NULL, *name = "";
+ char band[200], *b_pos, *b_end;
+ int i, res, *opclass = auth->e_band_support;
+ char *mud_url = "N/A";
+
+ wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
+ if (auth->e_name) {
+ size_t e_len = os_strlen(auth->e_name);
+
+ buf = os_malloc(e_len * 4 + 1);
+ if (buf) {
+ printf_encode(buf, len * 4 + 1,
+ (const u8 *) auth->e_name, e_len);
+ name = buf;
+ }
+ }
+ band[0] = '\0';
+ b_pos = band;
+ b_end = band + sizeof(band);
+ for (i = 0; opclass && opclass[i]; i++) {
+ res = os_snprintf(b_pos, b_end - b_pos, "%s%d",
+ b_pos == band ? "" : ",", opclass[i]);
+ if (os_snprintf_error(b_end - b_pos, res)) {
+ *b_pos = '\0';
+ break;
+ }
+ b_pos += res;
+ }
+ if (auth->e_mud_url) {
+ size_t e_len = os_strlen(auth->e_mud_url);
+
+ if (!has_ctrl_char((const u8 *) auth->e_mud_url, e_len))
+ mud_url = auth->e_mud_url;
+ }
+ wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_NEEDED
+ "peer=%d net_role=%s name=\"%s\" opclass=%s mud_url=%s",
+ auth->peer_bi->id, dpp_netrole_str(auth->e_netrole),
+ name, band, mud_url);
+ os_free(buf);
+
+ conn->gas_comeback_in_progress = 1;
+ return dpp_tcp_send_comeback_delay(conn,
+ WLAN_PA_GAS_INITIAL_RESP);
+ }
+
return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_INITIAL_RESP, resp);
}
@@ -1508,6 +1751,7 @@
conn->msg_ctx = ctrl->msg_ctx;
conn->cb_ctx = ctrl->cb_ctx;
conn->process_conf_obj = ctrl->process_conf_obj;
+ conn->tcp_msg_sent = ctrl->tcp_msg_sent;
conn->sock = fd;
conn->netrole = ctrl->netrole;
@@ -1533,11 +1777,11 @@
}
-int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
- const struct hostapd_ip_addr *addr, int port, const char *name,
- enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx,
- int (*process_conf_obj)(void *ctx,
- struct dpp_authentication *auth))
+int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex,
+ const struct hostapd_ip_addr *addr, int port,
+ void *msg_ctx, void *cb_ctx,
+ int (*pkex_done)(void *ctx, void *conn,
+ struct dpp_bootstrap_info *bi))
{
struct dpp_connection *conn;
struct sockaddr_storage saddr;
@@ -1549,6 +1793,102 @@
hostapd_ip_txt(addr, txt, sizeof(txt)), port);
if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
addr, port) < 0) {
+ dpp_pkex_free(pkex);
+ return -1;
+ }
+
+ conn = os_zalloc(sizeof(*conn));
+ if (!conn) {
+ dpp_pkex_free(pkex);
+ return -1;
+ }
+
+ conn->msg_ctx = msg_ctx;
+ conn->cb_ctx = cb_ctx;
+ conn->pkex_done = pkex_done;
+ conn->global = dpp;
+ conn->pkex = pkex;
+ conn->sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (conn->sock < 0)
+ goto fail;
+
+ if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
+ wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
+ strerror(errno));
+ goto fail;
+ }
+
+ if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
+ if (errno != EINPROGRESS) {
+ wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
+ strerror(errno));
+ goto fail;
+ }
+
+ /*
+ * Continue connecting in the background; eloop will call us
+ * once the connection is ready (or failed).
+ */
+ }
+
+ if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
+ dpp_conn_tx_ready, conn, NULL) < 0)
+ goto fail;
+ conn->write_eloop = 1;
+
+ hdr = wpabuf_head(pkex->exchange_req);
+ end = hdr + wpabuf_len(pkex->exchange_req);
+ hdr += 2; /* skip Category and Actiom */
+ pos = hdr + DPP_HDR_LEN;
+ conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
+ if (!conn->msg_out)
+ goto fail;
+ /* Message will be sent in dpp_conn_tx_ready() */
+
+ /* TODO: eloop timeout to clear a connection if it does not complete
+ * properly */
+ dl_list_add(&dpp->tcp_init, &conn->list);
+ return 0;
+fail:
+ dpp_connection_free(conn);
+ return -1;
+}
+
+
+static int dpp_tcp_auth_start(struct dpp_connection *conn,
+ struct dpp_authentication *auth)
+{
+ const u8 *hdr, *pos, *end;
+
+ hdr = wpabuf_head(auth->req_msg);
+ end = hdr + wpabuf_len(auth->req_msg);
+ hdr += 2; /* skip Category and Actiom */
+ pos = hdr + DPP_HDR_LEN;
+ conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
+ if (!conn->msg_out)
+ return -1;
+ /* Message will be sent in dpp_conn_tx_ready() */
+ return 0;
+}
+
+
+int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
+ const struct hostapd_ip_addr *addr, int port, const char *name,
+ enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx,
+ int (*process_conf_obj)(void *ctx,
+ struct dpp_authentication *auth),
+ bool (*tcp_msg_sent)(void *ctx,
+ struct dpp_authentication *auth))
+{
+ struct dpp_connection *conn;
+ struct sockaddr_storage saddr;
+ socklen_t addrlen;
+ char txt[100];
+
+ wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
+ hostapd_ip_txt(addr, txt, sizeof(txt)), port);
+ if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
+ addr, port) < 0) {
dpp_auth_deinit(auth);
return -1;
}
@@ -1562,6 +1902,7 @@
conn->msg_ctx = msg_ctx;
conn->cb_ctx = cb_ctx;
conn->process_conf_obj = process_conf_obj;
+ conn->tcp_msg_sent = tcp_msg_sent;
conn->name = os_strdup(name ? name : "Test");
conn->netrole = netrole;
conn->global = dpp;
@@ -1594,14 +1935,8 @@
goto fail;
conn->write_eloop = 1;
- hdr = wpabuf_head(auth->req_msg);
- end = hdr + wpabuf_len(auth->req_msg);
- hdr += 2; /* skip Category and Actiom */
- pos = hdr + DPP_HDR_LEN;
- conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
- if (!conn->msg_out)
+ if (dpp_tcp_auth_start(conn, auth) < 0)
goto fail;
- /* Message will be sent in dpp_conn_tx_ready() */
/* TODO: eloop timeout to clear a connection if it does not complete
* properly */
@@ -1613,6 +1948,33 @@
}
+int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
+ struct dpp_authentication *auth, const char *name,
+ enum dpp_netrole netrole,
+ int (*process_conf_obj)(void *ctx,
+ struct dpp_authentication *auth),
+ bool (*tcp_msg_sent)(void *ctx,
+ struct dpp_authentication *auth))
+{
+ struct dpp_connection *conn = _conn;
+
+ /* Continue with Authentication exchange on an existing TCP connection.
+ */
+ conn->process_conf_obj = process_conf_obj;
+ conn->tcp_msg_sent = tcp_msg_sent;
+ os_free(conn->name);
+ conn->name = os_strdup(name ? name : "Test");
+ conn->netrole = netrole;
+ conn->auth = auth;
+
+ if (dpp_tcp_auth_start(conn, auth) < 0)
+ return -1;
+
+ dpp_conn_tx_ready(conn->sock, conn, NULL);
+ return 0;
+}
+
+
int dpp_controller_start(struct dpp_global *dpp,
struct dpp_controller_config *config)
{
@@ -1638,6 +2000,7 @@
ctrl->msg_ctx = config->msg_ctx;
ctrl->cb_ctx = config->cb_ctx;
ctrl->process_conf_obj = config->process_conf_obj;
+ ctrl->tcp_msg_sent = config->tcp_msg_sent;
ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
if (ctrl->sock < 0)
@@ -1693,6 +2056,13 @@
}
+void dpp_controller_stop_for_ctx(struct dpp_global *dpp, void *cb_ctx)
+{
+ if (dpp && dpp->controller && dpp->controller->cb_ctx == cb_ctx)
+ dpp_controller_stop(dpp);
+}
+
+
static bool dpp_tcp_peer_id_match(struct dpp_authentication *auth,
unsigned int id)
{
@@ -1756,6 +2126,23 @@
}
+void dpp_controller_pkex_add(struct dpp_global *dpp,
+ struct dpp_bootstrap_info *bi,
+ const char *code, const char *identifier)
+{
+ struct dpp_controller *ctrl = dpp->controller;
+
+ if (!ctrl)
+ return;
+
+ ctrl->pkex_bi = bi;
+ os_free(ctrl->pkex_code);
+ ctrl->pkex_code = code ? os_strdup(code) : NULL;
+ os_free(ctrl->pkex_identifier);
+ ctrl->pkex_identifier = identifier ? os_strdup(identifier) : NULL;
+}
+
+
void dpp_tcp_init_flush(struct dpp_global *dpp)
{
struct dpp_connection *conn, *tmp;
@@ -1791,4 +2178,65 @@
}
}
+
+bool dpp_tcp_conn_status_requested(struct dpp_global *dpp)
+{
+ struct dpp_connection *conn;
+
+ dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
+ if (conn->auth && conn->auth->conn_status_requested)
+ return true;
+ }
+
+ return false;
+}
+
+
+static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn,
+ enum dpp_status_error result,
+ const u8 *ssid, size_t ssid_len,
+ const char *channel_list)
+{
+ struct dpp_authentication *auth = conn->auth;
+ int res;
+ struct wpabuf *msg;
+
+ auth->conn_status_requested = 0;
+
+ msg = dpp_build_conn_status_result(auth, result, ssid, ssid_len,
+ channel_list);
+ if (!msg) {
+ dpp_connection_remove(conn);
+ return;
+ }
+
+ res = dpp_tcp_send_msg(conn, msg);
+ wpabuf_free(msg);
+
+ if (res < 0) {
+ dpp_connection_remove(conn);
+ return;
+ }
+
+ /* This exchange will be terminated in the TX status handler */
+ conn->on_tcp_tx_complete_remove = 1;
+}
+
+
+void dpp_tcp_send_conn_status(struct dpp_global *dpp,
+ enum dpp_status_error result,
+ const u8 *ssid, size_t ssid_len,
+ const char *channel_list)
+{
+ struct dpp_connection *conn;
+
+ dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
+ if (conn->auth && conn->auth->conn_status_requested) {
+ dpp_tcp_send_conn_status_msg(conn, result, ssid,
+ ssid_len, channel_list);
+ break;
+ }
+ }
+}
+
#endif /* CONFIG_DPP2 */
diff --git a/src/common/dragonfly.c b/src/common/dragonfly.c
index 547be66..1e84271 100644
--- a/src/common/dragonfly.c
+++ b/src/common/dragonfly.c
@@ -213,3 +213,37 @@
"dragonfly: Unable to get randomness for own scalar");
return -1;
}
+
+
+/* res = sqrt(val) */
+int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
+ struct crypto_bignum *res)
+{
+ const struct crypto_bignum *prime;
+ struct crypto_bignum *tmp, *one;
+ int ret = 0;
+ u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN];
+ size_t prime_len;
+
+ /* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */
+
+ prime = crypto_ec_get_prime(ec);
+ prime_len = crypto_ec_prime_len(ec);
+ tmp = crypto_bignum_init();
+ one = crypto_bignum_init_uint(1);
+
+ if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
+ prime_len) < 0 ||
+ (prime_bin[prime_len - 1] & 0x03) != 3 ||
+ !tmp || !one ||
+ /* tmp = (p+1)/4 */
+ crypto_bignum_add(prime, one, tmp) < 0 ||
+ crypto_bignum_rshift(tmp, 2, tmp) < 0 ||
+ /* res = sqrt(val) */
+ crypto_bignum_exptmod(val, tmp, prime, res) < 0)
+ ret = -1;
+
+ crypto_bignum_deinit(tmp, 0);
+ crypto_bignum_deinit(one, 0);
+ return ret;
+}
diff --git a/src/common/dragonfly.h b/src/common/dragonfly.h
index ec3dd59..84d67f5 100644
--- a/src/common/dragonfly.h
+++ b/src/common/dragonfly.h
@@ -27,5 +27,7 @@
struct crypto_bignum *_rand,
struct crypto_bignum *_mask,
struct crypto_bignum *scalar);
+int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
+ struct crypto_bignum *res);
#endif /* DRAGONFLY_H */
diff --git a/src/common/gas_server.c b/src/common/gas_server.c
index 5f44ffe..745a13f 100644
--- a/src/common/gas_server.c
+++ b/src/common/gas_server.c
@@ -2,6 +2,7 @@
* Generic advertisement service (GAS) server
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2020, The Linux Foundation
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -18,7 +19,7 @@
#define MAX_ADV_PROTO_ID_LEN 10
-#define GAS_QUERY_TIMEOUT 10
+#define GAS_QUERY_TIMEOUT 60
struct gas_server_handler {
struct dl_list list;
@@ -26,7 +27,7 @@
u8 adv_proto_id_len;
struct wpabuf * (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
const u8 *query, size_t query_len,
- u16 *comeback_delay);
+ int *comeback_delay);
void (*status_cb)(void *ctx, struct wpabuf *resp, int ok);
void *ctx;
struct gas_server *gas;
@@ -42,6 +43,7 @@
u8 dialog_token;
struct gas_server_handler *handler;
u16 comeback_delay;
+ bool initial_resp_sent;
};
struct gas_server {
@@ -86,25 +88,22 @@
static void
-gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler,
+gas_server_send_resp(struct gas_server *gas,
struct gas_server_response *response,
- const u8 *da, int freq, u8 dialog_token,
struct wpabuf *query_resp, u16 comeback_delay)
{
- size_t max_len = (freq > 56160) ? 928 : 1400;
+ struct gas_server_handler *handler = response->handler;
+ size_t max_len = (response->freq > 56160) ? 928 : 1400;
size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2;
size_t resp_frag_len;
struct wpabuf *resp;
if (comeback_delay == 0 && !query_resp) {
+ dl_list_del(&response->list);
gas_server_free_response(response);
return;
}
- response->freq = freq;
- response->handler = handler;
- os_memcpy(response->dst, da, ETH_ALEN);
- response->dialog_token = dialog_token;
if (comeback_delay) {
/* Need more time to prepare the response */
resp_frag_len = 0;
@@ -119,12 +118,14 @@
resp_frag_len = wpabuf_len(query_resp);
}
- resp = gas_build_initial_resp(dialog_token, WLAN_STATUS_SUCCESS,
+ resp = gas_build_initial_resp(response->dialog_token,
+ WLAN_STATUS_SUCCESS,
comeback_delay,
handler->adv_proto_id_len +
resp_frag_len);
if (!resp) {
wpabuf_free(query_resp);
+ dl_list_del(&response->list);
gas_server_free_response(response);
return;
}
@@ -152,8 +153,9 @@
}
response->offset = resp_frag_len;
response->resp = query_resp;
- dl_list_add(&gas->responses, &response->list);
- gas->tx(gas->ctx, freq, da, resp, comeback_delay ? 2000 : 0);
+ response->initial_resp_sent = true;
+ gas->tx(gas->ctx, response->freq, response->dst, resp,
+ comeback_delay ? 2000 : 0);
wpabuf_free(resp);
eloop_register_timeout(GAS_QUERY_TIMEOUT, 0,
gas_server_response_timeout, response, NULL);
@@ -223,25 +225,35 @@
wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response);
dl_list_for_each(handler, &gas->handlers, struct gas_server_handler,
list) {
- u16 comeback_delay = 0;
+ int comeback_delay = 0;
if (adv_proto_len < 1 + handler->adv_proto_id_len ||
os_memcmp(adv_proto + 1, handler->adv_proto_id,
handler->adv_proto_id_len) != 0)
continue;
+ response->freq = freq;
+ response->handler = handler;
+ os_memcpy(response->dst, sa, ETH_ALEN);
+ response->dialog_token = dialog_token;
+ dl_list_add(&gas->responses, &response->list);
+
wpa_printf(MSG_DEBUG,
"GAS: Calling handler for the requested Advertisement Protocol ID");
resp = handler->req_cb(handler->ctx, response, sa, query_req,
query_req_len, &comeback_delay);
wpa_hexdump_buf(MSG_MSGDUMP, "GAS: Response from the handler",
resp);
+ if (comeback_delay < 0) {
+ wpa_printf(MSG_DEBUG,
+ "GAS: Handler requested short delay before sending out the initial response");
+ return 0;
+ }
if (comeback_delay)
wpa_printf(MSG_DEBUG,
"GAS: Handler requested comeback delay: %u TU",
comeback_delay);
- gas_server_send_resp(gas, handler, response, sa, freq,
- dialog_token, resp, comeback_delay);
+ gas_server_send_resp(gas, response, resp, comeback_delay);
return 0;
}
@@ -484,11 +496,42 @@
if (!response || response->resp)
return -1;
+ if (!response->initial_resp_sent) {
+ wpa_printf(MSG_DEBUG, "GAS: Send the delayed initial response");
+ gas_server_send_resp(gas, response, resp, 0);
+ return 0;
+ }
+
response->resp = resp;
return 0;
}
+int gas_server_set_comeback_delay(struct gas_server *gas, void *resp_ctx,
+ u16 comeback_delay)
+{
+ struct gas_server_response *tmp, *response = NULL;
+
+ dl_list_for_each(tmp, &gas->responses, struct gas_server_response,
+ list) {
+ if (tmp == resp_ctx) {
+ response = tmp;
+ break;
+ }
+ }
+
+ if (!response || response->initial_resp_sent)
+ return -1;
+
+ wpa_printf(MSG_DEBUG,
+ "GAS: Send the delayed initial response with comeback delay %u",
+ comeback_delay);
+ gas_server_send_resp(gas, response, NULL, comeback_delay);
+
+ return 0;
+}
+
+
bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx)
{
struct gas_server_response *tmp;
@@ -552,7 +595,7 @@
struct wpabuf *
(*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
const u8 *query, size_t query_len,
- u16 *comeback_delay),
+ int *comeback_delay),
void (*status_cb)(void *ctx, struct wpabuf *resp,
int ok),
void *ctx)
diff --git a/src/common/gas_server.h b/src/common/gas_server.h
index db00f87..8d5eaa2 100644
--- a/src/common/gas_server.h
+++ b/src/common/gas_server.h
@@ -2,6 +2,7 @@
* Generic advertisement service (GAS) server
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2020, The Linux Foundation
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -25,7 +26,7 @@
struct wpabuf *
(*req_cb)(void *ctx, void *resp_ctx, const u8 *sa,
const u8 *query, size_t query_len,
- u16 *comeback_delay),
+ int *comeback_delay),
void (*status_cb)(void *ctx, struct wpabuf *resp,
int ok),
void *ctx);
@@ -34,6 +35,8 @@
int freq);
void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data,
size_t data_len, int ack);
+int gas_server_set_comeback_delay(struct gas_server *gas, void *resp_ctx,
+ u16 comeback_delay);
int gas_server_set_resp(struct gas_server *gas, void *resp_ctx,
struct wpabuf *resp);
bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx);
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index b8b886f..f168d4e 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -114,7 +114,7 @@
{
int ok, first;
int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
- 149, 157, 165, 184, 192 };
+ 149, 157, 165, 173, 184, 192 };
size_t k;
int ht40_plus, pri_chan, sec_chan;
@@ -293,87 +293,12 @@
}
-/*
- * Returns:
- * 0: no impact
- * 1: overlapping BSS
- * 2: overlapping BSS with 40 MHz intolerant advertisement
- */
-int check_bss_coex_40mhz(struct wpa_scan_res *bss, int pri_freq, int sec_freq)
-{
- int affected_start, affected_end;
- struct ieee802_11_elems elems;
- int pri_chan, sec_chan;
- int pri = bss->freq;
- int sec = pri;
-
- if (pri_freq == sec_freq)
- return 1;
-
- affected_start = (pri_freq + sec_freq) / 2 - 25;
- affected_end = (pri_freq + sec_freq) / 2 + 25;
-
- /* Check for overlapping 20 MHz BSS */
- if (check_20mhz_bss(bss, pri_freq, affected_start, affected_end)) {
- wpa_printf(MSG_DEBUG, "Overlapping 20 MHz BSS is found");
- return 1;
- }
-
- get_pri_sec_chan(bss, &pri_chan, &sec_chan);
-
- if (sec_chan) {
- if (sec_chan < pri_chan)
- sec = pri - 20;
- else
- sec = pri + 20;
- }
-
- if ((pri < affected_start || pri > affected_end) &&
- (sec < affected_start || sec > affected_end))
- return 0; /* not within affected channel range */
-
- wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
- " freq=%d pri=%d sec=%d",
- MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
-
- if (sec_chan) {
- if (pri_freq != pri || sec_freq != sec) {
- wpa_printf(MSG_DEBUG,
- "40 MHz pri/sec mismatch with BSS "
- MACSTR
- " <%d,%d> (chan=%d%c) vs. <%d,%d>",
- MAC2STR(bss->bssid),
- pri, sec, pri_chan,
- sec > pri ? '+' : '-',
- pri_freq, sec_freq);
- return 1;
- }
- }
-
- ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
- if (elems.ht_capabilities) {
- struct ieee80211_ht_capabilities *ht_cap =
- (struct ieee80211_ht_capabilities *)
- elems.ht_capabilities;
-
- if (le_to_host16(ht_cap->ht_capabilities_info) &
- HT_CAP_INFO_40MHZ_INTOLERANT) {
- wpa_printf(MSG_DEBUG,
- "40 MHz Intolerant is set on channel %d in BSS "
- MACSTR, pri, MAC2STR(bss->bssid));
- return 2;
- }
- }
-
- return 0;
-}
-
-
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
struct wpa_scan_results *scan_res, int pri_chan,
int sec_chan)
{
int pri_freq, sec_freq;
+ int affected_start, affected_end;
size_t i;
if (!mode || !scan_res || !pri_chan || !sec_chan ||
@@ -383,12 +308,70 @@
pri_freq = hw_get_freq(mode, pri_chan);
sec_freq = hw_get_freq(mode, sec_chan);
+ affected_start = (pri_freq + sec_freq) / 2 - 25;
+ affected_end = (pri_freq + sec_freq) / 2 + 25;
wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
- (pri_freq + sec_freq) / 2 - 25,
- (pri_freq + sec_freq) / 2 + 25);
+ affected_start, affected_end);
for (i = 0; i < scan_res->num; i++) {
- if (check_bss_coex_40mhz(scan_res->res[i], pri_freq, sec_freq))
+ struct wpa_scan_res *bss = scan_res->res[i];
+ int pri = bss->freq;
+ int sec = pri;
+ struct ieee802_11_elems elems;
+
+ /* Check for overlapping 20 MHz BSS */
+ if (check_20mhz_bss(bss, pri_freq, affected_start,
+ affected_end)) {
+ wpa_printf(MSG_DEBUG,
+ "Overlapping 20 MHz BSS is found");
return 0;
+ }
+
+ get_pri_sec_chan(bss, &pri_chan, &sec_chan);
+
+ if (sec_chan) {
+ if (sec_chan < pri_chan)
+ sec = pri - 20;
+ else
+ sec = pri + 20;
+ }
+
+ if ((pri < affected_start || pri > affected_end) &&
+ (sec < affected_start || sec > affected_end))
+ continue; /* not within affected channel range */
+
+ wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
+ " freq=%d pri=%d sec=%d",
+ MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
+
+ if (sec_chan) {
+ if (pri_freq != pri || sec_freq != sec) {
+ wpa_printf(MSG_DEBUG,
+ "40 MHz pri/sec mismatch with BSS "
+ MACSTR
+ " <%d,%d> (chan=%d%c) vs. <%d,%d>",
+ MAC2STR(bss->bssid),
+ pri, sec, pri_chan,
+ sec > pri ? '+' : '-',
+ pri_freq, sec_freq);
+ return 0;
+ }
+ }
+
+ ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems,
+ 0);
+ if (elems.ht_capabilities) {
+ struct ieee80211_ht_capabilities *ht_cap =
+ (struct ieee80211_ht_capabilities *)
+ elems.ht_capabilities;
+
+ if (le_to_host16(ht_cap->ht_capabilities_info) &
+ HT_CAP_INFO_40MHZ_INTOLERANT) {
+ wpa_printf(MSG_DEBUG,
+ "40 MHz Intolerant is set on channel %d in BSS "
+ MACSTR, pri, MAC2STR(bss->bssid));
+ return 0;
+ }
+ }
}
return 1;
@@ -405,7 +388,7 @@
int center_segment1, u32 vht_caps,
struct he_capabilities *he_cap)
{
- if (!he_cap)
+ if (!he_cap || !he_cap->he_supported)
he_enabled = 0;
os_memset(data, 0, sizeof(*data));
data->mode = mode;
@@ -417,7 +400,16 @@
data->sec_channel_offset = sec_channel_offset;
data->center_freq1 = freq + sec_channel_offset * 10;
data->center_freq2 = 0;
- data->bandwidth = sec_channel_offset ? 40 : 20;
+ if (oper_chwidth == CHANWIDTH_80MHZ)
+ data->bandwidth = 80;
+ else if (oper_chwidth == CHANWIDTH_160MHZ ||
+ oper_chwidth == CHANWIDTH_80P80MHZ)
+ data->bandwidth = 160;
+ else if (sec_channel_offset)
+ data->bandwidth = 40;
+ else
+ data->bandwidth = 20;
+
hostapd_encode_edmg_chan(enable_edmg, edmg_channel, channel,
&data->edmg);
@@ -441,9 +433,8 @@
"Segment 0 center frequency isn't set");
return -1;
}
-
- data->center_freq1 = data->freq;
- data->bandwidth = 20;
+ if (!sec_channel_offset)
+ data->center_freq1 = data->freq;
} else {
int freq1, freq2 = 0;
int bw = center_idx_to_bw_6ghz(center_segment0);
@@ -491,7 +482,10 @@
if (data->he_enabled) switch (oper_chwidth) {
case CHANWIDTH_USE_HT:
- if (mode == HOSTAPD_MODE_IEEE80211G && sec_channel_offset) {
+ if (sec_channel_offset == 0)
+ break;
+
+ if (mode == HOSTAPD_MODE_IEEE80211G) {
if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) {
wpa_printf(MSG_ERROR,
@@ -572,13 +566,19 @@
/* fall through */
case CHANWIDTH_80MHZ:
data->bandwidth = 80;
- if ((oper_chwidth == CHANWIDTH_80MHZ &&
- center_segment1) ||
- (oper_chwidth == CHANWIDTH_80P80MHZ &&
- !center_segment1) ||
- !sec_channel_offset) {
+ if (!sec_channel_offset) {
wpa_printf(MSG_ERROR,
- "80/80+80 MHz: center segment 1 wrong or no second channel offset");
+ "80/80+80 MHz: no second channel offset");
+ return -1;
+ }
+ if (oper_chwidth == CHANWIDTH_80MHZ && center_segment1) {
+ wpa_printf(MSG_ERROR,
+ "80 MHz: center segment 1 configured");
+ return -1;
+ }
+ if (oper_chwidth == CHANWIDTH_80P80MHZ && !center_segment1) {
+ wpa_printf(MSG_ERROR,
+ "80+80 MHz: center segment 1 not configured");
return -1;
}
if (!center_segment0) {
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index ddde36b..0e92aa0 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -32,7 +32,6 @@
int check_40mhz_5g(struct wpa_scan_results *scan_res,
struct hostapd_channel_data *pri_chan,
struct hostapd_channel_data *sec_chan);
-int check_bss_coex_40mhz(struct wpa_scan_res *bss, int pri_freq, int sec_freq);
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
struct wpa_scan_results *scan_res, int pri_chan,
int sec_chan);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index fa39761..adc6f59 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1017,8 +1017,8 @@
return HOSTAPD_MODE_IEEE80211A;
}
- /* 5 GHz, channels 100..140 */
- if (freq >= 5000 && freq <= 5700) {
+ /* 5 GHz, channels 100..144 */
+ if (freq >= 5500 && freq <= 5720) {
if ((freq - 5000) % 5)
return NUM_HOSTAPD_MODES;
@@ -1537,6 +1537,16 @@
}
+/*
+ * 802.11-2020: Table E-4 - Global operating classes
+ * DFS_50_100_Behavior: 118, 119, 120, 121, 122, 123
+ */
+int is_dfs_global_op_class(u8 op_class)
+{
+ return (op_class >= 118) && (op_class <= 123);
+}
+
+
static int is_11b(u8 rate)
{
return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16
@@ -1901,10 +1911,10 @@
*/
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
- { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, NO_P2P_SUPP },
- { HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP },
- { HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP },
- { HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
@@ -2239,6 +2249,9 @@
int center_idx_to_bw_6ghz(u8 idx)
{
+ /* Channel: 2 */
+ if (idx == 2)
+ return 0; /* 20 MHz */
/* channels: 1, 5, 9, 13... */
if ((idx & 0x3) == 0x1)
return 0; /* 20 MHz */
@@ -2297,6 +2310,30 @@
}
+/**
+ * get_6ghz_sec_channel - Get the relative position of the secondary channel
+ * to the primary channel in 6 GHz
+ * @channel: Primary channel to be checked for (in global op class 131)
+ * Returns: 1 = secondary channel above, -1 = secondary channel below
+ */
+
+int get_6ghz_sec_channel(int channel)
+{
+ /*
+ * In the 6 GHz band, primary channels are numbered as 1, 5, 9, 13.., so
+ * the 40 MHz channels are formed with the channel pairs as (1,5),
+ * (9,13), (17,21)..
+ * The secondary channel for a given primary channel is below the
+ * primary channel for the channels 5, 13, 21.. and it is above the
+ * primary channel for the channels 1, 9, 17..
+ */
+
+ if (((channel - 1) / 4) % 2)
+ return -1;
+ return 1;
+}
+
+
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len)
{
@@ -2407,6 +2444,35 @@
}
+bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
+ unsigned int capab)
+{
+ const u8 *end;
+ size_t flen, i;
+ u32 capabs = 0;
+
+ if (!rsnxe || rsnxe_len == 0)
+ return false;
+ end = rsnxe + rsnxe_len;
+ flen = (rsnxe[0] & 0x0f) + 1;
+ if (rsnxe + flen > end)
+ return false;
+ if (flen > 4)
+ flen = 4;
+ for (i = 0; i < flen; i++)
+ capabs |= rsnxe[i] << (8 * i);
+
+ return capabs & BIT(capab);
+}
+
+
+bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
+{
+ return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL,
+ rsnxe ? rsnxe[1] : 0, capab);
+}
+
+
void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel,
int primary_channel,
struct ieee80211_edmg_config *edmg)
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index e4992b3..ec6556f 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -218,6 +218,7 @@
int sec_channel, u8 *op_class, u8 *channel);
int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes,
u16 num_modes);
+int is_dfs_global_op_class(u8 op_class);
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
@@ -264,11 +265,15 @@
bool is_6ghz_freq(int freq);
bool is_6ghz_op_class(u8 op_class);
bool is_6ghz_psc_frequency(int freq);
+int get_6ghz_sec_channel(int channel);
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len);
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
+bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
+ unsigned int capab);
+bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab);
int op_class_to_bandwidth(u8 op_class);
int op_class_to_ch_width(u8 op_class);
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index c385923..5ee691b 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -22,7 +22,7 @@
#define WLAN_FC_PWRMGT 0x1000
#define WLAN_FC_MOREDATA 0x2000
#define WLAN_FC_ISWEP 0x4000
-#define WLAN_FC_ORDER 0x8000
+#define WLAN_FC_HTC 0x8000
#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2)
#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4)
@@ -446,6 +446,7 @@
#define WLAN_EID_WHITE_SPACE_MAP 205
#define WLAN_EID_FTM_PARAMETERS 206
#define WLAN_EID_S1G_BCN_COMPAT 213
+#define WLAN_EID_TWT 216
#define WLAN_EID_S1G_CAPABILITIES 217
#define WLAN_EID_VENDOR_SPECIFIC 221
#define WLAN_EID_S1G_OPERATION 232
@@ -603,6 +604,10 @@
#define WLAN_ACTION_ROBUST_AV_STREAMING 19
#define WLAN_ACTION_UNPROTECTED_DMG 20
#define WLAN_ACTION_VHT 21
+#define WLAN_ACTION_S1G 22
+#define WLAN_ACTION_S1G_RELAY 23
+#define WLAN_ACTION_FLOW_CONTROL 24
+#define WLAN_ACTION_CTRL_RESP_MCS_NEG 25
#define WLAN_ACTION_FILS 26
#define WLAN_ACTION_PROTECTED_FTM 34
#define WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED 126
@@ -820,6 +825,19 @@
NAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10
};
+/* Unprotected S1G Action field values for WLAN_ACTION_S1G */
+#define S1G_ACT_AID_SWITCH_REQUEST 0
+#define S1G_ACT_AID_SWITCH_RESPONSE 1
+#define S1G_ACT_SYNC_CONTROL 2
+#define S1G_ACT_STA_INFO_ANNOUNCE 3
+#define S1G_ACT_EDCA_PARAM_SET 4
+#define S1G_ACT_EL_OPERATION 5
+#define S1G_ACT_TWT_SETUP 6
+#define S1G_ACT_TWT_TEARDOWN 7
+#define S1G_ACT_SECT_GROUP_ID_LIST 8
+#define S1G_ACT_SECT_ID_FEEDBACK 9
+#define S1G_ACT_TWT_INFORMATION 11
+
/*
* IEEE P802.11-REVmc/D5.0 Table 9-81 - Measurement type definitions for
* measurement requests
@@ -1325,6 +1343,7 @@
#define CHANWIDTH_4320MHZ 5
#define CHANWIDTH_6480MHZ 6
#define CHANWIDTH_8640MHZ 7
+#define CHANWIDTH_40MHZ_6GHZ 8
#define HE_NSS_MAX_STREAMS 8
@@ -1348,6 +1367,10 @@
#define DPP_CC_OUI_TYPE 0x1e
#define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f
#define SAE_PK_OUI_TYPE 0x1f
+#define QM_IE_VENDOR_TYPE 0x506f9a22
+#define QM_IE_OUI_TYPE 0x22
+#define WFA_CAPA_IE_VENDOR_TYPE 0x506f9a23
+#define WFA_CAPA_OUI_TYPE 0x23
#define MULTI_AP_SUB_ELEM_TYPE 0x06
#define MULTI_AP_TEAR_DOWN BIT(4)
@@ -1645,6 +1668,7 @@
#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)
#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)
#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)
+#define P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE BIT(6)
/* P2P Capability - Group Capability bitmap */
#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)
@@ -2174,6 +2198,7 @@
* and optional variable length PPE Thresholds field. */
u8 optional[33];
} STRUCT_PACKED;
+#define IEEE80211_HE_CAPAB_MIN_LEN (6 + 11)
struct ieee80211_he_operation {
le32 he_oper_params; /* HE Operation Parameters[3] and
@@ -2349,6 +2374,26 @@
/* B7: Reserved if sent by an AP; More Data Ack if sent by a non-AP STA */
#define HE_QOS_INFO_MORE_DATA_ACK ((u8) (BIT(7)))
+/*
+ * IEEE Std 802.11-2020 and IEEE Std 802.11ax-2021
+ * 9.4.2.170 Reduced Neighbor Report element
+ */
+#define RNR_HEADER_LEN 2
+#define RNR_TBTT_HEADER_LEN 4
+#define RNR_TBTT_INFO_COUNT(x) (((x) & 0xf) << 4)
+#define RNR_TBTT_INFO_COUNT_MAX 16
+#define RNR_TBTT_INFO_LEN 13
+#define RNR_NEIGHBOR_AP_OFFSET_UNKNOWN 255
+/* Figure 9-632a - BSS Parameters subfield format */
+#define RNR_BSS_PARAM_OCT_RECOMMENDED BIT(0)
+#define RNR_BSS_PARAM_SAME_SSID BIT(1)
+#define RNR_BSS_PARAM_MULTIPLE_BSSID BIT(2)
+#define RNR_BSS_PARAM_TRANSMITTED_BSSID BIT(3)
+#define RNR_BSS_PARAM_MEMBER_CO_LOCATED_ESS BIT(4)
+#define RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE BIT(5)
+#define RNR_BSS_PARAM_CO_LOCATED BIT(6)
+#define RNR_20_MHZ_PSD_MAX_TXPOWER 255 /* dBm */
+
/* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */
#define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6
#define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET 7
@@ -2453,4 +2498,35 @@
*/
#define FD_MAX_INTERVAL_6GHZ 20 /* TUs */
+/* Protected Vendor-specific QoS Management Action frame identifiers - WFA */
+#define QM_ACTION_VENDOR_TYPE 0x506f9a1a
+#define QM_ACTION_OUI_TYPE 0x1a
+
+/* QoS Management Action frame OUI subtypes */
+#define QM_DSCP_POLICY_QUERY 0
+#define QM_DSCP_POLICY_REQ 1
+#define QM_DSCP_POLICY_RESP 2
+
+/* QoS Management attributes */
+enum qm_attr_id {
+ QM_ATTR_PORT_RANGE = 1,
+ QM_ATTR_DSCP_POLICY = 2,
+ QM_ATTR_TCLAS = 3,
+ QM_ATTR_DOMAIN_NAME = 4,
+};
+
+/* DSCP Policy attribute - Request Type */
+enum dscp_policy_request_type {
+ DSCP_POLICY_REQ_ADD = 0, /* ADD/UPDATE */
+ DSCP_POLICY_REQ_REMOVE = 1,
+};
+
+/* Request/Response Control field of DSCP Policy Request/Response frame */
+#define DSCP_POLICY_CTRL_MORE BIT(0)
+#define DSCP_POLICY_CTRL_RESET BIT(1)
+
+/* Wi-Fi Alliance Capabilities element - Capabilities field */
+#define WFA_CAPA_QM_DSCP_POLICY BIT(0)
+#define WFA_CAPA_QM_UNSOLIC_DSCP BIT(1)
+
#endif /* IEEE802_11_DEFS_H */
diff --git a/src/common/ptksa_cache.c b/src/common/ptksa_cache.c
index 6a053d6..8fcb135 100644
--- a/src/common/ptksa_cache.c
+++ b/src/common/ptksa_cache.c
@@ -269,7 +269,7 @@
u32 life_time,
const struct wpa_ptk *ptk)
{
- struct ptksa_cache_entry *entry, *tmp;
+ struct ptksa_cache_entry *entry, *tmp, *tmp2 = NULL;
struct os_reltime now;
if (!ptksa || !ptk || !addr || !life_time || cipher == WPA_CIPHER_NONE)
@@ -296,21 +296,21 @@
entry->expiration = now.sec + life_time;
dl_list_for_each(tmp, &ptksa->ptksa, struct ptksa_cache_entry, list) {
- if (tmp->expiration > entry->expiration)
+ if (tmp->expiration > entry->expiration) {
+ tmp2 = tmp;
break;
+ }
}
/*
- * If the list was empty add to the head; otherwise if the expiration is
- * later then all other entries, add it to the end of the list;
+ * If the expiration is later then all other or the list is empty
+ * entries, add it to the end of the list;
* otherwise add it before the relevant entry.
*/
- if (!tmp)
- dl_list_add(&ptksa->ptksa, &entry->list);
- else if (tmp->expiration < entry->expiration)
- dl_list_add(&tmp->list, &entry->list);
+ if (tmp2)
+ dl_list_add(&tmp2->list, &entry->list);
else
- dl_list_add_tail(&tmp->list, &entry->list);
+ dl_list_add_tail(&ptksa->ptksa, &entry->list);
ptksa->n_ptksa++;
wpa_printf(MSG_DEBUG,
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index f7e5571..0f7d3af 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -512,7 +512,9 @@
* @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to
* configure parameters per peer to capture Channel Frequency Response
* (CFR) and enable Periodic CFR capture. The attributes for this command
- * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr.
+ * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr. This command
+ * can also be used to send CFR data from the driver to userspace when
+ * netlink events are used to send CFR data.
*
* @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes
* in throughput dynamically. The driver estimates the throughput based on
@@ -620,7 +622,14 @@
* This new command is alternative to existing command
* QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event
* is using stream of bytes instead of structured data using vendor
- * attributes.
+ * attributes. User space sends unsafe frequency ranges to the driver using
+ * a nested attribute %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE. On
+ * reception of this command, the driver shall check if an interface is
+ * operating on an unsafe frequency and the driver shall try to move to a
+ * safe channel when needed. If the driver is not able to find a safe
+ * channel the interface can keep operating on an unsafe channel with the
+ * TX power limit derived based on internal configurations like
+ * regulatory/SAR rules.
*
* @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to
* add the STA node details in driver/firmware. Attributes for this event
@@ -699,7 +708,86 @@
* The host driver selects Tx VDEV, and notifies user. The attributes
* used with this event are defined in enum
* qca_wlan_vendor_attr_mbssid_tx_vdev_status.
+ * This event contains Tx VDEV group information, other VDEVs
+ * interface index, and status information.
*
+ * @QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY: Vendor command to
+ * configure the concurrent session policies when multiple STA interfaces
+ * are (getting) active. The attributes used by this command are defined
+ * in enum qca_wlan_vendor_attr_concurrent_sta_policy.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS: Userspace can use this command
+ * to query usable channels for different interface types such as STA,
+ * AP, P2P GO, P2P Client, NAN, etc. The driver shall report all usable
+ * channels in the response based on country code, different static
+ * configurations, concurrency combinations, etc. The attributes used
+ * with this command are defined in
+ * enum qca_wlan_vendor_attr_usable_channels.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY: This vendor subcommand is used
+ * to get DFS radar history from the driver to userspace. The driver
+ * returns QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES attribute with an
+ * array of nested entries.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD: Userspace can use this command to
+ * enable/disable mDNS offload to the firmware. The attributes used with
+ * this command are defined in enum qca_wlan_vendor_attr_mdns_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE: This vendor subcommand is used
+ * to set packet monitor mode that aims to send the specified set of TX and
+ * RX frames on the current client interface to an active monitor
+ * interface. If this monitor mode is set, the driver will send the
+ * configured frames, from the interface on which the command is issued, to
+ * an active monitor interface. The attributes used with this command are
+ * defined in enum qca_wlan_vendor_attr_set_monitor_mode.
+ *
+ * Though the monitor mode is configured for the respective
+ * Data/Management/Control frames, it is up to the respective WLAN
+ * driver/firmware/hardware designs to consider the possibility of sending
+ * these frames over the monitor interface. For example, the Control frames
+ * are handled within the hardware and thus passing such frames over the
+ * monitor interface is left to the respective designs.
+ *
+ * Also, this monitor mode is governed to behave accordingly in
+ * suspend/resume states. If the firmware handles any of such frames in
+ * suspend state without waking up the host and if the monitor mode is
+ * configured to notify all such frames, the firmware is expected to resume
+ * the host and forward the respective frames to the monitor interface.
+ * Please note that such a request to get the frames over the monitor
+ * interface will have a definite power implication.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS: This vendor subcommand is used both
+ * as a request to set the driver/firmware with the parameters to trigger
+ * the roaming events, and also used by the driver/firmware to pass on the
+ * various roam events to userspace.
+ * Applicable only for the STA mode. The attributes used with this command
+ * are defined in enum qca_wlan_vendor_attr_roam_events.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG: Subcommand to set or reset the
+ * rate mask config for a list of PHY types. Userspace shall provide an
+ * array of the vendor attributes defined in
+ * enum qca_wlan_vendor_attr_ratemask_params.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA: Multi-channel Concurrency (MCC) occurs
+ * when two interfaces are active on the same band, using two different
+ * home channels, and only supported by a single radio. In this scenario
+ * the device must split the use of the radio between the two interfaces.
+ * The percentage of time allocated to a given interface is the quota.
+ * Depending on the configuration, the quota can either be fixed or
+ * dynamic.
+ *
+ * When used as an event, the device will report the quota type, and for
+ * all interfaces operating in MCC it will report the current quota.
+ * When used as a command, the device can be configured for a specific
+ * quota type, and in the case of a fixed quota, the quota to apply to one
+ * of the interfaces.
+ *
+ * Applications can use the event to do TX bitrate control based on the
+ * information, and can use the command to explicitly set the quota to
+ * enhance performance in specific scenarios.
+ *
+ * The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_mcc_quota.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -886,6 +974,15 @@
QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194,
QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195,
QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196,
+ QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY = 197,
+ QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198,
+ QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY = 199,
+ QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD = 200,
+ /* 201 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203,
+ QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG = 204,
+ QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA = 205,
};
enum qca_wlan_vendor_attr {
@@ -1124,7 +1221,7 @@
* @QCA_ROAM_REASON_CONGESTION: Roam triggered considering the connected channel
* or environment being very noisy or congested.
*
- * @QCA_ROAM_REASON_EXPLICIT_REQUEST: Roam triggered due to an explicit request
+ * @QCA_ROAM_REASON_USER_TRIGGER: Roam triggered due to an explicit request
* from the user (user space).
*
* @QCA_ROAM_REASON_BTM: Roam triggered due to BTM Request frame received from
@@ -1132,6 +1229,26 @@
*
* @QCA_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization
* breaching out the configured threshold.
+ *
+ * @QCA_ROAM_REASON_WTC: Roam triggered due to Wireless to Cellular BSS
+ * transition request.
+ *
+ * @QCA_ROAM_REASON_IDLE: Roam triggered when device is suspended, there is no
+ * data activity with the AP and the current RSSI falls below a certain
+ * threshold.
+ *
+ * @QCA_ROAM_REASON_DISCONNECTION: Roam triggered due to Deauthentication or
+ * Disassociation frames received from the connected AP.
+ *
+ * @QCA_ROAM_REASON_PERIODIC_TIMER: Roam triggered as part of the periodic scan
+ * that happens when there is no candidate AP found during the poor RSSI scan
+ * trigger.
+ *
+ * @QCA_ROAM_REASON_BACKGROUND_SCAN: Roam triggered based on the scan results
+ * obtained from an external scan (not aimed at roaming).
+ *
+ * @QCA_ROAM_REASON_BT_ACTIVITY: Roam triggered due to Bluetooth connection is
+ * established when the station is connected in the 2.4 GHz band.
*/
enum qca_roam_reason {
QCA_ROAM_REASON_UNKNOWN,
@@ -1143,6 +1260,12 @@
QCA_ROAM_REASON_USER_TRIGGER,
QCA_ROAM_REASON_BTM,
QCA_ROAM_REASON_BSS_LOAD,
+ QCA_ROAM_REASON_WTC,
+ QCA_ROAM_REASON_IDLE,
+ QCA_ROAM_REASON_DISCONNECTION,
+ QCA_ROAM_REASON_PERIODIC_TIMER,
+ QCA_ROAM_REASON_BACKGROUND_SCAN,
+ QCA_ROAM_REASON_BT_ACTIVITY,
};
enum qca_wlan_vendor_attr_roam_auth {
@@ -1362,6 +1485,16 @@
* Used with event to notify the EDMG channel number selected in ACS
* operation.
* EDMG primary channel is indicated by QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP: Optional (u16).
+ * Used with event to notify the puncture pattern selected in ACS operation.
+ * Encoding for this attribute will follow the convention used in the Disabled
+ * Subchannel Bitmap field of the EHT Operation IE.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED: Flag attribute.
+ * Used with command to configure ACS operation for EHT mode.
+ * Disable (flag attribute not present) - EHT disabled and
+ * Enable (flag attribute present) - EHT enabled.
*/
enum qca_wlan_vendor_attr_acs_offload {
QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
@@ -1382,6 +1515,8 @@
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15,
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16,
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17,
+ QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18,
+ QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19,
/* keep last */
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
@@ -1687,32 +1822,62 @@
};
/**
- * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture
- * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32)
- * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value
- * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized
- * SOC timer value at TSF capture
+ * enum qca_vendor_attr_tsf_cmd: Vendor attributes for TSF capture
+ * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: Required (u32)
+ * Specify the TSF command. Possible values are defined in
+ * &enum qca_tsf_cmd.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64)
+ * This attribute contains TSF timer value. This attribute is only available
+ * in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64)
+ * This attribute contains SOC timer value at TSF capture. This attribute is
+ * only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL: Optional (u32)
+ * This attribute is used to provide TSF sync interval and only applicable when
+ * TSF command is %QCA_TSF_SYNC_START. If this attribute is not provided, the
+ * driver will use the default value. Time unit is in milliseconds.
*/
enum qca_vendor_attr_tsf_cmd {
QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_TSF_CMD,
QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE,
QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE,
+ QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL,
QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_TSF_MAX =
QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1
};
/**
- * enum qca_tsf_operation: TSF driver commands
+ * enum qca_tsf_cmd: TSF driver commands
* @QCA_TSF_CAPTURE: Initiate TSF Capture
* @QCA_TSF_GET: Get TSF capture value
* @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
+ * @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target
+ * will automatically send TSF report to the host. To query
+ * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be
+ * initiated first.
+ * @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target
+ * will not automatically send TSF report to the host. If
+ * %QCA_TSF_AUTO_REPORT_ENABLE is initiated and
+ * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this
+ * operation needs to be initiated.
+ * @QCA_TSF_SYNC_START: Start periodic TSF sync feature. The driver periodically
+ * fetches TSF and host time mapping from the firmware with interval configured
+ * through the %QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL attribute. If the
+ * interval value is not provided the driver will use the default value. The
+ * userspace can query the TSF and host time mapping via the %QCA_TSF_GET
+ * command.
+ * @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature.
*/
enum qca_tsf_cmd {
QCA_TSF_CAPTURE,
QCA_TSF_GET,
QCA_TSF_SYNC_GET,
+ QCA_TSF_AUTO_REPORT_ENABLE,
+ QCA_TSF_AUTO_REPORT_DISABLE,
+ QCA_TSF_SYNC_START,
+ QCA_TSF_SYNC_STOP,
};
/**
@@ -1806,6 +1971,23 @@
};
/**
+ * enum qca_wlan_vendor_scan_priority - Specifies the valid values that the
+ * vendor scan attribute QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY can take.
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW: Very low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW: Low priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM: Medium priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH: High priority
+ * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH: Very high priority
+ */
+enum qca_wlan_vendor_scan_priority {
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW = 0,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW = 1,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM = 2,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH = 3,
+ QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH = 4,
+};
+
+/**
* enum qca_wlan_vendor_attr_scan - Specifies vendor scan attributes
*
* @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan
@@ -1830,6 +2012,11 @@
* @QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME: Unsigned 64-bit dwell time in
* microseconds. This is a common value which applies across all
* frequencies specified by QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES.
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY: Priority of vendor scan relative to
+ * other scan requests. It is a u32 attribute and takes values from enum
+ * qca_wlan_vendor_scan_priority. This is an optional attribute.
+ * If this attribute is not configured, the driver shall use
+ * QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH as the priority of vendor scan.
*/
enum qca_wlan_vendor_attr_scan {
QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
@@ -1845,6 +2032,7 @@
QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10,
QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11,
QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12,
+ QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13,
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
@@ -2399,6 +2587,46 @@
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78,
+ /*
+ * 8-bit unsigned value. This attribute, when set, indicates whether the
+ * specified interface is the primary STA interface when there are more
+ * than one STA interfaces concurrently active.
+ *
+ * This configuration helps the firmware/hardware to support certain
+ * features (e.g., roaming) on this primary interface, if the same
+ * cannot be supported on the concurrent STA interfaces simultaneously.
+ *
+ * This configuration is only applicable for a single STA interface on
+ * a device and gives the priority for it only over other concurrent STA
+ * interfaces.
+ *
+ * If the device is a multi wiphy/soc, this configuration applies to a
+ * single STA interface across the wiphys.
+ *
+ * 1-Enable (is the primary STA), 0-Disable (is not the primary STA)
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY = 79,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * driver to enable/disable FT-over-DS feature. Possible values for
+ * this attribute are 1-Enable and 0-Disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS = 80,
+
+ /*
+ * 8-bit unsigned value. This attribute can be used to configure the
+ * firmware to enable/disable ARP/NS offload feature. Possible values
+ * for this attribute are 0-Disable and 1-Enable.
+ *
+ * This attribute is only applicable for STA/P2P-Client interface,
+ * and is optional, default behavior is ARP/NS offload enabled.
+ *
+ * This attribute can be set in disconnected and connected state, and
+ * will restore to the default behavior if the interface is closed.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD = 81,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -3818,6 +4046,14 @@
* QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85,
+ /* u8 value representing the channel load percentage. Possible values
+ * are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_LOAD_PERCENTAGE = 86,
+ /* u8 value representing the time slicing duty cycle percentage.
+ * Possible values are 0-100.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE = 87,
/* keep last */
QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
@@ -4545,7 +4781,13 @@
* @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD: Signed 32-bit value in dBm,
* signifying the RSSI threshold of the candidate AP, indicating
* the driver to trigger roam only to the candidate AP with RSSI
- * better than this threshold.
+ * better than this threshold. If RSSI thresholds for candidate APs found
+ * in the 2.4 GHz, 5 GHz, and 6 GHz bands are configured separately using
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ,
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ, and/or
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ, those values will
+ * take precedence over the value configured using the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute.
*
* @QCA_ATTR_ROAM_CONTROL_USER_REASON: Unsigned 32-bit value. Represents the
* user defined reason code to be sent to the AP in response to AP's
@@ -4564,6 +4806,69 @@
* If both QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME and
* QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS are not specified, the
* driver shall proceed with the default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ: Signed 32-bit value
+ * in dBm, signifying the RSSI threshold of the candidate AP found in the
+ * 2.4 GHz band. The driver/firmware shall trigger roaming to the candidate
+ * AP found in the 2.4 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ: Signed 32-bit value in
+ * dBm, signifying the RSSI threshold of the candidate AP found in the 5
+ * GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ * found in the 5 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by tge
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ: Signed 32-bit value in
+ * dBm, signifying the RSSI threshold of the candidate AP found in the 6
+ * GHz band. The driver/firmware shall trigger roaming to the candidate AP
+ * found in the 6 GHz band only if its RSSI value is better than this
+ * threshold. Optional attribute. If this attribute is not included, the
+ * threshold value specified by the
+ * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_BAND_MASK: Unsigned 32-bit value.
+ * Carries bitmask value of bits from &enum qca_set_band and represents
+ * all the bands in which roaming is allowed. The configuration is valid
+ * until next disconnection. If this attribute is not present, the
+ * existing configuration shall be used. By default, roaming is allowed on
+ * all bands supported by the local device. When the value is set to
+ * %QCA_SETBAND_AUTO, all supported bands shall be enabled.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for active channels in the 2.4/5 GHz
+ * bands. If this attribute is not configured, the driver shall proceed
+ * with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for passive channels in the 5 GHz
+ * band. If this attribute is not configured, the driver shall proceed with
+ * default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME: u16 value in milliseconds.
+ * Optional parameter. The minimum duration to stay on the connected AP
+ * channel during the channel scanning. If this attribute is not
+ * configured, the driver shall proceed with default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME: u16 value in milliseconds.
+ * Optional parameter. The maximum duration for which the radio can scan
+ * foreign channels consecutively without coming back to home channel. If
+ * this attribute is not configured, the driver shall proceed with default
+ * behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for 6G Preferred Scanning Channels.
+ * If this attribute is not configured, the driver shall proceed with
+ * default behavior.
+ *
+ * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME: u16 value in milliseconds.
+ * Optional parameter. Scan dwell time for 6G Non Preferred Scanning
+ * Channels. If this attribute is not configured, the driver shall proceed
+ * with default behavior.
*/
enum qca_vendor_attr_roam_control {
QCA_ATTR_ROAM_CONTROL_ENABLE = 1,
@@ -4579,6 +4884,16 @@
QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11,
QCA_ATTR_ROAM_CONTROL_USER_REASON = 12,
QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS = 13,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ = 14,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ = 15,
+ QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ = 16,
+ QCA_ATTR_ROAM_CONTROL_BAND_MASK = 17,
+ QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME = 18,
+ QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME = 19,
+ QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME = 20,
+ QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME = 21,
+ QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME = 22,
+ QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME = 23,
/* keep last */
QCA_ATTR_ROAM_CONTROL_AFTER_LAST,
@@ -4601,14 +4916,14 @@
* ignored BSSIDs and accordingly clear the respective ones with the
* matching ID.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: Unsigned
- * 32-bit value.Represents the number of whitelist SSIDs configured.
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS: Unsigned
+ * 32-bit value. Represents the number of allowlist SSIDs configured.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST: Nested attribute
- * to carry the list of Whitelist SSIDs.
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST: Nested attribute
+ * to carry the list of allowlist SSIDs.
*
- * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID: SSID (binary attribute,
- * 0..32 octets). Represents the white list SSID. Whitelist SSIDs
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID: SSID (binary attribute,
+ * 0..32 octets). Represents the allow list SSID. Allowlist SSIDs
* represent the list of SSIDs to which the firmware/driver can consider
* to roam to.
*
@@ -4646,7 +4961,7 @@
*
* @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE: Unsigned 32-bit
* value. 1-Enable, 0-Disable. Represents "Lazy" mode, where
- * firmware is hunting for a better BSSID or white listed SSID even though
+ * firmware is hunting for a better BSSID or allow listed SSID even though
* the RSSI of the link is good. The parameters enabling the roaming are
* configured through the PARAM_A_BAND_XX attrbutes.
*
@@ -4688,10 +5003,10 @@
QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1,
QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2,
- /* Attributes for wifi_set_ssid_white_list */
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3,
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4,
- QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5,
+ /* Attributes for wifi_set_ssid_allow_list */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID = 5,
/* Attributes for set_roam_params */
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6,
@@ -4726,16 +5041,24 @@
QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST
+#define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID \
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID
+
/*
* enum qca_wlan_vendor_roaming_subcmd: Referred by
* QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD.
*
- * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST: Sub command to
- * configure the white list SSIDs. These are configured through
+ * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST: Sub command to
+ * configure the allow list SSIDs. These are configured through
* the following attributes.
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS,
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST,
- * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS,
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST,
+ * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID
*
* @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS: Sub command to
* configure the Roam params. These parameters are evaluated on the GScan
@@ -4751,7 +5074,7 @@
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS to set the BSSID
* preference.
*
- * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the list of BSSIDs
+ * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID: Sets the list of BSSIDs
* to ignore in roaming decision. Uses
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to set the list.
*
@@ -4775,17 +5098,23 @@
*/
enum qca_wlan_vendor_roaming_subcmd {
QCA_WLAN_VENDOR_ROAMING_SUBCMD_INVALID = 0,
- QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST = 1,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST = 1,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS = 2,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM = 3,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS = 4,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PARAMS = 5,
- QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID = 6,
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID = 6,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET = 7,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET = 8,
QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR = 9,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST \
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST
+#define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID \
+ QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID
+
enum qca_wlan_vendor_attr_gscan_config_params {
QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0,
@@ -5144,7 +5473,7 @@
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
= 43,
/* Unsigned 32-bit value; a GSCAN Capabilities attribute. */
- QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID
= 44,
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED = 45,
@@ -5152,10 +5481,10 @@
/* Unsigned 32-bit value; a GSCAN Capabilities attribute.
* This is used to limit the maximum number of BSSIDs while sending
* the vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM with subcmd
- * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID and attribute
+ * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID and attribute
* QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID.
*/
- QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID = 46,
+ QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID = 46,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST,
@@ -5163,6 +5492,12 @@
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST - 1,
};
+/* old names for API compatibility */
+#define QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID \
+ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID
+#define QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID \
+ QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID
+
enum qca_wlan_vendor_attr_pno_config_params {
QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0,
/* Attributes for data used by
@@ -6186,6 +6521,14 @@
* u32 attribute.
*/
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 = 29,
+ /* This attribute specifies the bandwidth to be used for spectral scan
+ * operation. This is an u8 attribute and uses the values in enum
+ * nl80211_chan_width. This is an optional attribute.
+ * If this attribute is not populated, the driver should configure the
+ * spectral scan bandwidth to the maximum value supported by the target
+ * for the current operating bandwidth.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH = 30,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX =
@@ -6296,6 +6639,14 @@
* u32 attribute.
*/
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ = 18,
+ /* Flag attribute to indicate agile spectral scan capability
+ * for 320 MHz mode.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_320 = 19,
+ /* Number of spectral detectors used for scan in 320 MHz.
+ * u32 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_320_MHZ = 20,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX =
@@ -6486,6 +6837,8 @@
QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25,
/* Bus failure */
QCA_WLAN_HANG_BUS_FAILURE = 26,
+ /* tasklet/credit latency found */
+ QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT = 27,
};
/**
@@ -6511,6 +6864,28 @@
};
/**
+ * enum qca_wlan_vendor_flush_pending_policy: Represents values for
+ * the policy to flush pending frames, configured via
+ * %QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING. This enumeration defines the
+ * valid values for %QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY.
+ *
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE: This value clears all
+ * the flush policy configured before. This command basically disables the
+ * flush config set by the user.
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE: This value configures
+ * the flush policy to be immediate. All pending packets for the peer/TID are
+ * flushed when this command/policy is received.
+ * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END: This value configures
+ * the flush policy to the end of TWT SP. All pending packets for the peer/TID
+ * are flushed when the end of TWT SP is reached.
+ */
+enum qca_wlan_vendor_flush_pending_policy {
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE = 0,
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE = 1,
+ QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_flush_pending - Attributes for
* flushing pending traffic in firmware.
*
@@ -6518,12 +6893,25 @@
* @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.
+ * flush packets with access category. This is optional. See below.
+ * @QCA_WLAN_VENDOR_ATTR_TID_MASK: Configure TID mask of the pending packets.
+ * It is a u32 value with bit 0-7 representing TID 0-7. Set corresponding
+ * bit to 1 to act upon the TID. This is optional. Either this attribute or
+ * %QCA_WLAN_VENDOR_ATTR_AC must be provided. If both are provided,
+ * %QCA_WLAN_VENDOR_ATTR_TID_MASK takes precedence. If neither are provided
+ * it is an error.
+ * @QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY: Policy of flushing the pending
+ * packets corresponding to the peer/TID provided. It is a u32 value,
+ * represented by %enum qca_wlan_vendor_flush_pending_policy. This
+ * value is honored only when TID mask is provided. This is not honored when AC
+ * mask is provided.
*/
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,
+ QCA_WLAN_VENDOR_ATTR_TID_MASK = 3,
+ QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY = 4,
/* keep last */
QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST,
@@ -6640,8 +7028,9 @@
*
* @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_XR:
+ * Use XR level to benefit XR (extended reality) application to achieve
+ * latency and power by via constraint scan/roaming/adaptive PS.
* @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.
@@ -6652,7 +7041,10 @@
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_XR = 2,
+ /* legacy name */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE =
+ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR,
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3,
QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4,
@@ -7203,6 +7595,15 @@
* there is any critical ongoing operation.
*/
QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW = 3,
+ /* Nested attribute, the driver/firmware uses this attribute to report
+ * thermal statistics of different thermal levels to userspace when
+ * requested using the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS command
+ * type. This attribute contains a nested array of records of thermal
+ * statistics of multiple levels. The attributes used inside this nested
+ * attribute are defined in enum qca_wlan_vendor_attr_thermal_stats.
+ */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS = 4,
/* keep last */
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST,
@@ -7231,6 +7632,13 @@
* @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL: Request to get the current
* thermal level from the driver/firmware. The driver should respond with a
* thermal level defined in enum qca_wlan_vendor_thermal_level.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS: Request to get the
+ * current thermal statistics from the driver/firmware. The driver should
+ * respond with statistics of all thermal levels encapsulated in the attribute
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS.
+ * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS: Request to clear
+ * the current thermal statistics for all thermal levels maintained in the
+ * driver/firmware and start counting from zero again.
*/
enum qca_wlan_vendor_attr_thermal_cmd_type {
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS,
@@ -7239,6 +7647,8 @@
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME,
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL,
QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS,
};
/**
@@ -7334,6 +7744,35 @@
};
/**
+ * enum qca_wlan_vendor_attr_thermal_stats - vendor subcmd attributes
+ * to get thermal status from the driver/firmware.
+ * enum values are used for NL attributes encapsulated inside the
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS nested attribute.
+ *
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE: Minimum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE: Maximum temperature
+ * of a thermal level in Celsius. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME: The total time spent on each
+ * thermal level in milliseconds. u32 size.
+ * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER: Indicates the number
+ * of times the temperature crossed into the temperature range defined by the
+ * thermal level from both higher and lower directions. u32 size.
+ */
+enum qca_wlan_vendor_attr_thermal_stats {
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX =
+ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_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.
@@ -7492,6 +7931,21 @@
};
/**
+ * enum qca_wlan_keep_alive_data_type - Keep alive data type configuration
+ *
+ * Indicates the frame types to use for keep alive data.
+ *
+ * @QCA_WLAN_KEEP_ALIVE_DEFAULT: Driver default type used for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_DATA: Data frame type for keep alive.
+ * @QCA_WLAN_KEEP_ALIVE_MGMT: Management frame type for keep alive.
+ */
+enum qca_wlan_keep_alive_data_type {
+ QCA_WLAN_KEEP_ALIVE_DEFAULT = 0,
+ QCA_WLAN_KEEP_ALIVE_DATA = 1,
+ QCA_WLAN_KEEP_ALIVE_MGMT = 2,
+};
+
+/**
* enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for
* HE operating mode control transmit request. These attributes are
* sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and
@@ -7989,6 +8443,78 @@
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX = 49,
+ /* 8-bit unsigned value to configure the driver to ignore the SAE H2E
+ * requirement mismatch for 6 GHz connection.
+ * 0 - Default behavior, 1 - Ignore SAE H2E requirement mismatch.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE = 50,
+
+ /* 8-bit unsigned value to configure the driver to allow 6 GHz
+ * connection with all security modes.
+ * 0 - Default behavior, 1 - Allow 6 GHz connection with all security
+ * modes.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE = 51,
+
+ /* 8-bit unsigned value to configure the driver to transmit data with
+ * ER SU PPDU type.
+ *
+ * 0 - Default behavior, 1 - Enable ER SU PPDU type TX.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE = 52,
+
+ /* 8-bit unsigned value to configure the driver to use Data or
+ * Management frame type for keep alive data.
+ * Uses enum qca_wlan_keep_alive_data_type values.
+ *
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE = 53,
+
+ /* 8-bit unsigned value to configure the driver to use scan request
+ * BSSID value in Probe Request frame RA(A1) during the scan. The
+ * driver saves this configuration and applies this setting to all user
+ * space scan requests until the setting is cleared. If this
+ * configuration is set, the driver uses the BSSID value from the scan
+ * request to set the RA(A1) in the Probe Request frames during the
+ * scan.
+ *
+ * 0 - Default behavior uses the broadcast RA in Probe Request frames.
+ * 1 - Uses the scan request BSSID in RA in Probe Request frames.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA = 54,
+
+ /* 8-bit unsigned value to configure the driver to enable/disable the
+ * BSS max idle period support.
+ *
+ * 0 - Disable the BSS max idle support.
+ * 1 - Enable the BSS max idle support.
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE = 55,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Rx control frame to MultiBSS subfield in the HE MAC
+ * capabilities information field.
+ * 0 - Disable Rx control frame to MultiBSS subfield
+ * 1 - Enable Rx control frame to MultiBSS subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS = 56,
+
+ /* 8-bit unsigned value to configure the driver/firmware to enable or
+ * disable Broadcast TWT support subfield in the HE MAC capabilities
+ * information field.
+ * 0 - Disable Broadcast TWT support subfield
+ * 1 - Enable Broadcast TWT support subfield
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT = 57,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -8061,6 +8587,10 @@
*
* @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmare is
* ready for a new TWT session setup after it issued a TWT teardown.
+ *
+ * @QCA_WLAN_TWT_SET_PARAM: Configure TWT related parameters. Required
+ * parameters are obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refer
+ * the enum qca_wlan_vendor_attr_twt_set_param.
*/
enum qca_wlan_twt_operation {
QCA_WLAN_TWT_SET = 0,
@@ -8073,6 +8603,7 @@
QCA_WLAN_TWT_CLEAR_STATS = 7,
QCA_WLAN_TWT_GET_CAPABILITIES = 8,
QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9,
+ QCA_WLAN_TWT_SET_PARAM = 10,
};
/**
@@ -8087,7 +8618,8 @@
* @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the
* parameters configured for TWT. These parameters are represented by
* enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume,
- * or enum qca_wlan_vendor_attr_twt_stats based on the operation.
+ * enum qca_wlan_vendor_attr_twt_set_param, or
+ * enum qca_wlan_vendor_attr_twt_stats based on the operation.
*/
enum qca_wlan_vendor_attr_config_twt {
QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0,
@@ -8378,9 +8910,13 @@
* response.
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64)
- * This field is applicable for TWT response only.
- * This field contains absolute TSF value of the wake time received
- * from the TWT responder and is passed to the userspace.
+ * In TWT setup command this field contains absolute TSF that will
+ * be used by TWT requester during setup.
+ * In TWT response this field contains absolute TSF value of the
+ * wake time received from the TWT responder and is passed to
+ * the userspace.
+ * This is an optional parameter for
+ * 1. TWT SET Request
* This is a required parameter for
* 1. TWT SET Response
* 2. TWT GET Response
@@ -8397,14 +8933,17 @@
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR: 6-byte MAC address
* Represents the MAC address of the peer for which the TWT session
* is being configured. This is used in AP mode to represent the respective
- * client. In AP mode, this is an optional parameter for response and is
- * a required parameter for
- * 1. TWT SET Request
- * 2. TWT GET Request
- * 3. TWT TERMINATE Request
- * 4. TWT SUSPEND Request
+ * client.
+ * In AP mode, this is a required parameter in response for
+ * 1. TWT SET
+ * 2. TWT GET
+ * 3. TWT TERMINATE
+ * 4. TWT SUSPEND
* In STA mode, this is an optional parameter in request and response for
* the above four TWT operations.
+ * In AP mode, this is a required parameter in request for
+ * 1. TWT GET
+ * 2. TWT TERMINATE
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL: Optional (u32)
* Minimum tolerance limit of wake interval parameter in microseconds.
@@ -8422,6 +8961,59 @@
* TWT state for the given dialog id. The values for this are represented
* by enum qca_wlan_twt_setup_state.
* This is obtained through TWT GET operation.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA: Optional (u32)
+ * This attribute is used to configure wake interval mantissa.
+ * The unit is microseconds. This attribute, when specified, takes
+ * precedence over QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA.
+ * This parameter is used for
+ * 1. TWT SET Request and Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID: Optional (u8)
+ * This attribute is used to configure Broadcast TWT ID.
+ * The Broadcast TWT ID indicates a specific Broadcast TWT for which the
+ * transmitting STA is providing TWT parameters. The allowed values are 0 to 31.
+ * This parameter is used for
+ * 1. TWT SET Request
+ * 2. TWT TERMINATE Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION: Optional (u8)
+ * This attribute is used to configure Broadcast TWT recommendation.
+ * The Broadcast TWT Recommendation subfield contains a value that indicates
+ * recommendations on the types of frames that are transmitted by TWT
+ * scheduled STAs and scheduling AP during the broadcast TWT SP.
+ * The allowed values are 0 - 3.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE: Optional (u8)
+ * This attribute is used to configure Broadcast TWT Persistence.
+ * The Broadcast TWT Persistence subfield indicates the number of
+ * TBTTs during which the Broadcast TWT SPs corresponding to this
+ * broadcast TWT Parameter set are present. The number of beacon intervals
+ * during which the Broadcast TWT SPs are present is equal to the value in the
+ * Broadcast TWT Persistence subfield plus 1 except that the value 255
+ * indicates that the Broadcast TWT SPs are present until explicitly terminated.
+ * This parameter is used for
+ * 1. TWT SET Request
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE: Optional (u8)
+ * This attribute contains the value of the Responder PM Mode subfield (0 or 1)
+ * from TWT response frame.
+ * This parameter is used for
+ * 1. TWT SET Response
+ * 2. TWT GET Response
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT: Optional (u32)
+ * This attribute is used to configure the announce timeout value (in us) in
+ * the firmware. This timeout value is only applicable for the announced TWT. If
+ * the timeout value is non-zero the firmware waits up to the timeout value to
+ * use Data frame as an announcement frame. If the timeout value is 0 the
+ * firmware sends an explicit QoS NULL frame as the announcement frame on SP
+ * start. The default value in the firmware is 0.
+ * This parameter is used for
+ * 1. TWT SET Request
*/
enum qca_wlan_vendor_attr_twt_setup {
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
@@ -8449,6 +9041,15 @@
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION = 19,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE = 20,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID = 22,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24,
+
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE = 25,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT = 26,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX =
@@ -8487,6 +9088,18 @@
* @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT
* session due to roaming. Used on the TWT_TERMINATE notification from the
* firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE: FW terminated the
+ * TWT session due to SCC (Single Channel Concurrency) and MCC (Multi Channel
+ * Concurrency). Used on the TWT_TERMINATE notification from the firmware.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS: FW rejected the TWT setup
+ * request due to roaming in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS: FW rejected the TWT
+ * setup request due to channel switch in progress.
+ * @QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS: FW rejected the TWT setup
+ * request due to scan in progress.
+ * QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE: The driver requested to
+ * terminate an existing TWT session on power save exit request from userspace.
+ * Used on the TWT_TERMINATE notification from the driver/firmware.
*/
enum qca_wlan_vendor_twt_status {
QCA_WLAN_VENDOR_TWT_STATUS_OK = 0,
@@ -8507,6 +9120,11 @@
QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15,
QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16,
QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17,
+ QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE = 18,
+ QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS = 19,
+ QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20,
+ QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS = 21,
+ QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE = 22,
};
/**
@@ -8763,6 +9381,27 @@
};
/**
+ * enum qca_wlan_vendor_attr_twt_set_param: Represents attributes for
+ * TWT (Target Wake Time) related parameters. It is used when
+ * %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION is set to %QCA_WLAN_TWT_SET_PARAM.
+ * These attributes are sent as part of %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE: Optional (u8)
+ * This attribute configures AC parameters to be used for all TWT
+ * sessions in AP mode.
+ * Uses the enum qca_wlan_ac_type values.
+ */
+enum qca_wlan_vendor_attr_twt_set_param {
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST - 1,
+};
+
+/**
* enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by
* the TWT responder
*
@@ -8853,6 +9492,22 @@
};
/**
+ * enum qca_wlan_vendor_cfr_data_transport_modes - Defines QCA vendor CFR data
+ * transport modes and is used by the attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE as a part of the vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
+ * @QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS: Use relayfs to send CFR data.
+ * @QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS: Use netlink events to send CFR
+ * data. The data shall be encapsulated within
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA along with the vendor sub command
+ * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an asynchronous event.
+ */
+enum qca_wlan_vendor_cfr_data_transport_modes {
+ QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS = 0,
+ QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS = 1,
+};
+
+/**
* enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by
* attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor
* command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
@@ -9042,6 +9697,27 @@
* MAC for CFR capture. This is a bitmask in which each bit represents the
* corresponding Data frame subtype value per IEEE Std 802.11-2016,
* 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE: Optional (u8)
+ * Userspace can use this attribute to specify the driver about which transport
+ * mode shall be used by the driver to send CFR data to userspace. Uses values
+ * from enum qca_wlan_vendor_cfr_data_transport_modes. When this attribute is
+ * not present, the driver shall use the default transport mechanism which is
+ * QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID: Optional (u32)
+ * Userspace can use this attribute to specify the nl port id of the application
+ * which receives the CFR data and processes it further so that the drivers can
+ * unicast the netlink events to a specific application. Optionally included
+ * when QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE is set to
+ * QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS, not required otherwise. The drivers
+ * shall multicast the netlink events when this attribute is not included.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA: Required (NLA_BINARY).
+ * This attribute will be used by the driver to encapsulate and send CFR data
+ * to userspace along with QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an
+ * asynchronous event when the driver is configured to send CFR data using
+ * netlink events with %QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS.
*/
enum qca_wlan_vendor_peer_cfr_capture_attr {
QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0,
@@ -9070,6 +9746,9 @@
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23,
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24,
QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE = 26,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID = 27,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA = 28,
/* Keep last */
QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST,
@@ -9291,7 +9970,6 @@
* has priority over BT_A2DP and ZB_HIGH.
* 3: BT_A2DP has priority over ZB_HIGH.
*/
-
enum qca_vendor_attr_coex_config_three_way {
QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_INVALID = 0,
QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE = 1,
@@ -9756,20 +10434,48 @@
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required
* Nested attribute containing multiple ranges with following attributes:
- * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
- * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START,
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, and
+ * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM.
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32)
* Starting center frequency in MHz.
*
* @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32)
* Ending center frequency in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM:
+ * s32 attribute, optional. It is a per frequency range attribute.
+ * The maximum TX power limit from user space is to be applied on an
+ * unrestricted interface for corresponding frequency range. It is also
+ * possible that the actual TX power may be even lower than this cap due to
+ * other considerations such as regulatory compliance, SAR, etc. In absence of
+ * this attribute the driver shall follow current behavior which means
+ * interface (SAP/P2P) function can keep operating on an unsafe channel with TX
+ * power derived by the driver based on regulatory/SAR during interface up.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK:
+ * u32 attribute, optional. Indicates all the interface types which are
+ * restricted for all frequency ranges provided in
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END.
+ * This attribute encapsulates bitmasks of interface types defined in
+ * enum nl80211_iftype. If an interface is marked as restricted the driver must
+ * move to a safe channel and if no safe channel is available the driver shall
+ * terminate that interface functionality. In absence of this attribute,
+ * interface (SAP/P2P) can still continue operating on an unsafe channel with
+ * TX power limit derived from either
+ * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM or based on
+ * regulatory/SAE limits if %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM
+ * is not provided.
*/
enum qca_wlan_vendor_attr_avoid_frequency_ext {
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3,
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM = 4,
+ QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK = 5,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX =
@@ -10140,6 +10846,11 @@
* failed roam invoke. Different roam invoke failure reason codes
* are specified in enum qca_vendor_roam_invoke_fail_reasons. This can be
* queried either in connected state or disconnected state.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY: u32, used in STA mode only.
+ * This represents the average congestion duration of uplink frames in MAC
+ * queue in unit of ms. This can be queried either in connected state or
+ * disconnected state.
*/
enum qca_wlan_vendor_attr_get_sta_info {
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0,
@@ -10192,6 +10903,7 @@
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON = 47,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON = 48,
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON = 49,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY = 50,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST,
@@ -10630,10 +11342,25 @@
* u8 attribute. Notify the TX VDEV status. Possible values 0, 1
* belonging to MBSSID/EMA_AP configuration. 0 means Non-Tx VDEV,
* 1 means Tx VDEV. Mandatory attribute for all MBSSID VDEV status events.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT:
+ * u8 attribute, required. 1 means Tx VDEV up event. 0 means Tx VDEV down event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID:
+ * u8 attribute, required. Indicates group id of Tx VDEV.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * group information. The attributes defined in enum
+ * qca_wlan_vendor_attr_mbssid_tx_vdev_group_info
+ * are nested in this attribute.
*/
enum qca_wlan_vendor_attr_mbssid_tx_vdev_status {
QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL = 1,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT = 2,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID = 3,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO = 4,
/* keep last */
QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST,
@@ -10642,6 +11369,79 @@
};
/**
+ * enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info - Attributes used
+ * inside %QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX:
+ * u32 attribute, required. Contains interface index.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS:
+ * u8 attribute, required. 0 - means vdev is in down state.
+ * 1 - means vdev is in up state.
+ */
+enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info {
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX = 1,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS = 2,
+
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO - 1,
+};
+
+/**
+ * enum qca_wlan_concurrent_sta_policy_config - Concurrent STA policies
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY: Preference to the primary
+ * STA interface has to be given while selecting the connection policies
+ * (e.g., BSSID, band, TX/RX chains, etc.) for the subsequent STA interface.
+ * An interface is set as primary through the attribute
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY. This policy is not
+ * applicable if the primary interface has not been set earlier.
+ *
+ * The intention is not to downgrade the primary STA performance, such as:
+ * - Do not reduce the number of TX/RX chains of primary connection.
+ * - Do not optimize DBS vs. MCC/SCC, if DBS ends up reducing the number of
+ * chains.
+ * - If using MCC, should set the MCC duty cycle of the primary connection to
+ * be higher than the secondary connection.
+ *
+ * @QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED: The connection policies for the
+ * subsequent STA connection shall be chosen to balance with the existing
+ * concurrent STA's performance.
+ * Such as
+ * - Can choose MCC or DBS mode depending on the MCC efficiency and hardware
+ * capability.
+ * - If using MCC, set the MCC duty cycle of the primary connection to be equal
+ * to the secondary.
+ * - Prefer BSSID candidates which will help provide the best "overall"
+ * performance for all the STA connections.
+ */
+enum qca_wlan_concurrent_sta_policy_config {
+ QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY = 0,
+ QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_concurrent_sta_policy - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG:
+ * u8 attribute. Configures the concurrent STA policy configuration.
+ * Possible values are defined in enum qca_wlan_concurrent_sta_policy_config.
+ */
+enum qca_wlan_vendor_attr_concurrent_sta_policy {
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG = 1,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX =
+ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST - 1,
+
+};
+
+/**
* enum qca_sta_connect_fail_reason_codes - Defines values carried
* by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor
* attribute.
@@ -10669,4 +11469,583 @@
QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7,
};
+/**
+ * enum qca_wlan_vendor_usable_channels_filter - Bitmask of different
+ * filters defined in this enum are used in attribute
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK.
+ *
+ * @QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX: When this bit is set, the driver
+ * shall filter the channels which are not usable because of coexistence with
+ * cellular radio.
+ * @QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY: When this bit is set, the driver
+ * shall filter the channels which are not usable because of existing active
+ * interfaces in the driver and will result in Multi Channel Concurrency, etc.
+ *
+ */
+enum qca_wlan_vendor_usable_channels_filter {
+ QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX = 0,
+ QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_chan_info - Attributes used inside
+ * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO nested attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ:
+ * u32 attribute, required. Indicates the center frequency of the primary
+ * channel in MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ:
+ * u32 attribute. Indicates the center frequency of the primary segment of the
+ * channel in MHz. This attribute is required when reporting 40 MHz, 80 MHz,
+ * 160 MHz, and 320 MHz channels.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ:
+ * u32 attribute. Indicates the center frequency of the secondary segment of
+ * 80+80 channel in MHz. This attribute is required only when
+ * QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH is set to NL80211_CHAN_WIDTH_80P80.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH:
+ * u32 attribute, required. Indicates the bandwidth of the channel, possible
+ * values are defined in enum nl80211_chan_width.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK:
+ * u32 attribute, required. Indicates all the interface types for which this
+ * channel is usable. This attribute encapsulates bitmasks of interface types
+ * defined in enum nl80211_iftype.
+ *
+ */
+enum qca_wlan_vendor_attr_chan_info {
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ = 1,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ = 2,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH = 4,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_usable_channels - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK:
+ * u32 attribute. Indicates the bands from which the channels should be reported
+ * in response. This attribute encapsulates bit masks of bands defined in enum
+ * nl80211_band. Optional attribute, if not present in the request the driver
+ * shall return channels from all supported bands.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK:
+ * u32 attribute. Indicates all the interface types for which the usable
+ * channels information is requested. This attribute encapsulates bitmasks of
+ * interface types defined in enum nl80211_iftype. Optional attribute, if not
+ * present in the request the driver shall send information of all supported
+ * interface modes.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK:
+ * u32 attribute. This attribute carries information of all filters that shall
+ * be applied while populating usable channels information by the driver. This
+ * attribute carries bit masks of different filters defined in enum
+ * qca_wlan_vendor_usable_channels_filter. Optional attribute, if not present
+ * in the request the driver shall send information of channels without applying
+ * any of the filters that can be configured through this attribute.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO:
+ * Nested attribute. This attribute shall be used by the driver to send
+ * usability information of each channel. The attributes defined in enum
+ * qca_wlan_vendor_attr_chan_info are used inside this attribute.
+ */
+enum qca_wlan_vendor_attr_usable_channels {
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK = 1,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK = 2,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK = 3,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX =
+ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_radar_history: Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY to get DFS radar history.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES: Nested attribute to carry
+ * the list of radar history entries.
+ * Each entry contains freq, timestamp, and radar signal detect flag.
+ * The driver shall add an entry when CAC has finished, or radar signal
+ * has been detected post AP beaconing. The driver shall maintain at least
+ * 8 entries in order to save CAC result for a 160 MHz channel.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ: u32 attribute.
+ * Channel frequency in MHz.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP: u64 nanoseconds.
+ * CLOCK_BOOTTIME timestamp when this entry is updated due to CAC
+ * or radar detection.
+ * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED: NLA_FLAG attribute.
+ * This flag indicates radar signal has been detected.
+ */
+enum qca_wlan_vendor_attr_radar_history {
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_INVALID = 0,
+
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES = 1,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ = 2,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP = 3,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST,
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX =
+ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_mcc_quota_type: MCC channel time quota type
+ *
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR: In the event, it indicates that the
+ * target exited MCC state and cleared the quota information. In the
+ * command it clears MCC quota setting and restores adaptive scheduling.
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED: Channel time quota is fixed and
+ * will not be changed.
+ * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC: Channel time quota is dynamic
+ * and the target may change the quota based on the data activity.
+ */
+enum qca_wlan_vendor_mcc_quota_type {
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR = 0,
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED = 1,
+ QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mcc_quota: Used by the vendor event
+ * QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA to indicate MCC channel
+ * quota information or as a command to set the required MCC quota for an
+ * interface.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE: u32 attribute.
+ * The type is defined in enum qca_wlan_vendor_mcc_quota_type.
+ * In a command this specifies the MCC quota type to be set for the interface.
+ * In an event this provides the current quota type in force.
+ * This is required in a command and an event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES: Nested attribute to carry
+ * the list of channel quota entries.
+ * In an event each entry contains the frequency and respective time quota for
+ * all the MCC interfaces.
+ * In a command it specifies the interface index and respective time quota.
+ * In a command only one entry (ifindex, quota pair) may be specified.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ: u32 attribute.
+ * Channel frequency in MHz. This is present only in an event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE: u32 attribute.
+ * Channel time quota expressed as percentage.
+ * This is present in an event and a command.
+ * In an command, the user shall specify the quota to be allocated for the
+ * interface represented by %QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX.
+ * In an event this provides the existing quota for the channel.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX: u32 attribute.
+ * Specifies the interface index (netdev) for which the corresponding
+ * configurations are applied. This is required in a command only. Only one
+ * interface index may be specified. If not specified, the configuration is
+ * rejected.
+ */
+enum qca_wlan_vendor_attr_mcc_quota {
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES = 2,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE = 4,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST,
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX =
+ QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_mdns_offload - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE: Required (flag)
+ * Enable mDNS offload. This attribute is mandatory to enable
+ * mDNS offload feature. If this attribute is not present, mDNS offload
+ * is disabled.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE: Nested attribute containing
+ * one or more %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY attributes. This
+ * attribute is mandatory when enabling the feature, and not required when
+ * disabling the feature.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY: Nested attribute containing
+ * the following attributes:
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT
+ * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN: Required string attribute.
+ * It consists of a hostname and ".local" as the domain name. The character
+ * set is limited to UTF-8 encoding. The maximum allowed size is 63 bytes.
+ * It is used to compare the domain in the "QU" query. Only 1 FQDN is
+ * supported per vdev.
+ * For example: myphone.local
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT: Required
+ * u16 attribute. It specifies the total number of resource records present
+ * in the answer section of the answer payload. This attribute is needed by the
+ * firmware to populate the mDNS response frame for mDNS queries without having
+ * to parse the answer payload.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD: Required binary blob
+ * attribute sent by the mdnsResponder from userspace. It contains resource
+ * records of various types (e.g., A, AAAA, PTR, TXT) and service list. This
+ * payload is passed down to the firmware and is transmitted in response to
+ * mDNS queries.
+ * The maximum supported size of the answer payload is 512 bytes.
+ */
+enum qca_wlan_vendor_attr_mdns_offload {
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE = 1,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE = 2,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY = 3,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN = 4,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT = 5,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD = 6,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_MAX =
+ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_monitor_data_frame_type - Represent the various
+ * Data frame types to be sent over the monitor interface.
+ */
+enum qca_wlan_vendor_monitor_data_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ARP = BIT(1),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV4 = BIT(2),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV6 = BIT(3),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_EAPOL = BIT(4),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV4 = BIT(5),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV6 = BIT(6),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYN = BIT(7),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FIN = BIT(9),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FINACK = BIT(10),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_ACK = BIT(11),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_RST = BIT(12),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV4 = BIT(13),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV6 = BIT(14),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_RTP = BIT(15),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_SIP = BIT(16),
+ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_QOS_NULL = BIT(17),
+};
+
+/**
+ * qca_wlan_vendor_monitor_mgmt_frame_type - Represent the various
+ * Management frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL: All the Management Frames.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON: All the Management frames
+ * except the Beacon frame.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON: Only the connected
+ * BSSID Beacon frames. Valid only in the connected state.
+ * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents
+ * the Beacon frames obtained during the scan (off channel and connected
+ * channel), when in connected state.
+ */
+enum qca_wlan_vendor_monitor_mgmt_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_MGMT_NO_BEACON = BIT(1),
+ QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON = BIT(2),
+ QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON = BIT(3),
+};
+
+/**
+ * qca_wlan_vendor_monitor_ctrl_frame_type - Represent the various
+ * Control frame types to be sent over the monitor interface.
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL: All the Control frames
+ * @QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME: Trigger frame
+ */
+enum qca_wlan_vendor_monitor_ctrl_frame_type {
+ QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL = BIT(0),
+ /* valid only if QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL is not set
+ */
+ QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_set_monitor_mode - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the
+ * monitor mode.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Data frame types to be monitored (u32). These Data frames
+ * are represented by enum qca_wlan_vendor_monitor_data_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Management frame types to be monitored (u32). These
+ * Management frames are represented by
+ * enum qca_wlan_vendor_monitor_mgmt_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute.
+ * Represents the TX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute.
+ * Represents the RX Control frame types to be monitored (u32). These Control
+ * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: u32
+ * attribute.
+ * Represents the interval in milliseconds only for the connected Beacon frames,
+ * expecting the connected BSS's Beacon frames to be sent on the monitor
+ * interface at this specific interval.
+ */
+enum qca_wlan_vendor_attr_set_monitor_mode {
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX =
+ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_roam_scan_state - Roam scan state flags.
+ * Bits will be set to 1 if the corresponding state is enabled.
+ *
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_START: Scan Start.
+ * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_END: Scan end.
+ */
+enum qca_wlan_vendor_roam_scan_state {
+ QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START = BIT(0),
+ QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END = BIT(1),
+};
+
+/**
+ * enum qca_wlan_vendor_roam_event_type - Roam event type flags.
+ * Bits will be set to 1 if the corresponding event is notified.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON: Represents that the roam event
+ * carries the trigger reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON. This event also carries
+ * the BSSID, RSSI, frequency info of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON: Represents that the roam event
+ * carries the roam fail reason. When set, it is expected that the roam event
+ * carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_FAIL_REASON. This event also carries the
+ * BSSID, RSSI, frequency info of the AP to which the roam was attempted.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON: Represents that the roam
+ * event carries the roam invoke fail reason. When set, it is expected that
+ * the roam event carries the respective reason via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON.
+ *
+ * @QCA_WLAN_VENDOR_ROAM_EVENT_SCAN_STATE: Represents that the roam event
+ * carries the roam scan state. When set, it is expected that the roam event
+ * carries the respective scan state via the attribute
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE and the corresponding
+ * frequency info via QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST.
+ */
+enum qca_wlan_vendor_roam_event_type {
+ QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON = BIT(0),
+ QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON = BIT(1),
+ QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON = BIT(2),
+ QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE = BIT(3),
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events_candidate_info: Roam candidate info.
+ * Referred by QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID: 6-byte MAC address
+ * representing the BSSID of the AP to which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI: Signed 32-bit value
+ * in dBm, signifying the RSSI of the candidate BSSID to which the Roaming is
+ * attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ: u32, frequency in MHz
+ * on which the roam is attempted.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam fail reason for the last failed
+ * roaming attempt by the firmware for the specific BSSID. Different roam
+ * failure reason codes are specified in enum qca_vendor_roam_fail_reasons.
+ */
+enum qca_wlan_vendor_attr_roam_events_candidate_info {
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON = 4,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_roam_events - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS to either configure the
+ * roam events to the driver or notify these events from the driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE: u8 attribute. Configures the
+ * driver/firmware to enable/disable the notification of roam events. It's a
+ * mandatory attribute and used only in the request from the userspace to the
+ * host driver. 1-Enable, 0-Disable.
+ * If the roaming is totally offloaded to the firmware, this request when
+ * enabled shall mandate the firmware to notify all the relevant roam events
+ * represented by the below attributes. If the host is in the suspend mode,
+ * the behavior of the firmware to notify these events is guided by
+ * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_DEVICE_STATE, and if the request is to get
+ * these events in the suspend state, the firmware is expected to wake up the
+ * host before the respective events are notified. Please note that such a
+ * request to get the events in the suspend state will have a definite power
+ * implication.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE: flag attribute. Represents
+ * that the roam events need to be notified in the suspend state too. By
+ * default, these roam events are notified in the resume state. With this flag,
+ * the roam events are notified in both resume and suspend states.
+ * This attribute is used in the request from the userspace to the host driver.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE: u32, used in STA mode only.
+ * Represents the different roam event types, signified by the enum
+ * qca_wlan_vendor_roam_event_type.
+ * Each bit of this attribute represents the different roam even types reported
+ * through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON: u32, used in STA
+ * mode only. This represents the roam trigger reason for the last roaming
+ * attempted by the firmware. Each bit of this attribute represents the
+ * different roam trigger reason code which are defined in enum
+ * qca_vendor_roam_triggers.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON: u32, used in
+ * STA mode only. This represents the roam invoke fail reason for the last
+ * failed roam invoke. Different roam invoke failure reason codes
+ * are specified in enum qca_vendor_roam_invoke_fail_reasons.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO: Array of candidates info
+ * for which the roam is attempted. Each entry is a nested attribute defined
+ * by enum qca_wlan_vendor_attr_roam_events_candidate_info.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE: u8 attribute. Represents
+ * the scan state on which the roam events need to be notified. The values for
+ * this attribute are referred from enum qca_wlan_vendor_roam_scan_state.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST: Nested attribute of
+ * u32 values. List of frequencies in MHz considered for a roam scan.
+ * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS.
+ */
+enum qca_wlan_vendor_attr_roam_events {
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE = 3,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON = 4,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON = 5,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO = 6,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE = 7,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST = 8,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST -1,
+};
+
+/**
+ * enum qca_wlan_ratemask_params_type - Rate mask config type
+ *
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM: CCK/OFDM rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HT: HT rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT: VHT rate mask config
+ * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HE: HE rate mask config
+ */
+enum qca_wlan_ratemask_params_type {
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM = 0,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_HT = 1,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT = 2,
+ QCA_WLAN_RATEMASK_PARAMS_TYPE_HE = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ratemask_params - Used by the
+ * vendor command QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG.
+ * This is used to set the rate mask value to be used in rate selection.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST:
+ * Array of nested containing attributes
+ * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE and
+ * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE: u8, represents
+ * the different PHY types to which the rate mask config is to be applied.
+ * The values for this attribute are referred from enum
+ * qca_wlan_vendor_ratemask_params_type.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP: binary, rate mask bitmap.
+ * A bit value of 1 represents rate is enabled and a value of 0
+ * represents rate is disabled.
+ * For HE targets, 12 bits correspond to one NSS setting.
+ * b0-13 => NSS1, MCS 0-13
+ * b14-27 => NSS2, MCS 0-13 and so on for other NSS.
+ * For VHT targets, 10 bits correspond to one NSS setting.
+ * b0-9 => NSS1, MCS 0-9
+ * b10-19 => NSS2, MCS 0-9 and so on for other NSS.
+ * For HT targets, 8 bits correspond to one NSS setting.
+ * b0-7 => NSS1, MCS 0-7
+ * b8-15 => NSS2, MCS 0-7 and so on for other NSS.
+ * For OFDM/CCK targets, 8 bits correspond to one NSS setting.
+ */
+enum qca_wlan_vendor_attr_ratemask_params {
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST = 1,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE = 2,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP = 3,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX =
+ QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index 372905d..c0f154e 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -280,32 +280,33 @@
static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password,
- size_t password_len, const char *identifier)
+ size_t password_len)
{
u8 counter, k;
u8 addrs[2 * ETH_ALEN];
- const u8 *addr[3];
- size_t len[3];
- size_t num_elem;
- u8 *dummy_password, *tmp_password;
+ const u8 *addr[2];
+ size_t len[2];
+ u8 *stub_password, *tmp_password;
int pwd_seed_odd = 0;
u8 prime[SAE_MAX_ECC_PRIME_LEN];
size_t prime_len;
- struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL;
+ struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL;
u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
u8 qr_bin[SAE_MAX_ECC_PRIME_LEN];
u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN];
+ u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN];
int res = -1;
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
* mask */
+ unsigned int is_eq;
os_memset(x_bin, 0, sizeof(x_bin));
- dummy_password = os_malloc(password_len);
+ stub_password = os_malloc(password_len);
tmp_password = os_malloc(password_len);
- if (!dummy_password || !tmp_password ||
- random_get_bytes(dummy_password, password_len) < 0)
+ if (!stub_password || !tmp_password ||
+ random_get_bytes(stub_password, password_len) < 0)
goto fail;
prime_len = sae->tmp->prime_len;
@@ -324,13 +325,10 @@
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 [|| identifier]
+ * base = password
* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
* base || counter)
*/
@@ -338,15 +336,8 @@
addr[0] = tmp_password;
len[0] = password_len;
- 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++;
+ addr[1] = &counter;
+ len[1] = sizeof(counter);
/*
* Continue for at least k iterations to protect against side-channel
@@ -365,9 +356,9 @@
}
wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
- const_time_select_bin(found, dummy_password, password,
+ const_time_select_bin(found, stub_password, password,
password_len, tmp_password);
- if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+ if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
addr, len, pwd_seed) < 0)
break;
@@ -407,26 +398,43 @@
goto fail;
}
- if (!sae->tmp->pwe_ecc)
- sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
- if (!sae->tmp->pwe_ecc)
- res = -1;
- else
- res = crypto_ec_point_solve_y_coord(sae->tmp->ec,
- sae->tmp->pwe_ecc, x,
- pwd_seed_odd);
- if (res < 0) {
- /*
- * This should not happen since we already checked that there
- * is a result.
- */
+ /* y = sqrt(x^3 + ax + b) mod p
+ * if LSB(save) == LSB(y): PWE = (x, y)
+ * else: PWE = (x, p - y)
+ *
+ * Calculate y and the two possible values for PWE and after that,
+ * use constant time selection to copy the correct alternative.
+ */
+ y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x);
+ if (!y ||
+ dragonfly_sqrt(sae->tmp->ec, y, y) < 0 ||
+ crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN,
+ prime_len) < 0 ||
+ crypto_bignum_sub(sae->tmp->prime, y, y) < 0 ||
+ crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN,
+ SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
+ goto fail;
+ }
+
+ is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01);
+ const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN,
+ prime_len, x_y + prime_len);
+ os_memcpy(x_y, x_bin, prime_len);
+ wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len);
+ crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
+ sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y);
+ if (!sae->tmp->pwe_ecc) {
+ wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
+ res = -1;
}
fail:
+ forced_memzero(x_y, sizeof(x_y));
crypto_bignum_deinit(qr, 0);
crypto_bignum_deinit(qnr, 0);
- os_free(dummy_password);
+ crypto_bignum_deinit(y, 1);
+ os_free(stub_password);
bin_clear_free(tmp_password, password_len);
crypto_bignum_deinit(x, 1);
os_memset(x_bin, 0, sizeof(x_bin));
@@ -438,13 +446,12 @@
static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password,
- size_t password_len, const char *identifier)
+ size_t password_len)
{
u8 counter, k, sel_counter = 0;
u8 addrs[2 * ETH_ALEN];
- const u8 *addr[3];
- size_t len[3];
- size_t num_elem;
+ const u8 *addr[2];
+ size_t len[2];
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
* mask */
u8 mask;
@@ -468,21 +475,14 @@
/*
* 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 [|| identifier] || counter)
+ * password || counter)
*/
sae_pwd_seed_key(addr1, addr2, addrs);
addr[0] = password;
len[0] = password_len;
- 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++;
+ addr[1] = &counter;
+ len[1] = sizeof(counter);
k = dragonfly_min_pwe_loop_iter(sae->group);
@@ -497,7 +497,7 @@
}
wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
- if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+ if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
addr, len, pwd_seed) < 0)
break;
res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
@@ -766,19 +766,9 @@
const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y);
wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len);
- /* y = sqrt(v)
- * For prime p such that p = 3 mod 4 --> v^((p+1)/4) */
- if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0)
- goto fail;
- if ((bin1[prime_len - 1] & 0x03) != 3) {
- wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4");
- goto fail;
- }
+ /* y = sqrt(v) */
y = crypto_bignum_init();
- if (!y ||
- crypto_bignum_add(prime, one, t1) < 0 ||
- crypto_bignum_rshift(t1, 2, t1) < 0 ||
- crypto_bignum_exptmod(v, t1, prime, y) < 0)
+ if (!y || dragonfly_sqrt(ec, v, y) < 0)
goto fail;
debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len);
@@ -1354,15 +1344,13 @@
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
const u8 *password, size_t password_len,
- const char *identifier, struct sae_data *sae)
+ struct sae_data *sae)
{
if (sae->tmp == NULL ||
(sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
- password_len,
- identifier) < 0) ||
+ password_len) < 0) ||
(sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
- password_len,
- identifier) < 0))
+ password_len) < 0))
return -1;
sae->h2e = 0;
@@ -2023,6 +2011,9 @@
static int sae_parse_password_identifier(struct sae_data *sae,
const u8 **pos, const u8 *end)
{
+ const u8 *epos;
+ u8 len;
+
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
*pos, end - *pos);
if (!sae_is_password_id_elem(*pos, end)) {
@@ -2037,9 +2028,17 @@
return WLAN_STATUS_SUCCESS; /* No Password Identifier */
}
+ epos = *pos;
+ epos++; /* skip IE type */
+ len = *epos++; /* IE length */
+ if (len > end - epos || len < 1)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ epos++; /* skip ext ID */
+ len--;
+
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)) {
+ (len != os_strlen(sae->tmp->pw_id) ||
+ os_memcmp(sae->tmp->pw_id, epos, len) != 0)) {
wpa_printf(MSG_DEBUG,
"SAE: The included Password Identifier does not match the expected one (%s)",
sae->tmp->pw_id);
@@ -2047,14 +2046,14 @@
}
os_free(sae->tmp->pw_id);
- sae->tmp->pw_id = os_malloc((*pos)[1]);
+ sae->tmp->pw_id = os_malloc(len + 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';
+ os_memcpy(sae->tmp->pw_id, epos, len);
+ sae->tmp->pw_id[len] = '\0';
wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
- sae->tmp->pw_id, (*pos)[1] - 1);
- *pos = *pos + 2 + (*pos)[1];
+ sae->tmp->pw_id, len);
+ *pos = epos + len;
return WLAN_STATUS_SUCCESS;
}
@@ -2062,19 +2061,30 @@
static int sae_parse_rejected_groups(struct sae_data *sae,
const u8 **pos, const u8 *end)
{
+ const u8 *epos;
+ u8 len;
+
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
*pos, end - *pos);
if (!sae_is_rejected_groups_elem(*pos, end))
return WLAN_STATUS_SUCCESS;
+
+ epos = *pos;
+ epos++; /* skip IE type */
+ len = *epos++; /* IE length */
+ if (len > end - epos || len < 1)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ epos++; /* skip ext ID */
+ len--;
+
wpabuf_free(sae->tmp->peer_rejected_groups);
- sae->tmp->peer_rejected_groups = wpabuf_alloc((*pos)[1] - 1);
+ sae->tmp->peer_rejected_groups = wpabuf_alloc(len);
if (!sae->tmp->peer_rejected_groups)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- wpabuf_put_data(sae->tmp->peer_rejected_groups, (*pos) + 3,
- (*pos)[1] - 1);
+ wpabuf_put_data(sae->tmp->peer_rejected_groups, epos, len);
wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list",
sae->tmp->peer_rejected_groups);
- *pos = *pos + 2 + (*pos)[1];
+ *pos = epos + len;
return WLAN_STATUS_SUCCESS;
}
@@ -2246,10 +2256,10 @@
hash_len = sae->tmp->kck_len;
/* Send-Confirm */
- sc = wpabuf_put(buf, 0);
- wpabuf_put_le16(buf, sae->send_confirm);
if (sae->send_confirm < 0xffff)
sae->send_confirm++;
+ sc = wpabuf_put(buf, 0);
+ wpabuf_put_le16(buf, sae->send_confirm);
if (sae->tmp->ec)
res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
diff --git a/src/common/sae.h b/src/common/sae.h
index 2243c0f..93fc5fb 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -122,7 +122,7 @@
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
const u8 *password, size_t password_len,
- const char *identifier, struct sae_data *sae);
+ struct sae_data *sae);
int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
const u8 *addr1, const u8 *addr2,
int *rejected_groups, const struct sae_pk *pk);
diff --git a/src/common/version.h b/src/common/version.h
index 0235c9b..4409e1c 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -9,6 +9,6 @@
#define GIT_VERSION_STR_POSTFIX ""
#endif /* GIT_VERSION_STR_POSTFIX */
-#define VERSION_STR "2.10-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
+#define VERSION_STR "2.11-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
#endif /* VERSION_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 2b8c7f6..b78db05 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -3226,6 +3226,16 @@
pos[1] >= sizeof(struct ieee80211_vht_capabilities))
{
ie->vht_capabilities = pos + 2;
+ } else if (*pos == WLAN_EID_EXTENSION &&
+ pos[1] >= 1 + IEEE80211_HE_CAPAB_MIN_LEN &&
+ pos[2] == WLAN_EID_EXT_HE_CAPABILITIES) {
+ ie->he_capabilities = pos + 3;
+ ie->he_capab_len = pos[1] - 1;
+ } else if (*pos == WLAN_EID_EXTENSION &&
+ pos[1] >= 1 +
+ sizeof(struct ieee80211_he_6ghz_band_cap) &&
+ pos[2] == WLAN_EID_EXT_HE_6GHZ_BAND_CAP) {
+ ie->he_6ghz_capabilities = pos + 3;
} else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
ie->qosinfo = pos[2];
} else if (*pos == WLAN_EID_SUPPORTED_CHANNELS) {
@@ -3414,14 +3424,17 @@
* @pasn_group: Finite Cyclic Group ID for PASN authentication
* @wrapped_data_format: Format of the data in the Wrapped Data IE
* @pubkey: A buffer holding the local public key. Can be NULL
+ * @compressed: In case pubkey is included, indicates if the public key is
+ * compressed (only x coordinate is included) or not (both x and y
+ * coordinates are included)
* @comeback: A buffer holding the comeback token. Can be NULL
* @after: If comeback is set, defined the comeback time in seconds. -1 to not
* include the Comeback After field (frames from non-AP STA).
*/
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
u8 wrapped_data_format,
- struct wpabuf *pubkey,
- struct wpabuf *comeback, int after)
+ const struct wpabuf *pubkey, bool compressed,
+ const struct wpabuf *comeback, int after)
{
struct pasn_parameter_ie *params;
@@ -3460,13 +3473,22 @@
/*
* 2 octets for the finite cyclic group + 2 octets public key
- * length + the actual key
+ * length + 1 octet for the compressed/uncompressed indication +
+ * the actual key.
*/
- params->len += 2 + 1 + wpabuf_len(pubkey);
+ params->len += 2 + 1 + 1 + wpabuf_len(pubkey);
params->control |= WPA_PASN_CTRL_GROUP_AND_KEY_PRESENT;
wpabuf_put_le16(buf, pasn_group);
- wpabuf_put_u8(buf, wpabuf_len(pubkey));
+
+ /*
+ * The first octet indicates whether the public key is
+ * compressed, as defined in RFC 5480 section 2.2.
+ */
+ wpabuf_put_u8(buf, wpabuf_len(pubkey) + 1);
+ wpabuf_put_u8(buf, compressed ? WPA_PASN_PUBKEY_COMPRESSED_0 :
+ WPA_PASN_PUBKEY_UNCOMPRESSED);
+
wpabuf_put_buf(buf, pubkey);
}
}
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index c31e1a0..c28c55d 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -546,6 +546,11 @@
const u8 *pubkey;
};
+/* See RFC 5480 section 2.2 */
+#define WPA_PASN_PUBKEY_COMPRESSED_0 0x02
+#define WPA_PASN_PUBKEY_COMPRESSED_1 0x03
+#define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
+
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
int use_sha384);
@@ -592,6 +597,9 @@
size_t ext_supp_rates_len;
const u8 *ht_capabilities;
const u8 *vht_capabilities;
+ const u8 *he_capabilities;
+ size_t he_capab_len;
+ const u8 *he_6ghz_capabilities;
const u8 *supp_channels;
size_t supp_channels_len;
const u8 *supp_oper_classes;
@@ -655,8 +663,8 @@
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
u8 wrapped_data_format,
- struct wpabuf *pubkey,
- struct wpabuf *comeback, int after);
+ const struct wpabuf *pubkey, bool compressed,
+ const struct wpabuf *comeback, int after);
int wpa_pasn_add_wrapped_data(struct wpabuf *buf,
struct wpabuf *wrapped_data_buf);
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 126a789..3d3a62a 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -126,6 +126,10 @@
#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT "
/** Frequency ranges that the driver recommends to avoid */
#define WPA_EVENT_AVOID_FREQ "CTRL-EVENT-AVOID-FREQ "
+/** A new network profile was added (followed by network entry id) */
+#define WPA_EVENT_NETWORK_ADDED "CTRL-EVENT-NETWORK-ADDED "
+/** A network profile was removed (followed by prior network entry id) */
+#define WPA_EVENT_NETWORK_REMOVED "CTRL-EVENT-NETWORK-REMOVED "
/** Result of MSCS setup */
#define WPA_EVENT_MSCS_RESULT "CTRL-EVENT-MSCS-RESULT "
/** WPS overlap detected in PBC mode */
@@ -157,6 +161,10 @@
#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN "
#define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK "
+/** Result of SCS setup */
+#define WPA_EVENT_SCS_RESULT "CTRL-EVENT-SCS-RESULT "
+/* Event indicating DSCP policy */
+#define WPA_EVENT_DSCP_POLICY "CTRL-EVENT-DSCP-POLICY "
/* WPS ER events */
#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD "
@@ -204,6 +212,7 @@
#define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT "
#define DPP_EVENT_CSR "DPP-CSR "
#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX "
+#define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED "
/* MESH events */
#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "