summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sunil Ravi <sunilravi@google.com> 2024-07-18 00:38:47 +0000
committer Sunil Ravi <sunilravi@google.com> 2024-07-23 20:26:50 +0000
commit1b46788ac0f5ea6d251e501b038c895c52537254 (patch)
tree4fec9c13e2d981321335c29f2dde5e60ea53c673
parent1e86fa60fc4f89fb873089682582708fa06d476a (diff)
Support for Wi-Fi Alliance WPA3 RSN overriding
This change includes, 1. Added a new overlay config item config_wifiRsnOverrideEnabled (Default set to false) for the device support for RSN Overriding. 2. Rearranged the code in parseRsnElement() method so that the same parser can be used for parsing RSN IE, RSNO IE and RSNO2 IE. 3. Added a boolean state tracker to set the final state of PMF required settings 4. Defined a feature flag rsn_overriding Bug: 348669010 Flag: com.android.wifi.flags.rsn_overriding Test: atest InformationElementUtilTest Test: atest ScanResultUtilTest Test: atest WifiNativeTest Test: manual - Connect/Disconnect to WPA2, WPA3 and WPA3-TM Access Points. Change-Id: I1f71bdfb765974df5d2df9f7bbed7c7d1a184a26
-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);