summaryrefslogtreecommitdiffstats
path: root/keystore/java
diff options
context:
space:
mode:
Diffstat (limited to 'keystore/java')
-rw-r--r--keystore/java/android/security/AndroidKeyPairGenerator.java165
-rw-r--r--keystore/java/android/security/AndroidKeyStoreProvider.java3
-rw-r--r--keystore/java/android/security/KeyChain.java6
-rw-r--r--keystore/java/android/security/KeyPairGeneratorSpec.java98
-rw-r--r--keystore/java/android/security/KeyStore.java9
5 files changed, 150 insertions, 131 deletions
diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java
index 458a46c..9d9a173 100644
--- a/keystore/java/android/security/AndroidKeyPairGenerator.java
+++ b/keystore/java/android/security/AndroidKeyPairGenerator.java
@@ -17,7 +17,6 @@
package android.security;
import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
-
import com.android.org.conscrypt.NativeCrypto;
import com.android.org.conscrypt.OpenSSLEngine;
@@ -34,7 +33,6 @@ import java.security.SecureRandom;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.X509EncodedKeySpec;
@@ -52,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
@@ -90,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");
}
@@ -111,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);
@@ -119,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);
@@ -153,15 +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 ("DSA".equalsIgnoreCase(keyType)) {
- return "sha1WithDSA";
- } 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);
}
}
@@ -173,13 +264,6 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi {
return new byte[][] { rsaSpec.getPublicExponent().toByteArray() };
}
break;
- case NativeCrypto.EVP_PKEY_DSA:
- if (spec instanceof DSAParameterSpec) {
- DSAParameterSpec dsaSpec = (DSAParameterSpec) spec;
- return new byte[][] { dsaSpec.getG().toByteArray(),
- dsaSpec.getP().toByteArray(), dsaSpec.getQ().toByteArray() };
- }
- break;
}
return null;
}
@@ -201,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 b17e450..9081e92 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/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 131e689..dfa41e8 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -242,7 +242,7 @@ public final class KeyChain {
* @param response Callback to invoke when the request completes;
* must not be null
* @param keyTypes The acceptable types of asymmetric keys such as
- * "RSA" or "DSA", or a null array.
+ * "EC" or "RSA", or a null array.
* @param issuers The acceptable certificate issuers for the
* certificate matching the private key, or null.
* @param host The host name of the server requesting the
@@ -263,7 +263,7 @@ public final class KeyChain {
*
* keyTypes would allow the list to be filtered and typically
* will be set correctly by the server. In practice today,
- * most all users will want only RSA, rarely DSA, and usually
+ * most all users will want only RSA or EC, and usually
* only a small number of certs will be available.
*
* issuers is typically not useful. Some servers historically
@@ -379,7 +379,7 @@ public final class KeyChain {
*/
public static boolean isKeyAlgorithmSupported(String algorithm) {
final String algUpper = algorithm.toUpperCase(Locale.US);
- return "DSA".equals(algUpper) || "EC".equals(algUpper) || "RSA".equals(algUpper);
+ return "EC".equals(algUpper) || "RSA".equals(algUpper);
}
/**
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index 4a823cc..cc097aa 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,8 +24,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.DSAParameterSpec;
-import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Date;
import javax.security.auth.x500.X500Principal;
@@ -55,24 +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
- */
-
- /* DSA */
- private static final int DSA_DEFAULT_KEY_SIZE = 1024;
- private static final int DSA_MIN_KEY_SIZE = 512;
- private static final int DSA_MAX_KEY_SIZE = 8192;
-
- /* 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;
@@ -114,7 +92,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
* @param context Android context for the activity
* @param keyStoreAlias name to use for the generated key in the Android
* keystore
- * @param keyType key algorithm to use (RSA, DSA, EC)
+ * @param keyType key algorithm to use (EC, RSA)
* @param keySize size of key to generate
* @param spec the underlying key type parameters
* @param subjectDN X.509 v3 Subject Distinguished Name
@@ -145,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;
@@ -164,57 +135,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
mFlags = flags;
}
- private static int getDefaultKeySizeForType(int keyType) {
- if (keyType == NativeCrypto.EVP_PKEY_DSA) {
- return DSA_DEFAULT_KEY_SIZE;
- } else 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_DSA) {
- if (keySize < DSA_MIN_KEY_SIZE || keySize > DSA_MAX_KEY_SIZE) {
- throw new IllegalArgumentException("DSA keys must be >= " + DSA_MIN_KEY_SIZE
- + " and <= " + DSA_MAX_KEY_SIZE);
- }
- } else 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_DSA && spec != null) {
- if (!(spec instanceof DSAParameterSpec)) {
- throw new IllegalArgumentException("DSA keys must have DSAParameterSpec specified");
- }
- } else 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.
*/
@@ -231,8 +151,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Returns the key type (e.g., "RSA", "DSA", "EC") specified by this
- * parameter.
+ * Returns the key type (e.g., "EC", "RSA") specified by this parameter.
*/
public String getKeyType() {
return mKeyType;
@@ -328,7 +247,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
private String mKeystoreAlias;
- private String mKeyType = "RSA";
+ private String mKeyType;
private int mKeySize = -1;
@@ -371,15 +290,13 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Sets the key type (e.g., RSA, DSA, EC) of the keypair to be created.
+ * Sets the key type (e.g., EC, RSA) of the keypair to be created.
*/
public Builder setKeyType(String keyType) throws NoSuchAlgorithmException {
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);
}
}
@@ -401,9 +318,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
}
/**
- * Sets the underlying key type's parameters. This is required for DSA
- * where you must set this to an instance of
- * {@link java.security.spec.DSAParameterSpec}.
+ * Sets the algorithm-specific key generation parameters. For example, for RSA keys
+ * this may be an instance of {@link java.security.spec.RSAKeyGenParameterSpec}.
*/
public Builder setAlgorithmParameterSpec(AlgorithmParameterSpec spec) {
if (spec == null) {
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 0db8c77..e753a7c 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -68,15 +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 ("DSA".equalsIgnoreCase(keyType)) {
- return NativeCrypto.EVP_PKEY_DSA;
} else if ("EC".equalsIgnoreCase(keyType)) {
return NativeCrypto.EVP_PKEY_EC;
} else {
- throw new IllegalArgumentException("Unsupported key type: " + keyType);
+ return -1;
}
}
@@ -207,7 +205,8 @@ public class KeyStore {
public boolean generate(String key, int uid, int keyType, int keySize, int flags,
byte[][] args) {
try {
- return mBinder.generate(key, uid, keyType, keySize, flags, args) == NO_ERROR;
+ return mBinder.generate(key, uid, keyType, keySize, flags,
+ new KeystoreArguments(args)) == NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;