summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/cms/SignerInformation.cs24
-rw-r--r--crypto/src/crypto/digests/NullDigest.cs24
-rw-r--r--crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs3
-rw-r--r--crypto/src/crypto/parameters/X448PrivateKeyParameters.cs3
-rw-r--r--crypto/src/crypto/signers/Ed25519Signer.cs11
-rw-r--r--crypto/src/crypto/signers/Ed25519ctxSigner.cs11
-rw-r--r--crypto/src/crypto/signers/Ed25519phSigner.cs4
-rw-r--r--crypto/src/crypto/signers/Ed448Signer.cs11
-rw-r--r--crypto/src/crypto/signers/Ed448phSigner.cs4
-rw-r--r--crypto/src/crypto/tls/TlsProtocol.cs29
-rw-r--r--crypto/src/math/ec/rfc7748/X25519.cs8
-rw-r--r--crypto/src/math/ec/rfc7748/X448.cs8
-rw-r--r--crypto/src/util/Arrays.cs10
-rw-r--r--crypto/src/util/io/Streams.cs25
14 files changed, 130 insertions, 45 deletions
diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs
index dad128263..39ecfa6d3 100644
--- a/crypto/src/cms/SignerInformation.cs
+++ b/crypto/src/cms/SignerInformation.cs
@@ -84,6 +84,30 @@ namespace Org.BouncyCastle.Cms
 			this.digestCalculator = digestCalculator;
 		}
 
+        /**
+         * Protected constructor. In some cases clients have their own idea about how to encode
+         * the signed attributes and calculate the signature. This constructor is to allow developers
+         * to deal with that by extending off the class and overridng methods like getSignedAttributes().
+         *
+         * @param baseInfo the SignerInformation to base this one on.
+         */
+        protected SignerInformation(SignerInformation baseInfo)
+        {
+            this.info = baseInfo.info;
+            this.contentType = baseInfo.contentType;
+            this.isCounterSignature = baseInfo.IsCounterSignature;
+            this.sid = baseInfo.SignerID;
+            this.digestAlgorithm = info.DigestAlgorithm;
+            this.signedAttributeSet = info.AuthenticatedAttributes;
+            this.unsignedAttributeSet = info.UnauthenticatedAttributes;
+            this.encryptionAlgorithm = info.DigestEncryptionAlgorithm;
+            this.signature = info.EncryptedDigest.GetOctets();
+            this.content = baseInfo.content;
+            this.resultDigest = baseInfo.resultDigest;
+            this.signedAttributeTable = baseInfo.signedAttributeTable;
+            this.unsignedAttributeTable = baseInfo.unsignedAttributeTable;
+        }
+
 		public bool IsCounterSignature
 		{
 			get { return isCounterSignature; }
diff --git a/crypto/src/crypto/digests/NullDigest.cs b/crypto/src/crypto/digests/NullDigest.cs
index e598cb145..76b69afbf 100644
--- a/crypto/src/crypto/digests/NullDigest.cs
+++ b/crypto/src/crypto/digests/NullDigest.cs
@@ -1,6 +1,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities.IO;
+
 namespace Org.BouncyCastle.Crypto.Digests
 {
 	public class NullDigest : IDigest
@@ -20,7 +22,7 @@ namespace Org.BouncyCastle.Crypto.Digests
 
 		public int GetDigestSize()
 		{
-			return (int) bOut.Length;
+			return (int)bOut.Length;
 		}
 
 		public void Update(byte b)
@@ -33,15 +35,19 @@ namespace Org.BouncyCastle.Crypto.Digests
 			bOut.Write(inBytes, inOff, len);
 		}
 
-		public int DoFinal(byte[] outBytes, int outOff)
+        public int DoFinal(byte[] outBytes, int outOff)
 		{
-			byte[] res = bOut.ToArray();
-			res.CopyTo(outBytes, outOff);
-			Reset();
-			return res.Length;
-		}
-
-		public void Reset()
+            try
+            {
+                return Streams.WriteBufTo(bOut, outBytes, outOff);
+            }
+            finally
+            {
+                Reset();
+            }
+        }
+
+        public void Reset()
 		{
 			bOut.SetLength(0);
 		}
diff --git a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
index c25ab9364..fb49a02b3 100644
--- a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
@@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
         {
             byte[] encoded = new byte[X25519.PointSize];
             publicKey.Encode(encoded, 0);
-            X25519.ScalarMult(data, 0, encoded, 0, buf, off);
+            if (!X25519.CalculateAgreement(data, 0, encoded, 0, buf, off))
+                throw new InvalidOperationException("X25519 agreement failed");
         }
     }
 }
diff --git a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
index 291eac10f..d17aa7947 100644
--- a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
@@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
         {
             byte[] encoded = new byte[X448.PointSize];
             publicKey.Encode(encoded, 0);
-            X448.ScalarMult(data, 0, encoded, 0, buf, off);
+            if (!X448.CalculateAgreement(data, 0, encoded, 0, buf, off))
+                throw new InvalidOperationException("X448 agreement failed");
         }
     }
 }
diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs
index 904450ed1..1b3142c7b 100644
--- a/crypto/src/crypto/signers/Ed25519Signer.cs
+++ b/crypto/src/crypto/signers/Ed25519Signer.cs
@@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Crypto.Signers
 {
@@ -58,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual byte[] GenerateSignature()
         {
-            if (!forSigning)
+            if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed25519Signer not initialised for signature generation.");
 
             return buffer.GenerateSignature(privateKey, publicKey);
@@ -66,7 +67,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual bool VerifySignature(byte[] signature)
         {
-            if (forSigning)
+            if (forSigning || null == publicKey)
                 throw new InvalidOperationException("Ed25519Signer not initialised for verification");
 
             return buffer.VerifySignature(publicKey, signature);
@@ -114,12 +115,12 @@ namespace Org.BouncyCastle.Crypto.Signers
             [MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
+                long count = Position;
 #if PORTABLE
                 this.Position = 0L;
-
-                // TODO Clear using Write method
+                Streams.WriteZeroes(this, count);
 #else
-                Array.Clear(GetBuffer(), 0, (int)Position);
+                Array.Clear(GetBuffer(), 0, (int)count);
 #endif
                 this.Position = 0L;
             }
diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
index e9c2eca44..965453011 100644
--- a/crypto/src/crypto/signers/Ed25519ctxSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
@@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Crypto.Signers
 {
@@ -60,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual byte[] GenerateSignature()
         {
-            if (!forSigning)
+            if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed25519ctxSigner not initialised for signature generation.");
 
             return buffer.GenerateSignature(privateKey, publicKey, context);
@@ -68,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual bool VerifySignature(byte[] signature)
         {
-            if (forSigning)
+            if (forSigning || null == publicKey)
                 throw new InvalidOperationException("Ed25519ctxSigner not initialised for verification");
 
             return buffer.VerifySignature(publicKey, context, signature);
@@ -116,12 +117,12 @@ namespace Org.BouncyCastle.Crypto.Signers
             [MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
+                long count = Position;
 #if PORTABLE
                 this.Position = 0L;
-
-                // TODO Clear using Write method
+                Streams.WriteZeroes(this, count);
 #else
-                Array.Clear(GetBuffer(), 0, (int)Position);
+                Array.Clear(GetBuffer(), 0, (int)count);
 #endif
                 this.Position = 0L;
             }
diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs
index 0d3de96f3..3318f6438 100644
--- a/crypto/src/crypto/signers/Ed25519phSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519phSigner.cs
@@ -60,7 +60,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual byte[] GenerateSignature()
         {
-            if (!forSigning)
+            if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed25519phSigner not initialised for signature generation.");
 
             byte[] msg = new byte[Ed25519.PrehashSize];
@@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual bool VerifySignature(byte[] signature)
         {
-            if (forSigning)
+            if (forSigning || null == publicKey)
                 throw new InvalidOperationException("Ed25519phSigner not initialised for verification");
 
             byte[] pk = publicKey.GetEncoded();
diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs
index c01d84b4d..d18f956a8 100644
--- a/crypto/src/crypto/signers/Ed448Signer.cs
+++ b/crypto/src/crypto/signers/Ed448Signer.cs
@@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Crypto.Signers
 {
@@ -60,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual byte[] GenerateSignature()
         {
-            if (!forSigning)
+            if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed448Signer not initialised for signature generation.");
 
             return buffer.GenerateSignature(privateKey, publicKey, context);
@@ -68,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual bool VerifySignature(byte[] signature)
         {
-            if (forSigning)
+            if (forSigning || null == publicKey)
                 throw new InvalidOperationException("Ed448Signer not initialised for verification");
 
             return buffer.VerifySignature(publicKey, context, signature);
@@ -116,12 +117,12 @@ namespace Org.BouncyCastle.Crypto.Signers
             [MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
+                long count = Position;
 #if PORTABLE
                 this.Position = 0L;
-
-                // TODO Clear using Write method
+                Streams.WriteZeroes(this, count);
 #else
-                Array.Clear(GetBuffer(), 0, (int)Position);
+                Array.Clear(GetBuffer(), 0, (int)count);
 #endif
                 this.Position = 0L;
             }
diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs
index 50d0a0154..b86d0855c 100644
--- a/crypto/src/crypto/signers/Ed448phSigner.cs
+++ b/crypto/src/crypto/signers/Ed448phSigner.cs
@@ -60,7 +60,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual byte[] GenerateSignature()
         {
-            if (!forSigning)
+            if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed448phSigner not initialised for signature generation.");
 
             byte[] msg = new byte[Ed448.PrehashSize];
@@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         public virtual bool VerifySignature(byte[] signature)
         {
-            if (forSigning)
+            if (forSigning || null == publicKey)
                 throw new InvalidOperationException("Ed448phSigner not initialised for verification");
 
             byte[] pk = publicKey.GetEncoded();
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index 72151d414..bbb76d53c 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -391,31 +391,30 @@ namespace Org.BouncyCastle.Crypto.Tls
                 if (queue.Available < totalLength)
                     break;
 
-                CheckReceivedChangeCipherSpec(mConnectionState == CS_END || type == HandshakeType.finished);
-
                 /*
                  * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages
                  * starting at client hello up to, but not including, this finished message.
                  * [..] Note: [Also,] Hello Request messages are omitted from handshake hashes.
                  */
-                switch (type)
-                {
-                case HandshakeType.hello_request:
-                    break;
-                case HandshakeType.finished:
-                default:
+                if (HandshakeType.hello_request != type)
                 {
-                    TlsContext ctx = Context;
-                    if (type == HandshakeType.finished
-                        && this.mExpectedVerifyData == null
-                        && ctx.SecurityParameters.MasterSecret != null)
+                    if (HandshakeType.finished == type)
                     {
-                        this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer);
+                        CheckReceivedChangeCipherSpec(true);
+
+                        TlsContext ctx = Context;
+                        if (this.mExpectedVerifyData == null
+                            && ctx.SecurityParameters.MasterSecret != null)
+                        {
+                            this.mExpectedVerifyData = CreateVerifyData(!ctx.IsServer);
+                        }
+                    }
+                    else
+                    {
+                        CheckReceivedChangeCipherSpec(mConnectionState == CS_END);
                     }
 
                     queue.CopyTo(mRecordStream.HandshakeHashUpdater, totalLength);
-                    break;
-                }
                 }
 
                 queue.RemoveData(4);
diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs
index d63cc5a3e..6b6acdecd 100644
--- a/crypto/src/math/ec/rfc7748/X25519.cs
+++ b/crypto/src/math/ec/rfc7748/X25519.cs
@@ -2,6 +2,8 @@
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Math.EC.Rfc7748
 {
     public abstract class X25519
@@ -21,6 +23,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
 
         private static int[] precompBase = null;
 
+        public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
+        {
+            ScalarMult(k, kOff, u, uOff, r, rOff);
+            return !Arrays.AreAllZeroes(r, rOff, PointSize);
+        }
+
         private static uint Decode32(byte[] bs, int off)
         {
             uint n = bs[off];
diff --git a/crypto/src/math/ec/rfc7748/X448.cs b/crypto/src/math/ec/rfc7748/X448.cs
index aac603b08..b93cb24c5 100644
--- a/crypto/src/math/ec/rfc7748/X448.cs
+++ b/crypto/src/math/ec/rfc7748/X448.cs
@@ -2,6 +2,8 @@
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Math.EC.Rfc7748
 {
     public abstract class X448
@@ -24,6 +26,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
 
         private static uint[] precompBase = null;
 
+        public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
+        {
+            ScalarMult(k, kOff, u, uOff, r, rOff);
+            return !Arrays.AreAllZeroes(r, rOff, PointSize);
+        }
+
         private static uint Decode32(byte[] bs, int off)
         {
             uint n = bs[off];
diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs
index 3df908240..a9a574dbf 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -11,6 +11,16 @@ namespace Org.BouncyCastle.Utilities
         public static readonly byte[] EmptyBytes = new byte[0];
         public static readonly int[] EmptyInts = new int[0];
 
+        public static bool AreAllZeroes(byte[] buf, int off, int len)
+        {
+            uint bits = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                bits |= buf[off + i];
+            }
+            return bits == 0;
+        }
+
         public static bool AreEqual(
             bool[]  a,
             bool[]  b)
diff --git a/crypto/src/util/io/Streams.cs b/crypto/src/util/io/Streams.cs
index cc7fa924c..503a1b4f1 100644
--- a/crypto/src/util/io/Streams.cs
+++ b/crypto/src/util/io/Streams.cs
@@ -96,5 +96,30 @@ namespace Org.BouncyCastle.Utilities.IO
         {
             buf.WriteTo(output);
         }
+
+        /// <exception cref="IOException"></exception>
+        public static int WriteBufTo(MemoryStream buf, byte[] output, int offset)
+        {
+#if PORTABLE
+            byte[] bytes = buf.ToArray();
+            bytes.CopyTo(output, offset);
+            return bytes.Length;
+#else
+            int size = (int)buf.Length;
+            buf.WriteTo(new MemoryStream(output, offset, size, true));
+            return size;
+#endif
+        }
+
+        public static void WriteZeroes(Stream outStr, long count)
+        {
+            byte[] zeroes = new byte[BufferSize];
+            while (count > BufferSize)
+            {
+                outStr.Write(zeroes, 0, BufferSize);
+                count -= BufferSize;
+            }
+            outStr.Write(zeroes, 0, (int)count);
+        }
     }
 }