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