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");