From 725fefb38a4cb0ab89de439f8131d6c46ccd8b17 Mon Sep 17 00:00:00 2001 From: Chad Brubaker Date: Wed, 25 Nov 2015 14:23:14 -0800 Subject: Use a custom TrustedCertificateStore Providing a TrustedCertificateStore to TrustManagerImpl avoids loading all of the trusted certificates into memory and indexing them. This is mainly for the system certificate store where loading all of the store into memory is wasteful for most applications. Change-Id: I9e6057f6a13d38ea7762fcac2f62bd3ff475af39 --- .../net/config/NetworkSecurityTrustManager.java | 12 +-- .../net/config/TrustedCertificateStoreAdapter.java | 116 +++++++++++++++++++++ 2 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 core/java/android/security/net/config/TrustedCertificateStoreAdapter.java diff --git a/core/java/android/security/net/config/NetworkSecurityTrustManager.java b/core/java/android/security/net/config/NetworkSecurityTrustManager.java index 6013c1e4023e..982ed68f13da 100644 --- a/core/java/android/security/net/config/NetworkSecurityTrustManager.java +++ b/core/java/android/security/net/config/NetworkSecurityTrustManager.java @@ -46,17 +46,13 @@ public class NetworkSecurityTrustManager implements X509TrustManager { throw new NullPointerException("config must not be null"); } mNetworkSecurityConfig = config; - // TODO: Create our own better KeyStoreImpl try { + TrustedCertificateStoreAdapter certStore = new TrustedCertificateStoreAdapter(config); + // Provide an empty KeyStore since TrustManagerImpl doesn't support null KeyStores. + // TrustManagerImpl will use certStore to lookup certificates. KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType()); store.load(null); - int certNum = 0; - for (TrustAnchor anchor : mNetworkSecurityConfig.getTrustAnchors()) { - store.setEntry(String.valueOf(certNum++), - new KeyStore.TrustedCertificateEntry(anchor.certificate), - null); - } - mDelegate = new TrustManagerImpl(store); + mDelegate = new TrustManagerImpl(store, null, certStore); } catch (GeneralSecurityException | IOException e) { throw new RuntimeException(e); } diff --git a/core/java/android/security/net/config/TrustedCertificateStoreAdapter.java b/core/java/android/security/net/config/TrustedCertificateStoreAdapter.java new file mode 100644 index 000000000000..4a90f8223ad7 --- /dev/null +++ b/core/java/android/security/net/config/TrustedCertificateStoreAdapter.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.net.config; + +import java.io.File; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Set; + +import com.android.org.conscrypt.TrustedCertificateStore; + +/** @hide */ +public class TrustedCertificateStoreAdapter extends TrustedCertificateStore { + private final NetworkSecurityConfig mConfig; + + public TrustedCertificateStoreAdapter(NetworkSecurityConfig config) { + mConfig = config; + } + + @Override + public X509Certificate findIssuer(X509Certificate cert) { + TrustAnchor anchor = mConfig.findTrustAnchorByIssuerAndSignature(cert); + if (anchor == null) { + return null; + } + return anchor.certificate; + } + + @Override + public X509Certificate getTrustAnchor(X509Certificate cert) { + TrustAnchor anchor = mConfig.findTrustAnchorBySubjectAndPublicKey(cert); + if (anchor == null) { + return null; + } + return anchor.certificate; + } + + @Override + public boolean isUserAddedCertificate(X509Certificate cert) { + // isUserAddedCertificate is used only for pinning overrides, so use overridesPins here. + TrustAnchor anchor = mConfig.findTrustAnchorBySubjectAndPublicKey(cert); + if (anchor == null) { + return false; + } + return anchor.overridesPins; + } + + @Override + public File getCertificateFile(File dir, X509Certificate x) { + // getCertificateFile is only used for tests, do not support it here. + throw new UnsupportedOperationException(); + } + + // The methods below are exposed in TrustedCertificateStore but not used by conscrypt, do not + // support them. + + @Override + public Certificate getCertificate(String alias) { + throw new UnsupportedOperationException(); + } + + @Override + public Certificate getCertificate(String alias, boolean includeDeletedSystem) { + throw new UnsupportedOperationException(); + } + + @Override + public Date getCreationDate(String alias) { + throw new UnsupportedOperationException(); + } + + @Override + public Set aliases() { + throw new UnsupportedOperationException(); + } + + @Override + public Set userAliases() { + throw new UnsupportedOperationException(); + } + + @Override + public Set allSystemAliases() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean containsAlias(String alias) { + throw new UnsupportedOperationException(); + } + + @Override + public String getCertificateAlias(Certificate c) { + throw new UnsupportedOperationException(); + } + + @Override + public String getCertificateAlias(Certificate c, boolean includeDeletedSystem) { + throw new UnsupportedOperationException(); + } +} -- cgit v1.2.3-59-g8ed1b