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