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