diff options
3 files changed, 113 insertions, 19 deletions
diff --git a/service/java/com/android/server/wifi/WificondControl.java b/service/java/com/android/server/wifi/WificondControl.java index c58c56471..bd756f643 100644 --- a/service/java/com/android/server/wifi/WificondControl.java +++ b/service/java/com/android/server/wifi/WificondControl.java @@ -16,6 +16,8 @@ package com.android.server.wifi; +import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; + import android.annotation.NonNull; import android.app.AlarmManager; import android.net.wifi.IApInterface; @@ -88,6 +90,7 @@ public class WificondControl implements IBinder.DeathRecipient { private AlarmManager mAlarmManager; private Handler mEventHandler; private Clock mClock; + private WifiNative mWifiNative = null; // Cached wificond binder handlers. private IWificond mWificond; @@ -102,6 +105,8 @@ public class WificondControl implements IBinder.DeathRecipient { * Ensures that no more than one sendMgmtFrame operation runs concurrently. */ private AtomicBoolean mSendMgmtFrameInProgress = new AtomicBoolean(false); + private boolean mIsEnhancedOpenSupportedInitialized = false; + private boolean mIsEnhancedOpenSupported; private class ScanEventHandler extends IScanEvent.Stub { private String mIfaceName; @@ -591,7 +596,7 @@ public class WificondControl implements IBinder.DeathRecipient { InformationElementUtil.parseInformationElements(result.infoElement); InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, result.capability); + capabilities.from(ies, result.capability, isEnhancedOpenSupported()); String flags = capabilities.generateCapabilitiesString(); NetworkDetail networkDetail; try { @@ -918,4 +923,34 @@ public class WificondControl implements IBinder.DeathRecipient { mApInterfaceListeners.clear(); mSendMgmtFrameInProgress.set(false); } + + /** + * Check if OWE (Enhanced Open) is supported on the device + * + * @return true if OWE is supported + */ + private boolean isEnhancedOpenSupported() { + if (mIsEnhancedOpenSupportedInitialized) { + return mIsEnhancedOpenSupported; + } + + // WifiNative handle might be null, check this here + if (mWifiNative == null) { + mWifiNative = mWifiInjector.getWifiNative(); + if (mWifiNative == null) { + return false; + } + } + + String iface = mWifiNative.getClientInterfaceName(); + if (iface == null) { + // Client interface might not be initialized during boot or Wi-Fi off + return false; + } + + mIsEnhancedOpenSupportedInitialized = true; + mIsEnhancedOpenSupported = (mWifiNative.getSupportedFeatureSet(iface) + & WIFI_FEATURE_OWE) != 0; + return mIsEnhancedOpenSupported; + } } diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java index f75d57eff..994cd2d65 100644 --- a/service/java/com/android/server/wifi/util/InformationElementUtil.java +++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java @@ -665,9 +665,10 @@ public class InformationElementUtil { * * @param ies -- Information Element array * @param beaconCap -- 16-bit Beacon Capability Information field + * @param isOweSupported -- Boolean flag to indicate if OWE is supported by the device */ - public void from(InformationElement[] ies, BitSet beaconCap) { + public void from(InformationElement[] ies, BitSet beaconCap, boolean isOweSupported) { protocol = new ArrayList<Integer>(); keyManagement = new ArrayList<ArrayList<Integer>>(); groupCipher = new ArrayList<Integer>(); @@ -691,7 +692,7 @@ public class InformationElementUtil { // TODO(b/62134557): parse WPS IE to provide finer granularity information. isWPS = true; } - if (isOweElement(ie)) { + if (isOweSupported && isOweElement(ie)) { /* From RFC 8110: Once the client and AP have finished 802.11 association, they then complete the Diffie-Hellman key exchange and create a Pairwise Master Key (PMK) and its associated identifier, PMKID [IEEE802.11]. @@ -700,8 +701,12 @@ public class InformationElementUtil { handshake generates a Key-Encrypting Key (KEK), a Key-Confirmation Key (KCK), and a Message Integrity Code (MIC) to use for protection of the frames that define the 4-way handshake. - */ + We check if OWE is supported here because we are adding the OWE + capabilities to the Open BSS. Non-supporting devices need to see this + open network and ignore this element. Supporting devices need to hide + the Open BSS of OWE in transition mode and connect to the Hidden one. + */ protocol.add(ScanResult.PROTOCOL_RSN); groupCipher.add(ScanResult.CIPHER_CCMP); ArrayList<Integer> owePairwiseCipher = new ArrayList<>(); 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 cbb728644..46830f3f5 100644 --- a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java +++ b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java @@ -265,7 +265,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); assertEquals("[RSN-PSK-CCMP+TKIP]", result); @@ -291,7 +291,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); assertEquals("[RSN]", result); @@ -319,7 +319,7 @@ public class InformationElementUtilTest { beaconCap.set(4); InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); assertEquals("[WPA-PSK-CCMP+TKIP]", result); @@ -343,7 +343,7 @@ public class InformationElementUtilTest { beaconCap.set(4); InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); assertEquals("[WPA]", result); @@ -381,7 +381,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); assertEquals("[WPA-PSK-CCMP+TKIP][RSN-PSK-CCMP+TKIP]", result); @@ -420,7 +420,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, true); String result = capabilities.generateCapabilitiesString(); assertEquals("[RSN-PSK+SAE-CCMP]", result); @@ -459,7 +459,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, true); String result = capabilities.generateCapabilitiesString(); assertEquals("[RSN-SAE+FT/SAE-CCMP]", result); @@ -496,13 +496,67 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, true); String result = capabilities.generateCapabilitiesString(); assertEquals("[RSN-OWE-CCMP]", result); } /** + * Test Capabilities.generateCapabilitiesString() with OWE IE. + * Expect the function to return a string with the proper security information. + */ + @Test + public void buildCapabilities_oweVsElementOweSupported() { + InformationElement ieOwe = new InformationElement(); + ieOwe.id = InformationElement.EID_VSA; + ieOwe.bytes = new byte[] { + // OWE vendor specific + (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x1C, + // OWE IE contains BSSID, SSID and channel of other BSS, but we don't parse it. + (byte) 0x00, (byte) 0x000, (byte) 0x00, (byte) 0x00 }; + + InformationElement[] ies = new InformationElement[] { ieOwe }; + + BitSet beaconCap = new BitSet(16); + beaconCap.set(0); + + InformationElementUtil.Capabilities capabilities = + new InformationElementUtil.Capabilities(); + capabilities.from(ies, beaconCap, true); + String result = capabilities.generateCapabilitiesString(); + + assertEquals("[RSN-OWE-CCMP][ESS]", result); + } + + /** + * Test Capabilities.generateCapabilitiesString() with OWE IE. + * Expect the function to return a string with the proper security information. + */ + @Test + public void buildCapabilities_oweVsElementOweNotSupported() { + InformationElement ieOwe = new InformationElement(); + ieOwe.id = InformationElement.EID_VSA; + ieOwe.bytes = new byte[] { + // OWE vendor specific + (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x1C, + // OWE IE contains BSSID, SSID and channel of other BSS, but we don't parse it. + (byte) 0x00, (byte) 0x000, (byte) 0x00, (byte) 0x00 }; + + InformationElement[] ies = new InformationElement[] { ieOwe }; + + BitSet beaconCap = new BitSet(16); + beaconCap.set(0); + + InformationElementUtil.Capabilities capabilities = + new InformationElementUtil.Capabilities(); + capabilities.from(ies, beaconCap, false); + String result = capabilities.generateCapabilitiesString(); + + assertEquals("[ESS]", result); + } + + /** * Test Capabilities.generateCapabilitiesString() with RSN IE, GCMP-256 and SUITE_B_192. * Expect the function to return a string with the proper security information. */ @@ -533,7 +587,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); assertEquals("[RSN-EAP_SUITE_B_192-GCMP-256]", result); @@ -565,7 +619,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); assertEquals("[WPA][RSN]", result); @@ -599,7 +653,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); assertEquals("[WPA-PSK-CCMP+TKIP][WPS]", result); @@ -627,7 +681,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); @@ -656,7 +710,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); @@ -684,7 +738,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); @@ -713,7 +767,7 @@ public class InformationElementUtilTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap); + capabilities.from(ies, beaconCap, false); String result = capabilities.generateCapabilitiesString(); |