summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorVamsi Krishna <quic_vamsin@quicinc.com>2019-12-13 11:02:27 +0530
committerSunil Ravi <sunilravi@google.com>2020-02-20 15:04:34 -0800
commit853857e57a4595ab67345fc8a198bb7b06e2aa0b (patch)
tree1d59c3027896e72544118862253cd3d1f3a6136f /service
parent40369495ec8f3fc06f655d3dd2ab07ae4844c130 (diff)
STA: Add support to connect to FILS enabled APs
Fast Initial Link Setup (FILS) feature defined in 802.11ai specifications provides means to make faster reconnections with APs within a realm using EAP-Reauthentication Protocol (ERP). When a STA connecting initially to an enterprise AP on which FILS is enabled, does full 802.1x EAP handshakes and generates ERP keys. The STA uses the ERP keys (until they are expired) in subsequent connections to the enterprise APs within same realm as that of the AP with which the STA has generated ERP keys to EAP-ERP process to make connection faster. The EAP-ERP request and EAP-ERP response frames will be exchanged via 802.11 authentication frames between STA and AP. More details of EAP-ERP can be found at https://tools.ietf.org/html/rfc6696 FILS specifications defines two AKM suites FILS-SHA256 and FILS-SHA384 for normal connection and two more AKM suites FILS-FT-SHA256 and FILS-FT-SHA384 for FT connections. The first connection without using ERP keys uses open auth algorithm and connects using full eap handshake and the subsequent connections with ERP keys uses FILS auth algorithm. DHCP with rapid commit optimizes the DHCP packet exchange. When using rapid commit feature, DHCP server responds with DHCP ACK packet when it receives DHCP discover packet. More details of DHCP with rapid commit can be found at https://tools.ietf.org/html/rfc4039. The DHCP discover and DHCP ACK packets can be sent with Association request frame and Association response frame using HLP feature defined in FILS protocol in order to get the IP address quickly. When connecting to a FILS AP, start the DHCP client withPreConnection option set to true before sending connect request to wpa_supplicant. DHCP client will form discover packet and sends it to Wi-Fi module, then the DHCP client moves to listen state to be able to receive and process DHCP ACK or DHCP Offer packets. After receiving DHCP discover packet from DHCP client, configure DHCP discover packet as HLP packet to wpa_supplicant and then issue connect request to wpa_supplicant with appropriate FILS AKM suite. The ERP config option also needs to be enabled so that wpa_supplicant generates ERP keys while connecting to FILS APs. If the STA is already connected to a different AP when wpa_supplicant receives the connect request to the FILS AP, wpa_supplicant disconnects with that AP before connecting to FILS AP and sends a disconnection event to frameworks. Do not stop IpClient when disconnection event is received if FILS connection is in progress, as the IpClient is started for ongoing FILS connection. If STA does not have ERP keys required for FILS connection or if the AP is rejecting the connection in FILS mode probably because of AP not having ERP keys, then STA will connect to FILS AP with open auth algorithm using full 802.1x EAP handshake. In these cases wpa_supplicant doesn't include HLP IEs in connect request. Wpa_supplicant notifies framework through connection event whether it sent HLP IEs to AP or not in the connection request. When HLP IEs are not sent in association request frame, abort pre-DHCP connection. When pre-DHCP connection is aborted, DHCP client transitions to dhcpInit state and sends DHCP discover packet to AP through data path. If STA has ERP keys, it will send the DHCP discover packet using HLP IEs in Association Request frame. AP may respond in three ways. 1. AP may not send any DHCP packet uisng HLP IEs in Association Response frame if the DHCP server doesn't send response within a time less than 802.11 mgmt. timeout. In this case, AP sends the DHCP packet as a data packet after sending out Association Response frame. 2. AP may send a DHCP ACK packet using HLP IEs in Association Response frame if the DHCP server supports DHCP with Rapid Commit feature and sends response within a time less than 802.11 mgmt. timeout. 3. AP may send a DHCP OFFER packet using HLP IEs in Association Response frame if the DHCP server doesn't support DHCP with Rapid Commit feature and sends response within a time less than 802.11 mgmt. timeout. Bug: 143259898 Test: atest. Test: Basic wifi sanity. Change-Id: Ib42eb5295fa2403d5a98ceddb15f501c130b61e5
Diffstat (limited to 'service')
-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
10 files changed, 641 insertions, 164 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 4b3732f22..86d799b41 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;
@@ -611,6 +614,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 };
@@ -678,6 +683,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();
}
/**
@@ -1897,6 +1929,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));
@@ -2162,6 +2195,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;
@@ -2620,7 +2656,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()
@@ -2637,7 +2673,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();
+ }
/* Reset data structures */
mWifiScoreReport.reset();
@@ -2712,6 +2759,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);
@@ -3269,6 +3331,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:
@@ -3482,6 +3545,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);
@@ -3558,6 +3622,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
@@ -3626,6 +3710,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;
@@ -3663,6 +3748,7 @@ public class ClientModeImpl extends StateMachine {
}
break;
case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+ stopIpClient();
mWifiDiagnostics.captureBugReportData(
WifiDiagnostics.REPORT_REASON_AUTH_FAILURE);
int disableReason = WifiConfiguration.NetworkSelectionStatus
@@ -3843,6 +3929,7 @@ public class ClientModeImpl extends StateMachine {
netId = message.arg1;
int uid = message.arg2;
bssid = (String) message.obj;
+ mSentHLPs = false;
if (!hasConnectionRequests()) {
if (mNetworkAgent == null) {
@@ -3864,60 +3951,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;
@@ -3988,6 +4059,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;
@@ -4161,6 +4234,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;
@@ -4174,6 +4255,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;
@@ -4468,10 +4581,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
@@ -4484,9 +4593,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);
@@ -4594,6 +4700,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);
@@ -4820,83 +4927,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();
@@ -5434,6 +5471,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;
@@ -6061,8 +6099,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");
@@ -6070,52 +6170,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");
@@ -6123,6 +6235,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 fb3459131..53be67d44 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 917f1f7a0..fd548fd40 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.