Loading api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -22593,8 +22593,11 @@ package android.security { } public final class KeyPairGeneratorSpec implements java.security.spec.AlgorithmParameterSpec { method public java.security.spec.AlgorithmParameterSpec getAlgorithmParameterSpec(); method public android.content.Context getContext(); method public java.util.Date getEndDate(); method public int getKeySize(); method public java.lang.String getKeyType(); method public java.lang.String getKeystoreAlias(); method public java.math.BigInteger getSerialNumber(); method public java.util.Date getStartDate(); Loading @@ -22605,9 +22608,12 @@ package android.security { public static final class KeyPairGeneratorSpec.Builder { ctor public KeyPairGeneratorSpec.Builder(android.content.Context); method public android.security.KeyPairGeneratorSpec build(); method public android.security.KeyPairGeneratorSpec.Builder setAlgorithmParameterSpec(java.security.spec.AlgorithmParameterSpec); method public android.security.KeyPairGeneratorSpec.Builder setAlias(java.lang.String); method public android.security.KeyPairGeneratorSpec.Builder setEncryptionRequired(); method public android.security.KeyPairGeneratorSpec.Builder setEndDate(java.util.Date); method public android.security.KeyPairGeneratorSpec.Builder setKeySize(int); method public android.security.KeyPairGeneratorSpec.Builder setKeyType(java.lang.String) throws java.security.NoSuchAlgorithmException; method public android.security.KeyPairGeneratorSpec.Builder setSerialNumber(java.math.BigInteger); method public android.security.KeyPairGeneratorSpec.Builder setStartDate(java.util.Date); method public android.security.KeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal); core/java/android/security/IKeystoreService.java +14 −2 Original line number Diff line number Diff line Loading @@ -244,7 +244,8 @@ public interface IKeystoreService extends IInterface { return _result; } public int generate(String name, int uid, int flags) throws RemoteException { public int generate(String name, int uid, int keyType, int keySize, int flags, byte[][] args) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; Loading @@ -252,7 +253,17 @@ public interface IKeystoreService extends IInterface { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(name); _data.writeInt(uid); _data.writeInt(keyType); _data.writeInt(keySize); _data.writeInt(flags); if (args == null) { _data.writeInt(0); } else { _data.writeInt(args.length); for (int i = 0; i < args.length; i++) { _data.writeByteArray(args[i]); } } mRemote.transact(Stub.TRANSACTION_generate, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); Loading Loading @@ -560,7 +571,8 @@ public interface IKeystoreService extends IInterface { public int zero() throws RemoteException; public int generate(String name, int uid, int flags) throws RemoteException; public int generate(String name, int uid, int keyType, int keySize, int flags, byte[][] args) throws RemoteException; public int import_key(String name, byte[] data, int uid, int flags) throws RemoteException; Loading keystore/java/android/security/AndroidKeyPairGenerator.java +43 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.security; import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; import com.android.org.conscrypt.NativeCrypto; import com.android.org.conscrypt.OpenSSLEngine; import java.security.InvalidAlgorithmParameterException; Loading @@ -33,7 +34,10 @@ 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.ECParameterSpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.X509EncodedKeySpec; /** Loading Loading @@ -87,8 +91,12 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { Credentials.deleteAllTypesForAlias(mKeyStore, alias); final int keyType = KeyStore.getKeyTypeForAlgorithm(mSpec.getKeyType()); byte[][] args = getArgsForKeyType(keyType, mSpec.getAlgorithmParameterSpec()); final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias; if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, mSpec.getFlags())) { if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, keyType, mSpec.getKeySize(), mSpec.getFlags(), args)) { throw new IllegalStateException("could not generate key in keystore"); } Loading @@ -104,10 +112,10 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { final PublicKey pubKey; try { final KeyFactory keyFact = KeyFactory.getInstance("RSA"); final KeyFactory keyFact = KeyFactory.getInstance(mSpec.getKeyType()); pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes)); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("Can't instantiate RSA key generator", e); throw new IllegalStateException("Can't instantiate key generator", e); } catch (InvalidKeySpecException e) { throw new IllegalStateException("keystore returned invalid key encoding", e); } Loading @@ -119,7 +127,7 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { certGen.setIssuerDN(mSpec.getSubjectDN()); certGen.setNotBefore(mSpec.getStartDate()); certGen.setNotAfter(mSpec.getEndDate()); certGen.setSignatureAlgorithm("sha1WithRSA"); certGen.setSignatureAlgorithm(getDefaultSignatureAlgorithmForKeyType(mSpec.getKeyType())); final X509Certificate cert; try { Loading @@ -146,6 +154,37 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { return new KeyPair(pubKey, privKey); } private static String getDefaultSignatureAlgorithmForKeyType(String keyType) { if ("RSA".equalsIgnoreCase(keyType)) { return "sha256WithRSA"; } else if ("DSA".equalsIgnoreCase(keyType)) { return "sha1WithDSA"; } else if ("EC".equalsIgnoreCase(keyType)) { return "sha256WithECDSA"; } else { throw new IllegalArgumentException("Unsupported key type " + keyType); } } private static byte[][] getArgsForKeyType(int keyType, AlgorithmParameterSpec spec) { switch (keyType) { case NativeCrypto.EVP_PKEY_RSA: if (spec instanceof RSAKeyGenParameterSpec) { RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) spec; 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; } @Override public void initialize(int keysize, SecureRandom random) { throw new IllegalArgumentException("cannot specify keysize with AndroidKeyPairGenerator"); Loading keystore/java/android/security/KeyPairGeneratorSpec.java +177 −9 Original line number Diff line number Diff line Loading @@ -16,13 +16,18 @@ package android.security; import com.android.org.conscrypt.NativeCrypto; import android.content.Context; import android.text.TextUtils; import java.math.BigInteger; 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; Loading Loading @@ -50,10 +55,35 @@ import javax.security.auth.x500.X500Principal; * certificate signed by a real Certificate Authority. */ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private final String mKeystoreAlias; /* * 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; private final String mKeystoreAlias; private final String mKeyType; private final int mKeySize; private final AlgorithmParameterSpec mSpec; private final X500Principal mSubjectDN; private final BigInteger mSerialNumber; Loading Loading @@ -84,6 +114,9 @@ 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 keySize size of key to generate * @param spec the underlying key type parameters * @param subjectDN X.509 v3 Subject Distinguished Name * @param serialNumber X509 v3 certificate serial number * @param startDate the start of the self-signed certificate validity period Loading @@ -93,9 +126,9 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * {@code endDate} is before {@code startDate}. * @hide should be built with KeyPairGeneratorSpecBuilder */ public KeyPairGeneratorSpec(Context context, String keyStoreAlias, X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate, int flags) { public KeyPairGeneratorSpec(Context context, String keyStoreAlias, String keyType, int keySize, AlgorithmParameterSpec spec, X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate, int flags) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { Loading @@ -112,8 +145,18 @@ 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; mKeySize = keySize; mSpec = spec; mSubjectDN = subjectDN; mSerialNumber = serialNumber; mStartDate = startDate; Loading @@ -121,6 +164,64 @@ 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. */ public Context getContext() { return mContext; } /** * Returns the alias that will be used in the {@code java.security.KeyStore} * in conjunction with the {@code AndroidKeyStore}. Loading @@ -130,10 +231,28 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** * Gets the Android context used for operations with this instance. * Returns the key type (e.g., "RSA", "DSA", "EC") specified by this * parameter. */ public Context getContext() { return mContext; public String getKeyType() { return mKeyType; } /** * Returns the key size specified by this parameter. For instance, for RSA * this will return the modulus size and for EC it will return the field * size. */ public int getKeySize() { return mKeySize; } /** * Returns the {@link AlgorithmParameterSpec} that will be used for creation * of the key pair. */ public AlgorithmParameterSpec getAlgorithmParameterSpec() { return mSpec; } /** Loading Loading @@ -209,6 +328,12 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private String mKeystoreAlias; private String mKeyType = "RSA"; private int mKeySize = -1; private AlgorithmParameterSpec mSpec; private X500Principal mSubjectDN; private BigInteger mSerialNumber; Loading Loading @@ -245,6 +370,49 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { return this; } /** * Sets the key type (e.g., RSA, DSA, EC) 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) { throw new NoSuchAlgorithmException("Unsupported key type: " + keyType); } } mKeyType = keyType; return this; } /** * Sets the key size for the keypair to be created. For instance, for a * key type of RSA this will set the modulus size and for a key type of * EC it will select a curve with a matching field size. */ public Builder setKeySize(int keySize) { if (keySize < 0) { throw new IllegalArgumentException("keySize < 0"); } mKeySize = keySize; return this; } /** * 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}. */ public Builder setAlgorithmParameterSpec(AlgorithmParameterSpec spec) { if (spec == null) { throw new NullPointerException("spec == null"); } mSpec = spec; return this; } /** * Sets the subject used for the self-signed certificate of the * generated key pair. Loading Loading @@ -311,8 +479,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * @return built instance of {@code KeyPairGeneratorSpec} */ public KeyPairGeneratorSpec build() { return new KeyPairGeneratorSpec(mContext, mKeystoreAlias, mSubjectDN, mSerialNumber, mStartDate, mEndDate, mFlags); return new KeyPairGeneratorSpec(mContext, mKeystoreAlias, mKeyType, mKeySize, mSpec, mSubjectDN, mSerialNumber, mStartDate, mEndDate, mFlags); } } } keystore/java/android/security/KeyStore.java +17 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.security; import com.android.org.conscrypt.NativeCrypto; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; Loading Loading @@ -64,6 +66,18 @@ public class KeyStore { return new KeyStore(keystore); } static int getKeyTypeForAlgorithm(String keyType) throws IllegalArgumentException { 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); } } public State state() { final int ret; try { Loading Loading @@ -188,9 +202,10 @@ public class KeyStore { } } public boolean generate(String key, int uid, int flags) { public boolean generate(String key, int uid, int keyType, int keySize, int flags, byte[][] args) { try { return mBinder.generate(key, uid, flags) == NO_ERROR; return mBinder.generate(key, uid, keyType, keySize, flags, args) == NO_ERROR; } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); return false; Loading Loading
api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -22593,8 +22593,11 @@ package android.security { } public final class KeyPairGeneratorSpec implements java.security.spec.AlgorithmParameterSpec { method public java.security.spec.AlgorithmParameterSpec getAlgorithmParameterSpec(); method public android.content.Context getContext(); method public java.util.Date getEndDate(); method public int getKeySize(); method public java.lang.String getKeyType(); method public java.lang.String getKeystoreAlias(); method public java.math.BigInteger getSerialNumber(); method public java.util.Date getStartDate(); Loading @@ -22605,9 +22608,12 @@ package android.security { public static final class KeyPairGeneratorSpec.Builder { ctor public KeyPairGeneratorSpec.Builder(android.content.Context); method public android.security.KeyPairGeneratorSpec build(); method public android.security.KeyPairGeneratorSpec.Builder setAlgorithmParameterSpec(java.security.spec.AlgorithmParameterSpec); method public android.security.KeyPairGeneratorSpec.Builder setAlias(java.lang.String); method public android.security.KeyPairGeneratorSpec.Builder setEncryptionRequired(); method public android.security.KeyPairGeneratorSpec.Builder setEndDate(java.util.Date); method public android.security.KeyPairGeneratorSpec.Builder setKeySize(int); method public android.security.KeyPairGeneratorSpec.Builder setKeyType(java.lang.String) throws java.security.NoSuchAlgorithmException; method public android.security.KeyPairGeneratorSpec.Builder setSerialNumber(java.math.BigInteger); method public android.security.KeyPairGeneratorSpec.Builder setStartDate(java.util.Date); method public android.security.KeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal);
core/java/android/security/IKeystoreService.java +14 −2 Original line number Diff line number Diff line Loading @@ -244,7 +244,8 @@ public interface IKeystoreService extends IInterface { return _result; } public int generate(String name, int uid, int flags) throws RemoteException { public int generate(String name, int uid, int keyType, int keySize, int flags, byte[][] args) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; Loading @@ -252,7 +253,17 @@ public interface IKeystoreService extends IInterface { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(name); _data.writeInt(uid); _data.writeInt(keyType); _data.writeInt(keySize); _data.writeInt(flags); if (args == null) { _data.writeInt(0); } else { _data.writeInt(args.length); for (int i = 0; i < args.length; i++) { _data.writeByteArray(args[i]); } } mRemote.transact(Stub.TRANSACTION_generate, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); Loading Loading @@ -560,7 +571,8 @@ public interface IKeystoreService extends IInterface { public int zero() throws RemoteException; public int generate(String name, int uid, int flags) throws RemoteException; public int generate(String name, int uid, int keyType, int keySize, int flags, byte[][] args) throws RemoteException; public int import_key(String name, byte[] data, int uid, int flags) throws RemoteException; Loading
keystore/java/android/security/AndroidKeyPairGenerator.java +43 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.security; import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; import com.android.org.conscrypt.NativeCrypto; import com.android.org.conscrypt.OpenSSLEngine; import java.security.InvalidAlgorithmParameterException; Loading @@ -33,7 +34,10 @@ 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.ECParameterSpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.X509EncodedKeySpec; /** Loading Loading @@ -87,8 +91,12 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { Credentials.deleteAllTypesForAlias(mKeyStore, alias); final int keyType = KeyStore.getKeyTypeForAlgorithm(mSpec.getKeyType()); byte[][] args = getArgsForKeyType(keyType, mSpec.getAlgorithmParameterSpec()); final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias; if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, mSpec.getFlags())) { if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, keyType, mSpec.getKeySize(), mSpec.getFlags(), args)) { throw new IllegalStateException("could not generate key in keystore"); } Loading @@ -104,10 +112,10 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { final PublicKey pubKey; try { final KeyFactory keyFact = KeyFactory.getInstance("RSA"); final KeyFactory keyFact = KeyFactory.getInstance(mSpec.getKeyType()); pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes)); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("Can't instantiate RSA key generator", e); throw new IllegalStateException("Can't instantiate key generator", e); } catch (InvalidKeySpecException e) { throw new IllegalStateException("keystore returned invalid key encoding", e); } Loading @@ -119,7 +127,7 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { certGen.setIssuerDN(mSpec.getSubjectDN()); certGen.setNotBefore(mSpec.getStartDate()); certGen.setNotAfter(mSpec.getEndDate()); certGen.setSignatureAlgorithm("sha1WithRSA"); certGen.setSignatureAlgorithm(getDefaultSignatureAlgorithmForKeyType(mSpec.getKeyType())); final X509Certificate cert; try { Loading @@ -146,6 +154,37 @@ public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { return new KeyPair(pubKey, privKey); } private static String getDefaultSignatureAlgorithmForKeyType(String keyType) { if ("RSA".equalsIgnoreCase(keyType)) { return "sha256WithRSA"; } else if ("DSA".equalsIgnoreCase(keyType)) { return "sha1WithDSA"; } else if ("EC".equalsIgnoreCase(keyType)) { return "sha256WithECDSA"; } else { throw new IllegalArgumentException("Unsupported key type " + keyType); } } private static byte[][] getArgsForKeyType(int keyType, AlgorithmParameterSpec spec) { switch (keyType) { case NativeCrypto.EVP_PKEY_RSA: if (spec instanceof RSAKeyGenParameterSpec) { RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) spec; 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; } @Override public void initialize(int keysize, SecureRandom random) { throw new IllegalArgumentException("cannot specify keysize with AndroidKeyPairGenerator"); Loading
keystore/java/android/security/KeyPairGeneratorSpec.java +177 −9 Original line number Diff line number Diff line Loading @@ -16,13 +16,18 @@ package android.security; import com.android.org.conscrypt.NativeCrypto; import android.content.Context; import android.text.TextUtils; import java.math.BigInteger; 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; Loading Loading @@ -50,10 +55,35 @@ import javax.security.auth.x500.X500Principal; * certificate signed by a real Certificate Authority. */ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private final String mKeystoreAlias; /* * 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; private final String mKeystoreAlias; private final String mKeyType; private final int mKeySize; private final AlgorithmParameterSpec mSpec; private final X500Principal mSubjectDN; private final BigInteger mSerialNumber; Loading Loading @@ -84,6 +114,9 @@ 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 keySize size of key to generate * @param spec the underlying key type parameters * @param subjectDN X.509 v3 Subject Distinguished Name * @param serialNumber X509 v3 certificate serial number * @param startDate the start of the self-signed certificate validity period Loading @@ -93,9 +126,9 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * {@code endDate} is before {@code startDate}. * @hide should be built with KeyPairGeneratorSpecBuilder */ public KeyPairGeneratorSpec(Context context, String keyStoreAlias, X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate, int flags) { public KeyPairGeneratorSpec(Context context, String keyStoreAlias, String keyType, int keySize, AlgorithmParameterSpec spec, X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate, int flags) { if (context == null) { throw new IllegalArgumentException("context == null"); } else if (TextUtils.isEmpty(keyStoreAlias)) { Loading @@ -112,8 +145,18 @@ 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; mKeySize = keySize; mSpec = spec; mSubjectDN = subjectDN; mSerialNumber = serialNumber; mStartDate = startDate; Loading @@ -121,6 +164,64 @@ 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. */ public Context getContext() { return mContext; } /** * Returns the alias that will be used in the {@code java.security.KeyStore} * in conjunction with the {@code AndroidKeyStore}. Loading @@ -130,10 +231,28 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { } /** * Gets the Android context used for operations with this instance. * Returns the key type (e.g., "RSA", "DSA", "EC") specified by this * parameter. */ public Context getContext() { return mContext; public String getKeyType() { return mKeyType; } /** * Returns the key size specified by this parameter. For instance, for RSA * this will return the modulus size and for EC it will return the field * size. */ public int getKeySize() { return mKeySize; } /** * Returns the {@link AlgorithmParameterSpec} that will be used for creation * of the key pair. */ public AlgorithmParameterSpec getAlgorithmParameterSpec() { return mSpec; } /** Loading Loading @@ -209,6 +328,12 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private String mKeystoreAlias; private String mKeyType = "RSA"; private int mKeySize = -1; private AlgorithmParameterSpec mSpec; private X500Principal mSubjectDN; private BigInteger mSerialNumber; Loading Loading @@ -245,6 +370,49 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { return this; } /** * Sets the key type (e.g., RSA, DSA, EC) 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) { throw new NoSuchAlgorithmException("Unsupported key type: " + keyType); } } mKeyType = keyType; return this; } /** * Sets the key size for the keypair to be created. For instance, for a * key type of RSA this will set the modulus size and for a key type of * EC it will select a curve with a matching field size. */ public Builder setKeySize(int keySize) { if (keySize < 0) { throw new IllegalArgumentException("keySize < 0"); } mKeySize = keySize; return this; } /** * 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}. */ public Builder setAlgorithmParameterSpec(AlgorithmParameterSpec spec) { if (spec == null) { throw new NullPointerException("spec == null"); } mSpec = spec; return this; } /** * Sets the subject used for the self-signed certificate of the * generated key pair. Loading Loading @@ -311,8 +479,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * @return built instance of {@code KeyPairGeneratorSpec} */ public KeyPairGeneratorSpec build() { return new KeyPairGeneratorSpec(mContext, mKeystoreAlias, mSubjectDN, mSerialNumber, mStartDate, mEndDate, mFlags); return new KeyPairGeneratorSpec(mContext, mKeystoreAlias, mKeyType, mKeySize, mSpec, mSubjectDN, mSerialNumber, mStartDate, mEndDate, mFlags); } } }
keystore/java/android/security/KeyStore.java +17 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.security; import com.android.org.conscrypt.NativeCrypto; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; Loading Loading @@ -64,6 +66,18 @@ public class KeyStore { return new KeyStore(keystore); } static int getKeyTypeForAlgorithm(String keyType) throws IllegalArgumentException { 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); } } public State state() { final int ret; try { Loading Loading @@ -188,9 +202,10 @@ public class KeyStore { } } public boolean generate(String key, int uid, int flags) { public boolean generate(String key, int uid, int keyType, int keySize, int flags, byte[][] args) { try { return mBinder.generate(key, uid, flags) == NO_ERROR; return mBinder.generate(key, uid, keyType, keySize, flags, args) == NO_ERROR; } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); return false; Loading