diff options
| author | 2015-01-16 17:01:55 +0000 | |
|---|---|---|
| committer | 2015-01-16 17:01:55 +0000 | |
| commit | bd124f9d55c9258ee94d66e2bc96d83be6f3aa12 (patch) | |
| tree | c216121948b8be043f9d1cc68182fa4f7c69171a | |
| parent | d28f0fee61d28ab3369e9d9a27db9dafbb0a6eb6 (diff) | |
| parent | 0624b2c8b75c13b7cdffe84bda3e5a1afd368220 (diff) | |
am 0624b2c8: am a2a5d4cd: am 590c068e: Merge "Add KeyPairGenerator.EC backed by Android KeyStore."
* commit '0624b2c8b75c13b7cdffe84bda3e5a1afd368220':
Add KeyPairGenerator.EC backed by Android KeyStore.
4 files changed, 140 insertions, 90 deletions
diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java index a0ffb5f0d75c..9d9a173353c5 100644 --- a/keystore/java/android/security/AndroidKeyPairGenerator.java +++ b/keystore/java/android/security/AndroidKeyPairGenerator.java @@ -50,10 +50,50 @@ import java.security.spec.X509EncodedKeySpec; * * {@hide} */ -public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { +public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { + + public static class RSA extends AndroidKeyPairGenerator { + public RSA() { + super("RSA"); + } + } + + public static class EC extends AndroidKeyPairGenerator { + public EC() { + super("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 android.security.KeyStore mKeyStore; private KeyPairGeneratorSpec mSpec; + private String mKeyAlgorithm; + private int mKeyType; + private int mKeySize; + + protected AndroidKeyPairGenerator(String algorithm) { + mAlgorithm = algorithm; + } + + public String getAlgorithm() { + return mAlgorithm; + } /** * Generate a KeyPair which is backed by the Android keystore service. You @@ -88,12 +128,11 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { Credentials.deleteAllTypesForAlias(mKeyStore, alias); - final int keyType = KeyStore.getKeyTypeForAlgorithm(mSpec.getKeyType()); - byte[][] args = getArgsForKeyType(keyType, mSpec.getAlgorithmParameterSpec()); + byte[][] args = getArgsForKeyType(mKeyType, mSpec.getAlgorithmParameterSpec()); final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias; - if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, keyType, - mSpec.getKeySize(), mSpec.getFlags(), args)) { + if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, mKeyType, mKeySize, + mSpec.getFlags(), args)) { throw new IllegalStateException("could not generate key in keystore"); } @@ -109,7 +148,7 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { final PublicKey pubKey; try { - final KeyFactory keyFact = KeyFactory.getInstance(mSpec.getKeyType()); + final KeyFactory keyFact = KeyFactory.getInstance(mKeyAlgorithm); pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes)); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("Can't instantiate key generator", e); @@ -117,18 +156,9 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { throw new IllegalStateException("keystore returned invalid key encoding", e); } - final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); - certGen.setPublicKey(pubKey); - certGen.setSerialNumber(mSpec.getSerialNumber()); - certGen.setSubjectDN(mSpec.getSubjectDN()); - certGen.setIssuerDN(mSpec.getSubjectDN()); - certGen.setNotBefore(mSpec.getStartDate()); - certGen.setNotAfter(mSpec.getEndDate()); - certGen.setSignatureAlgorithm(getDefaultSignatureAlgorithmForKeyType(mSpec.getKeyType())); - final X509Certificate cert; try { - cert = certGen.generate(privKey); + cert = generateCertificate(privKey, pubKey); } catch (Exception e) { Credentials.deleteAllTypesForAlias(mKeyStore, alias); throw new IllegalStateException("Can't generate certificate", e); @@ -151,13 +181,78 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { return new KeyPair(pubKey, privKey); } - private static String getDefaultSignatureAlgorithmForKeyType(String keyType) { - if ("RSA".equalsIgnoreCase(keyType)) { + @SuppressWarnings("deprecation") + private X509Certificate generateCertificate(PrivateKey privateKey, PublicKey publicKey) + throws Exception { + final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + certGen.setPublicKey(publicKey); + certGen.setSerialNumber(mSpec.getSerialNumber()); + certGen.setSubjectDN(mSpec.getSubjectDN()); + certGen.setIssuerDN(mSpec.getSubjectDN()); + certGen.setNotBefore(mSpec.getStartDate()); + certGen.setNotAfter(mSpec.getEndDate()); + certGen.setSignatureAlgorithm(getDefaultSignatureAlgorithmForKeyAlgorithm(mKeyAlgorithm)); + return certGen.generate(privateKey); + } + + private String getKeyAlgorithm(KeyPairGeneratorSpec spec) { + String result = spec.getKeyType(); + if (result != null) { + return result; + } + return getAlgorithm(); + } + + private static int getDefaultKeySize(int keyType) { + if (keyType == NativeCrypto.EVP_PKEY_EC) { + return EC_DEFAULT_KEY_SIZE; + } else if (keyType == NativeCrypto.EVP_PKEY_RSA) { + return RSA_DEFAULT_KEY_SIZE; + } + return -1; + } + + private static void checkValidKeySize(String keyAlgorithm, int keyType, int keySize) + throws InvalidAlgorithmParameterException { + if (keyType == NativeCrypto.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 == NativeCrypto.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 == NativeCrypto.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(String algorithm) { + if ("RSA".equalsIgnoreCase(algorithm)) { return "sha256WithRSA"; - } else if ("EC".equalsIgnoreCase(keyType)) { + } else if ("EC".equalsIgnoreCase(algorithm)) { return "sha256WithECDSA"; } else { - throw new IllegalArgumentException("Unsupported key type " + keyType); + throw new IllegalArgumentException("Unsupported key type " + algorithm); } } @@ -190,7 +285,26 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { } KeyPairGeneratorSpec spec = (KeyPairGeneratorSpec) params; + String keyAlgorithm = getKeyAlgorithm(spec); + 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 = android.security.KeyStore.getInstance(); } diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java index b17e450df216..9081e92006b5 100644 --- a/keystore/java/android/security/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/AndroidKeyStoreProvider.java @@ -33,6 +33,7 @@ public class AndroidKeyStoreProvider extends Provider { put("KeyStore." + AndroidKeyStore.NAME, AndroidKeyStore.class.getName()); // java.security.KeyPairGenerator - put("KeyPairGenerator.RSA", AndroidKeyPairGenerator.class.getName()); + put("KeyPairGenerator.EC", AndroidKeyPairGenerator.EC.class.getName()); + put("KeyPairGenerator.RSA", AndroidKeyPairGenerator.RSA.class.getName()); } } diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index 6b67f436bdd5..81964344c553 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -16,8 +16,6 @@ package android.security; -import com.android.org.conscrypt.NativeCrypto; - import android.content.Context; import android.text.TextUtils; @@ -26,7 +24,6 @@ import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.spec.AlgorithmParameterSpec; -import java.security.spec.RSAKeyGenParameterSpec; import java.util.Date; import javax.security.auth.x500.X500Principal; @@ -54,19 +51,6 @@ import javax.security.auth.x500.X500Principal; * certificate signed by a real Certificate Authority. */ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { - /* - * 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 Context mContext; @@ -139,13 +123,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { throw new IllegalArgumentException("endDate < startDate"); } - final int keyTypeInt = KeyStore.getKeyTypeForAlgorithm(keyType); - if (keySize == -1) { - keySize = getDefaultKeySizeForType(keyTypeInt); - } - checkCorrectParametersSpec(keyTypeInt, keySize, spec); - checkValidKeySize(keyTypeInt, keySize); - mContext = context; mKeystoreAlias = keyStoreAlias; mKeyType = keyType; @@ -158,46 +135,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mFlags = flags; } - private static int getDefaultKeySizeForType(int keyType) { - if (keyType == NativeCrypto.EVP_PKEY_EC) { - return EC_DEFAULT_KEY_SIZE; - } else if (keyType == NativeCrypto.EVP_PKEY_RSA) { - return RSA_DEFAULT_KEY_SIZE; - } - throw new IllegalArgumentException("Invalid key type " + keyType); - } - - private static void checkValidKeySize(int keyType, int keySize) { - if (keyType == NativeCrypto.EVP_PKEY_EC) { - if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) { - throw new IllegalArgumentException("EC keys must be >= " + EC_MIN_KEY_SIZE - + " and <= " + EC_MAX_KEY_SIZE); - } - } else if (keyType == NativeCrypto.EVP_PKEY_RSA) { - if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) { - throw new IllegalArgumentException("RSA keys must be >= " + RSA_MIN_KEY_SIZE - + " and <= " + RSA_MAX_KEY_SIZE); - } - } else { - throw new IllegalArgumentException("Invalid key type " + keyType); - } - } - - private static void checkCorrectParametersSpec(int keyType, int keySize, - AlgorithmParameterSpec spec) { - if (keyType == NativeCrypto.EVP_PKEY_RSA && spec != null) { - if (spec instanceof RSAKeyGenParameterSpec) { - RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) spec; - if (keySize != -1 && keySize != rsaSpec.getKeysize()) { - throw new IllegalArgumentException("RSA key size must match: " + keySize - + " vs " + rsaSpec.getKeysize()); - } - } else { - throw new IllegalArgumentException("RSA may only use RSAKeyGenParameterSpec"); - } - } - } - /** * Gets the Android context used for operations with this instance. */ @@ -311,7 +248,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private String mKeystoreAlias; - private String mKeyType = "RSA"; + private String mKeyType; private int mKeySize = -1; @@ -360,9 +297,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { if (keyType == null) { throw new NullPointerException("keyType == null"); } else { - try { - KeyStore.getKeyTypeForAlgorithm(keyType); - } catch (IllegalArgumentException e) { + if (KeyStore.getKeyTypeForAlgorithm(keyType) == -1) { throw new NoSuchAlgorithmException("Unsupported key type: " + keyType); } } diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 797067efa513..e753a7c931f2 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -68,13 +68,13 @@ public class KeyStore { return new KeyStore(keystore); } - static int getKeyTypeForAlgorithm(String keyType) throws IllegalArgumentException { + static int getKeyTypeForAlgorithm(String keyType) { if ("RSA".equalsIgnoreCase(keyType)) { return NativeCrypto.EVP_PKEY_RSA; } else if ("EC".equalsIgnoreCase(keyType)) { return NativeCrypto.EVP_PKEY_EC; } else { - throw new IllegalArgumentException("Unsupported key type: " + keyType); + return -1; } } |