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