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