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
17package android.security.keystore;
18
19import android.annotation.Nullable;
20import android.security.Credentials;
21import android.security.GateKeeper;
22import android.security.KeyPairGeneratorSpec;
23import android.security.KeyStore;
24import android.security.keymaster.KeyCharacteristics;
25import android.security.keymaster.KeymasterArguments;
26import android.security.keymaster.KeymasterCertificateChain;
27import android.security.keymaster.KeymasterDefs;
28
29import com.android.org.bouncycastle.asn1.ASN1EncodableVector;
30import com.android.org.bouncycastle.asn1.ASN1InputStream;
31import com.android.org.bouncycastle.asn1.ASN1Integer;
32import com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier;
33import com.android.org.bouncycastle.asn1.DERBitString;
34import com.android.org.bouncycastle.asn1.DERInteger;
35import com.android.org.bouncycastle.asn1.DERNull;
36import com.android.org.bouncycastle.asn1.DERSequence;
37import com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
38import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
39import com.android.org.bouncycastle.asn1.x509.Certificate;
40import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
41import com.android.org.bouncycastle.asn1.x509.TBSCertificate;
42import com.android.org.bouncycastle.asn1.x509.Time;
43import com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
44import com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
45import com.android.org.bouncycastle.jce.X509Principal;
46import com.android.org.bouncycastle.jce.provider.X509CertificateObject;
47import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
48
49import libcore.util.EmptyArray;
50
51import java.io.ByteArrayOutputStream;
52import java.io.IOException;
53import java.math.BigInteger;
54import java.security.InvalidAlgorithmParameterException;
55import java.security.KeyPair;
56import java.security.KeyPairGenerator;
57import java.security.KeyPairGeneratorSpi;
58import java.security.PrivateKey;
59import java.security.ProviderException;
60import java.security.PublicKey;
61import java.security.SecureRandom;
62import java.security.UnrecoverableKeyException;
63import java.security.cert.CertificateEncodingException;
64import java.security.cert.CertificateParsingException;
65import java.security.cert.X509Certificate;
66import java.security.spec.AlgorithmParameterSpec;
67import java.security.spec.ECGenParameterSpec;
68import java.security.spec.RSAKeyGenParameterSpec;
69import java.util.ArrayList;
70import java.util.Collection;
71import java.util.Collections;
72import java.util.HashMap;
73import java.util.HashSet;
74import java.util.Iterator;
75import java.util.List;
76import java.util.Locale;
77import java.util.Map;
78import 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 */
93public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
94
95    public static class RSA extends AndroidKeyStoreKeyPairGeneratorSpi {
96        public RSA() {
97            super(KeymasterDefs.KM_ALGORITHM_RSA);
98        }
99    }
100
101    public static class EC extends AndroidKeyStoreKeyPairGeneratorSpi {
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
142        SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet());
143        Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES);
144
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
172    protected AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm) {
173        mOriginalKeymasterAlgorithm = keymasterAlgorithm;
174    }
175
176    @SuppressWarnings("deprecation")
177    @Override
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
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);
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(),
347                        mSpec.isUserAuthenticationRequired(),
348                        mSpec.getUserAuthenticationValidityDurationSeconds(),
349                        mSpec.isUserAuthenticationValidWhileOnBody(),
350                        mSpec.isInvalidatedByBiometricEnrollment(),
351                        GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
352            } catch (IllegalArgumentException | IllegalStateException e) {
353                throw new InvalidAlgorithmParameterException(e);
354            }
355
356            mJcaKeyAlgorithm = jcaKeyAlgorithm;
357            mRng = random;
358            mKeyStore = KeyStore.getInstance();
359            success = true;
360        } finally {
361            if (!success) {
362                resetAll();
363            }
364        }
365    }
366
367    private void resetAll() {
368        mEntryAlias = null;
369        mEntryUid = KeyStore.UID_SELF;
370        mJcaKeyAlgorithm = null;
371        mKeymasterAlgorithm = -1;
372        mKeymasterPurposes = null;
373        mKeymasterBlockModes = null;
374        mKeymasterEncryptionPaddings = null;
375        mKeymasterSignaturePaddings = null;
376        mKeymasterDigests = null;
377        mKeySizeBits = 0;
378        mSpec = null;
379        mRSAPublicExponent = null;
380        mEncryptionAtRestRequired = false;
381        mRng = null;
382        mKeyStore = null;
383    }
384
385    private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException {
386        AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec();
387        switch (mKeymasterAlgorithm) {
388            case KeymasterDefs.KM_ALGORITHM_RSA:
389            {
390                BigInteger publicExponent = null;
391                if (algSpecificSpec instanceof RSAKeyGenParameterSpec) {
392                    RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec;
393                    if (mKeySizeBits == -1) {
394                        mKeySizeBits = rsaSpec.getKeysize();
395                    } else if (mKeySizeBits != rsaSpec.getKeysize()) {
396                        throw new InvalidAlgorithmParameterException("RSA key size must match "
397                                + " between " + mSpec + " and " + algSpecificSpec
398                                + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize());
399                    }
400                    publicExponent = rsaSpec.getPublicExponent();
401                } else if (algSpecificSpec != null) {
402                    throw new InvalidAlgorithmParameterException(
403                        "RSA may only use RSAKeyGenParameterSpec");
404                }
405                if (publicExponent == null) {
406                    publicExponent = RSAKeyGenParameterSpec.F4;
407                }
408                if (publicExponent.compareTo(BigInteger.ZERO) < 1) {
409                    throw new InvalidAlgorithmParameterException(
410                            "RSA public exponent must be positive: " + publicExponent);
411                }
412                if (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0) {
413                    throw new InvalidAlgorithmParameterException(
414                            "Unsupported RSA public exponent: " + publicExponent
415                            + ". Maximum supported value: " + KeymasterArguments.UINT64_MAX_VALUE);
416                }
417                mRSAPublicExponent = publicExponent;
418                break;
419            }
420            case KeymasterDefs.KM_ALGORITHM_EC:
421                if (algSpecificSpec instanceof ECGenParameterSpec) {
422                    ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec;
423                    String curveName = ecSpec.getName();
424                    Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get(
425                            curveName.toLowerCase(Locale.US));
426                    if (ecSpecKeySizeBits == null) {
427                        throw new InvalidAlgorithmParameterException(
428                                "Unsupported EC curve name: " + curveName
429                                + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
430                    }
431                    if (mKeySizeBits == -1) {
432                        mKeySizeBits = ecSpecKeySizeBits;
433                    } else if (mKeySizeBits != ecSpecKeySizeBits) {
434                        throw new InvalidAlgorithmParameterException("EC key size must match "
435                                + " between " + mSpec + " and " + algSpecificSpec
436                                + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits);
437                    }
438                } else if (algSpecificSpec != null) {
439                    throw new InvalidAlgorithmParameterException(
440                        "EC may only use ECGenParameterSpec");
441                }
442                break;
443            default:
444                throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
445        }
446    }
447
448    @Override
449    public KeyPair generateKeyPair() {
450        if (mKeyStore == null || mSpec == null) {
451            throw new IllegalStateException("Not initialized");
452        }
453
454        final int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0;
455        if (((flags & KeyStore.FLAG_ENCRYPTED) != 0)
456                && (mKeyStore.state() != KeyStore.State.UNLOCKED)) {
457            throw new IllegalStateException(
458                    "Encryption at rest using secure lock screen credential requested for key pair"
459                    + ", but the user has not yet entered the credential");
460        }
461
462        byte[] additionalEntropy =
463                KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
464                        mRng, (mKeySizeBits + 7) / 8);
465
466        Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid);
467        final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + mEntryAlias;
468        boolean success = false;
469        try {
470            generateKeystoreKeyPair(
471                    privateKeyAlias, constructKeyGenerationArguments(), additionalEntropy, flags);
472            KeyPair keyPair = loadKeystoreKeyPair(privateKeyAlias);
473
474            storeCertificateChain(flags, createCertificateChain(privateKeyAlias, keyPair));
475
476            success = true;
477            return keyPair;
478        } finally {
479            if (!success) {
480                Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid);
481            }
482        }
483    }
484
485    private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair)
486            throws ProviderException {
487        byte[] challenge = mSpec.getAttestationChallenge();
488        if (challenge != null) {
489            KeymasterArguments args = new KeymasterArguments();
490            args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge);
491            return getAttestationChain(privateKeyAlias, keyPair, args);
492        }
493
494        // Very short certificate chain in the non-attestation case.
495        return Collections.singleton(generateSelfSignedCertificateBytes(keyPair));
496    }
497
498    private void generateKeystoreKeyPair(final String privateKeyAlias, KeymasterArguments args,
499            byte[] additionalEntropy, final int flags) throws ProviderException {
500        KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
501        int errorCode = mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy,
502                mEntryUid, flags, resultingKeyCharacteristics);
503        if (errorCode != KeyStore.NO_ERROR) {
504            throw new ProviderException(
505                    "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode));
506        }
507    }
508
509    private KeyPair loadKeystoreKeyPair(final String privateKeyAlias) throws ProviderException {
510        try {
511            KeyPair result  = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
512                    mKeyStore, privateKeyAlias, mEntryUid);
513            if (!mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) {
514                throw new ProviderException(
515                        "Generated key pair algorithm does not match requested algorithm: "
516                                + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm);
517            }
518            return result;
519        } catch (UnrecoverableKeyException e) {
520            throw new ProviderException("Failed to load generated key pair from keystore", e);
521        }
522    }
523
524    private KeymasterArguments constructKeyGenerationArguments() {
525        KeymasterArguments args = new KeymasterArguments();
526        args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
527        args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
528        args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
529        args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
530        args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings);
531        args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
532        args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
533
534        KeymasterUtils.addUserAuthArgs(args,
535                mSpec.isUserAuthenticationRequired(),
536                mSpec.getUserAuthenticationValidityDurationSeconds(),
537                mSpec.isUserAuthenticationValidWhileOnBody(),
538                mSpec.isInvalidatedByBiometricEnrollment(),
539                GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
540        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
541        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
542                mSpec.getKeyValidityForOriginationEnd());
543        args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
544                mSpec.getKeyValidityForConsumptionEnd());
545        addAlgorithmSpecificParameters(args);
546
547        if (mSpec.isUniqueIdIncluded())
548            args.addBoolean(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID);
549
550        return args;
551    }
552
553    private void storeCertificateChain(final int flags, Iterable<byte[]> iterable)
554            throws ProviderException {
555        Iterator<byte[]> iter = iterable.iterator();
556        storeCertificate(
557                Credentials.USER_CERTIFICATE, iter.next(), flags, "Failed to store certificate");
558
559        if (!iter.hasNext()) {
560            return;
561        }
562
563        ByteArrayOutputStream certificateConcatenationStream = new ByteArrayOutputStream();
564        while (iter.hasNext()) {
565            byte[] data = iter.next();
566            certificateConcatenationStream.write(data, 0, data.length);
567        }
568
569        storeCertificate(Credentials.CA_CERTIFICATE, certificateConcatenationStream.toByteArray(),
570                flags, "Failed to store attestation CA certificate");
571    }
572
573    private void storeCertificate(String prefix, byte[] certificateBytes, final int flags,
574            String failureMessage) throws ProviderException {
575        int insertErrorCode = mKeyStore.insert(
576                prefix + mEntryAlias,
577                certificateBytes,
578                mEntryUid,
579                flags);
580        if (insertErrorCode != KeyStore.NO_ERROR) {
581            throw new ProviderException(failureMessage,
582                    KeyStore.getKeyStoreException(insertErrorCode));
583        }
584    }
585
586    private byte[] generateSelfSignedCertificateBytes(KeyPair keyPair) throws ProviderException {
587        try {
588            return generateSelfSignedCertificate(keyPair.getPrivate(), keyPair.getPublic())
589                    .getEncoded();
590        } catch (IOException | CertificateParsingException e) {
591            throw new ProviderException("Failed to generate self-signed certificate", e);
592        } catch (CertificateEncodingException e) {
593            throw new ProviderException(
594                    "Failed to obtain encoded form of self-signed certificate", e);
595        }
596    }
597
598    private Iterable<byte[]> getAttestationChain(String privateKeyAlias,
599            KeyPair keyPair, KeymasterArguments args)
600                    throws ProviderException {
601        KeymasterCertificateChain outChain = new KeymasterCertificateChain();
602        int errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain);
603        if (errorCode != KeyStore.NO_ERROR) {
604            throw new ProviderException("Failed to generate attestation certificate chain",
605                    KeyStore.getKeyStoreException(errorCode));
606        }
607        Collection<byte[]> chain = outChain.getCertificates();
608        if (chain.size() < 2) {
609            throw new ProviderException("Attestation certificate chain contained "
610                    + chain.size() + " entries. At least two are required.");
611        }
612        return chain;
613    }
614
615    private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) {
616        switch (mKeymasterAlgorithm) {
617            case KeymasterDefs.KM_ALGORITHM_RSA:
618                keymasterArgs.addUnsignedLong(
619                        KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent);
620                break;
621            case KeymasterDefs.KM_ALGORITHM_EC:
622                break;
623            default:
624                throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
625        }
626    }
627
628    private X509Certificate generateSelfSignedCertificate(PrivateKey privateKey,
629            PublicKey publicKey) throws CertificateParsingException, IOException {
630        String signatureAlgorithm =
631                getCertificateSignatureAlgorithm(mKeymasterAlgorithm, mKeySizeBits, mSpec);
632        if (signatureAlgorithm == null) {
633            // Key cannot be used to sign a certificate
634            return generateSelfSignedCertificateWithFakeSignature(publicKey);
635        } else {
636            // Key can be used to sign a certificate
637            try {
638                return generateSelfSignedCertificateWithValidSignature(
639                        privateKey, publicKey, signatureAlgorithm);
640            } catch (Exception e) {
641                // Failed to generate the self-signed certificate with valid signature. Fall back
642                // to generating a self-signed certificate with a fake signature. This is done for
643                // all exception types because we prefer key pair generation to succeed and end up
644                // producing a self-signed certificate with an invalid signature to key pair
645                // generation failing.
646                return generateSelfSignedCertificateWithFakeSignature(publicKey);
647            }
648        }
649    }
650
651    @SuppressWarnings("deprecation")
652    private X509Certificate generateSelfSignedCertificateWithValidSignature(
653            PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm) throws Exception {
654        final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
655        certGen.setPublicKey(publicKey);
656        certGen.setSerialNumber(mSpec.getCertificateSerialNumber());
657        certGen.setSubjectDN(mSpec.getCertificateSubject());
658        certGen.setIssuerDN(mSpec.getCertificateSubject());
659        certGen.setNotBefore(mSpec.getCertificateNotBefore());
660        certGen.setNotAfter(mSpec.getCertificateNotAfter());
661        certGen.setSignatureAlgorithm(signatureAlgorithm);
662        return certGen.generate(privateKey);
663    }
664
665    @SuppressWarnings("deprecation")
666    private X509Certificate generateSelfSignedCertificateWithFakeSignature(
667            PublicKey publicKey) throws IOException, CertificateParsingException {
668        V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator();
669        ASN1ObjectIdentifier sigAlgOid;
670        AlgorithmIdentifier sigAlgId;
671        byte[] signature;
672        switch (mKeymasterAlgorithm) {
673            case KeymasterDefs.KM_ALGORITHM_EC:
674                sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256;
675                sigAlgId = new AlgorithmIdentifier(sigAlgOid);
676                ASN1EncodableVector v = new ASN1EncodableVector();
677                v.add(new DERInteger(0));
678                v.add(new DERInteger(0));
679                signature = new DERSequence().getEncoded();
680                break;
681            case KeymasterDefs.KM_ALGORITHM_RSA:
682                sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption;
683                sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE);
684                signature = new byte[1];
685                break;
686            default:
687                throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm);
688        }
689
690        try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) {
691            tbsGenerator.setSubjectPublicKeyInfo(
692                    SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject()));
693        }
694        tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber()));
695        X509Principal subject =
696                new X509Principal(mSpec.getCertificateSubject().getEncoded());
697        tbsGenerator.setSubject(subject);
698        tbsGenerator.setIssuer(subject);
699        tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore()));
700        tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter()));
701        tbsGenerator.setSignature(sigAlgId);
702        TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate();
703
704        ASN1EncodableVector result = new ASN1EncodableVector();
705        result.add(tbsCertificate);
706        result.add(sigAlgId);
707        result.add(new DERBitString(signature));
708        return new X509CertificateObject(Certificate.getInstance(new DERSequence(result)));
709    }
710
711    private static int getDefaultKeySize(int keymasterAlgorithm) {
712        switch (keymasterAlgorithm) {
713            case KeymasterDefs.KM_ALGORITHM_EC:
714                return EC_DEFAULT_KEY_SIZE;
715            case KeymasterDefs.KM_ALGORITHM_RSA:
716                return RSA_DEFAULT_KEY_SIZE;
717            default:
718                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
719        }
720    }
721
722    private static void checkValidKeySize(int keymasterAlgorithm, int keySize)
723            throws InvalidAlgorithmParameterException {
724        switch (keymasterAlgorithm) {
725            case KeymasterDefs.KM_ALGORITHM_EC:
726                if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
727                    throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
728                            + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES);
729                }
730                break;
731            case KeymasterDefs.KM_ALGORITHM_RSA:
732                if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
733                    throw new InvalidAlgorithmParameterException("RSA key size must be >= "
734                            + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE);
735                }
736                break;
737            default:
738                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
739        }
740    }
741
742    /**
743     * Returns the {@code Signature} algorithm to be used for signing a certificate using the
744     * specified key or {@code null} if the key cannot be used for signing a certificate.
745     */
746    @Nullable
747    private static String getCertificateSignatureAlgorithm(
748            int keymasterAlgorithm,
749            int keySizeBits,
750            KeyGenParameterSpec spec) {
751        // Constraints:
752        // 1. Key must be authorized for signing without user authentication.
753        // 2. Signature digest must be one of key's authorized digests.
754        // 3. For RSA keys, the digest output size must not exceed modulus size minus space overhead
755        //    of RSA PKCS#1 signature padding scheme (about 30 bytes).
756        // 4. For EC keys, the there is no point in using a digest whose output size is longer than
757        //    key/field size because the digest will be truncated to that size.
758
759        if ((spec.getPurposes() & KeyProperties.PURPOSE_SIGN) == 0) {
760            // Key not authorized for signing
761            return null;
762        }
763        if (spec.isUserAuthenticationRequired()) {
764            // Key not authorized for use without user authentication
765            return null;
766        }
767        if (!spec.isDigestsSpecified()) {
768            // Key not authorized for any digests -- can't sign
769            return null;
770        }
771        switch (keymasterAlgorithm) {
772            case KeymasterDefs.KM_ALGORITHM_EC:
773            {
774                Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
775                        spec.getDigests(),
776                        AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
777
778                int bestKeymasterDigest = -1;
779                int bestDigestOutputSizeBits = -1;
780                for (int keymasterDigest : availableKeymasterDigests) {
781                    int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
782                    if (outputSizeBits == keySizeBits) {
783                        // Perfect match -- use this digest
784                        bestKeymasterDigest = keymasterDigest;
785                        bestDigestOutputSizeBits = outputSizeBits;
786                        break;
787                    }
788                    // Not a perfect match -- check against the best digest so far
789                    if (bestKeymasterDigest == -1) {
790                        // First digest tested -- definitely the best so far
791                        bestKeymasterDigest = keymasterDigest;
792                        bestDigestOutputSizeBits = outputSizeBits;
793                    } else {
794                        // Prefer output size to be as close to key size as possible, with output
795                        // sizes larger than key size preferred to those smaller than key size.
796                        if (bestDigestOutputSizeBits < keySizeBits) {
797                            // Output size of the best digest so far is smaller than key size.
798                            // Anything larger is a win.
799                            if (outputSizeBits > bestDigestOutputSizeBits) {
800                                bestKeymasterDigest = keymasterDigest;
801                                bestDigestOutputSizeBits = outputSizeBits;
802                            }
803                        } else {
804                            // Output size of the best digest so far is larger than key size.
805                            // Anything smaller is a win, as long as it's not smaller than key size.
806                            if ((outputSizeBits < bestDigestOutputSizeBits)
807                                    && (outputSizeBits >= keySizeBits)) {
808                                bestKeymasterDigest = keymasterDigest;
809                                bestDigestOutputSizeBits = outputSizeBits;
810                            }
811                        }
812                    }
813                }
814                if (bestKeymasterDigest == -1) {
815                    return null;
816                }
817                return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
818                        bestKeymasterDigest) + "WithECDSA";
819            }
820            case KeymasterDefs.KM_ALGORITHM_RSA:
821            {
822                // Check whether this key is authorized for PKCS#1 signature padding.
823                // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle
824                // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs
825                // to be authorized for PKCS#1 padding or padding NONE which means any padding.
826                boolean pkcs1SignaturePaddingSupported =
827                        com.android.internal.util.ArrayUtils.contains(
828                                KeyProperties.SignaturePadding.allToKeymaster(
829                                        spec.getSignaturePaddings()),
830                                KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
831                if (!pkcs1SignaturePaddingSupported) {
832                    // Key not authorized for PKCS#1 signature padding -- can't sign
833                    return null;
834                }
835
836                Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
837                        spec.getDigests(),
838                        AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
839
840                // The amount of space available for the digest is less than modulus size by about
841                // 30 bytes because padding must be at least 11 bytes long (00 || 01 || PS || 00,
842                // where PS must be at least 8 bytes long), and then there's also the 15--19 bytes
843                // overhead (depending the on chosen digest) for encoding digest OID and digest
844                // value in DER.
845                int maxDigestOutputSizeBits = keySizeBits - 30 * 8;
846                int bestKeymasterDigest = -1;
847                int bestDigestOutputSizeBits = -1;
848                for (int keymasterDigest : availableKeymasterDigests) {
849                    int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
850                    if (outputSizeBits > maxDigestOutputSizeBits) {
851                        // Digest too long (signature generation will fail) -- skip
852                        continue;
853                    }
854                    if (bestKeymasterDigest == -1) {
855                        // First digest tested -- definitely the best so far
856                        bestKeymasterDigest = keymasterDigest;
857                        bestDigestOutputSizeBits = outputSizeBits;
858                    } else {
859                        // The longer the better
860                        if (outputSizeBits > bestDigestOutputSizeBits) {
861                            bestKeymasterDigest = keymasterDigest;
862                            bestDigestOutputSizeBits = outputSizeBits;
863                        }
864                    }
865                }
866                if (bestKeymasterDigest == -1) {
867                    return null;
868                }
869                return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
870                        bestKeymasterDigest) + "WithRSA";
871            }
872            default:
873                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
874        }
875    }
876
877    private static Set<Integer> getAvailableKeymasterSignatureDigests(
878            @KeyProperties.DigestEnum String[] authorizedKeyDigests,
879            @KeyProperties.DigestEnum String[] supportedSignatureDigests) {
880        Set<Integer> authorizedKeymasterKeyDigests = new HashSet<Integer>();
881        for (int keymasterDigest : KeyProperties.Digest.allToKeymaster(authorizedKeyDigests)) {
882            authorizedKeymasterKeyDigests.add(keymasterDigest);
883        }
884        Set<Integer> supportedKeymasterSignatureDigests = new HashSet<Integer>();
885        for (int keymasterDigest
886                : KeyProperties.Digest.allToKeymaster(supportedSignatureDigests)) {
887            supportedKeymasterSignatureDigests.add(keymasterDigest);
888        }
889        Set<Integer> result = new HashSet<Integer>(supportedKeymasterSignatureDigests);
890        result.retainAll(authorizedKeymasterKeyDigests);
891        return result;
892    }
893}
894