• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019, The Android Open Source Project, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *   http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package com.google.android.attestation;
17 
18 import static com.google.android.attestation.AuthorizationList.UserAuthType.FINGERPRINT;
19 import static com.google.android.attestation.AuthorizationList.UserAuthType.PASSWORD;
20 import static com.google.android.attestation.AuthorizationList.UserAuthType.USER_AUTH_TYPE_ANY;
21 import static com.google.android.attestation.AuthorizationList.UserAuthType.USER_AUTH_TYPE_NONE;
22 import static com.google.android.attestation.Constants.KM_TAG_ACTIVE_DATE_TIME;
23 import static com.google.android.attestation.Constants.KM_TAG_ALGORITHM;
24 import static com.google.android.attestation.Constants.KM_TAG_ALLOW_WHILE_ON_BODY;
25 import static com.google.android.attestation.Constants.KM_TAG_ALL_APPLICATIONS;
26 import static com.google.android.attestation.Constants.KM_TAG_APPLICATION_ID;
27 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_APPLICATION_ID;
28 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_BRAND;
29 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_DEVICE;
30 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_IMEI;
31 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_MANUFACTURER;
32 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_MEID;
33 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_MODEL;
34 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_PRODUCT;
35 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_SECOND_IMEI;
36 import static com.google.android.attestation.Constants.KM_TAG_ATTESTATION_ID_SERIAL;
37 import static com.google.android.attestation.Constants.KM_TAG_AUTH_TIMEOUT;
38 import static com.google.android.attestation.Constants.KM_TAG_BOOT_PATCH_LEVEL;
39 import static com.google.android.attestation.Constants.KM_TAG_CREATION_DATE_TIME;
40 import static com.google.android.attestation.Constants.KM_TAG_DEVICE_UNIQUE_ATTESTATION;
41 import static com.google.android.attestation.Constants.KM_TAG_IDENTITY_CREDENTIAL_KEY;
42 import static com.google.android.attestation.Constants.KM_TAG_DIGEST;
43 import static com.google.android.attestation.Constants.KM_TAG_EC_CURVE;
44 import static com.google.android.attestation.Constants.KM_TAG_KEY_SIZE;
45 import static com.google.android.attestation.Constants.KM_TAG_NO_AUTH_REQUIRED;
46 import static com.google.android.attestation.Constants.KM_TAG_ORIGIN;
47 import static com.google.android.attestation.Constants.KM_TAG_ORIGINATION_EXPIRE_DATE_TIME;
48 import static com.google.android.attestation.Constants.KM_TAG_OS_PATCH_LEVEL;
49 import static com.google.android.attestation.Constants.KM_TAG_OS_VERSION;
50 import static com.google.android.attestation.Constants.KM_TAG_PADDING;
51 import static com.google.android.attestation.Constants.KM_TAG_PURPOSE;
52 import static com.google.android.attestation.Constants.KM_TAG_ROLLBACK_RESISTANCE;
53 import static com.google.android.attestation.Constants.KM_TAG_ROLLBACK_RESISTANT;
54 import static com.google.android.attestation.Constants.KM_TAG_ROOT_OF_TRUST;
55 import static com.google.android.attestation.Constants.KM_TAG_RSA_PUBLIC_EXPONENT;
56 import static com.google.android.attestation.Constants.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED;
57 import static com.google.android.attestation.Constants.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED;
58 import static com.google.android.attestation.Constants.KM_TAG_UNLOCKED_DEVICE_REQUIRED;
59 import static com.google.android.attestation.Constants.KM_TAG_USAGE_EXPIRE_DATE_TIME;
60 import static com.google.android.attestation.Constants.KM_TAG_USER_AUTH_TYPE;
61 import static com.google.android.attestation.Constants.KM_TAG_VENDOR_PATCH_LEVEL;
62 import static com.google.android.attestation.Constants.UINT32_MAX;
63 
64 import java.time.Duration;
65 import java.time.Instant;
66 import java.util.HashMap;
67 import java.util.HashSet;
68 import java.util.Map;
69 import java.util.Optional;
70 import java.util.Set;
71 import com.google.errorprone.annotations.CanIgnoreReturnValue;
72 import com.google.common.collect.ImmutableSet;
73 import org.bouncycastle.asn1.ASN1Encodable;
74 import org.bouncycastle.asn1.ASN1EncodableVector;
75 import org.bouncycastle.asn1.ASN1Integer;
76 import org.bouncycastle.asn1.ASN1OctetString;
77 import org.bouncycastle.asn1.ASN1Primitive;
78 import org.bouncycastle.asn1.ASN1Sequence;
79 import org.bouncycastle.asn1.ASN1Set;
80 import org.bouncycastle.asn1.ASN1TaggedObject;
81 import org.bouncycastle.asn1.DERNull;
82 import org.bouncycastle.asn1.DEROctetString;
83 import org.bouncycastle.asn1.DERSequence;
84 import org.bouncycastle.asn1.DERSet;
85 import org.bouncycastle.asn1.DERTaggedObject;
86 
87 /**
88  * This data structure contains the key pair's properties themselves, as defined in the Keymaster
89  * hardware abstraction layer (HAL). You compare these values to the device's current state or to a
90  * set of expected values to verify that a key pair is still valid for use in your app.
91  */
92 @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
93 public class AuthorizationList {
94   /** Specifies the types of user authenticators that may be used to authorize this key. */
95   public enum UserAuthType {
96     USER_AUTH_TYPE_NONE,
97     PASSWORD,
98     FINGERPRINT,
99     USER_AUTH_TYPE_ANY
100   }
101 
102   public final Optional<Set<Integer>> purpose;
103   public final Optional<Integer> algorithm;
104   public final Optional<Integer> keySize;
105   public final Optional<Set<Integer>> digest;
106   public final Optional<Set<Integer>> padding;
107   public final Optional<Integer> ecCurve;
108   public final Optional<Long> rsaPublicExponent;
109   public final boolean rollbackResistance;
110   public final Optional<Instant> activeDateTime;
111   public final Optional<Instant> originationExpireDateTime;
112   public final Optional<Instant> usageExpireDateTime;
113   public final boolean noAuthRequired;
114   public final Optional<Set<UserAuthType>> userAuthType;
115   public final Optional<Duration> authTimeout;
116   public final boolean allowWhileOnBody;
117   public final boolean trustedUserPresenceRequired;
118   public final boolean trustedConfirmationRequired;
119   public final boolean unlockedDeviceRequired;
120   public final boolean allApplications;
121   public final Optional<byte[]> applicationId;
122   public final Optional<Instant> creationDateTime;
123   public final Optional<Integer> origin;
124   public final boolean rollbackResistant;
125   public final Optional<RootOfTrust> rootOfTrust;
126   public final Optional<Integer> osVersion;
127   public final Optional<Integer> osPatchLevel;
128   public final Optional<AttestationApplicationId> attestationApplicationId;
129   public final Optional<byte[]> attestationApplicationIdBytes;
130   public final Optional<byte[]> attestationIdBrand;
131   public final Optional<byte[]> attestationIdDevice;
132   public final Optional<byte[]> attestationIdProduct;
133   public final Optional<byte[]> attestationIdSerial;
134   public final Optional<byte[]> attestationIdImei;
135   public final Optional<byte[]> attestationIdSecondImei;
136   public final Optional<byte[]> attestationIdMeid;
137   public final Optional<byte[]> attestationIdManufacturer;
138   public final Optional<byte[]> attestationIdModel;
139   public final Optional<Integer> vendorPatchLevel;
140   public final Optional<Integer> bootPatchLevel;
141   public final boolean individualAttestation;
142   public final boolean identityCredentialKey;
143 
AuthorizationList(ASN1Encodable[] authorizationList, int attestationVersion)144   private AuthorizationList(ASN1Encodable[] authorizationList, int attestationVersion) {
145     Map<Integer, ASN1Primitive> authorizationMap = getAuthorizationMap(authorizationList);
146     this.purpose = findOptionalIntegerSetAuthorizationListEntry(authorizationMap, KM_TAG_PURPOSE);
147     this.algorithm = findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_ALGORITHM);
148     this.keySize = findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_KEY_SIZE);
149     this.digest = findOptionalIntegerSetAuthorizationListEntry(authorizationMap, KM_TAG_DIGEST);
150     this.padding = findOptionalIntegerSetAuthorizationListEntry(authorizationMap, KM_TAG_PADDING);
151     this.ecCurve = findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_EC_CURVE);
152     this.rsaPublicExponent =
153         findOptionalLongAuthorizationListEntry(authorizationMap, KM_TAG_RSA_PUBLIC_EXPONENT);
154     this.rollbackResistance =
155         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_ROLLBACK_RESISTANCE);
156     this.activeDateTime =
157         findOptionalInstantMillisAuthorizationListEntry(authorizationMap, KM_TAG_ACTIVE_DATE_TIME);
158     this.originationExpireDateTime =
159         findOptionalInstantMillisAuthorizationListEntry(
160             authorizationMap, KM_TAG_ORIGINATION_EXPIRE_DATE_TIME);
161     this.usageExpireDateTime =
162         findOptionalInstantMillisAuthorizationListEntry(
163             authorizationMap, KM_TAG_USAGE_EXPIRE_DATE_TIME);
164     this.noAuthRequired =
165         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_NO_AUTH_REQUIRED);
166     this.userAuthType = findOptionalUserAuthType(authorizationMap, KM_TAG_USER_AUTH_TYPE);
167     this.authTimeout =
168         findOptionalDurationSecondsAuthorizationListEntry(authorizationMap, KM_TAG_AUTH_TIMEOUT);
169     this.allowWhileOnBody =
170         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_ALLOW_WHILE_ON_BODY);
171     this.trustedUserPresenceRequired =
172         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
173     this.trustedConfirmationRequired =
174         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
175     this.unlockedDeviceRequired =
176         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_UNLOCKED_DEVICE_REQUIRED);
177     this.allApplications =
178         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_ALL_APPLICATIONS);
179     this.applicationId =
180         findOptionalByteArrayAuthorizationListEntry(authorizationMap, KM_TAG_APPLICATION_ID);
181     this.creationDateTime =
182         findOptionalInstantMillisAuthorizationListEntry(
183             authorizationMap, KM_TAG_CREATION_DATE_TIME);
184     this.origin = findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_ORIGIN);
185     this.rollbackResistant =
186         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_ROLLBACK_RESISTANT);
187     this.rootOfTrust =
188         Optional.ofNullable(
189             RootOfTrust.createRootOfTrust(
190                 (ASN1Sequence) findAuthorizationListEntry(authorizationMap, KM_TAG_ROOT_OF_TRUST),
191                 attestationVersion));
192     this.osVersion = findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_OS_VERSION);
193     this.osPatchLevel =
194         findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_OS_PATCH_LEVEL);
195     this.attestationApplicationId =
196         Optional.ofNullable(
197             AttestationApplicationId.createAttestationApplicationId(
198                 (DEROctetString)
199                     findAuthorizationListEntry(
200                         authorizationMap, KM_TAG_ATTESTATION_APPLICATION_ID)));
201     this.attestationApplicationIdBytes =
202         findOptionalByteArrayAuthorizationListEntry(
203             authorizationMap, KM_TAG_ATTESTATION_APPLICATION_ID);
204     this.attestationIdBrand =
205         findOptionalByteArrayAuthorizationListEntry(authorizationMap, KM_TAG_ATTESTATION_ID_BRAND);
206     this.attestationIdDevice =
207         findOptionalByteArrayAuthorizationListEntry(authorizationMap, KM_TAG_ATTESTATION_ID_DEVICE);
208     this.attestationIdProduct =
209         findOptionalByteArrayAuthorizationListEntry(
210             authorizationMap, KM_TAG_ATTESTATION_ID_PRODUCT);
211     this.attestationIdSerial =
212         findOptionalByteArrayAuthorizationListEntry(authorizationMap, KM_TAG_ATTESTATION_ID_SERIAL);
213     this.attestationIdImei =
214         findOptionalByteArrayAuthorizationListEntry(authorizationMap, KM_TAG_ATTESTATION_ID_IMEI);
215     this.attestationIdSecondImei =
216             findOptionalByteArrayAuthorizationListEntry(authorizationMap, KM_TAG_ATTESTATION_ID_SECOND_IMEI);
217     this.attestationIdMeid =
218         findOptionalByteArrayAuthorizationListEntry(authorizationMap, KM_TAG_ATTESTATION_ID_MEID);
219     this.attestationIdManufacturer =
220         findOptionalByteArrayAuthorizationListEntry(
221             authorizationMap, KM_TAG_ATTESTATION_ID_MANUFACTURER);
222     this.attestationIdModel =
223         findOptionalByteArrayAuthorizationListEntry(authorizationMap, KM_TAG_ATTESTATION_ID_MODEL);
224     this.vendorPatchLevel =
225         findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_VENDOR_PATCH_LEVEL);
226     this.bootPatchLevel =
227         findOptionalIntegerAuthorizationListEntry(authorizationMap, KM_TAG_BOOT_PATCH_LEVEL);
228     this.individualAttestation =
229         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_DEVICE_UNIQUE_ATTESTATION);
230     this.identityCredentialKey =
231         findBooleanAuthorizationListEntry(authorizationMap, KM_TAG_IDENTITY_CREDENTIAL_KEY);
232 
233   }
234 
AuthorizationList(Builder builder)235   private AuthorizationList(Builder builder) {
236     this.purpose = Optional.ofNullable(builder.purpose);
237     this.algorithm = Optional.ofNullable(builder.algorithm);
238     this.keySize = Optional.ofNullable(builder.keySize);
239     this.digest = Optional.ofNullable(builder.digest);
240     this.padding = Optional.ofNullable(builder.padding);
241     this.ecCurve = Optional.ofNullable(builder.ecCurve);
242     this.rsaPublicExponent = Optional.ofNullable(builder.rsaPublicExponent);
243     this.rollbackResistance = builder.rollbackResistance;
244     this.activeDateTime = Optional.ofNullable(builder.activeDateTime);
245     this.originationExpireDateTime = Optional.ofNullable(builder.originationExpireDateTime);
246     this.usageExpireDateTime = Optional.ofNullable(builder.usageExpireDateTime);
247     this.noAuthRequired = builder.noAuthRequired;
248     this.userAuthType = Optional.ofNullable(builder.userAuthType);
249     this.authTimeout = Optional.ofNullable(builder.authTimeout);
250     this.allowWhileOnBody = builder.allowWhileOnBody;
251     this.trustedUserPresenceRequired = builder.trustedUserPresenceRequired;
252     this.trustedConfirmationRequired = builder.trustedConfirmationRequired;
253     this.unlockedDeviceRequired = builder.unlockedDeviceRequired;
254     this.allApplications = builder.allApplications;
255     this.applicationId = Optional.ofNullable(builder.applicationId);
256     this.creationDateTime = Optional.ofNullable(builder.creationDateTime);
257     this.origin = Optional.ofNullable(builder.origin);
258     this.rollbackResistant = builder.rollbackResistant;
259     this.rootOfTrust = Optional.ofNullable(builder.rootOfTrust);
260     this.osVersion = Optional.ofNullable(builder.osVersion);
261     this.osPatchLevel = Optional.ofNullable(builder.osPatchLevel);
262     this.attestationApplicationId = Optional.ofNullable(builder.attestationApplicationId);
263     this.attestationApplicationIdBytes = Optional.ofNullable(builder.attestationApplicationIdBytes);
264     this.attestationIdBrand = Optional.ofNullable(builder.attestationIdBrand);
265     this.attestationIdDevice = Optional.ofNullable(builder.attestationIdDevice);
266     this.attestationIdProduct = Optional.ofNullable(builder.attestationIdProduct);
267     this.attestationIdSerial = Optional.ofNullable(builder.attestationIdSerial);
268     this.attestationIdImei = Optional.ofNullable(builder.attestationIdImei);
269     this.attestationIdSecondImei = Optional.ofNullable(builder.attestationIdSecondImei);
270     this.attestationIdMeid = Optional.ofNullable(builder.attestationIdMeid);
271     this.attestationIdManufacturer = Optional.ofNullable(builder.attestationIdManufacturer);
272     this.attestationIdModel = Optional.ofNullable(builder.attestationIdModel);
273     this.vendorPatchLevel = Optional.ofNullable(builder.vendorPatchLevel);
274     this.bootPatchLevel = Optional.ofNullable(builder.bootPatchLevel);
275     this.individualAttestation = builder.individualAttestation;
276     this.identityCredentialKey = builder.identityCredentialKey;
277   }
278 
createAuthorizationList( ASN1Encodable[] authorizationList, int attestationVersion)279   static AuthorizationList createAuthorizationList(
280       ASN1Encodable[] authorizationList, int attestationVersion) {
281     return new AuthorizationList(authorizationList, attestationVersion);
282   }
283 
getAuthorizationMap( ASN1Encodable[] authorizationList)284   private static Map<Integer, ASN1Primitive> getAuthorizationMap(
285       ASN1Encodable[] authorizationList) {
286     Map<Integer, ASN1Primitive> authorizationMap = new HashMap<>();
287     for (ASN1Encodable entry : authorizationList) {
288       ASN1TaggedObject taggedEntry = (ASN1TaggedObject) entry;
289       authorizationMap.put(taggedEntry.getTagNo(), taggedEntry.getObject());
290     }
291     return authorizationMap;
292   }
293 
findAuthorizationListEntry( Map<Integer, ASN1Primitive> authorizationMap, int tag)294   private static ASN1Primitive findAuthorizationListEntry(
295       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
296     return authorizationMap.getOrDefault(tag, null);
297   }
298 
findOptionalIntegerSetAuthorizationListEntry( Map<Integer, ASN1Primitive> authorizationMap, int tag)299   private static Optional<Set<Integer>> findOptionalIntegerSetAuthorizationListEntry(
300       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
301     ASN1Set asn1Set = (ASN1Set) findAuthorizationListEntry(authorizationMap, tag);
302     if (asn1Set == null) {
303       return Optional.empty();
304     }
305     Set<Integer> entrySet = new HashSet<>();
306     for (ASN1Encodable value : asn1Set) {
307       entrySet.add(ASN1Parsing.getIntegerFromAsn1(value));
308     }
309     return Optional.of(entrySet);
310   }
311 
findOptionalDurationSecondsAuthorizationListEntry( Map<Integer, ASN1Primitive> authorizationMap, int tag)312   private static Optional<Duration> findOptionalDurationSecondsAuthorizationListEntry(
313       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
314     Optional<Integer> seconds = findOptionalIntegerAuthorizationListEntry(authorizationMap, tag);
315     return seconds.map(Duration::ofSeconds);
316   }
317 
findOptionalIntegerAuthorizationListEntry( Map<Integer, ASN1Primitive> authorizationMap, int tag)318   private static Optional<Integer> findOptionalIntegerAuthorizationListEntry(
319       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
320     ASN1Primitive entry = findAuthorizationListEntry(authorizationMap, tag);
321     return Optional.ofNullable(entry).map(ASN1Parsing::getIntegerFromAsn1);
322   }
323 
findOptionalInstantMillisAuthorizationListEntry( Map<Integer, ASN1Primitive> authorizationMap, int tag)324   private static Optional<Instant> findOptionalInstantMillisAuthorizationListEntry(
325       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
326     Optional<Long> millis = findOptionalLongAuthorizationListEntry(authorizationMap, tag);
327     return millis.map(Instant::ofEpochMilli);
328   }
329 
findOptionalLongAuthorizationListEntry( Map<Integer, ASN1Primitive> authorizationMap, int tag)330   private static Optional<Long> findOptionalLongAuthorizationListEntry(
331       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
332     ASN1Integer longEntry = ((ASN1Integer) findAuthorizationListEntry(authorizationMap, tag));
333     return Optional.ofNullable(longEntry).map(value -> value.getValue().longValue());
334   }
335 
findBooleanAuthorizationListEntry( Map<Integer, ASN1Primitive> authorizationMap, int tag)336   private static boolean findBooleanAuthorizationListEntry(
337       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
338     return null != findAuthorizationListEntry(authorizationMap, tag);
339   }
340 
findOptionalByteArrayAuthorizationListEntry( Map<Integer, ASN1Primitive> authorizationMap, int tag)341   private static Optional<byte[]> findOptionalByteArrayAuthorizationListEntry(
342       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
343     ASN1OctetString entry = (ASN1OctetString) findAuthorizationListEntry(authorizationMap, tag);
344     return Optional.ofNullable(entry).map(ASN1OctetString::getOctets);
345   }
346 
findOptionalUserAuthType( Map<Integer, ASN1Primitive> authorizationMap, int tag)347   private static Optional<Set<UserAuthType>> findOptionalUserAuthType(
348       Map<Integer, ASN1Primitive> authorizationMap, int tag) {
349     Optional<Long> userAuthType = findOptionalLongAuthorizationListEntry(authorizationMap, tag);
350     return userAuthType.map(AuthorizationList::userAuthTypeToEnum);
351   }
352 
353   // Visible for testing.
userAuthTypeToEnum(long userAuthType)354   static Set<UserAuthType> userAuthTypeToEnum(long userAuthType) {
355     if (userAuthType == 0) {
356       return ImmutableSet.of(USER_AUTH_TYPE_NONE);
357     }
358 
359     Set<UserAuthType> result = new HashSet<>();
360 
361     if ((userAuthType & 1L) == 1L) {
362       result.add(PASSWORD);
363     }
364     if ((userAuthType & 2L) == 2L) {
365       result.add(FINGERPRINT);
366     }
367     if (userAuthType == UINT32_MAX) {
368       result.add(USER_AUTH_TYPE_ANY);
369     }
370 
371     if (result.isEmpty()) {
372       throw new IllegalArgumentException("Invalid User Auth Type.");
373     }
374 
375     return result;
376   }
377 
userAuthTypeToLong(Set<UserAuthType> userAuthType)378   private static Long userAuthTypeToLong(Set<UserAuthType> userAuthType) {
379     if (userAuthType.contains(USER_AUTH_TYPE_NONE)) {
380       return 0L;
381     }
382 
383     long result = 0L;
384 
385     for (UserAuthType type : userAuthType) {
386       switch (type) {
387         case PASSWORD:
388           result |= 1L;
389           break;
390         case FINGERPRINT:
391           result |= 2L;
392           break;
393         case USER_AUTH_TYPE_ANY:
394           result |= UINT32_MAX;
395           break;
396         default:
397           break;
398       }
399     }
400 
401     if (result == 0) {
402       throw new IllegalArgumentException("Invalid User Auth Type.");
403     }
404 
405     return result;
406   }
407 
toAsn1Sequence()408   public ASN1Sequence toAsn1Sequence() {
409     ASN1EncodableVector vector = new ASN1EncodableVector();
410     addOptionalIntegerSet(KM_TAG_PURPOSE, this.purpose, vector);
411     addOptionalInteger(KM_TAG_ALGORITHM, this.algorithm, vector);
412     addOptionalInteger(KM_TAG_KEY_SIZE, this.keySize, vector);
413     addOptionalIntegerSet(KM_TAG_DIGEST, this.digest, vector);
414     addOptionalIntegerSet(KM_TAG_PADDING, this.padding, vector);
415     addOptionalInteger(KM_TAG_EC_CURVE, this.ecCurve, vector);
416     addOptionalLong(KM_TAG_RSA_PUBLIC_EXPONENT, this.rsaPublicExponent, vector);
417     addBoolean(KM_TAG_ROLLBACK_RESISTANCE, this.rollbackResistance, vector);
418     addOptionalInstant(KM_TAG_ACTIVE_DATE_TIME, this.activeDateTime, vector);
419     addOptionalInstant(KM_TAG_ORIGINATION_EXPIRE_DATE_TIME, this.originationExpireDateTime, vector);
420     addOptionalInstant(KM_TAG_USAGE_EXPIRE_DATE_TIME, this.usageExpireDateTime, vector);
421     addBoolean(KM_TAG_NO_AUTH_REQUIRED, this.noAuthRequired, vector);
422     addOptionalUserAuthType(KM_TAG_USER_AUTH_TYPE, this.userAuthType, vector);
423     addOptionalDuration(KM_TAG_AUTH_TIMEOUT, this.authTimeout, vector);
424     addBoolean(KM_TAG_ALLOW_WHILE_ON_BODY, this.allowWhileOnBody, vector);
425     addBoolean(KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED, this.trustedUserPresenceRequired, vector);
426     addBoolean(KM_TAG_TRUSTED_CONFIRMATION_REQUIRED, this.trustedConfirmationRequired, vector);
427     addBoolean(KM_TAG_UNLOCKED_DEVICE_REQUIRED, this.unlockedDeviceRequired, vector);
428     addBoolean(KM_TAG_ALL_APPLICATIONS, this.allApplications, vector);
429     addOptionalOctetString(KM_TAG_APPLICATION_ID, this.applicationId, vector);
430     addOptionalInstant(KM_TAG_CREATION_DATE_TIME, this.creationDateTime, vector);
431     addOptionalInteger(KM_TAG_ORIGIN, this.origin, vector);
432     addBoolean(KM_TAG_ROLLBACK_RESISTANT, this.rollbackResistant, vector);
433     addOptionalRootOfTrust(KM_TAG_ROOT_OF_TRUST, this.rootOfTrust, vector);
434     addOptionalInteger(KM_TAG_OS_VERSION, this.osVersion, vector);
435     addOptionalInteger(KM_TAG_OS_PATCH_LEVEL, this.osPatchLevel, vector);
436     addOptionalOctetString(
437         KM_TAG_ATTESTATION_APPLICATION_ID, this.attestationApplicationIdBytes, vector);
438     addOptionalOctetString(KM_TAG_ATTESTATION_ID_BRAND, this.attestationIdBrand, vector);
439     addOptionalOctetString(KM_TAG_ATTESTATION_ID_DEVICE, this.attestationIdDevice, vector);
440     addOptionalOctetString(KM_TAG_ATTESTATION_ID_PRODUCT, this.attestationIdProduct, vector);
441     addOptionalOctetString(KM_TAG_ATTESTATION_ID_SERIAL, this.attestationIdSerial, vector);
442     addOptionalOctetString(KM_TAG_ATTESTATION_ID_IMEI, this.attestationIdImei, vector);
443     addOptionalOctetString(KM_TAG_ATTESTATION_ID_SECOND_IMEI, this.attestationIdSecondImei, vector);
444     addOptionalOctetString(KM_TAG_ATTESTATION_ID_MEID, this.attestationIdMeid, vector);
445     addOptionalOctetString(
446         KM_TAG_ATTESTATION_ID_MANUFACTURER, this.attestationIdManufacturer, vector);
447     addOptionalOctetString(KM_TAG_ATTESTATION_ID_MODEL, this.attestationIdModel, vector);
448     addOptionalInteger(KM_TAG_VENDOR_PATCH_LEVEL, this.vendorPatchLevel, vector);
449     addOptionalInteger(KM_TAG_BOOT_PATCH_LEVEL, this.bootPatchLevel, vector);
450     addBoolean(KM_TAG_DEVICE_UNIQUE_ATTESTATION, this.individualAttestation, vector);
451     return new DERSequence(vector);
452   }
453 
addOptionalIntegerSet( int tag, Optional<Set<Integer>> entry, ASN1EncodableVector vector)454   private static void addOptionalIntegerSet(
455       int tag, Optional<Set<Integer>> entry, ASN1EncodableVector vector) {
456     if (entry.isPresent()) {
457       ASN1EncodableVector tmp = new ASN1EncodableVector();
458       entry.get().forEach((Integer value) -> tmp.add(new ASN1Integer(value.longValue())));
459       vector.add(new DERTaggedObject(tag, new DERSet(tmp)));
460     }
461   }
462 
addOptionalInstant( int tag, Optional<Instant> entry, ASN1EncodableVector vector)463   private static void addOptionalInstant(
464       int tag, Optional<Instant> entry, ASN1EncodableVector vector) {
465     if (entry.isPresent()) {
466       vector.add(new DERTaggedObject(tag, new ASN1Integer(entry.get().toEpochMilli())));
467     }
468   }
469 
addOptionalDuration( int tag, Optional<Duration> entry, ASN1EncodableVector vector)470   private static void addOptionalDuration(
471       int tag, Optional<Duration> entry, ASN1EncodableVector vector) {
472     if (entry.isPresent()) {
473       vector.add(new DERTaggedObject(tag, new ASN1Integer(entry.get().getSeconds())));
474     }
475   }
476 
addBoolean(int tag, boolean entry, ASN1EncodableVector vector)477   private static void addBoolean(int tag, boolean entry, ASN1EncodableVector vector) {
478     if (entry) {
479       vector.add(new DERTaggedObject(tag, DERNull.INSTANCE));
480     }
481   }
482 
addOptionalInteger( int tag, Optional<Integer> entry, ASN1EncodableVector vector)483   private static void addOptionalInteger(
484       int tag, Optional<Integer> entry, ASN1EncodableVector vector) {
485     if (entry.isPresent()) {
486       vector.add(new DERTaggedObject(tag, new ASN1Integer(entry.get())));
487     }
488   }
489 
addOptionalLong(int tag, Optional<Long> entry, ASN1EncodableVector vector)490   private static void addOptionalLong(int tag, Optional<Long> entry, ASN1EncodableVector vector) {
491     if (entry.isPresent()) {
492       vector.add(new DERTaggedObject(tag, new ASN1Integer(entry.get())));
493     }
494   }
495 
addOptionalOctetString( int tag, Optional<byte[]> entry, ASN1EncodableVector vector)496   private static void addOptionalOctetString(
497       int tag, Optional<byte[]> entry, ASN1EncodableVector vector) {
498     if (entry.isPresent()) {
499       vector.add(new DERTaggedObject(tag, new DEROctetString(entry.get())));
500     }
501   }
502 
addOptionalUserAuthType( int tag, Optional<Set<UserAuthType>> entry, ASN1EncodableVector vector)503   private static void addOptionalUserAuthType(
504       int tag, Optional<Set<UserAuthType>> entry, ASN1EncodableVector vector) {
505     if (entry.isPresent()) {
506       vector.add(new DERTaggedObject(tag, new ASN1Integer(userAuthTypeToLong(entry.get()))));
507     }
508   }
509 
addOptionalRootOfTrust( int tag, Optional<RootOfTrust> entry, ASN1EncodableVector vector)510   private static void addOptionalRootOfTrust(
511       int tag, Optional<RootOfTrust> entry, ASN1EncodableVector vector) {
512     if (entry.isPresent()) {
513       vector.add(new DERTaggedObject(tag, entry.get().toAsn1Sequence()));
514     }
515   }
516 
builder()517   public static Builder builder() {
518     return new Builder();
519   }
520 
521   /**
522    * Builder for an AuthorizationList. Any field not set will be made an Optional.empty or set with
523    * the default value.
524    */
525   public static final class Builder {
526 
527     Set<Integer> purpose;
528     Integer algorithm;
529     Integer keySize;
530     Set<Integer> digest;
531     Set<Integer> padding;
532     Integer ecCurve;
533     Long rsaPublicExponent;
534     boolean rollbackResistance;
535     Instant activeDateTime;
536     Instant originationExpireDateTime;
537     Instant usageExpireDateTime;
538     boolean noAuthRequired;
539     Set<UserAuthType> userAuthType;
540     Duration authTimeout;
541     boolean allowWhileOnBody;
542     boolean trustedUserPresenceRequired;
543     boolean trustedConfirmationRequired;
544     boolean unlockedDeviceRequired;
545     boolean allApplications;
546     byte[] applicationId;
547     Instant creationDateTime;
548     Integer origin;
549     boolean rollbackResistant;
550     RootOfTrust rootOfTrust;
551     Integer osVersion;
552     Integer osPatchLevel;
553     AttestationApplicationId attestationApplicationId;
554     byte[] attestationApplicationIdBytes;
555     byte[] attestationIdBrand;
556     byte[] attestationIdDevice;
557     byte[] attestationIdProduct;
558     byte[] attestationIdSerial;
559     byte[] attestationIdImei;
560     byte[] attestationIdSecondImei;
561     byte[] attestationIdMeid;
562     byte[] attestationIdManufacturer;
563     byte[] attestationIdModel;
564     Integer vendorPatchLevel;
565     Integer bootPatchLevel;
566     boolean individualAttestation;
567     boolean identityCredentialKey;
568 
569     @CanIgnoreReturnValue
setPurpose(Set<Integer> purpose)570     public Builder setPurpose(Set<Integer> purpose) {
571       this.purpose = purpose;
572       return this;
573     }
574 
575     @CanIgnoreReturnValue
setAlgorithm(Integer algorithm)576     public Builder setAlgorithm(Integer algorithm) {
577       this.algorithm = algorithm;
578       return this;
579     }
580 
581     @CanIgnoreReturnValue
setKeySize(Integer keySize)582     public Builder setKeySize(Integer keySize) {
583       this.keySize = keySize;
584       return this;
585     }
586 
587     @CanIgnoreReturnValue
setDigest(Set<Integer> digest)588     public Builder setDigest(Set<Integer> digest) {
589       this.digest = digest;
590       return this;
591     }
592 
593     @CanIgnoreReturnValue
setPadding(Set<Integer> padding)594     public Builder setPadding(Set<Integer> padding) {
595       this.padding = padding;
596       return this;
597     }
598 
599     @CanIgnoreReturnValue
setEcCurve(Integer ecCurve)600     public Builder setEcCurve(Integer ecCurve) {
601       this.ecCurve = ecCurve;
602       return this;
603     }
604 
605     @CanIgnoreReturnValue
setRsaPublicExponent(Long rsaPublicExponent)606     public Builder setRsaPublicExponent(Long rsaPublicExponent) {
607       this.rsaPublicExponent = rsaPublicExponent;
608       return this;
609     }
610 
611     @CanIgnoreReturnValue
setRollbackResistance(boolean rollbackResistance)612     public Builder setRollbackResistance(boolean rollbackResistance) {
613       this.rollbackResistance = rollbackResistance;
614       return this;
615     }
616 
617     @CanIgnoreReturnValue
setActiveDateTime(Instant activeDateTime)618     public Builder setActiveDateTime(Instant activeDateTime) {
619       this.activeDateTime = activeDateTime;
620       return this;
621     }
622 
623     @CanIgnoreReturnValue
setOriginationExpireDateTime(Instant originationExpireDateTime)624     public Builder setOriginationExpireDateTime(Instant originationExpireDateTime) {
625       this.originationExpireDateTime = originationExpireDateTime;
626       return this;
627     }
628 
629     @CanIgnoreReturnValue
setUsageExpireDateTime(Instant usageExpireDateTime)630     public Builder setUsageExpireDateTime(Instant usageExpireDateTime) {
631       this.usageExpireDateTime = usageExpireDateTime;
632       return this;
633     }
634 
635     @CanIgnoreReturnValue
setNoAuthRequired(boolean noAuthRequired)636     public Builder setNoAuthRequired(boolean noAuthRequired) {
637       this.noAuthRequired = noAuthRequired;
638       return this;
639     }
640 
641     @CanIgnoreReturnValue
setUserAuthType(Set<UserAuthType> userAuthType)642     public Builder setUserAuthType(Set<UserAuthType> userAuthType) {
643       this.userAuthType = userAuthType;
644       return this;
645     }
646 
647     @CanIgnoreReturnValue
setAuthTimeout(Duration authTimeout)648     public Builder setAuthTimeout(Duration authTimeout) {
649       this.authTimeout = authTimeout;
650       return this;
651     }
652 
653     @CanIgnoreReturnValue
setAllowWhileOnBody(boolean allowWhileOnBody)654     public Builder setAllowWhileOnBody(boolean allowWhileOnBody) {
655       this.allowWhileOnBody = allowWhileOnBody;
656       return this;
657     }
658 
659     @CanIgnoreReturnValue
setTrustedUserPresenceRequired(boolean trustedUserPresenceRequired)660     public Builder setTrustedUserPresenceRequired(boolean trustedUserPresenceRequired) {
661       this.trustedUserPresenceRequired = trustedUserPresenceRequired;
662       return this;
663     }
664 
665     @CanIgnoreReturnValue
setTrustedConfirmationRequired(boolean trustedConfirmationRequired)666     public Builder setTrustedConfirmationRequired(boolean trustedConfirmationRequired) {
667       this.trustedConfirmationRequired = trustedConfirmationRequired;
668       return this;
669     }
670 
671     @CanIgnoreReturnValue
setUnlockedDeviceRequired(boolean unlockedDeviceRequired)672     public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) {
673       this.unlockedDeviceRequired = unlockedDeviceRequired;
674       return this;
675     }
676 
677     @CanIgnoreReturnValue
setAllApplications(boolean allApplications)678     public Builder setAllApplications(boolean allApplications) {
679       this.allApplications = allApplications;
680       return this;
681     }
682 
683     @CanIgnoreReturnValue
setApplicationId(byte[] applicationId)684     public Builder setApplicationId(byte[] applicationId) {
685       this.applicationId = applicationId;
686       return this;
687     }
688 
689     @CanIgnoreReturnValue
setCreationDateTime(Instant creationDateTime)690     public Builder setCreationDateTime(Instant creationDateTime) {
691       this.creationDateTime = creationDateTime;
692       return this;
693     }
694 
695     @CanIgnoreReturnValue
setOrigin(Integer origin)696     public Builder setOrigin(Integer origin) {
697       this.origin = origin;
698       return this;
699     }
700 
701     @CanIgnoreReturnValue
setRollbackResistant(boolean rollbackResistant)702     public Builder setRollbackResistant(boolean rollbackResistant) {
703       this.rollbackResistant = rollbackResistant;
704       return this;
705     }
706 
707     @CanIgnoreReturnValue
setRootOfTrust(RootOfTrust rootOfTrust)708     public Builder setRootOfTrust(RootOfTrust rootOfTrust) {
709       this.rootOfTrust = rootOfTrust;
710       return this;
711     }
712 
713     @CanIgnoreReturnValue
setOsVersion(Integer osVersion)714     public Builder setOsVersion(Integer osVersion) {
715       this.osVersion = osVersion;
716       return this;
717     }
718 
719     @CanIgnoreReturnValue
setOsPatchLevel(Integer osPatchLevel)720     public Builder setOsPatchLevel(Integer osPatchLevel) {
721       this.osPatchLevel = osPatchLevel;
722       return this;
723     }
724 
725     @CanIgnoreReturnValue
setAttestationApplicationId(AttestationApplicationId attestationApplicationId)726     public Builder setAttestationApplicationId(AttestationApplicationId attestationApplicationId) {
727       this.attestationApplicationId = attestationApplicationId;
728       return this;
729     }
730 
731     @CanIgnoreReturnValue
setAttestationApplicationIdBytes(byte[] attestationApplicationIdBytes)732     public Builder setAttestationApplicationIdBytes(byte[] attestationApplicationIdBytes) {
733       this.attestationApplicationIdBytes = attestationApplicationIdBytes;
734       return this;
735     }
736 
737     @CanIgnoreReturnValue
setAttestationIdBrand(byte[] attestationIdBrand)738     public Builder setAttestationIdBrand(byte[] attestationIdBrand) {
739       this.attestationIdBrand = attestationIdBrand;
740       return this;
741     }
742 
743     @CanIgnoreReturnValue
setAttestationIdDevice(byte[] attestationIdDevice)744     public Builder setAttestationIdDevice(byte[] attestationIdDevice) {
745       this.attestationIdDevice = attestationIdDevice;
746       return this;
747     }
748 
749     @CanIgnoreReturnValue
setAttestationIdProduct(byte[] attestationIdProduct)750     public Builder setAttestationIdProduct(byte[] attestationIdProduct) {
751       this.attestationIdProduct = attestationIdProduct;
752       return this;
753     }
754 
755     @CanIgnoreReturnValue
setAttestationIdSerial(byte[] attestationIdSerial)756     public Builder setAttestationIdSerial(byte[] attestationIdSerial) {
757       this.attestationIdSerial = attestationIdSerial;
758       return this;
759     }
760 
761     @CanIgnoreReturnValue
setAttestationIdImei(byte[] attestationIdImei)762     public Builder setAttestationIdImei(byte[] attestationIdImei) {
763       this.attestationIdImei = attestationIdImei;
764       return this;
765     }
766 
767     @CanIgnoreReturnValue
setAttestationIdSecondImei(byte[] attestationIdSecondImei)768     public Builder setAttestationIdSecondImei(byte[] attestationIdSecondImei) {
769       this.attestationIdSecondImei = attestationIdSecondImei;
770       return this;
771     }
772 
773     @CanIgnoreReturnValue
setAttestationIdMeid(byte[] attestationIdMeid)774     public Builder setAttestationIdMeid(byte[] attestationIdMeid) {
775       this.attestationIdMeid = attestationIdMeid;
776       return this;
777     }
778 
779     @CanIgnoreReturnValue
setAttestationIdManufacturer(byte[] attestationIdManufacturer)780     public Builder setAttestationIdManufacturer(byte[] attestationIdManufacturer) {
781       this.attestationIdManufacturer = attestationIdManufacturer;
782       return this;
783     }
784 
785     @CanIgnoreReturnValue
setAttestationIdModel(byte[] attestationIdModel)786     public Builder setAttestationIdModel(byte[] attestationIdModel) {
787       this.attestationIdModel = attestationIdModel;
788       return this;
789     }
790 
791     @CanIgnoreReturnValue
setVendorPatchLevel(Integer vendorPatchLevel)792     public Builder setVendorPatchLevel(Integer vendorPatchLevel) {
793       this.vendorPatchLevel = vendorPatchLevel;
794       return this;
795     }
796 
797     @CanIgnoreReturnValue
setBootPatchLevel(Integer bootPatchLevel)798     public Builder setBootPatchLevel(Integer bootPatchLevel) {
799       this.bootPatchLevel = bootPatchLevel;
800       return this;
801     }
802 
803     @CanIgnoreReturnValue
setIndividualAttestation(boolean individualAttestation)804     public Builder setIndividualAttestation(boolean individualAttestation) {
805       this.individualAttestation = individualAttestation;
806       return this;
807     }
808 
809     @CanIgnoreReturnValue
setIdentityCredentialKey(boolean identityCredentialKey)810     public Builder setIdentityCredentialKey(boolean identityCredentialKey) {
811       this.identityCredentialKey = identityCredentialKey;
812       return this;
813     }
814 
build()815     public AuthorizationList build() {
816       return new AuthorizationList(this);
817     }
818   }
819 }
820