cumilative patch from commit 95ad71157

Bug: 341971059
Bug: 394110783
Test: Connect to open, WPA2, WPA3 and OWE
Test: Establish P2P connection
Test: Basic SoftAp tests
Test: Ran above tests on Pixel6
Test: Regression test (401126565)

Fixed the TLS failure caused by 400b89162294f0344d82334218e8950fd01bb12f
95ad71157 P2P2: Get ID of device identity block from wpas_p2p_validate_dira()
f02e1d777 nl80211: Determine capability for P2P-R2 and PCC mode
c144dcbdf P2P2: Add support to fetch the P2P2 and PCC capability
d0528fb5e Add QCA vendor feature flags to indicate P2P-R2 and PCC support
b3b0297d8 P2P2: Indicate bootstrapping comeback response to upper layers
5ec339723 nl80211: Fix typo in SAE PWE debug message
d0213ad1e AP MLD: Fix hostapd crash during interface deinit with non-ML BSS
de49e55d7 BSS: Validate partner link BSSs while parsing Basic MLE
800e481bd MLD: Verify Per-STA Profile subelement length in reconf MLE
351089daa MLD: Fix Reconfiguration Multi-Link element parsing on non-AP MLD
53303bb3e Update the link BSS pointer during BSS reallocation on scan results
a4d2288de MACsec: Add option to always include ICV Indicator
ed423e44f authsrv: Log RADIUS accounting data
96dd8a03b RADIUS server: Add accounting message callback
373378f89 EAP-pwd: Do not include MS_FUNCS in CONFIG_FIPS=y builds
67feaa563 OpenSSL: Enable HMAC with short salt in FIPS configuration
0f92c8d8c OpenSSL: Use default provider instead of fips provider for DH group 5
6a15737b3 OpenSSL: Allow MD5 if FIPS mode or FIPS provider is set externally
573e9c1bb OpenSSL: Disable FIPS mode if MD4 is needed
1592d3416 OpenSSL: Print more failure details for EC failures
3b5b19e9c OpenSSL: Make debug log clearer on TLS initialization failure
651370325 SAE: Add an explicit debug print for failure to derive PWE
1af015a5d DPP: Remove a duplicated check for priv_key
c0b180d94 DPP: Add an explicit debug print for failed to build DPPEnvelopedData
ccc841470 SAE: Do not mark SAE enabled network disabled if PSK is not set
26c19188b OpenSSL: More debug prints on EVP digest/cipher failures
c063724b9 RADIUS: Check MD5 processing result
c073f61c4 Define additional QCA vendor roam trigger attribute values
f85a79cea Share wpa_init() error path handling
4c1ae9101 AP MLD: Search MLD-level and per-link PMKSA caches
0de2f1865 AP MLD: Store PMKSA from DPP to both per-link and MLD-level cache
4645fac93 AP MLD: Store PMKSA from control interface to both caches
c4dcf7577 AP MLD: List PMKSA entries from MLD-level cache too
a56d2bd97 AP MLD: Mark STA as MLD before checking association IEs
0d71e041b AP MLD: Store OWE/FILS PMKSA into the MLD-level PMKSA cache for MLO
8e326cabc AP MLD: Also remove from ml_pmksa when removing a PMKSA entry
c439291fc AP MLD: Store PMKSA generated from SAE authentication into ml_pmksa
799cc8eca AP MLD: Define a new MLD-level PMKSA cache shared by all links
1993770a5 Fix current_bss use in checking whether SSID has been verified
870d13f97 ERP: Initialize hapd->erp_keys earlier to avoid undefined behavior
caa22873c OpenSSL: Avoid undefined behavior in altSubjectName matching
616d85a42 Avoid undefined behavior in get_vendor_ie()
4cb1b7c31 trace: Avoid undefined behavior in backtrace search
449135c26 Remove undefined behavior from ieee802_11_defrag()
d185ab38f Fix wpa_supplicant global config bool reading/writing
e0baab3b6 mesh: Fix mesh_external_pmksa_cache initialization to cover error cases
47ff1b68f FT: Do not discard EAPOL-Start frame during initial MD association
012a893c4 wolfssl: Update suiteb ciphersuites
2ed980627 wpa_gui: Port to Qt6
39c7ef222 nl80211: Mark HT disabled on channel switch to a 6 GHz channel
b49542f42 nl80211: Fix hostapd crash when managing AP MLD interfaces
daeb5e111 EAP-TEAP: Check session_id length explicitly to avoid warnings
1bfd4398f RNR: Silence static analyzer warnings
dc05cbc46 WPS: Use 0xffff instead of -1 to set all u16 bits to 1
bc3ee85e5 AP MLD: Bounds checking for own Probe Response to silence analyzers
41398a873 nl80211: Debug print setsockopt() failures for NETLINK_EXT_ACK
97c4999f1 MLD: Try to avoid static analyzer warnings about tainted variable
a90f2f7a8 Use pointer to Action frame body instead of Category field
cb3a47247 Check random_get_bytes() output even in testing case
1c3b564af SME: Use a helper function for adding wpabuf to AssocReq IEs
bf936cdd1 P2P2: Check ssid != NULL more consistently in wpas_p2p_invite()
86dc3e369 mka: Simplify dl_list entry freeing
a36577c82 Make eht_cap != NULL check explicit to help static analyzers
553e114e0 PASN: Make ssid != NULL check easier for static analyzers
fab6e6546 P2P: Initialize new_ssid explicitly to make this easier for analyzers
741d23c3c P2P: Make sure go_dev_addr is initialized
12cd887c4 P2P2: Check peer_addr being available more consistently
714734135 Check network configuration availability before use in MAC randomization
ecf62b4d1 HS 2.0: Remove subscription remediation notification
7bb11e35d HS 2.0: Remove OSU related ANQP operations
e83528859 OSEN: Remove all OSEN functionality
f61b5faa4 XML: Remove now unused code
e960c3741 HTTP: Remove now unused code
b76b896d9 HS 2.0 client: Remove OSU/SPP/OMA-DM/EST functionality
3462d242a HS 2.0 server: Remove example OSU SPP server
326f093b9 Interworking: Prefer cred realm over realm in username for anonymous NAI
ca9f86a19 SAE: Multiple default password iteration
3e592a1a7 nl80211: Fix PASN auth alg check on big-endian CPUs
ff5248a8e nl80211: Fix HE 6 GHz capability fetching on big-endian CPUs
dacfb3956 MLD: Fix MLE parsing in for association on big-endian CPUs
7d2d4c1bd wpa_supplicant: Fix VHT SGI disabling on big-endian CPUs
4fd90f61d wpa_supplicant: Fix HT STBC capability overriding on big-endian CPUs
6b837f61b dbus: Remove unused wpas_dbus_sta_signal_prop_changed()
6dcc4c795 OpenSSL: Use proper ANSI C function declaration
f1425f2e1 RNR: Mark internal functions static
6fe387ad5 OCV: Fix HT/VHT capability check on big-endian CPUs
43dae6b35 PASN: Use NULL instead of 0 as a pointer
be7beba15 DPP: Mark internal functions static
33381b724 trace: Mark wpa_trace_test_fail static
3e4782549 SME: MLD: Fix byte order for the link reconfig MLE control field
ebfe8be3a Convert one-bit signed bitfield to unsigned
9db8ed4b9 SCS: Convert endianness of MAC Capabilities Information before use
ad8d30e0a AP MLD: Request MLO Group KDEs for a subset of links
00dc99117 nl80211: Remove support for use_monitor
539648699 AP MLD: Set WLAN_STA_ASSOC flag before copying STA entry (SME-in-driver)
90856b195 DPP: Send connection status result if disconnected during 4-way HS
ab3791d91 AP MLD: Allow new link to be added through control interface
00a7cad9c Make sure wpa_sm has correct PMK when PMKSA cache used by driver
298592db0 AP MLD: Cancel ap_sta_assoc_timeout for partner links
25876e936 Define a QCA vendor subcmd to set periodic probe response config
a971fa5b5 P2P: Check IEs buffer before use more consistently
f2bf0a638 nl80211: Avoid uninitialized err_info on test failure path
5066a39e0 Simplify supported rates and BSS membership selectors generation
ea626cb8c AP: Remove xrates_supported config
71c5ceb21 MBSSID: Add Extended Supported Rates element in MBSSID profile
085e5fa07 MBSSID: Correctly compute the Extended Supported Rates element length
2605fbc81 MBSSID: Fix Non-Inheritance element length calculation
5edbb257d GAS: Fix eloop timeout clearing on random MAC address error path
c8c7d56a3 P2P2: Reject P2P_VALIDATE_DIRA without nonce or tag
6fe367d6c EAP-pwd: Make code easier for static analyzers
c3fefaf41 JSON: More explicit check for depth in arrays/objects
50330cb91 SHA-PRF: Make code easier for static analyzers
218659c58 BSS: Clear wpa_bss pointers on bss entry removal
39b6e6efe P2P: Clear pending_listen_freq if listen failed
ec50904c1 Fix a typo in documentation of a configuration parameter
8ead26ff5 wolfSSL: Include asn.h to fix build with some library configs
13a30f10c drivers: RX-only configuration of the next TK during 4-way handshake
a58a0c592 MLD: Fix Multi-Link element parsing for association failures
a9eb687c0 AP MLD: Fix STA Info field parsing in Basic Multi-Link element
104e47a60 AP MLD: Simplify MLD MAC Address parsing from Multi-Link element
038cb0fc5 AP MLD: Fix Multi-Link element parsing in (Re)Association Request frame
2ba179722 P2P: Add Group ID info into P2P invitation control interface events
37b618743 EHT: Fix 6 GHz HE operation bandwidth for 320 MHz with puncturing
e35a79ab0 Fix crash due to iteratively calling radio_remove_works()
58ea0a652 nl80211: Fix compilation error due to uninitialized variable
5546f0ac0 Remove extra statement terminators
339a33455 RADIUS: Fix pending request dropping
b25769e48 QCA vendor values for traffic types for browsing and aperiodic bursts
f4c7c13ec Add QCA vendor test config attribute for link reconfiguration
dac63d98b Add QCA vendor attribute to enable/disable link reconfiguration support
8a8d66f00 Add QCA vendor command to trigger primary link migration

c12fc97e3 wolfssl: wc_PBKDF2() in FIPS requires unlocking the private key
e41e91a43 wolfSSL: Implement openssl_ecdh_curves
a1150cc60 wolfSSL: Simplify option setting in tls_set_conn_flags()
7bd855f34 wolfssl: Verify that session ticket setup does not fail
c38150cfe wolfssl: Actually use ocsp_stapling_response
b870181d4 wolfssl: Implement check_cert_subject
5c07e9be0 wolfssl: Add missing return in tls_init() in an error case
26e2ff781 wolfssl: Remove unused and non-compiling code for OCSP
77f82dcb3 wolfssl: Log error number on failure
0797fd2ab wolfssl: Remove unnecessary WOLFSSL_X509_STORE manipulation
59c3bd658 wolfssl: Generate events when OCSP status is revoked
49d0c323a wolfssl: Set additional sigalgs when using anonymous cipher
f50f530da wolfssl: Implement SuiteB ciphersuites
99239d08d wolfssl: Implement RSA-OAEP-SHA256 for EAP-AKA privacy protection
5ed2778db wolfssl: Support tod policy
34914311c wolfssl: Fix get_x509_cert()
d83903545 wolfssl: Use defines for ex_data access
a3890142d wolfssl: Simplify tls_get_cipher()
400b89162 OpenSSL: Use pkcs11-provider when OPENSSL_NO_ENGINE is defined
d37045e85 AP: Fix disconnect from EAPOL state machine handling
c924335ad AP: Include the Probe Request frame inside RX_PROBE_REQUEST event
5545ca8f9 GnuTLS: Do not override priority string on shutdown for reauth
26d64d737 GnuTLS: Use standard comment for falling through switch case
4a504c4e5 GnuTLS: Disable TLS 1.3 if instructed
5543f5efa wpa_supplicant: Use wpa_dbg() for "Successfully set 4addr mode"
9693a9018 Extend QCA vendor attributes for PASN offload from driver to userspace
24ef9862f nl80211: Send a list of BSS membership selectors supported by SME
2d2c42a47 AP: Only include SAE H2E BSS membership selector if SAE is required
bb6b2b854 Sync with wireless-next.git include/uapi/linux/nl80211.h
82c60dd54 STA: Support SPP A-MSDU negotiation
9c03bb14d nl80211: Option to tell the driver about SPP A-MSDUs in assoc params
61f505078 AP: Support SPP A-MSDU negotiation
27aedf346 AP: Add spp_amsdu configuration parameter
72ffc71d5 nl80211: SPP A-MSDU driver capability
f8d02941b RSNXE definition of SPP A-MSDU Capable
43c65f8a5 AP: Add a csa_ie_only testing option
4ba989fd3 NAN USD: Add NAN_UNPAUSE_PUBLISH to cancel pauseState
5b0201a27 hostapd: Fix 'start_disabled' option being ignored
0ca781b93 build: Disable some optimizations if TRACE_BFD is enabled
92cea9a77 P2P: Provide better failure reason for group formation errors
1ce37105d ext_password_file: Ensure full key match with password file entries
77ff2b61a STA: Known STA Identification to skip association comeback mechanism
e62c2dc09 AP: Known STA Identification to skip association comeback mechanism
726432d76 RADIUS: Drop pending request only when accepting the response
6799809ee P2P2: Bootstrapping through wpas_p2p_prov_disc()
9f7dc9c30 P2P2: Control interface command to validate DIRA info
fee68c237 P2P2: Control interface command to get DIRA info of a P2P device
99de77c57 P2P2: Save the latest nonce and tag from a P2P USD discovery frame
7c9081685 wlantest: Parse Link Reconfiguration Request/Response
9e95f0d38 AP MLD: Skip over Extended MLD Capabilities And Operations field
b375b7630 Do not write mesh_fwding network parameter if it has default value
b6cab22c2 P2P2: Update P2P_INVITE processing for SSID randomization
374353d31 P2P2: SSID randomization on group reinvoke
ce193d6e1 P2P: Make p2p_build_ssid() available outside src/p2p
ec4569174 P2P2: Store ID of Device Identity block in network block
c96fd75b1 P2P2: Add USD service hash in the P2P2 PASN M1 frame
4845c87eb P2P2: Random PMKID in pairing verification
99905ab44 P2P2: Return ID of identity block for p2p_validate_dira()
f92959500 P2P2: Add DIRA to PASN-M1 during pairing verification
ee41bacfa OWE: Consider the currently associated transition mode SSID known
b0f587944 Do not remove a currently used BSS entry when removing oldest unknown BSS
c78295c35 nl80211: Fix compilation error when CONFIG_DRIVER_NL80211_BRCM is enabled
d73ad8cbc Enable beacon protection if IEEE 802.11be/EHT is enabled for BSS
9cb7b0bce DPP: Discard DPP Action frame in AP mode if no global DPP context
12f1edc9e RSNO: Generate IGTK if any of the RSN variants has PMF enabled
dd65d13ce Add QCA vendor attribute for BTM reject support
001a728fe Add QCA vendor attribute for extra EHT-LTF support
c54f4aab6 Add QCA vendor attribute for triggered SU BF support

BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from open source

Change-Id: I0e1b0cda9e035d946283b6a83a1f6d796b882bb7
Signed-off-by: Sunil Ravi <sunilravi@google.com>
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index 2ca85f9..f679df4 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -9,9 +9,6 @@
 #include "includes.h"
 #include <time.h>
 #include <sys/stat.h>
-#ifdef ANDROID
-#include "private/android_filesystem_config.h"
-#endif /* ANDROID */
 
 #include "common.h"
 #include "utils/browser.h"
@@ -25,10 +22,9 @@
 #include "crypto/sha256.h"
 #include "osu_client.h"
 
-const char *spp_xsd_fname = "spp.xsd";
+static void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...);
 
-
-void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
+static void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
 {
 	va_list ap;
 	FILE *f;
@@ -54,7 +50,7 @@
 }
 
 
-void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...)
+static void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...)
 {
 	va_list ap;
 	FILE *f;
@@ -74,231 +70,6 @@
 }
 
 
-void debug_dump_node(struct hs20_osu_client *ctx, const char *title,
-		     xml_node_t *node)
-{
-	char *str = xml_node_to_str(ctx->xml, node);
-	wpa_printf(MSG_DEBUG, "[hs20] %s: '%s'", title, str);
-	free(str);
-}
-
-
-static int valid_fqdn(const char *fqdn)
-{
-	const char *pos;
-
-	/* TODO: could make this more complete.. */
-	if (strchr(fqdn, '.') == 0 || strlen(fqdn) > 255)
-		return 0;
-	for (pos = fqdn; *pos; pos++) {
-		if (*pos >= 'a' && *pos <= 'z')
-			continue;
-		if (*pos >= 'A' && *pos <= 'Z')
-			continue;
-		if (*pos >= '0' && *pos <= '9')
-			continue;
-		if (*pos == '-' || *pos == '.' || *pos == '_')
-			continue;
-		return 0;
-	}
-	return 1;
-}
-
-
-static int android_update_permission(const char *path, mode_t mode)
-{
-#ifdef ANDROID
-	/* we need to change file/folder permission for Android */
-
-	if (!path) {
-		wpa_printf(MSG_ERROR, "file path null");
-		return -1;
-	}
-
-	/* Allow processes running with Group ID as AID_WIFI,
-	 * to read files from SP, SP/<fqdn>, Cert and osu-info directories */
-	if (lchown(path, -1, AID_WIFI)) {
-		wpa_printf(MSG_INFO, "CTRL: Could not lchown directory: %s",
-			   strerror(errno));
-		return -1;
-	}
-
-	if (chmod(path, mode) < 0) {
-		wpa_printf(MSG_INFO, "CTRL: Could not chmod directory: %s",
-			   strerror(errno));
-		return -1;
-	}
-#endif  /* ANDROID */
-
-	return 0;
-}
-
-
-int osu_get_certificate(struct hs20_osu_client *ctx, xml_node_t *getcert)
-{
-	xml_node_t *node;
-	char *url, *user = NULL, *pw = NULL;
-	char *proto;
-	int ret = -1;
-
-	proto = xml_node_get_attr_value(ctx->xml, getcert,
-					"enrollmentProtocol");
-	if (!proto)
-		return -1;
-	wpa_printf(MSG_INFO, "getCertificate - enrollmentProtocol=%s", proto);
-	write_summary(ctx, "getCertificate - enrollmentProtocol=%s", proto);
-	if (os_strcasecmp(proto, "EST") != 0) {
-		wpa_printf(MSG_INFO, "Unsupported enrollmentProtocol");
-		xml_node_get_attr_value_free(ctx->xml, proto);
-		return -1;
-	}
-	xml_node_get_attr_value_free(ctx->xml, proto);
-
-	node = get_node(ctx->xml, getcert, "enrollmentServerURI");
-	if (node == NULL) {
-		wpa_printf(MSG_INFO, "Could not find enrollmentServerURI node");
-		xml_node_get_attr_value_free(ctx->xml, proto);
-		return -1;
-	}
-	url = xml_node_get_text(ctx->xml, node);
-	if (url == NULL) {
-		wpa_printf(MSG_INFO, "Could not get URL text");
-		return -1;
-	}
-	wpa_printf(MSG_INFO, "enrollmentServerURI: %s", url);
-	write_summary(ctx, "enrollmentServerURI: %s", url);
-
-	node = get_node(ctx->xml, getcert, "estUserID");
-	if (node == NULL && !ctx->client_cert_present) {
-		wpa_printf(MSG_INFO, "Could not find estUserID node");
-		goto fail;
-	}
-	if (node) {
-		user = xml_node_get_text(ctx->xml, node);
-		if (user == NULL) {
-			wpa_printf(MSG_INFO, "Could not get estUserID text");
-			goto fail;
-		}
-		wpa_printf(MSG_INFO, "estUserID: %s", user);
-		write_summary(ctx, "estUserID: %s", user);
-	}
-
-	node = get_node(ctx->xml, getcert, "estPassword");
-	if (node == NULL && !ctx->client_cert_present) {
-		wpa_printf(MSG_INFO, "Could not find estPassword node");
-		goto fail;
-	}
-	if (node) {
-		pw = xml_node_get_base64_text(ctx->xml, node, NULL);
-		if (pw == NULL) {
-			wpa_printf(MSG_INFO, "Could not get estPassword text");
-			goto fail;
-		}
-		wpa_printf(MSG_INFO, "estPassword: %s", pw);
-	}
-
-	mkdir("Cert", S_IRWXU);
-	android_update_permission("Cert", S_IRWXU | S_IRWXG);
-
-	if (est_load_cacerts(ctx, url) < 0 ||
-	    est_build_csr(ctx, url) < 0 ||
-	    est_simple_enroll(ctx, url, user, pw) < 0)
-		goto fail;
-
-	ret = 0;
-fail:
-	xml_node_get_text_free(ctx->xml, url);
-	xml_node_get_text_free(ctx->xml, user);
-	xml_node_get_text_free(ctx->xml, pw);
-
-	return ret;
-}
-
-
-static int process_est_cert(struct hs20_osu_client *ctx, xml_node_t *cert,
-			    const char *fqdn)
-{
-	u8 digest1[SHA256_MAC_LEN], digest2[SHA256_MAC_LEN];
-	char *der, *pem;
-	size_t der_len, pem_len;
-	char *fingerprint;
-	char buf[200];
-
-	wpa_printf(MSG_INFO, "PPS for certificate credential - fqdn=%s", fqdn);
-
-	fingerprint = xml_node_get_text(ctx->xml, cert);
-	if (fingerprint == NULL)
-		return -1;
-	if (hexstr2bin(fingerprint, digest1, SHA256_MAC_LEN) < 0) {
-		wpa_printf(MSG_INFO, "Invalid SHA256 hash value");
-		write_result(ctx, "Invalid client certificate SHA256 hash value in PPS");
-		xml_node_get_text_free(ctx->xml, fingerprint);
-		return -1;
-	}
-	xml_node_get_text_free(ctx->xml, fingerprint);
-
-	der = os_readfile("Cert/est_cert.der", &der_len);
-	if (der == NULL) {
-		wpa_printf(MSG_INFO, "Could not find client certificate from EST");
-		write_result(ctx, "Could not find client certificate from EST");
-		return -1;
-	}
-
-	if (sha256_vector(1, (const u8 **) &der, &der_len, digest2) < 0) {
-		os_free(der);
-		return -1;
-	}
-	os_free(der);
-
-	if (os_memcmp(digest1, digest2, sizeof(digest1)) != 0) {
-		wpa_printf(MSG_INFO, "Client certificate from EST does not match fingerprint from PPS MO");
-		write_result(ctx, "Client certificate from EST does not match fingerprint from PPS MO");
-		return -1;
-	}
-
-	wpa_printf(MSG_INFO, "Client certificate from EST matches PPS MO");
-	unlink("Cert/est_cert.der");
-
-	os_snprintf(buf, sizeof(buf), "SP/%s/client-ca.pem", fqdn);
-	if (rename("Cert/est-cacerts.pem", buf) < 0) {
-		wpa_printf(MSG_INFO, "Could not move est-cacerts.pem to client-ca.pem: %s",
-			   strerror(errno));
-		return -1;
-	}
-	pem = os_readfile(buf, &pem_len);
-
-	os_snprintf(buf, sizeof(buf), "SP/%s/client-cert.pem", fqdn);
-	if (rename("Cert/est_cert.pem", buf) < 0) {
-		wpa_printf(MSG_INFO, "Could not move est_cert.pem to client-cert.pem: %s",
-			   strerror(errno));
-		os_free(pem);
-		return -1;
-	}
-
-	if (pem) {
-		FILE *f = fopen(buf, "a");
-		if (f) {
-			fwrite(pem, pem_len, 1, f);
-			fclose(f);
-		}
-		os_free(pem);
-	}
-
-	os_snprintf(buf, sizeof(buf), "SP/%s/client-key.pem", fqdn);
-	if (rename("Cert/privkey-plain.pem", buf) < 0) {
-		wpa_printf(MSG_INFO, "Could not move privkey-plain.pem to client-key.pem: %s",
-			   strerror(errno));
-		return -1;
-	}
-
-	unlink("Cert/est-req.b64");
-	unlink("Cert/est-req.pem");
-	rmdir("Cert");
-
-	return 0;
-}
-
-
 #define TMP_CERT_DL_FILE "tmp-cert-download"
 
 static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
@@ -337,12 +108,10 @@
 	xml_node_get_text_free(ctx->xml, hash);
 
 	write_summary(ctx, "Download certificate from %s", url);
-	ctx->no_osu_cert_validation = 1;
 	http_ocsp_set(ctx->http, 1);
 	res = http_download_file(ctx->http, url, TMP_CERT_DL_FILE, NULL);
 	http_ocsp_set(ctx->http,
 		      (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
-	ctx->no_osu_cert_validation = 0;
 	xml_node_get_text_free(ctx->xml, url);
 	if (res < 0)
 		return -1;
@@ -392,60 +161,6 @@
 }
 
 
-static int cmd_dl_osu_ca(struct hs20_osu_client *ctx, const char *pps_fname,
-			 const char *ca_fname)
-{
-	xml_node_t *pps, *node;
-	int ret;
-
-	pps = node_from_file(ctx->xml, pps_fname);
-	if (pps == NULL) {
-		wpa_printf(MSG_INFO, "Could not read or parse '%s'", pps_fname);
-		return -1;
-	}
-
-	node = get_child_node(ctx->xml, pps,
-			      "SubscriptionUpdate/TrustRoot");
-	if (node == NULL) {
-		wpa_printf(MSG_INFO, "No SubscriptionUpdate/TrustRoot/CertURL found from PPS");
-		xml_node_free(ctx->xml, pps);
-		return -1;
-	}
-
-	ret = download_cert(ctx, node, ca_fname);
-	xml_node_free(ctx->xml, pps);
-
-	return ret;
-}
-
-
-static int cmd_dl_polupd_ca(struct hs20_osu_client *ctx, const char *pps_fname,
-			    const char *ca_fname)
-{
-	xml_node_t *pps, *node;
-	int ret;
-
-	pps = node_from_file(ctx->xml, pps_fname);
-	if (pps == NULL) {
-		wpa_printf(MSG_INFO, "Could not read or parse '%s'", pps_fname);
-		return -1;
-	}
-
-	node = get_child_node(ctx->xml, pps,
-			      "Policy/PolicyUpdate/TrustRoot");
-	if (node == NULL) {
-		wpa_printf(MSG_INFO, "No Policy/PolicyUpdate/TrustRoot/CertURL found from PPS");
-		xml_node_free(ctx->xml, pps);
-		return -2;
-	}
-
-	ret = download_cert(ctx, node, ca_fname);
-	xml_node_free(ctx->xml, pps);
-
-	return ret;
-}
-
-
 static int cmd_dl_aaa_ca(struct hs20_osu_client *ctx, const char *pps_fname,
 			 const char *ca_fname)
 {
@@ -480,298 +195,6 @@
 }
 
 
-static int download_trust_roots(struct hs20_osu_client *ctx,
-				const char *pps_fname)
-{
-	char *dir, *pos;
-	char fname[300];
-	int ret, ret1;
-
-	dir = os_strdup(pps_fname);
-	if (dir == NULL)
-		return -1;
-	pos = os_strrchr(dir, '/');
-	if (pos == NULL) {
-		os_free(dir);
-		return -1;
-	}
-	*pos = '\0';
-
-	snprintf(fname, sizeof(fname), "%s/ca.pem", dir);
-	ret = cmd_dl_osu_ca(ctx, pps_fname, fname);
-	snprintf(fname, sizeof(fname), "%s/polupd-ca.pem", dir);
-	ret1 = cmd_dl_polupd_ca(ctx, pps_fname, fname);
-	if (ret == 0 && ret1 == -1)
-		ret = -1;
-	snprintf(fname, sizeof(fname), "%s/aaa-ca.pem", dir);
-	ret1 = cmd_dl_aaa_ca(ctx, pps_fname, fname);
-	if (ret == 0 && ret1 == -1)
-		ret = -1;
-
-	os_free(dir);
-
-	return ret;
-}
-
-
-static int server_dnsname_suffix_match(struct hs20_osu_client *ctx,
-				       const char *fqdn)
-{
-	size_t match_len, len, i;
-	const char *val;
-
-	match_len = os_strlen(fqdn);
-
-	for (i = 0; i < ctx->server_dnsname_count; i++) {
-		wpa_printf(MSG_INFO,
-			   "Checking suffix match against server dNSName %s",
-			   ctx->server_dnsname[i]);
-		val = ctx->server_dnsname[i];
-		len = os_strlen(val);
-
-		if (match_len > len)
-			continue;
-
-		if (os_strncasecmp(val + len - match_len, fqdn, match_len) != 0)
-			continue; /* no match */
-
-		if (match_len == len)
-			return 1; /* exact match */
-
-		if (val[len - match_len - 1] == '.')
-			return 1; /* full label match completes suffix match */
-
-		/* Reject due to incomplete label match */
-	}
-
-	/* None of the dNSName(s) matched */
-	return 0;
-}
-
-
-int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri,
-		    xml_node_t *add_mo, char *fname, size_t fname_len)
-{
-	char *str;
-	char *fqdn, *pos;
-	xml_node_t *tnds, *mo, *cert;
-	const char *name;
-	int ret;
-
-	if (strncmp(uri, "./Wi-Fi/", 8) != 0) {
-		wpa_printf(MSG_INFO, "Unsupported location for addMO to add PPS MO: '%s'",
-			   uri);
-		write_result(ctx, "Unsupported location for addMO to add PPS MO: '%s'",
-			     uri);
-		return -1;
-	}
-
-	fqdn = strdup(uri + 8);
-	if (fqdn == NULL)
-		return -1;
-	pos = strchr(fqdn, '/');
-	if (pos) {
-		if (os_strcasecmp(pos, "/PerProviderSubscription") != 0) {
-			wpa_printf(MSG_INFO, "Unsupported location for addMO to add PPS MO (extra directory): '%s'",
-				   uri);
-			write_result(ctx, "Unsupported location for addMO to "
-				     "add PPS MO (extra directory): '%s'", uri);
-			free(fqdn);
-			return -1;
-		}
-		*pos = '\0'; /* remove trailing slash and PPS node name */
-	}
-	wpa_printf(MSG_INFO, "SP FQDN: %s", fqdn);
-
-	if (!server_dnsname_suffix_match(ctx, fqdn)) {
-		wpa_printf(MSG_INFO,
-			   "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values, count: %d",
-			   fqdn, (int) ctx->server_dnsname_count);
-		write_result(ctx, "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values",
-			     fqdn);
-		free(fqdn);
-		return -1;
-	}
-
-	if (!valid_fqdn(fqdn)) {
-		wpa_printf(MSG_INFO, "Invalid FQDN '%s'", fqdn);
-		write_result(ctx, "Invalid FQDN '%s'", fqdn);
-		free(fqdn);
-		return -1;
-	}
-
-	mkdir("SP", S_IRWXU);
-	snprintf(fname, fname_len, "SP/%s", fqdn);
-	if (mkdir(fname, S_IRWXU) < 0) {
-		if (errno != EEXIST) {
-			int err = errno;
-			wpa_printf(MSG_INFO, "mkdir(%s) failed: %s",
-				   fname, strerror(err));
-			free(fqdn);
-			return -1;
-		}
-	}
-
-	android_update_permission("SP", S_IRWXU | S_IRWXG);
-	android_update_permission(fname, S_IRWXU | S_IRWXG);
-
-	snprintf(fname, fname_len, "SP/%s/pps.xml", fqdn);
-
-	if (os_file_exists(fname)) {
-		wpa_printf(MSG_INFO, "PPS file '%s' exists - reject addMO",
-			   fname);
-		write_result(ctx, "PPS file '%s' exists - reject addMO",
-			     fname);
-		free(fqdn);
-		return -2;
-	}
-	wpa_printf(MSG_INFO, "Using PPS file: %s", fname);
-
-	str = xml_node_get_text(ctx->xml, add_mo);
-	if (str == NULL) {
-		wpa_printf(MSG_INFO, "Could not extract MO text");
-		free(fqdn);
-		return -1;
-	}
-	wpa_printf(MSG_DEBUG, "[hs20] addMO text: '%s'", str);
-
-	tnds = xml_node_from_buf(ctx->xml, str);
-	xml_node_get_text_free(ctx->xml, str);
-	if (tnds == NULL) {
-		wpa_printf(MSG_INFO, "[hs20] Could not parse addMO text");
-		free(fqdn);
-		return -1;
-	}
-
-	mo = tnds_to_mo(ctx->xml, tnds);
-	if (mo == NULL) {
-		wpa_printf(MSG_INFO, "[hs20] Could not parse addMO TNDS text");
-		free(fqdn);
-		return -1;
-	}
-
-	debug_dump_node(ctx, "Parsed TNDS", mo);
-
-	name = xml_node_get_localname(ctx->xml, mo);
-	if (os_strcasecmp(name, "PerProviderSubscription") != 0) {
-		wpa_printf(MSG_INFO, "[hs20] Unexpected PPS MO root node name '%s'",
-			   name);
-		free(fqdn);
-		return -1;
-	}
-
-	cert = get_child_node(ctx->xml, mo,
-			      "Credential/DigitalCertificate/"
-			      "CertSHA256Fingerprint");
-	if (cert && process_est_cert(ctx, cert, fqdn) < 0) {
-		xml_node_free(ctx->xml, mo);
-		free(fqdn);
-		return -1;
-	}
-	free(fqdn);
-
-	if (node_to_file(ctx->xml, fname, mo) < 0) {
-		wpa_printf(MSG_INFO, "Could not write MO to file");
-		xml_node_free(ctx->xml, mo);
-		return -1;
-	}
-	xml_node_free(ctx->xml, mo);
-
-	wpa_printf(MSG_INFO, "A new PPS MO added as '%s'", fname);
-	write_summary(ctx, "A new PPS MO added as '%s'", fname);
-
-	ret = download_trust_roots(ctx, fname);
-	if (ret < 0) {
-		wpa_printf(MSG_INFO, "Remove invalid PPS MO file");
-		write_summary(ctx, "Remove invalid PPS MO file");
-		unlink(fname);
-	}
-
-	return ret;
-}
-
-
-int update_pps_file(struct hs20_osu_client *ctx, const char *pps_fname,
-		    xml_node_t *pps)
-{
-	char *str;
-	FILE *f;
-	char backup[300];
-
-	if (ctx->client_cert_present) {
-		xml_node_t *cert;
-		cert = get_child_node(ctx->xml, pps,
-				      "Credential/DigitalCertificate/"
-				      "CertSHA256Fingerprint");
-		if (cert && os_file_exists("Cert/est_cert.der") &&
-		    process_est_cert(ctx, cert, ctx->fqdn) < 0) {
-			wpa_printf(MSG_INFO, "EST certificate update processing failed on PPS MO update");
-			return -1;
-		}
-	}
-
-	wpa_printf(MSG_INFO, "Updating PPS MO %s", pps_fname);
-
-	str = xml_node_to_str(ctx->xml, pps);
-	if (str == NULL) {
-		wpa_printf(MSG_ERROR, "No node found");
-		return -1;
-	}
-	wpa_printf(MSG_MSGDUMP, "[hs20] Updated PPS: '%s'", str);
-
-	snprintf(backup, sizeof(backup), "%s.bak", pps_fname);
-	rename(pps_fname, backup);
-	f = fopen(pps_fname, "w");
-	if (f == NULL) {
-		wpa_printf(MSG_INFO, "Could not write PPS");
-		rename(backup, pps_fname);
-		free(str);
-		return -1;
-	}
-	fprintf(f, "%s\n", str);
-	fclose(f);
-
-	free(str);
-
-	return 0;
-}
-
-
-void get_user_pw(struct hs20_osu_client *ctx, xml_node_t *pps,
-		 const char *alt_loc, char **user, char **pw)
-{
-	xml_node_t *node;
-
-	node = get_child_node(ctx->xml, pps,
-			      "Credential/UsernamePassword/Username");
-	if (node)
-		*user = xml_node_get_text(ctx->xml, node);
-
-	node = get_child_node(ctx->xml, pps,
-			      "Credential/UsernamePassword/Password");
-	if (node)
-		*pw = xml_node_get_base64_text(ctx->xml, node, NULL);
-
-	node = get_child_node(ctx->xml, pps, alt_loc);
-	if (node) {
-		xml_node_t *a;
-		a = get_node(ctx->xml, node, "Username");
-		if (a) {
-			xml_node_get_text_free(ctx->xml, *user);
-			*user = xml_node_get_text(ctx->xml, a);
-			wpa_printf(MSG_INFO, "Use OSU username '%s'", *user);
-		}
-
-		a = get_node(ctx->xml, node, "Password");
-		if (a) {
-			free(*pw);
-			*pw = xml_node_get_base64_text(ctx->xml, a, NULL);
-			wpa_printf(MSG_INFO, "Use OSU password");
-		}
-	}
-}
-
-
 /* Remove old credentials based on HomeSP/FQDN */
 static void remove_sp_creds(struct hs20_osu_client *ctx, const char *fqdn)
 {
@@ -1874,14 +1297,13 @@
 			wpa_printf(MSG_INFO, "Failed to set provisioning_sp");
 		wpa_printf(MSG_INFO, "credential localname: '%s'", name);
 		set_pps_credential(ctx, id, child, fqdn);
-		ctx->pps_cred_set = 1;
 	}
 
 	xml_node_get_text_free(ctx->xml, update_identifier);
 }
 
 
-void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname)
+static void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname)
 {
 	xml_node_t *pps;
 	const char *fqdn;
@@ -1988,1167 +1410,20 @@
 }
 
 
-struct osu_icon {
-	int id;
-	char lang[4];
-	char mime_type[256];
-	char filename[256];
-};
-
-struct osu_data {
-	char bssid[20];
-	char url[256];
-	unsigned int methods;
-	char osu_ssid[33];
-	char osu_ssid2[33];
-	char osu_nai[256];
-	char osu_nai2[256];
-	struct osu_lang_text friendly_name[MAX_OSU_VALS];
-	size_t friendly_name_count;
-	struct osu_lang_text serv_desc[MAX_OSU_VALS];
-	size_t serv_desc_count;
-	struct osu_icon icon[MAX_OSU_VALS];
-	size_t icon_count;
-};
-
-
-static struct osu_data * parse_osu_providers(const char *fname, size_t *count)
-{
-	FILE *f;
-	char buf[1000];
-	struct osu_data *osu = NULL, *last = NULL;
-	size_t osu_count = 0;
-	char *pos, *end;
-	int res;
-
-	f = fopen(fname, "r");
-	if (f == NULL) {
-		wpa_printf(MSG_ERROR, "Could not open %s", fname);
-		return NULL;
-	}
-
-	while (fgets(buf, sizeof(buf), f)) {
-		pos = strchr(buf, '\n');
-		if (pos)
-			*pos = '\0';
-
-		if (strncmp(buf, "OSU-PROVIDER ", 13) == 0) {
-			last = realloc(osu, (osu_count + 1) * sizeof(*osu));
-			if (last == NULL)
-				break;
-			osu = last;
-			last = &osu[osu_count++];
-			memset(last, 0, sizeof(*last));
-			res = os_snprintf(last->bssid, sizeof(last->bssid),
-					  "%s", buf + 13);
-			if (os_snprintf_error(sizeof(last->bssid), res))
-				break;
-			continue;
-		}
-		if (!last)
-			continue;
-
-		if (strncmp(buf, "uri=", 4) == 0) {
-			res = os_snprintf(last->url, sizeof(last->url),
-					  "%s", buf + 4);
-			if (os_snprintf_error(sizeof(last->url), res))
-				break;
-			continue;
-		}
-
-		if (strncmp(buf, "methods=", 8) == 0) {
-			last->methods = strtol(buf + 8, NULL, 16);
-			continue;
-		}
-
-		if (strncmp(buf, "osu_ssid=", 9) == 0) {
-			res = os_snprintf(last->osu_ssid,
-					  sizeof(last->osu_ssid),
-					  "%s", buf + 9);
-			if (os_snprintf_error(sizeof(last->osu_ssid), res))
-				break;
-			continue;
-		}
-
-		if (strncmp(buf, "osu_ssid2=", 10) == 0) {
-			res = os_snprintf(last->osu_ssid2,
-					  sizeof(last->osu_ssid2),
-					  "%s", buf + 10);
-			if (os_snprintf_error(sizeof(last->osu_ssid2), res))
-				break;
-			continue;
-		}
-
-		if (os_strncmp(buf, "osu_nai=", 8) == 0) {
-			res = os_snprintf(last->osu_nai, sizeof(last->osu_nai),
-					  "%s", buf + 8);
-			if (os_snprintf_error(sizeof(last->osu_nai), res))
-				break;
-			continue;
-		}
-
-		if (os_strncmp(buf, "osu_nai2=", 9) == 0) {
-			res = os_snprintf(last->osu_nai2,
-					  sizeof(last->osu_nai2),
-					  "%s", buf + 9);
-			if (os_snprintf_error(sizeof(last->osu_nai2), res))
-				break;
-			continue;
-		}
-
-		if (strncmp(buf, "friendly_name=", 14) == 0) {
-			struct osu_lang_text *txt;
-			if (last->friendly_name_count == MAX_OSU_VALS)
-				continue;
-			pos = strchr(buf + 14, ':');
-			if (pos == NULL)
-				continue;
-			*pos++ = '\0';
-			txt = &last->friendly_name[last->friendly_name_count++];
-			res = os_snprintf(txt->lang, sizeof(txt->lang),
-					  "%s", buf + 14);
-			if (os_snprintf_error(sizeof(txt->lang), res))
-				break;
-			res = os_snprintf(txt->text, sizeof(txt->text),
-					  "%s", pos);
-			if (os_snprintf_error(sizeof(txt->text), res))
-				break;
-		}
-
-		if (strncmp(buf, "desc=", 5) == 0) {
-			struct osu_lang_text *txt;
-			if (last->serv_desc_count == MAX_OSU_VALS)
-				continue;
-			pos = strchr(buf + 5, ':');
-			if (pos == NULL)
-				continue;
-			*pos++ = '\0';
-			txt = &last->serv_desc[last->serv_desc_count++];
-			res = os_snprintf(txt->lang, sizeof(txt->lang),
-					  "%s", buf + 5);
-			if (os_snprintf_error(sizeof(txt->lang), res))
-				break;
-			res = os_snprintf(txt->text, sizeof(txt->text),
-					  "%s", pos);
-			if (os_snprintf_error(sizeof(txt->text), res))
-				break;
-		}
-
-		if (strncmp(buf, "icon=", 5) == 0) {
-			struct osu_icon *icon;
-			if (last->icon_count == MAX_OSU_VALS)
-				continue;
-			icon = &last->icon[last->icon_count++];
-			icon->id = atoi(buf + 5);
-			pos = strchr(buf, ':');
-			if (pos == NULL)
-				continue;
-			pos = strchr(pos + 1, ':');
-			if (pos == NULL)
-				continue;
-			pos = strchr(pos + 1, ':');
-			if (pos == NULL)
-				continue;
-			pos++;
-			end = strchr(pos, ':');
-			if (!end)
-				continue;
-			*end = '\0';
-			res = os_snprintf(icon->lang, sizeof(icon->lang),
-					  "%s", pos);
-			if (os_snprintf_error(sizeof(icon->lang), res))
-				break;
-			pos = end + 1;
-
-			end = strchr(pos, ':');
-			if (end)
-				*end = '\0';
-			res = os_snprintf(icon->mime_type,
-					  sizeof(icon->mime_type), "%s", pos);
-			if (os_snprintf_error(sizeof(icon->mime_type), res))
-				break;
-			if (!end)
-				continue;
-			pos = end + 1;
-
-			end = strchr(pos, ':');
-			if (end)
-				*end = '\0';
-			res = os_snprintf(icon->filename,
-					  sizeof(icon->filename), "%s", pos);
-			if (os_snprintf_error(sizeof(icon->filename), res))
-				break;
-			continue;
-		}
-	}
-
-	fclose(f);
-
-	*count = osu_count;
-	return osu;
-}
-
-
-static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
-		       const char *ssid, const char *ssid2, const char *url,
-		       unsigned int methods, int no_prod_assoc,
-		       const char *osu_nai, const char *osu_nai2)
-{
-	int id;
-	const char *ifname = ctx->ifname;
-	char buf[200];
-	struct wpa_ctrl *mon;
-	int res;
-
-	if (ssid2 && ssid2[0] == '\0')
-		ssid2 = NULL;
-
-	if (ctx->osu_ssid) {
-		if (os_strcmp(ssid, ctx->osu_ssid) == 0) {
-			wpa_printf(MSG_DEBUG,
-				   "Enforced OSU SSID matches ANQP info");
-			ssid2 = NULL;
-		} else if (ssid2 && os_strcmp(ssid2, ctx->osu_ssid) == 0) {
-			wpa_printf(MSG_DEBUG,
-				   "Enforced OSU SSID matches RSN[OSEN] info");
-			ssid = ssid2;
-		} else {
-			wpa_printf(MSG_INFO, "Enforced OSU SSID did not match");
-			write_summary(ctx, "Enforced OSU SSID did not match");
-			return -1;
-		}
-	}
-
-	id = add_network(ifname);
-	if (id < 0)
-		return -1;
-	if (set_network_quoted(ifname, id, "ssid", ssid) < 0)
-		return -1;
-	if (ssid2)
-		osu_nai = osu_nai2;
-	if (osu_nai && os_strlen(osu_nai) > 0) {
-		char dir[255], fname[300];
-		if (getcwd(dir, sizeof(dir)) == NULL)
-			return -1;
-		os_snprintf(fname, sizeof(fname), "%s/osu-ca.pem", dir);
-
-		if (ssid2 && set_network_quoted(ifname, id, "ssid", ssid2) < 0)
-			return -1;
-
-		if (set_network(ifname, id, "proto", "OSEN") < 0 ||
-		    set_network(ifname, id, "key_mgmt", "OSEN") < 0 ||
-		    set_network(ifname, id, "pairwise", "CCMP") < 0 ||
-		    set_network(ifname, id, "group", "GTK_NOT_USED CCMP") < 0 ||
-		    set_network(ifname, id, "eap", "WFA-UNAUTH-TLS") < 0 ||
-		    set_network(ifname, id, "ocsp", "2") < 0 ||
-		    set_network_quoted(ifname, id, "identity", osu_nai) < 0 ||
-		    set_network_quoted(ifname, id, "ca_cert", fname) < 0)
-			return -1;
-	} else if (ssid2) {
-		wpa_printf(MSG_INFO, "No OSU_NAI set for RSN[OSEN]");
-		write_summary(ctx, "No OSU_NAI set for RSN[OSEN]");
-		return -1;
-	} else {
-		if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
-			return -1;
-	}
-
-	mon = open_wpa_mon(ifname);
-	if (mon == NULL)
-		return -1;
-
-	wpa_printf(MSG_INFO, "Associate with OSU SSID");
-	write_summary(ctx, "Associate with OSU SSID");
-	snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", id);
-	if (wpa_command(ifname, buf) < 0)
-		return -1;
-
-	res = get_wpa_cli_event(mon, "CTRL-EVENT-CONNECTED",
-				buf, sizeof(buf));
-
-	wpa_ctrl_detach(mon);
-	wpa_ctrl_close(mon);
-
-	if (res < 0) {
-		wpa_printf(MSG_INFO, "Could not connect to OSU network");
-		write_summary(ctx, "Could not connect to OSU network");
-		wpa_printf(MSG_INFO, "Remove OSU network connection");
-		snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id);
-		wpa_command(ifname, buf);
-		return -1;
-	}
-
-	write_summary(ctx, "Waiting for IP address for subscription registration");
-	if (wait_ip_addr(ifname, 15) < 0) {
-		wpa_printf(MSG_INFO, "Could not get IP address for WLAN - try connection anyway");
-	}
-
-	if (no_prod_assoc) {
-		if (res < 0)
-			return -1;
-		wpa_printf(MSG_INFO, "No production connection used for testing purposes");
-		write_summary(ctx, "No production connection used for testing purposes");
-		return 0;
-	}
-
-	ctx->no_reconnect = 1;
-	if (methods & 0x02) {
-		wpa_printf(MSG_DEBUG, "Calling cmd_prov from osu_connect");
-		res = cmd_prov(ctx, url);
-	} else if (methods & 0x01) {
-		wpa_printf(MSG_DEBUG,
-			   "Calling cmd_oma_dm_prov from osu_connect");
-		res = cmd_oma_dm_prov(ctx, url);
-	}
-
-	wpa_printf(MSG_INFO, "Remove OSU network connection");
-	write_summary(ctx, "Remove OSU network connection");
-	snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id);
-	wpa_command(ifname, buf);
-
-	if (res < 0)
-		return -1;
-
-	wpa_printf(MSG_INFO, "Requesting reconnection with updated configuration");
-	write_summary(ctx, "Requesting reconnection with updated configuration");
-	if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) {
-		wpa_printf(MSG_INFO, "Failed to request wpa_supplicant to reconnect");
-		write_summary(ctx, "Failed to request wpa_supplicant to reconnect");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir,
-			  int connect, int no_prod_assoc,
-			  const char *friendly_name)
-{
-	char fname[255];
-	FILE *f;
-	struct osu_data *osu = NULL, *last = NULL;
-	size_t osu_count = 0, i, j;
-	int ret;
-
-	write_summary(ctx, "OSU provider selection");
-
-	if (dir == NULL) {
-		wpa_printf(MSG_INFO, "Missing dir parameter to osu_select");
-		return -1;
-	}
-
-	snprintf(fname, sizeof(fname), "%s/osu-providers.txt", dir);
-	osu = parse_osu_providers(fname, &osu_count);
-	if (osu == NULL) {
-		wpa_printf(MSG_INFO, "Could not find any OSU providers from %s",
-			   fname);
-		write_result(ctx, "No OSU providers available");
-		return -1;
-	}
-
-	if (friendly_name) {
-		for (i = 0; i < osu_count; i++) {
-			last = &osu[i];
-			for (j = 0; j < last->friendly_name_count; j++) {
-				if (os_strcmp(last->friendly_name[j].text,
-					      friendly_name) == 0)
-					break;
-			}
-			if (j < last->friendly_name_count)
-				break;
-		}
-		if (i == osu_count) {
-			wpa_printf(MSG_INFO, "Requested operator friendly name '%s' not found in the list of available providers",
-				   friendly_name);
-			write_summary(ctx, "Requested operator friendly name '%s' not found in the list of available providers",
-				      friendly_name);
-			free(osu);
-			return -1;
-		}
-
-		wpa_printf(MSG_INFO, "OSU Provider selected based on requested operator friendly name '%s'",
-			   friendly_name);
-		write_summary(ctx, "OSU Provider selected based on requested operator friendly name '%s'",
-			      friendly_name);
-		ret = i + 1;
-		goto selected;
-	}
-
-	snprintf(fname, sizeof(fname), "%s/osu-providers.html", dir);
-	f = fopen(fname, "w");
-	if (f == NULL) {
-		wpa_printf(MSG_INFO, "Could not open %s", fname);
-		free(osu);
-		return -1;
-	}
-
-	fprintf(f, "<html><head>"
-		"<meta http-equiv=\"Content-type\" content=\"text/html; "
-		"charset=utf-8\"<title>Select service operator</title>"
-		"</head><body><h1>Select service operator</h1>\n");
-
-	if (osu_count == 0)
-		fprintf(f, "No online signup available\n");
-
-	for (i = 0; i < osu_count; i++) {
-		last = &osu[i];
-#ifdef ANDROID
-		fprintf(f, "<p>\n"
-			"<a href=\"http://localhost:12345/osu/%d\">"
-			"<table><tr><td>", (int) i + 1);
-#else /* ANDROID */
-		fprintf(f, "<p>\n"
-			"<a href=\"osu://%d\">"
-			"<table><tr><td>", (int) i + 1);
-#endif /* ANDROID */
-		for (j = 0; j < last->icon_count; j++) {
-			fprintf(f, "<img src=\"osu-icon-%d.%s\">\n",
-				last->icon[j].id,
-				strcasecmp(last->icon[j].mime_type,
-					   "image/png") == 0 ? "png" : "icon");
-		}
-		fprintf(f, "<td>");
-		for (j = 0; j < last->friendly_name_count; j++) {
-			fprintf(f, "<small>[%s]</small> %s<br>\n",
-				last->friendly_name[j].lang,
-				last->friendly_name[j].text);
-		}
-		fprintf(f, "<tr><td colspan=2>");
-		for (j = 0; j < last->serv_desc_count; j++) {
-			fprintf(f, "<small>[%s]</small> %s<br>\n",
-				last->serv_desc[j].lang,
-				last->serv_desc[j].text);
-		}
-		fprintf(f, "</table></a><br><small>BSSID: %s<br>\n"
-			"SSID: %s<br>\n",
-			last->bssid, last->osu_ssid);
-		if (last->osu_ssid2[0])
-			fprintf(f, "SSID2: %s<br>\n", last->osu_ssid2);
-		if (last->osu_nai[0])
-			fprintf(f, "NAI: %s<br>\n", last->osu_nai);
-		if (last->osu_nai2[0])
-			fprintf(f, "NAI2: %s<br>\n", last->osu_nai2);
-		fprintf(f, "URL: %s<br>\n"
-			"methods:%s%s<br>\n"
-			"</small></p>\n",
-			last->url,
-			last->methods & 0x01 ? " OMA-DM" : "",
-			last->methods & 0x02 ? " SOAP-XML-SPP" : "");
-	}
-
-	fprintf(f, "</body></html>\n");
-
-	fclose(f);
-
-	snprintf(fname, sizeof(fname), "file://%s/osu-providers.html", dir);
-	write_summary(ctx, "Start web browser with OSU provider selection page");
-	ret = hs20_web_browser(fname, 0);
-
-selected:
-	if (ret > 0 && (size_t) ret <= osu_count) {
-		char *data;
-		size_t data_len;
-
-		wpa_printf(MSG_INFO, "Selected OSU id=%d", ret);
-		last = &osu[ret - 1];
-		ret = 0;
-		wpa_printf(MSG_INFO, "BSSID: %s", last->bssid);
-		wpa_printf(MSG_INFO, "SSID: %s", last->osu_ssid);
-		if (last->osu_ssid2[0])
-			wpa_printf(MSG_INFO, "SSID2: %s", last->osu_ssid2);
-		wpa_printf(MSG_INFO, "URL: %s", last->url);
-		write_summary(ctx, "Selected OSU provider id=%d BSSID=%s SSID=%s URL=%s",
-			      ret, last->bssid, last->osu_ssid, last->url);
-
-		ctx->friendly_name_count = last->friendly_name_count;
-		for (j = 0; j < last->friendly_name_count; j++) {
-			wpa_printf(MSG_INFO, "FRIENDLY_NAME: [%s]%s",
-				   last->friendly_name[j].lang,
-				   last->friendly_name[j].text);
-			os_strlcpy(ctx->friendly_name[j].lang,
-				   last->friendly_name[j].lang,
-				   sizeof(ctx->friendly_name[j].lang));
-			os_strlcpy(ctx->friendly_name[j].text,
-				   last->friendly_name[j].text,
-				   sizeof(ctx->friendly_name[j].text));
-		}
-
-		ctx->icon_count = last->icon_count;
-		for (j = 0; j < last->icon_count; j++) {
-			char fname[256];
-
-			os_snprintf(fname, sizeof(fname), "%s/osu-icon-%d.%s",
-				    dir, last->icon[j].id,
-				    strcasecmp(last->icon[j].mime_type,
-					       "image/png") == 0 ?
-				    "png" : "icon");
-			wpa_printf(MSG_INFO, "ICON: %s (%s)",
-				   fname, last->icon[j].filename);
-			os_strlcpy(ctx->icon_filename[j],
-				   last->icon[j].filename,
-				   sizeof(ctx->icon_filename[j]));
-
-			data = os_readfile(fname, &data_len);
-			if (data) {
-				sha256_vector(1, (const u8 **) &data, &data_len,
-					      ctx->icon_hash[j]);
-				os_free(data);
-			}
-		}
-
-		if (connect == 2) {
-			if (last->methods & 0x02) {
-				wpa_printf(MSG_DEBUG,
-					   "Calling cmd_prov from cmd_osu_select");
-				ret = cmd_prov(ctx, last->url);
-			} else if (last->methods & 0x01) {
-				wpa_printf(MSG_DEBUG,
-					   "Calling cmd_oma_dm_prov from cmd_osu_select");
-				ret = cmd_oma_dm_prov(ctx, last->url);
-			} else {
-				wpa_printf(MSG_DEBUG,
-					   "No supported OSU provisioning method");
-				ret = -1;
-			}
-		} else if (connect) {
-			ret = osu_connect(ctx, last->bssid, last->osu_ssid,
-					  last->osu_ssid2,
-					  last->url, last->methods,
-					  no_prod_assoc, last->osu_nai,
-					  last->osu_nai2);
-		}
-	} else
-		ret = -1;
-
-	free(osu);
-
-	return ret;
-}
-
-
-static int cmd_signup(struct hs20_osu_client *ctx, int no_prod_assoc,
-		      const char *friendly_name)
-{
-	char dir[255];
-	char fname[300], buf[400];
-	struct wpa_ctrl *mon;
-	const char *ifname;
-	int res;
-
-	ifname = ctx->ifname;
-
-	if (getcwd(dir, sizeof(dir)) == NULL)
-		return -1;
-
-	snprintf(fname, sizeof(fname), "%s/osu-info", dir);
-	if (mkdir(fname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 &&
-	    errno != EEXIST) {
-		wpa_printf(MSG_INFO, "mkdir(%s) failed: %s",
-			   fname, strerror(errno));
-		return -1;
-	}
-
-	android_update_permission(fname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
-
-	snprintf(buf, sizeof(buf), "SET osu_dir %s", fname);
-	if (wpa_command(ifname, buf) < 0) {
-		wpa_printf(MSG_INFO, "Failed to configure osu_dir to wpa_supplicant");
-		return -1;
-	}
-
-	mon = open_wpa_mon(ifname);
-	if (mon == NULL)
-		return -1;
-
-	wpa_printf(MSG_INFO, "Starting OSU fetch");
-	write_summary(ctx, "Starting OSU provider information fetch");
-	if (wpa_command(ifname, "FETCH_OSU") < 0) {
-		wpa_printf(MSG_INFO, "Could not start OSU fetch");
-		wpa_ctrl_detach(mon);
-		wpa_ctrl_close(mon);
-		return -1;
-	}
-	res = get_wpa_cli_event(mon, "OSU provider fetch completed",
-				buf, sizeof(buf));
-
-	wpa_ctrl_detach(mon);
-	wpa_ctrl_close(mon);
-
-	if (res < 0) {
-		wpa_printf(MSG_INFO, "OSU fetch did not complete");
-		write_summary(ctx, "OSU fetch did not complete");
-		return -1;
-	}
-	wpa_printf(MSG_INFO, "OSU provider fetch completed");
-
-	return cmd_osu_select(ctx, fname, 1, no_prod_assoc, friendly_name);
-}
-
-
-static int cmd_sub_rem(struct hs20_osu_client *ctx, const char *address,
-		       const char *pps_fname, const char *ca_fname)
-{
-	xml_node_t *pps, *node;
-	char pps_fname_buf[300];
-	char ca_fname_buf[200];
-	char *cred_username = NULL;
-	char *cred_password = NULL;
-	char *sub_rem_uri = NULL;
-	char client_cert_buf[200];
-	char *client_cert = NULL;
-	char client_key_buf[200];
-	char *client_key = NULL;
-	int spp;
-
-	wpa_printf(MSG_INFO, "Subscription remediation requested with Server URL: %s",
-		   address);
-
-	if (!pps_fname) {
-		char buf[256];
-		wpa_printf(MSG_INFO, "Determining PPS file based on Home SP information");
-		if (os_strncmp(address, "fqdn=", 5) == 0) {
-			wpa_printf(MSG_INFO, "Use requested FQDN from command line");
-			os_snprintf(buf, sizeof(buf), "%s", address + 5);
-			address = NULL;
-		} else if (get_wpa_status(ctx->ifname, "provisioning_sp", buf,
-					  sizeof(buf)) < 0) {
-			wpa_printf(MSG_INFO, "Could not get provisioning Home SP FQDN from wpa_supplicant");
-			return -1;
-		}
-		os_free(ctx->fqdn);
-		ctx->fqdn = os_strdup(buf);
-		if (ctx->fqdn == NULL)
-			return -1;
-		wpa_printf(MSG_INFO, "Home SP FQDN for current credential: %s",
-			   buf);
-		os_snprintf(pps_fname_buf, sizeof(pps_fname_buf),
-			    "SP/%s/pps.xml", ctx->fqdn);
-		pps_fname = pps_fname_buf;
-
-		os_snprintf(ca_fname_buf, sizeof(ca_fname_buf), "SP/%s/ca.pem",
-			    ctx->fqdn);
-		ca_fname = ca_fname_buf;
-	}
-
-	if (!os_file_exists(pps_fname)) {
-		wpa_printf(MSG_INFO, "PPS file '%s' does not exist or is not accessible",
-			   pps_fname);
-		return -1;
-	}
-	wpa_printf(MSG_INFO, "Using PPS file: %s", pps_fname);
-
-	if (ca_fname && !os_file_exists(ca_fname)) {
-		wpa_printf(MSG_INFO, "CA file '%s' does not exist or is not accessible",
-			   ca_fname);
-		return -1;
-	}
-	wpa_printf(MSG_INFO, "Using server trust root: %s", ca_fname);
-	ctx->ca_fname = ca_fname;
-
-	pps = node_from_file(ctx->xml, pps_fname);
-	if (pps == NULL) {
-		wpa_printf(MSG_INFO, "Could not read PPS MO");
-		return -1;
-	}
-
-	if (!ctx->fqdn) {
-		char *tmp;
-		node = get_child_node(ctx->xml, pps, "HomeSP/FQDN");
-		if (node == NULL) {
-			wpa_printf(MSG_INFO, "No HomeSP/FQDN found from PPS");
-			return -1;
-		}
-		tmp = xml_node_get_text(ctx->xml, node);
-		if (tmp == NULL) {
-			wpa_printf(MSG_INFO, "No HomeSP/FQDN text found from PPS");
-			return -1;
-		}
-		ctx->fqdn = os_strdup(tmp);
-		xml_node_get_text_free(ctx->xml, tmp);
-		if (!ctx->fqdn) {
-			wpa_printf(MSG_INFO, "No FQDN known");
-			return -1;
-		}
-	}
-
-	node = get_child_node(ctx->xml, pps,
-			      "SubscriptionUpdate/UpdateMethod");
-	if (node) {
-		char *tmp;
-		tmp = xml_node_get_text(ctx->xml, node);
-		if (tmp && os_strcasecmp(tmp, "OMA-DM-ClientInitiated") == 0)
-			spp = 0;
-		else
-			spp = 1;
-	} else {
-		wpa_printf(MSG_INFO, "No UpdateMethod specified - assume SPP");
-		spp = 1;
-	}
-
-	get_user_pw(ctx, pps, "SubscriptionUpdate/UsernamePassword",
-		    &cred_username, &cred_password);
-	if (cred_username)
-		wpa_printf(MSG_INFO, "Using username: %s", cred_username);
-	if (cred_password)
-		wpa_printf(MSG_DEBUG, "Using password: %s", cred_password);
-
-	if (cred_username == NULL && cred_password == NULL &&
-	    get_child_node(ctx->xml, pps, "Credential/DigitalCertificate")) {
-		wpa_printf(MSG_INFO, "Using client certificate");
-		os_snprintf(client_cert_buf, sizeof(client_cert_buf),
-			    "SP/%s/client-cert.pem", ctx->fqdn);
-		client_cert = client_cert_buf;
-		os_snprintf(client_key_buf, sizeof(client_key_buf),
-			    "SP/%s/client-key.pem", ctx->fqdn);
-		client_key = client_key_buf;
-		ctx->client_cert_present = 1;
-	}
-
-	node = get_child_node(ctx->xml, pps, "SubscriptionUpdate/URI");
-	if (node) {
-		sub_rem_uri = xml_node_get_text(ctx->xml, node);
-		if (sub_rem_uri &&
-		    (!address || os_strcmp(address, sub_rem_uri) != 0)) {
-			wpa_printf(MSG_INFO, "Override sub rem URI based on PPS: %s",
-				   sub_rem_uri);
-			address = sub_rem_uri;
-		}
-	}
-	if (!address) {
-		wpa_printf(MSG_INFO, "Server URL not known");
-		return -1;
-	}
-
-	write_summary(ctx, "Wait for IP address for subscriptiom remediation");
-	wpa_printf(MSG_INFO, "Wait for IP address before starting subscription remediation");
-
-	if (wait_ip_addr(ctx->ifname, 15) < 0) {
-		wpa_printf(MSG_INFO, "Could not get IP address for WLAN - try connection anyway");
-	}
-
-	if (spp)
-		spp_sub_rem(ctx, address, pps_fname,
-			    client_cert, client_key,
-			    cred_username, cred_password, pps);
-	else
-		oma_dm_sub_rem(ctx, address, pps_fname,
-			       client_cert, client_key,
-			       cred_username, cred_password, pps);
-
-	xml_node_get_text_free(ctx->xml, sub_rem_uri);
-	xml_node_get_text_free(ctx->xml, cred_username);
-	str_clear_free(cred_password);
-	xml_node_free(ctx->xml, pps);
-	return 0;
-}
-
-
-static int cmd_pol_upd(struct hs20_osu_client *ctx, const char *address,
-		       const char *pps_fname, const char *ca_fname)
-{
-	xml_node_t *pps;
-	xml_node_t *node;
-	char pps_fname_buf[300];
-	char ca_fname_buf[200];
-	char *uri = NULL;
-	char *cred_username = NULL;
-	char *cred_password = NULL;
-	char client_cert_buf[200];
-	char *client_cert = NULL;
-	char client_key_buf[200];
-	char *client_key = NULL;
-	int spp;
-
-	wpa_printf(MSG_INFO, "Policy update requested");
-
-	if (!pps_fname) {
-		char buf[256];
-		int res;
-
-		wpa_printf(MSG_INFO, "Determining PPS file based on Home SP information");
-		if (address && os_strncmp(address, "fqdn=", 5) == 0) {
-			wpa_printf(MSG_INFO, "Use requested FQDN from command line");
-			os_snprintf(buf, sizeof(buf), "%s", address + 5);
-			address = NULL;
-		} else if (get_wpa_status(ctx->ifname, "provisioning_sp", buf,
-					  sizeof(buf)) < 0) {
-			wpa_printf(MSG_INFO, "Could not get provisioning Home SP FQDN from wpa_supplicant");
-			return -1;
-		}
-		os_free(ctx->fqdn);
-		ctx->fqdn = os_strdup(buf);
-		if (ctx->fqdn == NULL)
-			return -1;
-		wpa_printf(MSG_INFO, "Home SP FQDN for current credential: %s",
-			   buf);
-		os_snprintf(pps_fname_buf, sizeof(pps_fname_buf),
-			    "SP/%s/pps.xml", ctx->fqdn);
-		pps_fname = pps_fname_buf;
-
-		res = os_snprintf(ca_fname_buf, sizeof(ca_fname_buf),
-				  "SP/%s/ca.pem", buf);
-		if (os_snprintf_error(sizeof(ca_fname_buf), res)) {
-			os_free(ctx->fqdn);
-			ctx->fqdn = NULL;
-			return -1;
-		}
-		ca_fname = ca_fname_buf;
-	}
-
-	if (!os_file_exists(pps_fname)) {
-		wpa_printf(MSG_INFO, "PPS file '%s' does not exist or is not accessible",
-			   pps_fname);
-		return -1;
-	}
-	wpa_printf(MSG_INFO, "Using PPS file: %s", pps_fname);
-
-	if (ca_fname && !os_file_exists(ca_fname)) {
-		wpa_printf(MSG_INFO, "CA file '%s' does not exist or is not accessible",
-			   ca_fname);
-		return -1;
-	}
-	wpa_printf(MSG_INFO, "Using server trust root: %s", ca_fname);
-	ctx->ca_fname = ca_fname;
-
-	pps = node_from_file(ctx->xml, pps_fname);
-	if (pps == NULL) {
-		wpa_printf(MSG_INFO, "Could not read PPS MO");
-		return -1;
-	}
-
-	if (!ctx->fqdn) {
-		char *tmp;
-		node = get_child_node(ctx->xml, pps, "HomeSP/FQDN");
-		if (node == NULL) {
-			wpa_printf(MSG_INFO, "No HomeSP/FQDN found from PPS");
-			return -1;
-		}
-		tmp = xml_node_get_text(ctx->xml, node);
-		if (tmp == NULL) {
-			wpa_printf(MSG_INFO, "No HomeSP/FQDN text found from PPS");
-			return -1;
-		}
-		ctx->fqdn = os_strdup(tmp);
-		xml_node_get_text_free(ctx->xml, tmp);
-		if (!ctx->fqdn) {
-			wpa_printf(MSG_INFO, "No FQDN known");
-			return -1;
-		}
-	}
-
-	node = get_child_node(ctx->xml, pps,
-			      "Policy/PolicyUpdate/UpdateMethod");
-	if (node) {
-		char *tmp;
-		tmp = xml_node_get_text(ctx->xml, node);
-		if (tmp && os_strcasecmp(tmp, "OMA-DM-ClientInitiated") == 0)
-			spp = 0;
-		else
-			spp = 1;
-	} else {
-		wpa_printf(MSG_INFO, "No UpdateMethod specified - assume SPP");
-		spp = 1;
-	}
-
-	get_user_pw(ctx, pps, "Policy/PolicyUpdate/UsernamePassword",
-		    &cred_username, &cred_password);
-	if (cred_username)
-		wpa_printf(MSG_INFO, "Using username: %s", cred_username);
-	if (cred_password)
-		wpa_printf(MSG_DEBUG, "Using password: %s", cred_password);
-
-	if (cred_username == NULL && cred_password == NULL &&
-	    get_child_node(ctx->xml, pps, "Credential/DigitalCertificate")) {
-		wpa_printf(MSG_INFO, "Using client certificate");
-		os_snprintf(client_cert_buf, sizeof(client_cert_buf),
-			    "SP/%s/client-cert.pem", ctx->fqdn);
-		client_cert = client_cert_buf;
-		os_snprintf(client_key_buf, sizeof(client_key_buf),
-			    "SP/%s/client-key.pem", ctx->fqdn);
-		client_key = client_key_buf;
-	}
-
-	if (!address) {
-		node = get_child_node(ctx->xml, pps, "Policy/PolicyUpdate/URI");
-		if (node) {
-			uri = xml_node_get_text(ctx->xml, node);
-			wpa_printf(MSG_INFO, "URI based on PPS: %s", uri);
-			address = uri;
-		}
-	}
-	if (!address) {
-		wpa_printf(MSG_INFO, "Server URL not known");
-		return -1;
-	}
-
-	if (spp)
-		spp_pol_upd(ctx, address, pps_fname,
-			    client_cert, client_key,
-			    cred_username, cred_password, pps);
-	else
-		oma_dm_pol_upd(ctx, address, pps_fname,
-			       client_cert, client_key,
-			       cred_username, cred_password, pps);
-
-	xml_node_get_text_free(ctx->xml, uri);
-	xml_node_get_text_free(ctx->xml, cred_username);
-	str_clear_free(cred_password);
-	xml_node_free(ctx->xml, pps);
-
-	return 0;
-}
-
-
-static char * get_hostname(const char *url)
-{
-	const char *pos, *end, *end2;
-	char *ret;
-
-	if (url == NULL)
-		return NULL;
-
-	pos = os_strchr(url, '/');
-	if (pos == NULL)
-		return NULL;
-	pos++;
-	if (*pos != '/')
-		return NULL;
-	pos++;
-
-	end = os_strchr(pos, '/');
-	end2 = os_strchr(pos, ':');
-	if ((end && end2 && end2 < end) || (!end && end2))
-		end = end2;
-	if (end)
-		end--;
-	else {
-		end = pos;
-		while (*end)
-			end++;
-		if (end > pos)
-			end--;
-	}
-
-	ret = os_malloc(end - pos + 2);
-	if (ret == NULL)
-		return NULL;
-
-	os_memcpy(ret, pos, end - pos + 1);
-	ret[end - pos + 1] = '\0';
-
-	return ret;
-}
-
-
-static int osu_cert_cb(void *_ctx, struct http_cert *cert)
-{
-	struct hs20_osu_client *ctx = _ctx;
-	size_t i, j;
-	int found;
-	char *host = NULL;
-
-	wpa_printf(MSG_INFO, "osu_cert_cb(osu_cert_validation=%d, url=%s server_url=%s)",
-		   !ctx->no_osu_cert_validation, cert->url ? cert->url : "N/A",
-		   ctx->server_url);
-
-	if (ctx->no_osu_cert_validation && cert->url)
-		host = get_hostname(cert->url);
-	else
-		host = get_hostname(ctx->server_url);
-
-	if (!ctx->no_osu_cert_validation) {
-		for (i = 0; i < ctx->server_dnsname_count; i++)
-			os_free(ctx->server_dnsname[i]);
-		os_free(ctx->server_dnsname);
-		ctx->server_dnsname = os_calloc(cert->num_dnsname,
-						sizeof(char *));
-		ctx->server_dnsname_count = 0;
-	}
-
-	found = 0;
-	for (i = 0; i < cert->num_dnsname; i++) {
-		if (!ctx->no_osu_cert_validation && ctx->server_dnsname) {
-			ctx->server_dnsname[ctx->server_dnsname_count] =
-				os_strdup(cert->dnsname[i]);
-			if (ctx->server_dnsname[ctx->server_dnsname_count])
-				ctx->server_dnsname_count++;
-		}
-		if (host && os_strcasecmp(host, cert->dnsname[i]) == 0)
-			found = 1;
-		wpa_printf(MSG_INFO, "dNSName '%s'", cert->dnsname[i]);
-	}
-
-	if (host && !found) {
-		wpa_printf(MSG_INFO, "Server name from URL (%s) did not match any dNSName - abort connection",
-			   host);
-		write_result(ctx, "Server name from URL (%s) did not match any dNSName - abort connection",
-			     host);
-		os_free(host);
-		return -1;
-	}
-
-	os_free(host);
-
-	for (i = 0; i < cert->num_othername; i++) {
-		if (os_strcmp(cert->othername[i].oid,
-			      "1.3.6.1.4.1.40808.1.1.1") == 0) {
-			wpa_hexdump_ascii(MSG_INFO,
-					  "id-wfa-hotspot-friendlyName",
-					  cert->othername[i].data,
-					  cert->othername[i].len);
-		}
-	}
-
-	for (j = 0; !ctx->no_osu_cert_validation &&
-		     j < ctx->friendly_name_count; j++) {
-		int found = 0;
-		for (i = 0; i < cert->num_othername; i++) {
-			if (os_strcmp(cert->othername[i].oid,
-				      "1.3.6.1.4.1.40808.1.1.1") != 0)
-				continue;
-			if (cert->othername[i].len < 3)
-				continue;
-			if (os_strncasecmp((char *) cert->othername[i].data,
-					   ctx->friendly_name[j].lang, 3) != 0)
-				continue;
-			if (os_strncmp((char *) cert->othername[i].data + 3,
-				       ctx->friendly_name[j].text,
-				       cert->othername[i].len - 3) == 0) {
-				found = 1;
-				break;
-			}
-		}
-
-		if (!found) {
-			wpa_printf(MSG_INFO, "No friendly name match found for '[%s]%s'",
-				   ctx->friendly_name[j].lang,
-				   ctx->friendly_name[j].text);
-			write_result(ctx, "No friendly name match found for '[%s]%s'",
-				     ctx->friendly_name[j].lang,
-				     ctx->friendly_name[j].text);
-			return -1;
-		}
-	}
-
-	for (i = 0; i < cert->num_logo; i++) {
-		struct http_logo *logo = &cert->logo[i];
-
-		wpa_printf(MSG_INFO, "logo hash alg %s uri '%s'",
-			   logo->alg_oid, logo->uri);
-		wpa_hexdump_ascii(MSG_INFO, "hashValue",
-				  logo->hash, logo->hash_len);
-	}
-
-	for (j = 0; !ctx->no_osu_cert_validation && j < ctx->icon_count; j++) {
-		int found = 0;
-		char *name = ctx->icon_filename[j];
-		size_t name_len = os_strlen(name);
-
-		wpa_printf(MSG_INFO,
-			   "[%zu] Looking for icon file name '%s' match",
-			   j, name);
-		for (i = 0; i < cert->num_logo; i++) {
-			struct http_logo *logo = &cert->logo[i];
-			size_t uri_len = os_strlen(logo->uri);
-			char *pos;
-
-			wpa_printf(MSG_INFO,
-				   "[%zu] Comparing to '%s' uri_len=%d name_len=%d",
-				   i, logo->uri, (int) uri_len, (int) name_len);
-			if (uri_len < 1 + name_len) {
-				wpa_printf(MSG_INFO, "URI Length is too short");
-				continue;
-			}
-			pos = &logo->uri[uri_len - name_len - 1];
-			if (*pos != '/')
-				continue;
-			pos++;
-			if (os_strcmp(pos, name) == 0) {
-				found = 1;
-				break;
-			}
-		}
-
-		if (!found) {
-			wpa_printf(MSG_INFO, "No icon filename match found for '%s'",
-				   name);
-			write_result(ctx,
-				     "No icon filename match found for '%s'",
-				     name);
-			return -1;
-		}
-	}
-
-	for (j = 0; !ctx->no_osu_cert_validation && j < ctx->icon_count; j++) {
-		int found = 0;
-
-		for (i = 0; i < cert->num_logo; i++) {
-			struct http_logo *logo = &cert->logo[i];
-
-			if (logo->hash_len != 32) {
-				wpa_printf(MSG_INFO,
-					   "[%zu][%zu] Icon hash length invalid (should be 32): %d",
-					   j, i, (int) logo->hash_len);
-				continue;
-			}
-			if (os_memcmp(logo->hash, ctx->icon_hash[j], 32) == 0) {
-				found = 1;
-				break;
-			}
-
-			wpa_printf(MSG_DEBUG,
-				   "[%zu][%zu] Icon hash did not match", j, i);
-			wpa_hexdump_ascii(MSG_DEBUG, "logo->hash",
-					  logo->hash, 32);
-			wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]",
-					  ctx->icon_hash[j], 32);
-		}
-
-		if (!found) {
-			wpa_printf(MSG_INFO,
-				   "No icon hash match (by hash) found");
-			write_result(ctx,
-				     "No icon hash match (by hash) found");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-
 static int init_ctx(struct hs20_osu_client *ctx)
 {
-	xml_node_t *devinfo, *devid;
-
 	os_memset(ctx, 0, sizeof(*ctx));
 	ctx->ifname = "wlan0";
 	ctx->xml = xml_node_init_ctx(ctx, NULL);
 	if (ctx->xml == NULL)
 		return -1;
 
-	devinfo = node_from_file(ctx->xml, "devinfo.xml");
-	if (devinfo) {
-		devid = get_node(ctx->xml, devinfo, "DevId");
-		if (devid) {
-			char *tmp = xml_node_get_text(ctx->xml, devid);
-
-			if (tmp) {
-				ctx->devid = os_strdup(tmp);
-				xml_node_get_text_free(ctx->xml, tmp);
-			}
-		}
-		xml_node_free(ctx->xml, devinfo);
-	}
-
 	ctx->http = http_init_ctx(ctx, ctx->xml);
 	if (ctx->http == NULL) {
 		xml_node_deinit_ctx(ctx->xml);
 		return -1;
 	}
 	http_ocsp_set(ctx->http, 2);
-	http_set_cert_cb(ctx->http, osu_cert_cb, ctx);
 
 	return 0;
 }
@@ -3156,17 +1431,8 @@
 
 static void deinit_ctx(struct hs20_osu_client *ctx)
 {
-	size_t i;
-
 	http_deinit_ctx(ctx->http);
 	xml_node_deinit_ctx(ctx->xml);
-	os_free(ctx->fqdn);
-	os_free(ctx->server_url);
-	os_free(ctx->devid);
-
-	for (i = 0; i < ctx->server_dnsname_count; i++)
-		os_free(ctx->server_dnsname[i]);
-	os_free(ctx->server_dnsname);
 }
 
 
@@ -3209,19 +1475,8 @@
 	       "- from_tnds <XML MO in TNDS format> <XML MO>\n"
 	       "- set_pps <PerProviderSubscription XML file name>\n"
 	       "- get_fqdn <PerProviderSubscription XML file name>\n"
-	       "- pol_upd [Server URL] [PPS] [CA cert]\n"
-	       "- sub_rem <Server URL> [PPS] [CA cert]\n"
-	       "- prov <Server URL> [CA cert]\n"
-	       "- oma_dm_prov <Server URL> [CA cert]\n"
-	       "- sim_prov <Server URL> [CA cert]\n"
-	       "- oma_dm_sim_prov <Server URL> [CA cert]\n"
-	       "- signup [CA cert]\n"
-	       "- dl_osu_ca <PPS> <CA file>\n"
-	       "- dl_polupd_ca <PPS> <CA file>\n"
 	       "- dl_aaa_ca <PPS> <CA file>\n"
-	       "- browser <URL>\n"
-	       "- parse_cert <X.509 certificate (DER)>\n"
-	       "- osu_select <OSU info directory> [CA cert]\n");
+	       "- browser <URL>\n");
 }
 
 
@@ -3230,8 +1485,6 @@
 	struct hs20_osu_client ctx;
 	int c;
 	int ret = 0;
-	int no_prod_assoc = 0;
-	const char *friendly_name = NULL;
 	const char *wpa_debug_file_path = NULL;
 	extern char *wpas_ctrl_path;
 	extern int wpa_debug_level;
@@ -3242,7 +1495,7 @@
 		return -1;
 
 	for (;;) {
-		c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tTw:x:");
+		c = getopt(argc, argv, "df:hKqr:s:S:tTw:");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -3256,15 +1509,6 @@
 		case 'K':
 			wpa_debug_show_keys++;
 			break;
-		case 'N':
-			no_prod_assoc = 1;
-			break;
-		case 'o':
-			ctx.osu_ssid = optarg;
-			break;
-		case 'O':
-			friendly_name = optarg;
-			break;
 		case 'q':
 			wpa_debug_level++;
 			break;
@@ -3286,9 +1530,6 @@
 		case 'w':
 			wpas_ctrl_path = optarg;
 			break;
-		case 'x':
-			spp_xsd_fname = optarg;
-			break;
 		case 'h':
 		default:
 			usage();
@@ -3335,62 +1576,12 @@
 			exit(0);
 		}
 		cmd_from_tnds(&ctx, argv[optind + 1], argv[optind + 2]);
-	} else if (strcmp(argv[optind], "sub_rem") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		ret = cmd_sub_rem(&ctx, argv[optind + 1],
-				  argc > optind + 2 ? argv[optind + 2] : NULL,
-				  argc > optind + 3 ? argv[optind + 3] : NULL);
-	} else if (strcmp(argv[optind], "pol_upd") == 0) {
-		ret = cmd_pol_upd(&ctx,
-				  argc > optind + 1 ? argv[optind + 1] : NULL,
-				  argc > optind + 2 ? argv[optind + 2] : NULL,
-				  argc > optind + 3 ? argv[optind + 3] : NULL);
-	} else if (strcmp(argv[optind], "prov") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		ctx.ca_fname = argv[optind + 2];
-		wpa_printf(MSG_DEBUG, "Calling cmd_prov from main");
-		cmd_prov(&ctx, argv[optind + 1]);
-	} else if (strcmp(argv[optind], "sim_prov") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		ctx.ca_fname = argv[optind + 2];
-		cmd_sim_prov(&ctx, argv[optind + 1]);
-	} else if (strcmp(argv[optind], "dl_osu_ca") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		cmd_dl_osu_ca(&ctx, argv[optind + 1], argv[optind + 2]);
-	} else if (strcmp(argv[optind], "dl_polupd_ca") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		cmd_dl_polupd_ca(&ctx, argv[optind + 1], argv[optind + 2]);
 	} else if (strcmp(argv[optind], "dl_aaa_ca") == 0) {
 		if (argc - optind < 2) {
 			usage();
 			exit(0);
 		}
 		cmd_dl_aaa_ca(&ctx, argv[optind + 1], argv[optind + 2]);
-	} else if (strcmp(argv[optind], "osu_select") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		ctx.ca_fname = argc > optind + 2 ? argv[optind + 2] : NULL;
-		cmd_osu_select(&ctx, argv[optind + 1], 2, 1, NULL);
-	} else if (strcmp(argv[optind], "signup") == 0) {
-		ctx.ca_fname = argc > optind + 1 ? argv[optind + 1] : NULL;
-		ret = cmd_signup(&ctx, no_prod_assoc, friendly_name);
 	} else if (strcmp(argv[optind], "set_pps") == 0) {
 		if (argc - optind < 2) {
 			usage();
@@ -3403,42 +1594,6 @@
 			exit(0);
 		}
 		ret = cmd_get_fqdn(&ctx, argv[optind + 1]);
-	} else if (strcmp(argv[optind], "oma_dm_prov") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		ctx.ca_fname = argv[optind + 2];
-		cmd_oma_dm_prov(&ctx, argv[optind + 1]);
-	} else if (strcmp(argv[optind], "oma_dm_sim_prov") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		ctx.ca_fname = argv[optind + 2];
-		if (cmd_oma_dm_sim_prov(&ctx, argv[optind + 1]) < 0) {
-			write_summary(&ctx, "Failed to complete OMA DM SIM provisioning");
-			return -1;
-		}
-	} else if (strcmp(argv[optind], "oma_dm_add") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		cmd_oma_dm_add(&ctx, argv[optind + 1], argv[optind + 2]);
-	} else if (strcmp(argv[optind], "oma_dm_replace") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		cmd_oma_dm_replace(&ctx, argv[optind + 1], argv[optind + 2]);
-	} else if (strcmp(argv[optind], "est_csr") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-		mkdir("Cert", S_IRWXU);
-		est_build_csr(&ctx, argv[optind + 1]);
 	} else if (strcmp(argv[optind], "browser") == 0) {
 		int ret;
 
@@ -3451,15 +1606,6 @@
 			   argv[optind + 1]);
 		ret = hs20_web_browser(argv[optind + 1], ctx.ignore_tls);
 		wpa_printf(MSG_INFO, "Web browser result: %d", ret);
-	} else if (strcmp(argv[optind], "parse_cert") == 0) {
-		if (argc - optind < 2) {
-			usage();
-			exit(0);
-		}
-
-		wpa_debug_level = MSG_MSGDUMP;
-		http_parse_x509_certificate(ctx.http, argv[optind + 1]);
-		wpa_debug_level = MSG_INFO;
 	} else {
 		wpa_printf(MSG_INFO, "Unknown command '%s'", argv[optind]);
 	}