blob: 3e692c36fb30fd125027daf04031595ecc78a3c3 [file] [log] [blame]
Esteban Talavera17aafef2014-09-30 17:03:32 +01001/*
2 * Copyright (C) 2014 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 */
16package com.android.cts.deviceowner;
17
Chad Brubakerfe9883f2016-04-20 13:34:40 -070018import android.net.http.X509TrustManagerExtensions;
Chad Brubakerf6a85eb2016-03-25 10:49:43 -070019import android.security.NetworkSecurityPolicy;
20
Esteban Talavera17aafef2014-09-30 17:03:32 +010021import java.io.ByteArrayInputStream;
Robin Lee53d26712015-09-30 17:19:29 +010022import java.security.GeneralSecurityException;
23import java.security.KeyStore;
24import java.security.cert.Certificate;
Esteban Talavera17aafef2014-09-30 17:03:32 +010025import java.security.cert.CertificateException;
26import java.security.cert.CertificateFactory;
Chad Brubakerfe9883f2016-04-20 13:34:40 -070027import java.security.cert.X509Certificate;
Robin Lee53d26712015-09-30 17:19:29 +010028import java.util.Arrays;
Esteban Talavera17aafef2014-09-30 17:03:32 +010029import java.util.List;
30
Robin Lee53d26712015-09-30 17:19:29 +010031import javax.net.ssl.TrustManager;
32import javax.net.ssl.TrustManagerFactory;
33import javax.net.ssl.X509TrustManager;
34
35import static com.android.cts.deviceowner.FakeKeys.FAKE_DSA_1;
36import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
37
Esteban Talavera17aafef2014-09-30 17:03:32 +010038public class CaCertManagementTest extends BaseDeviceOwnerTest {
Robin Lee53d26712015-09-30 17:19:29 +010039 /**
40 * Test: device admins should be able to list all installed certs.
41 *
42 * <p>The list of certificates must never be {@code null}.
43 */
Esteban Talavera17aafef2014-09-30 17:03:32 +010044 public void testCanRetrieveListOfInstalledCaCerts() {
45 List<byte[]> caCerts = mDevicePolicyManager.getInstalledCaCerts(getWho());
46 assertNotNull(caCerts);
47 }
48
Robin Lee53d26712015-09-30 17:19:29 +010049 /**
50 * Test: a valid cert should be installable and also removable.
51 */
Esteban Talavera17aafef2014-09-30 17:03:32 +010052 public void testCanInstallAndUninstallACaCert()
Robin Lee53d26712015-09-30 17:19:29 +010053 throws CertificateException, GeneralSecurityException {
54 assertUninstalled(FAKE_RSA_1.caCertificate);
55 assertUninstalled(FAKE_DSA_1.caCertificate);
56
Esteban Talavera17aafef2014-09-30 17:03:32 +010057 assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
Robin Lee53d26712015-09-30 17:19:29 +010058 assertInstalled(FAKE_RSA_1.caCertificate);
59 assertUninstalled(FAKE_DSA_1.caCertificate);
60
Esteban Talavera17aafef2014-09-30 17:03:32 +010061 mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
Robin Lee53d26712015-09-30 17:19:29 +010062 assertUninstalled(FAKE_RSA_1.caCertificate);
63 assertUninstalled(FAKE_DSA_1.caCertificate);
Esteban Talavera17aafef2014-09-30 17:03:32 +010064 }
65
Robin Lee53d26712015-09-30 17:19:29 +010066 /**
67 * Test: removing one certificate must not remove any others.
68 */
69 public void testUninstallationIsSelective()
70 throws CertificateException, GeneralSecurityException {
Esteban Talavera17aafef2014-09-30 17:03:32 +010071 assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
72 assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
Robin Lee53d26712015-09-30 17:19:29 +010073
Esteban Talavera17aafef2014-09-30 17:03:32 +010074 mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_DSA_1.caCertificate);
Robin Lee53d26712015-09-30 17:19:29 +010075 assertInstalled(FAKE_RSA_1.caCertificate);
76 assertUninstalled(FAKE_DSA_1.caCertificate);
77
Esteban Talavera17aafef2014-09-30 17:03:32 +010078 mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
79 }
80
Robin Lee53d26712015-09-30 17:19:29 +010081 /**
82 * Test: uninstallAllUserCaCerts should be equivalent to calling uninstallCaCert on every
83 * supplementary installed certificate.
84 */
85 public void testCanUninstallAllUserCaCerts()
86 throws CertificateException, GeneralSecurityException {
Esteban Talavera17aafef2014-09-30 17:03:32 +010087 assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
88 assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
Robin Lee53d26712015-09-30 17:19:29 +010089
Esteban Talavera17aafef2014-09-30 17:03:32 +010090 mDevicePolicyManager.uninstallAllUserCaCerts(getWho());
Robin Lee53d26712015-09-30 17:19:29 +010091 assertUninstalled(FAKE_RSA_1.caCertificate);
92 assertUninstalled(FAKE_DSA_1.caCertificate);
Esteban Talavera17aafef2014-09-30 17:03:32 +010093 }
94
Robin Lee53d26712015-09-30 17:19:29 +010095 private void assertInstalled(byte[] caBytes)
96 throws CertificateException, GeneralSecurityException {
97 Certificate caCert = readCertificate(caBytes);
98 assertTrue(isCaCertInstalledAndTrusted(caCert));
Esteban Talavera17aafef2014-09-30 17:03:32 +010099 }
100
Robin Lee53d26712015-09-30 17:19:29 +0100101 private void assertUninstalled(byte[] caBytes)
102 throws CertificateException, GeneralSecurityException {
103 Certificate caCert = readCertificate(caBytes);
104 assertFalse(isCaCertInstalledAndTrusted(caCert));
105 }
106
Chad Brubakerfe9883f2016-04-20 13:34:40 -0700107 private static X509TrustManager getFirstX509TrustManager(TrustManagerFactory tmf) {
108 for (TrustManager trustManager : tmf.getTrustManagers()) {
109 if (trustManager instanceof X509TrustManager) {
110 return (X509TrustManager) trustManager;
111 }
112 }
113 throw new RuntimeException("Unable to find X509TrustManager");
114 }
115
Robin Lee53d26712015-09-30 17:19:29 +0100116 /**
117 * Whether a given cert, or one a lot like it, has been installed system-wide and is available
118 * to all apps.
119 *
120 * <p>A CA certificate is "installed" if it matches all of the following conditions:
121 * <ul>
122 * <li>{@link DevicePolicyManager#hasCaCertInstalled} returns {@code true}.</li>
123 * <li>{@link DevicePolicyManager#getInstalledCaCerts} lists a matching certificate (not
124 * necessarily exactly the same) in its response.</li>
125 * <li>Any new instances of {@link TrustManager} should report the certificate among their
126 * accepted issuer list -- older instances may keep the set of issuers they were created
127 * with until explicitly refreshed.</li>
128 *
129 * @return {@code true} if installed by all metrics, {@code false} if not installed by any
130 * metric. In any other case an {@link AssertionError} will be thrown.
131 */
132 private boolean isCaCertInstalledAndTrusted(Certificate caCert)
133 throws GeneralSecurityException, CertificateException {
134 boolean installed = mDevicePolicyManager.hasCaCertInstalled(getWho(), caCert.getEncoded());
135
136 boolean listed = false;
137 for (byte[] certBuffer : mDevicePolicyManager.getInstalledCaCerts(getWho())) {
138 if (caCert.equals(readCertificate(certBuffer))) {
139 listed = true;
Esteban Talavera17aafef2014-09-30 17:03:32 +0100140 }
141 }
Robin Lee53d26712015-09-30 17:19:29 +0100142
Chad Brubakerf6a85eb2016-03-25 10:49:43 -0700143 NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
144
Chad Brubakerfe9883f2016-04-20 13:34:40 -0700145 // Verify that the user added CA is reflected in the default X509TrustManager.
Robin Lee53d26712015-09-30 17:19:29 +0100146 final TrustManagerFactory tmf =
147 TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
Chad Brubakerfe9883f2016-04-20 13:34:40 -0700148 // Use platform provided CA store.
Robin Lee53d26712015-09-30 17:19:29 +0100149 tmf.init((KeyStore) null);
Chad Brubakerfe9883f2016-04-20 13:34:40 -0700150 X509TrustManager tm = getFirstX509TrustManager(tmf);
151 boolean trusted = Arrays.asList(tm.getAcceptedIssuers()).contains(caCert);
152 X509TrustManagerExtensions xtm = new X509TrustManagerExtensions(tm);
153 boolean userAddedCertificate = xtm.isUserAddedCertificate((X509Certificate) caCert);
Robin Lee53d26712015-09-30 17:19:29 +0100154
155 // All three responses should match - if an installed certificate isn't trusted or (worse)
156 // a trusted certificate isn't even installed we should
157 assertEquals(installed, listed);
158 assertEquals(installed, trusted);
Chad Brubakerfe9883f2016-04-20 13:34:40 -0700159 assertEquals(installed, userAddedCertificate);
Robin Lee53d26712015-09-30 17:19:29 +0100160 return installed;
Esteban Talavera17aafef2014-09-30 17:03:32 +0100161 }
162
Robin Lee53d26712015-09-30 17:19:29 +0100163 /**
164 * Convert an encoded certificate back into a {@link Certificate}.
165 *
166 * Instantiates a fresh CertificateFactory every time for repeatability.
167 */
Esteban Talavera17aafef2014-09-30 17:03:32 +0100168 private static Certificate readCertificate(byte[] certBuffer) throws CertificateException {
169 final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
170 return certFactory.generateCertificate(new ByteArrayInputStream(certBuffer));
171 }
172}