summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2016-01-17 12:32:24 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2016-01-17 12:32:24 +0700
commit4819cab88fdd657bd64c672ff62e255a5cc1fe3e (patch)
treeeba6bc580707be8a5b8d969b43cbf83949dcfb34 /crypto
parentRemove expired draft-josefsson-salsa20-tls stuff (diff)
downloadBouncyCastle.NET-ed25519-4819cab88fdd657bd64c672ff62e255a5cc1fe3e.tar.xz
Fix re-init bug in HC128/256 engines
- add StreamCipherResetTest from Java API
Diffstat (limited to 'crypto')
-rw-r--r--crypto/crypto.csproj5
-rw-r--r--crypto/src/crypto/engines/HC128Engine.cs4
-rw-r--r--crypto/src/crypto/engines/HC256Engine.cs2
-rw-r--r--crypto/test/UnitTests.csproj1
-rw-r--r--crypto/test/src/crypto/test/RegressionTest.cs1
-rw-r--r--crypto/test/src/crypto/test/StreamCipherResetTest.cs134
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);
+        }
+    }
+}