AndroidKeyStoreKeyPairGeneratorSpi.java revision 6e90ade5dd7a3c3cd8a3949c863c6e72f9912233
1e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk/* 2e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Copyright (C) 2012 The Android Open Source Project 3e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * 4e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * you may not use this file except in compliance with the License. 6e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * You may obtain a copy of the License at 7e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * 8e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * 10e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * See the License for the specific language governing permissions and 14e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * limitations under the License. 15e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk */ 16e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 17e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkpackage android.security.keystore; 18e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 19e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.annotation.Nullable; 20e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.Credentials; 21e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.KeyPairGeneratorSpec; 22e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.KeyStore; 23e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.keymaster.KeyCharacteristics; 24e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.keymaster.KeymasterArguments; 25e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport android.security.keymaster.KeymasterDefs; 26e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 27e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.ASN1EncodableVector; 28e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.ASN1InputStream; 29e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.ASN1Integer; 30e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier; 31e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.DERBitString; 324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.DERInteger; 334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.DERNull; 34e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.DERSequence; 354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 36e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier; 374510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.x509.Certificate; 38e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.x509.TBSCertificate; 40e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.x509.Time; 414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; 42e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkimport com.android.org.bouncycastle.jce.X509Principal; 44e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.jce.provider.X509CertificateObject; 45e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport com.android.org.bouncycastle.x509.X509V3CertificateGenerator; 46e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 47e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport libcore.util.EmptyArray; 48e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 49e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.math.BigInteger; 50e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.InvalidAlgorithmParameterException; 51e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.KeyPair; 52e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.KeyPairGenerator; 53e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.KeyPairGeneratorSpi; 54e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.PrivateKey; 55e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.ProviderException; 56e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.PublicKey; 57e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.SecureRandom; 58e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.UnrecoverableKeyException; 59e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.cert.CertificateEncodingException; 60e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.cert.X509Certificate; 61e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.spec.AlgorithmParameterSpec; 62e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.spec.ECGenParameterSpec; 63e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.security.spec.RSAKeyGenParameterSpec; 64e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.ArrayList; 65e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Collections; 66e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Date; 67e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.HashMap; 68e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.HashSet; 69e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.List; 70e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Locale; 71e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Map; 72e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkimport java.util.Set; 73e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 74e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk/** 75e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Provides a way to create instances of a KeyPair which will be placed in the 76e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Android keystore service usable only by the application that called it. This 77e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * can be used in conjunction with 78e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * {@link java.security.KeyStore#getInstance(String)} using the 79e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * {@code "AndroidKeyStore"} type. 80e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * <p> 81e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * This class can not be directly instantiated and must instead be used via the 82e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * {@link KeyPairGenerator#getInstance(String) 83e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * KeyPairGenerator.getInstance("AndroidKeyStore")} API. 84e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * 85e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * @hide 86e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk */ 87e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkpublic abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGeneratorSpi { 88e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 89e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk public static class RSA extends AndroidKeyStoreKeyPairGeneratorSpi { 90e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk public RSA() { 91e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk super(KeymasterDefs.KM_ALGORITHM_RSA); 92e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 93e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 94e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 95e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk public static class EC extends AndroidKeyStoreKeyPairGeneratorSpi { 96e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk public EC() { 97e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk super(KeymasterDefs.KM_ALGORITHM_EC); 98e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 99e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 100e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 101e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk /* 102e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * These must be kept in sync with system/security/keystore/defaults.h 103e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk */ 104e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 105e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk /* EC */ 106e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static final int EC_DEFAULT_KEY_SIZE = 256; 107e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 108e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk /* RSA */ 109e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static final int RSA_DEFAULT_KEY_SIZE = 2048; 110e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static final int RSA_MIN_KEY_SIZE = 512; 111e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static final int RSA_MAX_KEY_SIZE = 8192; 112e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 113e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static final Map<String, Integer> SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE = 114e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk new HashMap<String, Integer>(); 115e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>(); 116e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>(); 117e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk static { 118e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Aliases for NIST P-224 119e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224); 120e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp224r1", 224); 121e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 122e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 123e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Aliases for NIST P-256 124e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-256", 256); 125e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp256r1", 256); 126e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("prime256v1", 256); 127e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 128e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Aliases for NIST P-384 129e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-384", 384); 130e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp384r1", 384); 131e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 132e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Aliases for NIST P-521 133e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-521", 521); 134e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp521r1", 521); 135e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 136e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet()); 137e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES); 138e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 139e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SUPPORTED_EC_NIST_CURVE_SIZES.addAll( 140e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values())); 141e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Collections.sort(SUPPORTED_EC_NIST_CURVE_SIZES); 142e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 143e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 144e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private final int mOriginalKeymasterAlgorithm; 145e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 146e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private KeyStore mKeyStore; 147e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 148e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private KeyGenParameterSpec mSpec; 149e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 150e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private String mEntryAlias; 151e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private boolean mEncryptionAtRestRequired; 152e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private @KeyProperties.KeyAlgorithmEnum String mJcaKeyAlgorithm; 153e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private int mKeymasterAlgorithm = -1; 154e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private int mKeySizeBits; 155e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private SecureRandom mRng; 156e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 157e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private int[] mKeymasterPurposes; 158e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private int[] mKeymasterBlockModes; 159e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private int[] mKeymasterEncryptionPaddings; 160e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private int[] mKeymasterSignaturePaddings; 161e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private int[] mKeymasterDigests; 162e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 163e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private long mRSAPublicExponent; 164e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 165e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk protected AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm) { 166e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mOriginalKeymasterAlgorithm = keymasterAlgorithm; 167e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 168e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 169e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk @Override 170e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk public void initialize(int keysize, SecureRandom random) { 171e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new IllegalArgumentException( 172e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName() 173e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + " required to initialize this KeyPairGenerator"); 174e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 175e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 176e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk @Override 177ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk public void initialize(AlgorithmParameterSpec params, SecureRandom random) 178e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throws InvalidAlgorithmParameterException { 179e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk resetAll(); 180ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk 181ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk boolean success = false; 182ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk try { 183ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk if (params == null) { 184ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk throw new InvalidAlgorithmParameterException( 1854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk "Must supply params of type " + KeyGenParameterSpec.class.getName() 1864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk + " or " + KeyPairGeneratorSpec.class.getName()); 1874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 1894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk KeyGenParameterSpec spec; 1904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk boolean encryptionAtRestRequired = false; 1914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk int keymasterAlgorithm = mOriginalKeymasterAlgorithm; 1924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (params instanceof KeyGenParameterSpec) { 193e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk spec = (KeyGenParameterSpec) params; 194e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else if (params instanceof KeyPairGeneratorSpec) { 195e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Legacy/deprecated spec 19645a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params; 19745a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala try { 19845a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala KeyGenParameterSpec.Builder specBuilder; 19945a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala String specKeyAlgorithm = legacySpec.getKeyType(); 20045a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala if (specKeyAlgorithm != null) { 20145a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala // Spec overrides the generator's default key algorithm 20245a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala try { 20345a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala keymasterAlgorithm = 20445a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm( 20545a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala specKeyAlgorithm); 20645a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala } catch (IllegalArgumentException e) { 20745a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala throw new InvalidAlgorithmParameterException( 208e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "Invalid key type in parameters", e); 209e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 210e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 211e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk switch (keymasterAlgorithm) { 2124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk case KeymasterDefs.KM_ALGORITHM_EC: 213e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk specBuilder = new KeyGenParameterSpec.Builder( 214e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk legacySpec.getKeystoreAlias(), 215e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyProperties.PURPOSE_SIGN 216e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk | KeyProperties.PURPOSE_VERIFY); 217e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Authorized to be used with any digest (including no digest). 218e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk specBuilder.setDigests(KeyProperties.DIGEST_NONE); 219e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 2204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk case KeymasterDefs.KM_ALGORITHM_RSA: 221e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk specBuilder = new KeyGenParameterSpec.Builder( 222e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk legacySpec.getKeystoreAlias(), 223e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyProperties.PURPOSE_ENCRYPT 224e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk | KeyProperties.PURPOSE_DECRYPT 225e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk | KeyProperties.PURPOSE_SIGN 226e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk | KeyProperties.PURPOSE_VERIFY); 227e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Authorized to be used with any digest (including no digest). 2284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk specBuilder.setDigests(KeyProperties.DIGEST_NONE); 229e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Authorized to be used with any encryption and signature padding 230e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // scheme (including no padding). 231e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk specBuilder.setEncryptionPaddings( 232e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyProperties.ENCRYPTION_PADDING_NONE); 233e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Disable randomized encryption requirement to support encryption 234e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // padding NONE above. 235e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk specBuilder.setRandomizedEncryptionRequired(false); 2364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk break; 237e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk default: 238e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException( 239e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "Unsupported algorithm: " + mKeymasterAlgorithm); 240e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 241e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 242e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (legacySpec.getKeySize() != -1) { 243ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk specBuilder.setKeySize(legacySpec.getKeySize()); 2444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 245ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk if (legacySpec.getAlgorithmParameterSpec() != null) { 246ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk specBuilder.setAlgorithmParameterSpec( 247ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk legacySpec.getAlgorithmParameterSpec()); 248ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk } 249ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk specBuilder.setCertificateSubject(legacySpec.getSubjectDN()); 250ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber()); 251ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk specBuilder.setCertificateNotBefore(legacySpec.getStartDate()); 2524510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk specBuilder.setCertificateNotAfter(legacySpec.getEndDate()); 253ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk encryptionAtRestRequired = legacySpec.isEncryptionRequired(); 254ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk specBuilder.setUserAuthenticationRequired(false); 255ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk 256ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk spec = specBuilder.build(); 257ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk } catch (NullPointerException | IllegalArgumentException e) { 258ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk throw new InvalidAlgorithmParameterException(e); 259ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk } 2604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else { 261ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk throw new InvalidAlgorithmParameterException( 262ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk "Unsupported params class: " + params.getClass().getName() 263ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk + ". Supported: " + KeyGenParameterSpec.class.getName() 264ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk + ", " + KeyPairGeneratorSpec.class.getName()); 265ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk } 266ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk 267ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mEntryAlias = spec.getKeystoreAlias(); 2684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mSpec = spec; 269ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mKeymasterAlgorithm = keymasterAlgorithm; 270ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mEncryptionAtRestRequired = encryptionAtRestRequired; 271ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mKeySizeBits = spec.getKeySize(); 272ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk initAlgorithmSpecificParameters(); 273ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk if (mKeySizeBits == -1) { 274ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mKeySizeBits = getDefaultKeySize(keymasterAlgorithm); 275ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk } 2764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk checkValidKeySize(keymasterAlgorithm, mKeySizeBits); 277ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk 278ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk if (spec.getKeystoreAlias() == null) { 279ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided"); 280ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk } 281ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk 282ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk String jcaKeyAlgorithm; 283ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk try { 2844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm( 285ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk keymasterAlgorithm); 286ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes()); 287ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes()); 288ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mKeymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster( 289ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk spec.getEncryptionPaddings()); 290ee777157c12a02e7350e18d49f7571b1222dfa69Ruben Brunk mKeymasterSignaturePaddings = KeyProperties.SignaturePadding.allToKeymaster( 2914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk spec.getSignaturePaddings()); 2924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (spec.isDigestsSpecified()) { 2934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests()); 2944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else { 2954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeymasterDigests = EmptyArray.INT; 2964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } catch (IllegalArgumentException e) { 2984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk throw new InvalidAlgorithmParameterException(e); 2994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 3014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mJcaKeyAlgorithm = jcaKeyAlgorithm; 3024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mRng = random; 3034510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeyStore = KeyStore.getInstance(); 3044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk success = true; 3054510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } finally { 3064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (!success) { 3074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk resetAll(); 3084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 3124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk private void resetAll() { 3134510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mEntryAlias = null; 3144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mJcaKeyAlgorithm = null; 3154510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeymasterAlgorithm = -1; 3164510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeymasterPurposes = null; 3174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeymasterBlockModes = null; 3184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeymasterEncryptionPaddings = null; 3194510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeymasterSignaturePaddings = null; 3204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeymasterDigests = null; 3214510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeySizeBits = 0; 3224510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mSpec = null; 3234510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mRSAPublicExponent = -1; 3244510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mEncryptionAtRestRequired = false; 3254510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mRng = null; 3264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeyStore = null; 3274510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 3294510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException { 3304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec(); 3314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk switch (mKeymasterAlgorithm) { 3324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk case KeymasterDefs.KM_ALGORITHM_RSA: 3334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk { 3344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk BigInteger publicExponent = null; 3354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (algSpecificSpec instanceof RSAKeyGenParameterSpec) { 3364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec; 3374510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (mKeySizeBits == -1) { 3384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mKeySizeBits = rsaSpec.getKeysize(); 3394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else if (mKeySizeBits != rsaSpec.getKeysize()) { 3404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk throw new InvalidAlgorithmParameterException("RSA key size must match " 3414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk + " between " + mSpec + " and " + algSpecificSpec 3424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize()); 3434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk publicExponent = rsaSpec.getPublicExponent(); 3454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else if (algSpecificSpec != null) { 3464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk throw new InvalidAlgorithmParameterException( 347e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "RSA may only use RSAKeyGenParameterSpec"); 348e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 349e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (publicExponent == null) { 350e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk publicExponent = RSAKeyGenParameterSpec.F4; 351e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 352e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (publicExponent.compareTo(BigInteger.ZERO) < 1) { 353e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new InvalidAlgorithmParameterException( 354e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "RSA public exponent must be positive: " + publicExponent); 3554510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 356e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (publicExponent.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { 357e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new InvalidAlgorithmParameterException( 358e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "Unsupported RSA public exponent: " + publicExponent 359e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + ". Only exponents <= " + Long.MAX_VALUE + " supported"); 360e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 361e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mRSAPublicExponent = publicExponent.longValue(); 3624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk break; 3634510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3644510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk case KeymasterDefs.KM_ALGORITHM_EC: 3654510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (algSpecificSpec instanceof ECGenParameterSpec) { 3664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec; 3674510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk String curveName = ecSpec.getName(); 3684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get( 3694510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk curveName.toLowerCase(Locale.US)); 370e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (ecSpecKeySizeBits == null) { 371e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new InvalidAlgorithmParameterException( 372e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "Unsupported EC curve name: " + curveName 373e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES); 374e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 375e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (mKeySizeBits == -1) { 376e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mKeySizeBits = ecSpecKeySizeBits; 377e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else if (mKeySizeBits != ecSpecKeySizeBits) { 3784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk throw new InvalidAlgorithmParameterException("EC key size must match " 379e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + " between " + mSpec + " and " + algSpecificSpec 380e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits); 381e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 382e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else if (algSpecificSpec != null) { 383e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new InvalidAlgorithmParameterException( 384e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "EC may only use ECGenParameterSpec"); 385e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 3864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk break; 387e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk default: 388e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm); 389e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 390e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 391e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 392e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk @Override 393e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk public KeyPair generateKeyPair() { 3944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (mKeyStore == null || mSpec == null) { 395e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new IllegalStateException("Not initialized"); 396e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 397e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 398e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk final int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0; 399e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (((flags & KeyStore.FLAG_ENCRYPTED) != 0) 400e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk && (mKeyStore.state() != KeyStore.State.UNLOCKED)) { 401e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new IllegalStateException( 4024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk "Encryption at rest using secure lock screen credential requested for key pair" 403e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + ", but the user has not yet entered the credential"); 404e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 405e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 406e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeymasterArguments args = new KeymasterArguments(); 407e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits); 408e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm); 409e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args.addInts(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes); 4104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes); 411e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings); 412e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings); 413e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args.addInts(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests); 414e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 415e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeymasterUtils.addUserAuthArgs(args, 416e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mSpec.isUserAuthenticationRequired(), 417e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mSpec.getUserAuthenticationValidityDurationSeconds()); 4184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, 419e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk (mSpec.getKeyValidityStart() != null) 420e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ? mSpec.getKeyValidityStart() : new Date(0)); 421e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, 422e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk (mSpec.getKeyValidityForOriginationEnd() != null) 423e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ? mSpec.getKeyValidityForOriginationEnd() : new Date(Long.MAX_VALUE)); 424e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, 425e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk (mSpec.getKeyValidityForConsumptionEnd() != null) 4264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ? mSpec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE)); 427e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk addAlgorithmSpecificParameters(args); 428e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 429e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk byte[] additionalEntropy = 430e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng( 431e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mRng, (mKeySizeBits + 7) / 8); 432e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 433e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + mEntryAlias; 4344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk boolean success = false; 435e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk try { 436e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias); 437e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics(); 438e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int errorCode = mKeyStore.generateKey( 439e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk privateKeyAlias, 440e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk args, 441e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk additionalEntropy, 4424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk flags, 443e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk resultingKeyCharacteristics); 444e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (errorCode != KeyStore.NO_ERROR) { 445e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException( 446e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode)); 447e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 448e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 449e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyPair result; 4504510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk try { 451e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk result = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore( 452e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mKeyStore, privateKeyAlias); 453e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } catch (UnrecoverableKeyException e) { 454e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Failed to load generated key pair from keystore", e); 455e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 456e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 457e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (!mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) { 4584510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk throw new ProviderException( 459e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "Generated key pair algorithm does not match requested algorithm: " 460e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm); 461e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 462e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 463e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk final X509Certificate cert; 464e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk try { 465e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk cert = generateSelfSignedCertificate(result.getPrivate(), result.getPublic()); 4664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } catch (Exception e) { 467e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Failed to generate self-signed certificate", e); 468e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 469e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 470e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk byte[] certBytes; 471e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk try { 472e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk certBytes = cert.getEncoded(); 473e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } catch (CertificateEncodingException e) { 4744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk throw new ProviderException( 475e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk "Failed to obtain encoded form of self-signed certificate", e); 476e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 477e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 478e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int insertErrorCode = mKeyStore.insert( 479e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Credentials.USER_CERTIFICATE + mEntryAlias, 480e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk certBytes, 481e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyStore.UID_SELF, 4824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk flags); 483e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (insertErrorCode != KeyStore.NO_ERROR) { 484e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Failed to store self-signed certificate", 485e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyStore.getKeyStoreException(insertErrorCode)); 486e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 487e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 488e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk success = true; 489e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return result; 4904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } finally { 491e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (!success) { 492e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias); 493e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 494e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 495e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 496e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 497e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) { 4984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk switch (mKeymasterAlgorithm) { 499e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk case KeymasterDefs.KM_ALGORITHM_RSA: 500e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk keymasterArgs.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent); 501e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 502e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk case KeymasterDefs.KM_ALGORITHM_EC: 503e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 504e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk default: 505e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm); 5064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 507e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 508e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 509e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private X509Certificate generateSelfSignedCertificate( 510e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk PrivateKey privateKey, PublicKey publicKey) throws Exception { 511e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk String signatureAlgorithm = 512e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk getCertificateSignatureAlgorithm(mKeymasterAlgorithm, mKeySizeBits, mSpec); 513e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (signatureAlgorithm == null) { 5144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk // Key cannot be used to sign a certificate 515e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return generateSelfSignedCertificateWithFakeSignature(publicKey); 516e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else { 517e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Key can be used to sign a certificate 518e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return generateSelfSignedCertificateWithValidSignature( 519e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk privateKey, publicKey, signatureAlgorithm); 520e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 521e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 5224510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 523e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk @SuppressWarnings("deprecation") 524e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private X509Certificate generateSelfSignedCertificateWithValidSignature( 525e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm) 526e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throws Exception { 527e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); 528e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk certGen.setPublicKey(publicKey); 529e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk certGen.setSerialNumber(mSpec.getCertificateSerialNumber()); 5304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk certGen.setSubjectDN(mSpec.getCertificateSubject()); 531e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk certGen.setIssuerDN(mSpec.getCertificateSubject()); 532e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk certGen.setNotBefore(mSpec.getCertificateNotBefore()); 533e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk certGen.setNotAfter(mSpec.getCertificateNotAfter()); 534e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk certGen.setSignatureAlgorithm(signatureAlgorithm); 535e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return certGen.generate(privateKey); 536e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 537e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 5384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk @SuppressWarnings("deprecation") 539e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private X509Certificate generateSelfSignedCertificateWithFakeSignature( 540e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk PublicKey publicKey) throws Exception { 541e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator(); 542e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ASN1ObjectIdentifier sigAlgOid; 543e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk AlgorithmIdentifier sigAlgId; 544e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk byte[] signature; 545e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk switch (mKeymasterAlgorithm) { 5464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk case KeymasterDefs.KM_ALGORITHM_EC: 547e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256; 548e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sigAlgId = new AlgorithmIdentifier(sigAlgOid); 549e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ASN1EncodableVector v = new ASN1EncodableVector(); 550e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk v.add(new DERInteger(0)); 551e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk v.add(new DERInteger(0)); 552e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk signature = new DERSequence().getEncoded(); 553e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 5544510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk case KeymasterDefs.KM_ALGORITHM_RSA: 555e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption; 556e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE); 557e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk signature = new byte[1]; 558e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 559e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk default: 560e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm); 561e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 5624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 563e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) { 564e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk tbsGenerator.setSubjectPublicKeyInfo( 565e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject())); 566e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 567e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber())); 568e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk X509Principal subject = 569e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk new X509Principal(mSpec.getCertificateSubject().getEncoded()); 5704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk tbsGenerator.setSubject(subject); 571e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk tbsGenerator.setIssuer(subject); 572e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore())); 573e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter())); 574e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk tbsGenerator.setSignature(sigAlgId); 575e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate(); 576e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 577e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ASN1EncodableVector result = new ASN1EncodableVector(); 5784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk result.add(tbsCertificate); 579e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk result.add(sigAlgId); 580e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk result.add(new DERBitString(signature)); 581e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return new X509CertificateObject(Certificate.getInstance(new DERSequence(result))); 582e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 583e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 584e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static int getDefaultKeySize(int keymasterAlgorithm) { 585e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk switch (keymasterAlgorithm) { 5864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk case KeymasterDefs.KM_ALGORITHM_EC: 587e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return EC_DEFAULT_KEY_SIZE; 588e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk case KeymasterDefs.KM_ALGORITHM_RSA: 589e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return RSA_DEFAULT_KEY_SIZE; 590e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk default: 591e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 592e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 593e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 5944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 595e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static void checkValidKeySize(int keymasterAlgorithm, int keySize) 596e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throws InvalidAlgorithmParameterException { 597e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk switch (keymasterAlgorithm) { 598e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk case KeymasterDefs.KM_ALGORITHM_EC: 599e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) { 600e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new InvalidAlgorithmParameterException("Unsupported EC key size: " 601e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES); 6024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 603e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 604e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk case KeymasterDefs.KM_ALGORITHM_RSA: 605e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) { 606e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new InvalidAlgorithmParameterException("RSA key size must be >= " 607e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE); 608e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 609e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 6104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk default: 611e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 612e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 613e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 614e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 615e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk /** 616e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Returns the {@code Signature} algorithm to be used for signing a certificate using the 617e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * specified key or {@code null} if the key cannot be used for signing a certificate. 6184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk */ 619e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk @Nullable 620e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static String getCertificateSignatureAlgorithm( 621e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int keymasterAlgorithm, 622e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int keySizeBits, 623e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyGenParameterSpec spec) { 624e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Constraints: 625e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // 1. Key must be authorized for signing without user authentication. 6264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk // 2. Signature digest must be one of key's authorized digests. 627e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // 3. For RSA keys, the digest output size must not exceed modulus size minus space overhead 628e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // of RSA PKCS#1 signature padding scheme (about 30 bytes). 629e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // 4. For EC keys, the there is no point in using a digest whose output size is longer than 630e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // key/field size because the digest will be truncated to that size. 631e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 632e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if ((spec.getPurposes() & KeyProperties.PURPOSE_SIGN) == 0) { 633e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Key not authorized for signing 6344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return null; 635e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 636e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (spec.isUserAuthenticationRequired()) { 637e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Key not authorized for use without user authentication 638e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return null; 639e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 640e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (!spec.isDigestsSpecified()) { 641e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Key not authorized for any digests -- can't sign 6424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return null; 643e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 644e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk switch (keymasterAlgorithm) { 645e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk case KeymasterDefs.KM_ALGORITHM_EC: 646e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk { 647e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests( 648e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk spec.getDigests(), 649e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests()); 6504510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 651e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int bestKeymasterDigest = -1; 652e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int bestDigestOutputSizeBits = -1; 653e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk for (int keymasterDigest : availableKeymasterDigests) { 654e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); 655e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (outputSizeBits == keySizeBits) { 656e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Perfect match -- use this digest 657e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestKeymasterDigest = keymasterDigest; 6584510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk bestDigestOutputSizeBits = outputSizeBits; 659e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 660e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 661e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Not a perfect match -- check against the best digest so far 662e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (bestKeymasterDigest == -1) { 663e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // First digest tested -- definitely the best so far 664e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestKeymasterDigest = keymasterDigest; 665e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestDigestOutputSizeBits = outputSizeBits; 6664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else { 667e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Prefer output size to be as close to key size as possible, with output 668e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // sizes larger than key size preferred to those smaller than key size. 669e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (bestDigestOutputSizeBits < keySizeBits) { 670e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Output size of the best digest so far is smaller than key size. 671e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Anything larger is a win. 672e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (outputSizeBits > bestDigestOutputSizeBits) { 673e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestKeymasterDigest = keymasterDigest; 674e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestDigestOutputSizeBits = outputSizeBits; 675e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 676e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else { 677e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Output size of the best digest so far is larger than key size. 678e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Anything smaller is a win, as long as it's not smaller than key size. 679e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if ((outputSizeBits < bestDigestOutputSizeBits) 6804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk && (outputSizeBits >= keySizeBits)) { 681e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestKeymasterDigest = keymasterDigest; 682e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestDigestOutputSizeBits = outputSizeBits; 683e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 684e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 685e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 686e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 687e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (bestKeymasterDigest == -1) { 6884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return null; 689e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 690e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest( 691e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestKeymasterDigest) + "WithECDSA"; 692e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 693e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk case KeymasterDefs.KM_ALGORITHM_RSA: 694e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk { 695e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Check whether this key is authorized for PKCS#1 signature padding. 6964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle 697e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs 698e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // to be authorized for PKCS#1 padding or padding NONE which means any padding. 699e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk boolean pkcs1SignaturePaddingSupported = false; 700e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk for (int keymasterPadding : KeyProperties.SignaturePadding.allToKeymaster( 701e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk spec.getSignaturePaddings())) { 702e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if ((keymasterPadding == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN) 703e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk || (keymasterPadding == KeymasterDefs.KM_PAD_NONE)) { 7044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk pkcs1SignaturePaddingSupported = true; 705e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 706e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 707e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 708e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (!pkcs1SignaturePaddingSupported) { 709e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Keymaster doesn't distinguish between encryption padding NONE and signature 710e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // padding NONE. In the Android Keystore API only encryption padding NONE is 711e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // exposed. 7124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk for (int keymasterPadding : KeyProperties.EncryptionPadding.allToKeymaster( 713e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk spec.getEncryptionPaddings())) { 714e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (keymasterPadding == KeymasterDefs.KM_PAD_NONE) { 715e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk pkcs1SignaturePaddingSupported = true; 716e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 717e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 718e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 719e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 7204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (!pkcs1SignaturePaddingSupported) { 721e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Key not authorized for PKCS#1 signature padding -- can't sign 722e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return null; 723e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 724e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 725e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests( 726e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk spec.getDigests(), 727e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests()); 7284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 729e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // The amount of space available for the digest is less than modulus size by about 730e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // 30 bytes because padding must be at least 11 bytes long (00 || 01 || PS || 00, 731e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // where PS must be at least 8 bytes long), and then there's also the 15--19 bytes 732e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // overhead (depending the on chosen digest) for encoding digest OID and digest 733e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // value in DER. 734e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int maxDigestOutputSizeBits = keySizeBits - 30 * 8; 735e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int bestKeymasterDigest = -1; 7364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk int bestDigestOutputSizeBits = -1; 737e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk for (int keymasterDigest : availableKeymasterDigests) { 738e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); 739e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (outputSizeBits > maxDigestOutputSizeBits) { 740e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Digest too long (signature generation will fail) -- skip 741e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk continue; 742e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 743e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (bestKeymasterDigest == -1) { 7444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk // First digest tested -- definitely the best so far 745e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestKeymasterDigest = keymasterDigest; 74645a599d79a1a1b74b959d98eccfbec9c6a5aa237Eino-Ville Talvala bestDigestOutputSizeBits = outputSizeBits; 747e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else { 748e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // The longer the better 749e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (outputSizeBits > bestDigestOutputSizeBits) { 750e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestKeymasterDigest = keymasterDigest; 751e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestDigestOutputSizeBits = outputSizeBits; 7524510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 753e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 754e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 755e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (bestKeymasterDigest == -1) { 756e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return null; 757e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 758e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest( 759e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk bestKeymasterDigest) + "WithRSA"; 7604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 761e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk default: 762e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm); 763e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 764e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 765e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 766e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk private static Set<Integer> getAvailableKeymasterSignatureDigests( 767e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk @KeyProperties.DigestEnum String[] authorizedKeyDigests, 7684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk @KeyProperties.DigestEnum String[] supportedSignatureDigests) { 769e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Set<Integer> authorizedKeymasterKeyDigests = new HashSet<Integer>(); 770e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk for (int keymasterDigest : KeyProperties.Digest.allToKeymaster(authorizedKeyDigests)) { 771e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk authorizedKeymasterKeyDigests.add(keymasterDigest); 772e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 773e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Set<Integer> supportedKeymasterSignatureDigests = new HashSet<Integer>(); 774e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk for (int keymasterDigest 775e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk : KeyProperties.Digest.allToKeymaster(supportedSignatureDigests)) { 7764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk supportedKeymasterSignatureDigests.add(keymasterDigest); 777e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 778e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (authorizedKeymasterKeyDigests.contains(KeymasterDefs.KM_DIGEST_NONE)) { 779e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Key is authorized to be used with any digest 780e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return supportedKeymasterSignatureDigests; 781e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else { 782e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Key is authorized to be used only with specific digests. 783e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk Set<Integer> result = new HashSet<Integer>(supportedKeymasterSignatureDigests); 7844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk result.retainAll(authorizedKeymasterKeyDigests); 785e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return result; 786e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 787e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 788e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 789e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk