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