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