1 /*
2  * Copyright (C) 2012 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.Nullable;
20 import android.security.Credentials;
21 import android.security.KeyPairGeneratorSpec;
22 import android.security.KeyStore;
23 import android.security.keymaster.KeyCharacteristics;
24 import android.security.keymaster.KeymasterArguments;
25 import android.security.keymaster.KeymasterCertificateChain;
26 import android.security.keymaster.KeymasterDefs;
27 
28 import com.android.org.bouncycastle.asn1.ASN1EncodableVector;
29 import com.android.org.bouncycastle.asn1.ASN1InputStream;
30 import com.android.org.bouncycastle.asn1.ASN1Integer;
31 import com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier;
32 import com.android.org.bouncycastle.asn1.DERBitString;
33 import com.android.org.bouncycastle.asn1.DERInteger;
34 import com.android.org.bouncycastle.asn1.DERNull;
35 import com.android.org.bouncycastle.asn1.DERSequence;
36 import com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
37 import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
38 import com.android.org.bouncycastle.asn1.x509.Certificate;
39 import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
40 import com.android.org.bouncycastle.asn1.x509.TBSCertificate;
41 import com.android.org.bouncycastle.asn1.x509.Time;
42 import com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
43 import com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
44 import com.android.org.bouncycastle.jce.X509Principal;
45 import com.android.org.bouncycastle.jce.provider.X509CertificateObject;
46 import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
47 
48 import libcore.util.EmptyArray;
49 
50 import java.io.ByteArrayOutputStream;
51 import java.io.IOException;
52 import java.math.BigInteger;
53 import java.security.InvalidAlgorithmParameterException;
54 import java.security.KeyPair;
55 import java.security.KeyPairGenerator;
56 import java.security.KeyPairGeneratorSpi;
57 import java.security.PrivateKey;
58 import java.security.ProviderException;
59 import java.security.PublicKey;
60 import java.security.SecureRandom;
61 import java.security.UnrecoverableKeyException;
62 import java.security.cert.CertificateEncodingException;
63 import java.security.cert.CertificateParsingException;
64 import java.security.cert.X509Certificate;
65 import java.security.spec.AlgorithmParameterSpec;
66 import java.security.spec.ECGenParameterSpec;
67 import java.security.spec.RSAKeyGenParameterSpec;
68 import java.util.ArrayList;
69 import java.util.Collection;
70 import java.util.Collections;
71 import java.util.HashMap;
72 import java.util.HashSet;
73 import java.util.Iterator;
74 import java.util.List;
75 import java.util.Locale;
76 import java.util.Map;
77 import java.util.Set;
78 
79 /**
80  * Provides a way to create instances of a KeyPair which will be placed in the
81  * Android keystore service usable only by the application that called it. This
82  * can be used in conjunction with
83  * {@link java.security.KeyStore#getInstance(String)} using the
84  * {@code "AndroidKeyStore"} type.
85  * <p>
86  * This class can not be directly instantiated and must instead be used via the
87  * {@link KeyPairGenerator#getInstance(String)
88  * KeyPairGenerator.getInstance("AndroidKeyStore")} API.
89  *
90  * @hide
91  */
92 public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
93 
94     public static class RSA extends AndroidKeyStoreKeyPairGeneratorSpi {
RSA()95         public RSA() {
96             super(KeymasterDefs.KM_ALGORITHM_RSA);
97         }
98     }
99 
100     public static class EC extends AndroidKeyStoreKeyPairGeneratorSpi {
EC()101         public EC() {
102             super(KeymasterDefs.KM_ALGORITHM_EC);
103         }
104     }
105 
106     /*
107      * These must be kept in sync with system/security/keystore/defaults.h
108      */
109 
110     /* EC */
111     private static final int EC_DEFAULT_KEY_SIZE = 256;
112 
113     /* RSA */
114     private static final int RSA_DEFAULT_KEY_SIZE = 2048;
115     private static final int RSA_MIN_KEY_SIZE = 512;
116     private static final int RSA_MAX_KEY_SIZE = 8192;
117 
118     private static final Map<String, Integer> SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE =
119             new HashMap<String, Integer>();
120     private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>();
121     private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>();
122     static {
123         // Aliases for NIST P-224
124         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224);
125         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp224r1", 224);
126 
127 
128         // Aliases for NIST P-256
129         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-256", 256);
130         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp256r1", 256);
131         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("prime256v1", 256);
132 
133         // Aliases for NIST P-384
134         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-384", 384);
135         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp384r1", 384);
136 
137         // Aliases for NIST P-521
138         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-521", 521);
139         SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp521r1", 521);
140 
SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet()141         SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet());
142         Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES);
143 
SUPPORTED_EC_NIST_CURVE_SIZES.addAll( new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values()))144         SUPPORTED_EC_NIST_CURVE_SIZES.addAll(
145                 new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values()));
146         Collections.sort(SUPPORTED_EC_NIST_CURVE_SIZES);
147     }
148 
149     private final int mOriginalKeymasterAlgorithm;
150 
151     private KeyStore mKeyStore;
152 
153     private KeyGenParameterSpec mSpec;
154 
155     private String mEntryAlias;
156     private int mEntryUid;
157     private boolean mEncryptionAtRestRequired;
158     private @KeyProperties.KeyAlgorithmEnum String mJcaKeyAlgorithm;
159     private int mKeymasterAlgorithm = -1;
160     private int mKeySizeBits;
161     private SecureRandom mRng;
162 
163     private int[] mKeymasterPurposes;
164     private int[] mKeymasterBlockModes;
165     private int[] mKeymasterEncryptionPaddings;
166     private int[] mKeymasterSignaturePaddings;
167     private int[] mKeymasterDigests;
168 
169     private BigInteger mRSAPublicExponent;
170 
AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm)171     protected AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm) {
172         mOriginalKeymasterAlgorithm = keymasterAlgorithm;
173     }
174 
175     @SuppressWarnings("deprecation")
176     @Override
initialize(int keysize, SecureRandom random)177     public void initialize(int keysize, SecureRandom random) {
178         throw new IllegalArgumentException(
179                 KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName()
180                 + " required to initialize this KeyPairGenerator");
181     }
182 
183     @SuppressWarnings("deprecation")
184     @Override
initialize(AlgorithmParameterSpec params, SecureRandom random)185     public void initialize(AlgorithmParameterSpec params, SecureRandom random)
186             throws InvalidAlgorithmParameterException {
187         resetAll();
188 
189         boolean success = false;
190         try {
191             if (params == null) {
192                 throw new InvalidAlgorithmParameterException(
193                         "Must supply params of type " + KeyGenParameterSpec.class.getName()
194                         + " or " + KeyPairGeneratorSpec.class.getName());
195             }
196 
197             KeyGenParameterSpec spec;
198             boolean encryptionAtRestRequired = false;
199             int keymasterAlgorithm = mOriginalKeymasterAlgorithm;
200             if (params instanceof KeyGenParameterSpec) {
201                 spec = (KeyGenParameterSpec) params;
202             } else if (params instanceof KeyPairGeneratorSpec) {
203                 // Legacy/deprecated spec
204                 KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params;
205                 try {
206                     KeyGenParameterSpec.Builder specBuilder;
207                     String specKeyAlgorithm = legacySpec.getKeyType();
208                     if (specKeyAlgorithm != null) {
209                         // Spec overrides the generator's default key algorithm
210                         try {
211                             keymasterAlgorithm =
212                                     KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(
213                                             specKeyAlgorithm);
214                         } catch (IllegalArgumentException e) {
215                             throw new InvalidAlgorithmParameterException(
216                                     "Invalid key type in parameters", e);
217                         }
218                     }
219                     switch (keymasterAlgorithm) {
220                         case KeymasterDefs.KM_ALGORITHM_EC:
221                             specBuilder = new KeyGenParameterSpec.Builder(
222                                     legacySpec.getKeystoreAlias(),
223                                     KeyProperties.PURPOSE_SIGN
224                                     | KeyProperties.PURPOSE_VERIFY);
225                             // Authorized to be used with any digest (including no digest).
226                             // MD5 was never offered for Android Keystore for ECDSA.
227                             specBuilder.setDigests(
228                                     KeyProperties.DIGEST_NONE,
229                                     KeyProperties.DIGEST_SHA1,
230                                     KeyProperties.DIGEST_SHA224,
231                                     KeyProperties.DIGEST_SHA256,
232                                     KeyProperties.DIGEST_SHA384,
233                                     KeyProperties.DIGEST_SHA512);
234                             break;
235                         case KeymasterDefs.KM_ALGORITHM_RSA:
236                             specBuilder = new KeyGenParameterSpec.Builder(
237                                     legacySpec.getKeystoreAlias(),
238                                     KeyProperties.PURPOSE_ENCRYPT
239                                     | KeyProperties.PURPOSE_DECRYPT
240                                     | KeyProperties.PURPOSE_SIGN
241                                     | KeyProperties.PURPOSE_VERIFY);
242                             // Authorized to be used with any digest (including no digest).
243                             specBuilder.setDigests(
244                                     KeyProperties.DIGEST_NONE,
245                                     KeyProperties.DIGEST_MD5,
246                                     KeyProperties.DIGEST_SHA1,
247                                     KeyProperties.DIGEST_SHA224,
248                                     KeyProperties.DIGEST_SHA256,
249                                     KeyProperties.DIGEST_SHA384,
250                                     KeyProperties.DIGEST_SHA512);
251                             // Authorized to be used with any encryption and signature padding
252                             // schemes (including no padding).
253                             specBuilder.setEncryptionPaddings(
254                                     KeyProperties.ENCRYPTION_PADDING_NONE,
255                                     KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1,
256                                     KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
257                             specBuilder.setSignaturePaddings(
258                                     KeyProperties.SIGNATURE_PADDING_RSA_PKCS1,
259                                     KeyProperties.SIGNATURE_PADDING_RSA_PSS);
260                             // Disable randomized encryption requirement to support encryption
261                             // padding NONE above.
262                             specBuilder.setRandomizedEncryptionRequired(false);
263                             break;
264                         default:
265                             throw new ProviderException(
266                                     "Unsupported algorithm: " + mKeymasterAlgorithm);
267                     }
268 
269                     if (legacySpec.getKeySize() != -1) {
270                         specBuilder.setKeySize(legacySpec.getKeySize());
271                     }
272                     if (legacySpec.getAlgorithmParameterSpec() != null) {
273                         specBuilder.setAlgorithmParameterSpec(
274                                 legacySpec.getAlgorithmParameterSpec());
275                     }
276                     specBuilder.setCertificateSubject(legacySpec.getSubjectDN());
277                     specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber());
278                     specBuilder.setCertificateNotBefore(legacySpec.getStartDate());
279                     specBuilder.setCertificateNotAfter(legacySpec.getEndDate());
280                     encryptionAtRestRequired = legacySpec.isEncryptionRequired();
281                     specBuilder.setUserAuthenticationRequired(false);
282 
283                     spec = specBuilder.build();
284                 } catch (NullPointerException | IllegalArgumentException e) {
285                     throw new InvalidAlgorithmParameterException(e);
286                 }
287             } else {
288                 throw new InvalidAlgorithmParameterException(
289                         "Unsupported params class: " + params.getClass().getName()
290                         + ". Supported: " + KeyGenParameterSpec.class.getName()
291                         + ", " + KeyPairGeneratorSpec.class.getName());
292             }
293 
294             mEntryAlias = spec.getKeystoreAlias();
295             mEntryUid = spec.getUid();
296             mSpec = spec;
297             mKeymasterAlgorithm = keymasterAlgorithm;
298             mEncryptionAtRestRequired = encryptionAtRestRequired;
299             mKeySizeBits = spec.getKeySize();
300             initAlgorithmSpecificParameters();
301             if (mKeySizeBits == -1) {
302                 mKeySizeBits = getDefaultKeySize(keymasterAlgorithm);
303             }
304             checkValidKeySize(keymasterAlgorithm, mKeySizeBits);
305 
306             if (spec.getKeystoreAlias() == null) {
307                 throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
308             }
309 
310             String jcaKeyAlgorithm;
311             try {
312                 jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
313                         keymasterAlgorithm);
314                 mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes());
315                 mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes());
316                 mKeymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
317                         spec.getEncryptionPaddings());
318                 if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0)
319                         && (spec.isRandomizedEncryptionRequired())) {
320                     for (int keymasterPadding : mKeymasterEncryptionPaddings) {
321                         if (!KeymasterUtils
322                                 .isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(
323                                         keymasterPadding)) {
324                             throw new InvalidAlgorithmParameterException(
325                                     "Randomized encryption (IND-CPA) required but may be violated"
326                                     + " by padding scheme: "
327                                     + KeyProperties.EncryptionPadding.fromKeymaster(
328                                             keymasterPadding)
329                                     + ". See " + KeyGenParameterSpec.class.getName()
330                                     + " documentation.");
331                         }
332                     }
333                 }
334                 mKeymasterSignaturePaddings = KeyProperties.SignaturePadding.allToKeymaster(
335                         spec.getSignaturePaddings());
336                 if (spec.isDigestsSpecified()) {
337                     mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
338                 } else {
339                     mKeymasterDigests = EmptyArray.INT;
340                 }
341 
342                 // Check that user authentication related parameters are acceptable. This method
343                 // will throw an IllegalStateException if there are issues (e.g., secure lock screen
344                 // not set up).
345                 KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
346                         mSpec.isUserAuthenticationRequired(),
347                         mSpec.getUserAuthenticationValidityDurationSeconds(),
348                         mSpec.isUserAuthenticationValidWhileOnBody(),
349                         mSpec.isInvalidatedByBiometricEnrollment());
350             } catch (IllegalArgumentException | IllegalStateException e) {
351                 throw new InvalidAlgorithmParameterException(e);
352             }
353 
354             mJcaKeyAlgorithm = jcaKeyAlgorithm;
355             mRng = random;
356             mKeyStore = KeyStore.getInstance();
357             success = true;
358         } finally {
359             if (!success) {
360                 resetAll();
361             }
362         }
363     }
364 
resetAll()365     private void resetAll() {
366         mEntryAlias = null;
367         mEntryUid = KeyStore.UID_SELF;
368         mJcaKeyAlgorithm = null;
369         mKeymasterAlgorithm = -1;
370         mKeymasterPurposes = null;
371         mKeymasterBlockModes = null;
372         mKeymasterEncryptionPaddings = null;
373         mKeymasterSignaturePaddings = null;
374         mKeymasterDigests = null;
375         mKeySizeBits = 0;
376         mSpec = null;
377         mRSAPublicExponent = null;
378         mEncryptionAtRestRequired = false;
379         mRng = null;
380         mKeyStore = null;
381     }
382 
initAlgorithmSpecificParameters()383     private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException {
384         AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec();
385         switch (mKeymasterAlgorithm) {
386             case KeymasterDefs.KM_ALGORITHM_RSA:
387             {
388                 BigInteger publicExponent = null;
389                 if (algSpecificSpec instanceof RSAKeyGenParameterSpec) {
390                     RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec;
391                     if (mKeySizeBits == -1) {
392                         mKeySizeBits = rsaSpec.getKeysize();
393                     } else if (mKeySizeBits != rsaSpec.getKeysize()) {
394                         throw new InvalidAlgorithmParameterException("RSA key size must match "
395                                 + " between " + mSpec + " and " + algSpecificSpec
396                                 + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize());
397                     }
398                     publicExponent = rsaSpec.getPublicExponent();
399                 } else if (algSpecificSpec != null) {
400                     throw new InvalidAlgorithmParameterException(
401                         "RSA may only use RSAKeyGenParameterSpec");
402                 }
403                 if (publicExponent == null) {
404                     publicExponent = RSAKeyGenParameterSpec.F4;
405                 }
406                 if (publicExponent.compareTo(BigInteger.ZERO) < 1) {
407                     throw new InvalidAlgorithmParameterException(
408                             "RSA public exponent must be positive: " + publicExponent);
409                 }
410                 if (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0) {
411                     throw new InvalidAlgorithmParameterException(
412                             "Unsupported RSA public exponent: " + publicExponent
413                             + ". Maximum supported value: " + KeymasterArguments.UINT64_MAX_VALUE);
414                 }
415                 mRSAPublicExponent = publicExponent;
416                 break;
417             }
418             case KeymasterDefs.KM_ALGORITHM_EC:
419                 if (algSpecificSpec instanceof ECGenParameterSpec) {
420                     ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec;
421                     String curveName = ecSpec.getName();
422                     Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get(
423                             curveName.toLowerCase(Locale.US));
424                     if (ecSpecKeySizeBits == null) {
425                         throw new InvalidAlgorithmParameterException(
426                                 "Unsupported EC curve name: " + curveName
427                                 + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
428                     }
429                     if (mKeySizeBits == -1) {
430                         mKeySizeBits = ecSpecKeySizeBits;
431                     } else if (mKeySizeBits != ecSpecKeySizeBits) {
432                         throw new InvalidAlgorithmParameterException("EC key size must match "
433                                 + " between " + mSpec + " and " + algSpecificSpec
434                                 + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits);
435                     }
436                 } else if (algSpecificSpec != null) {
437                     throw new InvalidAlgorithmParameterException(
438                         "EC may only use ECGenParameterSpec");
439                 }
440                 break;
441             default:
442                 throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
443         }
444     }
445 
446     @Override
generateKeyPair()447     public KeyPair generateKeyPair() {
448         if (mKeyStore == null || mSpec == null) {
449             throw new IllegalStateException("Not initialized");
450         }
451 
452         final int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0;
453         if (((flags & KeyStore.FLAG_ENCRYPTED) != 0)
454                 && (mKeyStore.state() != KeyStore.State.UNLOCKED)) {
455             throw new IllegalStateException(
456                     "Encryption at rest using secure lock screen credential requested for key pair"
457                     + ", but the user has not yet entered the credential");
458         }
459 
460         byte[] additionalEntropy =
461                 KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
462                         mRng, (mKeySizeBits + 7) / 8);
463 
464         Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid);
465         final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + mEntryAlias;
466         boolean success = false;
467         try {
468             generateKeystoreKeyPair(
469                     privateKeyAlias, constructKeyGenerationArguments(), additionalEntropy, flags);
470             KeyPair keyPair = loadKeystoreKeyPair(privateKeyAlias);
471 
472             storeCertificateChain(flags, createCertificateChain(privateKeyAlias, keyPair));
473 
474             success = true;
475             return keyPair;
476         } finally {
477             if (!success) {
478                 Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid);
479             }
480         }
481     }
482 
createCertificateChain(final String privateKeyAlias, KeyPair keyPair)483     private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair)
484             throws ProviderException {
485         byte[] challenge = mSpec.getAttestationChallenge();
486         if (challenge != null) {
487             KeymasterArguments args = new KeymasterArguments();
488             args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge);
489             return getAttestationChain(privateKeyAlias, keyPair, args);
490         }
491 
492         // Very short certificate chain in the non-attestation case.
493         return Collections.singleton(generateSelfSignedCertificateBytes(keyPair));
494     }
495 
generateKeystoreKeyPair(final String privateKeyAlias, KeymasterArguments args, byte[] additionalEntropy, final int flags)496     private void generateKeystoreKeyPair(final String privateKeyAlias, KeymasterArguments args,
497             byte[] additionalEntropy, final int flags) throws ProviderException {
498         KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
499         int errorCode = mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy,
500                 mEntryUid, flags, resultingKeyCharacteristics);
501         if (errorCode != KeyStore.NO_ERROR) {
502             throw new ProviderException(
503                     "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode));
504         }
505     }
506 
loadKeystoreKeyPair(final String privateKeyAlias)507     private KeyPair loadKeystoreKeyPair(final String privateKeyAlias) throws ProviderException {
508         try {
509             KeyPair result  = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
510                     mKeyStore, privateKeyAlias, mEntryUid);
511             if (!mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) {
512                 throw new ProviderException(
513                         "Generated key pair algorithm does not match requested algorithm: "
514                                 + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm);
515             }
516             return result;
517         } catch (UnrecoverableKeyException e) {
518             throw new ProviderException("Failed to load generated key pair from keystore", e);
519         }
520     }
521 
constructKeyGenerationArguments()522     private KeymasterArguments constructKeyGenerationArguments() {
523         KeymasterArguments args = new KeymasterArguments();
524         args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
525         args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
526         args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
527         args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
528         args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings);
529         args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
530         args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
531 
532         KeymasterUtils.addUserAuthArgs(args,
533                 mSpec.isUserAuthenticationRequired(),
534                 mSpec.getUserAuthenticationValidityDurationSeconds(),
535                 mSpec.isUserAuthenticationValidWhileOnBody(),
536                 mSpec.isInvalidatedByBiometricEnrollment());
537         args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
538         args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
539                 mSpec.getKeyValidityForOriginationEnd());
540         args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
541                 mSpec.getKeyValidityForConsumptionEnd());
542         addAlgorithmSpecificParameters(args);
543 
544         if (mSpec.isUniqueIdIncluded())
545             args.addBoolean(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID);
546 
547         return args;
548     }
549 
storeCertificateChain(final int flags, Iterable<byte[]> iterable)550     private void storeCertificateChain(final int flags, Iterable<byte[]> iterable)
551             throws ProviderException {
552         Iterator<byte[]> iter = iterable.iterator();
553         storeCertificate(
554                 Credentials.USER_CERTIFICATE, iter.next(), flags, "Failed to store certificate");
555 
556         if (!iter.hasNext()) {
557             return;
558         }
559 
560         ByteArrayOutputStream certificateConcatenationStream = new ByteArrayOutputStream();
561         while (iter.hasNext()) {
562             byte[] data = iter.next();
563             certificateConcatenationStream.write(data, 0, data.length);
564         }
565 
566         storeCertificate(Credentials.CA_CERTIFICATE, certificateConcatenationStream.toByteArray(),
567                 flags, "Failed to store attestation CA certificate");
568     }
569 
storeCertificate(String prefix, byte[] certificateBytes, final int flags, String failureMessage)570     private void storeCertificate(String prefix, byte[] certificateBytes, final int flags,
571             String failureMessage) throws ProviderException {
572         int insertErrorCode = mKeyStore.insert(
573                 prefix + mEntryAlias,
574                 certificateBytes,
575                 mEntryUid,
576                 flags);
577         if (insertErrorCode != KeyStore.NO_ERROR) {
578             throw new ProviderException(failureMessage,
579                     KeyStore.getKeyStoreException(insertErrorCode));
580         }
581     }
582 
generateSelfSignedCertificateBytes(KeyPair keyPair)583     private byte[] generateSelfSignedCertificateBytes(KeyPair keyPair) throws ProviderException {
584         try {
585             return generateSelfSignedCertificate(keyPair.getPrivate(), keyPair.getPublic())
586                     .getEncoded();
587         } catch (IOException | CertificateParsingException e) {
588             throw new ProviderException("Failed to generate self-signed certificate", e);
589         } catch (CertificateEncodingException e) {
590             throw new ProviderException(
591                     "Failed to obtain encoded form of self-signed certificate", e);
592         }
593     }
594 
getAttestationChain(String privateKeyAlias, KeyPair keyPair, KeymasterArguments args)595     private Iterable<byte[]> getAttestationChain(String privateKeyAlias,
596             KeyPair keyPair, KeymasterArguments args)
597                     throws ProviderException {
598         KeymasterCertificateChain outChain = new KeymasterCertificateChain();
599         int errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain);
600         if (errorCode != KeyStore.NO_ERROR) {
601             throw new ProviderException("Failed to generate attestation certificate chain",
602                     KeyStore.getKeyStoreException(errorCode));
603         }
604         Collection<byte[]> chain = outChain.getCertificates();
605         if (chain.size() < 2) {
606             throw new ProviderException("Attestation certificate chain contained "
607                     + chain.size() + " entries. At least two are required.");
608         }
609         return chain;
610     }
611 
addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs)612     private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) {
613         switch (mKeymasterAlgorithm) {
614             case KeymasterDefs.KM_ALGORITHM_RSA:
615                 keymasterArgs.addUnsignedLong(
616                         KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent);
617                 break;
618             case KeymasterDefs.KM_ALGORITHM_EC:
619                 break;
620             default:
621                 throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
622         }
623     }
624 
generateSelfSignedCertificate(PrivateKey privateKey, PublicKey publicKey)625     private X509Certificate generateSelfSignedCertificate(PrivateKey privateKey,
626             PublicKey publicKey) throws CertificateParsingException, IOException {
627         String signatureAlgorithm =
628                 getCertificateSignatureAlgorithm(mKeymasterAlgorithm, mKeySizeBits, mSpec);
629         if (signatureAlgorithm == null) {
630             // Key cannot be used to sign a certificate
631             return generateSelfSignedCertificateWithFakeSignature(publicKey);
632         } else {
633             // Key can be used to sign a certificate
634             try {
635                 return generateSelfSignedCertificateWithValidSignature(
636                         privateKey, publicKey, signatureAlgorithm);
637             } catch (Exception e) {
638                 // Failed to generate the self-signed certificate with valid signature. Fall back
639                 // to generating a self-signed certificate with a fake signature. This is done for
640                 // all exception types because we prefer key pair generation to succeed and end up
641                 // producing a self-signed certificate with an invalid signature to key pair
642                 // generation failing.
643                 return generateSelfSignedCertificateWithFakeSignature(publicKey);
644             }
645         }
646     }
647 
648     @SuppressWarnings("deprecation")
generateSelfSignedCertificateWithValidSignature( PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm)649     private X509Certificate generateSelfSignedCertificateWithValidSignature(
650             PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm) throws Exception {
651         final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
652         certGen.setPublicKey(publicKey);
653         certGen.setSerialNumber(mSpec.getCertificateSerialNumber());
654         certGen.setSubjectDN(mSpec.getCertificateSubject());
655         certGen.setIssuerDN(mSpec.getCertificateSubject());
656         certGen.setNotBefore(mSpec.getCertificateNotBefore());
657         certGen.setNotAfter(mSpec.getCertificateNotAfter());
658         certGen.setSignatureAlgorithm(signatureAlgorithm);
659         return certGen.generate(privateKey);
660     }
661 
662     @SuppressWarnings("deprecation")
generateSelfSignedCertificateWithFakeSignature( PublicKey publicKey)663     private X509Certificate generateSelfSignedCertificateWithFakeSignature(
664             PublicKey publicKey) throws IOException, CertificateParsingException {
665         V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator();
666         ASN1ObjectIdentifier sigAlgOid;
667         AlgorithmIdentifier sigAlgId;
668         byte[] signature;
669         switch (mKeymasterAlgorithm) {
670             case KeymasterDefs.KM_ALGORITHM_EC:
671                 sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256;
672                 sigAlgId = new AlgorithmIdentifier(sigAlgOid);
673                 ASN1EncodableVector v = new ASN1EncodableVector();
674                 v.add(new DERInteger(0));
675                 v.add(new DERInteger(0));
676                 signature = new DERSequence().getEncoded();
677                 break;
678             case KeymasterDefs.KM_ALGORITHM_RSA:
679                 sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption;
680                 sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE);
681                 signature = new byte[1];
682                 break;
683             default:
684                 throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm);
685         }
686 
687         try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) {
688             tbsGenerator.setSubjectPublicKeyInfo(
689                     SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject()));
690         }
691         tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber()));
692         X509Principal subject =
693                 new X509Principal(mSpec.getCertificateSubject().getEncoded());
694         tbsGenerator.setSubject(subject);
695         tbsGenerator.setIssuer(subject);
696         tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore()));
697         tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter()));
698         tbsGenerator.setSignature(sigAlgId);
699         TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate();
700 
701         ASN1EncodableVector result = new ASN1EncodableVector();
702         result.add(tbsCertificate);
703         result.add(sigAlgId);
704         result.add(new DERBitString(signature));
705         return new X509CertificateObject(Certificate.getInstance(new DERSequence(result)));
706     }
707 
getDefaultKeySize(int keymasterAlgorithm)708     private static int getDefaultKeySize(int keymasterAlgorithm) {
709         switch (keymasterAlgorithm) {
710             case KeymasterDefs.KM_ALGORITHM_EC:
711                 return EC_DEFAULT_KEY_SIZE;
712             case KeymasterDefs.KM_ALGORITHM_RSA:
713                 return RSA_DEFAULT_KEY_SIZE;
714             default:
715                 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
716         }
717     }
718 
checkValidKeySize(int keymasterAlgorithm, int keySize)719     private static void checkValidKeySize(int keymasterAlgorithm, int keySize)
720             throws InvalidAlgorithmParameterException {
721         switch (keymasterAlgorithm) {
722             case KeymasterDefs.KM_ALGORITHM_EC:
723                 if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
724                     throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
725                             + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES);
726                 }
727                 break;
728             case KeymasterDefs.KM_ALGORITHM_RSA:
729                 if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
730                     throw new InvalidAlgorithmParameterException("RSA key size must be >= "
731                             + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE);
732                 }
733                 break;
734             default:
735                 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
736         }
737     }
738 
739     /**
740      * Returns the {@code Signature} algorithm to be used for signing a certificate using the
741      * specified key or {@code null} if the key cannot be used for signing a certificate.
742      */
743     @Nullable
getCertificateSignatureAlgorithm( int keymasterAlgorithm, int keySizeBits, KeyGenParameterSpec spec)744     private static String getCertificateSignatureAlgorithm(
745             int keymasterAlgorithm,
746             int keySizeBits,
747             KeyGenParameterSpec spec) {
748         // Constraints:
749         // 1. Key must be authorized for signing without user authentication.
750         // 2. Signature digest must be one of key's authorized digests.
751         // 3. For RSA keys, the digest output size must not exceed modulus size minus space overhead
752         //    of RSA PKCS#1 signature padding scheme (about 30 bytes).
753         // 4. For EC keys, the there is no point in using a digest whose output size is longer than
754         //    key/field size because the digest will be truncated to that size.
755 
756         if ((spec.getPurposes() & KeyProperties.PURPOSE_SIGN) == 0) {
757             // Key not authorized for signing
758             return null;
759         }
760         if (spec.isUserAuthenticationRequired()) {
761             // Key not authorized for use without user authentication
762             return null;
763         }
764         if (!spec.isDigestsSpecified()) {
765             // Key not authorized for any digests -- can't sign
766             return null;
767         }
768         switch (keymasterAlgorithm) {
769             case KeymasterDefs.KM_ALGORITHM_EC:
770             {
771                 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
772                         spec.getDigests(),
773                         AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
774 
775                 int bestKeymasterDigest = -1;
776                 int bestDigestOutputSizeBits = -1;
777                 for (int keymasterDigest : availableKeymasterDigests) {
778                     int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
779                     if (outputSizeBits == keySizeBits) {
780                         // Perfect match -- use this digest
781                         bestKeymasterDigest = keymasterDigest;
782                         bestDigestOutputSizeBits = outputSizeBits;
783                         break;
784                     }
785                     // Not a perfect match -- check against the best digest so far
786                     if (bestKeymasterDigest == -1) {
787                         // First digest tested -- definitely the best so far
788                         bestKeymasterDigest = keymasterDigest;
789                         bestDigestOutputSizeBits = outputSizeBits;
790                     } else {
791                         // Prefer output size to be as close to key size as possible, with output
792                         // sizes larger than key size preferred to those smaller than key size.
793                         if (bestDigestOutputSizeBits < keySizeBits) {
794                             // Output size of the best digest so far is smaller than key size.
795                             // Anything larger is a win.
796                             if (outputSizeBits > bestDigestOutputSizeBits) {
797                                 bestKeymasterDigest = keymasterDigest;
798                                 bestDigestOutputSizeBits = outputSizeBits;
799                             }
800                         } else {
801                             // Output size of the best digest so far is larger than key size.
802                             // Anything smaller is a win, as long as it's not smaller than key size.
803                             if ((outputSizeBits < bestDigestOutputSizeBits)
804                                     && (outputSizeBits >= keySizeBits)) {
805                                 bestKeymasterDigest = keymasterDigest;
806                                 bestDigestOutputSizeBits = outputSizeBits;
807                             }
808                         }
809                     }
810                 }
811                 if (bestKeymasterDigest == -1) {
812                     return null;
813                 }
814                 return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
815                         bestKeymasterDigest) + "WithECDSA";
816             }
817             case KeymasterDefs.KM_ALGORITHM_RSA:
818             {
819                 // Check whether this key is authorized for PKCS#1 signature padding.
820                 // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle
821                 // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs
822                 // to be authorized for PKCS#1 padding or padding NONE which means any padding.
823                 boolean pkcs1SignaturePaddingSupported =
824                         com.android.internal.util.ArrayUtils.contains(
825                                 KeyProperties.SignaturePadding.allToKeymaster(
826                                         spec.getSignaturePaddings()),
827                                 KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
828                 if (!pkcs1SignaturePaddingSupported) {
829                     // Key not authorized for PKCS#1 signature padding -- can't sign
830                     return null;
831                 }
832 
833                 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
834                         spec.getDigests(),
835                         AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
836 
837                 // The amount of space available for the digest is less than modulus size by about
838                 // 30 bytes because padding must be at least 11 bytes long (00 || 01 || PS || 00,
839                 // where PS must be at least 8 bytes long), and then there's also the 15--19 bytes
840                 // overhead (depending the on chosen digest) for encoding digest OID and digest
841                 // value in DER.
842                 int maxDigestOutputSizeBits = keySizeBits - 30 * 8;
843                 int bestKeymasterDigest = -1;
844                 int bestDigestOutputSizeBits = -1;
845                 for (int keymasterDigest : availableKeymasterDigests) {
846                     int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
847                     if (outputSizeBits > maxDigestOutputSizeBits) {
848                         // Digest too long (signature generation will fail) -- skip
849                         continue;
850                     }
851                     if (bestKeymasterDigest == -1) {
852                         // First digest tested -- definitely the best so far
853                         bestKeymasterDigest = keymasterDigest;
854                         bestDigestOutputSizeBits = outputSizeBits;
855                     } else {
856                         // The longer the better
857                         if (outputSizeBits > bestDigestOutputSizeBits) {
858                             bestKeymasterDigest = keymasterDigest;
859                             bestDigestOutputSizeBits = outputSizeBits;
860                         }
861                     }
862                 }
863                 if (bestKeymasterDigest == -1) {
864                     return null;
865                 }
866                 return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
867                         bestKeymasterDigest) + "WithRSA";
868             }
869             default:
870                 throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
871         }
872     }
873 
getAvailableKeymasterSignatureDigests( @eyProperties.DigestEnum String[] authorizedKeyDigests, @KeyProperties.DigestEnum String[] supportedSignatureDigests)874     private static Set<Integer> getAvailableKeymasterSignatureDigests(
875             @KeyProperties.DigestEnum String[] authorizedKeyDigests,
876             @KeyProperties.DigestEnum String[] supportedSignatureDigests) {
877         Set<Integer> authorizedKeymasterKeyDigests = new HashSet<Integer>();
878         for (int keymasterDigest : KeyProperties.Digest.allToKeymaster(authorizedKeyDigests)) {
879             authorizedKeymasterKeyDigests.add(keymasterDigest);
880         }
881         Set<Integer> supportedKeymasterSignatureDigests = new HashSet<Integer>();
882         for (int keymasterDigest
883                 : KeyProperties.Digest.allToKeymaster(supportedSignatureDigests)) {
884             supportedKeymasterSignatureDigests.add(keymasterDigest);
885         }
886         Set<Integer> result = new HashSet<Integer>(supportedKeymasterSignatureDigests);
887         result.retainAll(authorizedKeymasterKeyDigests);
888         return result;
889     }
890 }
891