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

Commit c71b5dab authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic 'enterprise-client-chain'

* changes:
  Test passing null cert/keys to WifiEnterpriseConfig
  Account for null client certificate
  Add a client chain to WifiEnterpriseConfig
parents d0638435 88b3c589
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -24696,6 +24696,7 @@ package android.net.wifi {
    method public java.security.cert.X509Certificate getCaCertificate();
    method public java.security.cert.X509Certificate[] getCaCertificates();
    method public java.security.cert.X509Certificate getClientCertificate();
    method public java.security.cert.X509Certificate[] getClientCertificateChain();
    method public java.lang.String getDomainSuffixMatch();
    method public int getEapMethod();
    method public java.lang.String getIdentity();
@@ -24709,6 +24710,7 @@ package android.net.wifi {
    method public void setCaCertificate(java.security.cert.X509Certificate);
    method public void setCaCertificates(java.security.cert.X509Certificate[]);
    method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
    method public void setClientKeyEntryWithCertificateChain(java.security.PrivateKey, java.security.cert.X509Certificate[]);
    method public void setDomainSuffixMatch(java.lang.String);
    method public void setEapMethod(int);
    method public void setIdentity(java.lang.String);
+2 −0
Original line number Diff line number Diff line
@@ -27069,6 +27069,7 @@ package android.net.wifi {
    method public java.security.cert.X509Certificate getCaCertificate();
    method public java.security.cert.X509Certificate[] getCaCertificates();
    method public java.security.cert.X509Certificate getClientCertificate();
    method public java.security.cert.X509Certificate[] getClientCertificateChain();
    method public java.lang.String getDomainSuffixMatch();
    method public int getEapMethod();
    method public java.lang.String getIdentity();
@@ -27082,6 +27083,7 @@ package android.net.wifi {
    method public void setCaCertificate(java.security.cert.X509Certificate);
    method public void setCaCertificates(java.security.cert.X509Certificate[]);
    method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
    method public void setClientKeyEntryWithCertificateChain(java.security.PrivateKey, java.security.cert.X509Certificate[]);
    method public void setDomainSuffixMatch(java.lang.String);
    method public void setEapMethod(int);
    method public void setIdentity(java.lang.String);
+2 −0
Original line number Diff line number Diff line
@@ -24769,6 +24769,7 @@ package android.net.wifi {
    method public java.security.cert.X509Certificate getCaCertificate();
    method public java.security.cert.X509Certificate[] getCaCertificates();
    method public java.security.cert.X509Certificate getClientCertificate();
    method public java.security.cert.X509Certificate[] getClientCertificateChain();
    method public java.lang.String getDomainSuffixMatch();
    method public int getEapMethod();
    method public java.lang.String getIdentity();
@@ -24782,6 +24783,7 @@ package android.net.wifi {
    method public void setCaCertificate(java.security.cert.X509Certificate);
    method public void setCaCertificates(java.security.cert.X509Certificate[]);
    method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
    method public void setClientKeyEntryWithCertificateChain(java.security.PrivateKey, java.security.cert.X509Certificate[]);
    method public void setDomainSuffixMatch(java.lang.String);
    method public void setEapMethod(int);
    method public void setIdentity(java.lang.String);
+81 −10
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ public class WifiEnterpriseConfig implements Parcelable {
    private HashMap<String, String> mFields = new HashMap<String, String>();
    private X509Certificate[] mCaCerts;
    private PrivateKey mClientPrivateKey;
    private X509Certificate mClientCertificate;
    private X509Certificate[] mClientCertificateChain;
    private int mEapMethod = Eap.NONE;
    private int mPhase2Method = Phase2.NONE;

@@ -161,9 +161,19 @@ public class WifiEnterpriseConfig implements Parcelable {
        for (String key : source.mFields.keySet()) {
            mFields.put(key, source.mFields.get(key));
        }
        mCaCerts = source.mCaCerts;
        if (source.mCaCerts != null) {
            mCaCerts = Arrays.copyOf(source.mCaCerts, source.mCaCerts.length);
        } else {
            mCaCerts = null;
        }
        mClientPrivateKey = source.mClientPrivateKey;
        mClientCertificate = source.mClientCertificate;
        if (source.mClientCertificateChain != null) {
            mClientCertificateChain = Arrays.copyOf(
                    source.mClientCertificateChain,
                    source.mClientCertificateChain.length);
        } else {
            mClientCertificateChain = null;
        }
        mEapMethod = source.mEapMethod;
        mPhase2Method = source.mPhase2Method;
    }
@@ -185,7 +195,7 @@ public class WifiEnterpriseConfig implements Parcelable {
        dest.writeInt(mPhase2Method);
        ParcelUtil.writeCertificates(dest, mCaCerts);
        ParcelUtil.writePrivateKey(dest, mClientPrivateKey);
        ParcelUtil.writeCertificate(dest, mClientCertificate);
        ParcelUtil.writeCertificates(dest, mClientCertificateChain);
    }

    public static final Creator<WifiEnterpriseConfig> CREATOR =
@@ -204,7 +214,7 @@ public class WifiEnterpriseConfig implements Parcelable {
                    enterpriseConfig.mPhase2Method = in.readInt();
                    enterpriseConfig.mCaCerts = ParcelUtil.readCertificates(in);
                    enterpriseConfig.mClientPrivateKey = ParcelUtil.readPrivateKey(in);
                    enterpriseConfig.mClientCertificate = ParcelUtil.readCertificate(in);
                    enterpriseConfig.mClientCertificateChain = ParcelUtil.readCertificates(in);
                    return enterpriseConfig;
                }

@@ -742,10 +752,54 @@ public class WifiEnterpriseConfig implements Parcelable {
     * @throws IllegalArgumentException for an invalid key or certificate.
     */
    public void setClientKeyEntry(PrivateKey privateKey, X509Certificate clientCertificate) {
        X509Certificate[] clientCertificates = null;
        if (clientCertificate != null) {
            if (clientCertificate.getBasicConstraints() != -1) {
                throw new IllegalArgumentException("Cannot be a CA certificate");
            clientCertificates = new X509Certificate[] {clientCertificate};
        }
        setClientKeyEntryWithCertificateChain(privateKey, clientCertificates);
    }

    /**
     * Specify a private key and client certificate chain for client authorization.
     *
     * <p>A default name is automatically assigned to the key entry and used
     * with this configuration.  The framework takes care of installing the
     * key entry when the config is saved and removing the key entry when
     * the config is removed.

     * @param privateKey
     * @param clientCertificateChain
     * @throws IllegalArgumentException for an invalid key or certificate.
     */
    public void setClientKeyEntryWithCertificateChain(PrivateKey privateKey,
            X509Certificate[] clientCertificateChain) {
        X509Certificate[] newCerts = null;
        if (clientCertificateChain != null && clientCertificateChain.length > 0) {
            // We validate that this is a well formed chain that starts
            // with an end-certificate and is followed by CA certificates.
            // We don't validate that each following certificate verifies
            // the previous. https://en.wikipedia.org/wiki/Chain_of_trust
            //
            // Basic constraints is an X.509 extension type that defines
            // whether a given certificate is allowed to sign additional
            // certificates and what path length restrictions may exist.
            // We use this to judge whether the certificate is an end
            // certificate or a CA certificate.
            // https://cryptography.io/en/latest/x509/reference/
            if (clientCertificateChain[0].getBasicConstraints() != -1) {
                throw new IllegalArgumentException(
                        "First certificate in the chain must be a client end certificate");
            }

            for (int i = 1; i < clientCertificateChain.length; i++) {
                if (clientCertificateChain[i].getBasicConstraints() == -1) {
                    throw new IllegalArgumentException(
                            "All certificates following the first must be CA certificates");
                }
            }
            newCerts = Arrays.copyOf(clientCertificateChain,
                    clientCertificateChain.length);

            if (privateKey == null) {
                throw new IllegalArgumentException("Client cert without a private key");
            }
@@ -755,7 +809,7 @@ public class WifiEnterpriseConfig implements Parcelable {
        }

        mClientPrivateKey = privateKey;
        mClientCertificate = clientCertificate;
        mClientCertificateChain = newCerts;
    }

    /**
@@ -764,7 +818,24 @@ public class WifiEnterpriseConfig implements Parcelable {
     * @return X.509 client certificate
     */
    public X509Certificate getClientCertificate() {
        return mClientCertificate;
        if (mClientCertificateChain != null && mClientCertificateChain.length > 0) {
            return mClientCertificateChain[0];
        } else {
            return null;
        }
    }

    /**
     * Get the complete client certificate chain
     *
     * @return X.509 client certificates
     */
    @Nullable public X509Certificate[] getClientCertificateChain() {
        if (mClientCertificateChain != null && mClientCertificateChain.length > 0) {
            return mClientCertificateChain;
        } else {
            return null;
        }
    }

    /**
@@ -772,7 +843,7 @@ public class WifiEnterpriseConfig implements Parcelable {
     */
    public void resetClientKeyEntry() {
        mClientPrivateKey = null;
        mClientCertificate = null;
        mClientCertificateChain = null;
    }

    /**
+46 −0
Original line number Diff line number Diff line
@@ -86,6 +86,52 @@ public class WifiEnterpriseConfigTest {
        assertTrue(result[0] == cert0 && result[1] == cert1);
    }

    @Test
    public void testSetClientKeyEntryWithNull() {
        mEnterpriseConfig.setClientKeyEntry(null, null);
        assertEquals(null, mEnterpriseConfig.getClientCertificateChain());
        assertEquals(null, mEnterpriseConfig.getClientCertificate());
        mEnterpriseConfig.setClientKeyEntryWithCertificateChain(null, null);
        assertEquals(null, mEnterpriseConfig.getClientCertificateChain());
        assertEquals(null, mEnterpriseConfig.getClientCertificate());
    }

    @Test
    public void testSetClientCertificateChain() {
        PrivateKey clientKey = FakeKeys.RSA_KEY1;
        X509Certificate cert0 = FakeKeys.CLIENT_CERT;
        X509Certificate cert1 = FakeKeys.CA_CERT1;
        X509Certificate[] clientChain = new X509Certificate[] {cert0, cert1};
        mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain);
        X509Certificate[] result = mEnterpriseConfig.getClientCertificateChain();
        assertEquals(result.length, 2);
        assertTrue(result[0] == cert0 && result[1] == cert1);
        assertTrue(mEnterpriseConfig.getClientCertificate() == cert0);
    }

    private boolean isClientCertificateChainInvalid(X509Certificate[] clientChain) {
        boolean exceptionThrown = false;
        try {
            PrivateKey clientKey = FakeKeys.RSA_KEY1;
            mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain);
        } catch (IllegalArgumentException e) {
            exceptionThrown = true;
        }
        return exceptionThrown;
    }

    @Test
    public void testSetInvalidClientCertificateChain() {
        X509Certificate clientCert = FakeKeys.CLIENT_CERT;
        X509Certificate caCert = FakeKeys.CA_CERT1;
        assertTrue("Invalid client certificate",
                isClientCertificateChainInvalid(new X509Certificate[] {caCert, caCert}));
        assertTrue("Invalid CA certificate",
                isClientCertificateChainInvalid(new X509Certificate[] {clientCert, clientCert}));
        assertTrue("Both certificates invalid",
                isClientCertificateChainInvalid(new X509Certificate[] {caCert, clientCert}));
    }

    @Test
    public void testSaveSingleCaCertificateAlias() {
        final String alias = "single_alias 0";