summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2018-09-16 16:21:56 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2018-09-16 16:21:56 +0700
commitba3292784635dc3f06070e4c99c01ed630818940 (patch)
tree7a4c19ad7d721c4c5a9c1e8924fc0a6bc2c199ea
parentReduce single-bit extractions from scalars (diff)
downloadBouncyCastle.NET-ed25519-ba3292784635dc3f06070e4c99c01ed630818940.tar.xz
Fixed Rfc3211WrapEngine processing of messages over 127 bytes.
-rw-r--r--crypto/Readme.html9
-rw-r--r--crypto/src/crypto/engines/RFC3211WrapEngine.cs59
-rw-r--r--crypto/test/src/crypto/test/RFC3211WrapTest.cs2
3 files changed, 45 insertions, 25 deletions
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 72e97516f..1d1b74f1c 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -31,6 +31,8 @@
 				<a href="#mozTocId3413">Notes:</a>
 		<ol>
             <li>
+                <a href="#mozTocId85318">Release 1.8.4</a>
+            <li>
                 <a href="#mozTocId85317">Release 1.8.3</a>
             <li>
                 <a href="#mozTocId85316">Release 1.8.2</a>
@@ -294,6 +296,13 @@ 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="mozTocId85318"></a>Release 1.8.4, TBD</h4>
+
+        <h5>Defects Fixed</h5>
+        <ul>
+            <li>Rfc3211WrapEngine would not properly handle messages longer than 127 bytes. This has been fixed.</li>
+        </ul>
+
         <h4><a class="mozTocH4" name="mozTocId85317"></a>Release 1.8.3, Saturday August 11, 2018</h4>
 
         <h5>IMPORTANT</h5>
diff --git a/crypto/src/crypto/engines/RFC3211WrapEngine.cs b/crypto/src/crypto/engines/RFC3211WrapEngine.cs
index 4e3af5227..86480145c 100644
--- a/crypto/src/crypto/engines/RFC3211WrapEngine.cs
+++ b/crypto/src/crypto/engines/RFC3211WrapEngine.cs
@@ -32,10 +32,10 @@ namespace Org.BouncyCastle.Crypto.Engines
 
 			if (param is ParametersWithRandom)
 			{
-				ParametersWithRandom p = (ParametersWithRandom) param;
+				ParametersWithRandom p = (ParametersWithRandom)param;
 
-				this.rand = p.Random;
-				this.param = (ParametersWithIV) p.Parameters;
+                this.rand = p.Random;
+                this.param = p.Parameters as ParametersWithIV;
 			}
 			else
 			{
@@ -44,9 +44,12 @@ namespace Org.BouncyCastle.Crypto.Engines
 					rand = new SecureRandom();
 				}
 
-				this.param = (ParametersWithIV) param;
-			}
-		}
+                this.param = param as ParametersWithIV;
+            }
+
+            if (null == this.param)
+                throw new ArgumentException("RFC3211Wrap requires an IV", "param");
+        }
 
         public virtual string AlgorithmName
 		{
@@ -59,11 +62,11 @@ namespace Org.BouncyCastle.Crypto.Engines
 			int		inLen)
 		{
 			if (!forWrapping)
-			{
 				throw new InvalidOperationException("not set for wrapping");
-			}
+            if (inLen > 255 || inLen < 0)
+                throw new ArgumentException("input must be from 0 to 255 bytes", "inLen");
 
-			engine.Init(true, param);
+            engine.Init(true, param);
 
 			int blockSize = engine.GetBlockSize();
 			byte[] cekBlock;
@@ -78,15 +81,16 @@ namespace Org.BouncyCastle.Crypto.Engines
 			}
 
 			cekBlock[0] = (byte)inLen;
-			cekBlock[1] = (byte)~inBytes[inOff];
-			cekBlock[2] = (byte)~inBytes[inOff + 1];
-			cekBlock[3] = (byte)~inBytes[inOff + 2];
 
 			Array.Copy(inBytes, inOff, cekBlock, 4, inLen);
 
 			rand.NextBytes(cekBlock, inLen + 4, cekBlock.Length - inLen - 4);
 
-			for (int i = 0; i < cekBlock.Length; i += blockSize)
+            cekBlock[1] = (byte)~cekBlock[4];
+            cekBlock[2] = (byte)~cekBlock[4 + 1];
+            cekBlock[3] = (byte)~cekBlock[4 + 2];
+
+            for (int i = 0; i < cekBlock.Length; i += blockSize)
 			{
 				engine.ProcessBlock(cekBlock, i, cekBlock, i);
 			}
@@ -142,27 +146,34 @@ namespace Org.BouncyCastle.Crypto.Engines
 				engine.ProcessBlock(cekBlock, i, cekBlock, i);
 			}
 
-			if ((cekBlock[0] & 0xff) > cekBlock.Length - 4)
-			{
-				throw new InvalidCipherTextException("wrapped key corrupted");
-			}
+            bool invalidLength = (int)cekBlock[0] > (cekBlock.Length - 4);
 
-			byte[] key = new byte[cekBlock[0] & 0xff];
+            byte[] key;
+            if (invalidLength)
+            {
+                key = new byte[cekBlock.Length - 4];
+            }
+            else
+            {
+                key = new byte[cekBlock[0]];
+            }
 
-			Array.Copy(cekBlock, 4, key, 0, cekBlock[0]);
+            Array.Copy(cekBlock, 4, key, 0, key.Length);
 
 			// Note: Using constant time comparison
 			int nonEqual = 0;
 			for (int i = 0; i != 3; i++)
 			{
 				byte check = (byte)~cekBlock[1 + i];
-				nonEqual |= (check ^ key[i]);
-			}
+                nonEqual |= (check ^ cekBlock[4 + i]);
+            }
+
+            Array.Clear(cekBlock, 0, cekBlock.Length);
 
-			if (nonEqual != 0)
-				throw new InvalidCipherTextException("wrapped key fails checksum");
+            if (nonEqual != 0 | invalidLength)
+                throw new InvalidCipherTextException("wrapped key corrupted");
 
-			return key;
+            return key;
 		}
 	}
 }
diff --git a/crypto/test/src/crypto/test/RFC3211WrapTest.cs b/crypto/test/src/crypto/test/RFC3211WrapTest.cs
index bdef7c999..91dea34dd 100644
--- a/crypto/test/src/crypto/test/RFC3211WrapTest.cs
+++ b/crypto/test/src/crypto/test/RFC3211WrapTest.cs
@@ -115,7 +115,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 			}
 			catch (InvalidCipherTextException e)
 			{
-				if (!e.Message.Equals("wrapped key fails checksum"))
+                if (!e.Message.Equals("wrapped key corrupted"))
 				{
 					Fail("wrong exception");
 				}