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