diff options
author | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2013-11-01 16:04:09 +0000 |
---|---|---|
committer | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2013-11-01 16:04:09 +0000 |
commit | 7e37934b87aae3eddb9817663a20d9f9bb554bf2 (patch) | |
tree | 41518fd9391a5d52127ea2920ee0b578e2392f75 /bcprov/src/main/java/org/bouncycastle/crypto | |
parent | b9107e03cbb02e73f61e2105df4d5de9d2c6ab52 (diff) | |
parent | b1e4d28d756235ec33e45485994581f4590c37ff (diff) | |
download | android_external_bouncycastle-7e37934b87aae3eddb9817663a20d9f9bb554bf2.tar.gz android_external_bouncycastle-7e37934b87aae3eddb9817663a20d9f9bb554bf2.tar.bz2 android_external_bouncycastle-7e37934b87aae3eddb9817663a20d9f9bb554bf2.zip |
Merge tag 'android-4.4_r1' into cm-11.0cm-11.0-XNPH25R-bacon-d22b777afacm-11.0-XNPH22R-bacon-03d77315ea
Android 4.4 Release 1.0
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto')
29 files changed, 599 insertions, 211 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java index 2543b59..18cc648 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java @@ -130,7 +130,14 @@ public abstract class PBEParametersGenerator public static byte[] PKCS5PasswordToUTF8Bytes( char[] password) { - return Strings.toUTF8ByteArray(password); + if (password != null) + { + return Strings.toUTF8ByteArray(password); + } + else + { + return new byte[0]; + } } /** diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/AndroidDigestFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/AndroidDigestFactory.java index 3dc7059..b7bac28 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/AndroidDigestFactory.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/AndroidDigestFactory.java @@ -34,15 +34,18 @@ public final class AndroidDigestFactory { try { factoryImplementationClass = Class.forName(OpenSSLFactoryClassName); // Double check for NativeCrypto in case we are running on RI for testing - Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto"); + Class.forName("com.android.org.conscrypt.NativeCrypto"); } catch (ClassNotFoundException e1) { try { factoryImplementationClass = Class.forName(BouncyCastleFactoryClassName); } catch (ClassNotFoundException e2) { - throw new AssertionError("Failed to load AndroidDigestFactoryInterface " + AssertionError e = new AssertionError("Failed to load " + + "AndroidDigestFactoryInterface " + "implementation. Looked for " + OpenSSLFactoryClassName + " and " + BouncyCastleFactoryClassName); + e.initCause(e1); + throw e; } } if (!AndroidDigestFactoryInterface.class.isAssignableFrom(factoryImplementationClass)) { diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java index f2c9967..15f3ebb 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/GeneralDigest.java @@ -1,13 +1,14 @@ package org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.ExtendedDigest; +import org.bouncycastle.util.Memoable; /** * base implementation of MD4 family style digest as outlined in * "Handbook of Applied Cryptography", pages 344 - 347. */ public abstract class GeneralDigest - implements ExtendedDigest + implements ExtendedDigest, Memoable { private static final int BYTE_LENGTH = 64; private byte[] xBuf; @@ -32,6 +33,12 @@ public abstract class GeneralDigest protected GeneralDigest(GeneralDigest t) { xBuf = new byte[t.xBuf.length]; + + copyIn(t); + } + + protected void copyIn(GeneralDigest t) + { System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); xBufOff = t.xBufOff; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java index 22d457b..5c79e4e 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/LongDigest.java @@ -2,12 +2,13 @@ package org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.ExtendedDigest; import org.bouncycastle.crypto.util.Pack; +import org.bouncycastle.util.Memoable; /** * Base class for SHA-384 and SHA-512. */ public abstract class LongDigest - implements ExtendedDigest + implements ExtendedDigest, Memoable { private static final int BYTE_LENGTH = 128; @@ -41,6 +42,12 @@ public abstract class LongDigest protected LongDigest(LongDigest t) { xBuf = new byte[t.xBuf.length]; + + copyIn(t); + } + + protected void copyIn(LongDigest t) + { System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); xBufOff = t.xBufOff; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java index 05ed27a..ff9cedf 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java @@ -1,6 +1,8 @@ package org.bouncycastle.crypto.digests; +import org.bouncycastle.util.Memoable; + /** * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347. */ @@ -30,6 +32,13 @@ public class MD5Digest { super(t); + copyIn(t); + } + + private void copyIn(MD5Digest t) + { + super.copyIn(t); + H1 = t.H1; H2 = t.H2; H3 = t.H3; @@ -299,4 +308,16 @@ public class MD5Digest X[i] = 0; } } + + public Memoable copy() + { + return new MD5Digest(this); + } + + public void reset(Memoable other) + { + MD5Digest d = (MD5Digest)other; + + copyIn(d); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/OpenSSLDigest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/OpenSSLDigest.java index 3e7c0e7..07b4e50 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/OpenSSLDigest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/OpenSSLDigest.java @@ -16,7 +16,7 @@ package org.bouncycastle.crypto.digests; -import org.apache.harmony.xnet.provider.jsse.NativeCrypto; +import com.android.org.conscrypt.NativeCrypto; import org.bouncycastle.crypto.ExtendedDigest; /** diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java index 7f8d30a..21b1024 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java @@ -1,12 +1,13 @@ package org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.util.Pack; +import org.bouncycastle.util.Memoable; /** * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349. * * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5 - * is the "endienness" of the word processing! + * is the "endianness" of the word processing! */ public class SHA1Digest extends GeneralDigest @@ -34,6 +35,11 @@ public class SHA1Digest { super(t); + copyIn(t); + } + + private void copyIn(SHA1Digest t) + { H1 = t.H1; H2 = t.H2; H3 = t.H3; @@ -283,6 +289,19 @@ public class SHA1Digest X[i] = 0; } } + + public Memoable copy() + { + return new SHA1Digest(this); + } + + public void reset(Memoable other) + { + SHA1Digest d = (SHA1Digest)other; + + super.copyIn(d); + copyIn(d); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java index abd9c1b..a2ceda3 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java @@ -1,8 +1,8 @@ package org.bouncycastle.crypto.digests; -import org.bouncycastle.crypto.digests.GeneralDigest; import org.bouncycastle.crypto.util.Pack; +import org.bouncycastle.util.Memoable; /** @@ -42,6 +42,13 @@ public class SHA256Digest { super(t); + copyIn(t); + } + + private void copyIn(SHA256Digest t) + { + super.copyIn(t); + H1 = t.H1; H2 = t.H2; H3 = t.H3; @@ -291,5 +298,17 @@ public class SHA256Digest 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; + + public Memoable copy() + { + return new SHA256Digest(this); + } + + public void reset(Memoable other) + { + SHA256Digest d = (SHA256Digest)other; + + copyIn(d); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java index cdd979a..75d195d 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java @@ -1,6 +1,7 @@ package org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.util.Pack; +import org.bouncycastle.util.Memoable; /** @@ -17,7 +18,6 @@ import org.bouncycastle.crypto.util.Pack; public class SHA384Digest extends LongDigest { - private static final int DIGEST_LENGTH = 48; /** @@ -84,4 +84,16 @@ public class SHA384Digest H7 = 0xdb0c2e0d64f98fa7l; H8 = 0x47b5481dbefa4fa4l; } + + public Memoable copy() + { + return new SHA384Digest(this); + } + + public void reset(Memoable other) + { + SHA384Digest d = (SHA384Digest)other; + + super.copyIn(d); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java index 34a8e4e..7db63ad 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java @@ -1,6 +1,7 @@ package org.bouncycastle.crypto.digests; import org.bouncycastle.crypto.util.Pack; +import org.bouncycastle.util.Memoable; /** @@ -85,5 +86,17 @@ public class SHA512Digest H7 = 0x1f83d9abfb41bd6bL; H8 = 0x5be0cd19137e2179L; } + + public Memoable copy() + { + return new SHA512Digest(this); + } + + public void reset(Memoable other) + { + SHA512Digest d = (SHA512Digest)other; + + copyIn(d); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java index c4719cf..4dbfbff 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java @@ -1,5 +1,7 @@ package org.bouncycastle.crypto.encodings; +import java.security.SecureRandom; + import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; @@ -9,8 +11,6 @@ import org.bouncycastle.crypto.digests.AndroidDigestFactory; // END android-changed import org.bouncycastle.crypto.params.ParametersWithRandom; -import java.security.SecureRandom; - /** * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2. */ @@ -18,7 +18,6 @@ public class OAEPEncoding implements AsymmetricBlockCipher { private byte[] defHash; - private Digest hash; private Digest mgf1Hash; private AsymmetricBlockCipher engine; @@ -55,10 +54,11 @@ public class OAEPEncoding byte[] encodingParams) { this.engine = cipher; - this.hash = hash; this.mgf1Hash = mgf1Hash; this.defHash = new byte[hash.getDigestSize()]; + hash.reset(); + if (encodingParams != null) { hash.update(encodingParams, 0, encodingParams.length); @@ -256,15 +256,23 @@ public class OAEPEncoding // // check the hash of the encoding params. + // long check to try to avoid this been a source of a timing attack. // + boolean defHashWrong = false; + for (int i = 0; i != defHash.length; i++) { if (defHash[i] != block[defHash.length + i]) { - throw new InvalidCipherTextException("data hash wrong"); + defHashWrong = true; } } + if (defHashWrong) + { + throw new InvalidCipherTextException("data hash wrong"); + } + // // find the data block // @@ -322,9 +330,9 @@ public class OAEPEncoding byte[] C = new byte[4]; int counter = 0; - hash.reset(); + mgf1Hash.reset(); - do + while (counter < (length / hashBuf.length)) { ItoOSP(counter, C); @@ -333,8 +341,9 @@ public class OAEPEncoding mgf1Hash.doFinal(hashBuf, 0); System.arraycopy(hashBuf, 0, mask, counter * hashBuf.length, hashBuf.length); + + counter++; } - while (++counter < (length / hashBuf.length)); if ((counter * hashBuf.length) < length) { diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java index 1bc9aae..756197c 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java @@ -3,6 +3,7 @@ package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.KeyParameter; /** @@ -392,7 +393,7 @@ private static final int[] Tinv0 = if ((outOff + (32 / 2)) > out.length) { - throw new DataLengthException("output buffer too short"); + throw new OutputLengthException("output buffer too short"); } if (forEncryption) diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java index 7e91973..ff4b2f8 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java @@ -3,9 +3,7 @@ package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; -// BEGIN android-added import org.bouncycastle.crypto.OutputLengthException; -// END android-added import org.bouncycastle.crypto.params.KeyParameter; /** @@ -726,9 +724,7 @@ public class AESFastEngine if ((outOff + (32 / 2)) > out.length) { - // BEGIN android-changed throw new OutputLengthException("output buffer too short"); - // END android-changed } if (forEncryption) diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/BlowfishEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/BlowfishEngine.java index 6ee1c49..cfe7f1f 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/BlowfishEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/BlowfishEngine.java @@ -3,6 +3,7 @@ package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.KeyParameter; /** @@ -363,7 +364,7 @@ implements BlockCipher if ((outOff + BLOCK_SIZE) > out.length) { - throw new DataLengthException("output buffer too short"); + throw new OutputLengthException("output buffer too short"); } if (encrypting) diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java index b04911c..9b1e404 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESEngine.java @@ -3,6 +3,7 @@ package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.KeyParameter; /** @@ -78,7 +79,7 @@ public class DESEngine if ((outOff + BLOCK_SIZE) > out.length) { - throw new DataLengthException("output buffer too short"); + throw new OutputLengthException("output buffer too short"); } desFunc(workingKey, in, inOff, out, outOff); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java index c908218..513eccd 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java @@ -2,9 +2,7 @@ package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; -// BEGIN android-added import org.bouncycastle.crypto.OutputLengthException; -// END android-added import org.bouncycastle.crypto.params.KeyParameter; /** @@ -102,9 +100,7 @@ public class DESedeEngine if ((outOff + BLOCK_SIZE) > out.length) { - // BEGIN android-changed throw new OutputLengthException("output buffer too short"); - // END android-changed } byte[] temp = new byte[BLOCK_SIZE]; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC2Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC2Engine.java index 62240ea..02cb881 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC2Engine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC2Engine.java @@ -3,6 +3,7 @@ package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.RC2Parameters; @@ -174,7 +175,7 @@ public class RC2Engine if ((outOff + BLOCK_SIZE) > out.length) { - throw new DataLengthException("output buffer too short"); + throw new OutputLengthException("output buffer too short"); } if (encrypting) diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java index e7a9cdd..4de7ea6 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RC4Engine.java @@ -2,6 +2,7 @@ package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.StreamCipher; import org.bouncycastle.crypto.params.KeyParameter; @@ -81,7 +82,7 @@ public class RC4Engine implements StreamCipher if ((outOff + len) > out.length) { - throw new DataLengthException("output buffer too short"); + throw new OutputLengthException("output buffer too short"); } for (int i = 0; i < len ; i++) diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java index bf43ff2..31ac087 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java @@ -3,6 +3,7 @@ package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.KeyParameter; /** @@ -303,7 +304,7 @@ public final class TwofishEngine if ((outOff + BLOCK_SIZE) > out.length) { - throw new DataLengthException("output buffer too short"); + throw new OutputLengthException("output buffer too short"); } if (encrypting) diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java index 98dd0f7..50baa4d 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java @@ -1,23 +1,25 @@ package org.bouncycastle.crypto.generators; +import java.math.BigInteger; +import java.security.SecureRandom; + import org.bouncycastle.crypto.Digest; // BEGIN android-changed import org.bouncycastle.crypto.digests.AndroidDigestFactory; // END android-changed +import org.bouncycastle.crypto.params.DSAParameterGenerationParameters; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.DSAValidationParameters; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.BigIntegers; +import org.bouncycastle.util.encoders.Hex; -import java.math.BigInteger; -import java.security.SecureRandom; - -// TODO Update javadoc to mention FIPS 186-3 when done /** - * generate suitable parameters for DSA, in line with FIPS 186-2. + * Generate suitable parameters for DSA, in line with FIPS 186-2, or FIPS 186-3. */ public class DSAParametersGenerator { + private Digest digest; private int L, N; private int certainty; private SecureRandom random; @@ -26,6 +28,21 @@ public class DSAParametersGenerator private static final BigInteger ONE = BigInteger.valueOf(1); private static final BigInteger TWO = BigInteger.valueOf(2); + private boolean use186_3; + private int usageIndex; + + public DSAParametersGenerator() + { + // BEGIN android-changed + this(AndroidDigestFactory.getSHA1()); + // END android-changed + } + + public DSAParametersGenerator(Digest digest) + { + this.digest = digest; + } + /** * initialise the key generator. * @@ -38,23 +55,53 @@ public class DSAParametersGenerator int certainty, SecureRandom random) { - init(size, getDefaultN(size), certainty, random); + this.use186_3 = false; + this.L = size; + this.N = getDefaultN(size); + this.certainty = certainty; + this.random = random; } - // TODO Make public to enable support for DSA keys > 1024 bits - private void init( - int L, - int N, - int certainty, - SecureRandom random) + /** + * Initialise the key generator for DSA 2. + * <p> + * Use this init method if you need to generate parameters for DSA 2 keys. + * </p> + * + * @param params DSA 2 key generation parameters. + */ + public void init( + DSAParameterGenerationParameters params) { - // TODO Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2) // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1? + this.use186_3 = true; + this.L = params.getL(); + this.N = params.getN(); + this.certainty = params.getCertainty(); + this.random = params.getRandom(); + this.usageIndex = params.getUsageIndex(); + + if ((L < 1024 || L > 3072) || L % 1024 != 0) + { + throw new IllegalArgumentException("L values must be between 1024 and 3072 and a multiple of 1024"); + } + else if (L == 1024 && N != 160) + { + throw new IllegalArgumentException("N must be 160 for L = 1024"); + } + else if (L == 2048 && (N != 224 && N != 256)) + { + throw new IllegalArgumentException("N must be 224 or 256 for L = 2048"); + } + else if (L == 3072 && N != 256) + { + throw new IllegalArgumentException("N must be 256 for L = 3072"); + } - this.L = L; - this.N = N; - this.certainty = certainty; - this.random = random; + if (digest.getDigestSize() * 8 < N) + { + throw new IllegalStateException("Digest output size too small for value of N"); + } } /** @@ -65,7 +112,7 @@ public class DSAParametersGenerator */ public DSAParameters generateParameters() { - return L > 1024 + return (use186_3) ? generateParameters_FIPS186_3() : generateParameters_FIPS186_2(); } @@ -76,20 +123,24 @@ public class DSAParametersGenerator byte[] part1 = new byte[20]; byte[] part2 = new byte[20]; byte[] u = new byte[20]; - // BEGIN android-changed - Digest sha1 = AndroidDigestFactory.getSHA1(); - // END android-changed int n = (L - 1) / 160; byte[] w = new byte[L / 8]; + // BEGIN android-changed + if (!(digest.getAlgorithmName().equals("SHA-1"))) + // END android-changed + { + throw new IllegalStateException("can only use SHA-1 for generating FIPS 186-2 parameters"); + } + for (;;) { random.nextBytes(seed); - hash(sha1, seed, part1); + hash(digest, seed, part1); System.arraycopy(seed, 0, part2, 0, seed.length); inc(part2); - hash(sha1, part2, part2); + hash(digest, part2, part2); for (int i = 0; i != u.length; i++) { @@ -114,12 +165,12 @@ public class DSAParametersGenerator for (int k = 0; k < n; k++) { inc(offset); - hash(sha1, offset, part1); + hash(digest, offset, part1); System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length); } inc(offset); - hash(sha1, offset, part1); + hash(digest, offset, part1); System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length); w[0] |= (byte)0x80; @@ -169,9 +220,7 @@ public class DSAParametersGenerator { // A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function // FIXME This should be configurable (digest size in bits must be >= N) - // BEGIN android-changed - Digest d = AndroidDigestFactory.getSHA256(); - // END android-changed + Digest d = digest; int outlen = d.getDigestSize() * 8; // 1. Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2). If @@ -197,6 +246,7 @@ public class DSAParametersGenerator // 6. U = Hash (domain_parameter_seed) mod 2^(Nā1). hash(d, seed, output); + BigInteger U = new BigInteger(1, output).mod(ONE.shiftLeft(N - 1)); // 7. q = 2^(Nā1) + U + 1 ā ( U mod 2). @@ -258,16 +308,17 @@ public class DSAParametersGenerator { // 11.8 If p is determined to be prime, then return VALID and the values of p, q and // (optionally) the values of domain_parameter_seed and counter. - // TODO Make configurable (8-bit unsigned)? -// int index = 1; -// BigInteger g = calculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, index); -// if (g != null) -// { -// // TODO Should 'index' be a part of the validation parameters? -// return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter)); -// } + if (usageIndex >= 0) + { + BigInteger g = calculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, usageIndex); + if (g != null) + { + return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter, usageIndex)); + } + } BigInteger g = calculateGenerator_FIPS186_3_Unverifiable(p, q, random); + return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter)); } @@ -286,34 +337,34 @@ public class DSAParametersGenerator return calculateGenerator_FIPS186_2(p, q, r); } -// private static BigInteger calculateGenerator_FIPS186_3_Verifiable(Digest d, BigInteger p, BigInteger q, -// byte[] seed, int index) -// { -//// A.2.3 Verifiable Canonical Generation of the Generator g -// BigInteger e = p.subtract(ONE).divide(q); -// byte[] ggen = Hex.decode("6767656E"); -// -// // 7. U = domain_parameter_seed || "ggen" || index || count. -// byte[] U = new byte[seed.length + ggen.length + 1 + 2]; -// System.arraycopy(seed, 0, U, 0, seed.length); -// System.arraycopy(ggen, 0, U, seed.length, ggen.length); -// U[U.length - 3] = (byte)index; -// -// byte[] w = new byte[d.getDigestSize()]; -// for (int count = 1; count < (1 << 16); ++count) -// { -// inc(U); -// hash(d, U, w); -// BigInteger W = new BigInteger(1, w); -// BigInteger g = W.modPow(e, p); -// if (g.compareTo(TWO) >= 0) -// { -// return g; -// } -// } -// -// return null; -// } + private static BigInteger calculateGenerator_FIPS186_3_Verifiable(Digest d, BigInteger p, BigInteger q, + byte[] seed, int index) + { +// A.2.3 Verifiable Canonical Generation of the Generator g + BigInteger e = p.subtract(ONE).divide(q); + byte[] ggen = Hex.decode("6767656E"); + + // 7. U = domain_parameter_seed || "ggen" || index || count. + byte[] U = new byte[seed.length + ggen.length + 1 + 2]; + System.arraycopy(seed, 0, U, 0, seed.length); + System.arraycopy(ggen, 0, U, seed.length, ggen.length); + U[U.length - 3] = (byte)index; + + byte[] w = new byte[d.getDigestSize()]; + for (int count = 1; count < (1 << 16); ++count) + { + inc(U); + hash(d, U, w); + BigInteger W = new BigInteger(1, w); + BigInteger g = W.modPow(e, p); + if (g.compareTo(TWO) >= 0) + { + return g; + } + } + + return null; + } private static void hash(Digest d, byte[] input, byte[] output) { diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java index 8fb1cc8..d9b82c3 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java @@ -125,11 +125,10 @@ public class PKCS12ParametersGenerator byte[] B = new byte[v]; int c = (n + u - 1) / u; + byte[] A = new byte[u]; for (int i = 1; i <= c; i++) { - byte[] A = new byte[u]; - digest.update(D, 0, D.length); digest.update(I, 0, I.length); digest.doFinal(A, 0); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java index a6d87b9..316de64 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java @@ -23,6 +23,7 @@ public class PKCS5S2ParametersGenerator extends PBEParametersGenerator { private Mac hMac; + private byte[] state; /** * construct a PKCS5 Scheme 2 Parameters generator. @@ -30,27 +31,27 @@ public class PKCS5S2ParametersGenerator public PKCS5S2ParametersGenerator() { // BEGIN android-changed - this(AndroidDigestFactory.getSHA1()); + this(AndroidDigestFactory.getSHA1()); // END android-changed } public PKCS5S2ParametersGenerator(Digest digest) { hMac = new HMac(digest); + state = new byte[hMac.getMacSize()]; } private void F( - byte[] P, byte[] S, int c, byte[] iBuf, byte[] out, int outOff) { - byte[] state = new byte[hMac.getMacSize()]; - CipherParameters param = new KeyParameter(P); - - hMac.init(param); + if (c == 0) + { + throw new IllegalArgumentException("iteration count must be at least 1."); + } if (S != null) { @@ -58,19 +59,12 @@ public class PKCS5S2ParametersGenerator } hMac.update(iBuf, 0, iBuf.length); - hMac.doFinal(state, 0); System.arraycopy(state, 0, out, outOff, state.length); - - if (c == 0) - { - throw new IllegalArgumentException("iteration count must be at least 1."); - } for (int count = 1; count < c; count++) { - hMac.init(param); hMac.update(state, 0, state.length); hMac.doFinal(state, 0); @@ -81,32 +75,33 @@ public class PKCS5S2ParametersGenerator } } - private void intToOctet( - byte[] buf, - int i) - { - buf[0] = (byte)(i >>> 24); - buf[1] = (byte)(i >>> 16); - buf[2] = (byte)(i >>> 8); - buf[3] = (byte)i; - } - private byte[] generateDerivedKey( int dkLen) { int hLen = hMac.getMacSize(); int l = (dkLen + hLen - 1) / hLen; byte[] iBuf = new byte[4]; - byte[] out = new byte[l * hLen]; + byte[] outBytes = new byte[l * hLen]; + int outPos = 0; + + CipherParameters param = new KeyParameter(password); + + hMac.init(param); for (int i = 1; i <= l; i++) { - intToOctet(iBuf, i); + // Increment the value in 'iBuf' + int pos = 3; + while (++iBuf[pos] == 0) + { + --pos; + } - F(password, salt, iterationCount, iBuf, out, (i - 1) * hLen); + F(salt, iterationCount, iBuf, outBytes, outPos); + outPos += hLen; } - return out; + return outBytes; } /** diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java index f5b931d..c70a981 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java @@ -8,6 +8,7 @@ import org.bouncycastle.crypto.ExtendedDigest; import org.bouncycastle.crypto.Mac; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.util.Integers; +import org.bouncycastle.util.Memoable; /** * HMAC implementation based on RFC2104 @@ -23,9 +24,11 @@ public class HMac private Digest digest; private int digestSize; private int blockLength; - + private Memoable ipadState; + private Memoable opadState; + private byte[] inputPad; - private byte[] outputPad; + private byte[] outputBuf; private static Hashtable blockLengths; @@ -95,14 +98,12 @@ public class HMac int byteLength) { this.digest = digest; - digestSize = digest.getDigestSize(); - + this.digestSize = digest.getDigestSize(); this.blockLength = byteLength; - - inputPad = new byte[blockLength]; - outputPad = new byte[blockLength]; + this.inputPad = new byte[blockLength]; + this.outputBuf = new byte[blockLength + digestSize]; } - + public String getAlgorithmName() { return digest.getAlgorithmName() + "/HMAC"; @@ -119,39 +120,43 @@ public class HMac digest.reset(); byte[] key = ((KeyParameter)params).getKey(); + int keyLength = key.length; - if (key.length > blockLength) + if (keyLength > blockLength) { - digest.update(key, 0, key.length); + digest.update(key, 0, keyLength); digest.doFinal(inputPad, 0); - for (int i = digestSize; i < inputPad.length; i++) - { - inputPad[i] = 0; - } + + keyLength = digestSize; } else { - System.arraycopy(key, 0, inputPad, 0, key.length); - for (int i = key.length; i < inputPad.length; i++) - { - inputPad[i] = 0; - } + System.arraycopy(key, 0, inputPad, 0, keyLength); } - outputPad = new byte[inputPad.length]; - System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length); - - for (int i = 0; i < inputPad.length; i++) + for (int i = keyLength; i < inputPad.length; i++) { - inputPad[i] ^= IPAD; + inputPad[i] = 0; } - for (int i = 0; i < outputPad.length; i++) + System.arraycopy(inputPad, 0, outputBuf, 0, blockLength); + + xorPad(inputPad, blockLength, IPAD); + xorPad(outputBuf, blockLength, OPAD); + + if (digest instanceof Memoable) { - outputPad[i] ^= OPAD; + opadState = ((Memoable)digest).copy(); + + ((Digest)opadState).update(outputBuf, 0, blockLength); } digest.update(inputPad, 0, inputPad.length); + + if (digest instanceof Memoable) + { + ipadState = ((Memoable)digest).copy(); + } } public int getMacSize() @@ -177,15 +182,33 @@ public class HMac byte[] out, int outOff) { - byte[] tmp = new byte[digestSize]; - digest.doFinal(tmp, 0); + digest.doFinal(outputBuf, blockLength); - digest.update(outputPad, 0, outputPad.length); - digest.update(tmp, 0, tmp.length); + if (opadState != null) + { + ((Memoable)digest).reset(opadState); + digest.update(outputBuf, blockLength, digest.getDigestSize()); + } + else + { + digest.update(outputBuf, 0, outputBuf.length); + } - int len = digest.doFinal(out, outOff); + int len = digest.doFinal(out, outOff); - reset(); + for (int i = blockLength; i < outputBuf.length; i++) + { + outputBuf[i] = 0; + } + + if (ipadState != null) + { + ((Memoable)digest).reset(ipadState); + } + else + { + digest.update(inputPad, 0, inputPad.length); + } return len; } @@ -205,4 +228,12 @@ public class HMac */ digest.update(inputPad, 0, inputPad.length); } + + private static void xorPad(byte[] pad, int len, byte n) + { + for (int i = 0; i < len; ++i) + { + pad[i] ^= n; + } + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java index 18a3425..9a6e2e0 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java @@ -87,6 +87,11 @@ public class CCMBlockCipher { throw new IllegalArgumentException("invalid parameters passed to CCM"); } + + if (nonce == null || nonce.length < 7 || nonce.length > 13) + { + throw new IllegalArgumentException("nonce must have length from 7 to 13 octets"); + } } public String getAlgorithmName() @@ -183,22 +188,31 @@ public class CCMBlockCipher throw new IllegalStateException("CCM cipher unitialized."); } - BlockCipher ctrCipher = new SICBlockCipher(cipher); - byte[] iv = new byte[blockSize]; - byte[] out; - - iv[0] = (byte)(((15 - nonce.length) - 1) & 0x7); + int n = nonce.length; + int q = 15 - n; + if (q < 4) + { + int limitLen = 1 << (8 * q); + if (inLen >= limitLen) + { + throw new IllegalStateException("CCM packet too large for choice of q."); + } + } + byte[] iv = new byte[blockSize]; + iv[0] = (byte)((q - 1) & 0x7); System.arraycopy(nonce, 0, iv, 1, nonce.length); + BlockCipher ctrCipher = new SICBlockCipher(cipher); ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv)); + int index = inOff; + int outOff = 0; + byte[] output; + if (forEncryption) { - int index = inOff; - int outOff = 0; - - out = new byte[inLen + macSize]; + output = new byte[inLen + macSize]; calculateMac(in, inOff, inLen, macBlock); @@ -206,7 +220,7 @@ public class CCMBlockCipher while (index < inLen - blockSize) // S1... { - ctrCipher.processBlock(in, index, out, outOff); + ctrCipher.processBlock(in, index, output, outOff); outOff += blockSize; index += blockSize; } @@ -217,18 +231,15 @@ public class CCMBlockCipher ctrCipher.processBlock(block, 0, block, 0); - System.arraycopy(block, 0, out, outOff, inLen - index); + System.arraycopy(block, 0, output, outOff, inLen - index); outOff += inLen - index; - System.arraycopy(macBlock, 0, out, outOff, out.length - outOff); + System.arraycopy(macBlock, 0, output, outOff, output.length - outOff); } else { - int index = inOff; - int outOff = 0; - - out = new byte[inLen - macSize]; + output = new byte[inLen - macSize]; System.arraycopy(in, inOff + inLen - macSize, macBlock, 0, macSize); @@ -239,24 +250,24 @@ public class CCMBlockCipher macBlock[i] = 0; } - while (outOff < out.length - blockSize) + while (outOff < output.length - blockSize) { - ctrCipher.processBlock(in, index, out, outOff); + ctrCipher.processBlock(in, index, output, outOff); outOff += blockSize; index += blockSize; } byte[] block = new byte[blockSize]; - System.arraycopy(in, index, block, 0, out.length - outOff); + System.arraycopy(in, index, block, 0, output.length - outOff); ctrCipher.processBlock(block, 0, block, 0); - System.arraycopy(block, 0, out, outOff, out.length - outOff); + System.arraycopy(block, 0, output, outOff, output.length - outOff); byte[] calculatedMacBlock = new byte[blockSize]; - calculateMac(out, 0, out.length, calculatedMacBlock); + calculateMac(output, 0, output.length, calculatedMacBlock); if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock)) { @@ -264,7 +275,7 @@ public class CCMBlockCipher } } - return out; + return output; } private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock) @@ -340,13 +351,13 @@ public class CCMBlockCipher extra = (extra + textLength) % 16; if (extra != 0) { - for (int i = 0; i != 16 - extra; i++) + for (int i = extra; i != 16; i++) { cMac.update((byte)0x00); } } } - + // // add the text // diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java new file mode 100644 index 0000000..ba841b8 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java @@ -0,0 +1,80 @@ +package org.bouncycastle.crypto.params; + +import java.security.SecureRandom; + +public class DSAParameterGenerationParameters +{ + public static final int DIGITAL_SIGNATURE_USAGE = 1; + public static final int KEY_ESTABLISHMENT_USAGE = 2; + + private final int l; + private final int n; + private final int usageIndex; + private final int certainty; + private final SecureRandom random; + + /** + * Construct without a usage index, this will do a random construction of G. + * + * @param L desired length of prime P in bits (the effective key size). + * @param N desired length of prime Q in bits. + * @param certainty certainty level for prime number generation. + * @param random the source of randomness to use. + */ + public DSAParameterGenerationParameters( + int L, + int N, + int certainty, + SecureRandom random) + { + this(L, N, certainty, random, -1); + } + + /** + * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G. + * + * @param L desired length of prime P in bits (the effective key size). + * @param N desired length of prime Q in bits. + * @param certainty certainty level for prime number generation. + * @param random the source of randomness to use. + * @param usageIndex a valid usage index. + */ + public DSAParameterGenerationParameters( + int L, + int N, + int certainty, + SecureRandom random, + int usageIndex) + { + this.l = L; + this.n = N; + this.certainty = certainty; + this.usageIndex = usageIndex; + this.random = random; + } + + public int getL() + { + return l; + } + + public int getN() + { + return n; + } + + public int getCertainty() + { + return certainty; + } + + public SecureRandom getRandom() + { + return random; + } + + public int getUsageIndex() + { + return usageIndex; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java index 1cc4b93..07d93d0 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java @@ -4,6 +4,7 @@ import org.bouncycastle.util.Arrays; public class DSAValidationParameters { + private int usageIndex; private byte[] seed; private int counter; @@ -11,8 +12,17 @@ public class DSAValidationParameters byte[] seed, int counter) { + this(seed, counter, -1); + } + + public DSAValidationParameters( + byte[] seed, + int counter, + int usageIndex) + { this.seed = seed; this.counter = counter; + this.usageIndex = usageIndex; } public int getCounter() @@ -25,6 +35,11 @@ public class DSAValidationParameters return seed; } + public int getUsageIndex() + { + return usageIndex; + } + public int hashCode() { return counter ^ Arrays.hashCode(seed); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java index 95a3ec9..05a1327 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java @@ -5,26 +5,23 @@ import java.math.BigInteger; import org.bouncycastle.math.ec.ECConstants; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.util.Arrays; public class ECDomainParameters implements ECConstants { - ECCurve curve; - byte[] seed; - ECPoint G; - BigInteger n; - BigInteger h; + private ECCurve curve; + private byte[] seed; + private ECPoint G; + private BigInteger n; + private BigInteger h; public ECDomainParameters( ECCurve curve, ECPoint G, BigInteger n) { - this.curve = curve; - this.G = G; - this.n = n; - this.h = ONE; - this.seed = null; + this(curve, G, n, ONE, null); } public ECDomainParameters( @@ -33,11 +30,7 @@ public class ECDomainParameters BigInteger n, BigInteger h) { - this.curve = curve; - this.G = G; - this.n = n; - this.h = h; - this.seed = null; + this(curve, G, n, h, null); } public ECDomainParameters( @@ -76,6 +69,6 @@ public class ECDomainParameters public byte[] getSeed() { - return seed; + return Arrays.clone(seed); } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java index dac6efe..a80c574 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java @@ -137,6 +137,12 @@ public class ECDSASigner ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2); + // components must be bogus. + if (point.isInfinity()) + { + return false; + } + BigInteger v = point.getX().toBigInteger().mod(n); return v.equals(r); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java index 857b765..f0da0bf 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/Pack.java @@ -20,6 +20,13 @@ public abstract class Pack } } + public static byte[] intToBigEndian(int n) + { + byte[] bs = new byte[4]; + intToBigEndian(n, bs, 0); + return bs; + } + public static void intToBigEndian(int n, byte[] bs, int off) { bs[ off] = (byte)(n >>> 24); @@ -28,6 +35,13 @@ public abstract class Pack bs[++off] = (byte)(n ); } + public static byte[] intToBigEndian(int[] ns) + { + byte[] bs = new byte[4 * ns.length]; + intToBigEndian(ns, bs, 0); + return bs; + } + public static void intToBigEndian(int[] ns, byte[] bs, int off) { for (int i = 0; i < ns.length; ++i) @@ -44,12 +58,44 @@ public abstract class Pack return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL); } + public static void bigEndianToLong(byte[] bs, int off, long[] ns) + { + for (int i = 0; i < ns.length; ++i) + { + ns[i] = bigEndianToLong(bs, off); + off += 8; + } + } + + public static byte[] longToBigEndian(long n) + { + byte[] bs = new byte[8]; + longToBigEndian(n, bs, 0); + return bs; + } + public static void longToBigEndian(long n, byte[] bs, int off) { intToBigEndian((int)(n >>> 32), bs, off); intToBigEndian((int)(n & 0xffffffffL), bs, off + 4); } + public static byte[] longToBigEndian(long[] ns) + { + byte[] bs = new byte[8 * ns.length]; + longToBigEndian(ns, bs, 0); + return bs; + } + + public static void longToBigEndian(long[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.length; ++i) + { + longToBigEndian(ns[i], bs, off); + off += 8; + } + } + public static int littleEndianToInt(byte[] bs, int off) { int n = bs[ off] & 0xff; @@ -60,13 +106,20 @@ public abstract class Pack } public static void littleEndianToInt(byte[] bs, int off, int[] ns) - { - for (int i = 0; i < ns.length; ++i) - { - ns[i] = littleEndianToInt(bs, off); - off += 4; - } - } + { + for (int i = 0; i < ns.length; ++i) + { + ns[i] = littleEndianToInt(bs, off); + off += 4; + } + } + + public static byte[] intToLittleEndian(int n) + { + byte[] bs = new byte[4]; + intToLittleEndian(n, bs, 0); + return bs; + } public static void intToLittleEndian(int n, byte[] bs, int off) { @@ -76,14 +129,21 @@ public abstract class Pack bs[++off] = (byte)(n >>> 24); } - public static void intToLittleEndian(int[] ns, byte[] bs, int off) - { - for (int i = 0; i < ns.length; ++i) - { - intToLittleEndian(ns[i], bs, off); - off += 4; - } - } + public static byte[] intToLittleEndian(int[] ns) + { + byte[] bs = new byte[4 * ns.length]; + intToLittleEndian(ns, bs, 0); + return bs; + } + + public static void intToLittleEndian(int[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.length; ++i) + { + intToLittleEndian(ns[i], bs, off); + off += 4; + } + } public static long littleEndianToLong(byte[] bs, int off) { @@ -92,9 +152,41 @@ public abstract class Pack return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL); } + public static void littleEndianToLong(byte[] bs, int off, long[] ns) + { + for (int i = 0; i < ns.length; ++i) + { + ns[i] = littleEndianToLong(bs, off); + off += 8; + } + } + + public static byte[] longToLittleEndian(long n) + { + byte[] bs = new byte[8]; + longToLittleEndian(n, bs, 0); + return bs; + } + public static void longToLittleEndian(long n, byte[] bs, int off) { intToLittleEndian((int)(n & 0xffffffffL), bs, off); intToLittleEndian((int)(n >>> 32), bs, off + 4); } + + public static byte[] longToLittleEndian(long[] ns) + { + byte[] bs = new byte[8 * ns.length]; + longToLittleEndian(ns, bs, 0); + return bs; + } + + public static void longToLittleEndian(long[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.length; ++i) + { + longToLittleEndian(ns[i], bs, off); + off += 8; + } + } } |