summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
diff options
context:
space:
mode:
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java138
1 files changed, 97 insertions, 41 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
index fd9b9a9f..63d7b351 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
@@ -20,6 +20,9 @@ import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.interfaces.PBEKey;
import javax.crypto.spec.IvParameterSpec;
+// BEGIN android-added
+import javax.crypto.spec.PBEKeySpec;
+// END android-added
import javax.crypto.spec.PBEParameterSpec;
// BEGIN android-removed
// import javax.crypto.spec.RC2ParameterSpec;
@@ -75,6 +78,7 @@ import org.bouncycastle.crypto.params.RC2Parameters;
// END android-removed
import org.bouncycastle.jcajce.PKCS12Key;
import org.bouncycastle.jcajce.PKCS12KeyWithParameters;
+import org.bouncycastle.jcajce.spec.AEADParameterSpec;
// BEGIN android-removed
// import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
// import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec;
@@ -174,9 +178,9 @@ public class BaseBlockCipher
protected BaseBlockCipher(
AEADBlockCipher engine)
{
- baseEngine = engine.getUnderlyingCipher();
- ivLength = baseEngine.getBlockSize();
- cipher = new AEADGenericBlockCipher(engine);
+ this.baseEngine = engine.getUnderlyingCipher();
+ this.ivLength = baseEngine.getBlockSize();
+ this.cipher = new AEADGenericBlockCipher(engine);
}
protected BaseBlockCipher(
@@ -253,6 +257,18 @@ public class BaseBlockCipher
return null;
}
}
+ else if (aeadParams != null)
+ {
+ try
+ {
+ engineParams = createParametersInstance("GCM");
+ engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize() / 8).getEncoded());
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
else if (ivParam != null)
{
String name = cipher.getUnderlyingCipher().getAlgorithmName();
@@ -272,18 +288,6 @@ public class BaseBlockCipher
throw new RuntimeException(e.toString());
}
}
- else if (aeadParams != null)
- {
- try
- {
- engineParams = createParametersInstance("GCM");
- engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize() / 8).getEncoded());
- }
- catch (Exception e)
- {
- throw new RuntimeException(e.toString());
- }
- }
}
return engineParams;
@@ -512,7 +516,7 @@ public class BaseBlockCipher
//
if (!(key instanceof SecretKey))
{
- throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption.");
+ throw new InvalidKeyException("Key for algorithm " + ((key != null) ? key.getAlgorithm() : null) + " not suitable for symmetric enryption.");
}
//
@@ -550,34 +554,29 @@ public class BaseBlockCipher
if (k instanceof PBEKey && pbeSpec == null)
{
- // BEGIN android-added
- if (((PBEKey)k).getSalt() == null) {
- throw new InvalidAlgorithmParameterException("Parameters for the algorithm are null "
- + "and the PBEKey has null salt");
+ PBEKey pbeKey = (PBEKey)k;
+ if (pbeKey.getSalt() == null)
+ {
+ throw new InvalidAlgorithmParameterException("PBEKey requires parameters to specify salt");
}
- // END android-added
- pbeSpec = new PBEParameterSpec(((PBEKey)k).getSalt(), ((PBEKey)k).getIterationCount());
+ pbeSpec = new PBEParameterSpec(pbeKey.getSalt(), pbeKey.getIterationCount());
}
if (pbeSpec == null && !(k instanceof PBEKey))
{
throw new InvalidKeyException("Algorithm requires a PBE key");
}
+
if (key instanceof BCPBEKey)
{
- // BEGIN android-changed
- // Was:
- // if (((BCPBEKey)key).getParam() != null)
- // Change taken from:
- // https://github.com/bcgit/bc-java/commit/fcba5c782188d772148ba168beae368d06646ee2
- // PKCS#12 sets an IV, if we get a key that doesn't have ParametersWithIV we need to forget about the fact
- // it's a BCPBEKey
- if (((BCPBEKey)key).getParam() != null && ((BCPBEKey)key).getParam() instanceof ParametersWithIV)
- // END android-changed
+ // PKCS#12 sets an IV, if we get a key that doesn't have ParametersWithIV we need to reject it. If the
+ // key has no parameters it means it's an old-school JCE PBE Key - we use getEncoded() on it.
+ CipherParameters pbeKeyParam = ((BCPBEKey)key).getParam();
+ if (pbeKeyParam instanceof ParametersWithIV)
{
- param = ((BCPBEKey)key).getParam();
+ param = pbeKeyParam;
}
- else
+ else if (pbeKeyParam == null)
{
// BEGIN android-changed
// Was: param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName());
@@ -587,6 +586,10 @@ public class BaseBlockCipher
// END android-changed
throw new IllegalStateException("Unreachable code");
}
+ else
+ {
+ throw new InvalidKeyException("Algorithm requires a PBE key suitable for PKCS12");
+ }
}
else
{
@@ -638,6 +641,19 @@ public class BaseBlockCipher
else if (params instanceof PBEParameterSpec)
{
pbeSpec = (PBEParameterSpec)params;
+ // BEGIN android-added
+ // At this point, k.getParam() == null, so the key hasn't been generated. If
+ // the parameters have non-default values, recreate the BCPBEKey from algorithm
+ // parameters as to generate the key.
+ if ((pbeSpec.getSalt().length != 0) && (pbeSpec.getIterationCount() > 0)) {
+ k = new BCPBEKey(k.getAlgorithm(), k.getOID(), k.getType(), k.getDigest(),
+ k.getKeySize(), k.getIvSize(),
+ new PBEKeySpec(
+ k.getPassword(), pbeSpec.getSalt(), pbeSpec.getIterationCount(),
+ k.getKeySize()),
+ null /* CipherParameters */);
+ }
+ // END android-added
param = PBE.Util.makePBEParameters(k, params, cipher.getUnderlyingCipher().getAlgorithmName());
}
else
@@ -683,7 +699,27 @@ public class BaseBlockCipher
// }
// END android-removed
- if (params instanceof IvParameterSpec)
+ if (params instanceof AEADParameterSpec)
+ {
+ if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher))
+ {
+ throw new InvalidAlgorithmParameterException("AEADParameterSpec can only be used with AEAD modes.");
+ }
+
+ AEADParameterSpec aeadSpec = (AEADParameterSpec)params;
+
+ KeyParameter keyParam;
+ if (param instanceof ParametersWithIV)
+ {
+ keyParam = (KeyParameter)((ParametersWithIV)param).getParameters();
+ }
+ else
+ {
+ keyParam = (KeyParameter)param;
+ }
+ param = aeadParams = new AEADParameters(keyParam, aeadSpec.getMacSizeInBits(), aeadSpec.getNonce(), aeadSpec.getAssociatedData());
+ }
+ else if (params instanceof IvParameterSpec)
{
if (ivLength != 0)
{
@@ -865,6 +901,8 @@ public class BaseBlockCipher
}
}
+
+
if (random != null && padded)
{
param = new ParametersWithRandom(param, random);
@@ -885,16 +923,17 @@ public class BaseBlockCipher
default:
throw new InvalidParameterException("unknown opmode " + opmode + " passed");
}
+
+ if (cipher instanceof AEADGenericBlockCipher && aeadParams == null)
+ {
+ AEADBlockCipher aeadCipher = ((AEADGenericBlockCipher)cipher).cipher;
+
+ aeadParams = new AEADParameters((KeyParameter)ivParam.getParameters(), aeadCipher.getMac().length * 8, ivParam.getIV());
+ }
}
catch (final Exception e)
{
- throw new InvalidKeyException(e.getMessage())
- {
- public Throwable getCause()
- {
- return e;
- }
- };
+ throw new InvalidKeyOrParametersException(e.getMessage(), e);
}
}
@@ -1380,4 +1419,21 @@ public class BaseBlockCipher
}
}
}
+
+ private static class InvalidKeyOrParametersException
+ extends InvalidKeyException
+ {
+ private final Throwable cause;
+
+ InvalidKeyOrParametersException(String msg, Throwable cause)
+ {
+ super(msg);
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+ }
}