summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/crypto
diff options
context:
space:
mode:
authorSergio Giro <sgiro@google.com>2015-04-09 14:10:16 +0100
committerSergio Giro <sgiro@google.com>2015-04-20 15:41:23 +0100
commit028ab6e01e3b911024b9b9243e9a0f4ac377c0fa (patch)
tree35d98bf60cbe7a6487bd0014728eb263e89004bb /bcprov/src/main/java/org/bouncycastle/crypto
parentb44aff7a3b88138f0070630d467c7527cd90c2f3 (diff)
downloadandroid_external_bouncycastle-028ab6e01e3b911024b9b9243e9a0f4ac377c0fa.tar.gz
android_external_bouncycastle-028ab6e01e3b911024b9b9243e9a0f4ac377c0fa.tar.bz2
android_external_bouncycastle-028ab6e01e3b911024b9b9243e9a0f4ac377c0fa.zip
bouncycastle: upgrade to version 1.52
Change-Id: I227db8e458e67af46ccb1c07bfca77a733f25979
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java22
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java166
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java78
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java100
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java213
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java42
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java2
14 files changed, 335 insertions, 334 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
index 8e41e49..39f59da 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -141,7 +141,7 @@ public class BufferedBlockCipher
}
/**
- * process a single byte, producing an output block if neccessary.
+ * process a single byte, producing an output block if necessary.
*
* @param in the input byte.
* @param out the space for any output that might be produced.
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
index c78b1a5..7ba71c7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
@@ -70,7 +70,7 @@ public class PKCS1Encoding
* @param cipher
* The cipher to use for cryptographic operation.
* @param fallback
- * The fallback value, we don't to a arraycopy here.
+ * The fallback value, we don't do an arraycopy here.
*/
public PKCS1Encoding(
AsymmetricBlockCipher cipher,
@@ -350,7 +350,8 @@ public class PKCS1Encoding
* If the length of the expected plaintext is known, we use a constant-time decryption.
* If the decryption fails, we return a random value.
*/
- if (this.pLen != -1) {
+ if (this.pLen != -1)
+ {
return this.decodeBlockOrRandom(in, inOff, inLen);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java
index 5d316ac..6d3e5ac 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java
@@ -9,8 +9,21 @@ package org.bouncycastle.crypto.engines;
public class AESWrapEngine
extends RFC3394WrapEngine
{
+ /**
+ * Create a regular AESWrapEngine specifying the encrypt for wrapping, decrypt for unwrapping.
+ */
public AESWrapEngine()
{
super(new AESEngine());
}
+
+ /**
+ * Create an AESWrapEngine where the underlying cipher is set to decrypt for wrapping, encrypt for unwrapping.
+ *
+ * @param useReverseDirection true if underlying cipher should be used in decryption mode, false otherwise.
+ */
+ public AESWrapEngine(boolean useReverseDirection)
+ {
+ super(new AESEngine(), useReverseDirection);
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
index cfd86fb..d2886e7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
@@ -21,6 +21,7 @@ public class RFC3394WrapEngine
implements Wrapper
{
private BlockCipher engine;
+ private boolean wrapCipherMode;
private KeyParameter param;
private boolean forWrapping;
@@ -28,9 +29,26 @@ public class RFC3394WrapEngine
(byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6,
(byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6 };
+ /**
+ * Create a RFC 3394 WrapEngine specifying the encrypt for wrapping, decrypt for unwrapping.
+ *
+ * @param engine the block cipher to be used for wrapping.
+ */
public RFC3394WrapEngine(BlockCipher engine)
{
+ this(engine, false);
+ }
+
+ /**
+ * Create a RFC 3394 WrapEngine specifying the direction for wrapping and unwrapping..
+ *
+ * @param engine the block cipher to be used for wrapping.
+ * @param useReverseDirection true if engine should be used in decryption mode for wrapping, false otherwise.
+ */
+ public RFC3394WrapEngine(BlockCipher engine, boolean useReverseDirection)
+ {
this.engine = engine;
+ this.wrapCipherMode = (useReverseDirection) ? false : true;
}
public void init(
@@ -87,7 +105,7 @@ public class RFC3394WrapEngine
System.arraycopy(iv, 0, block, 0, iv.length);
System.arraycopy(in, inOff, block, iv.length, inLen);
- engine.init(true, param);
+ engine.init(wrapCipherMode, param);
for (int j = 0; j != 6; j++)
{
@@ -140,7 +158,7 @@ public class RFC3394WrapEngine
System.arraycopy(in, inOff, a, 0, iv.length);
System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length);
- engine.init(false, param);
+ engine.init(!wrapCipherMode, param);
n = n - 1;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
index 928c6a6..7277045 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
@@ -1,5 +1,7 @@
package org.bouncycastle.crypto.generators;
+import java.math.BigInteger;
+
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
import org.bouncycastle.crypto.KeyGenerationParameters;
@@ -8,8 +10,6 @@ import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.math.ec.WNafUtil;
-import java.math.BigInteger;
-
/**
* an RSA key pair generator.
*/
@@ -27,96 +27,118 @@ public class RSAKeyPairGenerator
public AsymmetricCipherKeyPair generateKeyPair()
{
- BigInteger p, q, n, d, e, pSub1, qSub1, phi;
+ AsymmetricCipherKeyPair result = null;
+ boolean done = false;
- //
- // p and q values should have a length of half the strength in bits
- //
- int strength = param.getStrength();
- int qBitlength = strength >>> 1;
- int pBitlength = strength - qBitlength;
- int mindiffbits = strength / 3;
- int minWeight = strength >>> 2;
+ while (!done)
+ {
+ BigInteger p, q, n, d, e, pSub1, qSub1, phi, lcm, dLowerBound;
- e = param.getPublicExponent();
+ //
+ // p and q values should have a length of half the strength in bits
+ //
+ int strength = param.getStrength();
+ int pbitlength = (strength + 1) / 2;
+ int qbitlength = strength - pbitlength;
+ int mindiffbits = strength / 3;
+ int minWeight = strength >> 2;
- // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
- // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
+ e = param.getPublicExponent();
- p = chooseRandomPrime(pBitlength, e);
+ // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
+ // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
- //
- // generate a modulus of the required length
- //
- for (;;)
- {
- q = chooseRandomPrime(qBitlength, e);
-
- // p and q should not be too close together (or equal!)
- BigInteger diff = q.subtract(p).abs();
- if (diff.bitLength() < mindiffbits)
- {
- continue;
- }
+ p = chooseRandomPrime(pbitlength, e);
//
- // calculate the modulus
+ // generate a modulus of the required length
//
- n = p.multiply(q);
-
- if (n.bitLength() != strength)
+ for (;;)
{
+ q = chooseRandomPrime(qbitlength, e);
+
+ // p and q should not be too close together (or equal!)
+ BigInteger diff = q.subtract(p).abs();
+ if (diff.bitLength() < mindiffbits)
+ {
+ continue;
+ }
+
//
- // if we get here our primes aren't big enough, make the largest
- // of the two p and try again
+ // calculate the modulus
//
- p = p.max(q);
- continue;
- }
-
- /*
- * Require a minimum weight of the NAF representation, since low-weight composites may
- * be weak against a version of the number-field-sieve for factoring.
- *
- * See "The number field sieve for integers of low weight", Oliver Schirokauer.
- */
- if (WNafUtil.getNafWeight(n) < minWeight)
+ n = p.multiply(q);
+
+ if (n.bitLength() != strength)
+ {
+ //
+ // if we get here our primes aren't big enough, make the largest
+ // of the two p and try again
+ //
+ p = p.max(q);
+ continue;
+ }
+
+ /*
+ * Require a minimum weight of the NAF representation, since low-weight composites may
+ * be weak against a version of the number-field-sieve for factoring.
+ *
+ * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+ */
+ if (WNafUtil.getNafWeight(n) < minWeight)
+ {
+ p = chooseRandomPrime(pbitlength, e);
+ continue;
+ }
+
+ break;
+ }
+
+ if (p.compareTo(q) < 0)
{
- p = chooseRandomPrime(pBitlength, e);
- continue;
+ phi = p;
+ p = q;
+ q = phi;
}
- break;
- }
+ pSub1 = p.subtract(ONE);
+ qSub1 = q.subtract(ONE);
+ phi = pSub1.multiply(qSub1);
+ lcm = phi.divide(pSub1.gcd(qSub1));
- if (p.compareTo(q) < 0)
- {
- phi = p;
- p = q;
- q = phi;
- }
+ //
+ // calculate the private exponent
+ //
+ d = e.modInverse(lcm);
- pSub1 = p.subtract(ONE);
- qSub1 = q.subtract(ONE);
- phi = pSub1.multiply(qSub1);
+ // if d is less than or equal to dLowerBound, we need to start over
+ // also, for backward compatibility, if d is not the same as
+ // e.modInverse(phi), we need to start over
- //
- // calculate the private exponent
- //
- d = e.modInverse(phi);
+ if (d.bitLength() <= qbitlength || !d.equals(e.modInverse(phi)))
+ {
+ continue;
+ }
+ else
+ {
+ done = true;
+ }
- //
- // calculate the CRT factors
- //
- BigInteger dP, dQ, qInv;
+ //
+ // calculate the CRT factors
+ //
+ BigInteger dP, dQ, qInv;
- dP = d.remainder(pSub1);
- dQ = d.remainder(qSub1);
- qInv = q.modInverse(p);
+ dP = d.remainder(pSub1);
+ dQ = d.remainder(qSub1);
+ qInv = q.modInverse(p);
+
+ result = new AsymmetricCipherKeyPair(
+ new RSAKeyParameters(false, n, e),
+ new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
+ }
- return new AsymmetricCipherKeyPair(
- new RSAKeyParameters(false, n, e),
- new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
+ return result;
}
/**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
index 5388b40..64b076d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
@@ -4,6 +4,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.StreamBlockCipher;
/**
* A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
@@ -22,9 +23,8 @@ public class CTSBlockCipher
public CTSBlockCipher(
BlockCipher cipher)
{
- if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher) || (cipher instanceof SICBlockCipher))
+ if (cipher instanceof StreamBlockCipher)
{
- // TODO: This is broken - need to introduce marker interface to differentiate block cipher primitive from mode?
throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
index 024eb86..93f0fe9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
@@ -7,6 +7,7 @@ import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.modes.gcm.GCMExponentiator;
import org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
+import org.bouncycastle.crypto.modes.gcm.GCMUtil;
import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
import org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
import org.bouncycastle.crypto.params.AEADParameters;
@@ -366,7 +367,7 @@ public class GCMBlockCipher
// Find the difference between the AAD hashes
if (atLengthPre > 0)
{
- xor(S_at, S_atPre);
+ GCMUtil.xor(S_at, S_atPre);
}
// Number of cipher-text blocks produced
@@ -382,10 +383,10 @@ public class GCMBlockCipher
exp.exponentiateX(c, H_c);
// Carry the difference forward
- multiply(S_at, H_c);
+ GCMUtil.multiply(S_at, H_c);
// Adjust the current hash
- xor(S, S_at);
+ GCMUtil.xor(S, S_at);
}
// Final gHASH
@@ -398,7 +399,7 @@ public class GCMBlockCipher
// T = MSBt(GCTRk(J0,S))
byte[] tag = new byte[BLOCK_SIZE];
cipher.processBlock(J0, 0, tag, 0);
- xor(tag, S);
+ GCMUtil.xor(tag, S);
int resultLen = extra;
@@ -473,7 +474,7 @@ public class GCMBlockCipher
{
byte[] tmp = getNextCounterBlock();
- xor(tmp, block);
+ GCMUtil.xor(tmp, block);
System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE);
gHASHBlock(S, forEncryption ? tmp : block);
@@ -485,7 +486,7 @@ public class GCMBlockCipher
{
byte[] tmp = getNextCounterBlock();
- xor(tmp, buf, off, len);
+ GCMUtil.xor(tmp, buf, off, len);
System.arraycopy(tmp, 0, out, outOff, len);
gHASHPartial(S, forEncryption ? tmp : buf, 0, len);
@@ -504,13 +505,13 @@ public class GCMBlockCipher
private void gHASHBlock(byte[] Y, byte[] b)
{
- xor(Y, b);
+ GCMUtil.xor(Y, b);
multiplier.multiplyH(Y);
}
private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
{
- xor(Y, b, off, len);
+ GCMUtil.xor(Y, b, off, len);
multiplier.multiplyH(Y);
}
@@ -532,65 +533,4 @@ public class GCMBlockCipher
cipher.processBlock(counter, 0, tmp, 0);
return tmp;
}
-
- private static void multiply(byte[] block, byte[] val)
- {
- byte[] tmp = Arrays.clone(block);
- byte[] c = new byte[16];
-
- for (int i = 0; i < 16; ++i)
- {
- byte bits = val[i];
- for (int j = 7; j >= 0; --j)
- {
- if ((bits & (1 << j)) != 0)
- {
- xor(c, tmp);
- }
-
- boolean lsb = (tmp[15] & 1) != 0;
- shiftRight(tmp);
- if (lsb)
- {
- // R = new byte[]{ 0xe1, ... };
-// xor(v, R);
- tmp[0] ^= (byte)0xe1;
- }
- }
- }
-
- System.arraycopy(c, 0, block, 0, 16);
- }
-
- private static void shiftRight(byte[] block)
- {
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i] & 0xff;
- block[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
- }
- }
-
- private static void xor(byte[] block, byte[] val)
- {
- for (int i = 15; i >= 0; --i)
- {
- block[i] ^= val[i];
- }
- }
-
- private static void xor(byte[] block, byte[] val, int off, int len)
- {
- while (len-- > 0)
- {
- block[len] ^= val[off + len];
- }
- }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
index 5dd47ae..fbc8bf4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
@@ -106,6 +106,27 @@ public class SICBlockCipher
return rv;
}
+ private void incrementCounterPow2(int pow2Div8)
+ {
+ // increment counter by 1 << 8 * pow2Div8
+ for (int i = counter.length - (1 + pow2Div8); i >= 0 && ++counter[i] == 0; i--)
+ {
+ ; // do nothing - pre-increment and test for 0 in counter does the job.
+ }
+ }
+
+ private void incrementCounter(int offSet)
+ {
+ byte old = counter[counter.length - 1];
+
+ counter[counter.length - 1] += offSet;
+
+ if (old != 0 && counter[counter.length - 1] < old)
+ {
+ incrementCounterPow2(1);
+ }
+ }
+
private void incrementCounter()
{
// increment counter by 1.
@@ -115,6 +136,33 @@ public class SICBlockCipher
}
}
+ private void decrementCounterPow2(int pow2Div8)
+ {
+ if (counter[pow2Div8] == 0)
+ {
+ boolean nonZero = false;
+
+ for (int i = counter.length - (1 + pow2Div8); i > 0; i--)
+ {
+ if (counter[i] != 0)
+ {
+ nonZero = true;
+ }
+ }
+
+ if (!nonZero)
+ {
+ throw new IllegalStateException("attempt to reduce counter past zero.");
+ }
+ }
+
+ // decrement counter by 1.
+ for (int i = counter.length - (1 + pow2Div8); i >= 0 && --counter[i] == -1; i--)
+ {
+ ;
+ }
+ }
+
private void decrementCounter()
{
if (counter[0] == 0)
@@ -148,9 +196,27 @@ public class SICBlockCipher
{
long numBlocks = (n + byteCount) / blockSize;
- for (long i = 0; i != numBlocks; i++)
+ if (numBlocks > 255)
+ {
+ long gap = numBlocks;
+
+ for (int i = 5; i >= 1; i--)
+ {
+ long diff = 1L << (8 * i);
+
+ while (gap >= diff)
+ {
+ incrementCounterPow2(i);
+
+ gap -= diff;
+ }
+ }
+
+ incrementCounter((int)gap);
+ }
+ else
{
- incrementCounter();
+ incrementCounter((int)numBlocks);
}
byteCount = (int)((n + byteCount) - (blockSize * numBlocks));
@@ -159,9 +225,33 @@ public class SICBlockCipher
{
long numBlocks = (-n - byteCount) / blockSize;
- for (long i = 0; i != numBlocks; i++)
+ if (numBlocks > 255)
{
- decrementCounter();
+ long gap = numBlocks;
+
+ for (int i = 5; i >= 1; i--)
+ {
+ long diff = 1L << (8 * i);
+
+ while (gap > diff)
+ {
+ decrementCounterPow2(i);
+
+ gap -= diff;
+ }
+ }
+
+ for (long i = 0; i != gap; i++)
+ {
+ decrementCounter();
+ }
+ }
+ else
+ {
+ for (long i = 0; i != numBlocks; i++)
+ {
+ decrementCounter();
+ }
}
int gap = (int)(byteCount + n + (blockSize * numBlocks));
@@ -209,7 +299,7 @@ public class SICBlockCipher
for (int i = res.length - 1; i >= 1; i--)
{
- int v = (res[i] - IV[i]);
+ int v = (res[i] & 0xff) - (IV[i] & 0xff);
if (v < 0)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
index f5ed7e4..58f4078 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
@@ -1,13 +1,11 @@
package org.bouncycastle.crypto.modes.gcm;
-import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Pack;
-abstract class GCMUtil
+public abstract class GCMUtil
{
private static final int E1 = 0xe1000000;
- private static final byte E1B = (byte)0xe1;
- private static final long E1L = (E1 & 0xFFFFFFFFL) << 24;
+ private static final long E1L = (E1 & 0xFFFFFFFFL) << 32;
private static int[] generateLookup()
{
@@ -31,170 +29,151 @@ abstract class GCMUtil
private static final int[] LOOKUP = generateLookup();
- static byte[] oneAsBytes()
+ public static byte[] oneAsBytes()
{
byte[] tmp = new byte[16];
tmp[0] = (byte)0x80;
return tmp;
}
- static int[] oneAsInts()
+ public static int[] oneAsInts()
{
int[] tmp = new int[4];
tmp[0] = 1 << 31;
return tmp;
}
- static long[] oneAsLongs()
+ public static long[] oneAsLongs()
{
long[] tmp = new long[2];
tmp[0] = 1L << 63;
return tmp;
}
- static byte[] asBytes(int[] x)
+ public static byte[] asBytes(int[] x)
{
byte[] z = new byte[16];
Pack.intToBigEndian(x, z, 0);
return z;
}
- static void asBytes(int[] x, byte[] z)
+ public static void asBytes(int[] x, byte[] z)
{
Pack.intToBigEndian(x, z, 0);
}
- static byte[] asBytes(long[] x)
+ public static byte[] asBytes(long[] x)
{
byte[] z = new byte[16];
Pack.longToBigEndian(x, z, 0);
return z;
}
- static void asBytes(long[] x, byte[] z)
+ public static void asBytes(long[] x, byte[] z)
{
Pack.longToBigEndian(x, z, 0);
}
- static int[] asInts(byte[] x)
+ public static int[] asInts(byte[] x)
{
int[] z = new int[4];
Pack.bigEndianToInt(x, 0, z);
return z;
}
- static void asInts(byte[] x, int[] z)
+ public static void asInts(byte[] x, int[] z)
{
Pack.bigEndianToInt(x, 0, z);
}
- static long[] asLongs(byte[] x)
+ public static long[] asLongs(byte[] x)
{
long[] z = new long[2];
Pack.bigEndianToLong(x, 0, z);
return z;
}
- static void asLongs(byte[] x, long[] z)
+ public static void asLongs(byte[] x, long[] z)
{
Pack.bigEndianToLong(x, 0, z);
}
- static void multiply(byte[] x, byte[] y)
+ public static void multiply(byte[] x, byte[] y)
{
- byte[] r0 = Arrays.clone(x);
- byte[] r1 = new byte[16];
-
- for (int i = 0; i < 16; ++i)
- {
- byte bits = y[i];
- for (int j = 7; j >= 0; --j)
- {
- if ((bits & (1 << j)) != 0)
- {
- xor(r1, r0);
- }
-
- if (shiftRight(r0) != 0)
- {
- r0[0] ^= E1B;
- }
- }
- }
-
- System.arraycopy(r1, 0, x, 0, 16);
+ int[] t1 = GCMUtil.asInts(x);
+ int[] t2 = GCMUtil.asInts(y);
+ GCMUtil.multiply(t1, t2);
+ GCMUtil.asBytes(t1, x);
}
- static void multiply(int[] x, int[] y)
+ public static void multiply(int[] x, int[] y)
{
- int[] r0 = Arrays.clone(x);
- int[] r1 = new int[4];
-
+ int r00 = x[0], r01 = x[1], r02 = x[2], r03 = x[3];
+ int r10 = 0, r11 = 0, r12 = 0, r13 = 0;
+
for (int i = 0; i < 4; ++i)
{
int bits = y[i];
- for (int j = 31; j >= 0; --j)
+ for (int j = 0; j < 32; ++j)
{
- if ((bits & (1 << j)) != 0)
- {
- xor(r1, r0);
- }
-
- if (shiftRight(r0) != 0)
- {
- r0[0] ^= E1;
- }
+ int m1 = bits >> 31; bits <<= 1;
+ r10 ^= (r00 & m1);
+ r11 ^= (r01 & m1);
+ r12 ^= (r02 & m1);
+ r13 ^= (r03 & m1);
+
+ int m2 = (r03 << 31) >> 8;
+ r03 = (r03 >>> 1) | (r02 << 63);
+ r02 = (r02 >>> 1) | (r01 << 63);
+ r01 = (r01 >>> 1) | (r00 << 63);
+ r00 = (r00 >>> 1) ^ (m2 & E1);
}
}
- System.arraycopy(r1, 0, x, 0, 4);
+ x[0] = r10;
+ x[1] = r11;
+ x[2] = r12;
+ x[3] = r13;
}
- static void multiply(long[] x, long[] y)
+ public static void multiply(long[] x, long[] y)
{
- long[] r0 = new long[]{ x[0], x[1] };
- long[] r1 = new long[2];
+ long r00 = x[0], r01 = x[1], r10 = 0, r11 = 0;
for (int i = 0; i < 2; ++i)
{
long bits = y[i];
- for (int j = 63; j >= 0; --j)
+ for (int j = 0; j < 64; ++j)
{
- if ((bits & (1L << j)) != 0)
- {
- xor(r1, r0);
- }
+ long m1 = bits >> 63; bits <<= 1;
+ r10 ^= (r00 & m1);
+ r11 ^= (r01 & m1);
- if (shiftRight(r0) != 0)
- {
- r0[0] ^= E1L;
- }
+ long m2 = (r01 << 63) >> 8;
+ r01 = (r01 >>> 1) | (r00 << 63);
+ r00 = (r00 >>> 1) ^ (m2 & E1L);
}
}
- x[0] = r1[0];
- x[1] = r1[1];
+ x[0] = r10;
+ x[1] = r11;
}
// P is the value with only bit i=1 set
- static void multiplyP(int[] x)
+ public static void multiplyP(int[] x)
{
- if (shiftRight(x) != 0)
- {
- x[0] ^= E1;
- }
+ int m = shiftRight(x) >> 8;
+ x[0] ^= (m & E1);
}
- static void multiplyP(int[] x, int[] y)
+ public static void multiplyP(int[] x, int[] z)
{
- if (shiftRight(x, y) != 0)
- {
- y[0] ^= E1;
- }
+ int m = shiftRight(x, z) >> 8;
+ z[0] ^= (m & E1);
}
// P is the value with only bit i=1 set
- static void multiplyP8(int[] x)
+ public static void multiplyP8(int[] x)
{
// for (int i = 8; i != 0; --i)
// {
@@ -205,74 +184,12 @@ abstract class GCMUtil
x[0] ^= LOOKUP[c >>> 24];
}
- static void multiplyP8(int[] x, int[] y)
+ public static void multiplyP8(int[] x, int[] y)
{
int c = shiftRightN(x, 8, y);
y[0] ^= LOOKUP[c >>> 24];
}
- static byte shiftRight(byte[] x)
- {
-// int c = 0;
-// for (int i = 0; i < 16; ++i)
-// {
-// int b = x[i] & 0xff;
-// x[i] = (byte)((b >>> 1) | c);
-// c = (b & 1) << 7;
-// }
-// return (byte)c;
-
- int i = 0, c = 0;
- do
- {
- int b = x[i] & 0xff;
- x[i++] = (byte)((b >>> 1) | c);
- c = (b & 1) << 7;
- b = x[i] & 0xff;
- x[i++] = (byte)((b >>> 1) | c);
- c = (b & 1) << 7;
- b = x[i] & 0xff;
- x[i++] = (byte)((b >>> 1) | c);
- c = (b & 1) << 7;
- b = x[i] & 0xff;
- x[i++] = (byte)((b >>> 1) | c);
- c = (b & 1) << 7;
- }
- while (i < 16);
- return (byte)c;
- }
-
- static byte shiftRight(byte[] x, byte[] z)
- {
-// int c = 0;
-// for (int i = 0; i < 16; ++i)
-// {
-// int b = x[i] & 0xff;
-// z[i] = (byte) ((b >>> 1) | c);
-// c = (b & 1) << 7;
-// }
-// return (byte) c;
-
- int i = 0, c = 0;
- do
- {
- int b = x[i] & 0xff;
- z[i++] = (byte)((b >>> 1) | c);
- c = (b & 1) << 7;
- b = x[i] & 0xff;
- z[i++] = (byte)((b >>> 1) | c);
- c = (b & 1) << 7;
- b = x[i] & 0xff;
- z[i++] = (byte)((b >>> 1) | c);
- c = (b & 1) << 7;
- b = x[i] & 0xff;
- z[i++] = (byte)((b >>> 1) | c);
- c = (b & 1) << 7;
- }
- while (i < 16);
- return (byte)c;
- }
-
static int shiftRight(int[] x)
{
// int c = 0;
@@ -393,7 +310,7 @@ abstract class GCMUtil
return b << nInv;
}
- static void xor(byte[] x, byte[] y)
+ public static void xor(byte[] x, byte[] y)
{
int i = 0;
do
@@ -406,15 +323,15 @@ abstract class GCMUtil
while (i < 16);
}
- static void xor(byte[] x, byte[] y, int yOff, int yLen)
+ public static void xor(byte[] x, byte[] y, int yOff, int yLen)
{
- while (yLen-- > 0)
+ while (--yLen >= 0)
{
x[yLen] ^= y[yOff + yLen];
}
}
- static void xor(byte[] x, byte[] y, byte[] z)
+ public static void xor(byte[] x, byte[] y, byte[] z)
{
int i = 0;
do
@@ -427,7 +344,7 @@ abstract class GCMUtil
while (i < 16);
}
- static void xor(int[] x, int[] y)
+ public static void xor(int[] x, int[] y)
{
x[0] ^= y[0];
x[1] ^= y[1];
@@ -435,7 +352,7 @@ abstract class GCMUtil
x[3] ^= y[3];
}
- static void xor(int[] x, int[] y, int[] z)
+ public static void xor(int[] x, int[] y, int[] z)
{
z[0] = x[0] ^ y[0];
z[1] = x[1] ^ y[1];
@@ -443,13 +360,13 @@ abstract class GCMUtil
z[3] = x[3] ^ y[3];
}
- static void xor(long[] x, long[] y)
+ public static void xor(long[] x, long[] y)
{
x[0] ^= y[0];
x[1] ^= y[1];
}
- static void xor(long[] x, long[] y, long[] z)
+ public static void xor(long[] x, long[] y, long[] z)
{
z[0] = x[0] ^ y[0];
z[1] = x[1] ^ y[1];
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
index 93b149f..8b30398 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
@@ -57,18 +57,19 @@ public class PKCS7Padding
throws InvalidCipherTextException
{
int count = in[in.length - 1] & 0xff;
+ byte countAsbyte = (byte)count;
- if (count > in.length || count == 0)
+ // constant time version
+ boolean failed = (count > in.length | count == 0);
+
+ for (int i = 0; i < in.length; i++)
{
- throw new InvalidCipherTextException("pad block corrupted");
+ failed |= (in.length - i <= count) & (in[i] != countAsbyte);
}
-
- for (int i = 1; i <= count; i++)
+
+ if (failed)
{
- if (in[in.length - i] != count)
- {
- throw new InvalidCipherTextException("pad block corrupted");
- }
+ throw new InvalidCipherTextException("pad block corrupted");
}
return count;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
index b679287..fec6dfd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
@@ -84,8 +84,7 @@ public class DHParameters
{
if (l != 0)
{
- BigInteger bigL = BigInteger.valueOf(2L ^ (l - 1));
- if (bigL.compareTo(p) == 1)
+ if (l > p.bitLength())
{
throw new IllegalArgumentException("when l value specified, it must satisfy 2^(l-1) <= p");
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
index f3614f3..44f838b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
@@ -80,32 +80,28 @@ public class DSASigner
byte[] message)
{
DSAParameters params = key.getParameters();
- BigInteger m = calculateE(params.getQ(), message);
+ BigInteger q = params.getQ();
+ BigInteger m = calculateE(q, message);
+ BigInteger x = ((DSAPrivateKeyParameters)key).getX();
if (kCalculator.isDeterministic())
{
- kCalculator.init(params.getQ(), ((DSAPrivateKeyParameters)key).getX(), message);
+ kCalculator.init(q, x, message);
}
else
{
- kCalculator.init(params.getQ(), random);
+ kCalculator.init(q, random);
}
BigInteger k = kCalculator.nextK();
- BigInteger r = params.getG().modPow(k, params.getP()).mod(params.getQ());
+ BigInteger r = params.getG().modPow(k, params.getP()).mod(q);
- k = k.modInverse(params.getQ()).multiply(
- m.add(((DSAPrivateKeyParameters)key).getX().multiply(r)));
+ k = k.modInverse(q).multiply(m.add(x.multiply(r)));
- BigInteger s = k.mod(params.getQ());
+ BigInteger s = k.mod(q);
- BigInteger[] res = new BigInteger[2];
-
- res[0] = r;
- res[1] = s;
-
- return res;
+ return new BigInteger[]{ r, s };
}
/**
@@ -119,28 +115,30 @@ public class DSASigner
BigInteger s)
{
DSAParameters params = key.getParameters();
- BigInteger m = calculateE(params.getQ(), message);
+ BigInteger q = params.getQ();
+ BigInteger m = calculateE(q, message);
BigInteger zero = BigInteger.valueOf(0);
- if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
+ if (zero.compareTo(r) >= 0 || q.compareTo(r) <= 0)
{
return false;
}
- if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
+ if (zero.compareTo(s) >= 0 || q.compareTo(s) <= 0)
{
return false;
}
- BigInteger w = s.modInverse(params.getQ());
+ BigInteger w = s.modInverse(q);
- BigInteger u1 = m.multiply(w).mod(params.getQ());
- BigInteger u2 = r.multiply(w).mod(params.getQ());
+ BigInteger u1 = m.multiply(w).mod(q);
+ BigInteger u2 = r.multiply(w).mod(q);
- u1 = params.getG().modPow(u1, params.getP());
- u2 = ((DSAPublicKeyParameters)key).getY().modPow(u2, params.getP());
+ BigInteger p = params.getP();
+ u1 = params.getG().modPow(u1, p);
+ u2 = ((DSAPublicKeyParameters)key).getY().modPow(u2, p);
- BigInteger v = u1.multiply(u2).mod(params.getP()).mod(params.getQ());
+ BigInteger v = u1.multiply(u2).mod(p).mod(q);
return v.equals(r);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
index 2a32278..a8ef959 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
@@ -224,6 +224,8 @@ public class RSADigestSigner
}
else
{
+ Arrays.constantTimeAreEqual(expected, expected); // keep time "steady".
+
return false;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
index bbd8cda..6a69308 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
@@ -3,7 +3,7 @@ package org.bouncycastle.crypto.signers;
import java.math.BigInteger;
import java.security.SecureRandom;
-class RandomDSAKCalculator
+public class RandomDSAKCalculator
implements DSAKCalculator
{
private static final BigInteger ZERO = BigInteger.valueOf(0);