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 17 package com.android.server.security; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 22 import com.android.framework.protobuf.ByteString; 23 import com.android.internal.org.bouncycastle.asn1.ASN1Boolean; 24 import com.android.internal.org.bouncycastle.asn1.ASN1Encodable; 25 import com.android.internal.org.bouncycastle.asn1.ASN1Enumerated; 26 import com.android.internal.org.bouncycastle.asn1.ASN1InputStream; 27 import com.android.internal.org.bouncycastle.asn1.ASN1Integer; 28 import com.android.internal.org.bouncycastle.asn1.ASN1ObjectIdentifier; 29 import com.android.internal.org.bouncycastle.asn1.ASN1OctetString; 30 import com.android.internal.org.bouncycastle.asn1.ASN1Sequence; 31 import com.android.internal.org.bouncycastle.asn1.ASN1Set; 32 import com.android.internal.org.bouncycastle.asn1.ASN1TaggedObject; 33 import com.android.internal.org.bouncycastle.asn1.x509.Certificate; 34 35 import java.nio.charset.StandardCharsets; 36 import java.security.cert.CertificateEncodingException; 37 import java.security.cert.X509Certificate; 38 import java.util.ArrayList; 39 import java.util.Collections; 40 import java.util.HashMap; 41 import java.util.List; 42 import java.util.Map; 43 44 /** 45 * Parsed {@link X509Certificate} attestation extension values for Android Keystore attestations. 46 * 47 * Pull fields out of the top-level sequence. A full description of this structure is at 48 * https://source.android.com/security/keystore/attestation. 49 * 50 * If a value is null or empty, then it was not set/found in the extension values. 51 * 52 */ 53 class AndroidKeystoreAttestationVerificationAttributes { 54 // The OID for the extension Android Keymaster puts into device-generated certificates. 55 private static final String ANDROID_KEYMASTER_KEY_DESCRIPTION_EXTENSION_OID = 56 "1.3.6.1.4.1.11129.2.1.17"; 57 58 // ASN.1 sequence index values for the Android Keymaster extension. 59 private static final int ATTESTATION_VERSION_INDEX = 0; 60 private static final int ATTESTATION_SECURITY_LEVEL_INDEX = 1; 61 private static final int KEYMASTER_VERSION_INDEX = 2; 62 private static final int KEYMASTER_SECURITY_LEVEL_INDEX = 3; 63 private static final int ATTESTATION_CHALLENGE_INDEX = 4; 64 private static final int KEYMASTER_UNIQUE_ID_INDEX = 5; 65 private static final int SW_ENFORCED_INDEX = 6; 66 private static final int HW_ENFORCED_INDEX = 7; 67 private static final int VERIFIED_BOOT_KEY_INDEX = 0; 68 private static final int VERIFIED_BOOT_LOCKED_INDEX = 1; 69 private static final int VERIFIED_BOOT_STATE_INDEX = 2; 70 private static final int VERIFIED_BOOT_HASH_INDEX = 3; 71 72 // ASN.1 sequence index values for the Android Keystore application id. 73 private static final int PACKAGE_INFO_SET_INDEX = 0; 74 private static final int PACKAGE_SIGNATURE_SET_INDEX = 1; 75 private static final int PACKAGE_INFO_NAME_INDEX = 0; 76 private static final int PACKAGE_INFO_VERSION_INDEX = 1; 77 78 // See these AOSP files: hardware/libhardware/include/hardware/hw_auth_token.h 79 private static final int HW_AUTH_NONE = 0; 80 81 // Some keymaster constants. See this AOSP file: 82 // hardware/libhardware/include/hardware/keymaster_defs.h 83 private static final int KM_TAG_NO_AUTH_REQUIRED = 503; 84 private static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = 509; 85 private static final int KM_TAG_ALL_APPLICATIONS = 600; 86 private static final int KM_TAG_ROOT_OF_TRUST = 704; 87 private static final int KM_TAG_OS_VERSION = 705; 88 private static final int KM_TAG_OS_PATCHLEVEL = 706; 89 private static final int KM_TAG_ATTESTATION_APPLICATION_ID = 709; 90 private static final int KM_TAG_ATTESTATION_ID_BRAND = 710; 91 private static final int KM_TAG_ATTESTATION_ID_DEVICE = 711; 92 private static final int KM_TAG_ATTESTATION_ID_PRODUCT = 712; 93 private static final int KM_TAG_VENDOR_PATCHLEVEL = 718; 94 private static final int KM_TAG_BOOT_PATCHLEVEL = 719; 95 96 private static final int KM_SECURITY_LEVEL_SOFTWARE = 0; 97 private static final int KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT = 1; 98 private static final int KM_SECURITY_LEVEL_STRONG_BOX = 2; 99 private static final int KM_VERIFIED_BOOT_STATE_VERIFIED = 0; 100 private static final int KM_VERIFIED_BOOT_STATE_SELF_SIGNED = 1; 101 private static final int KM_VERIFIED_BOOT_STATE_UNVERIFIED = 2; 102 private static final int KM_VERIFIED_BOOT_STATE_FAILED = 3; 103 104 private Integer mAttestationVersion = null; 105 private SecurityLevel mAttestationSecurityLevel = null; 106 private boolean mAttestationHardwareBacked = false; 107 private Integer mKeymasterVersion = null; 108 private SecurityLevel mKeymasterSecurityLevel = null; 109 private boolean mKeymasterHardwareBacked = false; 110 private ByteString mAttestationChallenge = null; 111 private ByteString mKeymasterUniqueId = null; 112 private String mDeviceBrand = null; 113 private String mDeviceName = null; 114 private String mDeviceProductName = null; 115 private boolean mKeyAllowedForAllApplications = false; 116 private Integer mKeyAuthenticatorType = null; 117 private Integer mKeyBootPatchLevel = null; 118 private Integer mKeyOsPatchLevel = null; 119 private Integer mKeyOsVersion = null; 120 private Integer mKeyVendorPatchLevel = null; 121 private Boolean mKeyRequiresUnlockedDevice = null; 122 private ByteString mVerifiedBootHash = null; 123 private ByteString mVerifiedBootKey = null; 124 private Boolean mVerifiedBootLocked = null; 125 private VerifiedBootState mVerifiedBootState = null; 126 private Map<String, Long> mApplicationPackageNameVersion = null; 127 private List<ByteString> mApplicationCertificateDigests = null; 128 129 enum VerifiedBootState { 130 VERIFIED, 131 SELF_SIGNED, 132 UNVERIFIED, 133 FAILED 134 } 135 136 enum SecurityLevel { 137 SOFTWARE, 138 TRUSTED_ENVIRONMENT, 139 STRONG_BOX 140 } 141 142 /** 143 * Extracts attestation extension properties from {@link X509Certificate} 144 * and returns a {@link AndroidKeystoreAttestationVerificationAttributes} that encapsulates the 145 * properties. 146 */ 147 @NonNull fromCertificate( @onNull X509Certificate x509Certificate)148 static AndroidKeystoreAttestationVerificationAttributes fromCertificate( 149 @NonNull X509Certificate x509Certificate) 150 throws Exception { 151 return new AndroidKeystoreAttestationVerificationAttributes(x509Certificate); 152 } 153 getAttestationVersion()154 int getAttestationVersion() { 155 return mAttestationVersion; 156 } 157 158 @Nullable getAttestationSecurityLevel()159 SecurityLevel getAttestationSecurityLevel() { 160 return mAttestationSecurityLevel; 161 } 162 isAttestationHardwareBacked()163 boolean isAttestationHardwareBacked() { 164 return mAttestationHardwareBacked; 165 } 166 getKeymasterVersion()167 int getKeymasterVersion() { 168 return mKeymasterVersion; 169 } 170 171 @Nullable getKeymasterSecurityLevel()172 SecurityLevel getKeymasterSecurityLevel() { 173 return mKeymasterSecurityLevel; 174 } 175 isKeymasterHardwareBacked()176 boolean isKeymasterHardwareBacked() { 177 return mKeymasterHardwareBacked; 178 } 179 180 @Nullable getAttestationChallenge()181 ByteString getAttestationChallenge() { 182 return mAttestationChallenge; 183 } 184 185 @Nullable getKeymasterUniqueId()186 ByteString getKeymasterUniqueId() { 187 return mKeymasterUniqueId; 188 } 189 190 @Nullable getDeviceBrand()191 String getDeviceBrand() { 192 return mDeviceBrand; 193 } 194 195 @Nullable getDeviceName()196 String getDeviceName() { 197 return mDeviceName; 198 } 199 200 @Nullable getDeviceProductName()201 String getDeviceProductName() { 202 return mDeviceProductName; 203 } 204 isKeyAllowedForAllApplications()205 boolean isKeyAllowedForAllApplications() { 206 return mKeyAllowedForAllApplications; 207 } 208 getKeyAuthenticatorType()209 int getKeyAuthenticatorType() { 210 if (mKeyAuthenticatorType == null) { 211 throw new IllegalStateException("KeyAuthenticatorType is not set."); 212 } 213 return mKeyAuthenticatorType; 214 } 215 getKeyBootPatchLevel()216 int getKeyBootPatchLevel() { 217 if (mKeyBootPatchLevel == null) { 218 throw new IllegalStateException("KeyBootPatchLevel is not set."); 219 } 220 return mKeyBootPatchLevel; 221 } 222 getKeyOsPatchLevel()223 int getKeyOsPatchLevel() { 224 if (mKeyOsPatchLevel == null) { 225 throw new IllegalStateException("KeyOsPatchLevel is not set."); 226 } 227 return mKeyOsPatchLevel; 228 } 229 getKeyVendorPatchLevel()230 int getKeyVendorPatchLevel() { 231 if (mKeyVendorPatchLevel == null) { 232 throw new IllegalStateException("KeyVendorPatchLevel is not set."); 233 } 234 return mKeyVendorPatchLevel; 235 } 236 getKeyOsVersion()237 int getKeyOsVersion() { 238 if (mKeyOsVersion == null) { 239 throw new IllegalStateException("KeyOsVersion is not set."); 240 } 241 return mKeyOsVersion; 242 } 243 isKeyRequiresUnlockedDevice()244 boolean isKeyRequiresUnlockedDevice() { 245 if (mKeyRequiresUnlockedDevice == null) { 246 throw new IllegalStateException("KeyRequiresUnlockedDevice is not set."); 247 } 248 return mKeyRequiresUnlockedDevice; 249 } 250 251 @Nullable getVerifiedBootHash()252 ByteString getVerifiedBootHash() { 253 return mVerifiedBootHash; 254 } 255 256 @Nullable getVerifiedBootKey()257 ByteString getVerifiedBootKey() { 258 return mVerifiedBootKey; 259 } 260 isVerifiedBootLocked()261 boolean isVerifiedBootLocked() { 262 if (mVerifiedBootLocked == null) { 263 throw new IllegalStateException("VerifiedBootLocked is not set."); 264 } 265 return mVerifiedBootLocked; 266 } 267 268 @Nullable getVerifiedBootState()269 VerifiedBootState getVerifiedBootState() { 270 return mVerifiedBootState; 271 } 272 273 @Nullable getApplicationPackageNameVersion()274 Map<String, Long> getApplicationPackageNameVersion() { 275 return Collections.unmodifiableMap(mApplicationPackageNameVersion); 276 } 277 278 @Nullable getApplicationCertificateDigests()279 List<ByteString> getApplicationCertificateDigests() { 280 return Collections.unmodifiableList(mApplicationCertificateDigests); 281 } 282 AndroidKeystoreAttestationVerificationAttributes(X509Certificate x509Certificate)283 private AndroidKeystoreAttestationVerificationAttributes(X509Certificate x509Certificate) 284 throws Exception { 285 Certificate certificate = Certificate.getInstance( 286 new ASN1InputStream(x509Certificate.getEncoded()).readObject()); 287 ASN1Sequence keyAttributes = (ASN1Sequence) certificate.getTBSCertificate().getExtensions() 288 .getExtensionParsedValue( 289 new ASN1ObjectIdentifier(ANDROID_KEYMASTER_KEY_DESCRIPTION_EXTENSION_OID)); 290 if (keyAttributes == null) { 291 throw new CertificateEncodingException( 292 "No attestation extension found in certificate."); 293 } 294 this.mAttestationVersion = getIntegerFromAsn1( 295 keyAttributes.getObjectAt(ATTESTATION_VERSION_INDEX)); 296 this.mAttestationSecurityLevel = getSecurityLevelEnum( 297 keyAttributes.getObjectAt(ATTESTATION_SECURITY_LEVEL_INDEX)); 298 this.mAttestationHardwareBacked = 299 this.mAttestationSecurityLevel == SecurityLevel.TRUSTED_ENVIRONMENT; 300 this.mAttestationChallenge = getOctetsFromAsn1( 301 keyAttributes.getObjectAt(ATTESTATION_CHALLENGE_INDEX)); 302 this.mKeymasterVersion = getIntegerFromAsn1( 303 keyAttributes.getObjectAt(KEYMASTER_VERSION_INDEX)); 304 this.mKeymasterUniqueId = getOctetsFromAsn1( 305 keyAttributes.getObjectAt(KEYMASTER_UNIQUE_ID_INDEX)); 306 this.mKeymasterSecurityLevel = getSecurityLevelEnum( 307 keyAttributes.getObjectAt(KEYMASTER_SECURITY_LEVEL_INDEX)); 308 this.mKeymasterHardwareBacked = 309 this.mKeymasterSecurityLevel == SecurityLevel.TRUSTED_ENVIRONMENT; 310 311 ASN1Encodable[] softwareEnforced = ((ASN1Sequence) 312 keyAttributes.getObjectAt(SW_ENFORCED_INDEX)).toArray(); 313 for (ASN1Encodable entry : softwareEnforced) { 314 ASN1TaggedObject taggedEntry = (ASN1TaggedObject) entry; 315 switch (taggedEntry.getTagNo()) { 316 case KM_TAG_ATTESTATION_APPLICATION_ID: 317 parseAttestationApplicationId( 318 getOctetsFromAsn1(taggedEntry.getObject()).toByteArray()); 319 break; 320 case KM_TAG_UNLOCKED_DEVICE_REQUIRED: 321 this.mKeyRequiresUnlockedDevice = getBoolFromAsn1(taggedEntry.getObject()); 322 break; 323 default: 324 break; 325 } 326 } 327 328 ASN1Encodable[] hardwareEnforced = ((ASN1Sequence) 329 keyAttributes.getObjectAt(HW_ENFORCED_INDEX)).toArray(); 330 for (ASN1Encodable entry : hardwareEnforced) { 331 ASN1TaggedObject taggedEntry = (ASN1TaggedObject) entry; 332 switch (taggedEntry.getTagNo()) { 333 case KM_TAG_NO_AUTH_REQUIRED: 334 this.mKeyAuthenticatorType = HW_AUTH_NONE; 335 break; 336 case KM_TAG_ALL_APPLICATIONS: 337 this.mKeyAllowedForAllApplications = true; 338 break; 339 case KM_TAG_ROOT_OF_TRUST: 340 ASN1Sequence rootOfTrust = (ASN1Sequence) taggedEntry.getObject(); 341 this.mVerifiedBootKey = 342 getOctetsFromAsn1(rootOfTrust.getObjectAt(VERIFIED_BOOT_KEY_INDEX)); 343 this.mVerifiedBootLocked = 344 getBoolFromAsn1(rootOfTrust.getObjectAt(VERIFIED_BOOT_LOCKED_INDEX)); 345 this.mVerifiedBootState = 346 getVerifiedBootStateEnum( 347 rootOfTrust.getObjectAt(VERIFIED_BOOT_STATE_INDEX)); 348 // The verified boot hash was added in structure version 3 (Keymaster 4.0). 349 if (mAttestationVersion >= 3) { 350 this.mVerifiedBootHash = 351 getOctetsFromAsn1( 352 rootOfTrust.getObjectAt(VERIFIED_BOOT_HASH_INDEX)); 353 } 354 break; 355 case KM_TAG_OS_VERSION: 356 this.mKeyOsVersion = getIntegerFromAsn1(taggedEntry.getObject()); 357 break; 358 case KM_TAG_OS_PATCHLEVEL: 359 this.mKeyOsPatchLevel = getIntegerFromAsn1(taggedEntry.getObject()); 360 break; 361 case KM_TAG_ATTESTATION_ID_BRAND: 362 this.mDeviceBrand = getUtf8FromOctetsFromAsn1(taggedEntry.getObject()); 363 break; 364 case KM_TAG_ATTESTATION_ID_DEVICE: 365 this.mDeviceName = getUtf8FromOctetsFromAsn1(taggedEntry.getObject()); 366 break; 367 case KM_TAG_ATTESTATION_ID_PRODUCT: 368 this.mDeviceProductName = getUtf8FromOctetsFromAsn1(taggedEntry.getObject()); 369 break; 370 case KM_TAG_VENDOR_PATCHLEVEL: 371 this.mKeyVendorPatchLevel = getIntegerFromAsn1(taggedEntry.getObject()); 372 break; 373 case KM_TAG_BOOT_PATCHLEVEL: 374 this.mKeyBootPatchLevel = getIntegerFromAsn1(taggedEntry.getObject()); 375 break; 376 default: 377 break; 378 } 379 } 380 } 381 parseAttestationApplicationId(byte [] attestationApplicationId)382 private void parseAttestationApplicationId(byte [] attestationApplicationId) 383 throws Exception { 384 ASN1Sequence outerSequence = ASN1Sequence.getInstance( 385 new ASN1InputStream(attestationApplicationId).readObject()); 386 Map<String, Long> packageNameVersion = new HashMap<>(); 387 ASN1Set packageInfoSet = (ASN1Set) outerSequence.getObjectAt(PACKAGE_INFO_SET_INDEX); 388 for (ASN1Encodable packageInfoEntry : packageInfoSet.toArray()) { 389 ASN1Sequence packageInfoSequence = (ASN1Sequence) packageInfoEntry; 390 packageNameVersion.put( 391 getUtf8FromOctetsFromAsn1( 392 packageInfoSequence.getObjectAt(PACKAGE_INFO_NAME_INDEX)), 393 getLongFromAsn1(packageInfoSequence.getObjectAt(PACKAGE_INFO_VERSION_INDEX))); 394 } 395 List<ByteString> certificateDigests = new ArrayList<>(); 396 ASN1Set certificateDigestSet = 397 (ASN1Set) outerSequence.getObjectAt(PACKAGE_SIGNATURE_SET_INDEX); 398 for (ASN1Encodable certificateDigestEntry : certificateDigestSet.toArray()) { 399 certificateDigests.add(getOctetsFromAsn1(certificateDigestEntry)); 400 } 401 this.mApplicationPackageNameVersion = Collections.unmodifiableMap(packageNameVersion); 402 this.mApplicationCertificateDigests = Collections.unmodifiableList(certificateDigests); 403 404 } 405 getVerifiedBootStateEnum(ASN1Encodable asn1)406 private VerifiedBootState getVerifiedBootStateEnum(ASN1Encodable asn1) { 407 int verifiedBoot = getEnumFromAsn1(asn1); 408 switch (verifiedBoot) { 409 case KM_VERIFIED_BOOT_STATE_VERIFIED: 410 return VerifiedBootState.VERIFIED; 411 case KM_VERIFIED_BOOT_STATE_SELF_SIGNED: 412 return VerifiedBootState.SELF_SIGNED; 413 case KM_VERIFIED_BOOT_STATE_UNVERIFIED: 414 return VerifiedBootState.UNVERIFIED; 415 case KM_VERIFIED_BOOT_STATE_FAILED: 416 return VerifiedBootState.FAILED; 417 default: 418 throw new IllegalArgumentException("Invalid verified boot state."); 419 } 420 } 421 getSecurityLevelEnum(ASN1Encodable asn1)422 private SecurityLevel getSecurityLevelEnum(ASN1Encodable asn1) { 423 int securityLevel = getEnumFromAsn1(asn1); 424 switch (securityLevel) { 425 case KM_SECURITY_LEVEL_SOFTWARE: 426 return SecurityLevel.SOFTWARE; 427 case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT: 428 return SecurityLevel.TRUSTED_ENVIRONMENT; 429 case KM_SECURITY_LEVEL_STRONG_BOX: 430 return SecurityLevel.STRONG_BOX; 431 default: 432 throw new IllegalArgumentException("Invalid security level."); 433 } 434 } 435 436 @NonNull getOctetsFromAsn1(ASN1Encodable asn1)437 private ByteString getOctetsFromAsn1(ASN1Encodable asn1) { 438 return ByteString.copyFrom(((ASN1OctetString) asn1).getOctets()); 439 } 440 441 @NonNull getUtf8FromOctetsFromAsn1(ASN1Encodable asn1)442 private String getUtf8FromOctetsFromAsn1(ASN1Encodable asn1) { 443 return new String(((ASN1OctetString) asn1).getOctets(), StandardCharsets.UTF_8); 444 } 445 446 @NonNull getIntegerFromAsn1(ASN1Encodable asn1)447 private int getIntegerFromAsn1(ASN1Encodable asn1) { 448 return ((ASN1Integer) asn1).getValue().intValueExact(); 449 } 450 451 @NonNull getLongFromAsn1(ASN1Encodable asn1)452 private long getLongFromAsn1(ASN1Encodable asn1) { 453 return ((ASN1Integer) asn1).getValue().longValueExact(); 454 } 455 456 @NonNull getEnumFromAsn1(ASN1Encodable asn1)457 private int getEnumFromAsn1(ASN1Encodable asn1) { 458 return ((ASN1Enumerated) asn1).getValue().intValueExact(); 459 } 460 461 @Nullable getBoolFromAsn1(ASN1Encodable asn1)462 private Boolean getBoolFromAsn1(ASN1Encodable asn1) { 463 if (asn1 instanceof ASN1Boolean) { 464 return ((ASN1Boolean) asn1).isTrue(); 465 } 466 return null; 467 } 468 } 469