1 /* 2 * Copyright (C) 2016 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 android.keystore.cts; 18 19 import static com.android.compatibility.common.util.PropertyUtil.getVsrApiLevel; 20 21 import static com.google.common.base.Functions.forMap; 22 import static com.google.common.collect.Collections2.transform; 23 24 import android.os.Build; 25 import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_AGREE_KEY; 26 import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_ENCRYPT; 27 import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_DECRYPT; 28 import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_SIGN; 29 import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_VERIFY; 30 import android.security.keystore.KeyProperties; 31 import android.util.Log; 32 33 import com.google.common.base.Joiner; 34 import com.google.common.collect.ImmutableMap; 35 import com.google.common.collect.ImmutableSet; 36 import com.google.common.collect.Lists; 37 38 import org.bouncycastle.asn1.ASN1Encodable; 39 import org.bouncycastle.asn1.ASN1Primitive; 40 import org.bouncycastle.asn1.ASN1Sequence; 41 import org.bouncycastle.asn1.ASN1SequenceParser; 42 import org.bouncycastle.asn1.ASN1TaggedObject; 43 44 import java.io.IOException; 45 import java.io.UnsupportedEncodingException; 46 import java.security.cert.CertificateParsingException; 47 import java.text.DateFormat; 48 import java.util.Collection; 49 import java.util.Date; 50 import java.util.HexFormat; 51 import java.util.List; 52 import java.util.Set; 53 54 import co.nstant.in.cbor.model.DataItem; 55 import co.nstant.in.cbor.model.Number; 56 57 public class AuthorizationList { 58 // Algorithm values. 59 public static final int KM_ALGORITHM_RSA = 1; 60 public static final int KM_ALGORITHM_EC = 3; 61 62 // EC Curves 63 public static final int KM_EC_CURVE_P224 = 0; 64 public static final int KM_EC_CURVE_P256 = 1; 65 public static final int KM_EC_CURVE_P384 = 2; 66 public static final int KM_EC_CURVE_P521 = 3; 67 public static final int KM_EC_CURVE_25519 = 4; 68 69 // Padding modes. 70 public static final int KM_PAD_NONE = 1; 71 public static final int KM_PAD_RSA_OAEP = 2; 72 public static final int KM_PAD_RSA_PSS = 3; 73 public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = 4; 74 public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = 5; 75 76 // Digest modes. 77 public static final int KM_DIGEST_NONE = 0; 78 public static final int KM_DIGEST_MD5 = 1; 79 public static final int KM_DIGEST_SHA1 = 2; 80 public static final int KM_DIGEST_SHA_2_224 = 3; 81 public static final int KM_DIGEST_SHA_2_256 = 4; 82 public static final int KM_DIGEST_SHA_2_384 = 5; 83 public static final int KM_DIGEST_SHA_2_512 = 6; 84 85 // Key origins. 86 public static final int KM_ORIGIN_GENERATED = 0; 87 public static final int KM_ORIGIN_IMPORTED = 2; 88 public static final int KM_ORIGIN_UNKNOWN = 3; 89 90 // User authenticators. 91 public static final int HW_AUTH_PASSWORD = 1 << 0; 92 public static final int HW_AUTH_FINGERPRINT = 1 << 1; 93 94 // Keymaster tag classes 95 private static final int KM_ENUM = 1 << 28; 96 private static final int KM_ENUM_REP = 2 << 28; 97 private static final int KM_UINT = 3 << 28; 98 private static final int KM_ULONG = 5 << 28; 99 private static final int KM_DATE = 6 << 28; 100 private static final int KM_BOOL = 7 << 28; 101 private static final int KM_BYTES = 9 << 28; 102 103 // Tag class removal mask 104 private static final int KEYMASTER_TAG_TYPE_MASK = 0x0FFFFFFF; 105 106 // Keymaster tags 107 private static final int KM_TAG_PURPOSE = KM_ENUM_REP | 1; 108 private static final int KM_TAG_ALGORITHM = KM_ENUM | 2; 109 private static final int KM_TAG_KEY_SIZE = KM_UINT | 3; 110 private static final int KM_TAG_DIGEST = KM_ENUM_REP | 5; 111 private static final int KM_TAG_PADDING = KM_ENUM_REP | 6; 112 private static final int KM_TAG_EC_CURVE = KM_ENUM | 10; 113 private static final int KM_TAG_RSA_PUBLIC_EXPONENT = KM_ULONG | 200; 114 private static final int KM_TAG_RSA_OAEP_MGF_DIGEST = KM_ENUM | 203; 115 private static final int KM_TAG_ROLLBACK_RESISTANCE = KM_BOOL | 303; 116 private static final int KM_TAG_ACTIVE_DATETIME = KM_DATE | 400; 117 private static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401; 118 private static final int KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402; 119 private static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503; 120 private static final int KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504; 121 private static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505; 122 private static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506; 123 private static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507; 124 private static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508; 125 private static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509; 126 private static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600; 127 private static final int KM_TAG_CREATION_DATETIME = KM_DATE | 701; 128 private static final int KM_TAG_ORIGIN = KM_ENUM | 702; 129 private static final int KM_TAG_ROLLBACK_RESISTANT = KM_BOOL | 703; 130 private static final int KM_TAG_ROOT_OF_TRUST = KM_BYTES | 704; 131 private static final int KM_TAG_OS_VERSION = KM_UINT | 705; 132 private static final int KM_TAG_OS_PATCHLEVEL = KM_UINT | 706; 133 private static final int KM_TAG_ATTESTATION_APPLICATION_ID = KM_BYTES | 709; 134 private static final int KM_TAG_ATTESTATION_ID_BRAND = KM_BYTES | 710; 135 private static final int KM_TAG_ATTESTATION_ID_DEVICE = KM_BYTES | 711; 136 private static final int KM_TAG_ATTESTATION_ID_PRODUCT = KM_BYTES | 712; 137 private static final int KM_TAG_ATTESTATION_ID_SERIAL = KM_BYTES | 713; 138 private static final int KM_TAG_ATTESTATION_ID_IMEI = KM_BYTES | 714; 139 private static final int KM_TAG_ATTESTATION_ID_MEID = KM_BYTES | 715; 140 private static final int KM_TAG_ATTESTATION_ID_MANUFACTURER = KM_BYTES | 716; 141 private static final int KM_TAG_ATTESTATION_ID_MODEL = KM_BYTES | 717; 142 private static final int KM_TAG_VENDOR_PATCHLEVEL = KM_UINT | 718; 143 private static final int KM_TAG_BOOT_PATCHLEVEL = KM_UINT | 719; 144 private static final int KM_TAG_ATTESTATION_ID_SECOND_IMEI = KM_BYTES | 723; 145 private static final int KM_TAG_MODULE_HASH = KM_BYTES | 724; 146 147 // Map for converting padding values to strings 148 private static final ImmutableMap<Integer, String> paddingMap = ImmutableMap 149 .<Integer, String> builder() 150 .put(KM_PAD_NONE, "NONE") 151 .put(KM_PAD_RSA_OAEP, "OAEP") 152 .put(KM_PAD_RSA_PSS, "PSS") 153 .put(KM_PAD_RSA_PKCS1_1_5_ENCRYPT, "PKCS1 ENCRYPT") 154 .put(KM_PAD_RSA_PKCS1_1_5_SIGN, "PKCS1 SIGN") 155 .build(); 156 157 // Map for converting digest values to strings 158 private static final ImmutableMap<Integer, String> digestMap = ImmutableMap 159 .<Integer, String> builder() 160 .put(KM_DIGEST_NONE, "NONE") 161 .put(KM_DIGEST_MD5, "MD5") 162 .put(KM_DIGEST_SHA1, "SHA1") 163 .put(KM_DIGEST_SHA_2_224, "SHA224") 164 .put(KM_DIGEST_SHA_2_256, "SHA256") 165 .put(KM_DIGEST_SHA_2_384, "SHA384") 166 .put(KM_DIGEST_SHA_2_512, "SHA512") 167 .build(); 168 169 // Map for converting purpose values to strings 170 private static final ImmutableMap<Integer, String> purposeMap = ImmutableMap 171 .<Integer, String> builder() 172 .put(KM_PURPOSE_DECRYPT, "DECRYPT") 173 .put(KM_PURPOSE_ENCRYPT, "ENCRYPT") 174 .put(KM_PURPOSE_SIGN, "SIGN") 175 .put(KM_PURPOSE_VERIFY, "VERIFY") 176 .put(KM_PURPOSE_AGREE_KEY, "AGREE_KEY") 177 .build(); 178 179 private Integer securityLevel; 180 private Set<Integer> purposes; 181 private Integer algorithm; 182 private Integer keySize; 183 private Set<Integer> digests; 184 private Set<Integer> paddingModes; 185 private Integer ecCurve; 186 private Long rsaPublicExponent; 187 private Set<Integer> mRsaOaepMgfDigests; 188 private Date activeDateTime; 189 private Date originationExpireDateTime; 190 private Date usageExpireDateTime; 191 private boolean noAuthRequired; 192 private Integer userAuthType; 193 private Integer authTimeout; 194 private boolean allowWhileOnBody; 195 private boolean allApplications; 196 private byte[] applicationId; 197 private Date creationDateTime; 198 private Integer origin; 199 private boolean rollbackResistant; 200 private boolean rollbackResistance; 201 private RootOfTrust rootOfTrust; 202 private Integer osVersion; 203 private Integer osPatchLevel; 204 private Integer vendorPatchLevel; 205 private Integer bootPatchLevel; 206 private AttestationApplicationId attestationApplicationId; 207 private String brand; 208 private String device; 209 private String serialNumber; 210 private String imei; 211 private String meid; 212 private String product; 213 private String manufacturer; 214 private String model; 215 private boolean userPresenceRequired; 216 private boolean confirmationRequired; 217 private String mSecondImei; 218 private byte[] mModuleHash; 219 AuthorizationList(ASN1Encodable sequence, int attestationVersion)220 public AuthorizationList(ASN1Encodable sequence, int attestationVersion) throws CertificateParsingException { 221 this(sequence, attestationVersion, true); 222 } 223 AuthorizationList(ASN1Encodable sequence, int attestationVersion, boolean strictParsing)224 public AuthorizationList(ASN1Encodable sequence, int attestationVersion, boolean strictParsing) throws CertificateParsingException { 225 if (!(sequence instanceof ASN1Sequence)) { 226 throw new CertificateParsingException("Expected sequence for authorization list, found " 227 + sequence.getClass().getName()); 228 } 229 230 ASN1SequenceParser parser = ((ASN1Sequence) sequence).parser(); 231 ASN1TaggedObject entry = parseAsn1TaggedObject(parser); 232 int currentTag = 0, prevTag = 0; 233 for (; entry != null; entry = parseAsn1TaggedObject(parser)) { 234 prevTag = currentTag; 235 currentTag = entry.getTagNo(); 236 // The ASN.1 schema for the `AuthorizationList` in the attestation extension requires 237 // that the fields appear in numerical order of their ASN.1 tag value / KeyMint Tag 238 // value. 239 // 240 // However, this was not previously checked for, so we can only be strict about 241 // requiring the correct ordering for later VSR devices. 242 if ((prevTag > currentTag) 243 && (getVsrApiLevel() >= Build.VERSION_CODES.VANILLA_ICE_CREAM)) { 244 throw new CertificateParsingException( 245 "Incorrect order of tags in authorization list: " + currentTag); 246 } 247 ASN1Primitive value = entry.getObject(); 248 Log.i("Attestation", "Parsing tag: [" + currentTag + "], value: [" + value + "]"); 249 switch (currentTag) { 250 default: 251 throw new CertificateParsingException("Unknown tag " + currentTag + " found"); 252 253 case KM_TAG_PURPOSE & KEYMASTER_TAG_TYPE_MASK: 254 purposes = Asn1Utils.getIntegersFromAsn1Set(value); 255 break; 256 case KM_TAG_ALGORITHM & KEYMASTER_TAG_TYPE_MASK: 257 algorithm = Asn1Utils.getIntegerFromAsn1(value); 258 break; 259 case KM_TAG_KEY_SIZE & KEYMASTER_TAG_TYPE_MASK: 260 keySize = Asn1Utils.getIntegerFromAsn1(value); 261 Log.i("Attestation", "Found KEY SIZE, value: " + keySize); 262 break; 263 case KM_TAG_DIGEST & KEYMASTER_TAG_TYPE_MASK: 264 digests = Asn1Utils.getIntegersFromAsn1Set(value); 265 break; 266 case KM_TAG_PADDING & KEYMASTER_TAG_TYPE_MASK: 267 paddingModes = Asn1Utils.getIntegersFromAsn1Set(value); 268 break; 269 case KM_TAG_RSA_PUBLIC_EXPONENT & KEYMASTER_TAG_TYPE_MASK: 270 rsaPublicExponent = Asn1Utils.getLongFromAsn1(value); 271 break; 272 case KM_TAG_RSA_OAEP_MGF_DIGEST & KEYMASTER_TAG_TYPE_MASK: 273 mRsaOaepMgfDigests = Asn1Utils.getIntegersFromAsn1Set(value); 274 break; 275 case KM_TAG_NO_AUTH_REQUIRED & KEYMASTER_TAG_TYPE_MASK: 276 noAuthRequired = true; 277 break; 278 case KM_TAG_CREATION_DATETIME & KEYMASTER_TAG_TYPE_MASK: 279 creationDateTime = Asn1Utils.getDateFromAsn1(value); 280 break; 281 case KM_TAG_ORIGIN & KEYMASTER_TAG_TYPE_MASK: 282 origin = Asn1Utils.getIntegerFromAsn1(value); 283 break; 284 case KM_TAG_OS_VERSION & KEYMASTER_TAG_TYPE_MASK: 285 osVersion = Asn1Utils.getIntegerFromAsn1(value); 286 break; 287 case KM_TAG_OS_PATCHLEVEL & KEYMASTER_TAG_TYPE_MASK: 288 osPatchLevel = Asn1Utils.getIntegerFromAsn1(value); 289 break; 290 case KM_TAG_VENDOR_PATCHLEVEL & KEYMASTER_TAG_TYPE_MASK: 291 vendorPatchLevel = Asn1Utils.getIntegerFromAsn1(value); 292 break; 293 case KM_TAG_BOOT_PATCHLEVEL & KEYMASTER_TAG_TYPE_MASK: 294 bootPatchLevel = Asn1Utils.getIntegerFromAsn1(value); 295 break; 296 case KM_TAG_ACTIVE_DATETIME & KEYMASTER_TAG_TYPE_MASK: 297 activeDateTime = Asn1Utils.getDateFromAsn1(value); 298 break; 299 case KM_TAG_ORIGINATION_EXPIRE_DATETIME & KEYMASTER_TAG_TYPE_MASK: 300 originationExpireDateTime = Asn1Utils.getDateFromAsn1(value); 301 break; 302 case KM_TAG_USAGE_EXPIRE_DATETIME & KEYMASTER_TAG_TYPE_MASK: 303 usageExpireDateTime = Asn1Utils.getDateFromAsn1(value); 304 break; 305 case KM_TAG_ROLLBACK_RESISTANT & KEYMASTER_TAG_TYPE_MASK: 306 rollbackResistant = true; 307 break; 308 case KM_TAG_ROLLBACK_RESISTANCE & KEYMASTER_TAG_TYPE_MASK: 309 rollbackResistance = true; 310 break; 311 case KM_TAG_AUTH_TIMEOUT & KEYMASTER_TAG_TYPE_MASK: 312 authTimeout = Asn1Utils.getIntegerFromAsn1(value); 313 break; 314 case KM_TAG_ALLOW_WHILE_ON_BODY & KEYMASTER_TAG_TYPE_MASK: 315 allowWhileOnBody = true; 316 break; 317 case KM_TAG_EC_CURVE & KEYMASTER_TAG_TYPE_MASK: 318 ecCurve = Asn1Utils.getIntegerFromAsn1(value); 319 break; 320 case KM_TAG_USER_AUTH_TYPE & KEYMASTER_TAG_TYPE_MASK: 321 userAuthType = Asn1Utils.getIntegerFromAsn1(value); 322 break; 323 case KM_TAG_ROOT_OF_TRUST & KEYMASTER_TAG_TYPE_MASK: 324 rootOfTrust = new RootOfTrust(value, attestationVersion, strictParsing); 325 break; 326 case KM_TAG_ATTESTATION_APPLICATION_ID & KEYMASTER_TAG_TYPE_MASK: 327 attestationApplicationId = new AttestationApplicationId(Asn1Utils 328 .getAsn1EncodableFromBytes(Asn1Utils.getByteArrayFromAsn1(value))); 329 break; 330 case KM_TAG_ATTESTATION_ID_BRAND & KEYMASTER_TAG_TYPE_MASK: 331 brand = getStringFromAsn1Value(value); 332 break; 333 case KM_TAG_ATTESTATION_ID_DEVICE & KEYMASTER_TAG_TYPE_MASK: 334 device = getStringFromAsn1Value(value); 335 break; 336 case KM_TAG_ATTESTATION_ID_PRODUCT & KEYMASTER_TAG_TYPE_MASK: 337 product = getStringFromAsn1Value(value); 338 break; 339 case KM_TAG_ATTESTATION_ID_SERIAL & KEYMASTER_TAG_TYPE_MASK: 340 serialNumber = getStringFromAsn1Value(value); 341 break; 342 case KM_TAG_ATTESTATION_ID_IMEI & KEYMASTER_TAG_TYPE_MASK: 343 imei = getStringFromAsn1Value(value); 344 break; 345 case KM_TAG_ATTESTATION_ID_MEID & KEYMASTER_TAG_TYPE_MASK: 346 meid = getStringFromAsn1Value(value); 347 break; 348 case KM_TAG_ATTESTATION_ID_MANUFACTURER & KEYMASTER_TAG_TYPE_MASK: 349 manufacturer = getStringFromAsn1Value(value); 350 break; 351 case KM_TAG_ATTESTATION_ID_MODEL & KEYMASTER_TAG_TYPE_MASK: 352 model = getStringFromAsn1Value(value); 353 break; 354 case KM_TAG_ALL_APPLICATIONS & KEYMASTER_TAG_TYPE_MASK: 355 allApplications = true; 356 break; 357 case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED & KEYMASTER_TAG_TYPE_MASK: 358 userPresenceRequired = true; 359 break; 360 case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED & KEYMASTER_TAG_TYPE_MASK: 361 confirmationRequired = true; 362 break; 363 case KM_TAG_ATTESTATION_ID_SECOND_IMEI & KEYMASTER_TAG_TYPE_MASK: 364 mSecondImei = getStringFromAsn1Value(value); 365 break; 366 case KM_TAG_MODULE_HASH & KEYMASTER_TAG_TYPE_MASK: 367 mModuleHash = Asn1Utils.getByteArrayFromAsn1(value); 368 break; 369 } 370 } 371 372 } 373 AuthorizationList(co.nstant.in.cbor.model.Map submodMap)374 public AuthorizationList(co.nstant.in.cbor.model.Map submodMap) 375 throws CertificateParsingException { 376 for (DataItem key : submodMap.getKeys()) { 377 int keyInt = ((Number) key).getValue().intValue(); 378 switch (keyInt) { 379 default: 380 throw new CertificateParsingException("Unknown EAT tag: " + key); 381 382 case EatClaim.SECURITY_LEVEL: 383 securityLevel = eatSecurityLevelToKeymasterSecurityLevel( 384 CborUtils.getInt(submodMap, key)); 385 break; 386 case EatClaim.PURPOSE: 387 purposes = CborUtils.getIntSet(submodMap, key); 388 break; 389 case EatClaim.ALGORITHM: 390 algorithm = CborUtils.getInt(submodMap, key); 391 break; 392 case EatClaim.KEY_SIZE: 393 keySize = CborUtils.getInt(submodMap, key); 394 Log.i("Attestation", "Found KEY SIZE, value: " + keySize); 395 break; 396 case EatClaim.DIGEST: 397 digests = CborUtils.getIntSet(submodMap, key); 398 break; 399 case EatClaim.PADDING: 400 paddingModes = CborUtils.getIntSet(submodMap, key); 401 break; 402 case EatClaim.RSA_PUBLIC_EXPONENT: 403 rsaPublicExponent = CborUtils.getLong(submodMap, key); 404 break; 405 case EatClaim.RSA_OAEP_MGF_DIGEST: 406 mRsaOaepMgfDigests = CborUtils.getIntSet(submodMap, key); 407 break; 408 case EatClaim.NO_AUTH_REQUIRED: 409 noAuthRequired = true; 410 break; 411 case EatClaim.IAT: 412 creationDateTime = CborUtils.getDate(submodMap, key); 413 break; 414 case EatClaim.ORIGIN: 415 origin = CborUtils.getInt(submodMap, key); 416 break; 417 case EatClaim.OS_VERSION: 418 osVersion = CborUtils.getInt(submodMap, key); 419 break; 420 case EatClaim.OS_PATCHLEVEL: 421 osPatchLevel = CborUtils.getInt(submodMap, key); 422 break; 423 case EatClaim.VENDOR_PATCHLEVEL: 424 vendorPatchLevel = CborUtils.getInt(submodMap, key); 425 break; 426 case EatClaim.BOOT_PATCHLEVEL: 427 bootPatchLevel = CborUtils.getInt(submodMap, key); 428 break; 429 case EatClaim.ACTIVE_DATETIME: 430 activeDateTime = CborUtils.getDate(submodMap, key); 431 break; 432 case EatClaim.ORIGINATION_EXPIRE_DATETIME: 433 originationExpireDateTime = CborUtils.getDate(submodMap, key); 434 break; 435 case EatClaim.USAGE_EXPIRE_DATETIME: 436 usageExpireDateTime = CborUtils.getDate(submodMap, key); 437 break; 438 case EatClaim.ROLLBACK_RESISTANT: 439 rollbackResistant = true; 440 break; 441 case EatClaim.ROLLBACK_RESISTANCE: 442 rollbackResistance = true; 443 break; 444 case EatClaim.AUTH_TIMEOUT: 445 authTimeout = CborUtils.getInt(submodMap, key); 446 break; 447 case EatClaim.ALLOW_WHILE_ON_BODY: 448 allowWhileOnBody = true; 449 break; 450 case EatClaim.EC_CURVE: 451 ecCurve = CborUtils.getInt(submodMap, key); 452 break; 453 case EatClaim.USER_AUTH_TYPE: 454 userAuthType = CborUtils.getInt(submodMap, key); 455 break; 456 case EatClaim.ATTESTATION_APPLICATION_ID: 457 // TODO: The attestation application ID is currently still encoded as an ASN.1 458 // structure. Parse a CBOR structure when it's available instead. 459 attestationApplicationId = new AttestationApplicationId( 460 Asn1Utils.getAsn1EncodableFromBytes(CborUtils.getBytes(submodMap, key))); 461 break; 462 case EatClaim.ATTESTATION_ID_BRAND: 463 brand = CborUtils.getString(submodMap, key); 464 break; 465 case EatClaim.ATTESTATION_ID_DEVICE: 466 device = CborUtils.getString(submodMap, key); 467 break; 468 case EatClaim.ATTESTATION_ID_PRODUCT: 469 product = CborUtils.getString(submodMap, key); 470 break; 471 case EatClaim.ATTESTATION_ID_SERIAL: 472 serialNumber = CborUtils.getString(submodMap, key); 473 break; 474 case EatClaim.UEID: 475 // TODO: Parse depending on encoding chosen in attestation_record.cpp. 476 imei = CborUtils.getString(submodMap, key); 477 break; 478 case EatClaim.ATTESTATION_ID_MEID: 479 meid = CborUtils.getString(submodMap, key); 480 break; 481 case EatClaim.ATTESTATION_ID_MANUFACTURER: 482 manufacturer = CborUtils.getString(submodMap, key); 483 break; 484 case EatClaim.ATTESTATION_ID_MODEL: 485 model = CborUtils.getString(submodMap, key); 486 break; 487 case EatClaim.USER_PRESENCE_REQUIRED: 488 userPresenceRequired = CborUtils.getBoolean(submodMap, key); 489 break; 490 case EatClaim.TRUSTED_CONFIRMATION_REQUIRED: 491 confirmationRequired = true; 492 break; 493 } 494 } 495 } 496 algorithmToString(int algorithm)497 public static String algorithmToString(int algorithm) { 498 switch (algorithm) { 499 case KM_ALGORITHM_RSA: 500 return "RSA"; 501 case KM_ALGORITHM_EC: 502 return "ECDSA"; 503 default: 504 return "Unknown"; 505 } 506 } 507 paddingModesToString(final Set<Integer> paddingModes)508 public static String paddingModesToString(final Set<Integer> paddingModes) { 509 return joinStrings(transform(paddingModes, forMap(paddingMap, "Unknown"))); 510 } 511 paddingModeToString(int paddingMode)512 public static String paddingModeToString(int paddingMode) { 513 return forMap(paddingMap, "Unknown").apply(paddingMode); 514 } 515 digestsToString(Set<Integer> digests)516 public static String digestsToString(Set<Integer> digests) { 517 return joinStrings(transform(digests, forMap(digestMap, "Unknown"))); 518 } 519 digestToString(int digest)520 public static String digestToString(int digest) { 521 return forMap(digestMap, "Unknown").apply(digest); 522 } 523 purposesToString(Set<Integer> purposes)524 public static String purposesToString(Set<Integer> purposes) { 525 return joinStrings(transform(purposes, forMap(purposeMap, "Unknown"))); 526 } 527 userAuthTypeToString(int userAuthType)528 public static String userAuthTypeToString(int userAuthType) { 529 List<String> types = Lists.newArrayList(); 530 if ((userAuthType & HW_AUTH_FINGERPRINT) != 0) 531 types.add("Fingerprint"); 532 if ((userAuthType & HW_AUTH_PASSWORD) != 0) 533 types.add("Password"); 534 return joinStrings(types); 535 } 536 originToString(int origin)537 public static String originToString(int origin) { 538 switch (origin) { 539 case KM_ORIGIN_GENERATED: 540 return "Generated"; 541 case KM_ORIGIN_IMPORTED: 542 return "Imported"; 543 case KM_ORIGIN_UNKNOWN: 544 return "Unknown (KM0)"; 545 default: 546 return "Unknown"; 547 } 548 } 549 joinStrings(Collection<String> collection)550 private static String joinStrings(Collection<String> collection) { 551 return new StringBuilder() 552 .append("[") 553 .append(Joiner.on(", ").join(collection)) 554 .append("]") 555 .toString(); 556 } 557 formatDate(Date date)558 private static String formatDate(Date date) { 559 return DateFormat.getDateTimeInstance().format(date); 560 } 561 parseAsn1TaggedObject(ASN1SequenceParser parser)562 private static ASN1TaggedObject parseAsn1TaggedObject(ASN1SequenceParser parser) 563 throws CertificateParsingException { 564 ASN1Encodable asn1Encodable = parseAsn1Encodable(parser); 565 if (asn1Encodable == null || asn1Encodable instanceof ASN1TaggedObject) { 566 return (ASN1TaggedObject) asn1Encodable; 567 } 568 throw new CertificateParsingException( 569 "Expected tagged object, found " + asn1Encodable.getClass().getName()); 570 } 571 parseAsn1Encodable(ASN1SequenceParser parser)572 private static ASN1Encodable parseAsn1Encodable(ASN1SequenceParser parser) 573 throws CertificateParsingException { 574 try { 575 return parser.readObject(); 576 } catch (IOException e) { 577 throw new CertificateParsingException("Failed to parse ASN1 sequence", e); 578 } 579 } 580 getSecurityLevel()581 public Integer getSecurityLevel() { 582 return securityLevel; 583 } 584 getPurposes()585 public Set<Integer> getPurposes() { 586 return purposes; 587 } 588 getAlgorithm()589 public Integer getAlgorithm() { 590 return algorithm; 591 } 592 getKeySize()593 public Integer getKeySize() { 594 return keySize; 595 } 596 getDigests()597 public Set<Integer> getDigests() { 598 return digests; 599 } 600 getPaddingModes()601 public Set<Integer> getPaddingModes() { 602 return paddingModes; 603 } 604 getPaddingModesAsStrings()605 public Set<String> getPaddingModesAsStrings() throws CertificateParsingException { 606 if (paddingModes == null) { 607 return ImmutableSet.of(); 608 } 609 610 ImmutableSet.Builder<String> builder = ImmutableSet.builder(); 611 for (int paddingMode : paddingModes) { 612 switch (paddingMode) { 613 case KM_PAD_NONE: 614 builder.add(KeyProperties.ENCRYPTION_PADDING_NONE); 615 break; 616 case KM_PAD_RSA_OAEP: 617 builder.add(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP); 618 break; 619 case KM_PAD_RSA_PKCS1_1_5_ENCRYPT: 620 builder.add(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1); 621 break; 622 case KM_PAD_RSA_PKCS1_1_5_SIGN: 623 builder.add(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1); 624 break; 625 case KM_PAD_RSA_PSS: 626 builder.add(KeyProperties.SIGNATURE_PADDING_RSA_PSS); 627 break; 628 default: 629 throw new CertificateParsingException("Invalid padding mode " + paddingMode); 630 } 631 } 632 return builder.build(); 633 } 634 getEcCurve()635 public Integer getEcCurve() { 636 return ecCurve; 637 } 638 ecCurveAsString()639 public String ecCurveAsString() { 640 if (ecCurve == null) 641 return "NULL"; 642 643 switch (ecCurve) { 644 case KM_EC_CURVE_P224: 645 return "secp224r1"; 646 case KM_EC_CURVE_P256: 647 return "secp256r1"; 648 case KM_EC_CURVE_P384: 649 return "secp384r1"; 650 case KM_EC_CURVE_P521: 651 return "secp521r1"; 652 case KM_EC_CURVE_25519: 653 return "CURVE_25519"; 654 default: 655 return "unknown"; 656 } 657 } 658 getRsaPublicExponent()659 public Long getRsaPublicExponent() { 660 return rsaPublicExponent; 661 } 662 getRsaOaepMgfDigests()663 public Set<Integer> getRsaOaepMgfDigests() { 664 return mRsaOaepMgfDigests; 665 } 666 getActiveDateTime()667 public Date getActiveDateTime() { 668 return activeDateTime; 669 } 670 getOriginationExpireDateTime()671 public Date getOriginationExpireDateTime() { 672 return originationExpireDateTime; 673 } 674 getUsageExpireDateTime()675 public Date getUsageExpireDateTime() { 676 return usageExpireDateTime; 677 } 678 isNoAuthRequired()679 public boolean isNoAuthRequired() { 680 return noAuthRequired; 681 } 682 getUserAuthType()683 public Integer getUserAuthType() { 684 return userAuthType; 685 } 686 getAuthTimeout()687 public Integer getAuthTimeout() { 688 return authTimeout; 689 } 690 isAllowWhileOnBody()691 public boolean isAllowWhileOnBody() { 692 return allowWhileOnBody; 693 } 694 isAllApplications()695 public boolean isAllApplications() { 696 return allApplications; 697 } 698 getApplicationId()699 public byte[] getApplicationId() { 700 return applicationId; 701 } 702 getCreationDateTime()703 public Date getCreationDateTime() { 704 return creationDateTime; 705 } 706 getOrigin()707 public Integer getOrigin() { 708 return origin; 709 } 710 isRollbackResistant()711 public boolean isRollbackResistant() { 712 return rollbackResistant; 713 } 714 isRollbackResistance()715 public boolean isRollbackResistance() { 716 return rollbackResistance; 717 } 718 getRootOfTrust()719 public RootOfTrust getRootOfTrust() { 720 return rootOfTrust; 721 } 722 getOsVersion()723 public Integer getOsVersion() { 724 return osVersion; 725 } 726 getOsPatchLevel()727 public Integer getOsPatchLevel() { 728 return osPatchLevel; 729 } 730 getVendorPatchLevel()731 public Integer getVendorPatchLevel() { 732 return vendorPatchLevel; 733 } 734 getBootPatchLevel()735 public Integer getBootPatchLevel() { 736 return bootPatchLevel; 737 } 738 getAttestationApplicationId()739 public AttestationApplicationId getAttestationApplicationId() { 740 return attestationApplicationId; 741 } 742 getBrand()743 public String getBrand() { 744 return brand; 745 } 746 getDevice()747 public String getDevice() { 748 return device; 749 } 750 getSerialNumber()751 public String getSerialNumber() { 752 return serialNumber; 753 } 754 getImei()755 public String getImei() { 756 return imei; 757 } 758 getMeid()759 public String getMeid() { 760 return meid; 761 } 762 getProduct()763 public String getProduct() { 764 return product; 765 } 766 getManufacturer()767 public String getManufacturer() { 768 return manufacturer; 769 } 770 getModel()771 public String getModel() { 772 return model; 773 } 774 isUserPresenceRequired()775 public boolean isUserPresenceRequired() { 776 return userPresenceRequired; 777 } 778 isConfirmationRequired()779 public boolean isConfirmationRequired() { 780 return confirmationRequired; 781 } 782 getSecondImei()783 public String getSecondImei() { 784 return mSecondImei; 785 } 786 getModuleHash()787 public byte[] getModuleHash() { 788 return mModuleHash; 789 } 790 eatSecurityLevelToKeymasterSecurityLevel(int eatSecurityLevel)791 static int eatSecurityLevelToKeymasterSecurityLevel(int eatSecurityLevel) { 792 switch(eatSecurityLevel) { 793 case EatClaim.SECURITY_LEVEL_UNRESTRICTED: 794 return Attestation.KM_SECURITY_LEVEL_SOFTWARE; 795 case EatClaim.SECURITY_LEVEL_SECURE_RESTRICTED: 796 return Attestation.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT; 797 case EatClaim.SECURITY_LEVEL_HARDWARE: 798 return Attestation.KM_SECURITY_LEVEL_STRONG_BOX; 799 default: 800 throw new RuntimeException("Invalid EAT security level: " + eatSecurityLevel); 801 } 802 } 803 getStringFromAsn1Value(ASN1Primitive value)804 private String getStringFromAsn1Value(ASN1Primitive value) throws CertificateParsingException { 805 try { 806 return Asn1Utils.getStringFromAsn1OctetStreamAssumingUTF8(value); 807 } catch (UnsupportedEncodingException e) { 808 throw new CertificateParsingException("Error parsing ASN.1 value", e); 809 } 810 } 811 812 @Override toString()813 public String toString() { 814 StringBuilder s = new StringBuilder(); 815 816 if (algorithm != null) { 817 s.append("\nAlgorithm: ").append(algorithmToString(algorithm)); 818 } 819 820 if (keySize != null) { 821 s.append("\nKeySize: ").append(keySize); 822 } 823 824 if (purposes != null && !purposes.isEmpty()) { 825 s.append("\nPurposes: ").append(purposesToString(purposes)); 826 } 827 828 if (digests != null && !digests.isEmpty()) { 829 s.append("\nDigests: ").append(digestsToString(digests)); 830 } 831 832 if (paddingModes != null && !paddingModes.isEmpty()) { 833 s.append("\nPadding modes: ").append(paddingModesToString(paddingModes)); 834 } 835 836 if (ecCurve != null) { 837 s.append("\nEC Curve: ").append(ecCurveAsString()); 838 } 839 840 String label = "\nRSA exponent: "; 841 if (rsaPublicExponent != null) { 842 s.append(label).append(rsaPublicExponent); 843 } 844 845 if (mRsaOaepMgfDigests != null && !mRsaOaepMgfDigests.isEmpty()) { 846 s.append("\nRSA OAEP MGF Digests: ").append(digestsToString(mRsaOaepMgfDigests)); 847 } 848 849 if (activeDateTime != null) { 850 s.append("\nActive: ").append(formatDate(activeDateTime)); 851 } 852 853 if (originationExpireDateTime != null) { 854 s.append("\nOrigination expire: ").append(formatDate(originationExpireDateTime)); 855 } 856 857 if (usageExpireDateTime != null) { 858 s.append("\nUsage expire: ").append(formatDate(usageExpireDateTime)); 859 } 860 861 if (!noAuthRequired && userAuthType != null) { 862 s.append("\nAuth types: ").append(userAuthTypeToString(userAuthType)); 863 if (authTimeout != null) { 864 s.append("\nAuth timeout: ").append(authTimeout); 865 } 866 } 867 868 if (applicationId != null) { 869 s.append("\nApplication ID: ").append(new String(applicationId)); 870 } 871 872 if (creationDateTime != null) { 873 s.append("\nCreated: ").append(formatDate(creationDateTime)); 874 } 875 876 if (origin != null) { 877 s.append("\nOrigin: ").append(originToString(origin)); 878 } 879 880 if (rollbackResistant) { 881 s.append("\nRollback resistant: true"); 882 } 883 884 if (rollbackResistance) { 885 s.append("\nRollback resistance: true"); 886 } 887 888 if (rootOfTrust != null) { 889 s.append("\nRoot of Trust:\n"); 890 s.append(rootOfTrust); 891 } 892 893 if (osVersion != null) { 894 s.append("\nOS Version: ").append(osVersion); 895 } 896 897 if (osPatchLevel != null) { 898 s.append("\nOS Patchlevel: ").append(osPatchLevel); 899 } 900 901 if (vendorPatchLevel != null) { 902 s.append("\nVendor Patchlevel: ").append(vendorPatchLevel); 903 } 904 905 if (bootPatchLevel != null) { 906 s.append("\nBoot Patchlevel: ").append(bootPatchLevel); 907 } 908 909 if (attestationApplicationId != null) { 910 s.append("\nAttestation Application Id:").append(attestationApplicationId); 911 } 912 913 if (userPresenceRequired) { 914 s.append("\nUser presence required"); 915 } 916 917 if (confirmationRequired) { 918 s.append("\nConfirmation required"); 919 } 920 921 if (brand != null) { 922 s.append("\nBrand: ").append(brand); 923 } 924 if (device != null) { 925 s.append("\nDevice type: ").append(device); 926 } 927 if (product != null) { 928 s.append("\nProduct: ").append(product); 929 } 930 if (manufacturer != null) { 931 s.append("\nManufacturer: ").append(manufacturer); 932 } 933 if (model != null) { 934 s.append("\nModel: ").append(model); 935 } 936 if (mModuleHash != null) { 937 HexFormat hexFormat = HexFormat.of(); 938 s.append("\nModule Hash: ").append(hexFormat.formatHex(mModuleHash)); 939 } 940 return s.toString(); 941 } 942 } 943