blob: 33ac85903443a3a8f17c8ff57d1bed9544530d26 [file] [log] [blame]
/*
* Copyright (C) 2016 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 org.conscrypt;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collection;
import javax.net.ssl.X509TrustManager;
import junit.framework.TestCase;
public class CertBlacklistTest extends TestCase {
private static final String BLACKLIST_CA = "test_blacklist_ca.pem";
private static final String BLACKLISTED_CHAIN = "blacklist_test_chain.pem";
private static final String BLACKLIST_FALLBACK_VALID_CA = "blacklist_test_valid_ca.pem";
private static final String BLACKLISTED_VALID_CHAIN = "blacklist_test_valid_chain.pem";
/**
* Ensure that the test blacklisted CA is actually blacklisted by default.
*/
public void testBlacklistedPublicKey() throws Exception {
X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
CertBlacklist blacklist = CertBlacklist.getDefault();
assertTrue(blacklist.isPublicKeyBlackListed(blacklistedCa.getPublicKey()));
}
/**
* Check that the blacklisted CA is rejected even if it used as a root of trust
*/
public void testBlacklistedCaUntrusted() throws Exception {
X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
assertUntrusted(new X509Certificate[] {blacklistedCa}, getTrustManager(blacklistedCa));
}
/**
* Check that a chain that is rooted in a blacklisted trusted CA is rejected.
*/
public void testBlacklistedRootOfTrust() throws Exception {
// Chain is leaf -> blacklisted
X509Certificate[] chain = loadCertificates(BLACKLISTED_CHAIN);
X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
assertUntrusted(chain, getTrustManager(blacklistedCa));
}
/** Test that the path building correctly routes around a blacklisted cert where there are
* other valid paths available. This prevents breakage where a cert was cross signed by a
* blacklisted CA but is still valid due to also being cross signed by CAs that remain trusted.
* Path:
*
* leaf -> intermediate -> blacklisted_ca
* \
* -------> trusted_ca
*/
public void testBlacklistedIntermediateFallback() throws Exception {
X509Certificate[] chain = loadCertificates(BLACKLISTED_VALID_CHAIN);
X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
X509Certificate validCa = loadCertificate(BLACKLIST_FALLBACK_VALID_CA);
assertTrusted(chain, getTrustManager(blacklistedCa, validCa));
// Check that without the trusted_ca the chain is invalid (since it only chains to a
// blacklisted ca)
assertUntrusted(chain, getTrustManager(blacklistedCa));
}
private static X509Certificate loadCertificate(String file) throws Exception {
return loadCertificates(file)[0];
}
private static X509Certificate[] loadCertificates(String file) throws Exception {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
try (InputStream is = TestUtils.openTestFile(file)) {
Collection<? extends Certificate> collection = factory.generateCertificates(is);
is.close();
X509Certificate[] certs = new X509Certificate[collection.size()];
int i = 0;
for (Certificate cert : collection) {
certs[i++] = (X509Certificate) cert;
}
return certs;
}
}
private static TrustManagerImpl getTrustManager(X509Certificate... trustedCas)
throws Exception {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null);
int i = 0;
for (X509Certificate ca : trustedCas) {
ks.setCertificateEntry(String.valueOf(i++), ca);
}
return new TrustManagerImpl(ks);
}
private static void assertTrusted(X509Certificate[] certs, X509TrustManager tm)
throws Exception {
tm.checkServerTrusted(certs, "RSA");
}
private static void assertUntrusted(X509Certificate[] certs, X509TrustManager tm) {
try {
tm.checkServerTrusted(certs, "RSA");
fail();
} catch (CertificateException expected) {
}
}
}