diff options
author | Alex Klyubin <klyubin@google.com> | 2015-05-13 15:57:09 -0700 |
---|---|---|
committer | Alex Klyubin <klyubin@google.com> | 2015-05-13 16:17:40 -0700 |
commit | dcdaf87ed0aa99073638bcfe645949f130f0c7ad (patch) | |
tree | a377474c30c5da15f447653dacbe12e25699bf0b /keystore/java/android/security/AndroidKeyPairGenerator.java | |
parent | 4ee67bc7a7bb84da1c92dc08427f9737ff8252d6 (diff) |
Move Android Keystore impl to android.security.keystore.
This moves the non-public API classes backing Android Keystore from
android.security to android.security.keystore, a package specially
created for Android Keystore.
Bug: 18088752
Change-Id: Ibf04d6a26c54d310b0501fc5e34f37b1176324ad
Diffstat (limited to 'keystore/java/android/security/AndroidKeyPairGenerator.java')
-rw-r--r-- | keystore/java/android/security/AndroidKeyPairGenerator.java | 394 |
1 files changed, 0 insertions, 394 deletions
diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java deleted file mode 100644 index e9f83200b270..000000000000 --- a/keystore/java/android/security/AndroidKeyPairGenerator.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.security; - -import android.annotation.NonNull; -import android.security.keystore.KeyGenParameterSpec; -import android.security.keystore.KeyProperties; - -import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; -import com.android.org.conscrypt.NativeConstants; -import com.android.org.conscrypt.OpenSSLEngine; - -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.KeyPairGeneratorSpi; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.security.spec.AlgorithmParameterSpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.RSAKeyGenParameterSpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.Locale; - -/** - * Provides a way to create instances of a KeyPair which will be placed in the - * Android keystore service usable only by the application that called it. This - * can be used in conjunction with - * {@link java.security.KeyStore#getInstance(String)} using the - * {@code "AndroidKeyStore"} type. - * <p> - * This class can not be directly instantiated and must instead be used via the - * {@link KeyPairGenerator#getInstance(String) - * KeyPairGenerator.getInstance("AndroidKeyPairGenerator")} API. - * - * {@hide} - */ -public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { - - public static class RSA extends AndroidKeyPairGenerator { - public RSA() { - super(KeyProperties.KEY_ALGORITHM_RSA); - } - } - - public static class EC extends AndroidKeyPairGenerator { - public EC() { - super(KeyProperties.KEY_ALGORITHM_EC); - } - } - - /* - * These must be kept in sync with system/security/keystore/defaults.h - */ - - /* EC */ - private static final int EC_DEFAULT_KEY_SIZE = 256; - private static final int EC_MIN_KEY_SIZE = 192; - private static final int EC_MAX_KEY_SIZE = 521; - - /* RSA */ - private static final int RSA_DEFAULT_KEY_SIZE = 2048; - private static final int RSA_MIN_KEY_SIZE = 512; - private static final int RSA_MAX_KEY_SIZE = 8192; - - private final String mAlgorithm; - - private KeyStore mKeyStore; - - private KeyGenParameterSpec mSpec; - private @KeyProperties.KeyAlgorithmEnum String mKeyAlgorithm; - private int mKeyType; - private int mKeySize; - - protected AndroidKeyPairGenerator(@KeyProperties.KeyAlgorithmEnum String algorithm) { - mAlgorithm = algorithm; - } - - @KeyProperties.KeyAlgorithmEnum String getAlgorithm() { - return mAlgorithm; - } - - /** - * Generate a KeyPair which is backed by the Android keystore service. You - * must call {@link KeyPairGenerator#initialize(AlgorithmParameterSpec)} - * with an {@link KeyPairGeneratorSpec} as the {@code params} - * argument before calling this otherwise an {@code IllegalStateException} - * will be thrown. - * <p> - * This will create an entry in the Android keystore service with a - * self-signed certificate using the {@code params} specified in the - * {@code initialize(params)} call. - * - * @throws IllegalStateException when called before calling - * {@link KeyPairGenerator#initialize(AlgorithmParameterSpec)} - * @see java.security.KeyPairGeneratorSpi#generateKeyPair() - */ - @Override - public KeyPair generateKeyPair() { - if (mKeyStore == null || mSpec == null) { - throw new IllegalStateException("Not initialized"); - - } - - final int flags = mSpec.getFlags(); - if (((flags & KeyStore.FLAG_ENCRYPTED) != 0) - && (mKeyStore.state() != KeyStore.State.UNLOCKED)) { - throw new IllegalStateException( - "Encryption at rest using secure lock screen credential requested for key pair" - + ", but the user has not yet entered the credential"); - } - - final String alias = mSpec.getKeystoreAlias(); - - Credentials.deleteAllTypesForAlias(mKeyStore, alias); - - byte[][] args = getArgsForKeyType(mKeyType, mSpec.getAlgorithmParameterSpec()); - - final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias; - - if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, mKeyType, mKeySize, - flags, args)) { - throw new IllegalStateException("could not generate key in keystore"); - } - - Credentials.deleteSecretKeyTypeForAlias(mKeyStore, alias); - - final PrivateKey privKey; - final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore"); - try { - privKey = engine.getPrivateKeyById(privateKeyAlias); - } catch (InvalidKeyException e) { - throw new RuntimeException("Can't get key", e); - } - - final byte[] pubKeyBytes = mKeyStore.getPubkey(privateKeyAlias); - - final PublicKey pubKey; - try { - final KeyFactory keyFact = KeyFactory.getInstance(mKeyAlgorithm); - pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes)); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("Can't instantiate key generator", e); - } catch (InvalidKeySpecException e) { - throw new IllegalStateException("keystore returned invalid key encoding", e); - } - - final X509Certificate cert; - try { - cert = generateCertificate(privKey, pubKey); - } catch (Exception e) { - Credentials.deleteAllTypesForAlias(mKeyStore, alias); - throw new IllegalStateException("Can't generate certificate", e); - } - - byte[] certBytes; - try { - certBytes = cert.getEncoded(); - } catch (CertificateEncodingException e) { - Credentials.deleteAllTypesForAlias(mKeyStore, alias); - throw new IllegalStateException("Can't get encoding of certificate", e); - } - - if (!mKeyStore.put(Credentials.USER_CERTIFICATE + alias, certBytes, KeyStore.UID_SELF, - flags)) { - Credentials.deleteAllTypesForAlias(mKeyStore, alias); - throw new IllegalStateException("Can't store certificate in AndroidKeyStore"); - } - - return new KeyPair(pubKey, privKey); - } - - @SuppressWarnings("deprecation") - private X509Certificate generateCertificate(PrivateKey privateKey, PublicKey publicKey) - throws Exception { - final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); - certGen.setPublicKey(publicKey); - certGen.setSerialNumber(mSpec.getCertificateSerialNumber()); - certGen.setSubjectDN(mSpec.getCertificateSubject()); - certGen.setIssuerDN(mSpec.getCertificateSubject()); - certGen.setNotBefore(mSpec.getCertificateNotBefore()); - certGen.setNotAfter(mSpec.getCertificateNotAfter()); - certGen.setSignatureAlgorithm(getDefaultSignatureAlgorithmForKeyAlgorithm(mKeyAlgorithm)); - return certGen.generate(privateKey); - } - - @NonNull - private @KeyProperties.KeyAlgorithmEnum String getKeyAlgorithm(KeyPairGeneratorSpec spec) { - String result = spec.getKeyType(); - if (result != null) { - return result; - } - return getAlgorithm(); - } - - private static int getDefaultKeySize(int keyType) { - if (keyType == NativeConstants.EVP_PKEY_EC) { - return EC_DEFAULT_KEY_SIZE; - } else if (keyType == NativeConstants.EVP_PKEY_RSA) { - return RSA_DEFAULT_KEY_SIZE; - } - return -1; - } - - private static void checkValidKeySize(String keyAlgorithm, int keyType, int keySize) - throws InvalidAlgorithmParameterException { - if (keyType == NativeConstants.EVP_PKEY_EC) { - if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) { - throw new InvalidAlgorithmParameterException("EC keys must be >= " - + EC_MIN_KEY_SIZE + " and <= " + EC_MAX_KEY_SIZE); - } - } else if (keyType == NativeConstants.EVP_PKEY_RSA) { - if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) { - throw new InvalidAlgorithmParameterException("RSA keys must be >= " - + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE); - } - } else { - throw new InvalidAlgorithmParameterException( - "Unsupported key algorithm: " + keyAlgorithm); - } - } - - private static void checkCorrectParametersSpec(int keyType, int keySize, - AlgorithmParameterSpec spec) throws InvalidAlgorithmParameterException { - if (keyType == NativeConstants.EVP_PKEY_RSA && spec != null) { - if (spec instanceof RSAKeyGenParameterSpec) { - RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) spec; - if (keySize != -1 && keySize != rsaSpec.getKeysize()) { - throw new InvalidAlgorithmParameterException("RSA key size must match: " - + keySize + " vs " + rsaSpec.getKeysize()); - } - } else { - throw new InvalidAlgorithmParameterException( - "RSA may only use RSAKeyGenParameterSpec"); - } - } - } - - private static String getDefaultSignatureAlgorithmForKeyAlgorithm( - @KeyProperties.KeyAlgorithmEnum String algorithm) { - if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(algorithm)) { - return "sha256WithRSA"; - } else if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(algorithm)) { - return "sha256WithECDSA"; - } else { - throw new IllegalArgumentException("Unsupported key type " + algorithm); - } - } - - private static byte[][] getArgsForKeyType(int keyType, AlgorithmParameterSpec spec) { - switch (keyType) { - case NativeConstants.EVP_PKEY_RSA: - if (spec instanceof RSAKeyGenParameterSpec) { - RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) spec; - return new byte[][] { rsaSpec.getPublicExponent().toByteArray() }; - } - break; - } - return null; - } - - @Override - public void initialize(int keysize, SecureRandom random) { - throw new IllegalArgumentException("cannot specify keysize with AndroidKeyPairGenerator"); - } - - @Override - public void initialize(AlgorithmParameterSpec params, SecureRandom random) - throws InvalidAlgorithmParameterException { - if (params == null) { - throw new InvalidAlgorithmParameterException( - "Must supply params of type " + KeyGenParameterSpec.class.getName() - + " or " + KeyPairGeneratorSpec.class.getName()); - } - - String keyAlgorithm; - KeyGenParameterSpec spec; - if (params instanceof KeyPairGeneratorSpec) { - KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params; - try { - KeyGenParameterSpec.Builder specBuilder; - keyAlgorithm = getKeyAlgorithm(legacySpec).toUpperCase(Locale.US); - if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) { - specBuilder = new KeyGenParameterSpec.Builder( - legacySpec.getKeystoreAlias(), - KeyProperties.PURPOSE_SIGN - | KeyProperties.PURPOSE_VERIFY); - specBuilder.setDigests( - KeyProperties.DIGEST_NONE, - KeyProperties.DIGEST_MD5, - KeyProperties.DIGEST_SHA1, - KeyProperties.DIGEST_SHA224, - KeyProperties.DIGEST_SHA256, - KeyProperties.DIGEST_SHA384, - KeyProperties.DIGEST_SHA512); - } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) { - specBuilder = new KeyGenParameterSpec.Builder( - legacySpec.getKeystoreAlias(), - KeyProperties.PURPOSE_ENCRYPT - | KeyProperties.PURPOSE_DECRYPT - | KeyProperties.PURPOSE_SIGN - | KeyProperties.PURPOSE_VERIFY); - specBuilder.setDigests( - KeyProperties.DIGEST_NONE, - KeyProperties.DIGEST_MD5, - KeyProperties.DIGEST_SHA1, - KeyProperties.DIGEST_SHA224, - KeyProperties.DIGEST_SHA256, - KeyProperties.DIGEST_SHA384, - KeyProperties.DIGEST_SHA512); - specBuilder.setSignaturePaddings( - KeyProperties.SIGNATURE_PADDING_RSA_PKCS1); - specBuilder.setBlockModes(KeyProperties.BLOCK_MODE_ECB); - specBuilder.setEncryptionPaddings( - KeyProperties.ENCRYPTION_PADDING_NONE, - KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1); - // Disable randomized encryption requirement to support encryption padding NONE - // above. - specBuilder.setRandomizedEncryptionRequired(false); - } else { - throw new InvalidAlgorithmParameterException( - "Unsupported key algorithm: " + keyAlgorithm); - } - - if (legacySpec.getKeySize() != -1) { - specBuilder.setKeySize(legacySpec.getKeySize()); - } - if (legacySpec.getAlgorithmParameterSpec() != null) { - specBuilder.setAlgorithmParameterSpec(legacySpec.getAlgorithmParameterSpec()); - } - specBuilder.setCertificateSubject(legacySpec.getSubjectDN()); - specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber()); - specBuilder.setCertificateNotBefore(legacySpec.getStartDate()); - specBuilder.setCertificateNotAfter(legacySpec.getEndDate()); - specBuilder.setEncryptionAtRestRequired(legacySpec.isEncryptionRequired()); - specBuilder.setUserAuthenticationRequired(false); - - spec = specBuilder.build(); - } catch (NullPointerException | IllegalArgumentException e) { - throw new InvalidAlgorithmParameterException(e); - } - } else if (params instanceof KeyGenParameterSpec) { - spec = (KeyGenParameterSpec) params; - keyAlgorithm = getAlgorithm(); - } else { - throw new InvalidAlgorithmParameterException( - "Unsupported params class: " + params.getClass().getName() - + ". Supported: " + KeyGenParameterSpec.class.getName() - + ", " + KeyPairGeneratorSpec.class); - } - - int keyType = KeyStore.getKeyTypeForAlgorithm(keyAlgorithm); - if (keyType == -1) { - throw new InvalidAlgorithmParameterException( - "Unsupported key algorithm: " + keyAlgorithm); - } - int keySize = spec.getKeySize(); - if (keySize == -1) { - keySize = getDefaultKeySize(keyType); - if (keySize == -1) { - throw new InvalidAlgorithmParameterException( - "Unsupported key algorithm: " + keyAlgorithm); - } - } - checkCorrectParametersSpec(keyType, keySize, spec.getAlgorithmParameterSpec()); - checkValidKeySize(keyAlgorithm, keyType, keySize); - - mKeyAlgorithm = keyAlgorithm; - mKeyType = keyType; - mKeySize = keySize; - mSpec = spec; - mKeyStore = KeyStore.getInstance(); - } -} |