Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08744836 authored by Hai Shalom's avatar Hai Shalom
Browse files

[Suggestion] Fix setWpa3EnterpriseConfig

Add missing support for standard WPA3-Enterprise networks, which
are basically WPA2-Enterprise networks + PMF.
Add missing support in the Specifier as well, and add unit tests
to cover these use cases.
The logic detects 192-bit or standard mode by looking at the
certificates. If the certificates are Suite-B, then the 192-bit
mode is enabled. Otherwise, standard mode is enabled.

Bug: 166670837
Test: atest WifiNetworkSuggestionTest WifiNetworkSpecifierTest
Change-Id: I875d0d0584d71fe6dd3fedc8f5371e0b5ed2e5e5
Merged-In: I875d0d0584d71fe6dd3fedc8f5371e0b5ed2e5e5
(cherry picked from commit e1369b62)
parent 65f41278
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@ import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.ECParameterSpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -1442,4 +1445,50 @@ public class WifiEnterpriseConfig implements Parcelable {
        }
        return TextUtils.isEmpty(getCaPath());
    }

    /**
     * Check if a given certificate Get the Suite-B cipher from the certificate
     *
     * @param x509Certificate Certificate to process
     * @return true if the certificate OID matches the Suite-B requirements for RSA or ECDSA
     * certificates, or false otherwise.
     * @hide
     */
    public static boolean isSuiteBCipherCert(@Nullable X509Certificate x509Certificate) {
        if (x509Certificate == null) {
            return false;
        }
        final String sigAlgOid = x509Certificate.getSigAlgOID();

        // Wi-Fi alliance requires the use of both ECDSA secp384r1 and RSA 3072 certificates
        // in WPA3-Enterprise 192-bit security networks, which are also known as Suite-B-192
        // networks, even though NSA Suite-B-192 mandates ECDSA only. The use of the term
        // Suite-B was already coined in the IEEE 802.11-2016 specification for
        // AKM 00-0F-AC but the test plan for WPA3-Enterprise 192-bit for APs mandates
        // support for both RSA and ECDSA, and for STAs it mandates ECDSA and optionally
        // RSA. In order to be compatible with all WPA3-Enterprise 192-bit deployments,
        // we are supporting both types here.
        if (sigAlgOid.equals("1.2.840.113549.1.1.12")) {
            // sha384WithRSAEncryption
            if (x509Certificate.getPublicKey() instanceof RSAPublicKey) {
                final RSAPublicKey rsaPublicKey = (RSAPublicKey) x509Certificate.getPublicKey();
                if (rsaPublicKey.getModulus() != null
                        && rsaPublicKey.getModulus().bitLength() >= 3072) {
                    return true;
                }
            }
        } else if (sigAlgOid.equals("1.2.840.10045.4.3.3")) {
            // ecdsa-with-SHA384
            if (x509Certificate.getPublicKey() instanceof ECPublicKey) {
                final ECPublicKey ecPublicKey = (ECPublicKey) x509Certificate.getPublicKey();
                final ECParameterSpec ecParameterSpec = ecPublicKey.getParams();

                if (ecParameterSpec != null && ecParameterSpec.getOrder() != null
                        && ecParameterSpec.getOrder().bitLength() >= 384) {
                    return true;
                }
            }
        }
        return false;
    }
}
+26 −5
Original line number Diff line number Diff line
@@ -78,12 +78,12 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
        private @Nullable String mWpa3SaePassphrase;
        /**
         * The enterprise configuration details specifying the EAP method,
         * certificates and other settings associated with the WPA-EAP networks.
         * certificates and other settings associated with the WPA/WPA2-Enterprise networks.
         */
        private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
        /**
         * The enterprise configuration details specifying the EAP method,
         * certificates and other settings associated with the SuiteB networks.
         * certificates and other settings associated with the WPA3-Enterprise networks.
         */
        private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
        /**
@@ -243,7 +243,11 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc

        /**
         * Set the associated enterprise configuration for this network. Needed for authenticating
         * to WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description.
         * to WPA3-Enterprise networks (standard and 192-bit security). See
         * {@link WifiEnterpriseConfig} for description. For 192-bit security networks, both the
         * client and CA certificates must be provided, and must be of type of either
         * sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384
         * (OID 1.2.840.10045.4.3.3).
         *
         * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
@@ -284,8 +288,25 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
            } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
                configuration.enterpriseConfig = mWpa2EnterpriseConfig;
            } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
            } else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise
                if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
                        && WifiEnterpriseConfig.isSuiteBCipherCert(
                        mWpa3EnterpriseConfig.getClientCertificate())
                        && WifiEnterpriseConfig.isSuiteBCipherCert(
                        mWpa3EnterpriseConfig.getCaCertificate())) {
                    // WPA3-Enterprise in 192-bit security mode (Suite-B)
                    configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
                } else {
                    // WPA3-Enterprise
                    configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
                    configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                    configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                    configuration.allowedPairwiseCiphers.set(
                            WifiConfiguration.PairwiseCipher.GCMP_256);
                    configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                    configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
                    configuration.requirePmf = true;
                }
                configuration.enterpriseConfig = mWpa3EnterpriseConfig;
            } else if (mIsEnhancedOpen) { // OWE network
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
+26 −5
Original line number Diff line number Diff line
@@ -72,12 +72,12 @@ public final class WifiNetworkSuggestion implements Parcelable {
        private @Nullable String mWpa3SaePassphrase;
        /**
         * The enterprise configuration details specifying the EAP method,
         * certificates and other settings associated with the WPA-EAP networks.
         * certificates and other settings associated with the WPA/WPA2-Enterprise networks.
         */
        private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
        /**
         * The enterprise configuration details specifying the EAP method,
         * certificates and other settings associated with the SuiteB networks.
         * certificates and other settings associated with the WPA3-Enterprise networks.
         */
        private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
        /**
@@ -276,7 +276,11 @@ public final class WifiNetworkSuggestion implements Parcelable {

        /**
         * Set the associated enterprise configuration for this network. Needed for authenticating
         * to WPA3 enterprise networks. See {@link WifiEnterpriseConfig} for description.
         * to WPA3-Enterprise networks (standard and 192-bit security). See
         * {@link WifiEnterpriseConfig} for description. For 192-bit security networks, both the
         * client and CA certificates must be provided, and must be of type of either
         * sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384
         * (OID 1.2.840.10045.4.3.3).
         *
         * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
@@ -522,8 +526,25 @@ public final class WifiNetworkSuggestion implements Parcelable {
            } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
                configuration.enterpriseConfig = mWpa2EnterpriseConfig;
            } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
            } else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise
                if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
                        && WifiEnterpriseConfig.isSuiteBCipherCert(
                        mWpa3EnterpriseConfig.getClientCertificate())
                        && WifiEnterpriseConfig.isSuiteBCipherCert(
                        mWpa3EnterpriseConfig.getCaCertificate())) {
                    // WPA3-Enterprise in 192-bit security mode (Suite-B)
                    configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
                } else {
                    // WPA3-Enterprise
                    configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
                    configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                    configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                    configuration.allowedPairwiseCiphers.set(
                            WifiConfiguration.PairwiseCipher.GCMP_256);
                    configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                    configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
                    configuration.requirePmf = true;
                }
                configuration.enterpriseConfig = mWpa3EnterpriseConfig;
            } else if (mIsEnhancedOpen) { // OWE network
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
+410 −3

File changed.

Preview size limit exceeded, changes collapsed.

+105 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import android.net.MacAddress;
@@ -35,6 +37,8 @@ import androidx.test.filters.SmallTest;

import org.junit.Test;

import java.security.cert.X509Certificate;

/**
 * Unit tests for {@link android.net.wifi.WifiNetworkSpecifier}.
 */
@@ -45,6 +49,7 @@ public class WifiNetworkSpecifierTest {
    private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
    private static final String TEST_BSSID = "12:12:12:12:12:12";
    private static final String TEST_PRESHARED_KEY = "\"Test123\"";
    private static final String TEST_DOMAIN_SUFFIX_MATCH = "domainSuffixMatch";

    /**
     * Validate correctness of WifiNetworkSpecifier object created by
@@ -135,6 +140,106 @@ public class WifiNetworkSpecifierTest {
                wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getPhase2Method());
    }

    /**
     * Validate correctness of WifiNetworkSuggestion object created by
     * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise network.
     */
    @Test
    public void testWifiNetworkSuggestionBuilderForWpa3EapNetwork() {
        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
        enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
        enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
        enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);

        NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
                .setSsid(TEST_SSID)
                .setWpa3EnterpriseConfig(enterpriseConfig)
                .build();

        assertTrue(specifier instanceof WifiNetworkSpecifier);
        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;

        assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
                .get(WifiConfiguration.KeyMgmt.IEEE8021X));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
                .get(WifiConfiguration.KeyMgmt.WPA_EAP));
        assertFalse(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
                .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
                .get(WifiConfiguration.GroupCipher.CCMP));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
        assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
        assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
    }

    /**
     * Validate correctness of WifiNetworkSuggestion object created by
     * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network.
     */
    @Test
    public void testWifiNetworkSuggestionBuilderForWpa3SuiteBRsaEapNetwork() {
        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
        enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
        enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT);
        enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY,
                new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});

        enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);

        NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
                .setSsid(TEST_SSID)
                .setWpa3EnterpriseConfig(enterpriseConfig)
                .build();

        assertTrue(specifier instanceof WifiNetworkSpecifier);
        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;

        assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
                .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
                .get(WifiConfiguration.GroupCipher.GCMP_256));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupManagementCiphers
                .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
        assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
        assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
    }

    /**
     * Validate correctness of WifiNetworkSuggestion object created by
     * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network.
     */
    @Test
    public void testWifiNetworkSuggestionBuilderForWpa3SuiteBEccEapNetwork() {
        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
        enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
        enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT);
        enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY,
                new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT});

        enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);

        NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
                .setSsid(TEST_SSID)
                .setWpa3EnterpriseConfig(enterpriseConfig)
                .build();

        assertTrue(specifier instanceof WifiNetworkSpecifier);
        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;

        assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
                .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
                .get(WifiConfiguration.GroupCipher.GCMP_256));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupManagementCiphers
                .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
        assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
        assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
        assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
    }

    /**
     * Ensure {@link WifiNetworkSpecifier.Builder#setSsid(String)} throws an exception
Loading