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