summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunil Ravi <sunilravi@google.com>2020-02-21 19:00:28 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-02-21 19:00:28 +0000
commitaebc25210b0dc86e0b9051a2cfb1135971a89e5a (patch)
tree05e9dae780883b8fdb706f0a8e79c9c8c8b774cc
parentf17ae57eac419d42b290c9b8589693b6dcd387ae (diff)
parent853857e57a4595ab67345fc8a198bb7b06e2aa0b (diff)
Merge "STA: Add support to connect to FILS enabled APs"
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java533
-rw-r--r--service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java2
-rw-r--r--service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java48
-rw-r--r--service/java/com/android/server/wifi/SupplicantStaIfaceHal.java101
-rw-r--r--service/java/com/android/server/wifi/SupplicantStaNetworkHal.java47
-rw-r--r--service/java/com/android/server/wifi/WifiConfigurationUtil.java12
-rw-r--r--service/java/com/android/server/wifi/WifiMonitor.java14
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java20
-rw-r--r--service/java/com/android/server/wifi/util/InformationElementUtil.java12
-rw-r--r--service/java/com/android/server/wifi/util/ScanResultUtil.java16
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java220
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java235
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalTest.java40
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java19
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java29
-rw-r--r--tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java82
-rw-r--r--tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java40
17 files changed, 1295 insertions, 175 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 8a49d027f..3dfb0e190 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -18,6 +18,8 @@ package com.android.server.wifi;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
@@ -40,6 +42,7 @@ import android.net.DhcpResultsParcelable;
import android.net.InvalidPacketException;
import android.net.IpConfiguration;
import android.net.KeepalivePacketData;
+import android.net.Layer2PacketParcelable;
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.MatchAllNetworkSpecifier;
@@ -610,6 +613,8 @@ public class ClientModeImpl extends StateMachine {
private static final int CMD_SAVE_NETWORK = BASE + 259;
private static final int CMD_PKT_CNT_FETCH = BASE + 261;
+ /* Start connection to FILS AP*/
+ static final int CMD_START_FILS_CONNECTION = BASE + 262;
// For message logging.
private static final Class[] sMessageClasses = {
AsyncChannel.class, ClientModeImpl.class };
@@ -677,6 +682,14 @@ public class ClientModeImpl extends StateMachine {
/* Network is not connected, supplicant assoc+auth is not complete */
private State mDisconnectedState = new DisconnectedState();
+ /*
+ * FILS connection related variables.
+ */
+ /* To indicate to IpClient whether HLP IEs were included or not in assoc request */
+ private boolean mSentHLPs = false;
+ /* Tracks IpClient start state until (FILS_)NETWORK_CONNECTION_EVENT event */
+ private boolean mIpClientWithPreConnection = false;
+
/**
* One of {@link WifiManager#WIFI_STATE_DISABLED},
* {@link WifiManager#WIFI_STATE_DISABLING},
@@ -878,6 +891,8 @@ public class ClientModeImpl extends StateMachine {
getHandler());
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT,
getHandler());
+ mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.FILS_NETWORK_CONNECTION_EVENT,
+ getHandler());
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT,
getHandler());
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT,
@@ -1013,6 +1028,11 @@ public class ClientModeImpl extends StateMachine {
}
@Override
+ public void onPreconnectionStart(List<Layer2PacketParcelable> packets) {
+ sendMessage(CMD_START_FILS_CONNECTION, 0, 0, packets);
+ }
+
+ @Override
public void onQuit() {
mWaitForStopCv.open();
}
@@ -1027,11 +1047,23 @@ public class ClientModeImpl extends StateMachine {
}
private void stopIpClient() {
- /* Restore power save and suspend optimizations */
- handlePostDhcpSetup();
+ if (mVerboseLoggingEnabled) {
+ log("stopIpClient IpClientWithPreConnection: " + mIpClientWithPreConnection);
+ }
if (mIpClient != null) {
+ if (mIpClientWithPreConnection) {
+ mIpClient.notifyPreconnectionComplete(false);
+ }
mIpClient.stop();
}
+ mIpClientWithPreConnection = false;
+ mSentHLPs = false;
+ }
+
+ private void stopDhcpSetup() {
+ /* Restore power save and suspend optimizations */
+ handlePostDhcpSetup();
+ stopIpClient();
}
/**
@@ -1898,6 +1930,7 @@ public class ClientModeImpl extends StateMachine {
}
sb.append(" blacklist=" + Boolean.toString(mDidBlackListBSSID));
break;
+ case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
case WifiMonitor.NETWORK_CONNECTION_EVENT:
sb.append(" ");
sb.append(Integer.toString(msg.arg1));
@@ -2163,6 +2196,9 @@ public class ClientModeImpl extends StateMachine {
case WifiMonitor.NETWORK_CONNECTION_EVENT:
s = "NETWORK_CONNECTION_EVENT";
break;
+ case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
+ s = "FILS_NETWORK_CONNECTION_EVENT";
+ break;
case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
s = "NETWORK_DISCONNECTION_EVENT";
break;
@@ -2621,7 +2657,7 @@ public class ClientModeImpl extends StateMachine {
*/
private void handleNetworkDisconnect() {
if (mVerboseLoggingEnabled) {
- log("handleNetworkDisconnect: Stopping DHCP and clearing IP"
+ log("handleNetworkDisconnect:"
+ " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
+ " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
+ " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
@@ -2638,7 +2674,18 @@ public class ClientModeImpl extends StateMachine {
clearTargetBssid("handleNetworkDisconnect");
- stopIpClient();
+ // Don't stop DHCP if Fils connection is in progress.
+ if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID
+ && mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID
+ && mLastNetworkId != mTargetNetworkId && mIpClientWithPreConnection) {
+ if (mVerboseLoggingEnabled) {
+ log("handleNetworkDisconnect: Don't stop IpClient as fils connection in progress: "
+ + " mLastNetworkId: " + mLastNetworkId
+ + " mTargetNetworkId" + mTargetNetworkId);
+ }
+ } else {
+ stopDhcpSetup();
+ }
mWifiScoreReport.stopConnectedNetworkScorer();
/* Reset data structures */
@@ -2714,6 +2761,21 @@ public class ClientModeImpl extends StateMachine {
}
}
+ void addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets) {
+ List<Layer2PacketParcelable> mLayer2Packet = packets;
+ if ((mLayer2Packet != null) && (mLayer2Packet.size() > 0)) {
+ mWifiNative.flushAllHlp(mInterfaceName);
+
+ for (int j = 0; j < mLayer2Packet.size(); j++) {
+ byte [] bytes = mLayer2Packet.get(j).payload;
+ byte [] payloadBytes = Arrays.copyOfRange(bytes, 12, bytes.length);
+ MacAddress dstAddress = mLayer2Packet.get(j).dstMacAddress;
+
+ mWifiNative.addHlpReq(mInterfaceName, dstAddress, payloadBytes);
+ }
+ }
+ }
+
void handlePostDhcpSetup() {
/* Restore power save and suspend optimizations */
setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true);
@@ -3271,6 +3333,7 @@ public class ClientModeImpl extends StateMachine {
case CMD_RECONNECT:
case CMD_REASSOCIATE:
case WifiMonitor.NETWORK_CONNECTION_EVENT:
+ case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
@@ -3485,6 +3548,7 @@ public class ClientModeImpl extends StateMachine {
* Helper method to stop external services and clean up state from client mode.
*/
private void stopClientMode() {
+ handleNetworkDisconnect();
// exiting supplicant started state is now only applicable to client mode
mWifiDiagnostics.stopLogging(mInterfaceName);
@@ -3563,6 +3627,26 @@ public class ClientModeImpl extends StateMachine {
return mLastBssid;
}
+ void connectToNetwork(WifiConfiguration config) {
+ if ((config != null) && mWifiNative.connectToNetwork(mInterfaceName, config)) {
+ mWifiInjector.getWifiLastResortWatchdog().noteStartConnectTime();
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT, config);
+ mLastConnectAttemptTimestamp = mClock.getWallClockMillis();
+ mIsAutoRoaming = false;
+ if (getCurrentState() != mDisconnectedState) {
+ transitionTo(mDisconnectingState);
+ }
+ } else {
+ loge("CMD_START_CONNECT Failed to start connection to network " + config);
+ mTargetWifiConfiguration = null;
+ stopIpClient();
+ reportConnectionAttemptEnd(
+ WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED,
+ WifiMetricsProto.ConnectionEvent.HLF_NONE,
+ WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
+ }
+ }
+
class ConnectModeState extends State {
@Override
@@ -3631,6 +3715,7 @@ public class ClientModeImpl extends StateMachine {
WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN;
switch (message.what) {
case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
+ stopIpClient();
mWifiDiagnostics.captureBugReportData(
WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE);
mDidBlackListBSSID = false;
@@ -3668,6 +3753,7 @@ public class ClientModeImpl extends StateMachine {
}
break;
case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+ stopIpClient();
mWifiDiagnostics.captureBugReportData(
WifiDiagnostics.REPORT_REASON_AUTH_FAILURE);
int disableReason = WifiConfiguration.NetworkSelectionStatus
@@ -3848,6 +3934,7 @@ public class ClientModeImpl extends StateMachine {
netId = message.arg1;
int uid = message.arg2;
bssid = (String) message.obj;
+ mSentHLPs = false;
if (!hasConnectionRequests()) {
if (mNetworkAgent == null) {
@@ -3869,60 +3956,44 @@ public class ClientModeImpl extends StateMachine {
loge("CMD_START_CONNECT and no config, bail out...");
break;
}
+ mTargetNetworkId = netId;
// Update scorecard while there is still state from existing connection
int scanRssi = mWifiConfigManager.findScanRssi(netId, SCAN_RSSI_VALID_TIME_MS);
mWifiScoreCard.noteConnectionAttempt(mWifiInfo, scanRssi, config.SSID);
- mTargetNetworkId = netId;
- setTargetBssid(config, bssid);
mBssidBlocklistMonitor.updateFirmwareRoamingConfiguration(config.SSID);
+ updateWifiConfigOnStartConnection(config, bssid);
+
reportConnectionAttemptStart(config, mTargetRoamBSSID,
WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED);
- if (config.macRandomizationSetting
- == WifiConfiguration.RANDOMIZATION_PERSISTENT
- && isConnectedMacRandomizationEnabled()) {
- configureRandomizedMacAddress(config);
- } else {
- setCurrentMacToFactoryMac(config);
- }
String currentMacAddress = mWifiNative.getMacAddress(mInterfaceName);
mWifiInfo.setMacAddress(currentMacAddress);
Log.i(TAG, "Connecting with " + currentMacAddress + " as the mac address");
- if (config.enterpriseConfig != null
- && config.enterpriseConfig.isAuthenticationSimBased()
- && mTelephonyUtil.isImsiEncryptionInfoAvailable(
- mTelephonyUtil.getBestMatchSubscriptionId(config))
- && TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())) {
- String anonAtRealm = mTelephonyUtil
- .getAnonymousIdentityWith3GppRealm(config);
- // Use anonymous@<realm> when pseudonym is not available
- config.enterpriseConfig.setAnonymousIdentity(anonAtRealm);
- }
-
- if (isWpa3SaeUpgradeEnabled() && config.allowedKeyManagement.get(
- WifiConfiguration.KeyMgmt.WPA_PSK)) {
- config = upgradeToWpa3IfPossible(config);
- }
+ mTargetWifiConfiguration = config;
+ /* Check for FILS configuration again after updating the config */
+ if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256)
+ || config.allowedKeyManagement.get(
+ WifiConfiguration.KeyMgmt.FILS_SHA384)) {
- if (mWifiNative.connectToNetwork(mInterfaceName, config)) {
- mWifiInjector.getWifiLastResortWatchdog().noteStartConnectTime();
- mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT, config);
- mLastConnectAttemptTimestamp = mClock.getWallClockMillis();
- mTargetWifiConfiguration = config;
- mIsAutoRoaming = false;
- if (getCurrentState() != mDisconnectedState) {
- transitionTo(mDisconnectingState);
+ boolean isIpClientStarted = startIpClient(config, true);
+ if (isIpClientStarted) {
+ mIpClientWithPreConnection = true;
+ break;
}
- } else {
- loge("CMD_START_CONNECT Failed to start connection to network " + config);
- reportConnectionAttemptEnd(
- WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED,
- WifiMetricsProto.ConnectionEvent.HLF_NONE,
- WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
- break;
}
+ connectToNetwork(config);
+ break;
+ case CMD_START_FILS_CONNECTION:
+ List<Layer2PacketParcelable> packets;
+ packets = (List<Layer2PacketParcelable>) message.obj;
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Send HLP IEs to supplicant");
+ }
+ addLayer2PacketsToHlpReq(packets);
+ config = mTargetWifiConfiguration;
+ connectToNetwork(config);
break;
case CMD_CONNECT_NETWORK:
callbackIdentifier = message.arg2;
@@ -3993,6 +4064,8 @@ public class ClientModeImpl extends StateMachine {
}
handleStatus = NOT_HANDLED;
break;
+ case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
+ mSentHLPs = true;
case WifiMonitor.NETWORK_CONNECTION_EVENT:
if (mVerboseLoggingEnabled) log("Network connection established");
mLastNetworkId = message.arg1;
@@ -4166,6 +4239,14 @@ public class ClientModeImpl extends StateMachine {
final boolean enabled = (message.arg1 > 0);
mWifiNative.configureNeighborDiscoveryOffload(mInterfaceName, enabled);
break;
+ case CMD_PRE_DHCP_ACTION:
+ case CMD_PRE_DHCP_ACTION_COMPLETE:
+ case CMD_POST_DHCP_ACTION:
+ case CMD_IPV4_PROVISIONING_SUCCESS:
+ case CMD_IP_CONFIGURATION_SUCCESSFUL:
+ case CMD_IPV4_PROVISIONING_FAILURE:
+ handleStatus = handleL3MessagesWhenNotConnected(message);
+ break;
default:
handleStatus = NOT_HANDLED;
break;
@@ -4179,6 +4260,38 @@ public class ClientModeImpl extends StateMachine {
}
}
+ private boolean handleL3MessagesWhenNotConnected(Message message) {
+ boolean handleStatus = HANDLED;
+
+ if (!mIpClientWithPreConnection) {
+ return NOT_HANDLED;
+ }
+
+ switch (message.what) {
+ case CMD_PRE_DHCP_ACTION:
+ handlePreDhcpSetup();
+ break;
+ case CMD_PRE_DHCP_ACTION_COMPLETE:
+ if (mIpClient != null) {
+ mIpClient.completedPreDhcpAction();
+ }
+ break;
+ case CMD_IPV4_PROVISIONING_FAILURE:
+ stopDhcpSetup();
+ deferMessage(message);
+ break;
+ case CMD_POST_DHCP_ACTION:
+ case CMD_IPV4_PROVISIONING_SUCCESS:
+ case CMD_IP_CONFIGURATION_SUCCESSFUL:
+ deferMessage(message);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+
+ return handleStatus;
+ }
+
private WifiNetworkAgentSpecifier createNetworkAgentSpecifier(
@NonNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid) {
currentWifiConfiguration.BSSID = currentBssid;
@@ -4474,10 +4587,6 @@ public class ClientModeImpl extends StateMachine {
@Override
public void exit() {
- if (mIpClient != null) {
- mIpClient.stop();
- }
-
// This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState
// Bug: 15347363
// For paranoia's sake, call handleNetworkDisconnect
@@ -4490,9 +4599,6 @@ public class ClientModeImpl extends StateMachine {
sb.append(" ").append(mLastBssid);
}
}
- if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
- handleNetworkDisconnect();
- }
mCountryCode.setReadyForChange(true);
mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
mWifiStateTracker.updateState(WifiStateTracker.DISCONNECTED);
@@ -4600,6 +4706,7 @@ public class ClientModeImpl extends StateMachine {
}
break;
case WifiMonitor.NETWORK_CONNECTION_EVENT:
+ case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
mWifiInfo.setBSSID((String) message.obj);
mLastNetworkId = message.arg1;
mWifiInfo.setNetworkId(mLastNetworkId);
@@ -4826,83 +4933,13 @@ public class ClientModeImpl extends StateMachine {
class ObtainingIpState extends State {
@Override
public void enter() {
- final WifiConfiguration currentConfig = getCurrentWifiConfiguration();
- final boolean isUsingStaticIp =
- (currentConfig.getIpAssignment() == IpConfiguration.IpAssignment.STATIC);
- if (mVerboseLoggingEnabled) {
- final String key = currentConfig.getKey();
- log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId)
- + " " + key + " "
- + " roam=" + mIsAutoRoaming
- + " static=" + isUsingStaticIp);
- }
-
- sendNetworkChangeBroadcast(DetailedState.OBTAINING_IPADDR);
-
- // We must clear the config BSSID, as the wifi chipset may decide to roam
- // from this point on and having the BSSID specified in the network block would
- // cause the roam to fail and the device to disconnect.
- clearTargetBssid("ObtainingIpAddress");
-
- // Stop IpClient in case we're switching from DHCP to static
- // configuration or vice versa.
- //
- // When we transition from static configuration to DHCP in
- // particular, we must tell ConnectivityService that we're
- // disconnected, because DHCP might take a long time during which
- // connectivity APIs such as getActiveNetworkInfo should not return
- // CONNECTED.
- stopIpClient();
-
- if (mIpClient != null) {
- mIpClient.setHttpProxy(currentConfig.getHttpProxy());
- if (!TextUtils.isEmpty(mContext.getResources().getString(
- R.string.config_wifi_tcp_buffers))) {
- mIpClient.setTcpBufferSizes(mContext.getResources().getString(
- R.string.config_wifi_tcp_buffers));
- }
- }
-
- WifiConfiguration config = getCurrentWifiConfiguration();
- ScanDetailCache scanDetailCache =
- mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
- ScanResult scanResult = null;
- if (scanDetailCache != null && mLastBssid != null) {
- scanResult = scanDetailCache.getScanResult(mLastBssid);
- }
-
- final ProvisioningConfiguration prov;
- ProvisioningConfiguration.ScanResultInfo scanResultInfo = null;
- if (scanResult != null) {
- final List<ScanResultInfo.InformationElement> ies =
- new ArrayList<ScanResultInfo.InformationElement>();
- for (ScanResult.InformationElement ie : scanResult.getInformationElements()) {
- ScanResultInfo.InformationElement scanResultInfoIe =
- new ScanResultInfo.InformationElement(ie.getId(), ie.getBytes());
- ies.add(scanResultInfoIe);
- }
- scanResultInfo = new ProvisioningConfiguration.ScanResultInfo(scanResult.SSID, ies);
- }
-
- if (!isUsingStaticIp) {
- prov = new ProvisioningConfiguration.Builder()
- .withPreDhcpAction()
- .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName))
- .withNetwork(getCurrentNetwork())
- .withDisplayName(currentConfig.SSID)
- .withScanResultInfo(scanResultInfo)
- .build();
+ WifiConfiguration currentConfig = getCurrentWifiConfiguration();
+ if (mIpClientWithPreConnection && mIpClient != null) {
+ mIpClient.notifyPreconnectionComplete(mSentHLPs);
+ mIpClientWithPreConnection = false;
+ mSentHLPs = false;
} else {
- StaticIpConfiguration staticIpConfig = currentConfig.getStaticIpConfiguration();
- prov = new ProvisioningConfiguration.Builder()
- .withStaticConfiguration(staticIpConfig)
- .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName))
- .withNetwork(getCurrentNetwork())
- .withDisplayName(currentConfig.SSID)
- .build();
- }
- if (mIpClient != null) {
- mIpClient.startProvisioning(prov);
+ startIpClient(currentConfig, false);
}
// Get Link layer stats so as we get fresh tx packet counters
getWifiLinkLayerStats();
@@ -5441,6 +5478,7 @@ public class ClientModeImpl extends StateMachine {
mWifiNative.disconnect(mInterfaceName);
break;
case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+ stopIpClient();
if (message.arg2 == 15 /* FOURWAY_HANDSHAKE_TIMEOUT */) {
String bssid = (message.obj == null)
? mTargetRoamBSSID : (String) message.obj;
@@ -6068,8 +6106,70 @@ public class ClientModeImpl extends StateMachine {
}
}
- private WifiConfiguration upgradeToWpa3IfPossible(@NonNull WifiConfiguration config) {
- if (isWpa3SaeUpgradeOffloadEnabled()) {
+ /**
+ * @return true if this device supports FILS-SHA256
+ */
+ private boolean isFilsSha256Supported() {
+ return (mWifiNative.getSupportedFeatureSet(mInterfaceName) & WIFI_FEATURE_FILS_SHA256) != 0;
+ }
+
+ /**
+ * @return true if this device supports FILS-SHA384
+ */
+ private boolean isFilsSha384Supported() {
+ return (mWifiNative.getSupportedFeatureSet(mInterfaceName) & WIFI_FEATURE_FILS_SHA384) != 0;
+ }
+
+ /**
+ * Helper method to set the allowed key management schemes from
+ * scan result.
+ */
+ private void updateAllowedKeyManagementSchemesFromScanResult(
+ WifiConfiguration config, ScanResult scanResult) {
+ if (isFilsSha256Supported()
+ && ScanResultUtil.isScanResultForFilsSha256Network(scanResult)) {
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FILS_SHA256);
+ }
+ if (isFilsSha384Supported()
+ && ScanResultUtil.isScanResultForFilsSha384Network(scanResult)) {
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FILS_SHA384);
+ }
+ }
+ /**
+ * Update wifi configuration based on the matching scan result.
+ *
+ * @param config Wifi configuration object.
+ * @param scanResult Scan result matching the network.
+ */
+ private void updateWifiConfigFromMatchingScanResult(WifiConfiguration config,
+ ScanResult scanResult) {
+ updateAllowedKeyManagementSchemesFromScanResult(config, scanResult);
+ if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256)
+ || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA384)) {
+ config.enterpriseConfig.setFieldValue(WifiEnterpriseConfig.EAP_ERP, "1");
+ }
+ }
+
+ /**
+ * Update the wifi configuration before sending connect to
+ * supplicant/driver.
+ *
+ * @param config wifi configuration object.
+ * @param bssid BSSID to assocaite with.
+ */
+ void updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid) {
+ boolean canUpgradePskToSae = false;
+ boolean isFrameworkWpa3SaeUpgradePossible = false;
+ boolean isLegacyWpa2ApInScanResult = false;
+
+ setTargetBssid(config, bssid);
+
+ if (isWpa3SaeUpgradeEnabled() && config.allowedKeyManagement.get(
+ WifiConfiguration.KeyMgmt.WPA_PSK)) {
+ isFrameworkWpa3SaeUpgradePossible = true;
+ }
+
+ if (isFrameworkWpa3SaeUpgradePossible && isWpa3SaeUpgradeOffloadEnabled()) {
// Driver offload of upgrading legacy WPA/WPA2 connection to WPA3
if (mVerboseLoggingEnabled) {
Log.d(TAG, "Driver upgrade legacy WPA/WPA2 connection to WPA3");
@@ -6077,52 +6177,64 @@ public class ClientModeImpl extends StateMachine {
config.allowedAuthAlgorithms.clear();
// Note: KeyMgmt.WPA2_PSK is already enabled, enable SAE as well
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
- return config;
+ isFrameworkWpa3SaeUpgradePossible = false;
}
-
- boolean canUpgradePskToSae = false;
-
// Check if network selection selected a good WPA3 candidate AP for a WPA2
// saved network.
ScanResult scanResultCandidate = config.getNetworkSelectionStatus().getCandidate();
- if (scanResultCandidate != null) {
+ if (isFrameworkWpa3SaeUpgradePossible && scanResultCandidate != null) {
ScanResultMatchInfo scanResultMatchInfo = ScanResultMatchInfo
.fromScanResult(scanResultCandidate);
if ((scanResultMatchInfo.networkType == WifiConfiguration.SECURITY_TYPE_SAE)) {
canUpgradePskToSae = true;
} else {
// No SAE candidate
- return config;
+ isFrameworkWpa3SaeUpgradePossible = false;
}
}
- // Now check if there are any additional legacy WPA2 only APs in range.
+ /**
+ * Go through the matching scan results and update wifi config.
+ */
+ ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(config);
ScanRequestProxy scanRequestProxy = mWifiInjector.getScanRequestProxy();
- for (ScanResult scanResult : scanRequestProxy.getScanResults()) {
+ List<ScanResult> scanResults = scanRequestProxy.getScanResults();
+ for (ScanResult scanResult : scanResults) {
if (!config.SSID.equals(ScanResultUtil.createQuotedSSID(scanResult.SSID))) {
continue;
}
- if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
- && !ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
- // Found a legacy WPA2 AP in range. Do not upgrade the connection to WPA3 to
- // allow seamless roaming within the ESS.
- if (mVerboseLoggingEnabled) {
- Log.d(TAG, "Found legacy WPA2 AP, do not upgrade to WPA3");
+ if (isFrameworkWpa3SaeUpgradePossible && !isLegacyWpa2ApInScanResult) {
+ if (ScanResultUtil.isScanResultForPskNetwork(scanResult)
+ && !ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
+ // Found a legacy WPA2 AP in range. Do not upgrade the connection to WPA3 to
+ // allow seamless roaming within the ESS.
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Found legacy WPA2 AP, do not upgrade to WPA3");
+ }
+ isLegacyWpa2ApInScanResult = true;
+ canUpgradePskToSae = false;
+ }
+ if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)
+ && scanResultCandidate == null) {
+ // When the user manually selected a network from the Wi-Fi picker, evaluate
+ // if to upgrade based on the scan results. The most typical use case during
+ // the WPA3 transition mode is to have a WPA2/WPA3 AP in transition mode. In
+ // this case, we would like to upgrade the connection.
+ canUpgradePskToSae = true;
}
- canUpgradePskToSae = false;
- break;
}
- if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)
- && scanResultCandidate == null) {
- // When the user manually selected a network from the Wi-Fi picker, evaluate
- // if to upgrade based on the scan results. The most typical use case during
- // the WPA3 transition mode is to have a WPA2/WPA3 AP in transition mode. In
- // this case, we would like to upgrade the connection.
- canUpgradePskToSae = true;
+
+ ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanResult);
+ if (!key1.equals(key2)) {
+ continue;
}
+ updateWifiConfigFromMatchingScanResult(config, scanResult);
}
- if (canUpgradePskToSae) {
+ if (isFrameworkWpa3SaeUpgradePossible && canUpgradePskToSae
+ && !(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256)
+ || config.allowedKeyManagement.get(
+ WifiConfiguration.KeyMgmt.FILS_SHA384))) {
// Upgrade legacy WPA/WPA2 connection to WPA3
if (mVerboseLoggingEnabled) {
Log.d(TAG, "Upgrade legacy WPA/WPA2 connection to WPA3");
@@ -6130,6 +6242,121 @@ public class ClientModeImpl extends StateMachine {
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
}
- return config;
+ if (config.macRandomizationSetting
+ == WifiConfiguration.RANDOMIZATION_PERSISTENT
+ && isConnectedMacRandomizationEnabled()) {
+ configureRandomizedMacAddress(config);
+ } else {
+ setCurrentMacToFactoryMac(config);
+ }
+
+ if (config.enterpriseConfig != null
+ && config.enterpriseConfig.isAuthenticationSimBased()
+ && mTelephonyUtil.isImsiEncryptionInfoAvailable(
+ mTelephonyUtil.getBestMatchSubscriptionId(config))
+ && TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())) {
+ String anonAtRealm = mTelephonyUtil
+ .getAnonymousIdentityWith3GppRealm(config);
+ // Use anonymous@<realm> when pseudonym is not available
+ config.enterpriseConfig.setAnonymousIdentity(anonAtRealm);
+ }
}
+
+ private boolean startIpClient(WifiConfiguration config, boolean isFilsConnection) {
+ if (mIpClient == null) {
+ return false;
+ }
+
+ final boolean isUsingStaticIp =
+ (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC);
+ if (mVerboseLoggingEnabled) {
+ final String key = config.getKey();
+ log("startIpClient netId=" + Integer.toString(mLastNetworkId)
+ + " " + key + " "
+ + " roam=" + mIsAutoRoaming
+ + " static=" + isUsingStaticIp
+ + " isFilsConnection=" + isFilsConnection);
+ }
+
+ if (isFilsConnection) {
+ stopIpClient();
+ if (isUsingStaticIp) {
+ mWifiNative.flushAllHlp(mInterfaceName);
+ return false;
+ }
+ final ProvisioningConfiguration prov =
+ new ProvisioningConfiguration.Builder()
+ .withPreDhcpAction()
+ .withPreconnection()
+ .withApfCapabilities(
+ mWifiNative.getApfCapabilities(mInterfaceName))
+ .build();
+ mIpClient.startProvisioning(prov);
+ } else {
+ sendNetworkChangeBroadcast(DetailedState.OBTAINING_IPADDR);
+ // We must clear the config BSSID, as the wifi chipset may decide to roam
+ // from this point on and having the BSSID specified in the network block would
+ // cause the roam to fail and the device to disconnect.
+ clearTargetBssid("ObtainingIpAddress");
+
+ // Stop IpClient in case we're switching from DHCP to static
+ // configuration or vice versa.
+ //
+ // When we transition from static configuration to DHCP in
+ // particular, we must tell ConnectivityService that we're
+ // disconnected, because DHCP might take a long time during which
+ // connectivity APIs such as getActiveNetworkInfo should not return
+ // CONNECTED.
+ stopDhcpSetup();
+
+ mIpClient.setHttpProxy(config.getHttpProxy());
+ if (!TextUtils.isEmpty(mContext.getResources().getString(
+ R.string.config_wifi_tcp_buffers))) {
+ mIpClient.setTcpBufferSizes(mContext.getResources().getString(
+ R.string.config_wifi_tcp_buffers));
+ }
+
+ ScanDetailCache scanDetailCache =
+ mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
+ ScanResult scanResult = null;
+ if (scanDetailCache != null && mLastBssid != null) {
+ scanResult = scanDetailCache.getScanResult(mLastBssid);
+ }
+
+ final ProvisioningConfiguration prov;
+ ProvisioningConfiguration.ScanResultInfo scanResultInfo = null;
+ if (scanResult != null) {
+ final List<ScanResultInfo.InformationElement> ies =
+ new ArrayList<ScanResultInfo.InformationElement>();
+ for (ScanResult.InformationElement ie : scanResult.getInformationElements()) {
+ ScanResultInfo.InformationElement scanResultInfoIe =
+ new ScanResultInfo.InformationElement(ie.getId(), ie.getBytes());
+ ies.add(scanResultInfoIe);
+ }
+ scanResultInfo = new ProvisioningConfiguration.ScanResultInfo(scanResult.SSID, ies);
+ }
+
+ if (!isUsingStaticIp) {
+ prov = new ProvisioningConfiguration.Builder()
+ .withPreDhcpAction()
+ .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName))
+ .withNetwork(getCurrentNetwork())
+ .withDisplayName(config.SSID)
+ .withScanResultInfo(scanResultInfo)
+ .build();
+ } else {
+ StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration();
+ prov = new ProvisioningConfiguration.Builder()
+ .withStaticConfiguration(staticIpConfig)
+ .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName))
+ .withNetwork(getCurrentNetwork())
+ .withDisplayName(config.SSID)
+ .build();
+ }
+ mIpClient.startProvisioning(prov);
+ }
+
+ return true;
+ }
+
}
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java
index 3d333c849..2d78514e4 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java
@@ -70,7 +70,7 @@ abstract class SupplicantStaIfaceCallbackImpl extends ISupplicantStaIfaceCallbac
/**
* Converts the supplicant state received from HIDL to the equivalent framework state.
*/
- private static SupplicantState supplicantHidlStateToFrameworkState(int state) {
+ protected static SupplicantState supplicantHidlStateToFrameworkState(int state) {
switch (state) {
case ISupplicantStaIfaceCallback.State.DISCONNECTED:
return SupplicantState.DISCONNECTED;
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java
index f3d72dc24..463881bbd 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java
@@ -18,9 +18,13 @@ package com.android.server.wifi;
import android.annotation.NonNull;
import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
import android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback.BssTmData;
+import android.net.wifi.SupplicantState;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
import android.util.Log;
+import com.android.server.wifi.util.NativeUtil;
+
import java.util.ArrayList;
abstract class SupplicantStaIfaceCallbackV1_3Impl extends
@@ -29,7 +33,9 @@ abstract class SupplicantStaIfaceCallbackV1_3Impl extends
private final SupplicantStaIfaceHal mStaIfaceHal;
private final String mIfaceName;
private final WifiMonitor mWifiMonitor;
+ private final SupplicantStaIfaceHal.SupplicantStaIfaceHalCallback mCallbackV10;
private final SupplicantStaIfaceHal.SupplicantStaIfaceHalCallbackV1_2 mCallbackV12;
+ private boolean mStateIsFourwayV13 = false; // Used to help check for PSK password mismatch
SupplicantStaIfaceCallbackV1_3Impl(@NonNull SupplicantStaIfaceHal staIfaceHal,
@NonNull String ifaceName,
@@ -40,6 +46,7 @@ abstract class SupplicantStaIfaceCallbackV1_3Impl extends
// Create an older callback for function delegation,
// and it would cascadingly create older one.
mCallbackV12 = mStaIfaceHal.new SupplicantStaIfaceHalCallbackV1_2(mIfaceName);
+ mCallbackV10 = mStaIfaceHal.new SupplicantStaIfaceHalCallback(mIfaceName);
}
@Override
@@ -49,7 +56,9 @@ abstract class SupplicantStaIfaceCallbackV1_3Impl extends
@Override
public void onNetworkRemoved(int id) {
- mCallbackV12.onNetworkRemoved(id);
+ mStaIfaceHal.logCallback("onNetworkRemoved");
+ // Reset 4way handshake state since network has been removed.
+ mStateIsFourwayV13 = false;
}
@Override
@@ -86,7 +95,20 @@ abstract class SupplicantStaIfaceCallbackV1_3Impl extends
@Override
public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated,
int reasonCode) {
- mCallbackV12.onDisconnected(bssid, locallyGenerated, reasonCode);
+ mStaIfaceHal.logCallback("onDisconnected");
+ if (mStaIfaceHal.isVerboseLoggingEnabled()) {
+ Log.e(TAG, "onDisconnected 4way=" + mStateIsFourwayV13
+ + " locallyGenerated=" + locallyGenerated
+ + " reasonCode=" + reasonCode);
+ }
+ if (mStateIsFourwayV13
+ && (!locallyGenerated || reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS)) {
+ mWifiMonitor.broadcastAuthenticationFailureEvent(
+ mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1);
+ }
+ mWifiMonitor.broadcastNetworkDisconnectionEvent(
+ mIfaceName, locallyGenerated ? 1 : 0, reasonCode,
+ NativeUtil.macAddressFromByteArray(bssid));
}
@Override
@@ -333,7 +355,25 @@ abstract class SupplicantStaIfaceCallbackV1_3Impl extends
@Override
public void onStateChanged_1_3(int newState, byte[/* 6 */] bssid, int id,
ArrayList<Byte> ssid, boolean filsHlpSent) {
- mCallbackV12.onStateChanged(newState, bssid, id, ssid);
+ mStaIfaceHal.logCallback("onStateChanged_1_3");
+ SupplicantState newSupplicantState =
+ mCallbackV10.supplicantHidlStateToFrameworkState(newState);
+ WifiSsid wifiSsid =
+ WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid));
+ String bssidStr = NativeUtil.macAddressFromByteArray(bssid);
+ mStateIsFourwayV13 =
+ (newState == ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE);
+ if (newSupplicantState == SupplicantState.COMPLETED) {
+ if (filsHlpSent) {
+ mWifiMonitor.broadcastFilsNetworkConnectionEvent(
+ mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), bssidStr);
+ } else {
+ mWifiMonitor.broadcastNetworkConnectionEvent(
+ mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), bssidStr);
+ }
+ }
+ mWifiMonitor.broadcastSupplicantStateChangeEvent(
+ mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName),
+ wifiSsid, bssidStr, newSupplicantState);
}
-
}
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
index bf2472935..717d0d7b5 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
@@ -16,6 +16,8 @@
package com.android.server.wifi;
import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384;
import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO;
import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
@@ -2129,6 +2131,88 @@ public class SupplicantStaIfaceHal {
}
/**
+ * Flush all previously configured HLPs.
+ *
+ * @param ifaceName Name of the interface.
+ * @return true if request is sent successfully, false otherwise.
+ */
+ public boolean flushAllHlp(@NonNull String ifaceName) {
+ synchronized (mLock) {
+ final String methodStr = "filsHlpFlushRequest";
+ if (isV1_3()) {
+ ISupplicantStaIface iface =
+ checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
+ if (iface == null) {
+ return false;
+ }
+
+ // Get a v1.3 supplicant STA Interface
+ android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 =
+ getStaIfaceMockableV1_3(iface);
+
+ if (staIfaceV13 == null) {
+ Log.e(TAG, methodStr
+ + ": ISupplicantStaIface is null, cannot flushAllHlp");
+ return false;
+ }
+ try {
+ SupplicantStatus status = staIfaceV13.filsHlpFlushRequest();
+ return checkStatusAndLogFailure(status, methodStr);
+ } catch (RemoteException e) {
+ handleRemoteException(e, methodStr);
+ return false;
+ }
+ } else {
+ Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Set FILS HLP packet.
+ *
+ * @param ifaceName Name of the interface.
+ * @param dst Destination MAC address.
+ * @param hlpPacket Hlp Packet data in hex.
+ * @return true if request is sent successfully, false otherwise.
+ */
+ public boolean addHlpReq(@NonNull String ifaceName, byte [] dst, byte [] hlpPacket) {
+ synchronized (mLock) {
+ final String methodStr = "filsHlpAddRequest";
+ if (isV1_3()) {
+ ISupplicantStaIface iface =
+ checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
+ if (iface == null) {
+ return false;
+ }
+
+ // Get a v1.3 supplicant STA Interface
+ android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 =
+ getStaIfaceMockableV1_3(iface);
+
+ if (staIfaceV13 == null) {
+ Log.e(TAG, methodStr
+ + ": ISupplicantStaIface is null, cannot addHlpReq");
+ return false;
+ }
+ try {
+ ArrayList<Byte> payload = NativeUtil.byteArrayToArrayList(hlpPacket);
+ SupplicantStatus status = staIfaceV13.filsHlpAddRequest(dst, payload);
+ return checkStatusAndLogFailure(status, methodStr);
+ } catch (RemoteException e) {
+ handleRemoteException(e, methodStr);
+ return false;
+ }
+ } else {
+ Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
+ return false;
+ }
+ }
+ }
+
+
+ /**
* Start WPS pin registrar operation with the specified peer and pin.
*
* @param ifaceName Name of the interface.
@@ -2658,6 +2742,23 @@ public class SupplicantStaIfaceHal {
}
}
+ if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
+ .KeyMgmtMask.FILS_SHA256) != 0) {
+ advancedCapabilities |= WIFI_FEATURE_FILS_SHA256;
+
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, methodStr + ": FILS_SHA256 supported");
+ }
+ }
+ if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
+ .KeyMgmtMask.FILS_SHA384) != 0) {
+ advancedCapabilities |= WIFI_FEATURE_FILS_SHA384;
+
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, methodStr + ": FILS_SHA384 supported");
+ }
+ }
+
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": Capability flags = " + keyMgmtCapabilities);
}
diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java
index 02bda7e0f..f9ac13f52 100644
--- a/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java
+++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHal.java
@@ -384,7 +384,6 @@ public class SupplicantStaNetworkHal {
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)) {
@@ -721,6 +720,15 @@ public class SupplicantStaNetworkHal {
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;
}
@@ -799,6 +807,14 @@ public class SupplicantStaNetworkHal {
mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask
.WAPI_CERT;
break;
+ case WifiConfiguration.KeyMgmt.FILS_SHA256:
+ mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask
+ .FILS_SHA256;
+ break;
+ case WifiConfiguration.KeyMgmt.FILS_SHA384:
+ mask |= android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask
+ .FILS_SHA384;
+ break;
case WifiConfiguration.KeyMgmt.WPA2_PSK: // This should never happen
default:
throw new IllegalArgumentException(
@@ -1054,6 +1070,12 @@ public class SupplicantStaNetworkHal {
mask = supplicantMaskValueToWifiConfigurationBitSet(
mask, android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask
.WAPI_CERT, bitset, WifiConfiguration.KeyMgmt.WAPI_CERT);
+ mask = supplicantMaskValueToWifiConfigurationBitSet(
+ mask, android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask
+ .FILS_SHA256, bitset, WifiConfiguration.KeyMgmt.FILS_SHA256);
+ mask = supplicantMaskValueToWifiConfigurationBitSet(
+ mask, android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork.KeyMgmtMask
+ .FILS_SHA384, bitset, WifiConfiguration.KeyMgmt.FILS_SHA384);
if (mask != 0) {
throw new IllegalArgumentException(
"invalid key mgmt mask from supplicant: " + mask);
@@ -1925,6 +1947,29 @@ public class SupplicantStaNetworkHal {
}
/** See ISupplicantStaNetwork.hal for documentation */
+ private boolean setEapErp(boolean enable) {
+ synchronized (mLock) {
+ final String methodStr = "setEapErp";
+ if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
+ try {
+ android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
+ iSupplicantStaNetworkV13;
+
+ iSupplicantStaNetworkV13 = getV1_3StaNetwork();
+ if (iSupplicantStaNetworkV13 != null) {
+ /* Support for set ERP Requires HAL v1.3 or higher */
+ SupplicantStatus status = iSupplicantStaNetworkV13.setEapErp(enable);
+ return checkStatusAndLogFailure(status, methodStr);
+ } else {
+ return false;
+ }
+ } catch (RemoteException e) {
+ handleRemoteException(e, methodStr);
+ return false;
+ }
+ }
+ }
+ /** See ISupplicantStaNetwork.hal for documentation */
private boolean getSaePasswordId() {
synchronized (mLock) {
final String methodStr = "getSaePasswordId";
diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
index 72d8db21c..3ed456b01 100644
--- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java
+++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
@@ -496,8 +496,8 @@ public class WifiConfigurationUtil {
private static boolean validateKeyMgmt(BitSet keyMgmnt) {
if (keyMgmnt.cardinality() > 1) {
- if (keyMgmnt.cardinality() > 3) {
- Log.e(TAG, "validateKeyMgmt failed: cardinality > 3");
+ if (keyMgmnt.cardinality() > 4) {
+ Log.e(TAG, "validateKeyMgmt failed: cardinality > 4");
return false;
}
if (!keyMgmnt.get(WifiConfiguration.KeyMgmt.WPA_EAP)) {
@@ -509,9 +509,11 @@ public class WifiConfigurationUtil {
Log.e(TAG, "validateKeyMgmt failed: not PSK or 8021X");
return false;
}
- if (keyMgmnt.cardinality() == 3
- && !keyMgmnt.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) {
- Log.e(TAG, "validateKeyMgmt failed: not SUITE_B_192");
+ if (keyMgmnt.cardinality() == 4
+ && (!keyMgmnt.get(WifiConfiguration.KeyMgmt.SUITE_B_192)
+ && !keyMgmnt.get(WifiConfiguration.KeyMgmt.FILS_SHA256)
+ && !keyMgmnt.get(WifiConfiguration.KeyMgmt.FILS_SHA384))) {
+ Log.e(TAG, "validateKeyMgmt failed: neither SUITE_B_192 nor FILS");
return false;
}
}
diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java
index 2ca87921c..4e006a2fc 100644
--- a/service/java/com/android/server/wifi/WifiMonitor.java
+++ b/service/java/com/android/server/wifi/WifiMonitor.java
@@ -100,6 +100,9 @@ public class WifiMonitor {
/* MBO/OCE events */
public static final int MBO_OCE_BSS_TM_HANDLING_DONE = BASE + 71;
+ /* Fils network connection completed */
+ public static final int FILS_NETWORK_CONNECTION_EVENT = BASE + 62;
+
/* WPS config errrors */
private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12;
private static final int CONFIG_AUTH_FAILURE = 18;
@@ -504,6 +507,17 @@ public class WifiMonitor {
}
/**
+ * Broadcast the fils network connection event to all the handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param networkId ID of the network in wpa_supplicant.
+ * @param bssid BSSID of the access point.
+ */
+ public void broadcastFilsNetworkConnectionEvent(String iface, int networkId, String bssid) {
+ sendMessage(iface, FILS_NETWORK_CONNECTION_EVENT, networkId, 0, bssid);
+ }
+
+ /**
* Broadcast the network disconnection event to all the handlers registered for this event.
*
* @param iface Name of iface on which this occurred.
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index a80486016..0ec2c14aa 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -1985,6 +1985,26 @@ public class WifiNative {
}
/**
+ * Flush all previously configured HLPs.
+ *
+ * @return true if request is sent successfully, false otherwise.
+ */
+ public boolean flushAllHlp(@NonNull String ifaceName) {
+ return mSupplicantStaIfaceHal.flushAllHlp(ifaceName);
+ }
+
+ /**
+ * Set FILS HLP packet.
+ *
+ * @param dst Destination MAC address.
+ * @param hlpPacket Hlp Packet data in hex.
+ * @return true if request is sent successfully, false otherwise.
+ */
+ public boolean addHlpReq(@NonNull String ifaceName, MacAddress dst, byte [] hlpPacket) {
+ return mSupplicantStaIfaceHal.addHlpReq(ifaceName, dst.toByteArray(), hlpPacket);
+ }
+
+ /**
* Initiate TDLS discover and setup or teardown with the specified peer.
*
* @param ifaceName Name of the interface.
diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java
index b5bf82269..091707a7a 100644
--- a/service/java/com/android/server/wifi/util/InformationElementUtil.java
+++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java
@@ -914,6 +914,8 @@ public class InformationElementUtil {
private static final int RSN_AKM_OWE = 0x12ac0f00;
private static final int RSN_AKM_EAP_SUITE_B_192 = 0x0cac0f00;
private static final int RSN_OSEN = 0x019a6f50;
+ private static final int RSN_AKM_FILS_SHA256 = 0x0eac0f00;
+ private static final int RSN_AKM_FILS_SHA384 = 0x0fac0f00;
private static final int WPA_CIPHER_NONE = 0x00f25000;
private static final int WPA_CIPHER_TKIP = 0x02f25000;
@@ -1016,6 +1018,12 @@ public class InformationElementUtil {
case RSN_OSEN:
rsnKeyManagement.add(ScanResult.KEY_MGMT_OSEN);
break;
+ case RSN_AKM_FILS_SHA256:
+ rsnKeyManagement.add(ScanResult.KEY_MGMT_FILS_SHA256);
+ break;
+ case RSN_AKM_FILS_SHA384:
+ rsnKeyManagement.add(ScanResult.KEY_MGMT_FILS_SHA384);
+ break;
default:
// do nothing
break;
@@ -1294,6 +1302,10 @@ public class InformationElementUtil {
return "WAPI-PSK";
case ScanResult.KEY_MGMT_WAPI_CERT:
return "WAPI-CERT";
+ case ScanResult.KEY_MGMT_FILS_SHA256:
+ return "FILS-SHA256";
+ case ScanResult.KEY_MGMT_FILS_SHA384:
+ return "FILS-SHA384";
default:
return "?";
}
diff --git a/service/java/com/android/server/wifi/util/ScanResultUtil.java b/service/java/com/android/server/wifi/util/ScanResultUtil.java
index 2e9a00a6f..320490c0b 100644
--- a/service/java/com/android/server/wifi/util/ScanResultUtil.java
+++ b/service/java/com/android/server/wifi/util/ScanResultUtil.java
@@ -127,6 +127,22 @@ public class ScanResultUtil {
}
/**
+ * Helper method to check if the provided |scanResult| corresponds to FILS SHA256 network.
+ * This checks if the provided capabilities string contains FILS-SHA256 or not.
+ */
+ public static boolean isScanResultForFilsSha256Network(ScanResult scanResult) {
+ return scanResult.capabilities.contains("FILS-SHA256");
+ }
+
+ /**
+ * Helper method to check if the provided |scanResult| corresponds to FILS SHA384 network.
+ * This checks if the provided capabilities string contains FILS-SHA384 or not.
+ */
+ public static boolean isScanResultForFilsSha384Network(ScanResult scanResult) {
+ return scanResult.capabilities.contains("FILS-SHA384");
+ }
+
+ /**
* Helper method to check if the provided |scanResult| corresponds to an open network or not.
* This checks if the provided capabilities string does not contain either of WEP, PSK, SAE
* or EAP encryption types or not.
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index 087259370..a31247be0 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -60,6 +60,7 @@ import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
import android.net.ConnectivityManager;
import android.net.DhcpResultsParcelable;
import android.net.InetAddresses;
+import android.net.Layer2PacketParcelable;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MacAddress;
@@ -151,6 +152,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
@@ -343,6 +345,7 @@ public class ClientModeImplTest extends WifiBaseTest {
static final int sFreq = 2437;
static final int sFreq1 = 5240;
static final String WIFI_IFACE_NAME = "mockWlan";
+ static final String sFilsSsid = "FILS-AP";
ClientModeImpl mCmi;
HandlerThread mWifiCoreThread;
@@ -2690,10 +2693,9 @@ public class ClientModeImplTest extends WifiBaseTest {
when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
.thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
- WifiConfiguration config = mock(WifiConfiguration.class);
+ WifiConfiguration config = new WifiConfiguration();
config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
- when(config.getNetworkSelectionStatus())
- .thenReturn(new WifiConfiguration.NetworkSelectionStatus());
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
@@ -2720,10 +2722,9 @@ public class ClientModeImplTest extends WifiBaseTest {
assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
- WifiConfiguration config = mock(WifiConfiguration.class);
+ WifiConfiguration config = new WifiConfiguration();
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
- when(config.getNetworkSelectionStatus())
- .thenReturn(new WifiConfiguration.NetworkSelectionStatus());
when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
@@ -2767,11 +2768,10 @@ public class ClientModeImplTest extends WifiBaseTest {
assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
- WifiConfiguration config = mock(WifiConfiguration.class);
+ WifiConfiguration config = new WifiConfiguration();
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
config.setRandomizedMacAddress(MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS));
- when(config.getNetworkSelectionStatus())
- .thenReturn(new WifiConfiguration.NetworkSelectionStatus());
when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
@@ -3205,7 +3205,7 @@ public class ClientModeImplTest extends WifiBaseTest {
disconnect();
mLooper.dispatchAll();
- verify(mWifiScoreCard).resetConnectionState();
+ verify(mWifiScoreCard, times(1)).resetConnectionState();
verify(mWifiScoreCard, never()).noteWifiDisabled(any());
verify(mWifiHealthMonitor, never()).setWifiEnabled(false);
@@ -3213,7 +3213,7 @@ public class ClientModeImplTest extends WifiBaseTest {
mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED);
mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
mLooper.dispatchAll();
- verify(mWifiScoreCard).resetConnectionState();
+ verify(mWifiScoreCard, times(2)).resetConnectionState();
verify(mWifiHealthMonitor).setWifiEnabled(false);
}
@@ -4513,4 +4513,202 @@ public class ClientModeImplTest extends WifiBaseTest {
assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ));
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ);
}
+
+ /**
+ * Helper function for setting up fils test.
+ *
+ * @param isDriverSupportFils true if driver support fils.
+ * @return wifi configuration.
+ */
+ private WifiConfiguration setupFilsTest(boolean isDriverSupportFils) {
+ assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
+ assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
+
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+ config.SSID = ScanResultUtil.createQuotedSSID(sFilsSsid);
+ config.networkId = 1;
+ config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
+ config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
+
+ when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config);
+ if (isDriverSupportFils) {
+ when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
+ WifiManager.WIFI_FEATURE_FILS_SHA256 | WifiManager.WIFI_FEATURE_FILS_SHA384);
+ } else {
+ when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn((long) 0);
+ }
+
+ return config;
+ }
+
+ /**
+ * Helper function for setting up a scan result with FILS supported AP.
+ *
+ */
+ private void setupFilsEnabledApInScanResult() {
+ String caps = "[WPA2-EAP+EAP-SHA256+FILS-SHA256-CCMP]"
+ + "[RSN-EAP+EAP-SHA256+FILS-SHA256-CCMP][ESS]";
+ ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(sFilsSsid),
+ sFilsSsid, sBSSID, 1245, 0, caps, -78, 2412, 1025, 22, 33, 20, 0, 0, true);
+ ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
+ sFilsSsid.getBytes(StandardCharsets.UTF_8));
+ scanResult.informationElements = new ScanResult.InformationElement[]{ie};
+ List<ScanResult> scanResults = new ArrayList<>();
+ scanResults.add(scanResult);
+
+ when(mScanRequestProxy.getScanResults()).thenReturn(scanResults);
+ }
+
+
+ /**
+ * Helper function to send CMD_START_FILS_CONNECTION along with HLP IEs.
+ *
+ */
+ private void prepareFilsHlpPktAndSendStartConnect() {
+ Layer2PacketParcelable l2Packet = new Layer2PacketParcelable();
+ l2Packet.dstMacAddress = TEST_GLOBAL_MAC_ADDRESS;
+ l2Packet.payload = new byte[] {0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13,
+ 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x55, 0x66};
+ mCmi.sendMessage(ClientModeImpl.CMD_START_FILS_CONNECTION, 0, 0,
+ Collections.singletonList(l2Packet));
+ mLooper.dispatchAll();
+ }
+
+ /**
+ * Verifies that while connecting to AP, the logic looks into the scan result and
+ * looks for AP matching the network type and ssid and update the wificonfig with FILS
+ * AKM if supported.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFilsAKMUpdateBeforeConnect() throws Exception {
+ initializeAndAddNetworkAndVerifySuccess();
+ WifiConfiguration config = setupFilsTest(true);
+ setupFilsEnabledApInScanResult();
+
+ mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
+ mLooper.dispatchAll();
+
+ assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256));
+ verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
+ }
+
+ /**
+ * Verifies that while connecting to AP, framework updates the wifi config with
+ * FILS AKM only if underlying driver support FILS feature.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFilsAkmIsNotAddedinWifiConfigIfDriverDoesNotSupportFils() throws Exception {
+ initializeAndAddNetworkAndVerifySuccess();
+ WifiConfiguration config = setupFilsTest(false);
+ setupFilsEnabledApInScanResult();
+
+ mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
+ mLooper.dispatchAll();
+
+ assertFalse(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256));
+ verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
+ }
+
+
+ /**
+ * Verifies that the HLP (DHCP) packets are send to wpa_supplicant
+ * prior to Fils connection.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFilsHlpUpdateBeforeFilsConnection() throws Exception {
+ initializeAndAddNetworkAndVerifySuccess();
+ WifiConfiguration config = setupFilsTest(true);
+ setupFilsEnabledApInScanResult();
+
+ mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
+ mLooper.dispatchAll();
+
+ prepareFilsHlpPktAndSendStartConnect();
+
+ verify(mWifiNative).flushAllHlp(eq(WIFI_IFACE_NAME));
+ verify(mWifiNative).addHlpReq(eq(WIFI_IFACE_NAME), any(), any());
+ verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
+ }
+
+ /**
+ * Verifies that an association rejection in first FILS connect attempt doesn't block
+ * the second connection attempt.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFilsSecondConnectAttemptIsNotBLockedAfterAssocReject() throws Exception {
+ initializeAndAddNetworkAndVerifySuccess();
+ WifiConfiguration config = setupFilsTest(true);
+ setupFilsEnabledApInScanResult();
+
+ mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
+ mLooper.dispatchAll();
+
+ prepareFilsHlpPktAndSendStartConnect();
+
+ verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
+
+ mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, 2, sBSSID);
+ mLooper.dispatchAll();
+
+ mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
+ mLooper.dispatchAll();
+ prepareFilsHlpPktAndSendStartConnect();
+
+ verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
+ }
+
+ /**
+ * Verifies Fils connection.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFilsConnection() throws Exception {
+ initializeAndAddNetworkAndVerifySuccess();
+ WifiConfiguration config = setupFilsTest(true);
+ setupFilsEnabledApInScanResult();
+
+ mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
+ mLooper.dispatchAll();
+
+ prepareFilsHlpPktAndSendStartConnect();
+
+ mCmi.sendMessage(WifiMonitor.FILS_NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
+ mLooper.dispatchAll();
+
+ mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
+ new StateChangeResult(0, WifiSsid.createFromAsciiEncoded(sFilsSsid),
+ sBSSID, SupplicantState.COMPLETED));
+ mLooper.dispatchAll();
+
+ assertEquals("ObtainingIpState", getCurrentState().getName());
+
+ DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
+ dhcpResults.baseConfiguration = new StaticIpConfiguration();
+ dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
+ dhcpResults.baseConfiguration.ipAddress =
+ new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
+ dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
+ dhcpResults.leaseDuration = 3600;
+
+ injectDhcpSuccess(dhcpResults);
+ mLooper.dispatchAll();
+
+ WifiInfo wifiInfo = mCmi.getWifiInfo();
+ assertNotNull(wifiInfo);
+ assertEquals(sBSSID, wifiInfo.getBSSID());
+ assertTrue(WifiSsid.createFromAsciiEncoded(sFilsSsid).equals(wifiInfo.getWifiSsid()));
+ assertEquals("ConnectedState", getCurrentState().getName());
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
index 2278d0dfe..64c6e0794 100644
--- a/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
@@ -16,6 +16,8 @@
package com.android.server.wifi;
import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384;
import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO;
import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
@@ -1673,6 +1675,44 @@ public class SupplicantStaIfaceHalTest extends WifiBaseTest {
}
/**
+ * Test FILS SHA256 key management support.
+ */
+ @Test
+ public void testGetKeyMgmtCapabilitiesFilsSha256() throws Exception {
+ setupMocksForHalV1_3();
+
+ executeAndValidateInitializationSequenceV1_3();
+
+ doAnswer(new GetKeyMgmtCapabilities_1_3Answer(android.hardware.wifi.supplicant.V1_3
+ .ISupplicantStaNetwork.KeyMgmtMask.FILS_SHA256))
+ .when(mISupplicantStaIfaceMockV13).getKeyMgmtCapabilities_1_3(any(
+ android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
+ .getKeyMgmtCapabilities_1_3Callback.class));
+
+ assertEquals(WIFI_FEATURE_FILS_SHA256,
+ mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME));
+ }
+
+ /**
+ * Test FILS SHA384 key management support.
+ */
+ @Test
+ public void testGetKeyMgmtCapabilitiesFilsSha384() throws Exception {
+ setupMocksForHalV1_3();
+
+ executeAndValidateInitializationSequenceV1_3();
+
+ doAnswer(new GetKeyMgmtCapabilities_1_3Answer(android.hardware.wifi.supplicant.V1_3
+ .ISupplicantStaNetwork.KeyMgmtMask.FILS_SHA384))
+ .when(mISupplicantStaIfaceMockV13).getKeyMgmtCapabilities_1_3(any(
+ android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
+ .getKeyMgmtCapabilities_1_3Callback.class));
+
+ assertEquals(WIFI_FEATURE_FILS_SHA384,
+ mDut.getAdvancedKeyMgmtCapabilities(WLAN0_IFACE_NAME));
+ }
+
+ /**
* Test Easy Connect (DPP) calls return failure if hal version is less than 1_2
*/
@Test
@@ -2534,4 +2574,199 @@ public class SupplicantStaIfaceHalTest extends WifiBaseTest {
eq(WLAN0_IFACE_NAME), btmFrameDataCaptor.capture());
}
+ /**
+ * Tests the configuring of FILS HLP packet in supplicant.
+ */
+ @Test
+ public void testAddHlpReq() throws Exception {
+ byte[] dstAddr = {0x45, 0x23, 0x12, 0x12, 0x12, 0x45};
+ byte[] hlpPacket = {0x00, 0x01, 0x02, 0x03, 0x04, 0x12, 0x15, 0x34, 0x55, 0x12,
+ 0x12, 0x45, 0x23, 0x52, 0x32, 0x16, 0x15, 0x53, 0x62, 0x32, 0x32, 0x10};
+
+ setupMocksForHalV1_3();
+ when(mISupplicantStaIfaceMockV13.filsHlpAddRequest(any(byte[].class),
+ any(ArrayList.class))).thenReturn(mStatusSuccess);
+
+ // Fail before initialization is performed.
+ assertFalse(mDut.addHlpReq(WLAN0_IFACE_NAME, dstAddr, hlpPacket));
+ verify(mISupplicantStaIfaceMockV13, never()).filsHlpAddRequest(any(byte[].class),
+ any(ArrayList.class));
+
+ executeAndValidateInitializationSequenceV1_3();
+ assertNotNull(mISupplicantStaIfaceCallbackV13);
+
+ ArrayList<Byte> hlpPayload = NativeUtil.byteArrayToArrayList(hlpPacket);
+ assertTrue(mDut.addHlpReq(WLAN0_IFACE_NAME, dstAddr, hlpPacket));
+ verify(mISupplicantStaIfaceMockV13).filsHlpAddRequest(eq(dstAddr), eq(hlpPayload));
+ }
+
+ /**
+ * Tests the flushing of FILS HLP packet from supplicant.
+ */
+ @Test
+ public void testFlushAllHlp() throws Exception {
+
+ setupMocksForHalV1_3();
+ when(mISupplicantStaIfaceMockV13.filsHlpFlushRequest()).thenReturn(mStatusSuccess);
+
+ // Fail before initialization is performed.
+ assertFalse(mDut.flushAllHlp(WLAN0_IFACE_NAME));
+ verify(mISupplicantStaIfaceMockV13, never()).filsHlpFlushRequest();
+
+ executeAndValidateInitializationSequenceV1_3();
+ assertNotNull(mISupplicantStaIfaceCallbackV13);
+
+ assertTrue(mDut.flushAllHlp(WLAN0_IFACE_NAME));
+ verify(mISupplicantStaIfaceMockV13).filsHlpFlushRequest();
+ }
+
+ /**
+ * Tests the handling of state change V13 notification without
+ * any configured network.
+ */
+ @Test
+ public void testonStateChangedV13CallbackWithNoConfiguredNetwork() throws Exception {
+ setupMocksForHalV1_3();
+ executeAndValidateInitializationSequenceV1_3();
+ assertNotNull(mISupplicantStaIfaceCallbackV13);
+
+ mISupplicantStaIfaceCallbackV13.onStateChanged_1_3(
+ ISupplicantStaIfaceCallback.State.INACTIVE,
+ NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID,
+ NativeUtil.decodeSsid(SUPPLICANT_SSID), false);
+
+ // Can't compare WifiSsid instances because they lack an equals.
+ verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
+ eq(WLAN0_IFACE_NAME), eq(WifiConfiguration.INVALID_NETWORK_ID),
+ any(WifiSsid.class), eq(BSSID), eq(SupplicantState.INACTIVE));
+ }
+
+ /**
+ * Tests the handling of state change V13 notification to
+ * associated after configuring a network.
+ */
+ @Test
+ public void testStateChangeV13ToAssociatedCallback() throws Exception {
+ setupMocksForHalV1_3();
+ executeAndValidateInitializationSequenceV1_3();
+ int frameworkNetworkId = 6;
+ executeAndValidateConnectSequence(frameworkNetworkId, false);
+ assertNotNull(mISupplicantStaIfaceCallbackV13);
+
+ mISupplicantStaIfaceCallbackV13.onStateChanged_1_3(
+ ISupplicantStaIfaceCallback.State.ASSOCIATED,
+ NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID,
+ NativeUtil.decodeSsid(SUPPLICANT_SSID), false);
+
+ verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
+ eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId),
+ any(WifiSsid.class), eq(BSSID), eq(SupplicantState.ASSOCIATED));
+ }
+
+ /**
+ * Tests the handling of state change V13 notification to
+ * completed after configuring a network.
+ */
+ @Test
+ public void testStateChangeV13ToCompletedCallback() throws Exception {
+ InOrder wifiMonitorInOrder = inOrder(mWifiMonitor);
+ setupMocksForHalV1_3();
+ executeAndValidateInitializationSequenceV1_3();
+ assertNotNull(mISupplicantStaIfaceCallbackV13);
+ int frameworkNetworkId = 6;
+ executeAndValidateConnectSequence(frameworkNetworkId, false);
+
+ mISupplicantStaIfaceCallbackV13.onStateChanged_1_3(
+ ISupplicantStaIfaceCallback.State.COMPLETED,
+ NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID,
+ NativeUtil.decodeSsid(SUPPLICANT_SSID), false);
+
+ wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent(
+ eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(BSSID));
+ wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
+ eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId),
+ any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED));
+ }
+
+ /**
+ * Tests the handling of incorrect network passwords, edge case
+ * when onStateChanged_1_3() is used.
+ *
+ * If the network is removed during 4-way handshake, do not call it a password mismatch.
+ */
+ @Test
+ public void testNetworkRemovedDuring4wayWhenonStateChangedV13IsUsed() throws Exception {
+ executeAndValidateInitializationSequence();
+ assertNotNull(mISupplicantStaIfaceCallback);
+ setupMocksForHalV1_3();
+ executeAndValidateInitializationSequenceV1_3();
+ assertNotNull(mISupplicantStaIfaceCallbackV13);
+
+ int reasonCode = 3;
+
+ mISupplicantStaIfaceCallbackV13.onStateChanged_1_3(
+ ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE,
+ NativeUtil.macAddressToByteArray(BSSID),
+ SUPPLICANT_NETWORK_ID,
+ NativeUtil.decodeSsid(SUPPLICANT_SSID), false);
+ mISupplicantStaIfaceCallback.onNetworkRemoved(SUPPLICANT_NETWORK_ID);
+ mISupplicantStaIfaceCallback.onDisconnected(
+ NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
+ verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(),
+ anyInt());
+ }
+
+ /**
+ * Tests the handling of incorrect network passwords when
+ * onStateChanged_1_3() is used, edge case.
+ *
+ * If the disconnect reason is "IE in 4way differs", do not call it a password mismatch.
+ */
+ @Test
+ public void testIeDiffersWhenonStateChangedV13IsUsed() throws Exception {
+ executeAndValidateInitializationSequence();
+ assertNotNull(mISupplicantStaIfaceCallback);
+ setupMocksForHalV1_3();
+ executeAndValidateInitializationSequenceV1_3();
+ assertNotNull(mISupplicantStaIfaceCallbackV13);
+
+ int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.IE_IN_4WAY_DIFFERS;
+
+ mISupplicantStaIfaceCallbackV13.onStateChanged_1_3(
+ ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE,
+ NativeUtil.macAddressToByteArray(BSSID),
+ SUPPLICANT_NETWORK_ID,
+ NativeUtil.decodeSsid(SUPPLICANT_SSID), false);
+ mISupplicantStaIfaceCallback.onDisconnected(
+ NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
+ verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(),
+ anyInt());
+ }
+
+ /**
+ * Tests the handling of state change V13 notification to
+ * completed (with FILS HLP IE sent) after configuring a
+ * network.
+ */
+ @Test
+ public void testStateChangeV13WithFilsHlpIESentToCompletedCallback() throws Exception {
+ InOrder wifiMonitorInOrder = inOrder(mWifiMonitor);
+ setupMocksForHalV1_3();
+ executeAndValidateInitializationSequenceV1_3();
+ assertNotNull(mISupplicantStaIfaceCallbackV13);
+ int frameworkNetworkId = 6;
+ executeAndValidateConnectSequence(frameworkNetworkId, false);
+
+ mISupplicantStaIfaceCallbackV13.onStateChanged_1_3(
+ ISupplicantStaIfaceCallback.State.COMPLETED,
+ NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID,
+ NativeUtil.decodeSsid(SUPPLICANT_SSID), true);
+
+ wifiMonitorInOrder.verify(mWifiMonitor).broadcastFilsNetworkConnectionEvent(
+ eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(BSSID));
+ wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
+ eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId),
+ any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED));
+ }
+
}
diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalTest.java
index 949b8659f..616472c10 100644
--- a/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalTest.java
@@ -387,6 +387,29 @@ public class SupplicantStaNetworkHalTest extends WifiBaseTest {
}
/**
+ * Tests the saving/loading of WifiConfiguration with FILS AKM
+ * to wpa_supplicant.
+ */
+ @Test
+ public void testTLSWifiEnterpriseConfigWithFilsEapErp() throws Exception {
+ // Now expose the V1.3 ISupplicantStaNetwork
+ createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_3);
+
+ WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork();
+ config.enterpriseConfig =
+ WifiConfigurationTestUtil.createTLSWifiEnterpriseConfigWithNonePhase2();
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.FILS_SHA256);
+ config.enterpriseConfig.setFieldValue(WifiEnterpriseConfig.EAP_ERP, "1");
+ testWifiConfigurationSaveLoad(config);
+ // Check the supplicant variables to ensure that we have added the FILS AKM.
+ assertTrue((mSupplicantVariables.keyMgmtMask & android.hardware.wifi.supplicant.V1_3
+ .ISupplicantStaNetwork.KeyMgmtMask.FILS_SHA256)
+ == android.hardware.wifi.supplicant.V1_3
+ .ISupplicantStaNetwork.KeyMgmtMask.FILS_SHA256);
+ verify(mISupplicantStaNetworkV13).setEapErp(eq(true));
+ }
+
+ /**
* Tests the saving of WifiConfiguration to wpa_supplicant.
*/
@Test
@@ -974,6 +997,14 @@ public class SupplicantStaNetworkHalTest extends WifiBaseTest {
Integer.parseInt(oppKeyCaching) == 1 ? true : false,
mSupplicantVariables.eapProactiveKeyCaching);
}
+ // There is no getter for this one, so check the supplicant variable.
+ String eapErp =
+ config.enterpriseConfig.getFieldValue(WifiEnterpriseConfig.EAP_ERP);
+ if (!TextUtils.isEmpty(eapErp)) {
+ assertEquals(
+ Integer.parseInt(eapErp) == 1 ? true : false,
+ mSupplicantVariables.eapErp);
+ }
}
/**
@@ -1695,6 +1726,14 @@ public class SupplicantStaNetworkHalTest extends WifiBaseTest {
}).when(mISupplicantStaNetworkV13)
.getWapiCertSuite(any(android.hardware.wifi.supplicant.V1_3
.ISupplicantStaNetwork.getWapiCertSuiteCallback.class));
+
+ /** EAP ERP */
+ doAnswer(new AnswerWithArguments() {
+ public SupplicantStatus answer(boolean enable) throws RemoteException {
+ mSupplicantVariables.eapErp = enable;
+ return mStatusSuccess;
+ }
+ }).when(mISupplicantStaNetworkV13).setEapErp(any(boolean.class));
}
private SupplicantStatus createSupplicantStatus(int code) {
@@ -1761,5 +1800,6 @@ public class SupplicantStaNetworkHalTest extends WifiBaseTest {
public int ocsp;
public ArrayList<Byte> serializedPmkCache;
public String wapiCertSuite;
+ public boolean eapErp;
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
index 40ca9b9a2..6652e9b0c 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
@@ -602,4 +602,23 @@ public class WifiMonitorTest extends WifiBaseTest {
assertEquals(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, messageCaptor.getValue().what);
}
+ /**
+ * Broadcast fils network connection test.
+ */
+ @Test
+ public void testBroadcastFilsNetworkConnectionEvent() {
+ mWifiMonitor.registerHandler(
+ WLAN_IFACE_NAME, WifiMonitor.FILS_NETWORK_CONNECTION_EVENT, mHandlerSpy);
+ int networkId = NETWORK_ID;
+ String bssid = BSSID;
+ mWifiMonitor.broadcastFilsNetworkConnectionEvent(WLAN_IFACE_NAME, networkId, bssid);
+ mLooper.dispatchAll();
+
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mHandlerSpy).handleMessage(messageCaptor.capture());
+ assertEquals(WifiMonitor.FILS_NETWORK_CONNECTION_EVENT, messageCaptor.getValue().what);
+ assertEquals(networkId, messageCaptor.getValue().arg1);
+ assertEquals(bssid, (String) messageCaptor.getValue().obj);
+ }
+
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
index 728af073a..ae8f1229e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
@@ -1033,4 +1033,33 @@ public class WifiNativeTest extends WifiBaseTest {
WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN);
verify(mWificondControl, never()).sendMgmtFrame(any(), any(), anyInt(), any(), any());
}
+
+ /**
+ * Tests that WifiNative#addHlpReq() calls
+ * SupplicantStaIfaceHal#addHlpReq()
+ */
+ @Test
+ public void testaddHlpReq() {
+ byte[] hlpPacket = {
+ 0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b,
+ 0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09,
+ (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66,
+ 0x00, 0x00
+ };
+ mWifiNative.addHlpReq(WIFI_IFACE_NAME, TEST_MAC_ADDRESS, hlpPacket);
+
+ verify(mStaIfaceHal).addHlpReq(eq(WIFI_IFACE_NAME),
+ eq(TEST_MAC_ADDRESS.toByteArray()), eq(hlpPacket));
+ }
+
+ /**
+ * Tests that WifiNative#flushAllHlp() calls
+ * SupplicantStaIfaceHal#flushAllHlp()
+ */
+ @Test
+ public void testflushAllHlp() {
+ mWifiNative.flushAllHlp(WIFI_IFACE_NAME);
+
+ verify(mStaIfaceHal).flushAllHlp(eq(WIFI_IFACE_NAME));
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
index 4b98a59d9..874da7043 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
@@ -627,6 +627,88 @@ public class InformationElementUtilTest extends WifiBaseTest {
}
/**
+ * Test Capabilities.generateCapabilitiesString() with RSN IE,
+ * CCMP and FILS SHA256. Expect the function to return a string
+ * with the proper security information.
+ */
+ @Test
+ public void buildCapabilities_rsnFilsSha256Element() {
+ InformationElement ieRsn = new InformationElement();
+ ieRsn.id = InformationElement.EID_RSN;
+ ieRsn.bytes = new byte[] {
+ // RSNE Version (0x0001)
+ (byte) 0x01, (byte) 0x00,
+ // Group cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of AKMs (3)
+ (byte) 0x03, (byte) 0x00,
+ // WPA AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01,
+ // WPA SHA256 AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x05,
+ // FILS SHA256 AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x0E,
+ // RSN capabilities
+ (byte) 0x00, (byte) 0x00 };
+
+ InformationElement[] ies = new InformationElement[] { ieRsn };
+ int beaconCap = 0x1 << 4;
+
+ InformationElementUtil.Capabilities capabilities =
+ new InformationElementUtil.Capabilities();
+ capabilities.from(ies, beaconCap, true);
+ String result = capabilities.generateCapabilitiesString();
+
+ assertEquals("[WPA2-EAP+EAP-SHA256+FILS-SHA256-CCMP][RSN-EAP+EAP-SHA256+FILS-SHA256-CCMP]",
+ result);
+ }
+
+ /**
+ * Test Capabilities.generateCapabilitiesString() with RSN IE,
+ * CCMP and FILS SHA384. Expect the function to return a string
+ * with the proper security information.
+ */
+ @Test
+ public void buildCapabilities_rsnFilsSha384Element() {
+ InformationElement ieRsn = new InformationElement();
+ ieRsn.id = InformationElement.EID_RSN;
+ ieRsn.bytes = new byte[] {
+ // RSNE Version (0x0001)
+ (byte) 0x01, (byte) 0x00,
+ // Group cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of AKMs (3)
+ (byte) 0x03, (byte) 0x00,
+ // WPA AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01,
+ // WPA SHA256 AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x05,
+ // FILS SHA384 AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x0F,
+ // RSN capabilities
+ (byte) 0x00, (byte) 0x00 };
+
+ InformationElement[] ies = new InformationElement[] { ieRsn };
+ int beaconCap = 0x1 << 4;
+
+ InformationElementUtil.Capabilities capabilities =
+ new InformationElementUtil.Capabilities();
+ capabilities.from(ies, beaconCap, true);
+ String result = capabilities.generateCapabilitiesString();
+
+ assertEquals("[WPA2-EAP+EAP-SHA256+FILS-SHA384-CCMP][RSN-EAP+EAP-SHA256+FILS-SHA384-CCMP]",
+ result);
+ }
+
+ /**
* Test Capabilities.generateCapabilitiesString() with both RSN and WPA1 IE which are malformed.
* Expect the function to return a string with empty key management & pairswise cipher security
* information.
diff --git a/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java
index bc5f880b4..0f69316e7 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java
@@ -203,6 +203,46 @@ public class ScanResultUtilTest extends WifiBaseTest {
assertFalse(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input));
}
+ /**
+ * Test that provided network supports FILS SHA256 AKM.
+ */
+ @Test
+ public void testFilsSha256AkmSupportedNetwork() {
+ final String ssid = "FILS-AP";
+ String caps = "[WPA2-EAP+EAP-SHA256+FILS-SHA256-CCMP]"
+ + "[RSN-EAP+EAP-SHA256+FILS-SHA256-CCMP][ESS]";
+
+ ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid,
+ "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0,
+ 0, true);
+
+ input.informationElements = new InformationElement[] {
+ createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8))
+ };
+
+ assertTrue(ScanResultUtil.isScanResultForFilsSha256Network(input));
+ }
+
+ /**
+ * Test that provided network supports FILS SHA384 AKM.
+ */
+ @Test
+ public void testFilsSha384AkmSupportedNetwork() {
+ final String ssid = "FILS-AP";
+ String caps = "[WPA2-EAP+EAP-SHA384+FILS-SHA384-CCMP]"
+ + "[RSN-EAP+EAP-SHA384+FILS-SHA384-CCMP][ESS]";
+
+ ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid,
+ "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0,
+ 0, true);
+
+ input.informationElements = new InformationElement[] {
+ createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8))
+ };
+
+ assertTrue(ScanResultUtil.isScanResultForFilsSha384Network(input));
+ }
+
private static InformationElement createIE(int id, byte[] bytes) {
InformationElement ie = new InformationElement();
ie.id = id;