blob: b1a7b012fe23a5925c45e2021c58b6789705a83e [file] [log] [blame]
/*
* 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.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.net.wifi.SecurityParams;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiManager;
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.server.wifi.util.ArrayUtils;
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.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 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;
SupplicantStaNetworkHalAidlImpl(ISupplicantStaNetwork staNetwork, String ifaceName,
Context context, WifiMonitor monitor, WifiGlobals wifiGlobals,
long advanceKeyMgmtFeature) {
mISupplicantStaNetwork = staNetwork;
mContext = context;
mIfaceName = ifaceName;
mWifiMonitor = monitor;
mWifiGlobals = wifiGlobals;
mAdvanceKeyMgmtFeatures = advanceKeyMgmtFeature;
}
/**
* Enable/Disable verbose logging.
*
* @param enable true to enable, false to disable.
*/
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 = NativeUtil.encodeSsid(NativeUtil.byteArrayToArrayList(mSsid));
} 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 = 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.
* @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;
}
/** SSID */
if (config.SSID != null) {
if (!setSsid(NativeUtil.byteArrayFromArrayList(
NativeUtil.decodeSsid(config.SSID)))) {
Log.e(TAG, "failed to set SSID: " + config.SSID);
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 = getOptimalPmfSettingForConfig(config,
securityParams.isRequirePmf());
/** 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 FT flags if supported.
BitSet keyMgmtMask = addFastTransitionFlags(allowedKeyManagement);
// Add SHA256 key management flags.
keyMgmtMask = addSha256KeyMgmtFlags(keyMgmtMask);
// Add upgradable type key management flags for PSK/SAE.
keyMgmtMask = addPskSaeUpgradableTypeFlagsIfSupported(config, keyMgmtMask);
if (!setKeyMgmt(wifiConfigurationToSupplicantKeyMgmtMask(keyMgmtMask))) {
Log.e(TAG, "failed to set Key Management");
return false;
}
// Check and set SuiteB configurations.
if (keyMgmtMask.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 (keyMgmtMask.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))) {
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 = 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;
}
/** 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 (securityParams.isSecurityType(WifiConfiguration.SECURITY_TYPE_SAE)) {
/* WPA3 case, field is SAE Password */
if (!setSaePassword(
NativeUtil.removeEnclosingQuotes(config.preSharedKey))) {
Log.e(TAG, "failed to set sae password");
return false;
}
} else {
if (!setPskPassphrase(
NativeUtil.removeEnclosingQuotes(config.preSharedKey))) {
Log.e(TAG, "failed to set psk passphrase");
return false;
}
}
} else {
if (securityParams.isSecurityType(WifiConfiguration.SECURITY_TYPE_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 (securityParams.isSecurityType(WifiConfiguration.SECURITY_TYPE_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;
}
}
// 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;
}
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;
}
}
return true;
}
}
/**
* 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) {
int mask = 0;
for (int bit = protoMask.nextSetBit(0); bit != -1;
bit = protoMask.nextSetBit(bit + 1)) {
switch (bit) {
case WifiConfiguration.Protocol.WPA:
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 supplicantMaskValueToWifiConfigurationBitSet(int supplicantMask,
int supplicantValue, BitSet bitset, int bitSetPosition) {
bitset.set(bitSetPosition, (supplicantMask & supplicantValue) == supplicantValue);
int modifiedSupplicantMask = supplicantMask & ~supplicantValue;
return modifiedSupplicantMask;
}
private static BitSet supplicantToWifiConfigurationKeyMgmtMask(int mask) {
BitSet bitset = new BitSet();
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.NONE, bitset,
WifiConfiguration.KeyMgmt.NONE);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.WPA_PSK, bitset,
WifiConfiguration.KeyMgmt.WPA_PSK);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.WPA_EAP, bitset,
WifiConfiguration.KeyMgmt.WPA_EAP);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.IEEE8021X, bitset,
WifiConfiguration.KeyMgmt.IEEE8021X);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.OSEN, bitset,
WifiConfiguration.KeyMgmt.OSEN);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.FT_PSK, bitset,
WifiConfiguration.KeyMgmt.FT_PSK);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.FT_EAP, bitset,
WifiConfiguration.KeyMgmt.FT_EAP);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.SAE,
bitset, WifiConfiguration.KeyMgmt.SAE);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.OWE,
bitset, WifiConfiguration.KeyMgmt.OWE);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.SUITE_B_192,
bitset, WifiConfiguration.KeyMgmt.SUITE_B_192);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.WPA_PSK_SHA256,
bitset, WifiConfiguration.KeyMgmt.WPA_PSK_SHA256);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.WPA_EAP_SHA256,
bitset, WifiConfiguration.KeyMgmt.WPA_EAP_SHA256);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.WAPI_PSK,
bitset, WifiConfiguration.KeyMgmt.WAPI_PSK);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.WAPI_CERT,
bitset, WifiConfiguration.KeyMgmt.WAPI_CERT);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.FILS_SHA256,
bitset, WifiConfiguration.KeyMgmt.FILS_SHA256);
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, KeyMgmtMask.FILS_SHA384,
bitset, WifiConfiguration.KeyMgmt.FILS_SHA384);
if (mask != 0) {
throw new IllegalArgumentException(
"invalid key mgmt mask from supplicant: " + mask);
}
return bitset;
}
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;
}
}
/**
* 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;
}
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;
}
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;
}
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;
}
}
/**
* Update PMF requirement if auto-upgrade offload is supported.
*
* If SAE auto-upgrade offload is supported and this config enables
* both PSK and SAE, do not set PMF requirement to
* mandatory to allow the device to roam between PSK and SAE BSSes.
* wpa_supplicant will set PMF requirement to optional by default.
*/
private boolean getOptimalPmfSettingForConfig(WifiConfiguration config,
boolean isPmfRequiredFromSelectedSecurityParams) {
if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)
&& config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK).isEnabled()
&& config.isSecurityType(WifiConfiguration.SECURITY_TYPE_SAE)
&& config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE).isEnabled()
&& mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()) {
if (mVerboseLoggingEnabled) {
Log.d(TAG, "Keep optional PMF for SAE auto-upgrade offload.");
}
return false;
}
return isPmfRequiredFromSelectedSecurityParams;
}
/**
* 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;
}
}
}