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