summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2018-08-11 11:54:57 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2018-08-11 11:54:57 +0700
commit8c0e3017783a5f41b2028eaffffe335a9046c859 (patch)
treeb92462a67bab6e5aa4cf93ddcb8f06d823ccf752
parentUpdate versions and release notes for 1.8.3 (diff)
downloadBouncyCastle.NET-ed25519-8c0e3017783a5f41b2028eaffffe335a9046c859.tar.xz
Further work to improve constant time in OAEP. release-1.8.3
-rw-r--r--crypto/Readme.html2
-rw-r--r--crypto/src/AssemblyInfo.cs2
-rw-r--r--crypto/src/crypto/encodings/OaepEncoding.cs15
-rw-r--r--crypto/test/src/crypto/test/OAEPTest.cs79
4 files changed, 89 insertions, 9 deletions
diff --git a/crypto/Readme.html b/crypto/Readme.html
index faad344cc..72e97516f 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -294,7 +294,7 @@ We state, where EC MQV has not otherwise been disabled or removed:
 		<hr style="WIDTH: 100%; HEIGHT: 2px">
 		<h3><a class="mozTocH3" name="mozTocId3413"></a>Notes:</h3>
 
-        <h4><a class="mozTocH4" name="mozTocId85317"></a>Release 1.8.3, Tuesday August 7, 2018</h4>
+        <h4><a class="mozTocH4" name="mozTocId85317"></a>Release 1.8.3, Saturday August 11, 2018</h4>
 
         <h5>IMPORTANT</h5>
         <ul>
diff --git a/crypto/src/AssemblyInfo.cs b/crypto/src/AssemblyInfo.cs
index e1a8f6717..5cc8fcd2f 100644
--- a/crypto/src/AssemblyInfo.cs
+++ b/crypto/src/AssemblyInfo.cs
@@ -34,7 +34,7 @@ using System.Runtime.InteropServices;
 // by using the '*' as shown below:
 
 [assembly: AssemblyVersion("1.8.3.0")]
-[assembly: AssemblyFileVersion("1.8.18219.1")]
+[assembly: AssemblyFileVersion("1.8.18223.1")]
 [assembly: AssemblyInformationalVersion("1.8.3")]
 
 //
diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs
index 287876f12..92001589c 100644
--- a/crypto/src/crypto/encodings/OaepEncoding.cs
+++ b/crypto/src/crypto/encodings/OaepEncoding.cs
@@ -212,10 +212,17 @@ namespace Org.BouncyCastle.Crypto.Encodings
             // on encryption, we need to make sure our decrypted block comes back
             // the same size.
             //
+            bool wrongData = (block.Length < (2 * defHash.Length) + 1);
 
-            Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
-
-            bool shortData = (block.Length < (2 * defHash.Length) + 1);
+            if (data.Length <= block.Length)
+            {
+                Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
+            }
+            else
+            {
+                Array.Copy(data, 0, block, 0, block.Length);
+                wrongData = true;
+            }
 
             //
             // unmask the seed.
@@ -269,7 +276,7 @@ namespace Org.BouncyCastle.Crypto.Encodings
 
             start++;
 
-            if (defHashWrong | shortData | dataStartWrong)
+            if (defHashWrong | wrongData | dataStartWrong)
             {
                 Arrays.Fill(block, 0);
                 throw new InvalidCipherTextException("data wrong");
diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs
index bc1dd9292..204784cee 100644
--- a/crypto/test/src/crypto/test/OAEPTest.cs
+++ b/crypto/test/src/crypto/test/OAEPTest.cs
@@ -8,6 +8,7 @@ using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto.Digests;
 using Org.BouncyCastle.Crypto.Encodings;
 using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
@@ -780,8 +781,10 @@ namespace Org.BouncyCastle.Crypto.Tests
             OaepVecTest(1027, 5, pubParam, privParam, seed_1027_5, input_1027_5, output_1027_5);
             OaepVecTest(1027, 6, pubParam, privParam, seed_1027_6, input_1027_6, output_1027_6);
 
+            TestForHighByteError("invalidCiphertextOaepTest 1024", 1024);
+
             //
-            // OAEP - public encrypt, private decrypt  differring hashes
+            // OAEP - public encrypt, private decrypt, differing hashes
             //
             IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), new byte[10]);
 
@@ -822,8 +825,78 @@ namespace Org.BouncyCastle.Crypto.Tests
             }
         }
 
-        public static void Main(
-            string[] args)
+        private void TestForHighByteError(string label, int keySizeBits)
+        {
+            // draw a key of the size asked
+            BigInteger e = BigInteger.One.ShiftLeft(16).Add(BigInteger.One);
+
+            IAsymmetricCipherKeyPairGenerator kpGen = new RsaKeyPairGenerator();
+
+            kpGen.Init(new RsaKeyGenerationParameters(e, new SecureRandom(), keySizeBits, 100));
+
+            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
+
+            IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine());
+
+            // obtain a known good ciphertext
+            cipher.Init(true, new ParametersWithRandom(kp.Public, new VecRand(seed)));
+            byte[] m = { 42 };
+            byte[] c = cipher.ProcessBlock(m, 0, m.Length);
+            int keySizeBytes = (keySizeBits + 7) / 8;
+            if (c.Length != keySizeBytes)
+            {
+                Fail(label + " failed ciphertext size");
+            }
+
+            BigInteger n = ((RsaPrivateCrtKeyParameters)kp.Private).Modulus;
+
+            // decipher
+            cipher.Init(false, kp.Private);
+            byte[] r = cipher.ProcessBlock(c, 0, keySizeBytes);
+            if (r.Length != 1 || r[0] != 42)
+            {
+                Fail(label + " failed first decryption of test message");
+            }
+
+            // decipher again
+            r = cipher.ProcessBlock(c, 0, keySizeBytes);
+            if (r.Length != 1 || r[0] != 42)
+            {
+                Fail(label + " failed second decryption of test message");
+            }
+
+            // check hapazard incorrect ciphertexts
+            for (int i = keySizeBytes * 8; --i >= 0; )
+            {
+                c[i / 8] ^= (byte)(1 << (i & 7));
+                bool ko = true;
+                try
+                {
+                    BigInteger cV = new BigInteger(1, c);
+
+                    // don't pass in c if it will be rejected trivially
+                    if (cV.CompareTo(n) < 0)
+                    {
+                        r = cipher.ProcessBlock(c, 0, keySizeBytes);
+                    }
+                    else
+                    {
+                        ko = false; // size errors are picked up at start
+                    }
+                }
+                catch (InvalidCipherTextException)
+                {
+                    ko = false;
+                }
+                if (ko)
+                {
+                    Fail(label + " invalid ciphertext caused no exception");
+                }
+                c[i / 8] ^= (byte)(1 << (i & 7));
+            }
+        }
+
+        public static void Main(string[] args)
         {
             RunTest(new OaepTest());
         }