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