1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.security.net.config; 18 19 import android.util.ArraySet; 20 import java.security.KeyStore; 21 import java.security.KeyStoreException; 22 import java.security.cert.Certificate; 23 import java.security.cert.X509Certificate; 24 import java.util.Collections; 25 import java.util.Enumeration; 26 import java.util.Set; 27 28 import com.android.org.conscrypt.TrustedCertificateIndex; 29 30 /** 31 * {@link CertificateSource} which provides certificates from trusted certificate entries of a 32 * {@link KeyStore}. 33 */ 34 class KeyStoreCertificateSource implements CertificateSource { 35 private final Object mLock = new Object(); 36 private final KeyStore mKeyStore; 37 private TrustedCertificateIndex mIndex; 38 private Set<X509Certificate> mCertificates; 39 KeyStoreCertificateSource(KeyStore ks)40 public KeyStoreCertificateSource(KeyStore ks) { 41 mKeyStore = ks; 42 } 43 44 @Override getCertificates()45 public Set<X509Certificate> getCertificates() { 46 ensureInitialized(); 47 return mCertificates; 48 } 49 ensureInitialized()50 private void ensureInitialized() { 51 synchronized (mLock) { 52 if (mCertificates != null) { 53 return; 54 } 55 56 try { 57 TrustedCertificateIndex localIndex = new TrustedCertificateIndex(); 58 Set<X509Certificate> certificates = new ArraySet<>(mKeyStore.size()); 59 for (Enumeration<String> en = mKeyStore.aliases(); en.hasMoreElements();) { 60 String alias = en.nextElement(); 61 X509Certificate cert = (X509Certificate) mKeyStore.getCertificate(alias); 62 if (cert != null) { 63 certificates.add(cert); 64 localIndex.index(cert); 65 } 66 } 67 mIndex = localIndex; 68 mCertificates = certificates; 69 } catch (KeyStoreException e) { 70 throw new RuntimeException("Failed to load certificates from KeyStore", e); 71 } 72 } 73 } 74 75 @Override findBySubjectAndPublicKey(X509Certificate cert)76 public X509Certificate findBySubjectAndPublicKey(X509Certificate cert) { 77 ensureInitialized(); 78 java.security.cert.TrustAnchor anchor = mIndex.findBySubjectAndPublicKey(cert); 79 if (anchor == null) { 80 return null; 81 } 82 return anchor.getTrustedCert(); 83 } 84 85 @Override findByIssuerAndSignature(X509Certificate cert)86 public X509Certificate findByIssuerAndSignature(X509Certificate cert) { 87 ensureInitialized(); 88 java.security.cert.TrustAnchor anchor = mIndex.findByIssuerAndSignature(cert); 89 if (anchor == null) { 90 return null; 91 } 92 return anchor.getTrustedCert(); 93 } 94 95 @Override findAllByIssuerAndSignature(X509Certificate cert)96 public Set<X509Certificate> findAllByIssuerAndSignature(X509Certificate cert) { 97 ensureInitialized(); 98 Set<java.security.cert.TrustAnchor> anchors = mIndex.findAllByIssuerAndSignature(cert); 99 if (anchors.isEmpty()) { 100 return Collections.<X509Certificate>emptySet(); 101 } 102 Set<X509Certificate> certs = new ArraySet<X509Certificate>(anchors.size()); 103 for (java.security.cert.TrustAnchor anchor : anchors) { 104 certs.add(anchor.getTrustedCert()); 105 } 106 return certs; 107 } 108 109 @Override handleTrustStorageUpdate()110 public void handleTrustStorageUpdate() { 111 // Nothing to do. 112 } 113 } 114