1 /* 2 * Copyright (C) 2016 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 org.conscrypt; 18 19 import java.io.InputStream; 20 import java.security.KeyStore; 21 import java.security.cert.Certificate; 22 import java.security.cert.CertificateException; 23 import java.security.cert.CertificateFactory; 24 import java.security.cert.X509Certificate; 25 import java.util.Collection; 26 import javax.net.ssl.X509TrustManager; 27 import junit.framework.TestCase; 28 29 public class CertBlacklistTest extends TestCase { 30 31 private static final String BLACKLIST_CA = "test_blacklist_ca.pem"; 32 private static final String BLACKLISTED_CHAIN = "blacklist_test_chain.pem"; 33 private static final String BLACKLIST_FALLBACK_VALID_CA = "blacklist_test_valid_ca.pem"; 34 private static final String BLACKLISTED_VALID_CHAIN = "blacklist_test_valid_chain.pem"; 35 36 /** 37 * Ensure that the test blacklisted CA is actually blacklisted by default. 38 */ 39 public void testBlacklistedPublicKey() throws Exception { 40 X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA); 41 CertBlacklist blacklist = CertBlacklist.getDefault(); 42 assertTrue(blacklist.isPublicKeyBlackListed(blacklistedCa.getPublicKey())); 43 } 44 45 /** 46 * Check that the blacklisted CA is rejected even if it used as a root of trust 47 */ 48 public void testBlacklistedCaUntrusted() throws Exception { 49 X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA); 50 assertUntrusted(new X509Certificate[] {blacklistedCa}, getTrustManager(blacklistedCa)); 51 } 52 53 /** 54 * Check that a chain that is rooted in a blacklisted trusted CA is rejected. 55 */ 56 public void testBlacklistedRootOfTrust() throws Exception { 57 // Chain is leaf -> blacklisted 58 X509Certificate[] chain = loadCertificates(BLACKLISTED_CHAIN); 59 X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA); 60 assertUntrusted(chain, getTrustManager(blacklistedCa)); 61 } 62 63 /** Test that the path building correctly routes around a blacklisted cert where there are 64 * other valid paths available. This prevents breakage where a cert was cross signed by a 65 * blacklisted CA but is still valid due to also being cross signed by CAs that remain trusted. 66 * Path: 67 * 68 * leaf -> intermediate -> blacklisted_ca 69 * \ 70 * -------> trusted_ca 71 */ 72 public void testBlacklistedIntermediateFallback() throws Exception { 73 X509Certificate[] chain = loadCertificates(BLACKLISTED_VALID_CHAIN); 74 X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA); 75 X509Certificate validCa = loadCertificate(BLACKLIST_FALLBACK_VALID_CA); 76 assertTrusted(chain, getTrustManager(blacklistedCa, validCa)); 77 // Check that without the trusted_ca the chain is invalid (since it only chains to a 78 // blacklisted ca) 79 assertUntrusted(chain, getTrustManager(blacklistedCa)); 80 } 81 82 private static X509Certificate loadCertificate(String file) throws Exception { 83 return loadCertificates(file)[0]; 84 } 85 86 private static X509Certificate[] loadCertificates(String file) throws Exception { 87 CertificateFactory factory = CertificateFactory.getInstance("X.509"); 88 try (InputStream is = TestUtils.openTestFile(file)) { 89 Collection<? extends Certificate> collection = factory.generateCertificates(is); 90 is.close(); 91 X509Certificate[] certs = new X509Certificate[collection.size()]; 92 int i = 0; 93 for (Certificate cert : collection) { 94 certs[i++] = (X509Certificate) cert; 95 } 96 return certs; 97 } 98 } 99 100 private static TrustManagerImpl getTrustManager(X509Certificate... trustedCas) 101 throws Exception { 102 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 103 ks.load(null); 104 int i = 0; 105 for (X509Certificate ca : trustedCas) { 106 ks.setCertificateEntry(String.valueOf(i++), ca); 107 } 108 return new TrustManagerImpl(ks); 109 } 110 111 private static void assertTrusted(X509Certificate[] certs, X509TrustManager tm) 112 throws Exception { 113 tm.checkServerTrusted(certs, "RSA"); 114 } 115 116 private static void assertUntrusted(X509Certificate[] certs, X509TrustManager tm) { 117 try { 118 tm.checkServerTrusted(certs, "RSA"); 119 fail(); 120 } catch (CertificateException expected) { 121 } 122 } 123 } 124