diff options
author | Sergio Giro <sgiro@google.com> | 2015-04-09 14:10:16 +0100 |
---|---|---|
committer | Sergio Giro <sgiro@google.com> | 2015-04-20 15:41:23 +0100 |
commit | 028ab6e01e3b911024b9b9243e9a0f4ac377c0fa (patch) | |
tree | 35d98bf60cbe7a6487bd0014728eb263e89004bb /bcprov/src/main/java/org/bouncycastle/crypto | |
parent | b44aff7a3b88138f0070630d467c7527cd90c2f3 (diff) | |
download | android_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')
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); |