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