1 /*
2  * Copyright (C) 2022 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 package com.android.server.security;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import static java.nio.charset.StandardCharsets.UTF_8;
21 
22 import androidx.test.ext.junit.runners.AndroidJUnit4;
23 import androidx.test.platform.app.InstrumentationRegistry;
24 
25 import org.hamcrest.CoreMatchers;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.rules.ExpectedException;
30 import org.junit.runner.RunWith;
31 
32 import java.security.cert.Certificate;
33 import java.security.cert.CertificateEncodingException;
34 import java.security.cert.CertificateFactory;
35 import java.security.cert.X509Certificate;
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.List;
39 
40 /** Test for data class holding parsed X509Certificate attestation attributes. */
41 @RunWith(AndroidJUnit4.class)
42 public class AndroidKeystoreAttestationVerificationAttributesTest {
43     @Rule public ExpectedException mException = ExpectedException.none();
44     private static final String TEST_PHYSCIAL_DEVICE_CERTS =
45             "test_attestation_wrong_root_certs.pem";
46     private static final String TEST_PHYSICAL_DEVICE_CERTS_2 =
47             "test_attestation_with_root_certs.pem";
48     private static final String TEST_VIRTUAL_DEVICE_CERTS =
49             "test_virtual_device_attestation_certs.pem";
50     private static final String TEST_CERT_NO_ATTESTATION_EXTENSION =
51             "test_no_attestation_ext_certs.pem";
52     private static final String TEST_CERTS_NO_ATTESTATION_EXTENSION_2 =
53             "test_root_certs.pem";
54 
55 
56     private CertificateFactory mFactory;
57     private AndroidKeystoreAttestationVerificationAttributes mPhysicalDeviceAttributes;
58     private AndroidKeystoreAttestationVerificationAttributes mPhysicalDeviceAttributes2;
59     private AndroidKeystoreAttestationVerificationAttributes mVirtualDeviceAttributes;
60 
61     @Before
setUp()62     public void setUp() throws Exception {
63         mFactory = CertificateFactory.getInstance("X.509");
64         mPhysicalDeviceAttributes =
65                 AndroidKeystoreAttestationVerificationAttributes.fromCertificate(
66                         generateCertificate(TEST_PHYSCIAL_DEVICE_CERTS));
67         mPhysicalDeviceAttributes2 =
68                 AndroidKeystoreAttestationVerificationAttributes.fromCertificate(
69                         generateCertificates(TEST_PHYSICAL_DEVICE_CERTS_2).get(0));
70         mVirtualDeviceAttributes =
71                 AndroidKeystoreAttestationVerificationAttributes.fromCertificate(
72                         generateCertificates(TEST_VIRTUAL_DEVICE_CERTS).get(0));
73     }
74 
75     @Test
parseCertificate_noAttestationExtension()76     public void parseCertificate_noAttestationExtension() throws Exception {
77         List<X509Certificate> certsNoAttestation =
78                 generateCertificates(TEST_CERTS_NO_ATTESTATION_EXTENSION_2);
79         certsNoAttestation.add(generateCertificate(TEST_CERT_NO_ATTESTATION_EXTENSION));
80         for (X509Certificate cert: certsNoAttestation) {
81             mException.expect(CertificateEncodingException.class);
82             mException.expectMessage(
83                     CoreMatchers.containsString("No attestation extension found in certificate."));
84 
85             AndroidKeystoreAttestationVerificationAttributes.fromCertificate(cert);
86         }
87     }
88 
89     @Test
parseCertificate_attestationLevel()90     public void  parseCertificate_attestationLevel() {
91         assertThat(mPhysicalDeviceAttributes.getAttestationVersion()).isEqualTo(3);
92         assertThat(mPhysicalDeviceAttributes2.getAttestationVersion()).isEqualTo(3);
93         assertThat(mVirtualDeviceAttributes.getAttestationVersion()).isEqualTo(4);
94     }
95 
96     @Test
parseCertificate_attestationSecurityLevel()97     public void  parseCertificate_attestationSecurityLevel() {
98         assertThat(mPhysicalDeviceAttributes.getAttestationSecurityLevel()).isEqualTo(
99                 AndroidKeystoreAttestationVerificationAttributes.SecurityLevel.TRUSTED_ENVIRONMENT);
100         assertThat(mPhysicalDeviceAttributes2.getAttestationSecurityLevel()).isEqualTo(
101                 AndroidKeystoreAttestationVerificationAttributes.SecurityLevel.TRUSTED_ENVIRONMENT);
102         assertThat(mVirtualDeviceAttributes.getAttestationSecurityLevel()).isEqualTo(
103                 AndroidKeystoreAttestationVerificationAttributes.SecurityLevel.SOFTWARE);
104     }
105 
106     @Test
parseCertificate_isAttestationHardwareBacked()107     public void  parseCertificate_isAttestationHardwareBacked() {
108         assertThat(mPhysicalDeviceAttributes.isAttestationHardwareBacked()).isTrue();
109         assertThat(mPhysicalDeviceAttributes2.isAttestationHardwareBacked()).isTrue();
110         assertThat(mVirtualDeviceAttributes.isAttestationHardwareBacked()).isFalse();
111     }
112 
113     @Test
parseCertificate_keymasterLevel()114     public void  parseCertificate_keymasterLevel() {
115         assertThat(mPhysicalDeviceAttributes.getKeymasterVersion()).isEqualTo(4);
116         assertThat(mPhysicalDeviceAttributes2.getKeymasterVersion()).isEqualTo(4);
117         assertThat(mVirtualDeviceAttributes.getKeymasterVersion()).isEqualTo(41);
118     }
119 
120     @Test
parseCertificate_keymasterSecurityLevel()121     public void  parseCertificate_keymasterSecurityLevel() {
122         assertThat(mPhysicalDeviceAttributes.getKeymasterSecurityLevel()).isEqualTo(
123                 AndroidKeystoreAttestationVerificationAttributes.SecurityLevel.TRUSTED_ENVIRONMENT);
124         assertThat(mPhysicalDeviceAttributes2.getKeymasterSecurityLevel()).isEqualTo(
125                 AndroidKeystoreAttestationVerificationAttributes.SecurityLevel.TRUSTED_ENVIRONMENT);
126         assertThat(mVirtualDeviceAttributes.getKeymasterSecurityLevel()).isEqualTo(
127                 AndroidKeystoreAttestationVerificationAttributes.SecurityLevel.SOFTWARE);
128     }
129 
130     @Test
parseCertificate_isKeymasterHardwareBacked()131     public void  parseCertificate_isKeymasterHardwareBacked() {
132         assertThat(mPhysicalDeviceAttributes.isKeymasterHardwareBacked()).isTrue();
133         assertThat(mPhysicalDeviceAttributes2.isKeymasterHardwareBacked()).isTrue();
134         assertThat(mVirtualDeviceAttributes.isKeymasterHardwareBacked()).isFalse();
135     }
136 
137     @Test
parseCertificate_attestationChallenge()138     public void  parseCertificate_attestationChallenge() {
139         assertThat(mPhysicalDeviceAttributes.getAttestationChallenge().toByteArray()).isEqualTo(
140                 "abc".getBytes(UTF_8));
141         assertThat(mPhysicalDeviceAttributes2.getAttestationChallenge().toByteArray()).isEqualTo(
142                 "player456".getBytes(UTF_8));
143         assertThat(mVirtualDeviceAttributes.getAttestationChallenge().toByteArray()).isEqualTo(
144                 "player456".getBytes(UTF_8));
145     }
146 
147     @Test
parseCertificate_verifiedBootState()148     public void  parseCertificate_verifiedBootState() {
149         assertThat(mPhysicalDeviceAttributes.getVerifiedBootState()).isEqualTo(
150                 AndroidKeystoreAttestationVerificationAttributes.VerifiedBootState.UNVERIFIED);
151         assertThat(mPhysicalDeviceAttributes2.getVerifiedBootState()).isEqualTo(
152                 AndroidKeystoreAttestationVerificationAttributes.VerifiedBootState.VERIFIED);
153         assertThat(mVirtualDeviceAttributes.getVerifiedBootState()).isNull();
154     }
155 
156     @Test
parseCertificate_keyBootPatchLevel()157     public void  parseCertificate_keyBootPatchLevel() {
158         assertThat(mPhysicalDeviceAttributes.getKeyBootPatchLevel()).isEqualTo(201907);
159         assertThat(mPhysicalDeviceAttributes2.getKeyBootPatchLevel()).isEqualTo(20220105);
160     }
161 
162     @Test
parseCertificate_keyBootPatchLevelNotSetException()163     public void parseCertificate_keyBootPatchLevelNotSetException() {
164         mException.expect(IllegalStateException.class);
165         mException.expectMessage(
166                 CoreMatchers.containsString("KeyBootPatchLevel is not set."));
167 
168         mVirtualDeviceAttributes.getKeyBootPatchLevel();
169     }
170 
171     @Test
parseCertificate_keyOsPatchLevel()172     public void  parseCertificate_keyOsPatchLevel() {
173         assertThat(mPhysicalDeviceAttributes.getKeyOsPatchLevel()).isEqualTo(201907);
174         assertThat(mPhysicalDeviceAttributes2.getKeyOsPatchLevel()).isEqualTo(202201);
175     }
176 
177     @Test
parseCertificate_keyOsPatchLevelNotSetException()178     public void parseCertificate_keyOsPatchLevelNotSetException() {
179         mException.expect(IllegalStateException.class);
180         mException.expectMessage(
181                 CoreMatchers.containsString("KeyOsPatchLevel is not set."));
182 
183         mVirtualDeviceAttributes.getKeyOsPatchLevel();
184     }
185 
186     @Test
parseCertificate_keyVendorPatchLevel()187     public void  parseCertificate_keyVendorPatchLevel() {
188         assertThat(mPhysicalDeviceAttributes.getKeyVendorPatchLevel()).isEqualTo(201907);
189         assertThat(mPhysicalDeviceAttributes2.getKeyVendorPatchLevel()).isEqualTo(20220105);
190     }
191 
192     @Test
parseCertificate_keyVendorPatchLevelNotSetException()193     public void parseCertificate_keyVendorPatchLevelNotSetException() {
194         mException.expect(IllegalStateException.class);
195         mException.expectMessage(
196                 CoreMatchers.containsString("KeyVendorPatchLevel is not set."));
197 
198         mVirtualDeviceAttributes.getKeyVendorPatchLevel();
199     }
200 
201     @Test
parseCertificate_keyAuthenticatorType()202     public void  parseCertificate_keyAuthenticatorType() {
203         assertThat(mPhysicalDeviceAttributes.getKeyAuthenticatorType()).isEqualTo(0);
204         assertThat(mPhysicalDeviceAttributes2.getKeyAuthenticatorType()).isEqualTo(0);
205     }
206 
207     @Test
parseCertificate_keyOsVersion()208     public void  parseCertificate_keyOsVersion() {
209         assertThat(mPhysicalDeviceAttributes.getKeyOsVersion()).isEqualTo(0);
210         assertThat(mPhysicalDeviceAttributes2.getKeyOsVersion()).isEqualTo(120000);
211     }
212 
213     @Test
parseCertificate_keyOsVersionNotSetException()214     public void parseCertificate_keyOsVersionNotSetException() {
215         mException.expect(IllegalStateException.class);
216         mException.expectMessage(
217                 CoreMatchers.containsString("KeyOsVersion is not set."));
218 
219         mVirtualDeviceAttributes.getKeyOsVersion();
220     }
221 
222     @Test
parseCertificate_verifiedBootHash()223     public void  parseCertificate_verifiedBootHash() {
224         assertThat(mPhysicalDeviceAttributes.getVerifiedBootHash()).isNotEmpty();
225         assertThat(mPhysicalDeviceAttributes2.getVerifiedBootHash()).isNotEmpty();
226     }
227 
228     @Test
parseCertificate_verifiedBootKey()229     public void  parseCertificate_verifiedBootKey() {
230         assertThat(mPhysicalDeviceAttributes.getVerifiedBootKey()).isNotEmpty();
231         assertThat(mPhysicalDeviceAttributes2.getVerifiedBootKey()).isNotEmpty();
232     }
233 
234     @Test
parseCertificate_isVerifiedBootLocked()235     public void  parseCertificate_isVerifiedBootLocked() {
236         assertThat(mPhysicalDeviceAttributes.isVerifiedBootLocked()).isFalse();
237         assertThat(mPhysicalDeviceAttributes2.isVerifiedBootLocked()).isTrue();
238     }
239 
240     @Test
parseCertificate_isVerifiedBootLockedNotSetException()241     public void parseCertificate_isVerifiedBootLockedNotSetException() {
242         mException.expect(IllegalStateException.class);
243         mException.expectMessage(
244                 CoreMatchers.containsString("VerifiedBootLocked is not set."));
245 
246         mVirtualDeviceAttributes.isVerifiedBootLocked();
247     }
248 
249     @Test
parseCertificate_applicationPackageNameVersion()250     public void  parseCertificate_applicationPackageNameVersion() {
251         assertThat(mPhysicalDeviceAttributes.getApplicationPackageNameVersion()).isNotEmpty();
252     }
253 
254     @Test
parseCertificate_applicationCertificateDigests()255     public void  parseCertificate_applicationCertificateDigests() {
256         assertThat(mPhysicalDeviceAttributes.getApplicationCertificateDigests()).isNotEmpty();
257     }
258 
259     @Test
parseCertificate_valuesNotSet()260     public void parseCertificate_valuesNotSet() {
261         assertThat(mPhysicalDeviceAttributes.getDeviceBrand()).isNull();
262         assertThat(mPhysicalDeviceAttributes.getDeviceName()).isNull();
263         assertThat(mPhysicalDeviceAttributes.getDeviceProductName()).isNull();
264         assertThat(mPhysicalDeviceAttributes.isKeyAllowedForAllApplications()).isFalse();
265         assertThat(mPhysicalDeviceAttributes2.getDeviceBrand()).isNull();
266         assertThat(mPhysicalDeviceAttributes2.getDeviceName()).isNull();
267         assertThat(mPhysicalDeviceAttributes2.getDeviceProductName()).isNull();
268         assertThat(mPhysicalDeviceAttributes2.isKeyAllowedForAllApplications()).isFalse();
269     }
270 
271     @Test
parseCertificate_keyRequiresUnlockedDeviceNotSetException()272     public void parseCertificate_keyRequiresUnlockedDeviceNotSetException() {
273         mException.expect(IllegalStateException.class);
274         mException.expectMessage(
275                 CoreMatchers.containsString("KeyRequiresUnlockedDevice is not set."));
276 
277         mPhysicalDeviceAttributes.isKeyRequiresUnlockedDevice();
278     }
279 
generateCertificate(String certificateString)280     private X509Certificate generateCertificate(String certificateString)
281             throws Exception {
282         return generateCertificates(certificateString).get(0);
283     }
284 
generateCertificates(String certificateString)285     private List<X509Certificate> generateCertificates(String certificateString)
286             throws Exception {
287         Collection<? extends Certificate> certificates = mFactory.generateCertificates(
288                 InstrumentationRegistry.getInstrumentation().getContext().getResources().getAssets()
289                         .open(certificateString));
290 
291         ArrayList<X509Certificate> x509Certs = new ArrayList<>();
292         for (Certificate cert : certificates) {
293             x509Certs.add((X509Certificate) cert);
294         }
295         return x509Certs;
296     }
297 }
298