Add KeyGenerators to Conscrypt.

This implements KeyGenerators for:
* AES
* DESEDE
* HmacMD5
* HmacSHA1
* HmacSHA{224,256,384,512}

These are implemented but not yet enabled in the provider, so that they
don't show up in devices.

Bug: 62369410
Test: cts -m CtsLibcoreTestCases
Change-Id: I8025752d9c09635569662793e0e4b3642355178f
diff --git a/common/src/main/java/org/conscrypt/KeyGeneratorImpl.java b/common/src/main/java/org/conscrypt/KeyGeneratorImpl.java
new file mode 100644
index 0000000..1223b13
--- /dev/null
+++ b/common/src/main/java/org/conscrypt/KeyGeneratorImpl.java
@@ -0,0 +1,153 @@
+package org.conscrypt;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.KeyGeneratorSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.DESedeKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * An implementation of {@link javax.crypto.KeyGenerator} suitable for use with other Conscrypt
+ * algorithms.
+ *
+ * @hide
+ */
+@Internal
+public abstract class KeyGeneratorImpl extends KeyGeneratorSpi {
+    private final String algorithm;
+    protected SecureRandom secureRandom;
+    private int keySizeBits;
+
+    private KeyGeneratorImpl(String algorithm, int defaultKeySizeBits) {
+        this.algorithm = algorithm;
+        this.keySizeBits = defaultKeySizeBits;
+    }
+
+    protected void checkKeySize(int keySize) {
+        if (keySize <= 0) {
+            throw new InvalidParameterException("Key size must be positive");
+        }
+    }
+
+    @Override
+    protected void engineInit(SecureRandom secureRandom) {
+        this.secureRandom = secureRandom;
+    }
+
+    @Override
+    protected void engineInit(AlgorithmParameterSpec params, SecureRandom secureRandom)
+            throws InvalidAlgorithmParameterException {
+        if (params == null) {
+            throw new InvalidAlgorithmParameterException("No params provided");
+        } else {
+            throw new InvalidAlgorithmParameterException(
+                    "Unknown param type: " + params.getClass().getName());
+        }
+    }
+
+    @Override
+    protected void engineInit(int keySize, SecureRandom secureRandom) {
+        checkKeySize(keySize);
+        this.keySizeBits = keySize;
+        this.secureRandom = secureRandom;
+    }
+
+    protected byte[] doKeyGeneration(int keyBytes) {
+        byte[] keyData = new byte[keyBytes];
+        secureRandom.nextBytes(keyData);
+        return keyData;
+    }
+
+    @Override
+    protected SecretKey engineGenerateKey() {
+        if (secureRandom == null) {
+            secureRandom = new SecureRandom();
+        }
+
+        return new SecretKeySpec(doKeyGeneration((keySizeBits + 7) / 8), algorithm);
+    }
+
+    // For HMAC, RFC 2104 recommends using the hash's output length as the key length
+    public static final class HmacMD5 extends KeyGeneratorImpl {
+        public HmacMD5() {
+            super("HmacMD5", 128);
+        }
+    }
+
+    public static final class HmacSHA1 extends KeyGeneratorImpl {
+        public HmacSHA1() {
+            super("HmacSHA1", 160);
+        }
+    }
+
+    public static final class HmacSHA224 extends KeyGeneratorImpl {
+        public HmacSHA224() {
+            super("HmacSHA224", 224);
+        }
+    }
+
+    public static final class HmacSHA256 extends KeyGeneratorImpl {
+        public HmacSHA256() {
+            super("HmacSHA256", 256);
+        }
+    }
+
+    public static final class HmacSHA384 extends KeyGeneratorImpl {
+        public HmacSHA384() {
+            super("HmacSHA384", 384);
+        }
+    }
+
+    public static final class HmacSHA512 extends KeyGeneratorImpl {
+        public HmacSHA512() {
+            super("HmacSHA512", 512);
+        }
+    }
+
+    public static final class DESEDE extends KeyGeneratorImpl {
+        public DESEDE() {
+            super("DESEDE", 192);
+        }
+
+        @Override
+        protected void checkKeySize(int keySize) {
+            if ((keySize != 112) && (keySize != 168)) {
+                throw new InvalidParameterException("Key size must be either 112 or 168 bits");
+            }
+        }
+
+        @Override
+        protected byte[] doKeyGeneration(int keyBytes) {
+            byte[] keyData = new byte[DESedeKeySpec.DES_EDE_KEY_LEN];
+            secureRandom.nextBytes(keyData);
+            // Set the parity bit for each byte
+            for (int i = 0; i < keyData.length; i++) {
+                if (Integer.bitCount(keyData[i]) % 2 == 0) {
+                    keyData[i] ^= 1;
+                }
+            }
+            if (keyBytes == 14) {
+                // The user requested an A-B-A key
+                System.arraycopy(keyData, 0, keyData, 16, 8);
+            }
+            return keyData;
+        }
+    }
+
+    public static final class AES extends KeyGeneratorImpl {
+        public AES() {
+            super("AES", 128);
+        }
+
+        @Override
+        protected void checkKeySize(int keySize) {
+            if ((keySize != 128) && (keySize != 192) && (keySize != 256)) {
+                throw new InvalidParameterException(
+                        "Key size must be either 128, 192, or 256 bits");
+            }
+        }
+    }
+}
diff --git a/common/src/main/java/org/conscrypt/OpenSSLProvider.java b/common/src/main/java/org/conscrypt/OpenSSLProvider.java
index 15fea2c..95e18f2 100644
--- a/common/src/main/java/org/conscrypt/OpenSSLProvider.java
+++ b/common/src/main/java/org/conscrypt/OpenSSLProvider.java
@@ -98,6 +98,47 @@
         put("MessageDigest.MD5", PREFIX + "OpenSSLMessageDigestJDK$MD5");
         put("Alg.Alias.MessageDigest.1.2.840.113549.2.5", "MD5");
 
+        /* == KeyGenerators == */
+        // TODO: Enable
+        /*
+        put("KeyGenerator.AES", PREFIX + "KeyGeneratorImpl$AES");
+
+        put("KeyGenerator.DESEDE", PREFIX + "KeyGeneratorImpl$DESEDE");
+        put("Alg.Alias.KeyGenerator.TDEA", "DESEDE");
+
+        put("KeyGenerator.HmacMD5", PREFIX + "KeyGeneratorImpl$HmacMD5");
+        put("Alg.Alias.KeyGenerator.1.3.6.1.5.5.8.1.1", "HmacMD5");
+        put("Alg.Alias.KeyGenerator.HMAC-MD5", "HmacMD5");
+        put("Alg.Alias.KeyGenerator.HMAC/MD5", "HmacMD5");
+
+        put("KeyGenerator.HmacSHA1", PREFIX + "KeyGeneratorImpl$HmacSHA1");
+        put("Alg.Alias.KeyGenerator.1.2.840.113549.2.7", "HmacSHA1");
+        put("Alg.Alias.KeyGenerator.1.3.6.1.5.5.8.1.2", "HmacSHA1");
+        put("Alg.Alias.KeyGenerator.HMAC-SHA1", "HmacSHA1");
+        put("Alg.Alias.KeyGenerator.HMAC/SHA1", "HmacSHA1");
+
+        put("KeyGenerator.HmacSHA224", PREFIX + "KeyGeneratorImpl$HmacSHA224");
+        put("Alg.Alias.KeyGenerator.1.2.840.113549.2.8", "HmacSHA224");
+        put("Alg.Alias.KeyGenerator.HMAC-SHA224", "HmacSHA224");
+        put("Alg.Alias.KeyGenerator.HMAC/SHA224", "HmacSHA224");
+
+        put("KeyGenerator.HmacSHA256", PREFIX + "KeyGeneratorImpl$HmacSHA256");
+        put("Alg.Alias.KeyGenerator.1.2.840.113549.2.9", "HmacSHA256");
+        put("Alg.Alias.KeyGenerator.2.16.840.1.101.3.4.2.1", "HmacSHA256");
+        put("Alg.Alias.KeyGenerator.HMAC-SHA256", "HmacSHA256");
+        put("Alg.Alias.KeyGenerator.HMAC/SHA256", "HmacSHA256");
+
+        put("KeyGenerator.HmacSHA384", PREFIX + "KeyGeneratorImpl$HmacSHA384");
+        put("Alg.Alias.KeyGenerator.1.2.840.113549.2.10", "HmacSHA384");
+        put("Alg.Alias.KeyGenerator.HMAC-SHA384", "HmacSHA384");
+        put("Alg.Alias.KeyGenerator.HMAC/SHA384", "HmacSHA384");
+
+        put("KeyGenerator.HmacSHA512", PREFIX + "KeyGeneratorImpl$HmacSHA512");
+        put("Alg.Alias.KeyGenerator.1.2.840.113549.2.11", "HmacSHA512");
+        put("Alg.Alias.KeyGenerator.HMAC-SHA512", "HmacSHA512");
+        put("Alg.Alias.KeyGenerator.HMAC/SHA512", "HmacSHA512");
+        */
+
         /* == KeyPairGenerators == */
         put("KeyPairGenerator.RSA", PREFIX + "OpenSSLRSAKeyPairGenerator");
         put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.1", "RSA");