summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/src/main/java/org/conscrypt/OpenSSLCipher.java49
-rw-r--r--luni/src/test/java/libcore/javax/crypto/CipherTest.java60
2 files changed, 100 insertions, 9 deletions
diff --git a/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java b/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
index 632f9e2..7acccc7 100644
--- a/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
@@ -16,6 +16,7 @@
package org.conscrypt;
+import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -118,6 +119,11 @@ public abstract class OpenSSLCipher extends CipherSpi {
}
/**
+ * Returns the standard name for the particular algorithm.
+ */
+ protected abstract String getBaseCipherName();
+
+ /**
* Returns the OpenSSL cipher name for the particular {@code keySize} and
* cipher {@code mode}.
*/
@@ -214,10 +220,22 @@ public abstract class OpenSSLCipher extends CipherSpi {
@Override
protected AlgorithmParameters engineGetParameters() {
+ if (iv != null && iv.length > 0) {
+ try {
+ AlgorithmParameters params = AlgorithmParameters.getInstance(getBaseCipherName());
+ params.init(iv);
+ return params;
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
return null;
}
- private void engineInitInternal(int opmode, Key key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException {
+ private void engineInitInternal(int opmode, Key key, byte[] iv, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE) {
encrypting = true;
} else if (opmode == Cipher.DECRYPT_MODE || opmode == Cipher.UNWRAP_MODE) {
@@ -245,9 +263,15 @@ public abstract class OpenSSLCipher extends CipherSpi {
}
final int ivLength = NativeCrypto.EVP_CIPHER_iv_length(cipherType);
- if (iv == null) {
+ if (iv == null && ivLength != 0) {
iv = new byte[ivLength];
- } else if (iv.length != ivLength) {
+ if (encrypting) {
+ if (random == null) {
+ random = new SecureRandom();
+ }
+ random.nextBytes(iv);
+ }
+ } else if (iv != null && iv.length != ivLength) {
throw new InvalidAlgorithmParameterException("expected IV length of " + ivLength);
}
@@ -273,7 +297,7 @@ public abstract class OpenSSLCipher extends CipherSpi {
@Override
protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
try {
- engineInitInternal(opmode, key, null);
+ engineInitInternal(opmode, key, null, random);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
@@ -290,7 +314,7 @@ public abstract class OpenSSLCipher extends CipherSpi {
iv = null;
}
- engineInitInternal(opmode, key, iv);
+ engineInitInternal(opmode, key, iv, random);
}
@Override
@@ -631,6 +655,11 @@ public abstract class OpenSSLCipher extends CipherSpi {
}
@Override
+ protected String getBaseCipherName() {
+ return "AES";
+ }
+
+ @Override
protected String getCipherName(int keyLength, Mode mode) {
return "aes-" + (keyLength * 8) + "-" + mode.toString().toLowerCase(Locale.US);
}
@@ -721,6 +750,11 @@ public abstract class OpenSSLCipher extends CipherSpi {
}
@Override
+ protected String getBaseCipherName() {
+ return "DESede";
+ }
+
+ @Override
protected String getCipherName(int keySize, Mode mode) {
final String baseCipherName;
if (keySize == 16) {
@@ -780,6 +814,11 @@ public abstract class OpenSSLCipher extends CipherSpi {
}
@Override
+ protected String getBaseCipherName() {
+ return "ARCFOUR";
+ }
+
+ @Override
protected String getCipherName(int keySize, Mode mode) {
return "rc4";
}
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index dac43a2..7922a04 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.math.BigInteger;
import java.nio.ByteBuffer;
+import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -778,8 +779,10 @@ public final class CipherTest extends TestCase {
// Cipher.getInstance(String)
Cipher c1 = Cipher.getInstance(algorithm);
- assertEquals(algorithm, c1.getAlgorithm());
- test_Cipher(c1);
+ if (provider.equals(c1.getProvider())) {
+ assertEquals(algorithm, c1.getAlgorithm());
+ test_Cipher(c1);
+ }
// Cipher.getInstance(String, Provider)
Cipher c2 = Cipher.getInstance(algorithm, provider);
@@ -812,6 +815,23 @@ public final class CipherTest extends TestCase {
final AlgorithmParameterSpec encryptSpec = getEncryptAlgorithmParameterSpec(algorithm);
int encryptMode = getEncryptMode(algorithm);
+
+ // Bouncycastle doesn't return a default PBEParameterSpec
+ if (isPBE(algorithm) && !"BC".equals(providerName)) {
+ assertNotNull(cipherID + " getParameters()", c.getParameters());
+ assertNotNull(c.getParameters().getParameterSpec(PBEParameterSpec.class));
+ } else {
+ assertNull(cipherID + " getParameters()", c.getParameters());
+ }
+ try {
+ assertNull(cipherID + " getIV()", c.getIV());
+ } catch (NullPointerException e) {
+ // Bouncycastle apparently has a bug here with AESWRAP, et al.
+ if (!("BC".equals(providerName) && isOnlyWrappingAlgorithm(algorithm))) {
+ throw e;
+ }
+ }
+
c.init(encryptMode, encryptKey, encryptSpec);
assertEquals(cipherID + " getBlockSize() encryptMode",
getExpectedBlockSize(algorithm, encryptMode, providerName), c.getBlockSize());
@@ -826,9 +846,41 @@ public final class CipherTest extends TestCase {
assertEquals(cipherID + " getOutputSize(0) decryptMode",
getExpectedOutputSize(algorithm, decryptMode, providerName), c.getOutputSize(0));
- // TODO: test Cipher.getIV()
+ if (isPBE(algorithm)) {
+ if (algorithm.endsWith("RC4")) {
+ assertNull(cipherID + " getIV()", c.getIV());
+ } else {
+ assertNotNull(cipherID + " getIV()", c.getIV());
+ }
+ } else if (decryptSpec instanceof IvParameterSpec) {
+ assertEquals(cipherID + " getIV()",
+ Arrays.toString(((IvParameterSpec) decryptSpec).getIV()),
+ Arrays.toString(c.getIV()));
+ } else {
+ try {
+ assertNull(cipherID + " getIV()", c.getIV());
+ } catch (NullPointerException e) {
+ // Bouncycastle apparently has a bug here with AESWRAP, et al.
+ if (!("BC".equals(providerName) && isOnlyWrappingAlgorithm(algorithm))) {
+ throw e;
+ }
+ }
+ }
- // TODO: test Cipher.getParameters()
+ AlgorithmParameters params = c.getParameters();
+ if (decryptSpec == null) {
+ assertNull(cipherID + " getParameters()", params);
+ } else if (decryptSpec instanceof IvParameterSpec) {
+ IvParameterSpec ivDecryptSpec = (IvParameterSpec) params.getParameterSpec(IvParameterSpec.class);
+ assertEquals(cipherID + " getIV()",
+ Arrays.toString(((IvParameterSpec) decryptSpec).getIV()),
+ Arrays.toString(ivDecryptSpec.getIV()));
+ } else if (decryptSpec instanceof PBEParameterSpec) {
+ // Bouncycastle seems to be schizophrenic about whther it returns this or not
+ if (!"BC".equals(providerName)) {
+ assertNotNull(cipherID + " getParameters()", params);
+ }
+ }
assertNull(cipherID, c.getExemptionMechanism());