Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e0609eb authored by Kenny Root's avatar Kenny Root Committed by Android (Google) Code Review
Browse files

Merge changes Ic710807d,I88dfcc8c into klp-dev

* changes:
  Unhide functions to allow ECDSA support
  Add support for DSA and ECDSA key types
parents dd592e2a c222ddd0
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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();
@@ -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);
+14 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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();
@@ -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;

+43 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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;

/**
@@ -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");
        }

@@ -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);
        }
@@ -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 {
@@ -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");
+177 −9
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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
@@ -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)) {
@@ -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;
@@ -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}.
@@ -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;
    }

    /**
@@ -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;
@@ -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.
@@ -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);
        }
    }
}
+17 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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 {
@@ -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