/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wifi; import android.annotation.NonNull; import android.content.Context; import android.hardware.wifi.supplicant.AuthAlgMask; import android.hardware.wifi.supplicant.DppConnectionKeys; import android.hardware.wifi.supplicant.EapMethod; import android.hardware.wifi.supplicant.EapPhase2Method; import android.hardware.wifi.supplicant.GroupCipherMask; import android.hardware.wifi.supplicant.GroupMgmtCipherMask; import android.hardware.wifi.supplicant.ISupplicantStaNetwork; import android.hardware.wifi.supplicant.ISupplicantStaNetworkCallback; import android.hardware.wifi.supplicant.KeyMgmtMask; import android.hardware.wifi.supplicant.NetworkResponseEapSimGsmAuthParams; import android.hardware.wifi.supplicant.NetworkResponseEapSimUmtsAuthParams; import android.hardware.wifi.supplicant.OcspType; import android.hardware.wifi.supplicant.PairwiseCipherMask; import android.hardware.wifi.supplicant.ProtoMask; import android.hardware.wifi.supplicant.SaeH2eMode; import android.hardware.wifi.supplicant.TlsVersion; import android.net.wifi.OuiKeyedData; import android.net.wifi.SecurityParams; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.util.ArrayUtils; import com.android.server.wifi.util.HalAidlUtil; import com.android.server.wifi.util.NativeUtil; import com.android.wifi.resources.R; import org.json.JSONException; import org.json.JSONObject; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.ArrayList; import java.util.BitSet; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.concurrent.ThreadSafe; /** * Wrapper class for ISupplicantStaNetwork HAL calls. Gets and sets supplicant sta network variables * and interacts with networks. * Public fields should be treated as invalid until their 'get' method is called, which will set the * value if it returns true * To maintain thread-safety, the locking protocol is that every non-static method (regardless of * access level) acquires mLock. */ @ThreadSafe public class SupplicantStaNetworkHalAidlImpl { private static final String TAG = "SupplicantStaNetworkHalAidlImpl"; @VisibleForTesting public static final String ID_STRING_KEY_FQDN = "fqdn"; @VisibleForTesting public static final String ID_STRING_KEY_CREATOR_UID = "creatorUid"; @VisibleForTesting public static final String ID_STRING_KEY_CONFIG_KEY = "configKey"; /** * Regex pattern for extracting the GSM sim authentication response params from a string. * Matches a strings like the following: "[:<kc_value>:<sres_value>]"; */ private static final Pattern GSM_AUTH_RESPONSE_PARAMS_PATTERN = Pattern.compile(":([0-9a-fA-F]+):([0-9a-fA-F]+)"); /** * Regex pattern for extracting the UMTS sim authentication response params from a string. * Matches a strings like the following: ":<ik_value>:<ck_value>:<res_value>"; */ private static final Pattern UMTS_AUTH_RESPONSE_PARAMS_PATTERN = Pattern.compile("^:([0-9a-fA-F]+):([0-9a-fA-F]+):([0-9a-fA-F]+)$"); /** * Regex pattern for extracting the UMTS sim auts response params from a string. * Matches a strings like the following: ":<auts_value>"; */ private static final Pattern UMTS_AUTS_RESPONSE_PARAMS_PATTERN = Pattern.compile("^:([0-9a-fA-F]+)$"); private final Object mLock = new Object(); private final Context mContext; private final String mIfaceName; private final WifiMonitor mWifiMonitor; private final WifiGlobals mWifiGlobals; private ISupplicantStaNetwork mISupplicantStaNetwork; private ISupplicantStaNetworkCallback mISupplicantStaNetworkCallback; private int mServiceVersion; private boolean mVerboseLoggingEnabled = false; // Network variables read from wpa_supplicant. private int mNetworkId; private byte[] mSsid; private byte[/* 6 */] mBssid; private boolean mScanSsid; private int mKeyMgmtMask; private int mProtoMask; private int mAuthAlgMask; private int mGroupCipherMask; private int mPairwiseCipherMask; private int mGroupMgmtCipherMask; private String mPskPassphrase; private String mSaePassword; private String mSaePasswordId; private byte[] mPsk; private byte[] mWepKey; private int mWepTxKeyIdx; private boolean mRequirePmf; private String mIdStr; private int mEapMethod; private int mEapPhase2Method; private byte[] mEapIdentity; private byte[] mEapAnonymousIdentity; private byte[] mEapPassword; private String mEapCACert; private String mEapCAPath; private String mEapClientCert; private String mEapPrivateKeyId; private String mEapSubjectMatch; private String mEapAltSubjectMatch; private boolean mEapEngine; private String mEapEngineID; private String mEapDomainSuffixMatch; private @WifiEnterpriseConfig.Ocsp int mOcsp; private String mWapiCertSuite; private long mAdvanceKeyMgmtFeatures; private long mWpaDriverFeatures; SupplicantStaNetworkHalAidlImpl(int serviceVersion, ISupplicantStaNetwork staNetwork, String ifaceName, Context context, WifiMonitor monitor, WifiGlobals wifiGlobals, long advanceKeyMgmtFeature, long wpaDriverFeatures) { mServiceVersion = serviceVersion; mISupplicantStaNetwork = staNetwork; mContext = context; mIfaceName = ifaceName; mWifiMonitor = monitor; mWifiGlobals = wifiGlobals; mAdvanceKeyMgmtFeatures = advanceKeyMgmtFeature; mWpaDriverFeatures = wpaDriverFeatures; } /** * Check that the service is running at least the expected version. * Use to avoid the case where the framework is using a newer * interface version than the service. */ private boolean isServiceVersionIsAtLeast(int expectedVersion) { return expectedVersion <= mServiceVersion; } /** * Enable/Disable verbose logging. * */ void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) { synchronized (mLock) { mVerboseLoggingEnabled = verboseEnabled; } } /** * Read network variables from wpa_supplicant into the provided WifiConfiguration object. * * @param config WifiConfiguration object to be populated. * @param networkExtras Map of network extras parsed from wpa_supplicant. * @return true if succeeds, false otherwise. * @throws IllegalArgumentException on malformed configuration params. */ @VisibleForTesting public boolean loadWifiConfiguration(WifiConfiguration config, Map<String, String> networkExtras) throws IllegalArgumentException { synchronized (mLock) { if (config == null) { return false; } /** SSID */ config.SSID = null; if (getSsid() && !ArrayUtils.isEmpty(mSsid)) { config.SSID = WifiSsid.fromBytes(mSsid).toString(); } else { Log.e(TAG, "failed to read ssid"); return false; } /** Network Id */ config.networkId = -1; if (getId()) { config.networkId = mNetworkId; } else { Log.e(TAG, "getId failed"); return false; } /** BSSID */ config.getNetworkSelectionStatus().setNetworkSelectionBSSID(null); if (getBssid() && !ArrayUtils.isEmpty(mBssid)) { config.getNetworkSelectionStatus().setNetworkSelectionBSSID( NativeUtil.macAddressFromByteArray(mBssid)); } /** Scan SSID (Is Hidden Network?) */ config.hiddenSSID = false; if (getScanSsid()) { config.hiddenSSID = mScanSsid; } /** Require PMF*/ config.requirePmf = false; if (getRequirePmf()) { config.requirePmf = mRequirePmf; } /** WEP keys **/ config.wepTxKeyIndex = -1; if (getWepTxKeyIdx()) { config.wepTxKeyIndex = mWepTxKeyIdx; } for (int i = 0; i < 4; i++) { config.wepKeys[i] = null; if (getWepKey(i) && !ArrayUtils.isEmpty(mWepKey)) { config.wepKeys[i] = NativeUtil.bytesToHexOrQuotedString( NativeUtil.byteArrayToArrayList(mWepKey)); } } /** allowedKeyManagement */ if (getKeyMgmt()) { BitSet keyMgmtMask = HalAidlUtil.supplicantToWifiConfigurationKeyMgmtMask( mKeyMgmtMask); keyMgmtMask = removeFastTransitionFlags(keyMgmtMask); keyMgmtMask = removeSha256KeyMgmtFlags(keyMgmtMask); keyMgmtMask = removePskSaeUpgradableTypeFlags(keyMgmtMask); config.setSecurityParams(keyMgmtMask); config.enableFils( keyMgmtMask.get(WifiConfiguration.KeyMgmt.FILS_SHA256), keyMgmtMask.get(WifiConfiguration.KeyMgmt.FILS_SHA384)); } // supplicant only have one valid security type, it won't be a disbled params. SecurityParams securityParams = config.getDefaultSecurityParams(); /** PSK passphrase */ config.preSharedKey = null; if (getPskPassphrase() && !TextUtils.isEmpty(mPskPassphrase)) { if (securityParams.isSecurityType(WifiConfiguration.SECURITY_TYPE_WAPI_PSK)) { config.preSharedKey = mPskPassphrase; } else { config.preSharedKey = NativeUtil.addEnclosingQuotes(mPskPassphrase); } } else if (getPsk() && !ArrayUtils.isEmpty(mPsk)) { config.preSharedKey = NativeUtil.hexStringFromByteArray(mPsk); } /* Do not read SAE password */ /** metadata: idstr */ if (getIdStr() && !TextUtils.isEmpty(mIdStr)) { Map<String, String> metadata = parseNetworkExtra(mIdStr); networkExtras.putAll(metadata); } else { Log.w(TAG, "getIdStr failed or empty"); } /** WAPI Cert Suite */ if (securityParams.isSecurityType(WifiConfiguration.SECURITY_TYPE_WAPI_CERT)) { if (config.enterpriseConfig == null) { return false; } config.enterpriseConfig.setEapMethod( WifiEnterpriseConfig.Eap.WAPI_CERT); /** WAPI Certificate Suite. */ if (getWapiCertSuite() && !TextUtils.isEmpty(mWapiCertSuite)) { config.enterpriseConfig.setWapiCertSuite(mWapiCertSuite); } return true; } return loadWifiEnterpriseConfig(config.SSID, config.enterpriseConfig); } } /** * Read network variables from the provided WifiConfiguration object into wpa_supplicant. * * @param config WifiConfiguration object to be saved. Note that the SSID will already by the * raw, untranslated SSID to pass to supplicant directly. * @return true if succeeds, false otherwise. * @throws IllegalArgumentException on malformed configuration params. */ public boolean saveWifiConfiguration(WifiConfiguration config) throws IllegalArgumentException { synchronized (mLock) { if (config == null) { return false; } // ieee80211be if (!config.isWifi7Enabled() && isServiceVersionIsAtLeast(3)) { if (!disableEht()) { Log.e(TAG, "failed to disable EHT (Wi-Fi 7)"); return false; } } // SSID if (config.SSID != null) { WifiSsid wifiSsid = WifiSsid.fromString(config.SSID); if (!setSsid(wifiSsid.getBytes())) { Log.e(TAG, "failed to set SSID: " + wifiSsid); return false; } } // BSSID String bssidStr = config.getNetworkSelectionStatus().getNetworkSelectionBSSID(); if (bssidStr != null) { byte[] bssid = NativeUtil.macAddressToByteArray(bssidStr); if (!setBssid(bssid)) { Log.e(TAG, "failed to set BSSID: " + bssidStr); return false; } } // HiddenSSID if (!setScanSsid(config.hiddenSSID)) { Log.e(TAG, config.SSID + ": failed to set hiddenSSID: " + config.hiddenSSID); return false; } SecurityParams securityParams = config.getNetworkSelectionStatus() .getCandidateSecurityParams(); if (securityParams == null) { Log.wtf(TAG, "No available security params."); return false; } Log.d(TAG, "The target security params: " + securityParams); boolean isRequirePmf = NativeUtil.getOptimalPmfSettingForConfig(config, securityParams.isRequirePmf(), mWifiGlobals); // RequirePMF if (!setRequirePmf(isRequirePmf)) { Log.e(TAG, config.SSID + ": failed to set requirePMF: " + config.requirePmf); return false; } // Key Management Scheme BitSet allowedKeyManagement = securityParams.getAllowedKeyManagement(); if (allowedKeyManagement.cardinality() != 0) { // Add upgradable type key management flags for PSK/SAE. allowedKeyManagement = addPskSaeUpgradableTypeFlagsIfSupported(config, allowedKeyManagement); // Add FT flags if supported. allowedKeyManagement = addFastTransitionFlags(allowedKeyManagement); // Add SHA256 key management flags. allowedKeyManagement = addSha256KeyMgmtFlags(allowedKeyManagement); if (!setKeyMgmt(wifiConfigurationToSupplicantKeyMgmtMask(allowedKeyManagement))) { Log.e(TAG, "failed to set Key Management"); return false; } // Check and set SuiteB configurations. if (allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192) && !saveSuiteBConfig(config)) { Log.e(TAG, "failed to set Suite-B-192 configuration"); return false; } // Check and set DPP Connection keys if (allowedKeyManagement.get(WifiConfiguration.KeyMgmt.DPP) && !saveDppConnectionConfig(config)) { Log.e(TAG, "failed to set DPP connection params"); return false; } } // Security Protocol BitSet allowedProtocols = securityParams.getAllowedProtocols(); if (allowedProtocols.cardinality() != 0 && !setProto( wifiConfigurationToSupplicantProtoMask(allowedProtocols, mWifiGlobals, WifiConfigurationUtil.isConfigForEnterpriseNetwork(config)))) { Log.e(TAG, "failed to set Security Protocol"); return false; } // Auth Algorithm BitSet allowedAuthAlgorithms = securityParams.getAllowedAuthAlgorithms(); if (allowedAuthAlgorithms.cardinality() != 0 && !setAuthAlg(wifiConfigurationToSupplicantAuthAlgMask( allowedAuthAlgorithms))) { Log.e(TAG, "failed to set AuthAlgorithm"); return false; } // Group Cipher BitSet allowedGroupCiphers = NativeUtil.getOptimalGroupCiphersForConfig( config, securityParams.getAllowedGroupCiphers(), mWifiGlobals); if (allowedGroupCiphers.cardinality() != 0 && (!setGroupCipher(wifiConfigurationToSupplicantGroupCipherMask( allowedGroupCiphers)))) { Log.e(TAG, "failed to set Group Cipher"); return false; } // Pairwise Cipher BitSet allowedPairwiseCiphers = NativeUtil.getOptimalPairwiseCiphersForConfig( config, securityParams.getAllowedPairwiseCiphers(), mWifiGlobals); if (allowedPairwiseCiphers.cardinality() != 0 && !setPairwiseCipher(wifiConfigurationToSupplicantPairwiseCipherMask( allowedPairwiseCiphers))) { Log.e(TAG, "failed to set PairwiseCipher"); return false; } // Pre Shared Key // For PSK, this can either be quoted ASCII passphrase or hex string for raw psk. // For SAE, password must be a quoted ASCII string if (config.preSharedKey != null) { if (securityParams.isSecurityType(WifiConfiguration.SECURITY_TYPE_WAPI_PSK)) { if (!setPskPassphrase(config.preSharedKey)) { Log.e(TAG, "failed to set wapi psk passphrase"); return false; } } else if (config.preSharedKey.startsWith("\"")) { if (allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { // WPA3 case, field is SAE Password if (!setSaePassword( NativeUtil.removeEnclosingQuotes(config.preSharedKey))) { Log.e(TAG, "failed to set sae password"); return false; } } if (allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { if (!setPskPassphrase( NativeUtil.removeEnclosingQuotes(config.preSharedKey))) { Log.e(TAG, "failed to set psk passphrase"); return false; } } } else { if (!allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) && allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { return false; } if (!setPsk(NativeUtil.hexStringToByteArray(config.preSharedKey))) { Log.e(TAG, "failed to set psk"); return false; } } } // Wep Keys boolean hasSetKey = false; if (config.wepKeys != null) { for (int i = 0; i < config.wepKeys.length; i++) { if (config.wepKeys[i] != null) { if (!setWepKey(i, NativeUtil.byteArrayFromArrayList( NativeUtil.hexOrQuotedStringToBytes(config.wepKeys[i])))) { Log.e(TAG, "failed to set wep_key " + i); return false; } hasSetKey = true; } } } // Wep Tx Key Idx if (hasSetKey) { if (!setWepTxKeyIdx(config.wepTxKeyIndex)) { Log.e(TAG, "failed to set wep_tx_keyidx: " + config.wepTxKeyIndex); return false; } } // metadata: FQDN + ConfigKey + CreatorUid final Map<String, String> metadata = new HashMap<String, String>(); if (config.isPasspoint()) { metadata.put(ID_STRING_KEY_FQDN, config.FQDN); // Selected RCOI if (!setSelectedRcoi(config.enterpriseConfig.getSelectedRcoi())) { Log.e(TAG, "failed to set selected RCOI"); return false; } } metadata.put(ID_STRING_KEY_CONFIG_KEY, config.getProfileKey()); metadata.put(ID_STRING_KEY_CREATOR_UID, Integer.toString(config.creatorUid)); if (!setIdStr(createNetworkExtra(metadata))) { Log.e(TAG, "failed to set id string"); return false; } // UpdateIdentifier if (config.updateIdentifier != null && !setUpdateIdentifier(Integer.parseInt(config.updateIdentifier))) { Log.e(TAG, "failed to set update identifier"); return false; } // SAE configuration if (allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) { /** * Hash-to-Element preference. * For devices that don't support H2E, H2E mode will be permanently disabled. * Devices that support H2E will enable both legacy and H2E mode by default, * and will connect to SAE networks with H2E if possible, unless H2E only * mode is enabled, and then the device will not connect to SAE networks in * legacy mode. */ if (!mWifiGlobals.isWpa3SaeH2eSupported() && securityParams.isSaeH2eOnlyMode()) { Log.e(TAG, "This device does not support SAE H2E."); return false; } byte mode = mWifiGlobals.isWpa3SaeH2eSupported() ? SaeH2eMode.H2E_OPTIONAL : SaeH2eMode.DISABLED; if (securityParams.isSaeH2eOnlyMode()) { mode = SaeH2eMode.H2E_MANDATORY; } if (!setSaeH2eMode(mode)) { Log.e(TAG, "failed to set H2E preference."); return false; } } // Vendor data if (SdkLevel.isAtLeastV() && isServiceVersionIsAtLeast(3) && config.getVendorData() != null && !config.getVendorData().isEmpty() && !setVendorData(config.getVendorData())) { Log.e(TAG, "Failed to set vendor data."); return false; } // Finish here if no EAP config to set if (config.enterpriseConfig != null && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) { if (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.WAPI_CERT) { // WAPI certificate suite name String param = config.enterpriseConfig .getFieldValue(WifiEnterpriseConfig.WAPI_CERT_SUITE_KEY); if (!TextUtils.isEmpty(param) && !setWapiCertSuite(param)) { Log.e(TAG, config.SSID + ": failed to set WAPI certificate suite: " + param); return false; } return true; } else if (!saveWifiEnterpriseConfig(config.SSID, config.enterpriseConfig)) { return false; } } // Now that the network is configured fully, start listening for callback events. return registerNewCallback(config.networkId, config.SSID); } } /** * Read network variables from wpa_supplicant into the provided WifiEnterpriseConfig object. * * @param ssid SSID of the network. (Used for logging purposes only) * @param eapConfig WifiEnterpriseConfig object to be populated. * @return true if succeeds, false otherwise. */ private boolean loadWifiEnterpriseConfig(String ssid, WifiEnterpriseConfig eapConfig) { synchronized (mLock) { if (eapConfig == null) { return false; } /** EAP method */ if (getEapMethod()) { eapConfig.setEapMethod(supplicantToWifiConfigurationEapMethod(mEapMethod)); } else { // Invalid eap method could be because it's not an enterprise config. Log.e(TAG, "Failed to get eap method. Assuming not an enterprise network"); return true; } /** EAP Phase 2 method */ if (getEapPhase2Method()) { eapConfig.setPhase2Method( supplicantToWifiConfigurationEapPhase2Method(mEapPhase2Method)); } else { // We cannot have an invalid eap phase 2 method. Return failure. Log.e(TAG, "Failed to get eap phase2 method"); return false; } /** EAP Identity */ if (getEapIdentity() && !ArrayUtils.isEmpty(mEapIdentity)) { eapConfig.setFieldValue( WifiEnterpriseConfig.IDENTITY_KEY, NativeUtil.stringFromByteArray(mEapIdentity)); } /** EAP Anonymous Identity */ if (getEapAnonymousIdentity() && !ArrayUtils.isEmpty(mEapAnonymousIdentity)) { eapConfig.setFieldValue( WifiEnterpriseConfig.ANON_IDENTITY_KEY, NativeUtil.stringFromByteArray(mEapAnonymousIdentity)); } /** EAP Password */ if (getEapPassword() && !ArrayUtils.isEmpty(mEapPassword)) { eapConfig.setFieldValue( WifiEnterpriseConfig.PASSWORD_KEY, NativeUtil.stringFromByteArray(mEapPassword)); } /** EAP Client Cert */ if (getEapClientCert() && !TextUtils.isEmpty(mEapClientCert)) { eapConfig.setFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY, mEapClientCert); } /** EAP CA Cert */ if (getEapCACert() && !TextUtils.isEmpty(mEapCACert)) { eapConfig.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, mEapCACert); } /** EAP OCSP type */ if (getOcsp()) { eapConfig.setOcsp(mOcsp); } /** EAP Subject Match */ if (getEapSubjectMatch() && !TextUtils.isEmpty(mEapSubjectMatch)) { eapConfig.setFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY, mEapSubjectMatch); } /** EAP Engine ID */ if (getEapEngineId() && !TextUtils.isEmpty(mEapEngineID)) { eapConfig.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, mEapEngineID); } /** EAP Engine. Set this only if the engine id is non null. */ if (getEapEngine() && !TextUtils.isEmpty(mEapEngineID)) { eapConfig.setFieldValue( WifiEnterpriseConfig.ENGINE_KEY, mEapEngine ? WifiEnterpriseConfig.ENGINE_ENABLE : WifiEnterpriseConfig.ENGINE_DISABLE); } /** EAP Private Key */ if (getEapPrivateKeyId() && !TextUtils.isEmpty(mEapPrivateKeyId)) { eapConfig.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, mEapPrivateKeyId); } /** EAP Alt Subject Match */ if (getEapAltSubjectMatch() && !TextUtils.isEmpty(mEapAltSubjectMatch)) { eapConfig.setFieldValue( WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, mEapAltSubjectMatch); } /** EAP Domain Suffix Match */ if (getEapDomainSuffixMatch() && !TextUtils.isEmpty(mEapDomainSuffixMatch)) { eapConfig.setFieldValue( WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, mEapDomainSuffixMatch); } /** EAP CA Path*/ if (getEapCAPath() && !TextUtils.isEmpty(mEapCAPath)) { eapConfig.setFieldValue(WifiEnterpriseConfig.CA_PATH_KEY, mEapCAPath); } return true; } } /** * save network variables from the provided dpp configuration to wpa_supplicant. * * @param config wificonfiguration object to be saved * @return true if succeeds, false otherwise. */ private boolean saveDppConnectionConfig(WifiConfiguration config) { synchronized (mLock) { final String methodStr = "setDppKeys"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { DppConnectionKeys keys = new DppConnectionKeys(); keys.connector = config.getDppConnector(); keys.cSign = config.getDppCSignKey(); keys.netAccessKey = config.getDppNetAccessKey(); mISupplicantStaNetwork.setDppKeys(keys); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Save network variables from the provided SuiteB configuration to wpa_supplicant. * * @param config WifiConfiguration object to be saved * @return true if succeeds, false otherwise. */ private boolean saveSuiteBConfig(WifiConfiguration config) { synchronized (mLock) { SecurityParams securityParams = config.getNetworkSelectionStatus() .getCandidateSecurityParams(); if (securityParams == null) { Log.wtf(TAG, "No available security params."); return false; } /** Group Cipher **/ BitSet allowedGroupCiphers = securityParams.getAllowedGroupCiphers(); if (allowedGroupCiphers.cardinality() != 0 && !setGroupCipher(wifiConfigurationToSupplicantGroupCipherMask( allowedGroupCiphers))) { Log.e(TAG, "Failed to set Group Cipher"); return false; } /** Pairwise Cipher*/ BitSet allowedPairwiseCiphers = securityParams.getAllowedPairwiseCiphers(); if (allowedPairwiseCiphers.cardinality() != 0 && !setPairwiseCipher(wifiConfigurationToSupplicantPairwiseCipherMask( allowedPairwiseCiphers))) { Log.e(TAG, "Failed to set PairwiseCipher"); return false; } /** GroupMgmt Cipher */ BitSet allowedGroupManagementCiphers = securityParams.getAllowedGroupManagementCiphers(); if (allowedGroupManagementCiphers.cardinality() != 0 && !setGroupMgmtCipher(wifiConfigurationToSupplicantGroupMgmtCipherMask( allowedGroupManagementCiphers))) { Log.e(TAG, "Failed to set GroupMgmtCipher"); return false; } BitSet allowedSuiteBCiphers = securityParams.getAllowedSuiteBCiphers(); if (allowedSuiteBCiphers.get(WifiConfiguration.SuiteBCipher.ECDHE_RSA)) { if (!enableTlsSuiteBEapPhase1Param(true)) { Log.e(TAG, "Failed to set TLSSuiteB"); return false; } } else if (allowedSuiteBCiphers.get(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA)) { if (!enableSuiteBEapOpenSslCiphers()) { Log.e(TAG, "Failed to set OpensslCipher"); return false; } } return true; } } /** * Save network variables from the provided WifiEnterpriseConfig object to wpa_supplicant. * * @param ssid SSID of the network. (Used for logging purposes only) * @param eapConfig WifiEnterpriseConfig object to be saved. * @return true if succeeds, false otherwise. */ private boolean saveWifiEnterpriseConfig(String ssid, WifiEnterpriseConfig eapConfig) { synchronized (mLock) { if (eapConfig == null) { return false; } /** EAP method */ if (!setEapMethod(wifiConfigurationToSupplicantEapMethod(eapConfig.getEapMethod()))) { Log.e(TAG, ssid + ": failed to set eap method: " + eapConfig.getEapMethod()); return false; } /** EAP Phase 2 method */ if (!setEapPhase2Method(wifiConfigurationToSupplicantEapPhase2Method( eapConfig.getPhase2Method()))) { Log.e(TAG, ssid + ": failed to set eap phase 2 method: " + eapConfig.getPhase2Method()); return false; } if (eapConfig.isAuthenticationSimBased() && eapConfig.getEapMethod() != WifiEnterpriseConfig.Eap.PEAP && eapConfig.getStrictConservativePeerMode()) { if (!enableStrictConservativePeerMode()) { Log.w(TAG, "failed or not support to set strict conservative peer mode."); } // don't return false, as the mode is optional. } String eapParam = null; /** EAP Identity */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapIdentity(NativeUtil.stringToByteArray(eapParam))) { Log.e(TAG, ssid + ": failed to set eap identity: " + eapParam); return false; } /** EAP Anonymous Identity */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY); if (!TextUtils.isEmpty(eapParam)) { String decoratedUsernamePrefix = eapConfig.getFieldValue(WifiEnterpriseConfig.DECORATED_IDENTITY_PREFIX_KEY); if (!TextUtils.isEmpty(decoratedUsernamePrefix)) { eapParam = decoratedUsernamePrefix + eapParam; } if (!setEapAnonymousIdentity(NativeUtil.stringToByteArray(eapParam))) { Log.e(TAG, ssid + ": failed to set eap anonymous identity: " + eapParam); return false; } } /** EAP Password */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapPassword(NativeUtil.stringToByteArray(eapParam))) { Log.e(TAG, ssid + ": failed to set eap password"); return false; } /** EAP Client Cert */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapClientCert(eapParam)) { Log.e(TAG, ssid + ": failed to set eap client cert: " + eapParam); return false; } /** EAP CA Cert */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapCACert(eapParam)) { Log.e(TAG, ssid + ": failed to set eap ca cert: " + eapParam); return false; } /** EAP Subject Match */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapSubjectMatch(eapParam)) { Log.e(TAG, ssid + ": failed to set eap subject match: " + eapParam); return false; } /** EAP Engine ID */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapEngineID(eapParam)) { Log.e(TAG, ssid + ": failed to set eap engine id: " + eapParam); return false; } /** EAP Engine */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapEngine( eapParam.equals(WifiEnterpriseConfig.ENGINE_ENABLE) ? true : false)) { Log.e(TAG, ssid + ": failed to set eap engine: " + eapParam); return false; } /** EAP Private Key */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapPrivateKeyId(eapParam)) { Log.e(TAG, ssid + ": failed to set eap private key: " + eapParam); return false; } /** EAP Alt Subject Match */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapAltSubjectMatch(eapParam)) { Log.e(TAG, ssid + ": failed to set eap alt subject match: " + eapParam); return false; } /** EAP Domain Suffix Match */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapDomainSuffixMatch(eapParam)) { Log.e(TAG, ssid + ": failed to set eap domain suffix match: " + eapParam); return false; } /** EAP CA Path*/ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY); if (!TextUtils.isEmpty(eapParam) && !setEapCAPath(eapParam)) { Log.e(TAG, ssid + ": failed to set eap ca path: " + eapParam); return false; } /** EAP Proactive Key Caching */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.OPP_KEY_CACHING); if (!TextUtils.isEmpty(eapParam) && !setEapProactiveKeyCaching(eapParam.equals("1") ? true : false)) { Log.e(TAG, ssid + ": failed to set proactive key caching: " + eapParam); return false; } /** OCSP (Online Certificate Status Protocol) */ if (!setOcsp(eapConfig.getOcsp())) { Log.e(TAG, "failed to set ocsp"); return false; } /** EAP ERP */ eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.EAP_ERP); if (!TextUtils.isEmpty(eapParam) && eapParam.equals("1")) { if (!setEapErp(true)) { Log.e(TAG, ssid + ": failed to set eap erp"); return false; } } if (isServiceVersionIsAtLeast(2)) { if (!setMinimumTlsVersionEapPhase1Param(getOptimalMinimumTlsVersion(eapConfig))) { Log.e(TAG, "Failed to set the minimum TLS version"); return false; } } return true; } } private int getOptimalMinimumTlsVersion(WifiEnterpriseConfig enterpriseConfig) { int maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_2; if ((mWpaDriverFeatures & WifiManager.WIFI_FEATURE_TLS_V1_3) != 0) { maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_3; } int requiredMinimumTlsVersion = enterpriseConfig.getMinimumTlsVersion(); if (requiredMinimumTlsVersion > maxTlsVersionSupported) { Log.w(TAG, "The required minimum TLS version " + requiredMinimumTlsVersion + " exceeds the maximum supported TLS version " + maxTlsVersionSupported + ", fallback to the maximum supported TLS version."); return maxTlsVersionSupported; } return requiredMinimumTlsVersion; } /** * Maps WifiConfiguration Key Management BitSet to Supplicant AIDL bitmask int * * @return bitmask int describing the allowed Key Management schemes, readable by the Supplicant * AIDL hal */ private static int wifiConfigurationToSupplicantKeyMgmtMask(BitSet keyMgmt) { int mask = 0; for (int bit = keyMgmt.nextSetBit(0); bit != -1; bit = keyMgmt.nextSetBit(bit + 1)) { switch (bit) { case WifiConfiguration.KeyMgmt.NONE: mask |= KeyMgmtMask.NONE; break; case WifiConfiguration.KeyMgmt.WPA_PSK: mask |= KeyMgmtMask.WPA_PSK; break; case WifiConfiguration.KeyMgmt.WPA_EAP: mask |= KeyMgmtMask.WPA_EAP; break; case WifiConfiguration.KeyMgmt.IEEE8021X: mask |= KeyMgmtMask.IEEE8021X; break; case WifiConfiguration.KeyMgmt.OSEN: mask |= KeyMgmtMask.OSEN; break; case WifiConfiguration.KeyMgmt.FT_PSK: mask |= KeyMgmtMask.FT_PSK; break; case WifiConfiguration.KeyMgmt.FT_EAP: mask |= KeyMgmtMask.FT_EAP; break; case WifiConfiguration.KeyMgmt.OWE: mask |= KeyMgmtMask.OWE; break; case WifiConfiguration.KeyMgmt.SAE: mask |= KeyMgmtMask.SAE; break; case WifiConfiguration.KeyMgmt.SUITE_B_192: mask |= KeyMgmtMask.SUITE_B_192; break; case WifiConfiguration.KeyMgmt.WPA_PSK_SHA256: mask |= KeyMgmtMask.WPA_PSK_SHA256; break; case WifiConfiguration.KeyMgmt.WPA_EAP_SHA256: mask |= KeyMgmtMask.WPA_EAP_SHA256; break; case WifiConfiguration.KeyMgmt.WAPI_PSK: mask |= KeyMgmtMask.WAPI_PSK; break; case WifiConfiguration.KeyMgmt.WAPI_CERT: mask |= KeyMgmtMask.WAPI_CERT; break; case WifiConfiguration.KeyMgmt.FILS_SHA256: mask |= KeyMgmtMask.FILS_SHA256; break; case WifiConfiguration.KeyMgmt.FILS_SHA384: mask |= KeyMgmtMask.FILS_SHA384; break; case WifiConfiguration.KeyMgmt.DPP: mask |= KeyMgmtMask.DPP; break; case WifiConfiguration.KeyMgmt.WPA2_PSK: // This should never happen default: throw new IllegalArgumentException( "Invalid protoMask bit in keyMgmt: " + bit); } } return mask; } private static int wifiConfigurationToSupplicantProtoMask(BitSet protoMask, WifiGlobals wifiGlobals, boolean isEnterprise) { int mask = 0; for (int bit = protoMask.nextSetBit(0); bit != -1; bit = protoMask.nextSetBit(bit + 1)) { switch (bit) { case WifiConfiguration.Protocol.WPA: if (isEnterprise || !wifiGlobals.isWpaPersonalDeprecated()) { mask |= ProtoMask.WPA; } break; case WifiConfiguration.Protocol.RSN: mask |= ProtoMask.RSN; break; case WifiConfiguration.Protocol.OSEN: mask |= ProtoMask.OSEN; break; case WifiConfiguration.Protocol.WAPI: mask |= ProtoMask.WAPI; break; default: throw new IllegalArgumentException( "Invalid protoMask bit in wificonfig: " + bit); } } return mask; } private static int wifiConfigurationToSupplicantAuthAlgMask(BitSet authAlgMask) { int mask = 0; for (int bit = authAlgMask.nextSetBit(0); bit != -1; bit = authAlgMask.nextSetBit(bit + 1)) { switch (bit) { case WifiConfiguration.AuthAlgorithm.OPEN: mask |= AuthAlgMask.OPEN; break; case WifiConfiguration.AuthAlgorithm.SHARED: mask |= AuthAlgMask.SHARED; break; case WifiConfiguration.AuthAlgorithm.LEAP: mask |= AuthAlgMask.LEAP; break; case WifiConfiguration.AuthAlgorithm.SAE: mask |= AuthAlgMask.SAE; break; default: throw new IllegalArgumentException( "Invalid authAlgMask bit in wificonfig: " + bit); } } return mask; } private int wifiConfigurationToSupplicantGroupCipherMask(BitSet groupCipherMask) { synchronized (mLock) { int mask = 0; for (int bit = groupCipherMask.nextSetBit(0); bit != -1; bit = groupCipherMask.nextSetBit(bit + 1)) { switch (bit) { case WifiConfiguration.GroupCipher.WEP40: mask |= GroupCipherMask.WEP40; break; case WifiConfiguration.GroupCipher.WEP104: mask |= GroupCipherMask.WEP104; break; case WifiConfiguration.GroupCipher.TKIP: mask |= GroupCipherMask.TKIP; break; case WifiConfiguration.GroupCipher.CCMP: mask |= GroupCipherMask.CCMP; break; case WifiConfiguration.GroupCipher.GTK_NOT_USED: mask |= GroupCipherMask.GTK_NOT_USED; break; case WifiConfiguration.GroupCipher.GCMP_256: if (0 == (mAdvanceKeyMgmtFeatures & WifiManager.WIFI_FEATURE_WPA3_SUITE_B)) { Log.d(TAG, "Ignore unsupported GCMP_256 cipher."); break; } mask |= GroupCipherMask.GCMP_256; break; case WifiConfiguration.GroupCipher.SMS4: mask |= GroupCipherMask.SMS4; break; case WifiConfiguration.GroupCipher.GCMP_128: mask |= GroupCipherMask.GCMP_128; break; default: throw new IllegalArgumentException( "Invalid GroupCipherMask bit in wificonfig: " + bit); } } return mask; } } private static int wifiConfigurationToSupplicantGroupMgmtCipherMask(BitSet groupMgmtCipherMask) { int mask = 0; for (int bit = groupMgmtCipherMask.nextSetBit(0); bit != -1; bit = groupMgmtCipherMask.nextSetBit(bit + 1)) { switch (bit) { case WifiConfiguration.GroupMgmtCipher.BIP_CMAC_256: mask |= GroupMgmtCipherMask.BIP_CMAC_256; break; case WifiConfiguration.GroupMgmtCipher.BIP_GMAC_128: mask |= GroupMgmtCipherMask.BIP_GMAC_128; break; case WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256: mask |= GroupMgmtCipherMask.BIP_GMAC_256; break; default: throw new IllegalArgumentException( "Invalid GroupMgmtCipherMask bit in wificonfig: " + bit); } } return mask; } private int wifiConfigurationToSupplicantPairwiseCipherMask(BitSet pairwiseCipherMask) { synchronized (mLock) { int mask = 0; for (int bit = pairwiseCipherMask.nextSetBit(0); bit != -1; bit = pairwiseCipherMask.nextSetBit(bit + 1)) { switch (bit) { case WifiConfiguration.PairwiseCipher.NONE: mask |= PairwiseCipherMask.NONE; break; case WifiConfiguration.PairwiseCipher.TKIP: mask |= PairwiseCipherMask.TKIP; break; case WifiConfiguration.PairwiseCipher.CCMP: mask |= PairwiseCipherMask.CCMP; break; case WifiConfiguration.PairwiseCipher.GCMP_256: if (0 == (mAdvanceKeyMgmtFeatures & WifiManager.WIFI_FEATURE_WPA3_SUITE_B)) { Log.d(TAG, "Ignore unsupporting GCMP_256 cipher."); break; } mask |= PairwiseCipherMask.GCMP_256; break; case WifiConfiguration.PairwiseCipher.SMS4: mask |= PairwiseCipherMask.SMS4; break; case WifiConfiguration.PairwiseCipher.GCMP_128: mask |= PairwiseCipherMask.GCMP_128; break; default: throw new IllegalArgumentException( "Invalid pairwiseCipherMask bit in wificonfig: " + bit); } } return mask; } } private static int supplicantToWifiConfigurationEapMethod(int value) { switch (value) { case EapMethod.PEAP: return WifiEnterpriseConfig.Eap.PEAP; case EapMethod.TLS: return WifiEnterpriseConfig.Eap.TLS; case EapMethod.TTLS: return WifiEnterpriseConfig.Eap.TTLS; case EapMethod.PWD: return WifiEnterpriseConfig.Eap.PWD; case EapMethod.SIM: return WifiEnterpriseConfig.Eap.SIM; case EapMethod.AKA: return WifiEnterpriseConfig.Eap.AKA; case EapMethod.AKA_PRIME: return WifiEnterpriseConfig.Eap.AKA_PRIME; case EapMethod.WFA_UNAUTH_TLS: return WifiEnterpriseConfig.Eap.UNAUTH_TLS; // WifiEnterpriseConfig.Eap.NONE: default: Log.e(TAG, "invalid eap method value from supplicant: " + value); return -1; } } private static int supplicantToWifiConfigurationEapPhase2Method(int value) { switch (value) { case EapPhase2Method.NONE: return WifiEnterpriseConfig.Phase2.NONE; case EapPhase2Method.PAP: return WifiEnterpriseConfig.Phase2.PAP; case EapPhase2Method.MSPAP: return WifiEnterpriseConfig.Phase2.MSCHAP; case EapPhase2Method.MSPAPV2: return WifiEnterpriseConfig.Phase2.MSCHAPV2; case EapPhase2Method.GTC: return WifiEnterpriseConfig.Phase2.GTC; case EapPhase2Method.SIM: return WifiEnterpriseConfig.Phase2.SIM; case EapPhase2Method.AKA: return WifiEnterpriseConfig.Phase2.AKA; case EapPhase2Method.AKA_PRIME: return WifiEnterpriseConfig.Phase2.AKA_PRIME; default: Log.e(TAG, "Invalid eap phase2 method value from supplicant: " + value); return -1; } } private static int wifiConfigurationToSupplicantEapMethod(int value) { switch (value) { case WifiEnterpriseConfig.Eap.PEAP: return EapMethod.PEAP; case WifiEnterpriseConfig.Eap.TLS: return EapMethod.TLS; case WifiEnterpriseConfig.Eap.TTLS: return EapMethod.TTLS; case WifiEnterpriseConfig.Eap.PWD: return EapMethod.PWD; case WifiEnterpriseConfig.Eap.SIM: return EapMethod.SIM; case WifiEnterpriseConfig.Eap.AKA: return EapMethod.AKA; case WifiEnterpriseConfig.Eap.AKA_PRIME: return EapMethod.AKA_PRIME; case WifiEnterpriseConfig.Eap.UNAUTH_TLS: return EapMethod.WFA_UNAUTH_TLS; // WifiEnterpriseConfig.Eap.NONE: default: Log.e(TAG, "Invalid eap method value from WifiConfiguration: " + value); return -1; } } private static int wifiConfigurationToSupplicantEapPhase2Method(int value) { switch (value) { case WifiEnterpriseConfig.Phase2.NONE: return EapPhase2Method.NONE; case WifiEnterpriseConfig.Phase2.PAP: return EapPhase2Method.PAP; case WifiEnterpriseConfig.Phase2.MSCHAP: return EapPhase2Method.MSPAP; case WifiEnterpriseConfig.Phase2.MSCHAPV2: return EapPhase2Method.MSPAPV2; case WifiEnterpriseConfig.Phase2.GTC: return EapPhase2Method.GTC; case WifiEnterpriseConfig.Phase2.SIM: return EapPhase2Method.SIM; case WifiEnterpriseConfig.Phase2.AKA: return EapPhase2Method.AKA; case WifiEnterpriseConfig.Phase2.AKA_PRIME: return EapPhase2Method.AKA_PRIME; default: Log.e(TAG, "Invalid eap phase2 method value from WifiConfiguration: " + value); return -1; } } /** * Retrieves the ID allocated to this network by the supplicant. * Result is stored in mNetworkId. * * This is not the |SSID| of the network, but an internal identifier for * this network used by the supplicant. * * @return true if ID was retrieved, false otherwise */ private boolean getId() { synchronized (mLock) { final String methodStr = "getId"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mNetworkId = mISupplicantStaNetwork.getId(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** Get current network id */ public int getNetworkId() { synchronized (mLock) { if (!getId()) { return -1; } return mNetworkId; } } private boolean registerCallback(ISupplicantStaNetworkCallback callback) { synchronized (mLock) { final String methodStr = "registerCallback"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.registerCallback(callback); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } private boolean registerNewCallback(int networkId, String ssid) { synchronized (mLock) { ISupplicantStaNetworkCallback callback = new SupplicantStaNetworkCallbackAidlImpl( SupplicantStaNetworkHalAidlImpl.this, networkId, ssid, mIfaceName, mLock, mWifiMonitor); if (!registerCallback(callback)) { Log.e(TAG, "Failed to register callback."); return false; } mISupplicantStaNetworkCallback = callback; return true; } } /** * Set SSID for this network. * * @param ssid Value to set. * Max length of |ParamSizeLimits.SSID_MAX_LEN_IN_BYTES|. * @return true if successful, false otherwise */ private boolean setSsid(byte[] ssid) { synchronized (mLock) { final String methodStr = "setSsid"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setSsid(ssid); Log.i(TAG, "Successfully set SSID"); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Disable EHT for this network. * * @return true if successful, false otherwise */ private boolean disableEht() { synchronized (mLock) { final String methodStr = "disableEht"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { if (!isServiceVersionIsAtLeast(3)) { return false; } mISupplicantStaNetwork.disableEht(); Log.i(TAG, "Successfully disabled EHT"); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set the BSSID for this network. * * @param bssidStr MAC address in "XX:XX:XX:XX:XX:XX" form or "any" to reset the mac address. * @return true if it succeeds, false otherwise. */ public boolean setBssid(String bssidStr) { synchronized (mLock) { try { return setBssid(NativeUtil.macAddressToByteArray(bssidStr)); } catch (IllegalArgumentException e) { Log.e(TAG, "Illegal argument " + bssidStr, e); return false; } } } private boolean setBssid(byte[/* 6 */] bssid) { synchronized (mLock) { final String methodStr = "setBssid"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setBssid(bssid); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set whether to send probe requests for this network (hidden). * * @param enable true to set, false otherwise. * @return true if successful, false otherwise */ private boolean setScanSsid(boolean enable) { synchronized (mLock) { final String methodStr = "setScanSsid"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setScanSsid(enable); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set key management mask for the network. * * @param keyMgmtMask value to set. * Combination of |KeyMgmtMask| values. * @return true if successful, false otherwise */ private boolean setKeyMgmt(int keyMgmtMask) { synchronized (mLock) { final String methodStr = "setKeyMgmt"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setKeyMgmt(keyMgmtMask); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set proto mask for the network. * * @param protoMask value to set. * Combination of |ProtoMask| values. * @return true if successful, false otherwise */ private boolean setProto(int protoMask) { synchronized (mLock) { final String methodStr = "setProto"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setProto(protoMask); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set auth alg mask for the network. * * @param authAlgMask value to set. * Combination of |ProtoMask| values. * @return true if successful, false otherwise */ private boolean setAuthAlg(int authAlgMask) { synchronized (mLock) { final String methodStr = "setAuthAlg"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setAuthAlg(authAlgMask); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set group cipher mask for the network. * * @param groupCipherMask value to set. * Combination of |ProtoMask| values. * @return true if successful, false otherwise */ private boolean setGroupCipher(int groupCipherMask) { synchronized (mLock) { final String methodStr = "setGroupCipher"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } if (mVerboseLoggingEnabled) { Log.d(TAG, String.format("setGroupCipher: 0x%x", groupCipherMask)); } try { mISupplicantStaNetwork.setGroupCipher(groupCipherMask); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Enable TLS Suite-B in EAP Phase1 * * @param enable Set to true to enable TLS Suite-B in EAP phase1 * @return true if successful, false otherwise */ private boolean enableTlsSuiteBEapPhase1Param(boolean enable) { synchronized (mLock) { final String methodStr = "setEapPhase1Params"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.enableTlsSuiteBEapPhase1Param(enable); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP OpenSSL Suite-B-192 ciphers for WPA3-Enterprise * * @return true if successful, false otherwise */ private boolean enableSuiteBEapOpenSslCiphers() { synchronized (mLock) { final String methodStr = "setEapOpenSslCiphers"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.enableSuiteBEapOpenSslCiphers(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set pairwise cipher mask for the network. * * @param pairwiseCipherMask value to set. * Combination of |ProtoMask| values. * @return true if successful, false otherwise */ private boolean setPairwiseCipher(int pairwiseCipherMask) { synchronized (mLock) { final String methodStr = "setPairwiseCipher"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } if (mVerboseLoggingEnabled) { Log.d(TAG, String.format("setPairwiseCipher: 0x%x", pairwiseCipherMask)); } try { mISupplicantStaNetwork.setPairwiseCipher(pairwiseCipherMask); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set group management cipher mask for the network. * * @param groupMgmtCipherMask value to set. * Combination of |GroupMgmtCipherMask| values. * @return true if successful, false otherwise */ private boolean setGroupMgmtCipher(int groupMgmtCipherMask) { synchronized (mLock) { final String methodStr = "setGroupMgmtCipher"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setGroupMgmtCipher(groupMgmtCipherMask); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set passphrase for WPA_PSK network. * * @param psk value to set. * Length of value must be between * |ParamSizeLimits.PSK_PASSPHRASE_MIN_LEN_IN_BYTES| and * |ParamSizeLimits.PSK_PASSPHRASE_MAX_LEN_IN_BYTES|. * @return true if successful, false otherwise */ private boolean setPskPassphrase(String psk) { synchronized (mLock) { final String methodStr = "setPskPassphrase"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setPskPassphrase(psk); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set raw psk for WPA_PSK network. * * @param psk value to set as specified in IEEE 802.11i-2004 standard. * This is the calculated using 'wpa_passphrase <ssid> [passphrase]' * @return true if successful, false otherwise */ private boolean setPsk(byte[] psk) { synchronized (mLock) { final String methodStr = "setPsk"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setPsk(psk); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ArrayIndexOutOfBoundsException e) { Log.e(TAG, "ISupplicantStaNetwork." + methodStr + " failed: " + e); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set WEP key for WEP network. * * @param keyIdx Index of wep key to set. * Max of |ParamSizeLimits.WEP_KEYS_MAX_NUM|. * @param wepKey value to set. * Length of each key must be either * |ParamSizeLimits.WEP40_KEY_LEN_IN_BYTES| or * |ParamSizeLimits.WEP104_KEY_LEN_IN_BYTES|. * @return true if successful, false otherwise */ private boolean setWepKey(int keyIdx, byte[] wepKey) { synchronized (mLock) { final String methodStr = "setWepKey"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setWepKey(keyIdx, wepKey); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set default Tx key index for WEP network. * * @param keyIdx value to set. * Max of |ParamSizeLimits.WEP_KEYS_MAX_NUM|. * @return true if successful, false otherwise */ private boolean setWepTxKeyIdx(int keyIdx) { synchronized (mLock) { final String methodStr = "setWepTxKeyIdx"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setWepTxKeyIdx(keyIdx); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set whether RequirePmf is enabled for this network. * * @param enable true to set, false otherwise. * @return true if successful, false otherwise */ private boolean setRequirePmf(boolean enable) { synchronized (mLock) { final String methodStr = "setRequirePmf"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } if (mVerboseLoggingEnabled) { Log.d(TAG, "setRequirePmf: " + enable); } try { mISupplicantStaNetwork.setRequirePmf(enable); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set PPS MO ID for this network. * (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier) * * @param identifier ID value to set. * @return true if successful, false otherwise */ private boolean setUpdateIdentifier(int identifier) { synchronized (mLock) { final String methodStr = "setUpdateIdentifier"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setUpdateIdentifier(identifier); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set WAPI certificate suite name for this network. * * @param certSuite value to set. * @return true if successful, false otherwise */ private boolean setWapiCertSuite(String certSuite) { synchronized (mLock) { final String methodStr = "setWapiCertSuite"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setWapiCertSuite(certSuite); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Method for this network. * * @param method value to be set. * Must be one of |EapMethod| values. * @return true if successful, false otherwise */ private boolean setEapMethod(int method) { synchronized (mLock) { final String methodStr = "setEapMethod"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapMethod(method); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Phase2 Method for this network. * * EAP method needs to be set for this to work. * * @param method value to set. * Must be one of |EapPhase2Method| values. * @return true if successful, false otherwise */ private boolean setEapPhase2Method(int method) { synchronized (mLock) { final String methodStr = "setEapPhase2Method"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapPhase2Method(method); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Identity for this network. * * @param identity value to set. * @return true if successful, false otherwise */ private boolean setEapIdentity(byte[] identity) { synchronized (mLock) { final String methodStr = "setEapIdentity"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapIdentity(identity); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Anonymous Identity for this network. * * @param identity value to set. * @return true if successful, false otherwise */ public boolean setEapAnonymousIdentity(byte[] identity) { synchronized (mLock) { final String methodStr = "setEapAnonymousIdentity"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapAnonymousIdentity(identity); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Password for this network. * * @param password value to set. * @return true if successful, false otherwise */ private boolean setEapPassword(byte[] password) { synchronized (mLock) { final String methodStr = "setEapPassword"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapPassword(password); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP CA certificate file path for this network. * * @param path value to set. * @return true if successful, false otherwise */ private boolean setEapCACert(String path) { synchronized (mLock) { final String methodStr = "setEapCACert"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapCACert(path); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP CA certificate directory path for this network. * * @param path value to set. * @return true if successful, false otherwise */ private boolean setEapCAPath(String path) { synchronized (mLock) { final String methodStr = "setEapCAPath"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapCAPath(path); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Client certificate file path for this network. * * @param path value to set. * @return true if successful, false otherwise */ private boolean setEapClientCert(String path) { synchronized (mLock) { final String methodStr = "setEapClientCert"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapClientCert(path); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP private key Id for this network. * This is used if private key operations for EAP-TLS are performed * using a smartcard. * * @param id value to set. * @return true if successful, false otherwise */ private boolean setEapPrivateKeyId(String id) { synchronized (mLock) { final String methodStr = "setEapPrivateKeyId"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapPrivateKeyId(id); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP subject match for this network. * * @param match value to set. * @return true if successful, false otherwise */ private boolean setEapSubjectMatch(String match) { synchronized (mLock) { final String methodStr = "setEapSubjectMatch"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapSubjectMatch(match); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Alt subject match for this network. * * @param match value to set. * @return true if successful, false otherwise */ private boolean setEapAltSubjectMatch(String match) { synchronized (mLock) { final String methodStr = "setEapAltSubjectMatch"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapAltSubjectMatch(match); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Enable EAP Open SSL Engine for this network. * * @param enable true to set, false otherwise. * @return true if successful, false otherwise */ private boolean setEapEngine(boolean enable) { synchronized (mLock) { final String methodStr = "setEapEngine"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapEngine(enable); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Open SSL Engine ID for this network. * * @param id value to set. * @return true if successful, false otherwise */ private boolean setEapEngineID(String id) { synchronized (mLock) { final String methodStr = "setEapEngineID"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapEngineID(id); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set EAP Domain suffix match for this network. * * @param match value to set. * @return true if successful, false otherwise */ private boolean setEapDomainSuffixMatch(String match) { synchronized (mLock) { final String methodStr = "setEapDomainSuffixMatch"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapDomainSuffixMatch(match); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * This field can be used to enable proactive key caching which is also * known as opportunistic PMKSA caching for WPA2. This is disabled (0) * by default unless default value is changed with the global okc=1 * parameter. * * Proactive key caching is used to make supplicant assume that the APs * are using the same PMK and generate PMKSA cache entries without * doing RSN pre-authentication. This requires support from the AP side * and is normally used with wireless switches that co-locate the * authenticator. * * @param enable true to set, false otherwise. * @return true if successful, false otherwise */ private boolean setEapProactiveKeyCaching(boolean enable) { synchronized (mLock) { final String methodStr = "setEapProactiveKeyCaching"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setProactiveKeyCaching(enable); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set ID string for this network. * Network identifier string for external scripts. * * @param idString ID string value to set. * @return true if successful, false otherwise */ private boolean setIdStr(String idString) { synchronized (mLock) { final String methodStr = "setIdStr"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setIdStr(idString); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set SAE password for WPA3-Personal * * @param saePassword string with the above option * @return true if successful, false otherwise */ private boolean setSaePassword(String saePassword) { synchronized (mLock) { final String methodStr = "setSaePassword"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setSaePassword(saePassword); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Enable Extensible Authentication (EAP) - Re-authentication Protocol (ERP) for this network. * * @param enable true to set, false otherwise. * @return true if successful, false otherwise */ private boolean setEapErp(boolean enable) { synchronized (mLock) { final String methodStr = "setEapErp"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setEapErp(enable); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get SSID for this network. Result is stored in mSsid. * * @return true if successful, false otherwise */ private boolean getSsid() { synchronized (mLock) { final String methodStr = "getSsid"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mSsid = mISupplicantStaNetwork.getSsid(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get the BSSID set for this network. Result is stored in mBssid. * * @return true if successful, false otherwise */ private boolean getBssid() { synchronized (mLock) { final String methodStr = "getBssid"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mBssid = mISupplicantStaNetwork.getBssid(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get whether Probe Requests are being sent for this network (hidden). * Result is stored in mScanSsid. * * @return true if successful, false otherwise */ private boolean getScanSsid() { synchronized (mLock) { final String methodStr = "getScanSsid"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mScanSsid = mISupplicantStaNetwork.getScanSsid(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get the key mgmt mask set for the network. Result is stored in mKeyMgmtMask. * * @return true if successful, false otherwise */ private boolean getKeyMgmt() { synchronized (mLock) { final String methodStr = "getKeyMgmt"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mKeyMgmtMask = mISupplicantStaNetwork.getKeyMgmt(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get the proto mask set for the network. Result is stored in mProtoMask. * * @return true if successful, false otherwise */ private boolean getProto() { synchronized (mLock) { final String methodStr = "getProto"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mProtoMask = mISupplicantStaNetwork.getProto(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get the auth alg mask set for the network. Result is stored in mAuthAlgMask. * * @return true if successful, false otherwise */ private boolean getAuthAlg() { synchronized (mLock) { final String methodStr = "getAuthAlg"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mAuthAlgMask = mISupplicantStaNetwork.getAuthAlg(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get the group cipher mask set for the network. Result is stored in mGroupCipherMask. * * @return true if successful, false otherwise */ private boolean getGroupCipher() { synchronized (mLock) { final String methodStr = "getGroupCipher"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mGroupCipherMask = mISupplicantStaNetwork.getGroupCipher(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get the pairwise cipher mask set for the network. Result is stored in mPairwiseCipherMask. * * @return true if successful, false otherwise */ private boolean getPairwiseCipher() { synchronized (mLock) { final String methodStr = "getPairwiseCipher"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mPairwiseCipherMask = mISupplicantStaNetwork.getPairwiseCipher(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get the group management cipher mask set for the network. Result is stored in * mGroupMgmtCipherMask. * * @return true if successful, false otherwise */ private boolean getGroupMgmtCipher() { synchronized (mLock) { final String methodStr = "getGroupMgmtCipher"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mGroupMgmtCipherMask = mISupplicantStaNetwork.getGroupMgmtCipher(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get passphrase for WPA_PSK network. Result is stored in mPskPassphrase if retrieved. * Must return a failure if network has no passphrase set (use |getPsk| if * network was configured with raw psk instead). * * @return true if successful, false otherwise */ private boolean getPskPassphrase() { synchronized (mLock) { final String methodStr = "getPskPassphrase"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mPskPassphrase = mISupplicantStaNetwork.getPskPassphrase(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get SAE password for WPA3-Personal. Result is stored in mSaePassword. * * @return true if successful, false otherwise */ private boolean getSaePassword() { synchronized (mLock) { final String methodStr = "getSaePassword"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mSaePassword = mISupplicantStaNetwork.getSaePassword(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get raw psk for WPA_PSK network. Result is stored in mPsk. * * @return true if successful, false otherwise */ private boolean getPsk() { synchronized (mLock) { final String methodStr = "getPsk"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mPsk = mISupplicantStaNetwork.getPsk(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get WEP key for WEP network. Result is stored in mWepKey. * * @param keyIdx Index of wep key to be fetched. * Max of |WEP_KEYS_MAX_NUM|. * @return true if successful, false otherwise */ private boolean getWepKey(int keyIdx) { synchronized (mLock) { final String methodStr = "keyIdx"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mWepKey = mISupplicantStaNetwork.getWepKey(keyIdx); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get default Tx key index for WEP network. Result is stored in mWepTxKeyIdx. * * @return true if successful, false otherwise */ private boolean getWepTxKeyIdx() { synchronized (mLock) { final String methodStr = "getWepTxKeyIdx"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mWepTxKeyIdx = mISupplicantStaNetwork.getWepTxKeyIdx(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get whether RequirePmf is enabled for this network. Result is stored in mWepTxKeyIdx. * * @return true if successful, false otherwise */ private boolean getRequirePmf() { synchronized (mLock) { final String methodStr = "getRequirePmf"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mRequirePmf = mISupplicantStaNetwork.getRequirePmf(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get WAPI certificate suite name set for this network. Result is stored in mWapiCertSuite. * * @return true if successful, false otherwise */ private boolean getWapiCertSuite() { synchronized (mLock) { final String methodStr = "getWapiCertSuite"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mWapiCertSuite = mISupplicantStaNetwork.getWapiCertSuite(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP Method set for this network. Result is stored in mEapMethod. * * @return true if successful, false otherwise */ private boolean getEapMethod() { synchronized (mLock) { final String methodStr = "getEapMethod"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapMethod = mISupplicantStaNetwork.getEapMethod(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP Phase2 Method set for this network. Result is stored in mEapPhase2Method. * * @return true if successful, false otherwise */ private boolean getEapPhase2Method() { synchronized (mLock) { final String methodStr = "getEapPhase2Method"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapPhase2Method = mISupplicantStaNetwork.getEapPhase2Method(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP Identity set for this network. Result is stored in mEapIdentity. * * @return true if successful, false otherwise */ private boolean getEapIdentity() { synchronized (mLock) { final String methodStr = "getEapIdentity"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapIdentity = mISupplicantStaNetwork.getEapIdentity(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP Anonymous Identity set for this network. Result is stored in mEapAnonymousIdentity. * * @return true if successful, false otherwise */ private boolean getEapAnonymousIdentity() { synchronized (mLock) { final String methodStr = "getEapAnonymousIdentity"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapAnonymousIdentity = mISupplicantStaNetwork.getEapAnonymousIdentity(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Wrapper method for getEapAnonymousIdentity(). Gets the anonymous identity * from supplicant and returns it as a string. * * @return anonymous identity string if successful, null otherwise. */ public String fetchEapAnonymousIdentity() { synchronized (mLock) { if (!getEapAnonymousIdentity()) { return null; } return NativeUtil.stringFromByteArray(mEapAnonymousIdentity); } } /** * Get EAP Password set for this network. Result is stored in mEapPassword. * * @return true if successful, false otherwise */ private boolean getEapPassword() { synchronized (mLock) { final String methodStr = "getEapPassword"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapPassword = mISupplicantStaNetwork.getEapPassword(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP CA certificate file path set for this network. Result is stored in mEapCACert. * * @return true if successful, false otherwise */ private boolean getEapCACert() { synchronized (mLock) { final String methodStr = "getEapCACert"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapCACert = mISupplicantStaNetwork.getEapCACert(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP CA certificate directory path set for this network. Result is stored in mEapCAPath. * * @return true if successful, false otherwise */ private boolean getEapCAPath() { synchronized (mLock) { final String methodStr = "getEapCAPath"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapCAPath = mISupplicantStaNetwork.getEapCAPath(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP Client certificate file path set for this network. * Result is stored in mEapClientCert. * * @return true if successful, false otherwise */ private boolean getEapClientCert() { synchronized (mLock) { final String methodStr = "getEapClientCert"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapClientCert = mISupplicantStaNetwork.getEapClientCert(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP private key Id set for this network. Result is stored in mEapPrivateKeyId. * * @return true if successful, false otherwise */ private boolean getEapPrivateKeyId() { synchronized (mLock) { final String methodStr = "getEapPrivateKeyId"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapPrivateKeyId = mISupplicantStaNetwork.getEapPrivateKeyId(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP subject match set for this network. Result is stored in mEapSubjectMatch. * * @return true if successful, false otherwise */ private boolean getEapSubjectMatch() { synchronized (mLock) { final String methodStr = "getEapSubjectMatch"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapSubjectMatch = mISupplicantStaNetwork.getEapSubjectMatch(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP Alt subject match set for this network. Result is stored in mEapAltSubjectMatch. * * @return true if successful, false otherwise */ private boolean getEapAltSubjectMatch() { synchronized (mLock) { final String methodStr = "getEapAltSubjectMatch"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapAltSubjectMatch = mISupplicantStaNetwork.getEapAltSubjectMatch(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get whether EAP Open SSL Engine is enabled for this network. Result is stored in mEapEngine. * * @return true if successful, false otherwise */ private boolean getEapEngine() { synchronized (mLock) { final String methodStr = "getEapEngine"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapEngine = mISupplicantStaNetwork.getEapEngine(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP Open SSL Engine ID set for this network. Result is stored in mEapEngineID. * * @return true if successful, false otherwise */ private boolean getEapEngineId() { synchronized (mLock) { final String methodStr = "getEapEngineId"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapEngineID = mISupplicantStaNetwork.getEapEngineId(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get EAP Domain suffix match set for this network. Result is stored in mEapDomainSuffixMatch. * * @return true if successful, false otherwise */ private boolean getEapDomainSuffixMatch() { synchronized (mLock) { final String methodStr = "getEapDomainSuffixMatch"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mEapDomainSuffixMatch = mISupplicantStaNetwork.getEapDomainSuffixMatch(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get ID string set for this network. Network identifier string for external scripts. * Result is stored in mIdStr. * * @return true if successful, false otherwise */ private boolean getIdStr() { synchronized (mLock) { final String methodStr = "getIdStr"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mIdStr = mISupplicantStaNetwork.getIdStr(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Enable the network for connection purposes. * * This must trigger a connection to the network if: * a) |noConnect| is false, and * b) This is the only network configured, and * c) Is visible in the current scan results. * * @param noConnect Only enable the network, don't trigger a connect. * @return true if successful, false otherwise */ public boolean enable(boolean noConnect) { synchronized (mLock) { final String methodStr = "enable"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.enable(noConnect); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Disable the network for connection purposes. * This must trigger a disconnection from the network, if currently * connected to this one. * * @return true if successful, false otherwise */ public boolean disable() { synchronized (mLock) { final String methodStr = "disable"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.disable(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Trigger a connection to this network. * * @return true if it succeeds, false otherwise. */ public boolean select() { synchronized (mLock) { final String methodStr = "select"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.select(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Send GSM auth response. * * @param paramsStr Response params as a string. * @return true if succeeds, false otherwise. */ public boolean sendNetworkEapSimGsmAuthResponse(String paramsStr) { synchronized (mLock) { try { Matcher match = GSM_AUTH_RESPONSE_PARAMS_PATTERN.matcher(paramsStr); ArrayList<NetworkResponseEapSimGsmAuthParams> params = new ArrayList<>(); while (match.find()) { if (match.groupCount() != 2) { Log.e(TAG, "Malformed gsm auth response params: " + paramsStr); return false; } NetworkResponseEapSimGsmAuthParams param = new NetworkResponseEapSimGsmAuthParams(); param.kc = new byte[8]; param.sres = new byte[4]; byte[] kc = NativeUtil.hexStringToByteArray(match.group(1)); if (kc == null || kc.length != param.kc.length) { Log.e(TAG, "Invalid kc value: " + match.group(1)); return false; } byte[] sres = NativeUtil.hexStringToByteArray(match.group(2)); if (sres == null || sres.length != param.sres.length) { Log.e(TAG, "Invalid sres value: " + match.group(2)); return false; } System.arraycopy(kc, 0, param.kc, 0, param.kc.length); System.arraycopy(sres, 0, param.sres, 0, param.sres.length); params.add(param); } // The number of kc/sres pairs can either be 2 or 3 depending on the request. if (params.size() > 3 || params.size() < 2) { Log.e(TAG, "Malformed gsm auth response params: " + paramsStr); return false; } NetworkResponseEapSimGsmAuthParams[] paramsArr = new NetworkResponseEapSimGsmAuthParams[params.size()]; for (int i = 0; i < params.size(); i++) { paramsArr[i] = params.get(i); } return sendNetworkEapSimGsmAuthResponse(paramsArr); } catch (IllegalArgumentException e) { Log.e(TAG, "Illegal argument " + paramsStr, e); return false; } } } private boolean sendNetworkEapSimGsmAuthResponse( NetworkResponseEapSimGsmAuthParams[] params) { synchronized (mLock) { final String methodStr = "sendNetworkEapSimGsmAuthResponse"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.sendNetworkEapSimGsmAuthResponse(params); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Send GSM auth failure. * * @return true if successful, false otherwise */ public boolean sendNetworkEapSimGsmAuthFailure() { synchronized (mLock) { final String methodStr = "sendNetworkEapSimGsmAuthFailure"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.sendNetworkEapSimGsmAuthFailure(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Send UMTS auth response. * * @param paramsStr Response params as a string. * @return true if succeeds, false otherwise. */ public boolean sendNetworkEapSimUmtsAuthResponse(String paramsStr) { synchronized (mLock) { try { Matcher match = UMTS_AUTH_RESPONSE_PARAMS_PATTERN.matcher(paramsStr); if (!match.find() || match.groupCount() != 3) { Log.e(TAG, "Malformed umts auth response params: " + paramsStr); return false; } NetworkResponseEapSimUmtsAuthParams params = new NetworkResponseEapSimUmtsAuthParams(); params.ik = new byte[16]; params.ck = new byte[16]; byte[] ik = NativeUtil.hexStringToByteArray(match.group(1)); if (ik == null || ik.length != params.ik.length) { Log.e(TAG, "Invalid ik value: " + match.group(1)); return false; } byte[] ck = NativeUtil.hexStringToByteArray(match.group(2)); if (ck == null || ck.length != params.ck.length) { Log.e(TAG, "Invalid ck value: " + match.group(2)); return false; } byte[] res = NativeUtil.hexStringToByteArray(match.group(3)); if (res == null || res.length == 0) { Log.e(TAG, "Invalid res value: " + match.group(3)); return false; } params.res = new byte[res.length]; System.arraycopy(ik, 0, params.ik, 0, params.ik.length); System.arraycopy(ck, 0, params.ck, 0, params.ck.length); System.arraycopy(res, 0, params.res, 0, params.res.length); return sendNetworkEapSimUmtsAuthResponse(params); } catch (IllegalArgumentException e) { Log.e(TAG, "Illegal argument " + paramsStr, e); return false; } } } private boolean sendNetworkEapSimUmtsAuthResponse( NetworkResponseEapSimUmtsAuthParams params) { synchronized (mLock) { final String methodStr = "sendNetworkEapSimUmtsAuthResponse"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.sendNetworkEapSimUmtsAuthResponse(params); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Send UMTS auts response. * * @param paramsStr Response params as a string. * @return true if succeeds, false otherwise. */ public boolean sendNetworkEapSimUmtsAutsResponse(String paramsStr) { synchronized (mLock) { try { Matcher match = UMTS_AUTS_RESPONSE_PARAMS_PATTERN.matcher(paramsStr); if (!match.find() || match.groupCount() != 1) { Log.e(TAG, "Malformed umts auts response params: " + paramsStr); return false; } byte[] auts = NativeUtil.hexStringToByteArray(match.group(1)); if (auts == null || auts.length != 14) { Log.e(TAG, "Invalid auts value: " + match.group(1)); return false; } return sendNetworkEapSimUmtsAutsResponse(auts); } catch (IllegalArgumentException e) { Log.e(TAG, "Illegal argument " + paramsStr, e); return false; } } } private boolean sendNetworkEapSimUmtsAutsResponse(byte[/* 14 */] auts) { synchronized (mLock) { final String methodStr = "sendNetworkEapSimUmtsAutsResponse"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.sendNetworkEapSimUmtsAutsResponse(auts); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Send UMTS auth failure. * * @return true if successful, false otherwise */ public boolean sendNetworkEapSimUmtsAuthFailure() { synchronized (mLock) { final String methodStr = "sendNetworkEapSimUmtsAuthFailure"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.sendNetworkEapSimUmtsAuthFailure(); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Send eap identity response. * * @param identityStr identity used for EAP-Identity * @param encryptedIdentityStr encrypted identity used for EAP-AKA/EAP-SIM * @return true if succeeds, false otherwise. */ public boolean sendNetworkEapIdentityResponse(String identityStr, String encryptedIdentityStr) { synchronized (mLock) { try { byte[] unencryptedIdentity = NativeUtil.stringToByteArray(identityStr); byte[] encryptedIdentity = new byte[0]; if (!TextUtils.isEmpty(encryptedIdentityStr)) { encryptedIdentity = NativeUtil.stringToByteArray(encryptedIdentityStr); } return sendNetworkEapIdentityResponse(unencryptedIdentity, encryptedIdentity); } catch (IllegalArgumentException e) { Log.e(TAG, "Illegal argument " + identityStr + "," + encryptedIdentityStr, e); return false; } } } private boolean sendNetworkEapIdentityResponse(byte[] unencryptedIdentity, byte[] encryptedIdentity) { synchronized (mLock) { final String methodStr = "sendNetworkEapIdentityResponse"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.sendNetworkEapIdentityResponse( unencryptedIdentity, encryptedIdentity); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set OCSP (Online Certificate Status Protocol) type for this network. * * @param ocsp value to set. * @return true if successful, false otherwise */ private boolean setOcsp(@WifiEnterpriseConfig.Ocsp int ocsp) { synchronized (mLock) { final String methodStr = "setOcsp"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } int halOcspValue = OcspType.NONE; switch (ocsp) { case WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS: halOcspValue = OcspType.REQUEST_CERT_STATUS; break; case WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS: halOcspValue = OcspType.REQUIRE_CERT_STATUS; break; case WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS: halOcspValue = OcspType.REQUIRE_ALL_CERTS_STATUS; break; } try { mISupplicantStaNetwork.setOcsp(halOcspValue); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Get OCSP (Online Certificate Status Protocol) type for this network. Value stored in mOcsp. * * @return true if successful, false otherwise */ private boolean getOcsp() { synchronized (mLock) { final String methodStr = "getOcsp"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { int halOcspValue = mISupplicantStaNetwork.getOcsp(); mOcsp = WifiEnterpriseConfig.OCSP_NONE; switch (halOcspValue) { case OcspType.REQUEST_CERT_STATUS: mOcsp = WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS; break; case OcspType.REQUIRE_CERT_STATUS: mOcsp = WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS; break; case OcspType.REQUIRE_ALL_CERTS_STATUS: mOcsp = WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS; break; default: Log.e(TAG, "Invalid HAL OCSP value " + halOcspValue); break; } return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Add a pairwise master key (PMK) into supplicant PMK cache. * * @param serializedEntry is serialized PMK cache entry, the content is * opaque for the framework and depends on the native implementation. * @return true if successful, false otherwise */ public boolean setPmkCache(byte[] serializedEntry) { synchronized (mLock) { final String methodStr = "setPmkCache"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setPmkCache(serializedEntry); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Set SAE H2E (Hash-to-Element) mode. * * @param mode SAE H2E supporting mode. * @return true if successful, false otherwise */ private boolean setSaeH2eMode(byte mode) { synchronized (mLock) { final String methodStr = "setSaeH2eMode"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork.setSaeH2eMode(mode); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } /** * Retrieve the NFC token for this network. * * @return Hex string corresponding to the NFC token or null for failure. */ public String getWpsNfcConfigurationToken() { synchronized (mLock) { byte[] token = getWpsNfcConfigurationTokenInternal(); if (token == null) { return null; } return NativeUtil.hexStringFromByteArray(token); } } private byte[] getWpsNfcConfigurationTokenInternal() { synchronized (mLock) { final String methodStr = "getWpsNfcConfigurationToken"; if (!checkStaNetworkAndLogFailure(methodStr)) { return null; } try { return mISupplicantStaNetwork.getWpsNfcConfigurationToken(); } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return null; } } private String getTag() { synchronized (mLock) { return TAG + "[" + mIfaceName + "]"; } } /** * Helper function to log callbacks. */ protected void logCallback(final String methodStr) { synchronized (mLock) { if (mVerboseLoggingEnabled) { Log.d(TAG, "ISupplicantStaNetworkCallback." + methodStr + " received"); } } } /** * Returns false if mISupplicantStaNetwork is null, and logs failure containing methodStr */ private boolean checkStaNetworkAndLogFailure(final String methodStr) { synchronized (mLock) { if (mISupplicantStaNetwork == null) { Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaNetwork is null"); return false; } return true; } } private void handleRemoteException(RemoteException e, String methodStr) { synchronized (mLock) { mISupplicantStaNetwork = null; Log.e(TAG, "ISupplicantStaNetwork." + methodStr + " failed with remote exception: ", e); } } private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { synchronized (mLock) { Log.e(TAG, "ISupplicantStaNetwork." + methodStr + " failed with " + "service specific exception: ", e); } } /** * Adds FT flags for networks if the device supports it. */ private BitSet addFastTransitionFlags(BitSet keyManagementFlags) { synchronized (mLock) { if (!mContext.getResources().getBoolean( R.bool.config_wifi_fast_bss_transition_enabled)) { return keyManagementFlags; } BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { modifiedFlags.set(WifiConfiguration.KeyMgmt.FT_PSK); } if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { modifiedFlags.set(WifiConfiguration.KeyMgmt.FT_EAP); } return modifiedFlags; } } /** * Removes FT flags for networks if the device supports it. */ private BitSet removeFastTransitionFlags(BitSet keyManagementFlags) { synchronized (mLock) { BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); modifiedFlags.clear(WifiConfiguration.KeyMgmt.FT_PSK); modifiedFlags.clear(WifiConfiguration.KeyMgmt.FT_EAP); return modifiedFlags; } } /** * Adds SHA256 key management flags for networks. */ private BitSet addSha256KeyMgmtFlags(BitSet keyManagementFlags) { synchronized (mLock) { BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { modifiedFlags.set(WifiConfiguration.KeyMgmt.WPA_PSK_SHA256); } if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_EAP)) { modifiedFlags.set(WifiConfiguration.KeyMgmt.WPA_EAP_SHA256); } return modifiedFlags; } } /** * Removes SHA256 key management flags for networks. */ private BitSet removeSha256KeyMgmtFlags(BitSet keyManagementFlags) { synchronized (mLock) { BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); modifiedFlags.clear(WifiConfiguration.KeyMgmt.WPA_PSK_SHA256); modifiedFlags.clear(WifiConfiguration.KeyMgmt.WPA_EAP_SHA256); return modifiedFlags; } } /** * Adds both PSK and SAE AKM if auto-upgrade offload is supported. */ private BitSet addPskSaeUpgradableTypeFlagsIfSupported( WifiConfiguration config, BitSet keyManagementFlags) { synchronized (mLock) { if (!config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK) || !config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK).isEnabled() || !mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()) { return keyManagementFlags; } BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); modifiedFlags.set(WifiConfiguration.KeyMgmt.WPA_PSK); modifiedFlags.set(WifiConfiguration.KeyMgmt.SAE); return modifiedFlags; } } /** * Removes SAE AKM when PSK and SAE AKM are both set, it only happens when * auto-upgrade offload is supported. */ private BitSet removePskSaeUpgradableTypeFlags(BitSet keyManagementFlags) { if (!keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_PSK) || !keyManagementFlags.get(WifiConfiguration.KeyMgmt.SAE)) { return keyManagementFlags; } BitSet modifiedFlags = (BitSet) keyManagementFlags.clone(); modifiedFlags.clear(WifiConfiguration.KeyMgmt.SAE); return modifiedFlags; } /** * Creates the JSON encoded network extra using the map of string key, value pairs. */ public static String createNetworkExtra(Map<String, String> values) { final String encoded; try { encoded = URLEncoder.encode(new JSONObject(values).toString(), "UTF-8"); } catch (NullPointerException e) { Log.e(TAG, "Unable to serialize networkExtra: " + e.toString()); return null; } catch (UnsupportedEncodingException e) { Log.e(TAG, "Unable to serialize networkExtra: " + e.toString()); return null; } return encoded; } /** * Parse the network extra JSON encoded string to a map of string key, value pairs. */ public static Map<String, String> parseNetworkExtra(String encoded) { if (TextUtils.isEmpty(encoded)) { return null; } try { // This method reads a JSON dictionary that was written by setNetworkExtra(). However, // on devices that upgraded from Marshmallow, it may encounter a legacy value instead - // an FQDN stored as a plain string. If such a value is encountered, the JSONObject // constructor will thrown a JSONException and the method will return null. final JSONObject json = new JSONObject(URLDecoder.decode(encoded, "UTF-8")); final Map<String, String> values = new HashMap<>(); final Iterator<?> it = json.keys(); while (it.hasNext()) { final String key = (String) it.next(); final Object value = json.get(key); if (value instanceof String) { values.put(key, (String) value); } } return values; } catch (UnsupportedEncodingException e) { Log.e(TAG, "Unable to deserialize networkExtra: " + e.toString()); return null; } catch (JSONException e) { // This is not necessarily an error. This exception will also occur if we encounter a // legacy FQDN stored as a plain string. We want to return null in this case as no JSON // dictionary of extras was found. return null; } } /** * Returns a big-endian representation of {@code rcoi} in an 3 or 5-element byte array. */ private static byte[] rcoiToByteArray(long rcoi) { // An RCOI is either 3- or 5-octet array, IEEE Std 802.11, section 9.4.1.31: Organization // Identifier field int arraySize = 3; rcoi &= 0xffffffffffL; if ((rcoi & 0xffff000000L) != 0) { // This is a 5-octet RCOI arraySize = 5; } byte[] result = new byte[arraySize]; for (int i = arraySize - 1; i >= 0; i--) { result[i] = (byte) (rcoi & 0xffL); rcoi >>= 8; } return result; } /** * Set the selected RCOI for this Passpoint network. * * @param selectedRcoi value to set. * @return true if successful, false otherwise */ private boolean setSelectedRcoi(long selectedRcoi) { if (selectedRcoi == 0) { // Nothing to set return true; } synchronized (mLock) { final String methodStr = "setSelectedRcoi"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { mISupplicantStaNetwork .setRoamingConsortiumSelection(rcoiToByteArray(selectedRcoi)); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } private int frameworkToAidlTlsVersion(@WifiEnterpriseConfig.TlsVersion int tlsVersion) { switch (tlsVersion) { case WifiEnterpriseConfig.TLS_V1_3: return TlsVersion.TLS_V1_3; case WifiEnterpriseConfig.TLS_V1_2: return TlsVersion.TLS_V1_2; case WifiEnterpriseConfig.TLS_V1_1: return TlsVersion.TLS_V1_1; case WifiEnterpriseConfig.TLS_V1_0: return TlsVersion.TLS_V1_0; default: Log.e(TAG, "Invalid TLS version: " + tlsVersion); return -1; } } /** * Enable TLS V1.3 in EAP Phase1 * * @param tlsVersion the TLS version * @return true if successful, false otherwise */ private boolean setMinimumTlsVersionEapPhase1Param( @WifiEnterpriseConfig.TlsVersion int tlsVersion) { synchronized (mLock) { final String methodStr = "setMinimumTlsVersionEapPhase1Param"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } int aidlTlsVersion = frameworkToAidlTlsVersion(tlsVersion); if (aidlTlsVersion < 0) { return false; } try { mISupplicantStaNetwork.setMinimumTlsVersionEapPhase1Param(aidlTlsVersion); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } private boolean enableStrictConservativePeerMode() { synchronized (mLock) { final String methodStr = "setStrictConservativePeerMode"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } // check AIDL version try { if (mISupplicantStaNetwork.getInterfaceVersion() < 2) { return false; } mISupplicantStaNetwork.setStrictConservativePeerMode(true); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } private boolean setVendorData(@NonNull List<OuiKeyedData> vendorData) { synchronized (mLock) { final String methodStr = "setVendorData"; if (!checkStaNetworkAndLogFailure(methodStr)) { return false; } try { if (!isServiceVersionIsAtLeast(3)) { return false; } if (vendorData == null || vendorData.isEmpty()) { return false; } mISupplicantStaNetwork.setVendorData( HalAidlUtil.frameworkToHalOuiKeyedDataList(vendorData)); return true; } catch (RemoteException e) { handleRemoteException(e, methodStr); } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } return false; } } }