1 /* 2 * Copyright (C) 2015 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.security.keystore; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.StringDef; 23 import android.annotation.SystemApi; 24 import android.os.Process; 25 import android.security.KeyStore; 26 import android.security.keymaster.KeymasterDefs; 27 28 import libcore.util.EmptyArray; 29 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 import java.util.Collection; 33 import java.util.Locale; 34 35 /** 36 * Properties of <a href="{@docRoot}training/articles/keystore.html">Android Keystore</a> keys. 37 */ 38 public abstract class KeyProperties { KeyProperties()39 private KeyProperties() {} 40 41 /** 42 * @hide 43 */ 44 @Retention(RetentionPolicy.SOURCE) 45 @IntDef(flag = true, prefix = { "AUTH_" }, value = { 46 AUTH_BIOMETRIC_STRONG, 47 AUTH_DEVICE_CREDENTIAL, 48 }) 49 public @interface AuthEnum {} 50 51 /** 52 * The non-biometric credential used to secure the device (i.e., PIN, pattern, or password) 53 */ 54 public static final int AUTH_DEVICE_CREDENTIAL = 1 << 0; 55 56 /** 57 * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the 58 * requirements for <strong>Strong</strong>, as defined by the Android CDD. 59 */ 60 public static final int AUTH_BIOMETRIC_STRONG = 1 << 1; 61 62 /** 63 * @hide 64 */ 65 @Retention(RetentionPolicy.SOURCE) 66 @IntDef(flag = true, prefix = { "PURPOSE_" }, value = { 67 PURPOSE_ENCRYPT, 68 PURPOSE_DECRYPT, 69 PURPOSE_SIGN, 70 PURPOSE_VERIFY, 71 PURPOSE_WRAP_KEY, 72 PURPOSE_AGREE_KEY, 73 PURPOSE_ATTEST_KEY, 74 }) 75 public @interface PurposeEnum {} 76 77 /** 78 * Purpose of key: encryption. 79 */ 80 public static final int PURPOSE_ENCRYPT = 1 << 0; 81 82 /** 83 * Purpose of key: decryption. 84 */ 85 public static final int PURPOSE_DECRYPT = 1 << 1; 86 87 /** 88 * Purpose of key: signing or generating a Message Authentication Code (MAC). 89 */ 90 public static final int PURPOSE_SIGN = 1 << 2; 91 92 /** 93 * Purpose of key: signature or Message Authentication Code (MAC) verification. 94 */ 95 public static final int PURPOSE_VERIFY = 1 << 3; 96 97 /** 98 * Purpose of key: wrapping and unwrapping wrapped keys for secure import. 99 */ 100 public static final int PURPOSE_WRAP_KEY = 1 << 5; 101 102 /** 103 * Purpose of key: creating a shared ECDH secret through key agreement. 104 * 105 * <p>A key having this purpose can be combined with the elliptic curve public key of another 106 * party to establish a shared secret over an insecure channel. It should be used as a 107 * parameter to {@link javax.crypto.KeyAgreement#init(java.security.Key)} (a complete example is 108 * available <a 109 * href="{@docRoot}reference/android/security/keystore/KeyGenParameterSpec#example:ecdh" 110 * >here</a>). 111 * See <a href="https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman">this 112 * article</a> for a more detailed explanation. 113 */ 114 public static final int PURPOSE_AGREE_KEY = 1 << 6; 115 116 /** 117 * Purpose of key: Signing attestaions. This purpose is incompatible with all others, meaning 118 * that when generating a key with PURPOSE_ATTEST_KEY, no other purposes may be specified. In 119 * addition, PURPOSE_ATTEST_KEY may not be specified for imported keys. 120 */ 121 public static final int PURPOSE_ATTEST_KEY = 1 << 7; 122 123 /** 124 * @hide 125 */ 126 public static abstract class Purpose { Purpose()127 private Purpose() {} 128 toKeymaster(@urposeEnum int purpose)129 public static int toKeymaster(@PurposeEnum int purpose) { 130 switch (purpose) { 131 case PURPOSE_ENCRYPT: 132 return KeymasterDefs.KM_PURPOSE_ENCRYPT; 133 case PURPOSE_DECRYPT: 134 return KeymasterDefs.KM_PURPOSE_DECRYPT; 135 case PURPOSE_SIGN: 136 return KeymasterDefs.KM_PURPOSE_SIGN; 137 case PURPOSE_VERIFY: 138 return KeymasterDefs.KM_PURPOSE_VERIFY; 139 case PURPOSE_WRAP_KEY: 140 return KeymasterDefs.KM_PURPOSE_WRAP; 141 case PURPOSE_AGREE_KEY: 142 return KeymasterDefs.KM_PURPOSE_AGREE_KEY; 143 case PURPOSE_ATTEST_KEY: 144 return KeymasterDefs.KM_PURPOSE_ATTEST_KEY; 145 default: 146 throw new IllegalArgumentException("Unknown purpose: " + purpose); 147 } 148 } 149 fromKeymaster(int purpose)150 public static @PurposeEnum int fromKeymaster(int purpose) { 151 switch (purpose) { 152 case KeymasterDefs.KM_PURPOSE_ENCRYPT: 153 return PURPOSE_ENCRYPT; 154 case KeymasterDefs.KM_PURPOSE_DECRYPT: 155 return PURPOSE_DECRYPT; 156 case KeymasterDefs.KM_PURPOSE_SIGN: 157 return PURPOSE_SIGN; 158 case KeymasterDefs.KM_PURPOSE_VERIFY: 159 return PURPOSE_VERIFY; 160 case KeymasterDefs.KM_PURPOSE_WRAP: 161 return PURPOSE_WRAP_KEY; 162 case KeymasterDefs.KM_PURPOSE_AGREE_KEY: 163 return PURPOSE_AGREE_KEY; 164 case KeymasterDefs.KM_PURPOSE_ATTEST_KEY: 165 return PURPOSE_ATTEST_KEY; 166 default: 167 throw new IllegalArgumentException("Unknown purpose: " + purpose); 168 } 169 } 170 171 @NonNull allToKeymaster(@urposeEnum int purposes)172 public static int[] allToKeymaster(@PurposeEnum int purposes) { 173 int[] result = getSetFlags(purposes); 174 for (int i = 0; i < result.length; i++) { 175 result[i] = toKeymaster(result[i]); 176 } 177 return result; 178 } 179 allFromKeymaster(@onNull Collection<Integer> purposes)180 public static @PurposeEnum int allFromKeymaster(@NonNull Collection<Integer> purposes) { 181 @PurposeEnum int result = 0; 182 for (int keymasterPurpose : purposes) { 183 result |= fromKeymaster(keymasterPurpose); 184 } 185 return result; 186 } 187 } 188 189 /** 190 * @hide 191 */ 192 @Retention(RetentionPolicy.SOURCE) 193 @StringDef(prefix = { "KEY_" }, value = { 194 KEY_ALGORITHM_RSA, 195 KEY_ALGORITHM_EC, 196 KEY_ALGORITHM_AES, 197 KEY_ALGORITHM_HMAC_SHA1, 198 KEY_ALGORITHM_HMAC_SHA224, 199 KEY_ALGORITHM_HMAC_SHA256, 200 KEY_ALGORITHM_HMAC_SHA384, 201 KEY_ALGORITHM_HMAC_SHA512, 202 }) 203 public @interface KeyAlgorithmEnum {} 204 205 /** Rivest Shamir Adleman (RSA) key. */ 206 public static final String KEY_ALGORITHM_RSA = "RSA"; 207 208 /** Elliptic Curve (EC) Cryptography key. */ 209 public static final String KEY_ALGORITHM_EC = "EC"; 210 211 /** Advanced Encryption Standard (AES) key. */ 212 public static final String KEY_ALGORITHM_AES = "AES"; 213 214 /** 215 * Triple Data Encryption Algorithm (3DES) key. 216 * 217 * @deprecated Included for interoperability with legacy systems. Prefer {@link 218 * KeyProperties#KEY_ALGORITHM_AES} for new development. 219 */ 220 @Deprecated 221 public static final String KEY_ALGORITHM_3DES = "DESede"; 222 223 /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-1 as the hash. */ 224 public static final String KEY_ALGORITHM_HMAC_SHA1 = "HmacSHA1"; 225 226 /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-224 as the hash. */ 227 public static final String KEY_ALGORITHM_HMAC_SHA224 = "HmacSHA224"; 228 229 /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-256 as the hash. */ 230 public static final String KEY_ALGORITHM_HMAC_SHA256 = "HmacSHA256"; 231 232 /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-384 as the hash. */ 233 public static final String KEY_ALGORITHM_HMAC_SHA384 = "HmacSHA384"; 234 235 /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-512 as the hash. */ 236 public static final String KEY_ALGORITHM_HMAC_SHA512 = "HmacSHA512"; 237 238 /** 239 * @hide 240 */ 241 public static abstract class KeyAlgorithm { KeyAlgorithm()242 private KeyAlgorithm() {} 243 toKeymasterAsymmetricKeyAlgorithm( @onNull @eyAlgorithmEnum String algorithm)244 public static int toKeymasterAsymmetricKeyAlgorithm( 245 @NonNull @KeyAlgorithmEnum String algorithm) { 246 if (KEY_ALGORITHM_EC.equalsIgnoreCase(algorithm)) { 247 return KeymasterDefs.KM_ALGORITHM_EC; 248 } else if (KEY_ALGORITHM_RSA.equalsIgnoreCase(algorithm)) { 249 return KeymasterDefs.KM_ALGORITHM_RSA; 250 } else { 251 throw new IllegalArgumentException("Unsupported key algorithm: " + algorithm); 252 } 253 } 254 255 @NonNull fromKeymasterAsymmetricKeyAlgorithm( int keymasterAlgorithm)256 public static @KeyAlgorithmEnum String fromKeymasterAsymmetricKeyAlgorithm( 257 int keymasterAlgorithm) { 258 switch (keymasterAlgorithm) { 259 case KeymasterDefs.KM_ALGORITHM_EC: 260 return KEY_ALGORITHM_EC; 261 case KeymasterDefs.KM_ALGORITHM_RSA: 262 return KEY_ALGORITHM_RSA; 263 default: 264 throw new IllegalArgumentException( 265 "Unsupported key algorithm: " + keymasterAlgorithm); 266 } 267 } 268 toKeymasterSecretKeyAlgorithm( @onNull @eyAlgorithmEnum String algorithm)269 public static int toKeymasterSecretKeyAlgorithm( 270 @NonNull @KeyAlgorithmEnum String algorithm) { 271 if (KEY_ALGORITHM_AES.equalsIgnoreCase(algorithm)) { 272 return KeymasterDefs.KM_ALGORITHM_AES; 273 } else if (KEY_ALGORITHM_3DES.equalsIgnoreCase(algorithm)) { 274 return KeymasterDefs.KM_ALGORITHM_3DES; 275 } else if (algorithm.toUpperCase(Locale.US).startsWith("HMAC")) { 276 return KeymasterDefs.KM_ALGORITHM_HMAC; 277 } else { 278 throw new IllegalArgumentException( 279 "Unsupported secret key algorithm: " + algorithm); 280 } 281 } 282 283 @NonNull fromKeymasterSecretKeyAlgorithm( int keymasterAlgorithm, int keymasterDigest)284 public static @KeyAlgorithmEnum String fromKeymasterSecretKeyAlgorithm( 285 int keymasterAlgorithm, int keymasterDigest) { 286 switch (keymasterAlgorithm) { 287 case KeymasterDefs.KM_ALGORITHM_AES: 288 return KEY_ALGORITHM_AES; 289 case KeymasterDefs.KM_ALGORITHM_3DES: 290 return KEY_ALGORITHM_3DES; 291 case KeymasterDefs.KM_ALGORITHM_HMAC: 292 switch (keymasterDigest) { 293 case KeymasterDefs.KM_DIGEST_SHA1: 294 return KEY_ALGORITHM_HMAC_SHA1; 295 case KeymasterDefs.KM_DIGEST_SHA_2_224: 296 return KEY_ALGORITHM_HMAC_SHA224; 297 case KeymasterDefs.KM_DIGEST_SHA_2_256: 298 return KEY_ALGORITHM_HMAC_SHA256; 299 case KeymasterDefs.KM_DIGEST_SHA_2_384: 300 return KEY_ALGORITHM_HMAC_SHA384; 301 case KeymasterDefs.KM_DIGEST_SHA_2_512: 302 return KEY_ALGORITHM_HMAC_SHA512; 303 default: 304 throw new IllegalArgumentException("Unsupported HMAC digest: " 305 + Digest.fromKeymaster(keymasterDigest)); 306 } 307 default: 308 throw new IllegalArgumentException( 309 "Unsupported key algorithm: " + keymasterAlgorithm); 310 } 311 } 312 313 /** 314 * @hide 315 * 316 * @return keymaster digest or {@code -1} if the algorithm does not involve a digest. 317 */ toKeymasterDigest(@onNull @eyAlgorithmEnum String algorithm)318 public static int toKeymasterDigest(@NonNull @KeyAlgorithmEnum String algorithm) { 319 String algorithmUpper = algorithm.toUpperCase(Locale.US); 320 if (algorithmUpper.startsWith("HMAC")) { 321 String digestUpper = algorithmUpper.substring("HMAC".length()); 322 switch (digestUpper) { 323 case "SHA1": 324 return KeymasterDefs.KM_DIGEST_SHA1; 325 case "SHA224": 326 return KeymasterDefs.KM_DIGEST_SHA_2_224; 327 case "SHA256": 328 return KeymasterDefs.KM_DIGEST_SHA_2_256; 329 case "SHA384": 330 return KeymasterDefs.KM_DIGEST_SHA_2_384; 331 case "SHA512": 332 return KeymasterDefs.KM_DIGEST_SHA_2_512; 333 default: 334 throw new IllegalArgumentException( 335 "Unsupported HMAC digest: " + digestUpper); 336 } 337 } else { 338 return -1; 339 } 340 } 341 } 342 343 /** 344 * @hide 345 */ 346 @Retention(RetentionPolicy.SOURCE) 347 @StringDef(prefix = { "BLOCK_MODE_" }, value = { 348 BLOCK_MODE_ECB, 349 BLOCK_MODE_CBC, 350 BLOCK_MODE_CTR, 351 BLOCK_MODE_GCM, 352 }) 353 public @interface BlockModeEnum {} 354 355 /** Electronic Codebook (ECB) block mode. */ 356 public static final String BLOCK_MODE_ECB = "ECB"; 357 358 /** Cipher Block Chaining (CBC) block mode. */ 359 public static final String BLOCK_MODE_CBC = "CBC"; 360 361 /** Counter (CTR) block mode. */ 362 public static final String BLOCK_MODE_CTR = "CTR"; 363 364 /** Galois/Counter Mode (GCM) block mode. */ 365 public static final String BLOCK_MODE_GCM = "GCM"; 366 367 /** 368 * @hide 369 */ 370 public static abstract class BlockMode { BlockMode()371 private BlockMode() {} 372 toKeymaster(@onNull @lockModeEnum String blockMode)373 public static int toKeymaster(@NonNull @BlockModeEnum String blockMode) { 374 if (BLOCK_MODE_ECB.equalsIgnoreCase(blockMode)) { 375 return KeymasterDefs.KM_MODE_ECB; 376 } else if (BLOCK_MODE_CBC.equalsIgnoreCase(blockMode)) { 377 return KeymasterDefs.KM_MODE_CBC; 378 } else if (BLOCK_MODE_CTR.equalsIgnoreCase(blockMode)) { 379 return KeymasterDefs.KM_MODE_CTR; 380 } else if (BLOCK_MODE_GCM.equalsIgnoreCase(blockMode)) { 381 return KeymasterDefs.KM_MODE_GCM; 382 } else { 383 throw new IllegalArgumentException("Unsupported block mode: " + blockMode); 384 } 385 } 386 387 @NonNull fromKeymaster(int blockMode)388 public static @BlockModeEnum String fromKeymaster(int blockMode) { 389 switch (blockMode) { 390 case KeymasterDefs.KM_MODE_ECB: 391 return BLOCK_MODE_ECB; 392 case KeymasterDefs.KM_MODE_CBC: 393 return BLOCK_MODE_CBC; 394 case KeymasterDefs.KM_MODE_CTR: 395 return BLOCK_MODE_CTR; 396 case KeymasterDefs.KM_MODE_GCM: 397 return BLOCK_MODE_GCM; 398 default: 399 throw new IllegalArgumentException("Unsupported block mode: " + blockMode); 400 } 401 } 402 403 @NonNull allFromKeymaster( @onNull Collection<Integer> blockModes)404 public static @BlockModeEnum String[] allFromKeymaster( 405 @NonNull Collection<Integer> blockModes) { 406 if ((blockModes == null) || (blockModes.isEmpty())) { 407 return EmptyArray.STRING; 408 } 409 @BlockModeEnum String[] result = new String[blockModes.size()]; 410 int offset = 0; 411 for (int blockMode : blockModes) { 412 result[offset] = fromKeymaster(blockMode); 413 offset++; 414 } 415 return result; 416 } 417 allToKeymaster(@ullable @lockModeEnum String[] blockModes)418 public static int[] allToKeymaster(@Nullable @BlockModeEnum String[] blockModes) { 419 if ((blockModes == null) || (blockModes.length == 0)) { 420 return EmptyArray.INT; 421 } 422 int[] result = new int[blockModes.length]; 423 for (int i = 0; i < blockModes.length; i++) { 424 result[i] = toKeymaster(blockModes[i]); 425 } 426 return result; 427 } 428 } 429 430 /** 431 * @hide 432 */ 433 @Retention(RetentionPolicy.SOURCE) 434 @StringDef(prefix = { "ENCRYPTION_PADDING_" }, value = { 435 ENCRYPTION_PADDING_NONE, 436 ENCRYPTION_PADDING_PKCS7, 437 ENCRYPTION_PADDING_RSA_PKCS1, 438 ENCRYPTION_PADDING_RSA_OAEP, 439 }) 440 public @interface EncryptionPaddingEnum {} 441 442 /** 443 * No encryption padding. 444 */ 445 public static final String ENCRYPTION_PADDING_NONE = "NoPadding"; 446 447 /** 448 * PKCS#7 encryption padding scheme. 449 */ 450 public static final String ENCRYPTION_PADDING_PKCS7 = "PKCS7Padding"; 451 452 /** 453 * RSA PKCS#1 v1.5 padding scheme for encryption. 454 */ 455 public static final String ENCRYPTION_PADDING_RSA_PKCS1 = "PKCS1Padding"; 456 457 /** 458 * RSA Optimal Asymmetric Encryption Padding (OAEP) scheme. 459 */ 460 public static final String ENCRYPTION_PADDING_RSA_OAEP = "OAEPPadding"; 461 462 /** 463 * @hide 464 */ 465 public static abstract class EncryptionPadding { EncryptionPadding()466 private EncryptionPadding() {} 467 toKeymaster(@onNull @ncryptionPaddingEnum String padding)468 public static int toKeymaster(@NonNull @EncryptionPaddingEnum String padding) { 469 if (ENCRYPTION_PADDING_NONE.equalsIgnoreCase(padding)) { 470 return KeymasterDefs.KM_PAD_NONE; 471 } else if (ENCRYPTION_PADDING_PKCS7.equalsIgnoreCase(padding)) { 472 return KeymasterDefs.KM_PAD_PKCS7; 473 } else if (ENCRYPTION_PADDING_RSA_PKCS1.equalsIgnoreCase(padding)) { 474 return KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT; 475 } else if (ENCRYPTION_PADDING_RSA_OAEP.equalsIgnoreCase(padding)) { 476 return KeymasterDefs.KM_PAD_RSA_OAEP; 477 } else { 478 throw new IllegalArgumentException( 479 "Unsupported encryption padding scheme: " + padding); 480 } 481 } 482 483 @NonNull fromKeymaster(int padding)484 public static @EncryptionPaddingEnum String fromKeymaster(int padding) { 485 switch (padding) { 486 case KeymasterDefs.KM_PAD_NONE: 487 return ENCRYPTION_PADDING_NONE; 488 case KeymasterDefs.KM_PAD_PKCS7: 489 return ENCRYPTION_PADDING_PKCS7; 490 case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT: 491 return ENCRYPTION_PADDING_RSA_PKCS1; 492 case KeymasterDefs.KM_PAD_RSA_OAEP: 493 return ENCRYPTION_PADDING_RSA_OAEP; 494 default: 495 throw new IllegalArgumentException( 496 "Unsupported encryption padding: " + padding); 497 } 498 } 499 500 @NonNull allToKeymaster(@ullable @ncryptionPaddingEnum String[] paddings)501 public static int[] allToKeymaster(@Nullable @EncryptionPaddingEnum String[] paddings) { 502 if ((paddings == null) || (paddings.length == 0)) { 503 return EmptyArray.INT; 504 } 505 int[] result = new int[paddings.length]; 506 for (int i = 0; i < paddings.length; i++) { 507 result[i] = toKeymaster(paddings[i]); 508 } 509 return result; 510 } 511 } 512 513 /** 514 * @hide 515 */ 516 @Retention(RetentionPolicy.SOURCE) 517 @StringDef(prefix = { "SIGNATURE_PADDING_" }, value = { 518 SIGNATURE_PADDING_RSA_PKCS1, 519 SIGNATURE_PADDING_RSA_PSS, 520 }) 521 public @interface SignaturePaddingEnum {} 522 523 /** 524 * RSA PKCS#1 v1.5 padding for signatures. 525 */ 526 public static final String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1"; 527 528 /** 529 * RSA PKCS#1 v2.1 Probabilistic Signature Scheme (PSS) padding. 530 */ 531 public static final String SIGNATURE_PADDING_RSA_PSS = "PSS"; 532 533 /** 534 * @hide 535 */ 536 public abstract static class SignaturePadding { SignaturePadding()537 private SignaturePadding() {} 538 539 /** 540 * @hide 541 */ toKeymaster(@onNull @ignaturePaddingEnum String padding)542 public static int toKeymaster(@NonNull @SignaturePaddingEnum String padding) { 543 switch (padding.toUpperCase(Locale.US)) { 544 case SIGNATURE_PADDING_RSA_PKCS1: 545 return KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN; 546 case SIGNATURE_PADDING_RSA_PSS: 547 return KeymasterDefs.KM_PAD_RSA_PSS; 548 default: 549 throw new IllegalArgumentException( 550 "Unsupported signature padding scheme: " + padding); 551 } 552 } 553 554 @NonNull fromKeymaster(int padding)555 public static @SignaturePaddingEnum String fromKeymaster(int padding) { 556 switch (padding) { 557 case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN: 558 return SIGNATURE_PADDING_RSA_PKCS1; 559 case KeymasterDefs.KM_PAD_RSA_PSS: 560 return SIGNATURE_PADDING_RSA_PSS; 561 default: 562 throw new IllegalArgumentException("Unsupported signature padding: " + padding); 563 } 564 } 565 566 @NonNull allToKeymaster(@ullable @ignaturePaddingEnum String[] paddings)567 public static int[] allToKeymaster(@Nullable @SignaturePaddingEnum String[] paddings) { 568 if ((paddings == null) || (paddings.length == 0)) { 569 return EmptyArray.INT; 570 } 571 int[] result = new int[paddings.length]; 572 for (int i = 0; i < paddings.length; i++) { 573 result[i] = toKeymaster(paddings[i]); 574 } 575 return result; 576 } 577 } 578 579 /** 580 * @hide 581 */ 582 @Retention(RetentionPolicy.SOURCE) 583 @StringDef(prefix = { "DIGEST_" }, value = { 584 DIGEST_NONE, 585 DIGEST_MD5, 586 DIGEST_SHA1, 587 DIGEST_SHA224, 588 DIGEST_SHA256, 589 DIGEST_SHA384, 590 DIGEST_SHA512, 591 }) 592 public @interface DigestEnum {} 593 594 /** 595 * No digest: sign/authenticate the raw message. 596 */ 597 public static final String DIGEST_NONE = "NONE"; 598 599 /** 600 * MD5 digest. 601 */ 602 public static final String DIGEST_MD5 = "MD5"; 603 604 /** 605 * SHA-1 digest. 606 */ 607 public static final String DIGEST_SHA1 = "SHA-1"; 608 609 /** 610 * SHA-2 224 (aka SHA-224) digest. 611 */ 612 public static final String DIGEST_SHA224 = "SHA-224"; 613 614 /** 615 * SHA-2 256 (aka SHA-256) digest. 616 */ 617 public static final String DIGEST_SHA256 = "SHA-256"; 618 619 /** 620 * SHA-2 384 (aka SHA-384) digest. 621 */ 622 public static final String DIGEST_SHA384 = "SHA-384"; 623 624 /** 625 * SHA-2 512 (aka SHA-512) digest. 626 */ 627 public static final String DIGEST_SHA512 = "SHA-512"; 628 629 /** 630 * @hide 631 */ 632 public static abstract class Digest { Digest()633 private Digest() {} 634 toKeymaster(@onNull @igestEnum String digest)635 public static int toKeymaster(@NonNull @DigestEnum String digest) { 636 switch (digest.toUpperCase(Locale.US)) { 637 case DIGEST_SHA1: 638 return KeymasterDefs.KM_DIGEST_SHA1; 639 case DIGEST_SHA224: 640 return KeymasterDefs.KM_DIGEST_SHA_2_224; 641 case DIGEST_SHA256: 642 return KeymasterDefs.KM_DIGEST_SHA_2_256; 643 case DIGEST_SHA384: 644 return KeymasterDefs.KM_DIGEST_SHA_2_384; 645 case DIGEST_SHA512: 646 return KeymasterDefs.KM_DIGEST_SHA_2_512; 647 case DIGEST_NONE: 648 return KeymasterDefs.KM_DIGEST_NONE; 649 case DIGEST_MD5: 650 return KeymasterDefs.KM_DIGEST_MD5; 651 default: 652 throw new IllegalArgumentException("Unsupported digest algorithm: " + digest); 653 } 654 } 655 656 @NonNull fromKeymaster(int digest)657 public static @DigestEnum String fromKeymaster(int digest) { 658 switch (digest) { 659 case KeymasterDefs.KM_DIGEST_NONE: 660 return DIGEST_NONE; 661 case KeymasterDefs.KM_DIGEST_MD5: 662 return DIGEST_MD5; 663 case KeymasterDefs.KM_DIGEST_SHA1: 664 return DIGEST_SHA1; 665 case KeymasterDefs.KM_DIGEST_SHA_2_224: 666 return DIGEST_SHA224; 667 case KeymasterDefs.KM_DIGEST_SHA_2_256: 668 return DIGEST_SHA256; 669 case KeymasterDefs.KM_DIGEST_SHA_2_384: 670 return DIGEST_SHA384; 671 case KeymasterDefs.KM_DIGEST_SHA_2_512: 672 return DIGEST_SHA512; 673 default: 674 throw new IllegalArgumentException("Unsupported digest algorithm: " + digest); 675 } 676 } 677 678 @NonNull fromKeymasterToSignatureAlgorithmDigest(int digest)679 public static @DigestEnum String fromKeymasterToSignatureAlgorithmDigest(int digest) { 680 switch (digest) { 681 case KeymasterDefs.KM_DIGEST_NONE: 682 return "NONE"; 683 case KeymasterDefs.KM_DIGEST_MD5: 684 return "MD5"; 685 case KeymasterDefs.KM_DIGEST_SHA1: 686 return "SHA1"; 687 case KeymasterDefs.KM_DIGEST_SHA_2_224: 688 return "SHA224"; 689 case KeymasterDefs.KM_DIGEST_SHA_2_256: 690 return "SHA256"; 691 case KeymasterDefs.KM_DIGEST_SHA_2_384: 692 return "SHA384"; 693 case KeymasterDefs.KM_DIGEST_SHA_2_512: 694 return "SHA512"; 695 default: 696 throw new IllegalArgumentException("Unsupported digest algorithm: " + digest); 697 } 698 } 699 700 @NonNull allFromKeymaster(@onNull Collection<Integer> digests)701 public static @DigestEnum String[] allFromKeymaster(@NonNull Collection<Integer> digests) { 702 if (digests.isEmpty()) { 703 return EmptyArray.STRING; 704 } 705 String[] result = new String[digests.size()]; 706 int offset = 0; 707 for (int digest : digests) { 708 result[offset] = fromKeymaster(digest); 709 offset++; 710 } 711 return result; 712 } 713 714 @NonNull allToKeymaster(@ullable @igestEnum String[] digests)715 public static int[] allToKeymaster(@Nullable @DigestEnum String[] digests) { 716 if ((digests == null) || (digests.length == 0)) { 717 return EmptyArray.INT; 718 } 719 int[] result = new int[digests.length]; 720 int offset = 0; 721 for (@DigestEnum String digest : digests) { 722 result[offset] = toKeymaster(digest); 723 offset++; 724 } 725 return result; 726 } 727 } 728 729 /** 730 * @hide 731 */ 732 @Retention(RetentionPolicy.SOURCE) 733 @IntDef(prefix = { "ORIGIN_" }, value = { 734 ORIGIN_GENERATED, 735 ORIGIN_IMPORTED, 736 ORIGIN_UNKNOWN, 737 }) 738 739 public @interface OriginEnum {} 740 741 /** Key was generated inside AndroidKeyStore. */ 742 public static final int ORIGIN_GENERATED = 1 << 0; 743 744 /** Key was imported into AndroidKeyStore. */ 745 public static final int ORIGIN_IMPORTED = 1 << 1; 746 747 /** 748 * Origin of the key is unknown. This can occur only for keys backed by an old TEE-backed 749 * implementation which does not record origin information. 750 */ 751 public static final int ORIGIN_UNKNOWN = 1 << 2; 752 753 /** 754 * Key was imported into the AndroidKeyStore in an encrypted wrapper. Unlike imported keys, 755 * securely imported keys can be imported without appearing as plaintext in the device's host 756 * memory. 757 */ 758 public static final int ORIGIN_SECURELY_IMPORTED = 1 << 3; 759 760 761 /** 762 * @hide 763 */ 764 public static abstract class Origin { Origin()765 private Origin() {} 766 fromKeymaster(int origin)767 public static @OriginEnum int fromKeymaster(int origin) { 768 switch (origin) { 769 case KeymasterDefs.KM_ORIGIN_GENERATED: 770 return ORIGIN_GENERATED; 771 case KeymasterDefs.KM_ORIGIN_IMPORTED: 772 return ORIGIN_IMPORTED; 773 case KeymasterDefs.KM_ORIGIN_UNKNOWN: 774 return ORIGIN_UNKNOWN; 775 case KeymasterDefs.KM_ORIGIN_SECURELY_IMPORTED: 776 return ORIGIN_SECURELY_IMPORTED; 777 default: 778 throw new IllegalArgumentException("Unknown origin: " + origin); 779 } 780 } 781 } 782 getSetFlags(int flags)783 private static int[] getSetFlags(int flags) { 784 if (flags == 0) { 785 return EmptyArray.INT; 786 } 787 int result[] = new int[getSetBitCount(flags)]; 788 int resultOffset = 0; 789 int flag = 1; 790 while (flags != 0) { 791 if ((flags & 1) != 0) { 792 result[resultOffset] = flag; 793 resultOffset++; 794 } 795 flags >>>= 1; 796 flag <<= 1; 797 } 798 return result; 799 } 800 getSetBitCount(int value)801 private static int getSetBitCount(int value) { 802 if (value == 0) { 803 return 0; 804 } 805 int result = 0; 806 while (value != 0) { 807 if ((value & 1) != 0) { 808 result++; 809 } 810 value >>>= 1; 811 } 812 return result; 813 } 814 815 /** 816 * @hide 817 */ 818 @Retention(RetentionPolicy.SOURCE) 819 @IntDef(prefix = { "SECURITY_LEVEL_" }, value = { 820 SECURITY_LEVEL_UNKNOWN, 821 SECURITY_LEVEL_UNKNOWN_SECURE, 822 SECURITY_LEVEL_SOFTWARE, 823 SECURITY_LEVEL_TRUSTED_ENVIRONMENT, 824 SECURITY_LEVEL_STRONGBOX, 825 }) 826 public @interface SecurityLevelEnum {} 827 828 /** 829 * This security level indicates that no assumptions can be made about the security level of the 830 * respective key. 831 */ 832 public static final int SECURITY_LEVEL_UNKNOWN = -2; 833 /** 834 * This security level indicates that due to the target API level of the caller no exact 835 * statement can be made about the security level of the key, however, the security level 836 * can be considered is at least equivalent to {@link #SECURITY_LEVEL_TRUSTED_ENVIRONMENT}. 837 */ 838 public static final int SECURITY_LEVEL_UNKNOWN_SECURE = -1; 839 840 /** Indicates enforcement by system software. */ 841 public static final int SECURITY_LEVEL_SOFTWARE = 0; 842 843 /** Indicates enforcement by a trusted execution environment. */ 844 public static final int SECURITY_LEVEL_TRUSTED_ENVIRONMENT = 1; 845 846 /** 847 * Indicates enforcement by environment meeting the Strongbox security profile, 848 * such as a secure element. 849 */ 850 public static final int SECURITY_LEVEL_STRONGBOX = 2; 851 852 /** 853 * @hide 854 */ 855 public abstract static class SecurityLevel { SecurityLevel()856 private SecurityLevel() {} 857 858 /** 859 * @hide 860 */ toKeymaster(int securityLevel)861 public static int toKeymaster(int securityLevel) { 862 switch (securityLevel) { 863 case SECURITY_LEVEL_SOFTWARE: 864 return KeymasterDefs.KM_SECURITY_LEVEL_SOFTWARE; 865 case SECURITY_LEVEL_TRUSTED_ENVIRONMENT: 866 return KeymasterDefs.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT; 867 case SECURITY_LEVEL_STRONGBOX: 868 return KeymasterDefs.KM_SECURITY_LEVEL_STRONGBOX; 869 default: 870 throw new IllegalArgumentException("Unsupported security level: " 871 + securityLevel); 872 } 873 } 874 875 /** 876 * @hide 877 */ 878 @NonNull fromKeymaster(int securityLevel)879 public static int fromKeymaster(int securityLevel) { 880 switch (securityLevel) { 881 case KeymasterDefs.KM_SECURITY_LEVEL_SOFTWARE: 882 return SECURITY_LEVEL_SOFTWARE; 883 case KeymasterDefs.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT: 884 return SECURITY_LEVEL_TRUSTED_ENVIRONMENT; 885 case KeymasterDefs.KM_SECURITY_LEVEL_STRONGBOX: 886 return SECURITY_LEVEL_STRONGBOX; 887 default: 888 throw new IllegalArgumentException("Unsupported security level: " 889 + securityLevel); 890 } 891 } 892 } 893 894 /** 895 * Namespaces provide system developers and vendors with a way to use keystore without 896 * requiring an applications uid. Namespaces can be configured using SEPolicy. 897 * See <a href="https://source.android.com/security/keystore#access-control"> 898 * Keystore 2.0 access-control</a> 899 * {@See KeyGenParameterSpec.Builder#setNamespace} 900 * {@See android.security.keystore2.AndroidKeyStoreLoadStoreParameter} 901 * @hide 902 */ 903 @Retention(RetentionPolicy.SOURCE) 904 @IntDef(prefix = { "NAMESPACE_" }, value = { 905 NAMESPACE_APPLICATION, 906 NAMESPACE_WIFI, 907 NAMESPACE_LOCKSETTINGS, 908 }) 909 public @interface Namespace {} 910 911 /** 912 * This value indicates the implicit keystore namespace of the calling application. 913 * It is used by default. Only select system components can choose a different namespace 914 * which it must be configured in SEPolicy. 915 * @hide 916 */ 917 @SystemApi 918 public static final int NAMESPACE_APPLICATION = -1; 919 920 /** 921 * The namespace identifier for the WIFI Keystore namespace. 922 * This must be kept in sync with system/sepolicy/private/keystore2_key_contexts 923 * @hide 924 */ 925 @SystemApi 926 public static final int NAMESPACE_WIFI = 102; 927 928 /** 929 * The namespace identifier for the LOCKSETTINGS Keystore namespace. 930 * This must be kept in sync with system/sepolicy/private/keystore2_key_contexts 931 * @hide 932 */ 933 public static final int NAMESPACE_LOCKSETTINGS = 103; 934 935 /** 936 * For legacy support, translate namespaces into known UIDs. 937 * @hide 938 */ namespaceToLegacyUid(@amespace int namespace)939 public static int namespaceToLegacyUid(@Namespace int namespace) { 940 switch (namespace) { 941 case NAMESPACE_APPLICATION: 942 return KeyStore.UID_SELF; 943 case NAMESPACE_WIFI: 944 return Process.WIFI_UID; 945 default: 946 throw new IllegalArgumentException("No UID corresponding to namespace " 947 + namespace); 948 } 949 } 950 951 /** 952 * For legacy support, translate namespaces into known UIDs. 953 * @hide 954 */ legacyUidToNamespace(int uid)955 public static @Namespace int legacyUidToNamespace(int uid) { 956 switch (uid) { 957 case KeyStore.UID_SELF: 958 return NAMESPACE_APPLICATION; 959 case Process.WIFI_UID: 960 return NAMESPACE_WIFI; 961 default: 962 throw new IllegalArgumentException("No namespace corresponding to uid " 963 + uid); 964 } 965 } 966 967 /** 968 * This value indicates that there is no restriction on the number of times the key can be used. 969 */ 970 public static final int UNRESTRICTED_USAGE_COUNT = -1; 971 } 972