Add a client chain to WifiEnterpriseConfig

am: 291ddaef78

Change-Id: Ic8451631732bd3bfce7ff08f9f37b18745cda357
This commit is contained in:
Paul Stewart
2017-01-28 01:45:05 +00:00
committed by android-build-merger
5 changed files with 121 additions and 11 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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,51 @@ public class WifiEnterpriseConfig implements Parcelable {
* @throws IllegalArgumentException for an invalid key or certificate.
*/
public void setClientKeyEntry(PrivateKey privateKey, X509Certificate clientCertificate) {
if (clientCertificate != null) {
if (clientCertificate.getBasicConstraints() != -1) {
throw new IllegalArgumentException("Cannot be a CA certificate");
setClientKeyEntryWithCertificateChain(privateKey,
new X509Certificate[] {clientCertificate});
}
/**
* 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 +806,7 @@ public class WifiEnterpriseConfig implements Parcelable {
}
mClientPrivateKey = privateKey;
mClientCertificate = clientCertificate;
mClientCertificateChain = newCerts;
}
/**
@@ -764,7 +815,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 +840,7 @@ public class WifiEnterpriseConfig implements Parcelable {
*/
public void resetClientKeyEntry() {
mClientPrivateKey = null;
mClientCertificate = null;
mClientCertificateChain = null;
}
/**

View File

@@ -86,6 +86,42 @@ public class WifiEnterpriseConfigTest {
assertTrue(result[0] == cert0 && result[1] == cert1);
}
@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";