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