• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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