diff options
8 files changed, 106 insertions, 3 deletions
diff --git a/core/java/android/security/net/config/CertificateSource.java b/core/java/android/security/net/config/CertificateSource.java index 7e3601e1fbea..f3272e478665 100644 --- a/core/java/android/security/net/config/CertificateSource.java +++ b/core/java/android/security/net/config/CertificateSource.java @@ -16,12 +16,13 @@ package android.security.net.config; -import java.util.Set; import java.security.cert.X509Certificate; +import java.util.Set; /** @hide */ public interface CertificateSource { Set<X509Certificate> getCertificates(); X509Certificate findBySubjectAndPublicKey(X509Certificate cert); X509Certificate findByIssuerAndSignature(X509Certificate cert); + Set<X509Certificate> findAllByIssuerAndSignature(X509Certificate cert); } diff --git a/core/java/android/security/net/config/CertificatesEntryRef.java b/core/java/android/security/net/config/CertificatesEntryRef.java index ff728efc2d93..742d430a4e78 100644 --- a/core/java/android/security/net/config/CertificatesEntryRef.java +++ b/core/java/android/security/net/config/CertificatesEntryRef.java @@ -17,8 +17,8 @@ package android.security.net.config; import android.util.ArraySet; -import java.util.Set; import java.security.cert.X509Certificate; +import java.util.Set; /** @hide */ public final class CertificatesEntryRef { @@ -60,4 +60,8 @@ public final class CertificatesEntryRef { return new TrustAnchor(foundCert, mOverridesPins); } + + public Set<X509Certificate> findAllCertificatesByIssuerAndSignature(X509Certificate cert) { + return mSource.findAllByIssuerAndSignature(cert); + } } diff --git a/core/java/android/security/net/config/DirectoryCertificateSource.java b/core/java/android/security/net/config/DirectoryCertificateSource.java index bf29efabb00a..b2c068cb4516 100644 --- a/core/java/android/security/net/config/DirectoryCertificateSource.java +++ b/core/java/android/security/net/config/DirectoryCertificateSource.java @@ -29,6 +29,7 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.Collections; import java.util.Set; import libcore.io.IoUtils; @@ -110,10 +111,50 @@ abstract class DirectoryCertificateSource implements CertificateSource { }); } + @Override + public Set<X509Certificate> findAllByIssuerAndSignature(final X509Certificate cert) { + return findCerts(cert.getIssuerX500Principal(), new CertSelector() { + @Override + public boolean match(X509Certificate ca) { + try { + cert.verify(ca.getPublicKey()); + return true; + } catch (Exception e) { + return false; + } + } + }); + } + private static interface CertSelector { boolean match(X509Certificate cert); } + private Set<X509Certificate> findCerts(X500Principal subj, CertSelector selector) { + String hash = getHash(subj); + Set<X509Certificate> certs = null; + for (int index = 0; index >= 0; index++) { + String fileName = hash + "." + index; + if (!new File(mDir, fileName).exists()) { + break; + } + if (isCertMarkedAsRemoved(fileName)) { + continue; + } + X509Certificate cert = readCertificate(fileName); + if (!subj.equals(cert.getSubjectX500Principal())) { + continue; + } + if (selector.match(cert)) { + if (certs == null) { + certs = new ArraySet<X509Certificate>(); + } + certs.add(cert); + } + } + return certs != null ? certs : Collections.<X509Certificate>emptySet(); + } + private X509Certificate findCert(X500Principal subj, CertSelector selector) { String hash = getHash(subj); for (int index = 0; index >= 0; index++) { diff --git a/core/java/android/security/net/config/KeyStoreCertificateSource.java b/core/java/android/security/net/config/KeyStoreCertificateSource.java index b6105cd5da4c..ba5dd8396024 100644 --- a/core/java/android/security/net/config/KeyStoreCertificateSource.java +++ b/core/java/android/security/net/config/KeyStoreCertificateSource.java @@ -21,6 +21,7 @@ import java.security.KeyStore; import java.security.KeyStoreException; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.Collections; import java.util.Enumeration; import java.util.Set; @@ -90,4 +91,18 @@ class KeyStoreCertificateSource implements CertificateSource { } return anchor.getTrustedCert(); } + + @Override + public Set<X509Certificate> findAllByIssuerAndSignature(X509Certificate cert) { + ensureInitialized(); + Set<java.security.cert.TrustAnchor> anchors = mIndex.findAllByIssuerAndSignature(cert); + if (anchors.isEmpty()) { + return Collections.<X509Certificate>emptySet(); + } + Set<X509Certificate> certs = new ArraySet<X509Certificate>(anchors.size()); + for (java.security.cert.TrustAnchor anchor : anchors) { + certs.add(anchor.getTrustedCert()); + } + return certs; + } } diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java index 0a2edff2295f..ebe14691464c 100644 --- a/core/java/android/security/net/config/NetworkSecurityConfig.java +++ b/core/java/android/security/net/config/NetworkSecurityConfig.java @@ -145,6 +145,15 @@ public final class NetworkSecurityConfig { return null; } + /** @hide */ + public Set<X509Certificate> findAllCertificatesByIssuerAndSignature(X509Certificate cert) { + Set<X509Certificate> certs = new ArraySet<X509Certificate>(); + for (CertificatesEntryRef ref : mCertificatesEntryRefs) { + certs.addAll(ref.findAllCertificatesByIssuerAndSignature(cert)); + } + return certs; + } + /** * Return a {@link Builder} for the default {@code NetworkSecurityConfig}. * diff --git a/core/java/android/security/net/config/ResourceCertificateSource.java b/core/java/android/security/net/config/ResourceCertificateSource.java index e489c2c529eb..8803c4b2559c 100644 --- a/core/java/android/security/net/config/ResourceCertificateSource.java +++ b/core/java/android/security/net/config/ResourceCertificateSource.java @@ -25,6 +25,7 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Collection; +import java.util.Collections; import java.util.Set; import com.android.org.conscrypt.TrustedCertificateIndex; @@ -100,4 +101,18 @@ public class ResourceCertificateSource implements CertificateSource { } return anchor.getTrustedCert(); } + + @Override + public Set<X509Certificate> findAllByIssuerAndSignature(X509Certificate cert) { + ensureInitialized(); + Set<java.security.cert.TrustAnchor> anchors = mIndex.findAllByIssuerAndSignature(cert); + if (anchors.isEmpty()) { + return Collections.<X509Certificate>emptySet(); + } + Set<X509Certificate> certs = new ArraySet<X509Certificate>(anchors.size()); + for (java.security.cert.TrustAnchor anchor : anchors) { + certs.add(anchor.getTrustedCert()); + } + return certs; + } } diff --git a/core/java/android/security/net/config/TrustedCertificateStoreAdapter.java b/core/java/android/security/net/config/TrustedCertificateStoreAdapter.java index 4a90f8223ad7..c2f29bed1b27 100644 --- a/core/java/android/security/net/config/TrustedCertificateStoreAdapter.java +++ b/core/java/android/security/net/config/TrustedCertificateStoreAdapter.java @@ -42,6 +42,11 @@ public class TrustedCertificateStoreAdapter extends TrustedCertificateStore { } @Override + public Set<X509Certificate> findAllIssuers(X509Certificate cert) { + return mConfig.findAllCertificatesByIssuerAndSignature(cert); + } + + @Override public X509Certificate getTrustAnchor(X509Certificate cert) { TrustAnchor anchor = mConfig.findTrustAnchorBySubjectAndPublicKey(cert); if (anchor == null) { diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestCertificateSource.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestCertificateSource.java index 0c360631c294..4c12c2d5da7c 100644 --- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestCertificateSource.java +++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestCertificateSource.java @@ -16,8 +16,9 @@ package android.security.net.config; -import java.util.Set; +import android.util.ArraySet; import java.security.cert.X509Certificate; +import java.util.Set; import com.android.org.conscrypt.TrustedCertificateIndex; @@ -33,10 +34,12 @@ public class TestCertificateSource implements CertificateSource { } } + @Override public Set<X509Certificate> getCertificates() { return mCertificates; } + @Override public X509Certificate findBySubjectAndPublicKey(X509Certificate cert) { java.security.cert.TrustAnchor anchor = mIndex.findBySubjectAndPublicKey(cert); if (anchor == null) { @@ -45,6 +48,7 @@ public class TestCertificateSource implements CertificateSource { return anchor.getTrustedCert(); } + @Override public X509Certificate findByIssuerAndSignature(X509Certificate cert) { java.security.cert.TrustAnchor anchor = mIndex.findByIssuerAndSignature(cert); if (anchor == null) { @@ -52,4 +56,13 @@ public class TestCertificateSource implements CertificateSource { } return anchor.getTrustedCert(); } + + @Override + public Set<X509Certificate> findAllByIssuerAndSignature(X509Certificate cert) { + Set<X509Certificate> certs = new ArraySet<X509Certificate>(); + for (java.security.cert.TrustAnchor anchor : mIndex.findAllByIssuerAndSignature(cert)) { + certs.add(anchor.getTrustedCert()); + } + return certs; + } } |