From ccbce520d82a197cffc2e765efaf7ba375652852 Mon Sep 17 00:00:00 2001 From: Ecco Park Date: Wed, 9 Jan 2019 11:04:27 -0800 Subject: [PATCH] passpoint-r2: handle multiple CA certificates This is required to save the AAA root CA certs for PPS MO. Put @hide for new API because this is only used for wifi service. Bug: 117717842 Test: ./frameworks/base/wifi/tests/runtests.sh Test: tested with R1 AP for installing profile and R2 AP for connection Change-Id: Ib84c030024d3429140cd80bb622fd23ca608b9bb Signed-off-by: Ecco Park --- .../net/wifi/hotspot2/pps/Credential.java | 59 ++++++++++++++----- .../net/wifi/hotspot2/pps/CredentialTest.java | 27 +++++---- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java index 7689fc34ff5be..59a7290eb8a90 100644 --- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java +++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java @@ -572,7 +572,7 @@ public final class Credential implements Parcelable { @Override public int hashCode() { - return Objects.hash(mCertType, mCertSha256Fingerprint); + return Objects.hash(mCertType, Arrays.hashCode(mCertSha256Fingerprint)); } @Override @@ -842,24 +842,50 @@ public final class Credential implements Parcelable { } /** - * CA (Certificate Authority) X509 certificate. + * CA (Certificate Authority) X509 certificates. */ - private X509Certificate mCaCertificate = null; + private X509Certificate[] mCaCertificates = null; + /** * Set the CA (Certification Authority) certificate associated with this credential. * * @param caCertificate The CA certificate to set to */ public void setCaCertificate(X509Certificate caCertificate) { - mCaCertificate = caCertificate; + mCaCertificates = null; + if (caCertificate != null) { + mCaCertificates = new X509Certificate[] {caCertificate}; + } } + + /** + * Set the CA (Certification Authority) certificates associated with this credential. + * + * @param caCertificates The list of CA certificates to set to + * @hide + */ + public void setCaCertificates(X509Certificate[] caCertificates) { + mCaCertificates = caCertificates; + } + /** * Get the CA (Certification Authority) certificate associated with this credential. * - * @return CA certificate associated with this credential + * @return CA certificate associated with this credential, {@code null} if certificate is not + * set or certificate is more than one. */ public X509Certificate getCaCertificate() { - return mCaCertificate; + return mCaCertificates == null || mCaCertificates.length > 1 ? null : mCaCertificates[0]; + } + + /** + * Get the CA (Certification Authority) certificates associated with this credential. + * + * @return The list of CA certificates associated with this credential + * @hide + */ + public X509Certificate[] getCaCertificates() { + return mCaCertificates; } /** @@ -933,7 +959,11 @@ public final class Credential implements Parcelable { mClientCertificateChain = Arrays.copyOf(source.mClientCertificateChain, source.mClientCertificateChain.length); } - mCaCertificate = source.mCaCertificate; + if (source.mCaCertificates != null) { + mCaCertificates = Arrays.copyOf(source.mCaCertificates, + source.mCaCertificates.length); + } + mClientPrivateKey = source.mClientPrivateKey; } } @@ -952,7 +982,7 @@ public final class Credential implements Parcelable { dest.writeParcelable(mUserCredential, flags); dest.writeParcelable(mCertCredential, flags); dest.writeParcelable(mSimCredential, flags); - ParcelUtil.writeCertificate(dest, mCaCertificate); + ParcelUtil.writeCertificates(dest, mCaCertificates); ParcelUtil.writeCertificates(dest, mClientCertificateChain); ParcelUtil.writePrivateKey(dest, mClientPrivateKey); } @@ -977,16 +1007,17 @@ public final class Credential implements Parcelable { : mCertCredential.equals(that.mCertCredential)) && (mSimCredential == null ? that.mSimCredential == null : mSimCredential.equals(that.mSimCredential)) - && isX509CertificateEquals(mCaCertificate, that.mCaCertificate) + && isX509CertificatesEquals(mCaCertificates, that.mCaCertificates) && isX509CertificatesEquals(mClientCertificateChain, that.mClientCertificateChain) && isPrivateKeyEquals(mClientPrivateKey, that.mClientPrivateKey); } @Override public int hashCode() { - return Objects.hash(mRealm, mCreationTimeInMillis, mExpirationTimeInMillis, + return Objects.hash(mCreationTimeInMillis, mExpirationTimeInMillis, mRealm, mCheckAaaServerCertStatus, mUserCredential, mCertCredential, mSimCredential, - mCaCertificate, mClientCertificateChain, mClientPrivateKey); + mClientPrivateKey, Arrays.hashCode(mCaCertificates), + Arrays.hashCode(mClientCertificateChain)); } @Override @@ -1067,7 +1098,7 @@ public final class Credential implements Parcelable { credential.setUserCredential(in.readParcelable(null)); credential.setCertCredential(in.readParcelable(null)); credential.setSimCredential(in.readParcelable(null)); - credential.setCaCertificate(ParcelUtil.readCertificate(in)); + credential.setCaCertificates(ParcelUtil.readCertificates(in)); credential.setClientCertificateChain(ParcelUtil.readCertificates(in)); credential.setClientPrivateKey(ParcelUtil.readPrivateKey(in)); return credential; @@ -1100,7 +1131,7 @@ public final class Credential implements Parcelable { // CA certificate is required for R1 Passpoint profile. // For R2, it is downloaded using cert URL provided in PPS MO after validation completes. - if (isR1 && mCaCertificate == null) { + if (isR1 && mCaCertificates == null) { Log.d(TAG, "Missing CA Certificate for user credential"); return false; } @@ -1131,7 +1162,7 @@ public final class Credential implements Parcelable { // Verify required key and certificates for certificate credential. // CA certificate is required for R1 Passpoint profile. // For R2, it is downloaded using cert URL provided in PPS MO after validation completes. - if (isR1 && mCaCertificate == null) { + if (isR1 && mCaCertificates == null) { Log.d(TAG, "Missing CA Certificate for certificate credential"); return false; } diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java index a9d4b8f008f6e..1ecc3fecf7c30 100644 --- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java +++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java @@ -16,6 +16,7 @@ package android.net.wifi.hotspot2.pps; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -44,17 +45,16 @@ public class CredentialTest { * @param userCred Instance of UserCredential * @param certCred Instance of CertificateCredential * @param simCred Instance of SimCredential - * @param caCert CA certificate * @param clientCertificateChain Chain of client certificates * @param clientPrivateKey Client private key + * @param caCerts CA certificates * @return {@link Credential} */ private static Credential createCredential(Credential.UserCredential userCred, - Credential.CertificateCredential certCred, - Credential.SimCredential simCred, - X509Certificate caCert, - X509Certificate[] clientCertificateChain, - PrivateKey clientPrivateKey) { + Credential.CertificateCredential certCred, + Credential.SimCredential simCred, + X509Certificate[] clientCertificateChain, PrivateKey clientPrivateKey, + X509Certificate... caCerts) { Credential cred = new Credential(); cred.setCreationTimeInMillis(123455L); cred.setExpirationTimeInMillis(2310093L); @@ -63,7 +63,11 @@ public class CredentialTest { cred.setUserCredential(userCred); cred.setCertCredential(certCred); cred.setSimCredential(simCred); - cred.setCaCertificate(caCert); + if (caCerts != null && caCerts.length == 1) { + cred.setCaCertificate(caCerts[0]); + } else { + cred.setCaCertificates(caCerts); + } cred.setClientCertificateChain(clientCertificateChain); cred.setClientPrivateKey(clientPrivateKey); return cred; @@ -80,8 +84,8 @@ public class CredentialTest { certCred.setCertType("x509v3"); certCred.setCertSha256Fingerprint( MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded())); - return createCredential(null, certCred, null, FakeKeys.CA_CERT0, - new X509Certificate[] {FakeKeys.CLIENT_CERT}, FakeKeys.RSA_KEY1); + return createCredential(null, certCred, null, new X509Certificate[] {FakeKeys.CLIENT_CERT}, + FakeKeys.RSA_KEY1, FakeKeys.CA_CERT0, FakeKeys.CA_CERT1); } /** @@ -93,7 +97,7 @@ public class CredentialTest { Credential.SimCredential simCred = new Credential.SimCredential(); simCred.setImsi("1234*"); simCred.setEapType(EAPConstants.EAP_SIM); - return createCredential(null, null, simCred, null, null, null); + return createCredential(null, null, simCred, null, null, (X509Certificate[]) null); } /** @@ -110,7 +114,7 @@ public class CredentialTest { userCred.setSoftTokenApp("TestApp"); userCred.setEapType(EAPConstants.EAP_TTLS); userCred.setNonEapInnerMethod("MS-CHAP"); - return createCredential(userCred, null, null, FakeKeys.CA_CERT0, null, null); + return createCredential(userCred, null, null, null, null, FakeKeys.CA_CERT0); } private static void verifyParcel(Credential writeCred) { @@ -120,6 +124,7 @@ public class CredentialTest { parcel.setDataPosition(0); // Rewind data position back to the beginning for read. Credential readCred = Credential.CREATOR.createFromParcel(parcel); assertTrue(readCred.equals(writeCred)); + assertEquals(writeCred.hashCode(), readCred.hashCode()); } /**