diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2016-01-17 12:32:24 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2016-01-17 12:32:24 +0700 |
commit | 4819cab88fdd657bd64c672ff62e255a5cc1fe3e (patch) | |
tree | eba6bc580707be8a5b8d969b43cbf83949dcfb34 | |
parent | Remove expired draft-josefsson-salsa20-tls stuff (diff) | |
download | BouncyCastle.NET-ed25519-4819cab88fdd657bd64c672ff62e255a5cc1fe3e.tar.xz |
Fix re-init bug in HC128/256 engines
- add StreamCipherResetTest from Java API
-rw-r--r-- | crypto/crypto.csproj | 5 | ||||
-rw-r--r-- | crypto/src/crypto/engines/HC128Engine.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/engines/HC256Engine.cs | 2 | ||||
-rw-r--r-- | crypto/test/UnitTests.csproj | 1 | ||||
-rw-r--r-- | crypto/test/src/crypto/test/RegressionTest.cs | 1 | ||||
-rw-r--r-- | crypto/test/src/crypto/test/StreamCipherResetTest.cs | 134 |
6 files changed, 144 insertions, 3 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 73afed47e..392ff5813 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -11760,6 +11760,11 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\test\StreamCipherResetTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\test\StreamCipherVectorTest.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/crypto/engines/HC128Engine.cs b/crypto/src/crypto/engines/HC128Engine.cs index 7bd1a48ed..b83eb7083 100644 --- a/crypto/src/crypto/engines/HC128Engine.cs +++ b/crypto/src/crypto/engines/HC128Engine.cs @@ -107,7 +107,8 @@ namespace Org.BouncyCastle.Crypto.Engines if (key.Length != 16) throw new ArgumentException("The key must be 128 bits long"); - cnt = 0; + idx = 0; + cnt = 0; uint[] w = new uint[1280]; @@ -223,7 +224,6 @@ namespace Org.BouncyCastle.Crypto.Engines public virtual void Reset() { - idx = 0; Init(); } diff --git a/crypto/src/crypto/engines/HC256Engine.cs b/crypto/src/crypto/engines/HC256Engine.cs index b72258a19..d8d83a634 100644 --- a/crypto/src/crypto/engines/HC256Engine.cs +++ b/crypto/src/crypto/engines/HC256Engine.cs @@ -92,6 +92,7 @@ namespace Org.BouncyCastle.Crypto.Engines iv = newIV; } + idx = 0; cnt = 0; uint[] w = new uint[2560]; @@ -207,7 +208,6 @@ namespace Org.BouncyCastle.Crypto.Engines public virtual void Reset() { - idx = 0; Init(); } diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj index 24a60346e..94fd1cf7a 100644 --- a/crypto/test/UnitTests.csproj +++ b/crypto/test/UnitTests.csproj @@ -252,6 +252,7 @@ <Compile Include="src\crypto\test\SM3DigestTest.cs" /> <Compile Include="src\crypto\test\SkeinDigestTest.cs" /> <Compile Include="src\crypto\test\SkeinMacTest.cs" /> + <Compile Include="src\crypto\test\StreamCipherResetTest.cs" /> <Compile Include="src\crypto\test\Threefish1024Test.cs" /> <Compile Include="src\crypto\test\Threefish256Test.cs" /> <Compile Include="src\crypto\test\Threefish512Test.cs" /> diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs index bf38ae360..ea9fd84f2 100644 --- a/crypto/test/src/crypto/test/RegressionTest.cs +++ b/crypto/test/src/crypto/test/RegressionTest.cs @@ -120,6 +120,7 @@ namespace Org.BouncyCastle.Crypto.Tests new Poly1305Test(), new OcbTest(), new NonMemoableDigestTest(), + new StreamCipherResetTest(), new SM3DigestTest(), new X931SignerTest(), new KeccakDigestTest(), diff --git a/crypto/test/src/crypto/test/StreamCipherResetTest.cs b/crypto/test/src/crypto/test/StreamCipherResetTest.cs new file mode 100644 index 000000000..49760a24b --- /dev/null +++ b/crypto/test/src/crypto/test/StreamCipherResetTest.cs @@ -0,0 +1,134 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Test whether block ciphers implement reset contract on init, encrypt/decrypt and reset. + */ + [TestFixture] + public class StreamCipherResetTest + : SimpleTest + { + public override string Name + { + get { return "Stream Cipher Reset"; } + } + + public override void PerformTest() + { + TestReset(typeof(Salsa20Engine), 32, 8); + TestReset(typeof(Salsa20Engine), 16, 8); + TestReset(typeof(XSalsa20Engine), 32, 24); + TestReset(typeof(ChaChaEngine), 32, 8); + TestReset(typeof(ChaChaEngine), 16, 8); + TestReset(typeof(RC4Engine), 16); + TestReset(typeof(IsaacEngine), 16); + TestReset(typeof(HC128Engine), 16, 16); + TestReset(typeof(HC256Engine), 16, 16); + //TestReset(typeof(Grainv1Engine), 16, 8); + //TestReset(typeof(Grain128Engine), 16, 12); + } + + private static readonly SecureRandom RAND = new SecureRandom(); + + private static byte[] Random(int size) + { + return SecureRandom.GetNextBytes(RAND, size); + } + + private IStreamCipher Make(Type sct) + { + return (IStreamCipher)Activator.CreateInstance(sct); + } + + private void TestReset(Type sct, int keyLen) + { + TestReset(Make(sct), Make(sct), new KeyParameter(Random(keyLen))); + } + + private void TestReset(Type sct, int keyLen, int ivLen) + { + TestReset(Make(sct), Make(sct), new ParametersWithIV(new KeyParameter(Random(keyLen)), Random(ivLen))); + } + + private void TestReset(IStreamCipher cipher1, IStreamCipher cipher2, ICipherParameters cipherParams) + { + cipher1.Init(true, cipherParams); + + byte[] plaintext = new byte[1023]; + byte[] ciphertext = new byte[plaintext.Length]; + + // Establish baseline answer + cipher1.ProcessBytes(plaintext, 0, plaintext.Length, ciphertext, 0); + + // Test encryption resets + CheckReset(cipher1, cipherParams, true, plaintext, ciphertext); + + // Test decryption resets with fresh instance + cipher2.Init(false, cipherParams); + CheckReset(cipher2, cipherParams, false, ciphertext, plaintext); + } + + private void CheckReset(IStreamCipher cipher, ICipherParameters cipherParams, + bool encrypt, byte[] pretext, byte[] posttext) + { + // Do initial run + byte[] output = new byte[posttext.Length]; + cipher.ProcessBytes(pretext, 0, pretext.Length, output, 0); + + // Check encrypt resets cipher + cipher.Init(encrypt, cipherParams); + + try + { + cipher.ProcessBytes(pretext, 0, pretext.Length, output, 0); + } + catch (Exception e) + { + Fail(cipher.AlgorithmName + " init did not reset: " + e.Message); + } + if (!Arrays.AreEqual(output, posttext)) + { + Fail(cipher.AlgorithmName + " init did not reset.", Hex.ToHexString(posttext), Hex.ToHexString(output)); + } + + // Check reset resets data + cipher.Reset(); + + try + { + cipher.ProcessBytes(pretext, 0, pretext.Length, output, 0); + } + catch (Exception e) + { + Fail(cipher.AlgorithmName + " reset did not reset: " + e.Message); + } + if (!Arrays.AreEqual(output, posttext)) + { + Fail(cipher.AlgorithmName + " reset did not reset."); + } + } + + public static void Main(string[] args) + { + RunTest(new StreamCipherResetTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} |