summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flags/wifi_flags.aconfig8
-rw-r--r--framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java27
-rw-r--r--service/ServiceWifiResources/res/values/config.xml7
-rw-r--r--service/ServiceWifiResources/res/values/overlayable.xml1
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java7
-rw-r--r--service/java/com/android/server/wifi/util/InformationElementUtil.java54
-rw-r--r--service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java21
-rw-r--r--service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java223
8 files changed, 334 insertions, 14 deletions
diff --git a/flags/wifi_flags.aconfig b/flags/wifi_flags.aconfig
index 7710231bff..93f6d076c5 100644
--- a/flags/wifi_flags.aconfig
+++ b/flags/wifi_flags.aconfig
@@ -127,3 +127,11 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "rsn_overriding"
+ namespace: "wifi"
+ description: "Wi-Fi Alliance RSN Overriding feature"
+ bug: "348669010"
+ is_fixed_read_only: true
+}
diff --git a/framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java b/framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java
index 4a485c06ab..5a51ac6e5f 100644
--- a/framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java
+++ b/framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java
@@ -363,6 +363,33 @@ public class ScanResultUtilTest {
}
/**
+ * Test that a network configured in WPA3-Compatibility mode is detected as WPA3-transition mode
+ */
+ @Test
+ public void testWPA3CompatibilityModeNetwork() {
+ final String ssid = "WPA3-Compatibility";
+ String caps = "[WPA2-PSK-CCMP][RSN-PSK-CCMP][RSN-SAE-CCMP][MFPC][RSNO]";
+
+ ScanResult input = new ScanResult.Builder(WifiSsid.fromUtf8Text(ssid),
+ "ab:cd:01:ef:45:89")
+ .setHessid(1245)
+ .setCaps(caps)
+ .setRssi(-78)
+ .setFrequency(2450)
+ .setTsf(1025)
+ .setDistanceCm(22)
+ .setDistanceSdCm(33)
+ .setIs80211McRTTResponder(true)
+ .build();
+
+ input.informationElements = new InformationElement[] {
+ createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8))
+ };
+
+ assertTrue(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input));
+ }
+
+ /**
* Test that a PSK network is not detected as transition mode
*/
@Test
diff --git a/service/ServiceWifiResources/res/values/config.xml b/service/ServiceWifiResources/res/values/config.xml
index cb76012876..454eb236fd 100644
--- a/service/ServiceWifiResources/res/values/config.xml
+++ b/service/ServiceWifiResources/res/values/config.xml
@@ -1363,4 +1363,11 @@
See also config_wifiDelayedSelectionCarrierIds.
-->
<integer translatable="false" name="config_wifiDelayedCarrierSelectionTimeMs">90000</integer>
+
+ <!-- Boolean indicating whether the device supports Wi-Fi Alliance WPA3 Specification
+ version 3.3 Section 14 - RSN Overriding.
+ Enabling this config allows framework to parse the RSNO IE and RSNO2 IE.
+ Only enable this flag if Supplicant and driver/firmware supports RSN Overriding. otherwise
+ the connection may fail or downgrade to WPA2 -->
+ <bool translatable="false" name ="config_wifiRsnOverridingEnabled">false</bool>
</resources>
diff --git a/service/ServiceWifiResources/res/values/overlayable.xml b/service/ServiceWifiResources/res/values/overlayable.xml
index e2cd626f8f..247797c2b2 100644
--- a/service/ServiceWifiResources/res/values/overlayable.xml
+++ b/service/ServiceWifiResources/res/values/overlayable.xml
@@ -348,6 +348,7 @@
<item type="bool" name="config_wifiWepAllowedControlSupported" />
<item type="array" name="config_wifiDelayedSelectionCarrierIds" />
<item type="integer" name="config_wifiDelayedCarrierSelectionTimeMs" />
+ <item type="bool" name="config_wifiRsnOverridingEnabled" />
<!-- Params from config.xml that can be overlayed -->
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 9ec97ee493..61ccf321b3 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -21,11 +21,12 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_NAN;
-import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P;
+import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA;
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES;
import static com.android.server.wifi.p2p.WifiP2pNative.P2P_IFACE_NAME;
import static com.android.server.wifi.p2p.WifiP2pNative.P2P_INTERFACE_PROPERTY;
+import static com.android.wifi.flags.Flags.rsnOverriding;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -134,6 +135,7 @@ public class WifiNative {
private NetdWrapper mNetdWrapper;
private boolean mVerboseLoggingEnabled = false;
private boolean mIsEnhancedOpenSupported = false;
+ @VisibleForTesting boolean mIsRsnOverridingSupported = false;
private final List<CoexUnsafeChannel> mCachedCoexUnsafeChannels = new ArrayList<>();
private int mCachedCoexRestrictions;
private CountryCodeChangeListenerInternal mCountryCodeChangeListener;
@@ -1557,6 +1559,8 @@ public class WifiNative {
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
updateSupportedBandForStaInternal(iface);
+ mIsRsnOverridingSupported = mContext.getResources().getBoolean(
+ R.bool.config_wifiRsnOverridingEnabled) && rsnOverriding();
mWifiVendorHal.enableStaChannelForPeerNetwork(mContext.getResources().getBoolean(
R.bool.config_wifiEnableStaIndoorChannelForPeerNetwork),
@@ -2090,6 +2094,7 @@ public class WifiNative {
ies,
result.getCapabilities(),
mIsEnhancedOpenSupported,
+ mIsRsnOverridingSupported,
result.getFrequencyMhz(),
mUnknownAkmMap);
String flags = capabilities.generateCapabilitiesString();
diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java
index 57643b9c01..ea499578df 100644
--- a/service/java/com/android/server/wifi/util/InformationElementUtil.java
+++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java
@@ -1859,6 +1859,8 @@ public class InformationElementUtil {
private static final int WPS_VENDOR_OUI_TYPE = 0x04f25000;
private static final short WPA_VENDOR_OUI_VERSION = 0x0001;
private static final int OWE_VENDOR_OUI_TYPE = 0x1c9a6f50;
+ private static final int RSNE_OVERRIDE_VENDOR_OUI_TYPE = 0x299a6f50;
+ private static final int RSNE_OVERRIDE2_VENDOR_OUI_TYPE = 0x2A9a6f50;
private static final short RSNE_VERSION = 0x0001;
private static final int WPA_AKM_EAP = 0x01f25000;
@@ -1910,10 +1912,25 @@ public class InformationElementUtil {
public boolean isWPS;
public boolean isManagementFrameProtectionRequired;
public boolean isManagementFrameProtectionCapable;
+ private boolean mHasPmfRequiredBitSetToFalseOccurred;
+ public boolean isRSNEOverrideElementPresent;
public Capabilities() {
}
+ private static boolean isRsneOverrideElement(InformationElement ie) {
+ ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN);
+ try {
+ int vendorOuiType = buf.getInt();
+ // Wi-Fi Alliance specific OUI and OUI type identifying RSNE Override element.
+ return (vendorOuiType == RSNE_OVERRIDE_VENDOR_OUI_TYPE
+ || vendorOuiType == RSNE_OVERRIDE2_VENDOR_OUI_TYPE);
+ } catch (BufferUnderflowException e) {
+ Log.e("IE_Capabilities", "Couldn't parse VSA IE, buffer underflow");
+ return false;
+ }
+ }
+
// RSNE format (size unit: byte)
//
// | Element ID | Length | Version | Group Data Cipher Suite |
@@ -1927,8 +1944,7 @@ public class InformationElementUtil {
//
// Note: InformationElement.bytes has 'Element ID' and 'Length'
// stripped off already
- private void parseRsnElement(InformationElement ie, SparseIntArray unknownAkmMap) {
- ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN);
+ private void parseRsnElement(ByteBuffer buf, SparseIntArray unknownAkmMap) {
try {
// version
@@ -2027,9 +2043,17 @@ public class InformationElementUtil {
// see section 9.4.2.25 - RSNE - In IEEE Std 802.11-2016
if (buf.remaining() < 2) return;
int rsnCaps = buf.getShort();
- isManagementFrameProtectionRequired =
- 0 != (RSN_CAP_MANAGEMENT_FRAME_PROTECTION_REQUIRED & rsnCaps);
- isManagementFrameProtectionCapable =
+ // This method gets called multiple times if the AP and STA supports RSN overriding.
+ // The PMF required bit should be set to false if one of the RSN fields PMF
+ // required bit is ever false. The PMF capable bit should be set to true if one of
+ // the RSN fields PMF capable bit is ever true.
+ if ((RSN_CAP_MANAGEMENT_FRAME_PROTECTION_REQUIRED & rsnCaps) == 0) {
+ mHasPmfRequiredBitSetToFalseOccurred = true;
+ isManagementFrameProtectionRequired = false;
+ } else if (!mHasPmfRequiredBitSetToFalseOccurred) {
+ isManagementFrameProtectionRequired = true;
+ }
+ isManagementFrameProtectionCapable |=
0 != (RSN_CAP_MANAGEMENT_FRAME_PROTECTION_CAPABLE & rsnCaps);
if (buf.remaining() < 2) return;
@@ -2218,6 +2242,8 @@ 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
+ * @param isRsnOverridingSupported -- Boolean flag to indicate if RSN Overriding is
+ * supported by the device
* @param freq -- Frequency on which frame/beacon was transmitted. Some parsing may be
* affected such as DMG parameters in DMG (60GHz) beacon.
* @param unknownAkmMap -- unknown AKM to known AKM mapping (Internally converted to
@@ -2228,6 +2254,7 @@ public class InformationElementUtil {
InformationElement[] ies,
int beaconCap,
boolean isOweSupported,
+ boolean isRsnOverridingSupported,
int freq,
SparseIntArray unknownAkmMap) {
protocol = new ArrayList<>();
@@ -2265,10 +2292,22 @@ public class InformationElementUtil {
}
if (ie.id == InformationElement.EID_RSN) {
- parseRsnElement(ie, unknownAkmMap);
+ parseRsnElement(ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN),
+ unknownAkmMap);
}
if (ie.id == InformationElement.EID_VSA) {
+ if (isRsnOverridingSupported && isRsneOverrideElement(ie)) {
+ ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN);
+ // RSN Override and RSN Override 2 vendor specific element begins
+ // with 3 bytes of Wi-Fi Alliance specific OUI and 1 byte of OUI type.
+ // The Payload field of the RSNE Override element and the RSNE Override 2
+ // element uses the same format as the Information field of the RSNE.
+ // So skip the 4 byte OUI field and proceed to parse the RSN element.
+ buf.getInt();
+ parseRsnElement(buf, unknownAkmMap);
+ isRSNEOverrideElementPresent = true;
+ }
if (isWpaOneElement(ie)) {
parseWpaOneElement(ie, unknownAkmMap);
}
@@ -2474,6 +2513,9 @@ public class InformationElementUtil {
if (isManagementFrameProtectionCapable) {
capabilities.append("[MFPC]");
}
+ if (isRSNEOverrideElementPresent) {
+ capabilities.append("[RSNO]");
+ }
return capabilities.toString();
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
index cff25254dd..1027f13124 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
@@ -43,6 +43,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
import android.net.MacAddress;
import android.net.wifi.CoexUnsafeChannel;
@@ -52,6 +53,7 @@ import android.net.wifi.WifiAvailableChannel;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiContext;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiMigration;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiScanner.ScanData;
import android.net.wifi.WifiSsid;
@@ -73,6 +75,7 @@ import com.android.server.wifi.hal.WifiChip;
import com.android.server.wifi.proto.WifiStatsLog;
import com.android.server.wifi.util.NativeUtil;
import com.android.server.wifi.util.NetdWrapper;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
import org.junit.After;
@@ -344,8 +347,12 @@ public class WifiNativeTest extends WifiBaseTest {
mSession = ExtendedMockito.mockitoSession()
.strictness(Strictness.LENIENT)
.mockStatic(WifiStatsLog.class)
+ .mockStatic(Flags.class, withSettings().lenient())
+ .mockStatic(WifiMigration.class, withSettings().lenient())
.startMocking();
+ when(Flags.rsnOverriding()).thenReturn(false);
+
mWifiNative = new WifiNative(
mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl,
mWifiMonitor, mPropertyService, mWifiMetrics,
@@ -1820,4 +1827,18 @@ public class WifiNativeTest extends WifiBaseTest {
WifiManager.ROAMING_MODE_NORMAL));
verify(mWifiVendorHal).setRoamingMode(WIFI_IFACE_NAME, WifiManager.ROAMING_MODE_NORMAL);
}
+
+ @Test
+ public void testRsnOverridingFeatureFlag() throws Exception {
+ mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, true);
+ when(Flags.rsnOverriding()).thenReturn(false);
+ mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
+ mConcreteClientModeManager);
+ assertFalse(mWifiNative.mIsRsnOverridingSupported);
+ mWifiNative.teardownAllInterfaces();
+ when(Flags.rsnOverriding()).thenReturn(true);
+ mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
+ mConcreteClientModeManager);
+ assertTrue(mWifiNative.mIsRsnOverridingSupported);
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
index 0d5e495193..abc04e5f9d 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
@@ -466,11 +466,13 @@ public class InformationElementUtilTest extends WifiBaseTest {
InformationElement[] ies,
int beaconCap,
boolean isOweSupported,
+ boolean isRsnOverridingSupported,
String capsStr,
SparseIntArray unknownAkmMap) {
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
- capabilities.from(ies, beaconCap, isOweSupported, 2400, unknownAkmMap);
+ capabilities.from(ies, beaconCap, isOweSupported, isRsnOverridingSupported, 2400,
+ unknownAkmMap);
String result = capabilities.generateCapabilitiesString();
assertEquals(capsStr, result);
@@ -484,7 +486,8 @@ public class InformationElementUtilTest extends WifiBaseTest {
SparseIntArray unknownAkmMap) {
InformationElement[] ies = new InformationElement[] { ie };
verifyCapabilityStringFromIes(
- new InformationElement[] {ie}, beaconCap, isOweSupported, capsStr, unknownAkmMap);
+ new InformationElement[] {ie}, beaconCap, isOweSupported, false, capsStr,
+ unknownAkmMap);
}
private void verifyCapabilityStringFromIeWithoutOweSupported(
@@ -801,6 +804,7 @@ public class InformationElementUtilTest extends WifiBaseTest {
ies,
0x1 << 4,
false,
+ false,
"[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][RSN-PSK-CCMP+TKIP]",
null);
}
@@ -1130,6 +1134,210 @@ public class InformationElementUtilTest extends WifiBaseTest {
}
/**
+ * Test Capabilities.generateCapabilitiesString() with RSN, RSNO & RSNO2 element
+ * This configuration is same as a Wi-Fi 7 supported AP configured in
+ * WPA3-Compatibility Mode operating on the 2.4GHz/5GHz.
+ * Expect the function to return a string with the proper security information.
+ */
+ @Test
+ public void buildCapabilities_rsnRsnoAndRsno2Element() {
+ //RSNE Element carries WPA-PSK (AKM: 2)
+ 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 pairwise cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Pairwise Cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of AKMs (1)
+ (byte) 0x01, (byte) 0x00,
+ // PSK AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02,
+ // RSN capabilities
+ (byte) 0x00, (byte) 0x00,
+ };
+
+ //RSNE Override Element carries SAE (AKM: 8)
+ InformationElement ieRsno = new InformationElement();
+ ieRsno.id = InformationElement.EID_VSA;
+ ieRsno.bytes = new byte[] {
+ // RSNO (OUI type - 0x29) WFA vendor specific IE header
+ (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x29,
+ // RSNE Version (0x0001)
+ (byte) 0x01, (byte) 0x00,
+ // Group cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of pairwise cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Pairwise Cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of AKMs (1)
+ (byte) 0x01, (byte) 0x00,
+ // SAE AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x08,
+ // RSN capabilities
+ (byte) 0xC0, (byte) 0x00 };
+
+ //RSNE Override Element 2 Element carries SAE_EXT_KEY (AKM: 24)
+ InformationElement ieRsno2 = new InformationElement();
+ ieRsno2.id = InformationElement.EID_VSA;
+ ieRsno2.bytes = new byte[]{
+ // RSNO2 (OUI type - 0x2A) WFA vendor specific IE header
+ (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x2A,
+ // RSNE Version (0x0001)
+ (byte) 0x01, (byte) 0x00,
+ // Group cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of pairwise cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Cipher suite: GCMP-256
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x09,
+ // Number of AKMs (1)
+ (byte) 0x01, (byte) 0x00,
+ // SAE-EXT-KEY AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x18,
+ // Padding
+ // RSN capabilities
+ (byte) 0xC0, (byte) 0x00,
+ };
+
+ InformationElement[] ies = new InformationElement[] { ieRsn, ieRsno, ieRsno2 };
+
+ verifyCapabilityStringFromIes(
+ ies,
+ 0x1 << 4,
+ true,
+ true,
+ "[WPA2-PSK-CCMP][RSN-PSK-CCMP][RSN-SAE-CCMP][RSN-SAE_EXT_KEY-GCMP-256][MFPC][RSNO]",
+ null);
+ }
+
+ /**
+ * Test Capabilities.generateCapabilitiesString() with RSN, RSNO & RSNO2 element
+ * This configuration is same as a Wi-Fi 7 supported AP configured in
+ * WPA3-Compatibility Mode operating on the 6GHz band.
+ * Expect the function to return a string with the proper security information.
+ */
+ @Test
+ public void buildCapabilities_rsnAndRsno2Element() {
+ //RSNE Element carries SAE (AKM: 8)
+ 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 pairwise cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Pairwise Cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of AKMs (1)
+ (byte) 0x01, (byte) 0x00,
+ // SAE AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x08,
+ // RSN capabilities
+ (byte) 0xC0, (byte) 0x00,
+ };
+
+ //RSNE Override Element 2 Element carries SAE_EXT_KEY (AKM: 24)
+ InformationElement ieRsno2 = new InformationElement();
+ ieRsno2.id = InformationElement.EID_VSA;
+ ieRsno2.bytes = new byte[]{
+ // RSNO2 (OUI type - 0x2A) WFA vendor specific IE header
+ (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x2A,
+ // RSNE Version (0x0001)
+ (byte) 0x01, (byte) 0x00,
+ // Group cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of pairwise cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Cipher suite: GCMP-256
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x09,
+ // Number of AKMs (1)
+ (byte) 0x01, (byte) 0x00,
+ // SAE-EXT-KEY AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x18,
+ // Padding
+ // RSN capabilities
+ (byte) 0xC0, (byte) 0x00,
+ };
+
+ InformationElement[] ies = new InformationElement[] { ieRsn, ieRsno2 };
+
+ verifyCapabilityStringFromIes(
+ ies,
+ 0x1 << 4,
+ true,
+ true,
+ "[RSN-SAE-CCMP][RSN-SAE_EXT_KEY-GCMP-256][MFPR][MFPC][RSNO]",
+ null);
+ }
+
+ /**
+ * Test Capabilities.generateCapabilitiesString() without RSN Overriding support.
+ * The AP advertise WPA2 security params in RSN IE and WPA3 security params in RSNO element.
+ * But without the RSN Overriding support, it is expected to return a capabilities string
+ * which contains only WPA2 security params.
+ */
+ @Test
+ public void buildCapabilities_rsnAndRsnoElementWithoutRsnOverridingSupport() {
+ //RSNE Element carries WPA-PSK (AKM: 2)
+ 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 pairwise cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Pairwise Cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of AKMs (1)
+ (byte) 0x01, (byte) 0x00,
+ // PSK AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02,
+ // RSN capabilities
+ (byte) 0x00, (byte) 0x00,
+ };
+
+ //RSNE Override Element carries SAE (AKM: 8)
+ InformationElement ieRsno = new InformationElement();
+ ieRsno.id = InformationElement.EID_VSA;
+ ieRsno.bytes = new byte[] {
+ // RSNO (OUI type - 0x29) WFA vendor specific IE header
+ (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x29,
+ // RSNE Version (0x0001)
+ (byte) 0x01, (byte) 0x00,
+ // Group cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of pairwise cipher suites (1)
+ (byte) 0x01, (byte) 0x00,
+ // Pairwise Cipher suite: CCMP
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
+ // Number of AKMs (1)
+ (byte) 0x01, (byte) 0x00,
+ // SAE AKM
+ (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x08,
+ // RSN capabilities
+ (byte) 0xC0, (byte) 0x00 };
+ InformationElement[] ies = new InformationElement[] { ieRsn, ieRsno };
+
+ verifyCapabilityStringFromIes(
+ ies,
+ 0x1 << 4,
+ true,
+ false,
+ "[WPA2-PSK-CCMP][RSN-PSK-CCMP]",
+ null);
+ }
+
+ /**
* 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.
@@ -1148,7 +1356,7 @@ public class InformationElementUtilTest extends WifiBaseTest {
(byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00,
(byte) 0x00, (byte) 0x50 };
InformationElement[] ies = new InformationElement[] { ieWpa, ieRsn };
- verifyCapabilityStringFromIes(ies, 0x1 << 4, false, "[WPA][RSN]", null);
+ verifyCapabilityStringFromIes(ies, 0x1 << 4, false, false, "[WPA][RSN]", null);
}
/**
@@ -1172,7 +1380,8 @@ public class InformationElementUtilTest extends WifiBaseTest {
ieWps.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04 };
InformationElement[] ies = new InformationElement[] { ieWpa, ieWps };
- verifyCapabilityStringFromIes(ies, 0x1 << 4, false, "[WPA-PSK-CCMP+TKIP][WPS]", null);
+ verifyCapabilityStringFromIes(ies, 0x1 << 4, false, false, "[WPA-PSK-CCMP+TKIP][WPS]",
+ null);
}
/**
@@ -1253,7 +1462,7 @@ public class InformationElementUtilTest extends WifiBaseTest {
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
- capabilities.from(new InformationElement[0], beaconCap, false, 2400, null);
+ capabilities.from(new InformationElement[0], beaconCap, false, false, 2400, null);
String result = capabilities.generateCapabilitiesString();
assertEquals("[IBSS]", result);
@@ -1270,7 +1479,7 @@ public class InformationElementUtilTest extends WifiBaseTest {
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
- capabilities.from(new InformationElement[0], beaconCap, false, 58320, null);
+ capabilities.from(new InformationElement[0], beaconCap, false, false, 58320, null);
String result = capabilities.generateCapabilitiesString();
assertEquals("[IBSS]", result);
@@ -1287,7 +1496,7 @@ public class InformationElementUtilTest extends WifiBaseTest {
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
- capabilities.from(new InformationElement[0], beaconCap, false, 58320, null);
+ capabilities.from(new InformationElement[0], beaconCap, false, false, 58320, null);
String result = capabilities.generateCapabilitiesString();
assertEquals("[ESS]", result);