• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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