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